diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index f790c91..bcf0cda 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -35,6 +35,7 @@ from sugar.graphics.toolbutton import ToolButton
 from sugar.graphics.tray import TrayIcon
 from sugar.graphics import xocolor
 from sugar.util import unique_id
+from sugar import profile
 
 from jarabe.model import network
 from jarabe.model.network import Settings
@@ -50,6 +51,7 @@ _NM_PATH = '/org/freedesktop/NetworkManager'
 _NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
 _NM_WIRED_IFACE = 'org.freedesktop.NetworkManager.Device.Wired'
 _NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless'
+_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh'
 _NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
 _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
 
@@ -81,7 +83,7 @@ class WirelessPalette(Palette):
                                    gobject.TYPE_NONE, ([])),
     }
 
-    def __init__(self, primary_text):
+    def __init__(self, primary_text, can_create=True):
         Palette.__init__(self, label=primary_text)
 
         self._disconnect_item = None
@@ -112,21 +114,29 @@ class WirelessPalette(Palette):
         self._disconnect_item.connect('activate', self.__disconnect_activate_cb)
         self.menu.append(self._disconnect_item)
 
-        self._adhoc_item = gtk.MenuItem(_('Create new wireless network'))
-        self._adhoc_item.connect('activate', self.__adhoc_activate_cb)
-        self.menu.append(self._adhoc_item)
-        self._adhoc_item.show()
+        if can_create:
+            self._adhoc_item = gtk.MenuItem(_('Create new wireless network'))
+            self._adhoc_item.connect('activate', self.__adhoc_activate_cb)
+            self.menu.append(self._adhoc_item)
+            self._adhoc_item.show()
 
     def set_connecting(self):
         self.props.secondary_text = _('Connecting...')
 
-    def set_connected(self, frequency, iaddress):
+    def _set_connected(self, iaddress):
         self.set_content(self._info)
         self.props.secondary_text = _('Connected')
-        self._set_channel(frequency)
         self._set_ip_address(iaddress)
         self._disconnect_item.show()
-        
+
+    def set_connected_with_frequency(self, frequency, iaddress):
+        self._set_connected(iaddress)
+        self._set_frequency(frequency)
+
+    def set_connected_with_channel(self, channel, iaddress):
+        self._set_connected(iaddress)
+        self._set_channel(channel)
+
     def set_disconnected(self):
         self.props.primary_text = ''
         self.props.secondary_text = ''
@@ -139,11 +149,14 @@ class WirelessPalette(Palette):
     def __adhoc_activate_cb(self, menuitem):
         self.emit('create-connection')
 
-    def _set_channel(self, frequency):
+    def _set_frequency(self, frequency):
         try:
             channel = frequency_to_channel(frequency)
         except KeyError:
             channel = 0
+        self._set_channel(channel)   
+
+    def _set_channel(self, channel):
         self._channel_label.set_text("%s: %d" % (_("Channel"), channel))
 
     def _set_ip_address(self, ip_address):
@@ -385,7 +398,7 @@ class WirelessDeviceView(ToolButton):
             self._icon.props.pulsing = True
         elif state == network.DEVICE_STATE_ACTIVATED:
             address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address')
-            self._palette.set_connected(self._frequency, address)
+            self._palette.set_connected_with_frequency(self._frequency, address)
             self._icon.props.pulsing = False
         else:
             self._icon.props.badge_name = None
@@ -471,6 +484,128 @@ class WirelessDeviceView(ToolButton):
     def __activate_error_cb(self, err):
         logging.debug('Failed to create network: %s', err)
 
