Merge remote branch 'origin/master' into wimax
authorDan Williams <dcbw@redhat.com>
Wed, 19 May 2010 15:55:26 +0000 (08:55 -0700)
committerDan Williams <dcbw@redhat.com>
Wed, 19 May 2010 15:55:26 +0000 (08:55 -0700)
19 files changed:
1  2 
configure.ac
include/NetworkManager.h
introspection/Makefile.am
introspection/all.xml
introspection/nm-manager.xml
libnm-glib/Makefile.am
libnm-glib/libnm-glib.ver
libnm-glib/nm-device.c
libnm-util/Makefile.am
libnm-util/libnm-util.ver
src/Makefile.am
src/main.c
src/nm-device-olpc-mesh.c
src/nm-manager.c
src/nm-udev-manager.c
src/wimax/nm-wimax-device.c
src/wimax/nm-wimax-device.h
src/wimax/nm-wimax-manager.c
src/wimax/nm-wimax-manager.h

diff --cc configure.ac
Simple merge
Simple merge
@@@ -24,6 -24,5 +24,7 @@@ EXTRA_DIST = 
        nm-ppp-manager.xml \
        nm-active-connection.xml \
        nm-dhcp4-config.xml \
 -      nm-dhcp6-config.xml
++      nm-dhcp6-config.xml \
 +      nm-wimax-device.xml \
 +      nm-wimax-nsp.xml
  
Simple merge
Simple merge
@@@ -21,8 -21,32 +21,33 @@@ BUILT_SOURCES = 
        nm-ip4-config-bindings.h \
        nm-dhcp4-config-bindings.h \
        nm-ip6-config-bindings.h \
 -      nm-dhcp6-config-bindings.h
++      nm-dhcp6-config-bindings.h \
 +      nm-wimax-device-bindings.h
  
+ #####################################################
+ # Deprecated original libnm_glib bits
+ #####################################################
+ noinst_LTLIBRARIES = libdeprecated-nm-glib.la
+ libdeprecated_nm_glib_la_SOURCES = \
+       libnm_glib.h \
+       libnm_glib.c
+ libdeprecated_nm_glib_la_CPPFLAGS = \
+       $(DBUS_CFLAGS) \
+       $(GLIB_CFLAGS) \
+       -Wno-deprecated-declarations \
+       -Wno-deprecated
+ libdeprecated_nm_glib_la_LIBADD = \
+       $(DBUS_LIBS) \
+       $(GLIB_LIBS)
+ #####################################################
+ # Real libnm-glib stuff
+ #####################################################
  lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la
  
  libnm_glib_la_CFLAGS = \
@@@ -60,12 -85,9 +86,11 @@@ libnminclude_HEADERS = 
        nm-remote-settings-system.h \
        nm-settings-connection-interface.h \
        nm-exported-connection.h \
 -      nm-settings-service.h
 +      nm-settings-service.h \
 +      nm-wimax-device.h \
 +      nm-wimax-nsp.h
  
  libnm_glib_la_SOURCES = \
-       libnm_glib.c \
        nm-object.c \
        nm-object-private.h \
        nm-client.c \
@@@ -177,9 -199,9 +204,12 @@@ nm-dhcp4-config-bindings.h: $(top_srcdi
  nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml
        dbus-binding-tool --prefix=nm_ip6_config --mode=glib-client --output=$@ $<
  
+ nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
+       dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $<
 +nm-wimax-device-bindings.h: $(top_srcdir)/introspection/nm-wimax-device.xml
 +      dbus-binding-tool --prefix=nm_wimax_device --mode=glib-client --output=$@ $<
 +
  pkgconfigdir = $(libdir)/pkgconfig
  pkgconfig_DATA = libnm-glib.pc libnm-glib-vpn.pc
  
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/Makefile.am
@@@ -166,12 -208,9 +210,10 @@@ BUILT_SOURCES = 
  NetworkManager_CPPFLAGS = \
        $(DBUS_CFLAGS) \
        $(GLIB_CFLAGS) \
-       $(HAL_CFLAGS) \
        $(GUDEV_CFLAGS) \
-       $(OPENSSL_CFLAGS) \
        $(LIBNL_CFLAGS) \
        $(GMODULE_CFLAGS) \
 +      $(WIMAX_CFLAGS) \
        -DG_DISABLE_DEPRECATED \
        -DBINDIR=\"$(bindir)\" \
        -DSBINDIR=\"$(sbindir)\" \
diff --cc src/main.c
@@@ -445,10 -442,10 +453,10 @@@ main (int argc, char *argv[]
        GOptionContext *opt_ctx = NULL;
        gboolean become_daemon = FALSE;
        gboolean g_fatal_warnings = FALSE;
-       char *pidfile = NULL, *user_pidfile = NULL;
-       char *config = NULL, *plugins = NULL;
-       char *state_file = NM_DEFAULT_SYSTEM_STATE_FILE;
+       char *pidfile = NULL, *state_file = NULL, *dhcp = NULL;
+       char *config = NULL, *plugins = NULL, *conf_plugins = NULL;
+       char *log_level = NULL, *log_domains = NULL;
 -      gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE;
 +      gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE, wimax_enabled = TRUE;
        gboolean success;
        NMPolicy *policy = NULL;
        NMVPNManager *vpn_manager = NULL;
                }
        }
  
-       g_clear_error (&error);
+       /* Logging setup */
+       if (!nm_logging_setup (log_level ? log_level : cfg_log_level,
+                              log_domains ? log_domains : cfg_log_domains,
+                              &error)) {
+               fprintf (stderr,
+                        _("%s.  Please use --help to see a list of valid options.\n"),
+                        error->message);
+               exit (1);
+       }
+       /* Plugins specified with '--plugins' override those of config file */
+       plugins = plugins ? plugins : g_strdup (conf_plugins);
+       g_free (conf_plugins);
  
        /* Parse the state file */
 -      if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) {
 +      if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &wimax_enabled, &error)) {
-               g_warning ("State file %s parsing failed: (%d) %s.",
-                          state_file,
-                          error ? error->code : -1,
-                          (error && error->message) ? error->message : "unknown");
+               fprintf (stderr, "State file %s parsing failed: (%d) %s\n",
+                        state_file,
+                        error ? error->code : -1,
+                        (error && error->message) ? error->message : "unknown");
                /* Not a hard failure */
        }
