From 75c734f1a914efea424f8c1ea1f3156021ae9572 Mon Sep 17 00:00:00 2001 From: Tambet Ingo Date: Mon, 14 Dec 2009 13:51:50 +0200 Subject: [PATCH] wimax: Implement WiMAX support --- configure.ac | 3 + include/NetworkManager.h | 4 + introspection/Makefile.am | 4 +- introspection/all.xml | 2 + introspection/nm-wimax-device.xml | 63 ++ introspection/nm-wimax-nsp.xml | 44 ++ libnm-glib/Makefile.am | 14 +- libnm-glib/libnm-glib.ver | 11 + libnm-glib/nm-device.c | 4 + libnm-glib/nm-wimax-device.c | 567 ++++++++++++++++ libnm-glib/nm-wimax-device.h | 67 ++ libnm-glib/nm-wimax-nsp.c | 301 ++++++++ libnm-glib/nm-wimax-nsp.h | 77 +++ libnm-util/Makefile.am | 2 + libnm-util/libnm-util.ver | 6 + libnm-util/nm-connection.c | 8 +- libnm-util/nm-setting-wimax.c | 229 +++++++ libnm-util/nm-setting-wimax.h | 70 ++ src/Makefile.am | 4 + src/nm-manager.c | 8 +- src/nm-udev-manager.c | 9 + src/wimax/Makefile.am | 39 ++ src/wimax/nm-wimax-device.c | 1055 +++++++++++++++++++++++++++++ src/wimax/nm-wimax-device.h | 76 +++ src/wimax/nm-wimax-manager.c | 139 ++++ src/wimax/nm-wimax-manager.h | 31 + src/wimax/nm-wimax-nsp.c | 249 +++++++ src/wimax/nm-wimax-nsp.h | 63 ++ src/wimax/nm-wimax-types.h | 31 + src/wimax/nm-wimax-util.c | 117 ++++ src/wimax/nm-wimax-util.h | 36 + test/nm-tool.c | 60 ++ 32 files changed, 3387 insertions(+), 6 deletions(-) create mode 100644 introspection/nm-wimax-device.xml create mode 100644 introspection/nm-wimax-nsp.xml create mode 100644 libnm-glib/nm-wimax-device.c create mode 100644 libnm-glib/nm-wimax-device.h create mode 100644 libnm-glib/nm-wimax-nsp.c create mode 100644 libnm-glib/nm-wimax-nsp.h create mode 100644 libnm-util/nm-setting-wimax.c create mode 100644 libnm-util/nm-setting-wimax.h create mode 100644 src/wimax/Makefile.am create mode 100644 src/wimax/nm-wimax-device.c create mode 100644 src/wimax/nm-wimax-device.h create mode 100644 src/wimax/nm-wimax-manager.c create mode 100644 src/wimax/nm-wimax-manager.h create mode 100644 src/wimax/nm-wimax-nsp.c create mode 100644 src/wimax/nm-wimax-nsp.h create mode 100644 src/wimax/nm-wimax-types.h create mode 100644 src/wimax/nm-wimax-util.c create mode 100644 src/wimax/nm-wimax-util.h diff --git a/configure.ac b/configure.ac index 2d59fa1b9c..cc79b67c5a 100644 --- a/configure.ac +++ b/configure.ac @@ -229,6 +229,8 @@ PKG_CHECK_MODULES(POLKIT, polkit-gobject-1) AC_SUBST(POLKIT_CFLAGS) +PKG_CHECK_MODULES(WIMAX, libiWmxSdk-0) + AC_ARG_WITH(crypto, AS_HELP_STRING([--with-crypto=nss | gnutls], [Cryptography library to use for certificate and key operations]),ac_crypto=$withval, ac_crypto=nss) with_nss=no @@ -438,6 +440,7 @@ src/ppp-manager/Makefile src/dnsmasq-manager/Makefile src/modem-manager/Makefile src/bluez-manager/Makefile +src/wimax/Makefile src/system-settings/Makefile src/backends/Makefile libnm-util/libnm-util.pc diff --git a/include/NetworkManager.h b/include/NetworkManager.h index c8d5074a1e..f269971123 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -38,6 +38,9 @@ #define NM_DBUS_INTERFACE_SERIAL_DEVICE NM_DBUS_INTERFACE_DEVICE ".Serial" #define NM_DBUS_INTERFACE_GSM_DEVICE NM_DBUS_INTERFACE_DEVICE ".Gsm" #define NM_DBUS_INTERFACE_CDMA_DEVICE NM_DBUS_INTERFACE_DEVICE ".Cdma" +#define NM_DBUS_INTERFACE_WIMAX_DEVICE NM_DBUS_INTERFACE_DEVICE ".WiMax" +#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" +#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp" #define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active" #define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config" #define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config" @@ -79,6 +82,7 @@ typedef enum NMDeviceType NM_DEVICE_TYPE_GSM, NM_DEVICE_TYPE_CDMA, NM_DEVICE_TYPE_BT, /* Bluetooth */ + NM_DEVICE_TYPE_WIMAX, NM_DEVICE_TYPE_OLPC_MESH } NMDeviceType; diff --git a/introspection/Makefile.am b/introspection/Makefile.am index 0dc286a9cd..091384f22d 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -23,5 +23,7 @@ EXTRA_DIST = \ nm-vpn-connection.xml \ nm-ppp-manager.xml \ nm-active-connection.xml \ - nm-dhcp4-config.xml + nm-dhcp4-config.xml \ + nm-wimax-device.xml \ + nm-wimax-nsp.xml diff --git a/introspection/all.xml b/introspection/all.xml index 67f1e54216..b84853c2c8 100644 --- a/introspection/all.xml +++ b/introspection/all.xml @@ -43,6 +43,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + diff --git a/introspection/nm-wimax-device.xml b/introspection/nm-wimax-device.xml new file mode 100644 index 0000000000..69c1102b48 --- /dev/null +++ b/introspection/nm-wimax-device.xml @@ -0,0 +1,63 @@ + + + + + + + + + List of NSP object paths + + + + Get the list of NSPs visible to this device. + + + + + + Hardware address of the device. + + + + + + Object path of the NSP currently used by the WiMax device. + + + + + + + A dictionary mapping property names to variant boxed values. + + + + Emitted when the WiMax device's properties changed. + + + + + + + The object path of the newly found NSP. + + + + Emitted when a new NSP is found by the device. + + + + + + + The object path of the NSP that has disappeared. + + + + Emitted when an NSP disappears from view of the device. + + + + + diff --git a/introspection/nm-wimax-nsp.xml b/introspection/nm-wimax-nsp.xml new file mode 100644 index 0000000000..55ac4abcf2 --- /dev/null +++ b/introspection/nm-wimax-nsp.xml @@ -0,0 +1,44 @@ + + + + + + + The name of the NSP. + + + The current signal quality of the NSP, in percent. + + + The network type of the NSP. + + + + + + A dictionary mapping property names to variant boxed values. + + + + + + + Network type of the NSP. + + + Unknown network. + + + Home network. + + + Partner network. + + + Roaming partner network. + + + + + + diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index f91623e1b9..9ad6c99cf1 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -20,7 +20,8 @@ BUILT_SOURCES = \ nm-active-connection-bindings.h \ nm-ip4-config-bindings.h \ nm-dhcp4-config-bindings.h \ - nm-ip6-config-bindings.h + nm-ip6-config-bindings.h \ + nm-wimax-device-bindings.h lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la @@ -59,7 +60,9 @@ 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 \ @@ -94,7 +97,9 @@ libnm_glib_la_SOURCES = \ nm-remote-settings-system.c \ nm-settings-connection-interface.c \ nm-exported-connection.c \ - nm-settings-service.c + nm-settings-service.c \ + nm-wimax-device.c \ + nm-wimax-nsp.c libnm_glib_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ @@ -172,6 +177,9 @@ nm-dhcp4-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml dbus-binding-tool --prefix=nm_ip6_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 diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 25556391dd..108a83726f 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -149,6 +149,17 @@ global: nm_vpn_connection_get_type; nm_vpn_connection_get_vpn_state; nm_vpn_connection_new; + nm_wimax_device_get_hw_address; + nm_wimax_device_get_active_nsp; + nm_wimax_device_get_nsp_by_path; + nm_wimax_device_get_nsps; + nm_wimax_device_get_type; + nm_wimax_device_new; + nm_wimax_nsp_get_name; + nm_wimax_nsp_get_network_type; + nm_wimax_nsp_get_signal_quality; + nm_wimax_nsp_get_type; + nm_wimax_nsp_new; local: *; }; diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 17caa99d5d..aa6afeb0f6 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -32,6 +32,7 @@ #include "nm-gsm-device.h" #include "nm-cdma-device.h" #include "nm-device-bt.h" +#include "nm-wimax-device.h" #include "nm-device.h" #include "nm-device-private.h" #include "nm-object-private.h" @@ -621,6 +622,9 @@ nm_device_new (DBusGConnection *connection, const char *path) case NM_DEVICE_TYPE_BT: dtype = NM_TYPE_DEVICE_BT; break; + case NM_DEVICE_TYPE_WIMAX: + dtype = NM_TYPE_WIMAX_DEVICE; + break; default: g_warning ("Unknown device type %d", g_value_get_uint (&value)); break; diff --git a/libnm-glib/nm-wimax-device.c b/libnm-glib/nm-wimax-device.c new file mode 100644 index 0000000000..09a9bad64d --- /dev/null +++ b/libnm-glib/nm-wimax-device.c @@ -0,0 +1,567 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; 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 + +#include "nm-wimax-device.h" +#include "nm-object-private.h" +#include "nm-object-cache.h" +#include "nm-dbus-glib-types.h" +#include "nm-types-private.h" + +#include "nm-wimax-device-bindings.h" + +G_DEFINE_TYPE (NMWimaxDevice, nm_wimax_device, NM_TYPE_DEVICE) + +#define NM_WIMAX_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_DEVICE, NMWimaxDevicePrivate)) + +static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field); + +void _nm_wimax_device_set_wireless_enabled (NMWimaxDevice *wimax, gboolean enabled); + +typedef struct { + gboolean disposed; + DBusGProxy *proxy; + + char *hw_address; + NMWimaxNsp *active_nsp; + gboolean null_active_nsp; + GPtrArray *nsps; +} NMWimaxDevicePrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_ACTIVE_NSP, + + LAST_PROP +}; + +#define DBUS_PROP_HW_ADDRESS "HwAddress" +#define DBUS_PROP_ACTIVE_NSP "ActiveNsp" + +enum { + NSP_ADDED, + NSP_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/** + * nm_wimax_device_new: + * @connection: the #DBusGConnection + * @path: the DBus object path of the wimax + * + * Creates a new #NMWimaxDevice. + * + * Returns: a new wimax + **/ +GObject * +nm_wimax_device_new (DBusGConnection *connection, const char *path) +{ + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + + return g_object_new (NM_TYPE_WIMAX_DEVICE, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); +} + +/** + * nm_wimax_device_get_hw_address: + * @device: a #NMWimaxDevice + * + * Gets the hardware (MAC) address of the #NMWimaxDevice + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_wimax_device_get_hw_address (NMWimaxDevice *wimax) +{ + NMWimaxDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + + priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + if (!priv->hw_address) { + priv->hw_address = _nm_object_get_string_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_WIMAX_DEVICE, + DBUS_PROP_HW_ADDRESS); + } + + return priv->hw_address; +} + +/** + * nm_wimax_device_get_active_nsp: + * @wimax: a #NMWimaxDevice + * + * Gets the active #NMWimaxNsp. + * + * Returns: the access point or %NULL if none is active + **/ +NMWimaxNsp * +nm_wimax_device_get_active_nsp (NMWimaxDevice *wimax) +{ + NMWimaxDevicePrivate *priv; + NMDeviceState state; + char *path; + GValue value = { 0, }; + + g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + + state = nm_device_get_state (NM_DEVICE (wimax)); + switch (state) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_ACTIVATED: + break; + default: + return NULL; + break; + } + + priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + if (priv->active_nsp) + return priv->active_nsp; + if (priv->null_active_nsp) + return NULL; + + path = _nm_object_get_object_path_property (NM_OBJECT (wimax), + NM_DBUS_INTERFACE_WIMAX_DEVICE, + DBUS_PROP_ACTIVE_NSP); + if (path) { + g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH); + g_value_take_boxed (&value, path); + demarshal_active_nsp (NM_OBJECT (wimax), NULL, &value, &priv->active_nsp); + g_value_unset (&value); + } + + return priv->active_nsp; +} + +/** + * nm_wimax_device_get_nsps: + * @wimax: a #NMWimaxDevice + * + * Gets all the scanned NSPs of the #NMWimaxDevice. + * + * Returns: a #GPtrArray containing all the scanned #NMWimaxNsps. + * The returned array is owned by the client and should not be modified. + **/ +const GPtrArray * +nm_wimax_device_get_nsps (NMWimaxDevice *wimax) +{ + NMWimaxDevicePrivate *priv; + DBusGConnection *connection; + GValue value = { 0, }; + GError *error = NULL; + GPtrArray *temp; + + g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + + priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + if (priv->nsps) + return handle_ptr_array_return (priv->nsps); + + if (!org_freedesktop_NetworkManager_Device_WiMax_get_nsp_list (priv->proxy, &temp, &error)) { + g_warning ("%s: error getting NSPs: %s", __func__, error->message); + g_error_free (error); + return NULL; + } + + g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH); + g_value_take_boxed (&value, temp); + connection = nm_object_get_connection (NM_OBJECT (wimax)); + _nm_object_array_demarshal (&value, &priv->nsps, connection, nm_wimax_nsp_new); + g_value_unset (&value); + + return handle_ptr_array_return (priv->nsps); +} + +/** + * nm_wimax_device_get_nsp_by_path: + * @wimax: a #NMWimaxDevice + * @path: the object path of the NSP + * + * Gets a #NMWimaxNsp by path. + * + * Returns: the access point or %NULL if none is found. + **/ +NMWimaxNsp * +nm_wimax_device_get_nsp_by_path (NMWimaxDevice *wimax, + const char *path) +{ + const GPtrArray *nsps; + int i; + NMWimaxNsp *nsp = NULL; + + g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + g_return_val_if_fail (path != NULL, NULL); + + nsps = nm_wimax_device_get_nsps (wimax); + if (!nsps) + return NULL; + + for (i = 0; i < nsps->len; i++) { + NMWimaxNsp *candidate = g_ptr_array_index (nsps, i); + if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) { + nsp = candidate; + break; + } + } + + return nsp; +} + +static void +nsp_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data) +{ + NMWimaxDevice *self = NM_WIMAX_DEVICE (user_data); + NMWimaxDevicePrivate *priv; + GObject *nsp; + + g_return_if_fail (self != NULL); + + nsp = G_OBJECT (nm_wimax_device_get_nsp_by_path (self, path)); + if (!nsp) { + DBusGConnection *connection = nm_object_get_connection (NM_OBJECT (self)); + + priv = NM_WIMAX_DEVICE_GET_PRIVATE (self); + nsp = G_OBJECT (_nm_object_cache_get (path)); + if (nsp) { + g_ptr_array_add (priv->nsps, g_object_ref (nsp)); + } else { + nsp = G_OBJECT (nm_wimax_nsp_new (connection, path)); + if (nsp) + g_ptr_array_add (priv->nsps, nsp); + } + } + + if (nsp) + g_signal_emit (self, signals[NSP_ADDED], 0, nsp); +} + +static void +nsp_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data) +{ + NMWimaxDevice *self = NM_WIMAX_DEVICE (user_data); + NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (self); + NMWimaxNsp *nsp; + + g_return_if_fail (self != NULL); + + nsp = nm_wimax_device_get_nsp_by_path (self, path); + if (nsp) { + if (nsp == priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + priv->null_active_nsp = FALSE; + + _nm_object_queue_notify (NM_OBJECT (self), NM_WIMAX_DEVICE_ACTIVE_NSP); + } + + g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); + g_ptr_array_remove (priv->nsps, nsp); + g_object_unref (G_OBJECT (nsp)); + } +} + +static void +clean_up_nsps (NMWimaxDevice *self, gboolean notify) +{ + NMWimaxDevicePrivate *priv; + + g_return_if_fail (NM_IS_WIMAX_DEVICE (self)); + + priv = NM_WIMAX_DEVICE_GET_PRIVATE (self); + + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + } + + if (priv->nsps) { + while (priv->nsps->len) { + NMWimaxNsp *nsp = NM_WIMAX_NSP (g_ptr_array_index (priv->nsps, 0)); + + if (notify) + g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); + g_ptr_array_remove (priv->nsps, nsp); + g_object_unref (nsp); + } + g_ptr_array_free (priv->nsps, TRUE); + priv->nsps = NULL; + } +} + +/**************************************************************/ + +static void +nm_wimax_device_init (NMWimaxDevice *wimax) +{ +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMWimaxDevice *self = NM_WIMAX_DEVICE (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_wimax_device_get_hw_address (self)); + break; + case PROP_ACTIVE_NSP: + g_value_set_object (value, nm_wimax_device_get_active_nsp (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NMWimaxDevice *self = NM_WIMAX_DEVICE (device); + NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (self); + + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + priv->null_active_nsp = FALSE; + } + _nm_object_queue_notify (NM_OBJECT (device), NM_WIMAX_DEVICE_ACTIVE_NSP); + break; + default: + break; + } +} + +static gboolean +demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) +{ + NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + const char *path; + NMWimaxNsp *nsp = NULL; + DBusGConnection *connection; + + if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) + return FALSE; + + priv->null_active_nsp = FALSE; + + path = g_value_get_boxed (value); + if (path) { + if (!strcmp (path, "/")) + priv->null_active_nsp = TRUE; + else { + nsp = NM_WIMAX_NSP (_nm_object_cache_get (path)); + if (nsp) + nsp = g_object_ref (nsp); + else { + connection = nm_object_get_connection (object); + nsp = NM_WIMAX_NSP (nm_wimax_nsp_new (connection, path)); + } + } + } + + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + } + + if (nsp) + priv->active_nsp = nsp; + + _nm_object_queue_notify (object, NM_WIMAX_DEVICE_ACTIVE_NSP); + return TRUE; +} + +static void +register_for_property_changed (NMWimaxDevice *wimax) +{ + NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + const NMPropertiesChangedInfo property_changed_info[] = { + { NM_WIMAX_DEVICE_HW_ADDRESS, _nm_object_demarshal_generic, &priv->hw_address }, + { NM_WIMAX_DEVICE_ACTIVE_NSP, demarshal_active_nsp, &priv->active_nsp }, + { NULL }, + }; + + _nm_object_handle_properties_changed (NM_OBJECT (wimax), + priv->proxy, + property_changed_info); +} + +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 = NM_WIMAX_DEVICE_GET_PRIVATE (object); + + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), + NM_DBUS_SERVICE, + nm_object_get_path (NM_OBJECT (object)), + NM_DBUS_INTERFACE_WIMAX_DEVICE); + + dbus_g_proxy_add_signal (priv->proxy, "NspAdded", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "NspAdded", + G_CALLBACK (nsp_added_proxy), + object, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "NspRemoved", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "NspRemoved", + G_CALLBACK (nsp_removed_proxy), + object, NULL); + + register_for_property_changed (NM_WIMAX_DEVICE (object)); + + g_signal_connect (object, + "notify::" NM_DEVICE_STATE, + G_CALLBACK (state_changed_cb), + NULL); + + return object; +} + +static void +dispose (GObject *object) +{ + NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_wimax_device_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + clean_up_nsps (NM_WIMAX_DEVICE (object), FALSE); + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_wimax_device_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + + if (priv->hw_address) + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_wimax_device_parent_class)->finalize (object); +} + +static void +nm_wimax_device_class_init (NMWimaxDeviceClass *wimax_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wimax_class); + + g_type_class_add_private (wimax_class, sizeof (NMWimaxDevicePrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* properties */ + + /** + * NMWimaxDevice:active-nsp: + * + * The active #NMWimaxNsp of the device. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_NSP, + g_param_spec_object (NM_WIMAX_DEVICE_ACTIVE_NSP, + "Active NSP", + "Active NSP", + NM_TYPE_WIMAX_NSP, + G_PARAM_READABLE)); + + /* signals */ + + /** + * NMWimaxDevice::nsp-added: + * @self: the wimax device that received the signal + * @nsp: the new NSP + * + * Notifies that a #NMWimaxNsp is added to the wimax device. + **/ + 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); + + /** + * NMWimaxDevice::nsp-removed: + * @self: the wimax device that received the signal + * @nsp: the removed NSP + * + * Notifies that a #NMWimaxNsp is removed from the wimax device. + **/ + 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); +} diff --git a/libnm-glib/nm-wimax-device.h b/libnm-glib/nm-wimax-device.h new file mode 100644 index 0000000000..1e59fd0d52 --- /dev/null +++ b/libnm-glib/nm-wimax-device.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; 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 "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 ((obj), 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_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 *self, NMWimaxNsp *nsp); + void (*nsp_removed) (NMWimaxDevice *self, NMWimaxNsp *nsp); +} NMWimaxDeviceClass; + +GType nm_wimax_device_get_type (void); + +GObject *nm_wimax_device_new (DBusGConnection *connection, + const char *path); + +const char *nm_wimax_device_get_hw_address (NMWimaxDevice *wimax); +NMWimaxNsp *nm_wimax_device_get_active_nsp (NMWimaxDevice *wimax); +NMWimaxNsp *nm_wimax_device_get_nsp_by_path (NMWimaxDevice *wimax, + const char *path); + +const GPtrArray *nm_wimax_device_get_nsps (NMWimaxDevice *wimax); + +G_END_DECLS + +#endif /* NM_WIMAX_DEVICE_H */ diff --git a/libnm-glib/nm-wimax-nsp.c b/libnm-glib/nm-wimax-nsp.c new file mode 100644 index 0000000000..0c2cbca8f6 --- /dev/null +++ b/libnm-glib/nm-wimax-nsp.c @@ -0,0 +1,301 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; 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 + +#include "nm-wimax-nsp.h" +#include "NetworkManager.h" +#include "nm-types-private.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, NM_TYPE_OBJECT) + +#define NM_WIMAX_NSP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) + +typedef struct { + gboolean disposed; + DBusGProxy *proxy; + + char *name; + guint8 signal_quality; + NMWimaxNspNetworkType network_type; +} NMWimaxNspPrivate; + +enum { + PROP_0, + PROP_NAME, + PROP_SIGNAL_QUALITY, + PROP_NETWORK_TYPE, + + LAST_PROP +}; + +#define DBUS_PROP_NAME "Name" +#define DBUS_PROP_SIGNAL_QUALITY "SignalQuality" +#define DBUS_PROP_NETWORK_TYPE "NetworkType" + +/** + * nm_wimax_nsp_new: + * @connection: the #DBusGConnection + * @path: the DBusobject path of the wimax NSP + * + * Creates a new #NMWimaxNsp. + * + * Returns: a new wimax nsp + **/ +GObject * +nm_wimax_nsp_new (DBusGConnection *connection, const char *path) +{ + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + + return (GObject *) g_object_new (NM_TYPE_WIMAX_NSP, + NM_OBJECT_DBUS_CONNECTION, connection, + NM_OBJECT_DBUS_PATH, path, + NULL); +} + +/** + * nm_wimax_nsp_get_name: + * @nsp: a #NMWimaxNsp + * + * Gets the name of the wimax NSP + * + * Returns: the name + **/ +const char * +nm_wimax_nsp_get_name (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NULL); + + priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + if (!priv->name) + priv->name = _nm_object_get_string_property (NM_OBJECT (nsp), + NM_DBUS_INTERFACE_WIMAX_NSP, + DBUS_PROP_NAME); + + return priv->name; +} + +/** + * nm_wimax_nsp_get_signal_quality: + * @nsp: a #NMWimaxNsp + * + * Gets the WPA signal quality of the wimax NSP. + * + * Returns: the signal quality + **/ +guint8 +nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), 0); + + priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + if (!priv->signal_quality) + priv->signal_quality = _nm_object_get_byte_property (NM_OBJECT (nsp), + NM_DBUS_INTERFACE_WIMAX_NSP, + DBUS_PROP_SIGNAL_QUALITY); + + return priv->signal_quality; +} + +/** + * nm_wimax_nsp_get_network_type: + * @nsp: a #NMWimaxNsp + * + * Gets the network type of the wimax NSP. + * + * Returns: the network type + **/ +NMWimaxNspNetworkType +nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN); + + priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + if (!priv->network_type) + priv->network_type = _nm_object_get_uint_property (NM_OBJECT (nsp), + NM_DBUS_INTERFACE_WIMAX_NSP, + DBUS_PROP_NETWORK_TYPE); + + return priv->network_type; +} + +/************************************************************/ + +static void +nm_wimax_nsp_init (NMWimaxNsp *nsp) +{ +} + +static void +dispose (GObject *object) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + g_free (priv->name); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMWimaxNsp *nsp = NM_WIMAX_NSP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_wimax_nsp_get_name (nsp)); + break; + case PROP_SIGNAL_QUALITY: + g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (nsp)); + break; + case PROP_NETWORK_TYPE: + g_value_set_uint (value, nm_wimax_nsp_get_network_type (nsp)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +register_for_property_changed (NMWimaxNsp *nsp) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (nsp); + const NMPropertiesChangedInfo property_changed_info[] = { + { NM_WIMAX_NSP_SIGNAL_QUALITY, _nm_object_demarshal_generic, &priv->signal_quality }, + { NULL }, + }; + + _nm_object_handle_properties_changed (NM_OBJECT (nsp), + priv->proxy, + property_changed_info); +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + NMObject *object; + NMWimaxNspPrivate *priv; + + object = (NMObject *) G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object), + NM_DBUS_SERVICE, + nm_object_get_path (object), + NM_DBUS_INTERFACE_WIMAX_NSP); + + register_for_property_changed (NM_WIMAX_NSP (object)); + + return G_OBJECT (object); +} + + +static void +nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (nsp_class); + + g_type_class_add_private (nsp_class, sizeof (NMWimaxNspPrivate)); + + /* virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* properties */ + + /** + * NMWimaxNsp:name: + * + * The name of the wimax NSP. + **/ + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_WIMAX_NSP_NAME, + "Name", + "Name", + NULL, + G_PARAM_READABLE)); + + /** + * NMWimaxNsp:signal-quality: + * + * The signal quality of the wimax NSP. + **/ + g_object_class_install_property + (object_class, PROP_SIGNAL_QUALITY, + g_param_spec_uchar (NM_WIMAX_NSP_SIGNAL_QUALITY, + "Signal Quality", + "Signal Quality", + 0, G_MAXUINT8, 0, + G_PARAM_READABLE)); + + /** + * NMWimaxNsp:network-type: + * + * The network type of the wimax NSP. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_uint (NM_WIMAX_NSP_NETWORK_TYPE, + "Network Type", + "Network Type", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE)); +} diff --git a/libnm-glib/nm-wimax-nsp.h b/libnm-glib/nm-wimax-nsp.h new file mode 100644 index 0000000000..654b49c75e --- /dev/null +++ b/libnm-glib/nm-wimax-nsp.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; 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_NSP_H +#define NM_WIMAX_NSP_H + +#include +#include +#include +#include "nm-object.h" + +G_BEGIN_DECLS + +#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) +#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) +#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) +#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) + +#define NM_WIMAX_NSP_NAME "name" +#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" +#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" + +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN = 0, + NM_WIMAX_NSP_NETWORK_TYPE_HOME = 1, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER = 2, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER = 3 +} NMWimaxNspNetworkType; + +typedef struct { + NMObject parent; +} NMWimaxNsp; + +typedef struct { + NMObjectClass parent; + + /* Padding for future expansion */ + void (*_reserved1) (void); + void (*_reserved2) (void); + void (*_reserved3) (void); + void (*_reserved4) (void); + void (*_reserved5) (void); + void (*_reserved6) (void); +} NMWimaxNspClass; + +GType nm_wimax_nsp_get_type (void); + +GObject *nm_wimax_nsp_new (DBusGConnection *connection, const char *path); + +const char * nm_wimax_nsp_get_name (NMWimaxNsp *nsp); +guint8 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp); +NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp); + +G_END_DECLS + +#endif /* NM_WIMAX_NSP_H */ diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am index 2aa4c4ed6e..70c09402a0 100644 --- a/libnm-util/Makefile.am +++ b/libnm-util/Makefile.am @@ -24,6 +24,7 @@ libnm_util_include_HEADERS = \ nm-setting-gsm.h \ nm-setting-cdma.h \ nm-setting-olpc-mesh.h \ + nm-setting-wimax.h \ nm-setting-wired.h \ nm-setting-wireless.h \ nm-setting-wireless-security.h \ @@ -48,6 +49,7 @@ libnm_util_la_SOURCES= \ nm-setting-gsm.c \ nm-setting-cdma.c \ nm-setting-olpc-mesh.c \ + nm-setting-wimax.c \ nm-setting-wired.c \ nm-setting-wireless.c \ nm-setting-wireless-security.c \ diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index 17ce1749ff..ba0086264f 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver @@ -273,6 +273,12 @@ global: nm_setting_vpn_foreach_secret; nm_setting_vpn_get_secret; nm_setting_vpn_remove_secret; + nm_setting_wimax_error_get_type; + nm_setting_wimax_error_quark; + nm_setting_wimax_get_type; + nm_setting_wimax_new; + nm_setting_wimax_get_network_name; + nm_setting_wimax_get_mac_address; nm_setting_wired_error_get_type; nm_setting_wired_error_quark; nm_setting_wired_get_type; diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index f4cb787ee9..d70b94f996 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -37,6 +37,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" +#include "nm-setting-wimax.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" @@ -141,7 +142,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; static GHashTable *registered_settings = NULL; -#define DEFAULT_MAP_SIZE 15 +#define DEFAULT_MAP_SIZE 16 static struct SettingInfo { const char *name; @@ -237,6 +238,11 @@ register_default_settings (void) NM_SETTING_BLUETOOTH_ERROR, 1); + register_one_setting (NM_SETTING_WIMAX_SETTING_NAME, + NM_TYPE_SETTING_WIMAX, + NM_SETTING_WIMAX_ERROR, + 1); + register_one_setting (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_ERROR, diff --git a/libnm-util/nm-setting-wimax.c b/libnm-util/nm-setting-wimax.c new file mode 100644 index 0000000000..349a3ae8ea --- /dev/null +++ b/libnm-util/nm-setting-wimax.c @@ -0,0 +1,229 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2009 Novell, Inc. + */ + +#include +#include +#include "nm-setting-wimax.h" +#include "nm-param-spec-specialized.h" + +GQuark +nm_setting_wimax_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-setting-wimax-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_setting_wimax_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Unknown error. */ + ENUM_ENTRY (NM_SETTING_WIMAX_ERROR_UNKNOWN, "UnknownError"), + /* The specified property was invalid. */ + ENUM_ENTRY (NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, "InvalidProperty"), + /* The specified property was missing and is required. */ + ENUM_ENTRY (NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY, "MissingProperty"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMSettingWimaxError", values); + } + return etype; +} + + +G_DEFINE_TYPE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING) + +#define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate)) + +typedef struct { + char *network_name; + GByteArray *mac_address; +} NMSettingWimaxPrivate; + +enum { + PROP_0, + PROP_NETWORK_NAME, + PROP_MAC_ADDRESS, + + LAST_PROP +}; + +NMSetting * +nm_setting_wimax_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIMAX, NULL); +} + +const char * +nm_setting_wimax_get_network_name (NMSettingWimax *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), NULL); + + return NM_SETTING_WIMAX_GET_PRIVATE (setting)->network_name; +} + +const GByteArray * +nm_setting_wimax_get_mac_address (NMSettingWimax *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), NULL); + + return NM_SETTING_WIMAX_GET_PRIVATE (setting)->mac_address; +} + +static gboolean +verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (setting); + + if (!priv->network_name) { + g_set_error (error, + NM_SETTING_WIMAX_ERROR, + NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY, + NM_SETTING_WIMAX_NETWORK_NAME); + + return FALSE; + } + + if (priv->mac_address && priv->mac_address->len != ETH_ALEN) { + g_set_error (error, + NM_SETTING_WIMAX_ERROR, + NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, + NM_SETTING_WIMAX_MAC_ADDRESS); + return FALSE; + } + + return TRUE; +} + +static void +nm_setting_wimax_init (NMSettingWimax *setting) +{ + g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIMAX_SETTING_NAME, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (object); + + g_free (priv->network_name); + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + + G_OBJECT_CLASS (nm_setting_wimax_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NETWORK_NAME: + g_free (priv->network_name); + priv->network_name = g_value_dup_string (value); + break; + case PROP_MAC_ADDRESS: + if (priv->mac_address) + g_byte_array_free (priv->mac_address, TRUE); + priv->mac_address = g_value_dup_boxed (value); + break; + 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) +{ + NMSettingWimax *setting = NM_SETTING_WIMAX (object); + + switch (prop_id) { + case PROP_NETWORK_NAME: + g_value_set_string (value, nm_setting_wimax_get_network_name (setting)); + break; + case PROP_MAC_ADDRESS: + g_value_set_boxed (value, nm_setting_wimax_get_mac_address (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingWimaxPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + /** + * NMSettingWimax:network-name: + * + * Network name of the WiMAX network. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_NAME, + g_param_spec_string (NM_SETTING_WIMAX_NETWORK_NAME, + "NetworkName", + "Network name", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + + /** + * NMSettingWimax:mac-address: + * + * If specified, this connection will only apply to the WiMAX device + * whose MAC address matches. This property does not change the MAC address + * of the device (known as MAC spoofing). + **/ + g_object_class_install_property + (object_class, PROP_MAC_ADDRESS, + _nm_param_spec_specialized (NM_SETTING_WIMAX_MAC_ADDRESS, + "MAC Address", + "If specified, this connection will only apply to " + "the WiMAX device whose MAC address matches. " + "This property does not change the MAC address " + "of the device (known as MAC spoofing).", + DBUS_TYPE_G_UCHAR_ARRAY, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); +} diff --git a/libnm-util/nm-setting-wimax.h b/libnm-util/nm-setting-wimax.h new file mode 100644 index 0000000000..a3e500be51 --- /dev/null +++ b/libnm-util/nm-setting-wimax.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2009 Novell, Inc. + */ + +#ifndef NM_SETTING_WIMAX_H +#define NM_SETTING_WIMAX_H + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_WIMAX (nm_setting_wimax_get_type ()) +#define NM_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimax)) +#define NM_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) +#define NM_IS_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIMAX)) +#define NM_IS_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTING_WIMAX)) +#define NM_SETTING_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass)) + +#define NM_SETTING_WIMAX_SETTING_NAME "wimax" + +typedef enum +{ + NM_SETTING_WIMAX_ERROR_UNKNOWN = 0, + NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY, + NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY +} NMSettingWimaxError; + +#define NM_TYPE_SETTING_WIMAX_ERROR (nm_setting_wimax_error_get_type ()) +GType nm_setting_wimax_error_get_type (void); + +#define NM_SETTING_WIMAX_ERROR nm_setting_wimax_error_quark () +GQuark nm_setting_wimax_error_quark (void); + +#define NM_SETTING_WIMAX_NETWORK_NAME "network-name" +#define NM_SETTING_WIMAX_MAC_ADDRESS "mac-address" + +typedef struct { + NMSetting parent; +} NMSettingWimax; + +typedef struct { + NMSettingClass parent; +} NMSettingWimaxClass; + +GType nm_setting_wimax_get_type (void); + +NMSetting *nm_setting_wimax_new (void); +const char *nm_setting_wimax_get_network_name (NMSettingWimax *setting); +const GByteArray *nm_setting_wimax_get_mac_address (NMSettingWimax *setting); + +G_END_DECLS + +#endif /* NM_SETTING_WIMAX_H */ diff --git a/src/Makefile.am b/src/Makefile.am index f351c787d1..14ddec3abe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,7 @@ SUBDIRS= \ dnsmasq-manager \ modem-manager \ bluez-manager \ + wimax \ system-settings \ . \ tests @@ -24,6 +25,7 @@ INCLUDES = -I${top_srcdir} \ -I${top_srcdir}/src/dnsmasq-manager \ -I${top_srcdir}/src/modem-manager \ -I$(top_srcdir)/src/bluez-manager \ + -I$(top_srcdir)/src/wimax \ -I$(top_srcdir)/src/system-settings \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/libnm-glib \ @@ -169,6 +171,7 @@ NetworkManager_CPPFLAGS = \ $(OPENSSL_CFLAGS) \ $(LIBNL_CFLAGS) \ $(GMODULE_CFLAGS) \ + $(WIMAX_CFLAGS) \ -DG_DISABLE_DEPRECATED \ -DBINDIR=\"$(bindir)\" \ -DSBINDIR=\"$(sbindir)\" \ @@ -191,6 +194,7 @@ NetworkManager_LDADD = \ ./ppp-manager/libppp-manager.la \ ./modem-manager/libmodem-manager.la \ ./bluez-manager/libbluez-manager.la \ + ./wimax/libwimax.la \ ./system-settings/libsystem-settings.la \ ./backends/libnmbackend.la \ $(top_builddir)/libnm-util/libnm-util.la \ diff --git a/src/nm-manager.c b/src/nm-manager.c index 14c2a907e0..6947cc295f 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -37,6 +37,7 @@ #include "nm-device-ethernet.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" +#include "nm-wimax-device.h" #include "NetworkManagerSystem.h" #include "nm-properties-changed-signal.h" #include "nm-setting-bluetooth.h" @@ -1185,6 +1186,8 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled) for (iter = priv->devices; iter; iter = iter->next) { if (NM_IS_DEVICE_WIFI (iter->data)) nm_device_wifi_set_enabled (NM_DEVICE_WIFI (iter->data), enabled); + else if (NM_IS_WIMAX_DEVICE (iter->data)) + nm_wimax_device_set_enabled (NM_WIMAX_DEVICE (iter->data), enabled); } } @@ -1372,7 +1375,8 @@ add_device (NMManager *self, NMDevice *device) */ nm_manager_rfkill_update (self); nm_device_wifi_set_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled); - } + } else if (NM_IS_WIMAX_DEVICE (device)) + nm_wimax_device_set_enabled (NM_WIMAX_DEVICE (device), priv->wireless_enabled); type_desc = nm_device_get_type_desc (device); g_assert (type_desc); @@ -2563,6 +2567,8 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error) */ if (NM_IS_DEVICE_WIFI (iter->data)) nm_device_wifi_set_enabled (NM_DEVICE_WIFI (iter->data), wifi_enabled); + else if (NM_IS_WIMAX_DEVICE (iter->data)) + nm_wimax_device_set_enabled (NM_WIMAX_DEVICE (iter->data), wifi_enabled); nm_device_clear_autoconnect_inhibit (device); if (nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index be0825c6b3..a907afc2ed 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -38,6 +38,7 @@ #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" #include "nm-device-ethernet.h" +#include "nm-wimax-manager.h" typedef struct { GUdevClient *client; @@ -279,6 +280,12 @@ is_olpc_mesh (GUdevDevice *device) return (prop != NULL); } +static gboolean +is_wimax (const char *driver) +{ + return g_strcmp0 (driver, "i2400m_usb") == 0; +} + static GObject * device_creator (NMUdevManager *manager, GUdevDevice *udev_device, @@ -331,6 +338,8 @@ device_creator (NMUdevManager *manager, device = (GObject *) nm_device_olpc_mesh_new (path, ifname, driver, ifindex); else if (is_wireless (udev_device)) device = (GObject *) nm_device_wifi_new (path, ifname, driver, ifindex); + else if (is_wimax (driver)) + device = (GObject *) nm_wimax_manager_create_device (path, ifname, driver, ifindex); else device = (GObject *) nm_device_ethernet_new (path, ifname, driver, ifindex); diff --git a/src/wimax/Makefile.am b/src/wimax/Makefile.am new file mode 100644 index 0000000000..2b915b4b03 --- /dev/null +++ b/src/wimax/Makefile.am @@ -0,0 +1,39 @@ +INCLUDES = \ + -I${top_srcdir}/src \ + -I${top_srcdir}/include \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/marshallers + +noinst_LTLIBRARIES = libwimax.la + +libwimax_la_SOURCES = \ + nm-wimax-device.c \ + nm-wimax-device.h \ + nm-wimax-manager.c \ + nm-wimax-manager.h \ + nm-wimax-nsp.c \ + nm-wimax-nsp.h \ + nm-wimax-types.h \ + nm-wimax-util.c \ + nm-wimax-util.h + +libwimax_la_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(WIMAX_CFLAGS) + +libwimax_la_LIBADD = \ + $(DBUS_LIBS) \ + $(WIMAX_LIBS) \ + $(top_builddir)/marshallers/libmarshallers.la + +nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml + dbus-binding-tool --prefix=nm_wimax_nsp --mode=glib-server --output=$@ $< + +nm-wimax-device-glue.h: $(top_srcdir)/introspection/nm-wimax-device.xml + dbus-binding-tool --prefix=nm_wimax_device --mode=glib-server --output=$@ $< + +BUILT_SOURCES = \ + nm-wimax-nsp-glue.h \ + nm-wimax-device-glue.h + +CLEANFILES = $(BUILT_SOURCES) diff --git a/src/wimax/nm-wimax-device.c b/src/wimax/nm-wimax-device.c new file mode 100644 index 0000000000..ffb0ab5fd0 --- /dev/null +++ b/src/wimax/nm-wimax-device.c @@ -0,0 +1,1055 @@ +/* -*- 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 +#include +#include + +#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" + +G_DEFINE_TYPE (NMWimaxDevice, nm_wimax_device, NM_TYPE_DEVICE) + +enum { + PROP_0, + PROP_INDEX, + PROP_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; + guint32 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, + int 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, + NM_WIMAX_DEVICE_IFINDEX, 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)); +} + +guint32 +nm_wimax_device_get_ifindex (NMWimaxDevice *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_DEVICE (self), 0); + + return GET_PRIVATE (self)->ifindex; +} + +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_wimax_device_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); +} + +void +nm_wimax_device_set_enabled (NMWimaxDevice *self, gboolean enabled) +{ + NMWimaxDevicePrivate *priv; + + g_return_if_fail (NM_IS_WIMAX_DEVICE (self)); + + priv = GET_PRIVATE (self); + if (priv->enabled == enabled) + return; + + priv->enabled = enabled; + schedule_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; + } +} + +/* 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 +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; + case PROP_IFINDEX: + priv->ifindex = g_value_get_uint (value); + break; + 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_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)); + + 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); +} diff --git a/src/wimax/nm-wimax-device.h b/src/wimax/nm-wimax-device.h new file mode 100644 index 0000000000..e381dddfc2 --- /dev/null +++ b/src/wimax/nm-wimax-device.h @@ -0,0 +1,76 @@ +/* -*- 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 +#include +#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" +#define NM_WIMAX_DEVICE_IFINDEX "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, + int ifindex, + guchar wimax_device_index); + +void nm_wimax_device_get_hw_address (NMWimaxDevice *self, + struct ether_addr *addr); + +guint32 nm_wimax_device_get_ifindex (NMWimaxDevice *self); +void nm_wimax_device_set_enabled (NMWimaxDevice *self, + gboolean enabled); + +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 */ diff --git a/src/wimax/nm-wimax-manager.c b/src/wimax/nm-wimax-manager.c new file mode 100644 index 0000000000..1cba7c57d5 --- /dev/null +++ b/src/wimax/nm-wimax-manager.c @@ -0,0 +1,139 @@ +/* -*- 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 +#include +#include + +#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, + const char *driver, + int ifindex) +{ + 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, ifindex, 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; +} diff --git a/src/wimax/nm-wimax-manager.h b/src/wimax/nm-wimax-manager.h new file mode 100644 index 0000000000..e0427dd152 --- /dev/null +++ b/src/wimax/nm-wimax-manager.h @@ -0,0 +1,31 @@ +/* -*- 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, + int ifindex); + +#endif /* NM_WIMAX_MANAGER_H */ diff --git a/src/wimax/nm-wimax-nsp.c b/src/wimax/nm-wimax-nsp.c new file mode 100644 index 0000000000..e69fc95efb --- /dev/null +++ b/src/wimax/nm-wimax-nsp.c @@ -0,0 +1,249 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#include "nm-wimax-nsp.h" +#include "NetworkManager.h" +#include "nm-dbus-manager.h" +#include "nm-setting-wimax.h" +#include "nm-properties-changed-signal.h" +#include "nm-wimax-nsp-glue.h" +#include "nm-utils.h" + +G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, G_TYPE_OBJECT) + +enum { + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_NAME, + PROP_SIGNAL_QUALITY, + PROP_NETWORK_TYPE, + + LAST_PROP +}; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) + +typedef struct { + char *dbus_path; + + char *name; + guint32 signal_quality; + NMWimaxNspNetworkType network_type; +} NMWimaxNspPrivate; + +NMWimaxNsp * +nm_wimax_nsp_new (const char *name) +{ + g_return_val_if_fail (name != NULL, NULL); + + return NM_WIMAX_NSP (g_object_new (NM_TYPE_WIMAX_NSP, + NM_WIMAX_NSP_NAME, name, + NULL)); +} + +const char * +nm_wimax_nsp_get_name (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); + + return GET_PRIVATE (self)->name; +} + +guint32 +nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); + + return GET_PRIVATE (self)->signal_quality; +} + +NMWimaxNspNetworkType +nm_wimax_nsp_get_network_type (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); + + return GET_PRIVATE (self)->network_type; +} + +void +nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self) +{ + NMWimaxNspPrivate *priv; + NMDBusManager *mgr; + DBusGConnection *g_connection; + static guint32 counter = 0; + + g_return_if_fail (NM_IS_WIMAX_NSP (self)); + + priv = GET_PRIVATE (self); + + if (priv->dbus_path) { + nm_warning ("NSP already exported."); + return; + } + + mgr = nm_dbus_manager_get (); + g_assert (mgr); + + g_connection = nm_dbus_manager_get_connection (mgr); + g_assert (g_connection); + + priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_WIMAX_NSP "/%d", counter++); + dbus_g_connection_register_g_object (g_connection, priv->dbus_path, G_OBJECT (self)); + + g_object_unref (mgr); +} + +const char * +nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); + + return GET_PRIVATE (self)->dbus_path; +} + +gboolean +nm_wimax_nsp_check_compatible (NMWimaxNsp *self, + NMConnection *connection) +{ + NMWimaxNspPrivate *priv; + NMSettingWimax *s_wimax; + + g_return_val_if_fail (NM_IS_WIMAX_NSP (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + priv = GET_PRIVATE (self); + + s_wimax = NM_SETTING_WIMAX (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX)); + if (!s_wimax) + return FALSE; + + return g_strcmp0 (nm_wimax_nsp_get_name (self), nm_setting_wimax_get_network_name (s_wimax)) == 0; +} + +static void +nm_wimax_nsp_init (NMWimaxNsp *self) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMWimaxNspPrivate *priv = GET_PRIVATE (object); + guint32 quality; + guchar network_type; + + switch (prop_id) { + case PROP_NAME: + /* Construct only */ + priv->name = g_value_dup_string (value); + break; + case PROP_SIGNAL_QUALITY: + quality = g_value_get_uint (value); + if (quality != priv->signal_quality) { + priv->signal_quality = quality; + g_object_notify (object, NM_WIMAX_NSP_SIGNAL_QUALITY); + } + break; + case PROP_NETWORK_TYPE: + network_type = g_value_get_uchar (value); + if (network_type != priv->network_type) { + priv->network_type = network_type; + g_object_notify (object, NM_WIMAX_NSP_NETWORK_TYPE); + } + break; + 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) +{ + NMWimaxNsp *self = NM_WIMAX_NSP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_wimax_nsp_get_name (self)); + break; + case PROP_SIGNAL_QUALITY: + g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (self)); + break; + case PROP_NETWORK_TYPE: + g_value_set_uchar (value, nm_wimax_nsp_get_network_type (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMWimaxNspPrivate *priv = GET_PRIVATE (object); + + g_free (priv->name); + g_free (priv->dbus_path); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); +} + +static void +nm_wimax_nsp_class_init (NMWimaxNspClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMWimaxNspPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_WIMAX_NSP_NAME, + "Name", + "Name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SIGNAL_QUALITY, + g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, + "SignalQuality", + "SignalQuality", + 0, + 100, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_uchar (NM_WIMAX_NSP_NETWORK_TYPE, + "NetworkType", + "NetworkType", + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + G_PARAM_READWRITE)); + + /* Signals */ + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMWimaxNspClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_wimax_nsp_object_info); +} diff --git a/src/wimax/nm-wimax-nsp.h b/src/wimax/nm-wimax-nsp.h new file mode 100644 index 0000000000..a74b68a79d --- /dev/null +++ b/src/wimax/nm-wimax-nsp.h @@ -0,0 +1,63 @@ +/* -*- 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_NSP_H +#define NM_WIMAX_NSP_H + +#include +#include "nm-wimax-types.h" +#include "nm-connection.h" + +#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) +#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) +#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) +#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIMAX_NSP)) +#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) + +#define NM_WIMAX_NSP_NAME "name" +#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" +#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" + +typedef struct { + GObject parent; +} NMWimaxNsp; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*properties_changed) (NMWimaxNsp *nsp, GHashTable *properties); +} NMWimaxNspClass; + +GType nm_wimax_nsp_get_type (void); + +NMWimaxNsp *nm_wimax_nsp_new (const char *name); +const char *nm_wimax_nsp_get_name (NMWimaxNsp *self); +guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self); +NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *self); + +void nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self); +const char *nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self); + +gboolean nm_wimax_nsp_check_compatible (NMWimaxNsp *self, + NMConnection *connection); + +#endif /* NM_WIMAX_NSP_H */ diff --git a/src/wimax/nm-wimax-types.h b/src/wimax/nm-wimax-types.h new file mode 100644 index 0000000000..8c807fd8a4 --- /dev/null +++ b/src/wimax/nm-wimax-types.h @@ -0,0 +1,31 @@ +/* -*- 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_TYPES_H +#define NM_WIMAX_TYPES_H + +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + NM_WIMAX_NSP_NETWORK_TYPE_HOME, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER +} NMWimaxNspNetworkType; + +#endif /* NM_WIMAX_TYPES_H */ diff --git a/src/wimax/nm-wimax-util.c b/src/wimax/nm-wimax-util.c new file mode 100644 index 0000000000..ca1b0dcea8 --- /dev/null +++ b/src/wimax/nm-wimax-util.c @@ -0,0 +1,117 @@ +/* -*- 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 +#include "nm-wimax-util.h" +#include "nm-utils.h" + +void +nm_wimax_util_error (struct WIMAX_API_DEVICE_ID *device_id, + const char *message, + WIMAX_API_RET result) +{ + char *warning_msg; + char str[MAX_SIZE_OF_STRING_BUFFER]; + gsize str_len = MAX_SIZE_OF_STRING_BUFFER; + + GetErrorString (device_id, result, str, &str_len); + warning_msg = g_strconcat (message, ": %s (%d)", NULL); + g_warning (warning_msg, str, result); + g_free (warning_msg); +} + +NMWimaxNspNetworkType +nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type) +{ + NMWimaxNspNetworkType type; + + switch (wimax_network_type) { + case WIMAX_API_HOME: + type = NM_WIMAX_NSP_NETWORK_TYPE_HOME; + break; + case WIMAX_API_PARTNER: + type = NM_WIMAX_NSP_NETWORK_TYPE_PARTNER; + break; + case WIMAX_API_ROAMING_PARTNER: + type = NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER; + break; + default: + type = NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN; + break; + } + + return type; +} + +/* cinr_to_percentage() and the comment is borrowed from connman */ + +/* + * FIXME: pulled it it out of some hole + * + * the cinr to percentage computation comes from the L3/L4 doc + * + * But some other places (L4 code) have a more complex, seemingly + * logarithmical computation. + * + * Oh well... + * + */ + +int +nm_wimax_util_cinr_to_percentage (int cinr) +{ + int strength; + + if (cinr <= -5) + strength = 0; + else if (cinr >= 25) + strength = 100; + else /* Calc percentage on the value from -5 to 25 */ + strength = ((100UL * (cinr - -5)) / (25 - -5)); + + return strength; +} + +const char * +nm_wimax_util_device_status_to_str (WIMAX_API_DEVICE_STATUS status) +{ + switch (status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + return "Device is uninitialized"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + return "Device RF Off(both H/W and S/W)"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + return "Device RF Off(via H/W switch)"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + return "Device RF Off(via S/W switch)"; + case WIMAX_API_DEVICE_STATUS_Ready: + return "Device is ready"; + case WIMAX_API_DEVICE_STATUS_Scanning: + return "Device is scanning"; + case WIMAX_API_DEVICE_STATUS_Connecting: + return "Connection in progress"; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + return "Layer 2 connected"; + case WIMAX_API_DEVICE_STATUS_Connection_Idle: + return "Idle connection"; + } + + return "Unknown device state"; +} diff --git a/src/wimax/nm-wimax-util.h b/src/wimax/nm-wimax-util.h new file mode 100644 index 0000000000..e40ed46dbf --- /dev/null +++ b/src/wimax/nm-wimax-util.h @@ -0,0 +1,36 @@ +/* -*- 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_UTIL_H +#define NM_WIMAX_UTIL_H + +#include +#include "nm-wimax-types.h" + +void nm_wimax_util_error (struct WIMAX_API_DEVICE_ID *device_id, + const char *message, + WIMAX_API_RET result); + +NMWimaxNspNetworkType nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type); +int nm_wimax_util_cinr_to_percentage (int cinr); + +const char *nm_wimax_util_device_status_to_str (WIMAX_API_DEVICE_STATUS status); + +#endif /* NM_WIMAX_UTIL_H */ diff --git a/test/nm-tool.c b/test/nm-tool.c index 9d1a245718..dc4efb8c9d 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -192,6 +193,46 @@ detail_access_point (gpointer data, gpointer user_data) g_free (tmp); } +static const char * +wimax_network_type_to_str (NMWimaxNspNetworkType type) +{ + switch (type) { + case NM_WIMAX_NSP_NETWORK_TYPE_HOME: + return "Home network"; + case NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: + return "Partner network"; + case NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: + return "Roaming partner network"; + default: + return "Unknown network"; + } +} + +static void +detail_nsp (gpointer data, gpointer user_data) +{ + NMWimaxNsp *nsp = NM_WIMAX_NSP (data); + const char *active_name = (const char *) user_data; + const char *name; + char *label; + char *data_str; + gboolean active = FALSE; + + name = nm_wimax_nsp_get_name (nsp); + + if (active_name) + active = g_strcmp0 (active_name, name) == 0; + + label = g_strdup_printf (" %s%s", active ? "*" : "", name); + data_str = g_strdup_printf ("%s, Signal quality: %d", + wimax_network_type_to_str (nm_wimax_nsp_get_network_type (nsp)), + nm_wimax_nsp_get_signal_quality (nsp)); + + print_string (label, data); + g_free (label); + g_free (data_str); +} + static gchar * ip4_address_as_string (guint32 ip) { @@ -315,6 +356,8 @@ detail_device (gpointer data, gpointer user_data) print_string ("Type", "Mobile Broadband (CDMA)"); else if (NM_IS_DEVICE_BT (device)) print_string ("Type", "Bluetooth"); + else if (NM_IS_WIMAX_DEVICE (device)) + print_string ("Type", "WiMAX"); print_string ("Driver", nm_device_get_driver (device) ? nm_device_get_driver (device) : "(unknown)"); @@ -330,6 +373,8 @@ detail_device (gpointer data, gpointer user_data) tmp = g_strdup (nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device))); else if (NM_IS_DEVICE_WIFI (device)) tmp = g_strdup (nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device))); + else if (NM_IS_WIMAX_DEVICE (device)) + tmp = g_strdup (nm_wimax_device_get_hw_address (NM_WIMAX_DEVICE (device))); if (tmp) { print_string ("HW Address", tmp); @@ -395,6 +440,21 @@ detail_device (gpointer data, gpointer user_data) print_string (" Carrier", "on"); else print_string (" Carrier", "off"); + } else if (NM_IS_WIMAX_DEVICE (device)) { + NMWimaxNsp *active_nsp = NULL; + const char *active_name = NULL; + const GPtrArray *nsps; + + if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) { + active_nsp = nm_wimax_device_get_active_nsp (NM_WIMAX_DEVICE (device)); + active_name = active_nsp ? nm_wimax_nsp_get_name (active_nsp) : NULL; + } + + printf ("\n WiMAX NSPs %s\n", active_nsp ? "(* current NSP)" : ""); + + nsps = nm_wimax_device_get_nsps (NM_WIMAX_DEVICE (device)); + if (nsps && nsps->len) + g_ptr_array_foreach ((GPtrArray *) nsps, detail_nsp, (gpointer) active_name); } /* IP Setup info */