+class OlpcMeshDeviceView(ToolButton):
+    _ICON_NAME = 'network-mesh'
+    FRAME_POSITION_RELATIVE = 302
+
+    def __init__(self, device):
+        ToolButton.__init__(self)
+
+        self._bus = dbus.SystemBus()
+        self._device = device
+        self._device_props = None
+        self._device_state = None
+        self._channel = 0
+
+        self._icon = PulsingIcon(icon_name=self._ICON_NAME)
+        self._icon.props.pulse_color = xocolor.XoColor( \
+            "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
+                       style.COLOR_TRANSPARENT.get_svg()))
+        self._icon.props.base_color = profile.get_color()
+
+        self.set_icon_widget(self._icon)
+        self._icon.show()
+
+        self.set_palette_invoker(FrameWidgetInvoker(self))
+        self._palette = WirelessPalette(_("Mesh Network"))
+        self._palette.connect('deactivate-connection',
+                              self.__deactivate_connection)
+        self.set_palette(self._palette)
+        self._palette.set_group_id('frame')
+
+        self._device_props = dbus.Interface(self._device,
+                                            'org.freedesktop.DBus.Properties')
+        self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True,
+                              reply_handler=self.__get_device_props_reply_cb,
+                              error_handler=self.__get_device_props_error_cb)
+        self._device_props.Get(_NM_OLPC_MESH_IFACE, 'ActiveChannel',
+                            reply_handler=self.__get_active_channel_reply_cb,
+                            error_handler=self.__get_active_channel_error_cb)
+
+        self._bus.add_signal_receiver(self.__state_changed_cb,
+                                      signal_name='StateChanged',
+                                      path=self._device.object_path,
+                                      dbus_interface=_NM_DEVICE_IFACE)
+        self._bus.add_signal_receiver(self.__wireless_properties_changed_cb,
+                                      signal_name='PropertiesChanged',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_OLPC_MESH_IFACE)
+
+    def disconnect(self):
+        self._bus.remove_signal_receiver(self.__state_changed_cb,
+                                         signal_name='StateChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_DEVICE_IFACE)
+        self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb,
+                                         signal_name='PropertiesChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_OLPC_MESH_IFACE)
+
+    def __get_device_props_reply_cb(self, properties):
+        if 'State' in properties:
+            self._device_state = properties['State']
+            self._update()
+
+    def __get_device_props_error_cb(self, err):
+        logging.error('Error getting the device properties: %s', err)
+
+    def __get_active_channel_reply_cb(self, channel):
+        self._channel = channel
+        self._update_text()
+
+    def __get_active_channel_error_cb(self, err):
+        logging.error('Error getting the active channel: %s', err)
+
+    def __state_changed_cb(self, new_state, old_state, reason):
+        self._device_state = new_state
+        self._update()
+
+    def __wireless_properties_changed_cb(self, properties):
+        if 'ActiveChannel' in properties:
+            self._channel = properties['ActiveChannel']
+            self._update_text()
+
+    def _update_text(self):
+        text = _("Mesh Network") + " " + str(self._channel)
+        self._palette.props.primary_text = text
+
+    def _update(self):
+        state = self._device_state
+
+        if state in [network.DEVICE_STATE_PREPARE,
+                     network.DEVICE_STATE_CONFIG,
+                     network.DEVICE_STATE_NEED_AUTH,
+                     network.DEVICE_STATE_IP_CONFIG]:
+            self._palette.set_connecting()
+            self._icon.props.pulsing = True
+        elif state == network.DEVICE_STATE_ACTIVATED:
+            address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address')
+            self._palette.set_connected_with_channel(self._channel, address)
+            self._icon.props.pulsing = False
+
+    def __deactivate_connection(self, palette, data=None):
+        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+        netmgr = dbus.Interface(obj, _NM_IFACE)
+        netmgr_props = dbus.Interface(netmgr, 'org.freedesktop.DBus.Properties')
+        active_connections_o = netmgr_props.Get(_NM_IFACE,
+                                                'ActiveConnections')
+
+        for conn_o in active_connections_o:
+            # The connection path for a mesh connection is the device itself.
+            obj = self._bus.get_object(_NM_IFACE, conn_o)
+            props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+            ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
+
+            try:
+                obj = self._bus.get_object(_NM_IFACE, ap_op)
+                props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties')
+                type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
+                if type == network.DEVICE_TYPE_802_11_OLPC_MESH:
+                    netmgr.DeactivateConnection(conn_o)
+                    break
+            except dbus.exceptions.DBusException:
+                pass
+
 class WiredDeviceView(TrayIcon):
 
     _ICON_NAME = 'network-wired'
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
index 81363ac..9648b4f 100644
--- a/src/jarabe/desktop/meshbox.py
+++ b/src/jarabe/desktop/meshbox.py
@@ -36,6 +36,7 @@ from sugar.graphics.menuitem import MenuItem
 from sugar.activity.activityhandle import ActivityHandle
 from sugar.activity import activityfactory
 from sugar.util import unique_id
+from sugar import profile
 
 from jarabe.model import neighborhood
 from jarabe.view.buddyicon import BuddyIcon
@@ -51,17 +52,20 @@ from jarabe.model.network import Settings
 from jarabe.model.network import IP4Config
 from jarabe.model.network import WirelessSecurity
 from jarabe.model.network import AccessPoint
+from jarabe.model.network import OlpcMesh as OlpcMeshSettings
+from jarabe.model.olpcmesh import OlpcMeshManager
 
 _NM_SERVICE = 'org.freedesktop.NetworkManager'
 _NM_IFACE = 'org.freedesktop.NetworkManager'
 _NM_PATH = '/org/freedesktop/NetworkManager'
 _NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
 _NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless'
+_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh'
 _NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint'
 _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active'
 
-_ICON_NAME = 'network-wireless'
-
+_AP_ICON_NAME = 'network-wireless'
+_OLPC_MESH_ICON_NAME = 'network-mesh'
 
 class WirelessNetworkView(CanvasPulsingIcon):
     def __init__(self, initial_ap):
@@ -139,7 +143,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
             and self._name[-15] == '#'
 
     def _create_palette(self):
-        icon_name = get_icon_state(_ICON_NAME, self._strength)
+        icon_name = get_icon_state(_AP_ICON_NAME, self._strength)
         self._palette_icon = Icon(icon_name=icon_name,
                                   icon_size=style.STANDARD_ICON_SIZE,
                                   badge_name=self.props.badge_name)
@@ -216,9 +220,9 @@ class WirelessNetworkView(CanvasPulsingIcon):
                 if self._mode == network.NM_802_11_MODE_INFRA:
                     connection.set_connected()
 
-            icon_name = '%s-connected' % _ICON_NAME
+            icon_name = '%s-connected' % _AP_ICON_NAME
         else:
-            icon_name = _ICON_NAME
+            icon_name = _AP_ICON_NAME
 
         icon_name = get_icon_state(icon_name, self._strength)
         if icon_name:
@@ -443,6 +447,17 @@ class WirelessNetworkView(CanvasPulsingIcon):
             return None
         return self._access_points[ap_path]
 
+    def is_olpc_mesh(self):
+        return self._mode == network.NM_802_11_MODE_ADHOC \
+            and self.name == "olpc-mesh"
+
+    def remove_all_aps(self):
+        for ap in self._access_points.values():
+            ap.disconnect()
+        self._access_points = {}
+        self._active_ap = None
+        self.update_strength()
+
     def disconnect(self):
         self._bus.remove_signal_receiver(self.__device_state_changed_cb,
                                          signal_name='StateChanged',
@@ -454,6 +469,146 @@ class WirelessNetworkView(CanvasPulsingIcon):
                                          dbus_interface=_NM_WIRELESS_IFACE)
 
 
+class OlpcMeshView(CanvasPulsingIcon):
+    def __init__(self, mesh_mgr, channel):
+        CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
+                                   size=style.STANDARD_ICON_SIZE, cache=True)
+        self._bus = dbus.SystemBus()
+        self._channel = channel
+        self._mesh_mgr = mesh_mgr
+        self._disconnect_item = None
+        self._connect_item = None
+        self._greyed_out = False
+        self._name = ''
+        self._device_state = None
+        self._connection = None
+        self._active = False
+        device = mesh_mgr.mesh_device
+
+        self.connect('button-release-event', self.__button_release_event_cb)
+
+        interface_props = dbus.Interface(device,
+                                         'org.freedesktop.DBus.Properties')
+        interface_props.Get(_NM_DEVICE_IFACE, 'State',
+                            reply_handler=self.__get_device_state_reply_cb,
+                            error_handler=self.__get_device_state_error_cb)
+        interface_props.Get(_NM_OLPC_MESH_IFACE, 'ActiveChannel',
+                            reply_handler=self.__get_active_channel_reply_cb,
+                            error_handler=self.__get_active_channel_error_cb)
+
+        self._bus.add_signal_receiver(self.__device_state_changed_cb,
+                                      signal_name='StateChanged',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_DEVICE_IFACE)
+        self._bus.add_signal_receiver(self.__wireless_properties_changed_cb,
+                                      signal_name='PropertiesChanged',
+                                      path=device.object_path,
+                                      dbus_interface=_NM_OLPC_MESH_IFACE)
+
+        pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
+                                         style.COLOR_TRANSPARENT.get_svg()))
+        self.props.pulse_color = pulse_color
+        self.props.base_color = profile.get_color()
+        self._palette = self._create_palette()
+        self.set_palette(self._palette)
+
+    def _create_palette(self):
+        _palette = palette.Palette(_("Mesh Network %d") % self._channel)
+
+        self._connect_item = MenuItem(_('Connect'), 'dialog-ok')
+        self._connect_item.connect('activate', self.__connect_activate_cb)
+        _palette.menu.append(self._connect_item)
+
+        return _palette
+
+    def __get_device_state_reply_cb(self, state):
+        self._device_state = state
+        self._update()
+
+    def __get_device_state_error_cb(self, err):
+        logging.error('Error getting the device state: %s', err)
+
+    def __device_state_changed_cb(self, new_state, old_state, reason):
+        self._device_state = new_state
+        self._update()
+
+    def __get_active_channel_reply_cb(self, channel):
+        self._active = (channel == self._channel)
+        self._update()
+
+    def __get_active_channel_error_cb(self, err):
+        logging.error('Error getting the active channel: %s', err)
+
+    def __wireless_properties_changed_cb(self, properties):
+        if 'ActiveChannel' in properties:
+            channel = properties['ActiveChannel']
+            self._active = (channel == self._channel)
+            self._update()
+
+    def _update(self):
+        if self._active:
+            state = self._device_state
+        else:
+            state = network.DEVICE_STATE_UNKNOWN
+
+        if state in [network.DEVICE_STATE_PREPARE,
+                     network.DEVICE_STATE_CONFIG,
+                     network.DEVICE_STATE_NEED_AUTH,
+                     network.DEVICE_STATE_IP_CONFIG]:
+            if self._disconnect_item:
+                self._disconnect_item.show()
+            self._connect_item.hide()
+            self._palette.props.secondary_text = _('Connecting...')
+            self.props.pulsing = True
+        elif state == network.DEVICE_STATE_ACTIVATED:
+            if self._disconnect_item:
+                self._disconnect_item.show()
+            self._connect_item.hide()
+            self._palette.props.secondary_text = _('Connected')
+            self.props.pulsing = False
+        else:
+            if self._disconnect_item:
+                self._disconnect_item.hide()
+            self._connect_item.show()
+            self._palette.props.secondary_text = None
+            self.props.pulsing = False
+
+    def _update_color(self):
+        if self._greyed_out:
+            self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
+        else:
+            self.props.base_color = profile.get_color()
+
+    def __connect_activate_cb(self, icon):
+        self._connect()
+
+    def __button_release_event_cb(self, icon, event):
+        self._connect()
+
+    def _connect(self):
+        self._mesh_mgr.user_activate_channel(self._channel)
+
+    def __activate_reply_cb(self, connection):
+        logging.debug('Connection activated: %s', connection)
+
+    def __activate_error_cb(self, err):
+        logging.error('Failed to activate connection: %s', err)
+
+    def set_filter(self, query):
+        self._greyed_out = (query != '')
+        self._update_color()
+
+    def disconnect(self):
+        self._bus.remove_signal_receiver(self.__device_state_changed_cb,
+                                         signal_name='StateChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_DEVICE_IFACE)
+        self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb,
+                                         signal_name='PropertiesChanged',
+                                         path=self._device.object_path,
+                                         dbus_interface=_NM_OLPC_MESH_IFACE)
+
+
 class ActivityView(hippo.CanvasBox):
     def __init__(self, model):
         hippo.CanvasBox.__init__(self)