+       g_clear_error (&error);
  
        /* Tricky: become_daemon is FALSE by default, so unless it's TRUE because
         * of a CLI option, it'll become TRUE after this
                                  net_enabled,
                                  wifi_enabled,
                                  wwan_enabled,
 +                                                        wimax_enabled,
                                  &error);
        if (manager == NULL) {
-               nm_error ("Failed to initialize the network manager: %s",
+               nm_log_err (LOGD_CORE, "failed to initialize the network manager: %s",
                          error && error->message ? error->message : "(unknown)");
                goto done;
        }
@@@ -906,18 -902,19 +902,19 @@@ check_companion_cb (gpointer user_data
                return FALSE;
        }
  
-       if (priv->device_added_cb != 0)
+       if (priv->device_added_id != 0)
                return FALSE;
  
 -      manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL);
 +      manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
  
-       priv->device_added_cb = g_signal_connect (manager, "device-added",
+       priv->device_added_id = g_signal_connect (manager, "device-added",
                                                  G_CALLBACK (device_added_cb), self);
  
-       list = nm_manager_get_devices (manager);
-       for (; list != NULL ; list = list->next)
+       /* Try to find the companion if it's already known to the NMManager */
+       for (list = nm_manager_get_devices (manager); list ; list = g_slist_next (list)) {
                if (is_companion (self, NM_DEVICE (list->data)))
                        break;
+       }
  
        g_object_unref (manager);
  
  #include "nm-device-ethernet.h"
  #include "nm-device-wifi.h"
  #include "nm-device-olpc-mesh.h"
- #include "NetworkManagerSystem.h"
 +#include "nm-wimax-device.h"
+ #include "nm-device-cdma.h"
+ #include "nm-device-gsm.h"
+ #include "nm-system.h"
  #include "nm-properties-changed-signal.h"
  #include "nm-setting-bluetooth.h"
  #include "nm-setting-connection.h"
@@@ -3131,15 -3167,15 +3189,15 @@@ nm_manager_init (NMManager *manager
        priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED;
        priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN";
        priv->radio_states[RFKILL_TYPE_WWAN].other_enabled_func = nm_manager_get_modem_enabled_state;
-       priv->radio_states[RFKILL_TYPE_WWAN].object_filter_func = rfkill_wwan_filter;
+       priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN;
  
        priv->radio_states[RFKILL_TYPE_WIMAX].enabled = TRUE;
-       priv->radio_states[RFKILL_TYPE_WIMAX].key = "WimaxEnabled";
+       priv->radio_states[RFKILL_TYPE_WIMAX].key = "WiMAXEnabled";
 -      priv->radio_states[RFKILL_TYPE_WIMAX].prop = NULL;
 -      priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NULL;
 +      priv->radio_states[RFKILL_TYPE_WIMAX].prop = NM_MANAGER_WIMAX_ENABLED;
 +      priv->radio_states[RFKILL_TYPE_WIMAX].hw_prop = NM_MANAGER_WIMAX_HARDWARE_ENABLED;
        priv->radio_states[RFKILL_TYPE_WIMAX].desc = "WiMAX";
        priv->radio_states[RFKILL_TYPE_WIMAX].other_enabled_func = NULL;
-       priv->radio_states[RFKILL_TYPE_WIMAX].object_filter_func = rfkill_wimax_filter;
+       priv->radio_states[RFKILL_TYPE_WIMAX].rtype = RFKILL_TYPE_WIMAX;
  
        for (i = 0; i < RFKILL_TYPE_MAX; i++)
                priv->radio_states[i].hw_enabled = TRUE;
@@@ -363,13 -384,11 +391,13 @@@ device_creator (NMUdevManager *manager
        }
  
        if (is_olpc_mesh (udev_device)) /* must be before is_wireless */
-               device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver, ifindex);
+               device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver);
        else if (is_wireless (udev_device))
-               device = (GObject *) nm_device_wifi_new (path, ifname, driver, ifindex);
+               device = (GObject *) nm_device_wifi_new (path, ifname, driver);
 +      else if (is_wimax (driver))
-               device = (GObject *) nm_wimax_manager_create_device (path, ifname, driver, ifindex);
++              device = (GObject *) nm_wimax_manager_create_device (path, ifname, driver);
        else
-               device = (GObject *) nm_device_ethernet_new (path, ifname, driver, ifindex);
+               device = (GObject *) nm_device_ethernet_new (path, ifname, driver);
  
  out:
        if (grandparent)