@@ -752,6 +907,8 @@ class NetworkManagerObserver(object):
         device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
         if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
             self._devices[device_o] = DeviceObserver(self._box, device)
+        elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
+            self._box.enable_olpc_mesh(device)
 
     def _get_device_path_error_cb(self, err):
         logging.error('Failed to get device type: %s', err)
@@ -764,6 +921,13 @@ class NetworkManagerObserver(object):
             observer = self._devices[device_o]
             observer.disconnect()
             del self._devices[device_o]
+            return
+            
+        device = self._bus.get_object(_NM_SERVICE, device_o)
+        props = dbus.Interface(device, 'org.freedesktop.DBus.Properties')
+        device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
+        if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
+            self._box.disable_olpc_mesh(device)
 
 
 class MeshBox(gtk.VBox):
@@ -779,7 +943,7 @@ class MeshBox(gtk.VBox):
         self._model = neighborhood.get_model()
         self._buddies = {}
         self._activities = {}
-        self._mesh = {}
+        self._mesh = []
         self._buddy_to_activity = {}
         self._suspended = True
         self._query = ''
@@ -924,6 +1088,14 @@ class MeshBox(gtk.VBox):
             del self.wireless_networks[hash]
  
     def _ap_props_changed_cb(self, ap, old_hash):
+        # if we have mesh hardware, ignore OLPC mesh networks that appear as
+        # normal wifi networks
+        if len(self._mesh) > 0 and ap.mode == network.NM_802_11_MODE_ADHOC \
+                and ap.name == "olpc-mesh":
+            logging.debug("ignoring OLPC mesh IBSS")
+            ap.disconnect()
+            return
+
         if old_hash is None: # new AP finished initializing
             self._add_ap_to_network(ap)
             return
@@ -958,18 +1130,49 @@ class MeshBox(gtk.VBox):
             self._remove_net_if_empty(net, ap.network_hash())
             return
 
-        logging.error('Can not remove access point %s', ap_o)
+        # it's not an error if the AP isn't found, since we might have ignored
+        # it (e.g. olpc-mesh adhoc network)
+        logging.debug('Can not remove access point %s' % ap_o)
+
+    def _add_olpc_mesh_icon(self, mesh_mgr, channel):
+        icon = OlpcMeshView(mesh_mgr, channel)
+        self._layout.add(icon)
+        self._mesh.append(icon)
+
+    def enable_olpc_mesh(self, mesh_device):
+        mesh_mgr = OlpcMeshManager(mesh_device)
+        self._add_olpc_mesh_icon(mesh_mgr, 1)
+        self._add_olpc_mesh_icon(mesh_mgr, 6)
+        self._add_olpc_mesh_icon(mesh_mgr, 11)
+
+        # the OLPC mesh can be recognised as a "normal" wifi network. remove
+        # any such normal networks if they have been created
+        for hash, net in self.wireless_networks.iteritems():
+            if not net.is_olpc_mesh():
+                continue
+
+            logging.debug("removing OLPC mesh IBSS")
+            net.remove_all_aps()
+            net.disconnect()
+            self._layout.remove(net)
+            del self.wireless_networks[hash]
+
+    def disable_olpc_mesh(self, mesh_device):
+        for icon in self._mesh:
+            icon.disconnect()
+            self._layout.remove(icon)
+        self._mesh = []
 
     def suspend(self):
         if not self._suspended:
             self._suspended = True