index 66a7b65,0000000..6a5aed9
mode 100644,000000..100644
--- /dev/null
@@@ -1,1063 -1,0 +1,1040 @@@
-       PROP_IFINDEX,
 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 +/* NetworkManager -- Network link manager
 + *
 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
 + * Copyright (C) 2009 Novell, Inc.
 + */
 +
 +#include <string.h>
 +#include <WiMaxAPI.h>
 +#include <WiMaxAPIEx.h>
 +
 +#include "nm-wimax-device.h"
 +#include "nm-wimax-util.h"
 +#include "nm-device-interface.h"
 +#include "nm-device-private.h"
 +#include "NetworkManagerSystem.h"
 +#include "NetworkManagerUtils.h"
 +#include "nm-properties-changed-signal.h"
 +#include "nm-connection.h"
 +#include "nm-setting-connection.h"
 +#include "nm-setting-wimax.h"
 +#include "nm-utils.h"
 +
 +static gboolean impl_device_get_nsp_list (NMWimaxDevice *device, GPtrArray **list, GError **error);
 +
 +#include "nm-wimax-device-glue.h"
 +
 +static void device_interface_init (NMDeviceInterface *iface_class);
 +
 +G_DEFINE_TYPE_EXTENDED (NMWimaxDevice, nm_wimax_device, NM_TYPE_DEVICE, 0,
 +                                              G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init))
 +
 +enum {
 +      PROP_0,
 +      PROP_INDEX,
-       guint32 ifindex;
 +      PROP_HW_ADDRESS,
 +      PROP_ACTIVE_NSP,
 +
 +      LAST_PROP
 +};
 +
 +enum {
 +      NSP_ADDED,
 +      NSP_REMOVED,
 +      PROPERTIES_CHANGED,
 +
 +      LAST_SIGNAL
 +};
 +
 +static guint signals[LAST_SIGNAL] = { 0 };
 +
 +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_DEVICE, NMWimaxDevicePrivate))
 +
 +typedef struct {
 +      struct WIMAX_API_DEVICE_ID device_id;
 +      NMWimaxDevice *object;
 +
 +      gboolean enabled;
 +      struct ether_addr hw_addr;
-                                        int ifindex,
 +      guint activation_timeout_id;
 +
 +      GSList *nsp_list;
 +      NMWimaxNsp *current_nsp;
 +      guint rf_update_id;
 +} NMWimaxDevicePrivate;
 +
 +static void nm_wimax_api_close (NMWimaxDevice *self);
 +static gboolean nm_wimax_api_open (NMWimaxDevice *self);
 +static void real_update_hw_address (NMDevice *device);
 +
 +typedef enum
 +{
 +      NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX = 0,
 +      NM_WIMAX_ERROR_CONNECTION_INVALID,
 +      NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE,
 +} NMWimaxError;
 +
 +#define NM_WIMAX_ERROR (nm_wimax_error_quark ())
 +#define NM_TYPE_WIMAX_ERROR (nm_wimax_error_get_type ()) 
 +
 +static GQuark
 +nm_wimax_error_quark (void)
 +{
 +      static GQuark quark = 0;
 +      if (!quark)
 +              quark = g_quark_from_static_string ("nm-wimax-error");
 +      return quark;
 +}
 +
 +/* This should really be standard. */
 +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
 +
 +static GType
 +nm_wimax_error_get_type (void)
 +{
 +      static GType etype = 0;
 +
 +      if (etype == 0) {
 +              static const GEnumValue values[] = {
 +                      /* Connection was not a wired connection. */
 +                      ENUM_ENTRY (NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX, "ConnectionNotWimax"),
 +                      /* Connection was not a valid wired connection. */
 +                      ENUM_ENTRY (NM_WIMAX_ERROR_CONNECTION_INVALID, "ConnectionInvalid"),
 +                      /* Connection does not apply to this device. */
 +                      ENUM_ENTRY (NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"),
 +                      { 0, 0, 0 }
 +              };
 +              etype = g_enum_register_static ("NMWimaxError", values);
 +      }
 +      return etype;
 +}
 +
 +
 +NMDevice *
 +nm_wimax_device_new (const char *udi,
 +                                       const char *iface,
 +                                       const char *driver,
-                                                                       NM_WIMAX_DEVICE_IFINDEX, ifindex,
 +                                       guchar wimax_device_index)
 +{
 +      g_return_val_if_fail (udi != NULL, NULL);
 +      g_return_val_if_fail (iface != NULL, NULL);
 +      g_return_val_if_fail (driver != NULL, NULL);
 +      g_return_val_if_fail (wimax_device_index != 0, NULL);
 +
 +      return NM_DEVICE (g_object_new (NM_TYPE_WIMAX_DEVICE,
 +                                                                      NM_DEVICE_INTERFACE_UDI, udi,
 +                                                                      NM_DEVICE_INTERFACE_IFACE, iface,
 +                                                                      NM_DEVICE_INTERFACE_DRIVER, driver,
 +                                                                      NM_DEVICE_INTERFACE_TYPE_DESC, "WiMAX",
 +                                                                      NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_WIMAX,
 +                                                                      NM_WIMAX_DEVICE_INDEX, wimax_device_index,
- guint32
- nm_wimax_device_get_ifindex (NMWimaxDevice *self)
- {
-       g_return_val_if_fail (NM_IS_WIMAX_DEVICE (self), 0);
-       return GET_PRIVATE (self)->ifindex;
- }
 +                                                                      NULL));
 +}
 +
 +void
 +nm_wimax_device_get_hw_address (NMWimaxDevice *self, struct ether_addr *addr)
 +{
 +      g_return_if_fail (NM_IS_WIMAX_DEVICE (self));
 +      g_return_if_fail (addr != NULL);
 +
 +      memcpy (addr, &(GET_PRIVATE (self)->hw_addr), sizeof (struct ether_addr));
 +}
 +
-       case PROP_IFINDEX:
-               priv->ifindex = g_value_get_uint (value);
-               break;
 +static gboolean
 +rf_state_update (NMWimaxDevice *self)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +      WIMAX_API_DEVICE_STATUS status;
 +      WIMAX_API_CONNECTION_PROGRESS_INFO pi;
 +      WIMAX_API_RET result;
 +      gboolean enable;
 +
 +      priv->rf_update_id = 0;
 +
 +      enable = priv->enabled;
 +      if (enable) {
 +              if (nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)) < NM_DEVICE_STATE_UNAVAILABLE)
 +                      enable = FALSE;
 +      }
 +
 +      result = GetDeviceStatus (&priv->device_id, &status, &pi);
 +      if (result != WIMAX_API_RET_SUCCESS)
 +              nm_wimax_util_error (&priv->device_id, "Reading WiMax device status failed", result);
 +
 +      switch (status) {
 +      case WIMAX_API_DEVICE_STATUS_UnInitialized:
 +      case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
 +      case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
 +              /* Can not enable the device */
 +              if (enable)
 +                      nm_warning ("Can not enable the WiMAX device, it's RF killed");
 +              goto out;
 +      case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
 +              if (!enable)
 +                      /* Already matches */
 +                      goto out;
 +              break;
 +      case WIMAX_API_DEVICE_STATUS_Ready:
 +      case WIMAX_API_DEVICE_STATUS_Scanning:
 +      case WIMAX_API_DEVICE_STATUS_Connecting:
 +      case WIMAX_API_DEVICE_STATUS_Data_Connected:
 +      case WIMAX_API_DEVICE_STATUS_Connection_Idle:
 +              if (enable)
 +                      /* Already matches */
 +                      goto out;
 +              break;
 +      default:
 +              nm_warning ("Unhandled WiMAX device state");
 +              goto out;
 +      }
 +
 +      g_debug ("Changing wimax device RF state: %d", enable);
 +      result = CmdControlPowerManagement (&priv->device_id, enable ? WIMAX_API_RF_ON : WIMAX_API_RF_OFF);
 +      if (result != WIMAX_API_RET_SUCCESS)
 +              nm_wimax_util_error (&priv->device_id, "WiMax device RF change failed", result);
 +
 + out:
 +      return FALSE;
 +}
 +
 +static void
 +schedule_rf_state_update (NMWimaxDevice *self)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +
 +      /* This is scheduled because on startup we get nm_device_interface_set_enabled()
 +         while the device state is still unmanaged. It'll change to unavailable right
 +         after it, so it would result in enabling RF kill, followed by disabling it again.
 +         Pretty lame.
 +      */
 +
 +      if (priv->rf_update_id == 0)
 +              priv->rf_update_id = g_idle_add ((GSourceFunc) rf_state_update, self);
 +}
 +
 +GSList *
 +nm_wimax_device_get_nsps (NMWimaxDevice *self)
 +{
 +      g_return_val_if_fail (NM_IS_WIMAX_DEVICE (self), NULL);
 +
 +      return GET_PRIVATE (self)->nsp_list;
 +}
 +
 +static gboolean
 +impl_device_get_nsp_list (NMWimaxDevice *device, GPtrArray **nsps, GError **error)
 +{
 +      GSList *list;
 +      GSList *iter;
 +
 +      list = nm_wimax_device_get_nsps (device);
 +      *nsps = g_ptr_array_sized_new (g_slist_length (list));
 +      for (iter = list; iter; iter = iter->next) {
 +              const char *path;
 +
 +              path = nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data));
 +              if (path)
 +                      g_ptr_array_add (*nsps, g_strdup (path));
 +      }
 +
 +      return TRUE;
 +}
 +
 +static void
 +set_current_nsp (NMWimaxDevice *self, NMWimaxNsp *new_nsp)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +      NMWimaxNsp *old_nsp;
 +      char *old_path = NULL;
 +
 +      old_nsp = priv->current_nsp;
 +      if (old_nsp) {
 +              old_path = g_strdup (nm_wimax_nsp_get_dbus_path (old_nsp));
 +              priv->current_nsp = NULL;
 +      }
 +
 +      if (new_nsp)
 +              priv->current_nsp = g_object_ref (new_nsp);
 +
 +      if (old_nsp)
 +              g_object_unref (old_nsp);
 +
 +      /* Only notify if it's really changed */
 +      if ((!old_path && new_nsp)
 +              || (old_path && !new_nsp)
 +          || (old_path && new_nsp && strcmp (old_path, nm_wimax_nsp_get_dbus_path (new_nsp))))
 +              g_object_notify (G_OBJECT (self), NM_WIMAX_DEVICE_ACTIVE_NSP);
 +
 +      g_free (old_path);
 +}
 +
 +NMWimaxNsp *
 +nm_wimax_device_get_active_nsp (NMWimaxDevice *self)
 +{
 +      g_return_val_if_fail (NM_IS_WIMAX_DEVICE (self), NULL);
 +
 +      return GET_PRIVATE (self)->current_nsp;
 +}
 +
 +static gboolean
 +activation_timed_out (gpointer data)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (data);
 +
 +      priv->activation_timeout_id = 0;
 +      nm_device_state_changed (NM_DEVICE (data), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
 +
 +      return FALSE;
 +}
 +
 +static void
 +wimax_status_change_cb (struct WIMAX_API_DEVICE_ID *device_id,
 +                                              WIMAX_API_DEVICE_STATUS status,
 +                                              WIMAX_API_STATUS_REASON reason,
 +                                              WIMAX_API_CONNECTION_PROGRESS_INFO progress)
 +{
 +      NMWimaxDevicePrivate *priv = (NMWimaxDevicePrivate *) device_id;
 +      NMWimaxDevice *self = priv->object;
 +      NMDeviceState device_state;
 +
 +      device_state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
 +      g_debug ("wimax status changed: %s (device state %d)", nm_wimax_util_device_status_to_str (status), device_state);
 +
 +      switch (status) {
 +      case WIMAX_API_DEVICE_STATUS_UnInitialized:
 +      case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
 +      case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
 +      case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
 +              priv->enabled = FALSE;
 +              if (device_state >= NM_DEVICE_STATE_DISCONNECTED)
 +                      nm_device_state_changed (NM_DEVICE (self),
 +                                                                       NM_DEVICE_STATE_UNAVAILABLE,
 +                                                                       NM_DEVICE_STATE_REASON_NONE);
 +              break;
 +      case WIMAX_API_DEVICE_STATUS_Ready:
 +      case WIMAX_API_DEVICE_STATUS_Scanning:
 +      case WIMAX_API_DEVICE_STATUS_Connecting:
 +      case WIMAX_API_DEVICE_STATUS_Data_Connected:
 +      case WIMAX_API_DEVICE_STATUS_Connection_Idle:
 +              priv->enabled = TRUE;
 +              if (device_state < NM_DEVICE_STATE_DISCONNECTED)
 +                      nm_device_state_changed (NM_DEVICE (self),
 +                                                                       NM_DEVICE_STATE_DISCONNECTED,
 +                                                                       NM_DEVICE_STATE_REASON_NONE);
 +              break;
 +      default:
 +              nm_warning ("Unhandled WiMAX device state");
 +      }
 +}
 +
 +static void
 +remove_all_nsps (NMWimaxDevice *self)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +
 +      while (g_slist_length (priv->nsp_list)) {
 +              NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data);
 +
 +              priv->nsp_list = g_slist_remove (priv->nsp_list, nsp);
 +              g_signal_emit (self, signals[NSP_REMOVED], 0, nsp);
 +              g_object_unref (nsp);
 +      }
 +
 +      g_slist_free (priv->nsp_list);
 +      priv->nsp_list = NULL;
 +}
 +
 +static void
 +remove_outdated_nsps (NMWimaxDevice *self,
 +                                        struct WIMAX_API_NSP_INFO_EX *nsp_list,
 +                                        guint32 list_size)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +      GSList *iter;
 +      GSList *to_remove = NULL;
 +
 +      for (iter = priv->nsp_list; iter; iter = iter->next) {
 +              NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
 +              int i;
 +              gboolean found = FALSE;
 +
 +              for (i = 0; i < list_size; i++) {
 +                      struct WIMAX_API_NSP_INFO_EX *info = &nsp_list[i];
 +
 +                      if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), (char *) info->NSPName)) {
 +                              found = TRUE;
 +                              break;
 +                      }
 +              }
 +
 +              if (!found)
 +                      to_remove = g_slist_prepend (to_remove, nsp);
 +      }
 +
 +      for (iter = to_remove; iter; iter = iter->next) {
 +              NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
 +
 +              g_signal_emit (self, signals[NSP_REMOVED], 0, nsp);
 +              priv->nsp_list = g_slist_remove (priv->nsp_list, nsp);
 +              g_object_unref (nsp);
 +      }
 +
 +      g_slist_free (to_remove);
 +}
 +
 +static NMWimaxNsp *
 +get_nsp_by_name (NMWimaxDevice *self, const char *name)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +      GSList *iter;
 +
 +      for (iter = priv->nsp_list; iter; iter = iter->next) {
 +              NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
 +      
 +              if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), name))
 +                      return nsp;
 +      }
 +
 +      return NULL;
 +}
 +
 +static void
 +wimax_scan_cb (struct WIMAX_API_DEVICE_ID *device_id,
 +                         struct WIMAX_API_NSP_INFO_EX *nsp_list,
 +                         guint32 list_size,
 +                         guint32 progress)
 +{
 +      NMWimaxDevicePrivate *priv = (NMWimaxDevicePrivate *) device_id;
 +      NMWimaxDevice *self = NM_WIMAX_DEVICE (priv->object);
 +      int i;
 +
 +      remove_outdated_nsps (self, nsp_list, list_size);
 +
 +      for (i = 0; i < list_size; i++) {
 +              struct WIMAX_API_NSP_INFO_EX *info = &nsp_list[i];
 +              NMWimaxNsp *nsp;
 +              gboolean new_nsp;
 +              guint32 quality;
 +      
 +              nsp = get_nsp_by_name (self, (char *) info->NSPName);
 +              new_nsp = nsp == NULL;
 +              if (new_nsp)
 +                      nsp = nm_wimax_nsp_new ((char *) info->NSPName);
 +
 +              quality = info->linkQuality;
 +              if (quality == 0) {
 +                      /* This is borrowed from connman */
 +                      quality = nm_wimax_util_cinr_to_percentage (info->CINR - 10);
 +              }
 +
 +              g_object_set (nsp,
 +                                        NM_WIMAX_NSP_SIGNAL_QUALITY, quality,
 +                                        NM_WIMAX_NSP_NETWORK_TYPE, nm_wimax_util_convert_network_type (info->networkType),
 +                                        NULL);
 +
 +              if (new_nsp) {
 +                      priv->nsp_list = g_slist_append (priv->nsp_list, nsp);
 +                      nm_wimax_nsp_export_to_dbus (nsp);
 +                      g_signal_emit (self, signals[NSP_ADDED], 0, nsp);
 +              }
 +      }
 +}
 +
 +static void
 +wimax_wide_scan_cb (struct WIMAX_API_DEVICE_ID *device_id,
 +                                      struct WIMAX_API_NSP_INFO_EX *nsp_list,
 +                                      guint32 list_size)
 +{
 +      wimax_scan_cb (device_id, nsp_list, list_size, 0);
 +}
 +
 +static void
 +wimax_connect_cb (struct WIMAX_API_DEVICE_ID *device_id,
 +                                WIMAX_API_NETWORK_CONNECTION_RESP response)
 +{
 +      NMWimaxDevicePrivate *priv = (NMWimaxDevicePrivate *) device_id;
 +      NMWimaxDevice *self = NM_WIMAX_DEVICE (priv->object);
 +
 +      if (priv->activation_timeout_id == 0) {
 +              g_warning ("WiMax device activated from outside");
 +              return;
 +      }
 +
 +      g_source_remove (priv->activation_timeout_id);
 +      priv->activation_timeout_id = 0;
 +
 +      if (response == WIMAX_API_CONNECTION_SUCCESS)
 +              nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self));
 +      else
 +              nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
 +}
 +
 +static void
 +wimax_disconnect_cb (struct WIMAX_API_DEVICE_ID *device_id,
 +                                       WIMAX_API_NETWORK_CONNECTION_RESP response)
 +{
 +      if (response == WIMAX_API_CONNECTION_SUCCESS) {
 +      } else {
 +              g_warning ("WiMax device disconnect failed");
 +      }
 +}
 +
 +static void
 +nm_wimax_api_close (NMWimaxDevice *self)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +
 +      nm_debug ("Closing wimax device API");
 +
 +      UnsubscribeDisconnectToNetwork (&priv->device_id);
 +      UnsubscribeConnectToNetwork (&priv->device_id);
 +      UnsubscribeNetworkSearchWideScanEx (&priv->device_id);
 +      UnsubscribeNetworkSearchEx (&priv->device_id);
 +      UnsubscribeDeviceStatusChange (&priv->device_id);
 +      WiMaxDeviceClose (&priv->device_id);
 +}
 +
 +static gboolean
 +nm_wimax_api_open (NMWimaxDevice *self)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +      WIMAX_API_RET result;
 +      gboolean success = FALSE;
 +
 +      nm_debug ("Opening wimax device API");
 +
 +      result = WiMaxDeviceOpen (&priv->device_id);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax device open failed", result);
 +              goto err;
 +      }
 +
 +      result = SetConnectionMode (&priv->device_id, WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax device connection mode setting failed", result);
 +              goto err;
 +      }
 +
 +      result = SubscribeDeviceStatusChange (&priv->device_id, wimax_status_change_cb);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax subscription to device status changes failed", result);
 +              goto err;
 +      }
 +
 +      result = SubscribeNetworkSearchEx (&priv->device_id, wimax_scan_cb);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax subscription to network scanning failed", result);
 +              goto err;
 +      }
 +
 +      result = SubscribeNetworkSearchWideScanEx (&priv->device_id, wimax_wide_scan_cb);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax subscription to wide network scanning failed", result);
 +              goto err;
 +      }
 +
 +      result = SubscribeConnectToNetwork (&priv->device_id, wimax_connect_cb);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax subscription to connected messages failed", result);
 +              goto err;
 +      }
 +
 +      result = SubscribeDisconnectToNetwork (&priv->device_id, wimax_disconnect_cb);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax subscription to disconnected messages failed", result);
 +              goto err;
 +      }
 +
 +      success = TRUE;
 +
 + err:
 +      if (!success)
 +              nm_wimax_api_close (self);
 +
 +      return success;
 +}
 +
 +static void
 +device_state_changed (NMDevice *device,
 +                      NMDeviceState new_state,
 +                      NMDeviceState old_state,
 +                      NMDeviceStateReason reason,
 +                      gpointer user_data)
 +{
 +      NMWimaxDevice *self = NM_WIMAX_DEVICE (device);
 +
 +      switch (new_state) {
 +      case NM_DEVICE_STATE_UNMANAGED:
 +      case NM_DEVICE_STATE_UNAVAILABLE:
 +      case NM_DEVICE_STATE_DISCONNECTED:
 +              remove_all_nsps (self);
 +              schedule_rf_state_update (self);
 +              break;
 +      default:
 +              break;
 +      }
 +}
 +
 +/* NMDeviceInterface interface */
 +
 +static void
 +real_set_enabled (NMDeviceInterface *device, gboolean enabled)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +
 +      if (priv->enabled == enabled)
 +              return;
 +
 +      priv->enabled = enabled;
 +      schedule_rf_state_update (NM_WIMAX_DEVICE (device));
 +}
 +
 +/* NMDevice methods */
 +
 +static void
 +real_take_down (NMDevice *device)
 +{
 +      NMWimaxDevice *self = NM_WIMAX_DEVICE (device);
 +
 +      set_current_nsp (self, NULL);
 +      remove_all_nsps (self);
 +}
 +
 +static gboolean
 +real_hw_is_up (NMDevice *device)
 +{
 +      return nm_system_device_is_up (device);
 +}
 +
 +static gboolean
 +real_hw_bring_up (NMDevice *dev, gboolean *no_firmware)
 +{
 +      return nm_system_device_set_up_down (dev, TRUE, no_firmware);
 +}
 +
 +static void
 +real_hw_take_down (NMDevice *dev)
 +{
 +      nm_system_device_set_up_down (dev, FALSE, NULL);
 +}
 +
 +static void
 +real_update_hw_address (NMDevice *device)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      struct WIMAX_API_DEVICE_INFO info = { 0, };
 +    WIMAX_API_RET result;
 +
 +    result = GetDeviceInformation (&priv->device_id, &info);
 +    if (result != WIMAX_API_RET_SUCCESS)
 +              nm_wimax_util_error (&priv->device_id, "Could not read WiMax device hardware address", result);
 +
 +      if (memcmp (&priv->hw_addr, info.macAddress, sizeof (struct ether_addr))) {
 +              memcpy (&priv->hw_addr, info.macAddress, sizeof (struct ether_addr));
 +              g_object_notify (G_OBJECT (device), NM_WIMAX_DEVICE_HW_ADDRESS);
 +      }
 +}
 +
 +static gboolean
 +real_check_connection_compatible (NMDevice *device,
 +                                  NMConnection *connection,
 +                                  GError **error)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      NMSettingConnection *s_con;
 +      NMSettingWimax *s_wimax;
 +      const char *connection_type;
 +      const GByteArray *mac;
 +
 +      s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
 +      g_assert (s_con);
 +
 +      connection_type = nm_setting_connection_get_connection_type (s_con);
 +      if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) {
 +              g_set_error (error,
 +                           NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_NOT_WIMAX,
 +                           "The connection was not a WiMAX connection.");
 +              return FALSE;
 +      }
 +
 +      s_wimax = (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
 +      if (!s_wimax) {
 +              g_set_error (error,
 +                           NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INVALID,
 +                           "The connection was not a valid WiMAX connection.");
 +              return FALSE;
 +      }
 +
 +      mac = nm_setting_wimax_get_mac_address (s_wimax);
 +      if (mac && memcmp (mac->data, &(priv->hw_addr.ether_addr_octet), ETH_ALEN)) {
 +              g_set_error (error,
 +                                       NM_WIMAX_ERROR, NM_WIMAX_ERROR_CONNECTION_INCOMPATIBLE,
 +                                       "The connection's MAC address did not match this device.");
 +              return FALSE;
 +      }
 +
 +      return TRUE;
 +}
 +
 +static NMConnection *
 +real_get_best_auto_connection (NMDevice *device,
 +                               GSList *connections,
 +                               char **specific_object)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      GSList *iter;
 +
 +      for (iter = connections; iter; iter = g_slist_next (iter)) {
 +              NMConnection *connection = NM_CONNECTION (iter->data);
 +              NMSettingConnection *s_con;
 +              NMSettingWimax *s_wimax;
 +              const char *connection_type;
 +              const GByteArray *mac;
 +
 +              s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
 +              g_assert (s_con);
 +
 +              if (!nm_setting_connection_get_autoconnect (s_con))
 +                      continue;
 +
 +              connection_type = nm_setting_connection_get_connection_type (s_con);
 +              if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME))
 +                      continue;
 +
 +              s_wimax = (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
 +              if (!s_wimax)
 +                      continue;
 +
 +              mac = nm_setting_wimax_get_mac_address (s_wimax);
 +              if (mac && memcmp (mac->data, priv->hw_addr.ether_addr_octet, ETH_ALEN))
 +                      continue;
 +
 +              for (iter = priv->nsp_list; iter; iter = iter->next) {
 +                      NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
 +
 +                      if (nm_wimax_nsp_check_compatible (nsp, connection)) {
 +                              *specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp);
 +                              return connection;
 +                      }
 +              }
 +      }
 +
 +      return NULL;
 +}
 +
 +static guint32
 +real_get_generic_capabilities (NMDevice *dev)
 +{
 +      return NM_DEVICE_CAP_NM_SUPPORTED;
 +}
 +
 +static gboolean
 +real_is_available (NMDevice *device)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      WIMAX_API_DEVICE_STATUS status;
 +      WIMAX_API_CONNECTION_PROGRESS_INFO pi;
 +      WIMAX_API_RET result;
 +
 +      if (!priv->enabled)
 +              return FALSE;
 +
 +      result = GetDeviceStatus (&priv->device_id, &status, &pi);
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "Reading WiMax device status failed", result);
 +              return FALSE;
 +      }
 +
 +      return status >= WIMAX_API_DEVICE_STATUS_Ready;
 +}
 +
 +static NMActStageReturn
 +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      NMActRequest *req;
 +      GSList *iter;
 +      const char *path;
 +
 +      req = nm_device_get_act_request (device);
 +      if (!req)
 +              goto err;
 +
 +      path = nm_act_request_get_specific_object (req);
 +      if (!path)
 +              goto err;
 +
 +      for (iter = priv->nsp_list; iter; iter = iter->next) {
 +              NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data);
 +
 +              if (!strcmp (path, nm_wimax_nsp_get_dbus_path (nsp))) {
 +                      set_current_nsp (NM_WIMAX_DEVICE (device), nsp);
 +                      return NM_ACT_STAGE_RETURN_SUCCESS;
 +              }
 +      }
 +
 + err:
 +      *reason = NM_DEVICE_STATE_REASON_NONE;
 +      return NM_ACT_STAGE_RETURN_FAILURE;
 +}
 +
 +static NMActStageReturn
 +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      NMConnection *connection;
 +      NMSettingWimax *s_wimax;
 +      WIMAX_API_RET result;
 +
 +      connection = nm_act_request_get_connection (nm_device_get_act_request (device));
 +      g_assert (connection);
 +
 +      s_wimax = NM_SETTING_WIMAX (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX));
 +      g_assert (s_wimax);
 +
 +      result = CmdConnectToNetwork (&priv->device_id,
 +                                                                (WIMAX_API_ASTRING) nm_setting_wimax_get_network_name (s_wimax),
 +                                                                0, NULL);
 +
 +      if (result != WIMAX_API_RET_SUCCESS) {
 +              nm_wimax_util_error (&priv->device_id, "WiMax connect to network failed", result);
 +              *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
 +              return NM_ACT_STAGE_RETURN_FAILURE;
 +      }
 +
 +      /* FIXME: Is 60 seconds good estimation? I have no idea */
 +      priv->activation_timeout_id = g_timeout_add_seconds (60, activation_timed_out, device);
 +
 +      return NM_ACT_STAGE_RETURN_POSTPONE;
 +}
 +
 +static void
 +real_deactivate_quickly (NMDevice *device)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (device);
 +      WIMAX_API_DEVICE_STATUS status;
 +      WIMAX_API_CONNECTION_PROGRESS_INFO pi;
 +      WIMAX_API_RET result;
 +
 +      if (priv->activation_timeout_id) {
 +              g_source_remove (priv->activation_timeout_id);
 +              priv->activation_timeout_id = 0;
 +      }
 +
 +      set_current_nsp (NM_WIMAX_DEVICE (device), NULL);
 +
 +      result = GetDeviceStatus (&priv->device_id, &status, &pi);
 +      if (result != WIMAX_API_RET_SUCCESS)
 +              nm_wimax_util_error (&priv->device_id, "Reading WiMax device status failed", result);
 +
 +      if (status == WIMAX_API_DEVICE_STATUS_Connecting ||
 +              status == WIMAX_API_DEVICE_STATUS_Data_Connected || 
 +              status == WIMAX_API_DEVICE_STATUS_Connection_Idle) {
 +
 +              result = CmdDisconnectFromNetwork (&priv->device_id);
 +              if (result != WIMAX_API_RET_SUCCESS)
 +                      nm_wimax_util_error (&priv->device_id, "WiMax disconnect from network failed", result);
 +      }
 +}
 +
 +/* GObject methods */
 +
 +static void
 +device_interface_init (NMDeviceInterface *iface_class)
 +{
 +    iface_class->set_enabled = real_set_enabled;
 +}
 +
 +static void
 +nm_wimax_device_init (NMWimaxDevice *self)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +
 +      priv->object = self;
 +      priv->device_id.structureSize = sizeof (NMWimaxDevicePrivate);
 +      priv->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
 +
 +      g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), NULL);
 +}
 +
 +static GObject*
 +constructor (GType type,
 +                       guint n_construct_params,
 +                       GObjectConstructParam *construct_params)
 +{
 +      GObject *object;
 +      NMWimaxDevicePrivate *priv;
 +
 +      object = G_OBJECT_CLASS (nm_wimax_device_parent_class)->constructor (type, n_construct_params, construct_params);
 +      if (!object)
 +              return NULL;
 +
 +      priv = GET_PRIVATE (object);
 +      if (priv->device_id.deviceIndex == 0) {
 +              g_warning ("Invalid or missing constructor arguments");
 +              g_object_unref (object);
 +              object = NULL;
 +      }
 +
 +      if (!nm_wimax_api_open (NM_WIMAX_DEVICE (object))) {
 +              g_object_unref (object);
 +              object = NULL;
 +      }
 +
 +      return object;
 +}
 +
 +static void
 +set_property (GObject *object, guint prop_id,
 +                        const GValue *value, GParamSpec *pspec)
 +{
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (object);
 +
 +      switch (prop_id) {
 +      case PROP_INDEX:
 +              priv->device_id.deviceIndex = g_value_get_uchar (value);
 +              break;
-       g_object_class_install_property
-               (object_class, PROP_IFINDEX,
-                g_param_spec_uint (NM_WIMAX_DEVICE_IFINDEX,
-                                                       "Ifindex",
-                                                       "Interface index",
-                                                       0, G_MAXUINT32, 0,
-                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
 +      default:
 +              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 +              break;
 +      }
 +}
 +
 +static void
 +get_property (GObject *object, guint prop_id,
 +                        GValue *value, GParamSpec *pspec)
 +{
 +      NMWimaxDevice *self = NM_WIMAX_DEVICE (object);
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +      struct ether_addr hw_addr;
 +
 +      switch (prop_id) {
 +      case PROP_HW_ADDRESS:
 +              nm_wimax_device_get_hw_address (self, &hw_addr);
 +              g_value_take_string (value, nm_ether_ntop (&hw_addr));
 +              break;
 +      case PROP_ACTIVE_NSP:
 +              if (priv->current_nsp)
 +                      g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp));
 +              else
 +                      g_value_set_boxed (value, "/");
 +              break;
 +      default:
 +              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 +              break;
 +      }
 +}
 +
 +static void
 +finalize (GObject *object)
 +{
 +      NMWimaxDevice *self = NM_WIMAX_DEVICE (object);
 +      NMWimaxDevicePrivate *priv = GET_PRIVATE (self);
 +
 +      if (priv->rf_update_id)
 +              g_source_remove (priv->rf_update_id);
 +
 +      set_current_nsp (self, NULL);
 +
 +      g_slist_foreach (priv->nsp_list, (GFunc) g_object_unref, NULL);
 +      g_slist_free (priv->nsp_list);
 +
 +      nm_wimax_api_close (self);
 +
 +      G_OBJECT_CLASS (nm_wimax_device_parent_class)->finalize (object);
 +}
 +
 +static void
 +nm_wimax_device_class_init (NMWimaxDeviceClass *klass)
 +{
 +      GObjectClass *object_class = G_OBJECT_CLASS (klass);
 +      NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
 +
 +      g_type_class_add_private (object_class, sizeof (NMWimaxDevicePrivate));
 +
 +      /* Virtual methods */
 +      object_class->constructor = constructor;
 +      object_class->set_property = set_property;
 +      object_class->get_property = get_property;
 +      object_class->finalize = finalize;
 +
 +      device_class->take_down = real_take_down;
 +      device_class->hw_is_up = real_hw_is_up;
 +      device_class->hw_bring_up = real_hw_bring_up;
 +      device_class->hw_take_down = real_hw_take_down;
 +      device_class->update_hw_address = real_update_hw_address;
 +      device_class->check_connection_compatible = real_check_connection_compatible;
 +      device_class->get_best_auto_connection = real_get_best_auto_connection;
 +      device_class->get_generic_capabilities = real_get_generic_capabilities;
 +      device_class->is_available = real_is_available;
 +      device_class->act_stage1_prepare = real_act_stage1_prepare;
 +      device_class->act_stage2_config = real_act_stage2_config;
 +      device_class->deactivate_quickly = real_deactivate_quickly;
 +
 +      /* Properties */
 +      g_object_class_install_property
 +              (object_class, PROP_INDEX,
 +               g_param_spec_uchar (NM_WIMAX_DEVICE_INDEX,
 +                                                       "Index",
 +                                                       "Index",
 +                                                       0, 1, 0,
 +                                                       G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
 +
 +      g_object_class_install_property
 +              (object_class, PROP_HW_ADDRESS,
 +               g_param_spec_string (NM_WIMAX_DEVICE_HW_ADDRESS,
 +                                                        "MAC Address",
 +                                                        "Hardware MAC address",
 +                                                        NULL,
 +                                                        G_PARAM_READABLE));
 +
 +      g_object_class_install_property (object_class, PROP_ACTIVE_NSP,
 +              g_param_spec_boxed (NM_WIMAX_DEVICE_ACTIVE_NSP,
 +                                  "Active NSP",
 +                                  "Currently active NSP",
 +                                  DBUS_TYPE_G_OBJECT_PATH,
 +                                  G_PARAM_READABLE));
 +
 +      /* Signals */
 +      signals[NSP_ADDED] =
 +              g_signal_new ("nsp-added",
 +                                        G_OBJECT_CLASS_TYPE (object_class),
 +                                        G_SIGNAL_RUN_FIRST,
 +                                        G_STRUCT_OFFSET (NMWimaxDeviceClass, nsp_added),
 +                                        NULL, NULL,
 +                                        g_cclosure_marshal_VOID__OBJECT,
 +                                        G_TYPE_NONE, 1,
 +                                        G_TYPE_OBJECT);
 +
 +      signals[NSP_REMOVED] =
 +              g_signal_new ("nsp-removed",
 +                                        G_OBJECT_CLASS_TYPE (object_class),
 +                                        G_SIGNAL_RUN_FIRST,
 +                                        G_STRUCT_OFFSET (NMWimaxDeviceClass, nsp_removed),
 +                                        NULL, NULL,
 +                                        g_cclosure_marshal_VOID__OBJECT,
 +                                        G_TYPE_NONE, 1,
 +                                        G_TYPE_OBJECT);
 +
 +      signals[PROPERTIES_CHANGED] = 
 +              nm_properties_changed_signal_new (object_class, G_STRUCT_OFFSET (NMWimaxDeviceClass, properties_changed));
 +
 +
 +      dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
 +                                                                       &dbus_glib_nm_wimax_device_object_info);
 +
 +      dbus_g_error_domain_register (NM_WIMAX_ERROR, NULL, NM_TYPE_WIMAX_ERROR);
 +}
index 301ebdd,0000000..f461dad
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,70 @@@
- #define NM_WIMAX_DEVICE_IFINDEX    "ifindex"
 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 +/* NetworkManager -- Network link manager
 + *
 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
 + * Copyright (C) 2009 Novell, Inc.
 + */
 +
 +#ifndef NM_WIMAX_DEVICE_H
 +#define NM_WIMAX_DEVICE_H
 +
 +#include <net/ethernet.h>
 +#include <WiMaxType.h>
 +#include "nm-device.h"
 +#include "nm-wimax-nsp.h"
 +
 +G_BEGIN_DECLS
 +
 +#define NM_TYPE_WIMAX_DEVICE                  (nm_wimax_device_get_type ())
 +#define NM_WIMAX_DEVICE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_DEVICE, NMWimaxDevice))
 +#define NM_WIMAX_DEVICE_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_WIMAX_DEVICE, NMWimaxDeviceClass))
 +#define NM_IS_WIMAX_DEVICE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_DEVICE))
 +#define NM_IS_WIMAX_DEVICE_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_WIMAX_DEVICE))
 +#define NM_WIMAX_DEVICE_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_WIMAX_DEVICE, NMWimaxDeviceClass))
 +
 +#define NM_WIMAX_DEVICE_INDEX      "index"
-                                                                                       int ifindex,
 +#define NM_WIMAX_DEVICE_HW_ADDRESS "hw-address"
 +#define NM_WIMAX_DEVICE_ACTIVE_NSP "active-nsp"
 +
 +typedef struct {
 +      NMDevice parent;
 +} NMWimaxDevice;
 +
 +typedef struct {
 +      NMDeviceClass parent;
 +
 +      /* Signals */
 +      void (*nsp_added)   (NMWimaxDevice *wimax, NMWimaxNsp *nsp);
 +      void (*nsp_removed) (NMWimaxDevice *wimax, NMWimaxNsp *nsp);
 +      void (*properties_changed) (NMWimaxDevice *wimax, GHashTable *properties);
 +} NMWimaxDeviceClass;
 +
 +GType nm_wimax_device_get_type (void);
 +
 +NMDevice   *nm_wimax_device_new            (const char *udi,
 +                                                                                      const char *iface,
 +                                                                                      const char *driver,
- guint32     nm_wimax_device_get_ifindex    (NMWimaxDevice *self);
 +                                                                                      guchar wimax_device_index);
 +
 +void        nm_wimax_device_get_hw_address (NMWimaxDevice *self,
 +                                                                                      struct ether_addr *addr);
 +
 +GSList     *nm_wimax_device_get_nsps       (NMWimaxDevice *self);
 +NMWimaxNsp *nm_wimax_device_get_active_nsp (NMWimaxDevice *self);
 +
 +G_END_DECLS
 +
 +#endif        /* NM_WIMAX_DEVICE_H */
index 1cba7c5,0000000..e223ee3
mode 100644,000000..100644
--- /dev/null
@@@ -1,139 -1,0 +1,138 @@@
-                                                               const char *driver,
-                                                               int ifindex)
 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 +/* NetworkManager -- Network link manager
 + *
 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
 + * Copyright (C) 2009 Novell, Inc.
 + */
 +
 +#include <stdio.h>
 +#include <net/if.h>
 +#include <WiMaxAPI.h>
 +
 +#include "nm-wimax-manager.h"
 +#include "nm-wimax-device.h"
 +#include "nm-wimax-util.h"
 +
 +typedef struct {
 +      struct WIMAX_API_DEVICE_ID device_id;
 +      int refs;
 +} NMWimaxManager;
 +
 +static NMWimaxManager *global_wimax_manager = NULL;
 +
 +static NMWimaxManager *
 +nm_wimax_manager_get (void)
 +{
 +      WIMAX_API_RET result;
 +
 +      if (!global_wimax_manager) {
 +              global_wimax_manager = g_new (NMWimaxManager, 1);
 +              global_wimax_manager->refs = 1;
 +
 +              g_debug ("Opening WiMAX API");
 +              global_wimax_manager->device_id.structureSize = sizeof (NMWimaxManager);
 +              global_wimax_manager->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE;
 +              result = WiMaxAPIOpen (&global_wimax_manager->device_id);
 +              if (result != WIMAX_API_RET_SUCCESS) {
 +                      nm_wimax_util_error (&global_wimax_manager->device_id, "Could not initialize WiMax", result);
 +                      g_free (global_wimax_manager);
 +                      global_wimax_manager = NULL;
 +              }
 +      } else
 +              global_wimax_manager->refs++;
 +
 +      return global_wimax_manager;
 +}
 +
 +static void
 +nm_wimax_manager_unref (NMWimaxManager *manager)
 +{
 +      if (--manager->refs == 0) {
 +              g_debug ("Closing WiMAX API");
 +              WiMaxAPIClose (&manager->device_id);
 +              g_free (manager);
 +              global_wimax_manager = NULL;
 +      }
 +}
 +
 +static gboolean
 +wimax_device_matches (struct WIMAX_API_HW_DEVICE_ID *hw_id,
 +                                        const char *ifname,
 +                                        int ifindex)
 +{
 +      const char *device_name;
 +      char *s;
 +      char hw_ifname[16];
 +
 +      if (!hw_id)
 +              return FALSE;
 +
 +      device_name = (const char *) hw_id->deviceName;
 +      if (!device_name)
 +              return FALSE;
 +
 +      s = g_strrstr (device_name, "if:");
 +      if (s == NULL || sscanf (s, "if:%15[^ \f\n\r\t\v]", hw_ifname) != 1)
 +              return FALSE;
 +
 +      if (g_strcmp0 (ifname, hw_ifname))
 +              return FALSE;
 +
 +      if (if_nametoindex (hw_ifname) != ifindex)
 +              return FALSE;
 +
 +      return TRUE;
 +}
 +
 +NMDevice *
 +nm_wimax_manager_create_device (const char *path,
 +                                                              const char *ifname,
-                               device = nm_wimax_device_new (path, ifname, driver, ifindex, device_id_list[0].deviceIndex);
++                                                              const char *driver)
 +{
 +      NMWimaxManager *manager;
 +      struct WIMAX_API_HW_DEVICE_ID device_id_list[5];
 +      NMDevice *device = NULL;
 +    gsize device_id_list_size = 5;
 +      WIMAX_API_RET result;
 +
 +      g_return_val_if_fail (path != NULL, NULL);
 +      g_return_val_if_fail (ifname != NULL, NULL);
 +      g_return_val_if_fail (driver != NULL, NULL);
 +
 +      manager = nm_wimax_manager_get ();
 +      if (!manager)
 +              return NULL;
 +
 +      result = GetListDevice (&manager->device_id, device_id_list, &device_id_list_size);
 +      if (result == WIMAX_API_RET_SUCCESS) {
 +              int i;
 +
 +              for (i = 0; i < device_id_list_size; i++) {
 +                      if (wimax_device_matches (&device_id_list[i], ifname, ifindex)) {
++                              device = nm_wimax_device_new (path, ifname, driver, device_id_list[0].deviceIndex);
 +                              break;
 +                      }
 +              }
 +      } else
 +              nm_wimax_util_error (&manager->device_id, "Could not get WiMax device list", result);
 +
 +      if (device)
 +              g_object_weak_ref (G_OBJECT (device), (GWeakNotify) nm_wimax_manager_unref, manager);
 +      else
 +              nm_wimax_manager_unref (manager);
 +
 +      return device;
 +}
index e0427dd,0000000..c3b2881
mode 100644,000000..100644
--- /dev/null
@@@ -1,31 -1,0 +1,30 @@@
-                                                                                 const char *driver,
-                                                                                 int ifindex);
 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 +/* NetworkManager -- Network link manager
 + *
 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
 + * Copyright (C) 2009 Novell, Inc.
 + */
 +
 +#ifndef NM_WIMAX_MANAGER_H
 +#define NM_WIMAX_MANAGER_H
 +
 +#include "nm-device.h"
 +
 +NMDevice *nm_wimax_manager_create_device (const char *path,
 +                                                                                const char *ifname,
++                                                                                const char *driver);
 +
 +#endif /* NM_WIMAX_MANAGER_H */