-            for net in self.wireless_networks.values():
+            for net in self.wireless_networks.values() + self._mesh:
                 net.props.paused = True
 
     def resume(self):
         if self._suspended:
             self._suspended = False
-            for net in self.wireless_networks.values():
+            for net in self.wireless_networks.values() + self._mesh:
                 net.props.paused = False
 
     def _toolbar_query_changed_cb(self, toolbar, query):
diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am
index 399db65..18d44da 100644
--- a/src/jarabe/model/Makefile.am
+++ b/src/jarabe/model/Makefile.am
@@ -6,6 +6,7 @@ sugar_PYTHON =			\
 	filetransfer.py		\
 	friends.py		\
 	invites.py		\
+	olpcmesh.py		\
 	owner.py		\
 	neighborhood.py		\
         network.py              \
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index 23b7472..97c5d27 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -29,6 +29,7 @@ from sugar import env
 
 DEVICE_TYPE_802_3_ETHERNET = 1
 DEVICE_TYPE_802_11_WIRELESS = 2
+DEVICE_TYPE_802_11_OLPC_MESH = 6
 
 DEVICE_STATE_UNKNOWN = 0
 DEVICE_STATE_UNMANAGED = 1
@@ -103,6 +104,8 @@ class WirelessSecurity(object):
         return wireless_security
 
 class Wireless(object):
+    nm_name = "802-11-wireless"
+
     def __init__(self):
         self.ssid = None
         self.security = None
@@ -119,6 +122,23 @@ class Wireless(object):
             wireless['band'] = self.band
         return wireless
 
+class OlpcMesh(object):
+    nm_name = "802-11-olpc-mesh"
+
+    def __init__(self, channel, anycast_addr):
+        self.channel = channel
+        self.anycast_addr = anycast_addr
+
+    def get_dict(self):
+        ret = {
+            "ssid": dbus.ByteArray("olpc-mesh"),
+            "channel": self.channel,
+        }
+
+        if self.anycast_addr:
+            ret["dhcp-anycast-address"] = dbus.ByteArray(self.anycast_addr)
+        return ret
+
 class Connection(object):
     def __init__(self):
         self.id = None
@@ -147,16 +167,20 @@ class IP4Config(object):
         return ip4_config
 
 class Settings(object):
-    def __init__(self):
+    def __init__(self, wireless_cfg=None):
         self.connection = Connection()
-        self.wireless = Wireless()
         self.ip4_config = None
         self.wireless_security = None
 
+        if wireless_cfg is not None:
+            self.wireless = wireless_cfg
+        else:
+            self.wireless = Wireless()
+
     def get_dict(self):
         settings = {}
         settings['connection'] = self.connection.get_dict()
-        settings['802-11-wireless'] = self.wireless.get_dict()
+        settings[self.wireless.nm_name] = self.wireless.get_dict()
         if self.wireless_security is not None:
             settings['802-11-wireless-security'] = \
                 self.wireless_security.get_dict()
diff --git a/src/jarabe/model/olpcmesh.py b/src/jarabe/model/olpcmesh.py
new file mode 100644
index 0000000..bdf0cec
--- /dev/null
+++ b/src/jarabe/model/olpcmesh.py
@@ -0,0 +1,214 @@
+# Copyright (C) 2009 One Laptop per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import logging
+
+import dbus
+import gobject
+
+from jarabe.model import network
+from jarabe.model.network import Settings
+from jarabe.model.network import OlpcMesh as OlpcMeshSettings
+from sugar.util import unique_id
+
+_NM_SERVICE = 'org.freedesktop.NetworkManager'
+_NM_IFACE = 'org.freedesktop.NetworkManager'
+_NM_PATH = '/org/freedesktop/NetworkManager'
+_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
+_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh'
+
+_XS_ANYCAST = "\xc0\x27\xc0\x27\xc0\x00"
+
+DEVICE_STATE_UNKNOWN = 0
+DEVICE_STATE_UNMANAGED = 1
+DEVICE_STATE_UNAVAILABLE = 2
+DEVICE_STATE_DISCONNECTED = 3
+DEVICE_STATE_PREPARE = 4
+DEVICE_STATE_CONFIG = 5
+DEVICE_STATE_NEED_AUTH = 6
+DEVICE_STATE_IP_CONFIG = 7
+DEVICE_STATE_ACTIVATED = 8
+DEVICE_STATE_FAILED = 9
+
+class OlpcMeshManager(object):
+    def __init__(self, mesh_device):
+        self._bus = dbus.SystemBus()
+
+        self.mesh_device = mesh_device
+        self.eth_device = self._get_companion_device()
+
+        self._connection_queue = []
+        """Stack of connections that we'll iterate through until we find one
+           that works.
+
+        """
+
+        props = dbus.Interface(self.mesh_device,
+                               'org.freedesktop.DBus.Properties')
+        props.Get(_NM_DEVICE_IFACE, 'State',
+                  reply_handler=self.__get_mesh_state_reply_cb,
+                  error_handler=self.__get_state_error_cb)
+
+        props = dbus.Interface(self.eth_device,
+                               'org.freedesktop.DBus.Properties')
+        props.Get(_NM_DEVICE_IFACE, 'State',
+                  reply_handler=self.__get_eth_state_reply_cb,
+                  error_handler=self.__get_state_error_cb)
+
+        self._bus.add_signal_receiver(self.__eth_device_state_changed_cb,
+                                      signal_name='StateChanged',
+                                      path=self.eth_device.object_path,
+                                      dbus_interface=_NM_DEVICE_IFACE)
+
+        self._bus.add_signal_receiver(self.__mshdev_state_changed_cb,
+                                      signal_name='StateChanged',
+                                      path=self.mesh_device.object_path,
+                                      dbus_interface=_NM_DEVICE_IFACE)
+
+        self._idle_source = 0
+        self._mesh_device_state = DEVICE_STATE_UNKNOWN
+        self._eth_device_state = DEVICE_STATE_UNKNOWN
+
+        if self._have_configured_connections():
+            self._start_automesh_timer()
+        else:
+            self._start_automesh()
+
+    def _get_companion_device(self):
+        props = dbus.Interface(self.mesh_device,
+                               'org.freedesktop.DBus.Properties')
+        eth_device_o = props.Get(_NM_OLPC_MESH_IFACE, 'Companion')
+        return self._bus.get_object(_NM_SERVICE, eth_device_o)
+
+    def _have_configured_connections(self):
+        return len(network.get_settings().connections) > 0
+
+    def _start_automesh_timer(self):
+        """Start our timer system which basically looks for 10 seconds of
+           inactivity on both devices, then starts automesh.
+
+        """
+        if self._idle_source != 0:
+            gobject.source_remove(self._idle_source)
+        self._idle_source = gobject.timeout_add_seconds(10, self._idle_check)
+
+    def __get_state_error_cb(self, err):
+        logging.debug('Error getting the device state: %s', err)
+
+    def __get_mesh_state_reply_cb(self, state):
+        self._mesh_device_state = state
+        self._maybe_schedule_idle_check()
+
+    def __get_eth_state_reply_cb(self, state):
+        self._eth_device_state = state
+        self._maybe_schedule_idle_check()
+
+    def __eth_device_state_changed_cb(self, new_state, old_state, reason):
+        """If a connection is activated on the eth device, stop trying our
+        automatic connections.
+        
+        """
+        self._eth_device_state = new_state
+        self._maybe_schedule_idle_check()
+
+        if new_state >= DEVICE_STATE_PREPARE \
+                and new_state <= DEVICE_STATE_ACTIVATED \
+                and len(self._connection_queue) > 0:
+            self._connection_queue = []
+
+    def __mshdev_state_changed_cb(self, new_state, old_state, reason):
+        self._mesh_device_state = new_state
+        self._maybe_schedule_idle_check()
+
+        if new_state == DEVICE_STATE_FAILED:
+            self._try_next_connection_from_queue()
+        elif new_state == DEVICE_STATE_ACTIVATED \
+                and len(self._connection_queue) > 0:
+            self._empty_connection_queue()
+
+    def _maybe_schedule_idle_check(self):
+        if self._mesh_device_state == DEVICE_STATE_DISCONNECTED \
+                and self._eth_device_state == DEVICE_STATE_DISCONNECTED:
+            self._start_automesh_timer()
+
+    def _idle_check(self):
+        if self._mesh_device_state == DEVICE_STATE_DISCONNECTED \
+                and self._eth_device_state == DEVICE_STATE_DISCONNECTED:
+            logging.debug("starting automesh due to inactivity")
+            self._start_automesh()
+        return False
+
+    def _make_connection(self, channel, anycast_address=None):
+        wireless_config = OlpcMeshSettings(channel, anycast_address)
+        settings = Settings(wireless_cfg=wireless_config)
+        if not anycast_address:
+            settings.ip4_config = network.IP4Config()
+            settings.ip4_config.method = 'link-local'
+        settings.connection.id = 'olpc-mesh-' + str(channel)
+        settings.connection.uuid = unique_id()
+        settings.connection.type = '802-11-olpc-mesh'
+        connection = network.add_connection(settings.connection.id, settings)
+        return connection
+
+    def __activate_reply_cb(self, connection):
+        logging.debug('Connection activated: %s', connection)
+
+    def __activate_error_cb(self, err):
+        logging.error('Failed to activate connection: %s', err)
+
+    def _activate_connection(self, channel, anycast_address=None):
+        logging.debug("activate channel %d anycast %s",
+                      (channel, repr(anycast_address)))
+        proxy = self._bus.get_object(_NM_SERVICE, _NM_PATH)
+        network_manager = dbus.Interface(proxy, _NM_IFACE)
+        connection = self._make_connection(channel, anycast_address)
+
+        network_manager.ActivateConnection(network.SETTINGS_SERVICE,
+                connection.path,
+                self.mesh_device.object_path,
+                self.mesh_device.object_path,
+                reply_handler=self.__activate_reply_cb,
+                error_handler=self.__activate_error_cb)
+
+    def _try_next_connection_from_queue(self):
+        if len(self._connection_queue) == 0:
+            return
+
+        channel, anycast = self._connection_queue.pop()
+        self._activate_connection(channel, anycast)
+
+    def _empty_connection_queue(self):
+        self._connection_queue = []
+
+    def user_activate_channel(self, channel):
+        """Activate a mesh connection on a user-specified channel.
+        Looks for XS first, then resorts to simple mesh."""
+        self._empty_connection_queue()
+        self._connection_queue.append((channel, None))
+        self._connection_queue.append((channel, _XS_ANYCAST))
+        self._try_next_connection_from_queue()
+
+    def _start_automesh(self):
+        """Start meshing automatically, intended when there are no better
+        networks to connect to. First looks for XS on all channels, then falls
+        back to simple mesh on channel 1."""
+        self._empty_connection_queue()
+        self._connection_queue.append((1, None))
+        self._connection_queue.append((11, _XS_ANYCAST))
+        self._connection_queue.append((6, _XS_ANYCAST))
+        self._connection_queue.append((1, _XS_ANYCAST))
+        self._try_next_connection_from_queue()
+
