From 9e80c1e85d6ba032729a4e2bf488e522884926c9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 3 Jan 2011 23:55:38 -0600 Subject: [PATCH] wimax: make WiMAX mostly work Heavily modify Inaky's Intel WiMAX SDK glue (originally from connman) to be more generic and more thread-safe, and suitable for use with NetworkManager instead of rolling our own client code. Rewrite the NMDeviceWimax code to mostly work. Still to be done: actual connection logic, DHCP handling, spawning wimaxd if it's not started yet --- include/NetworkManager.h | 2 +- introspection/Makefile.am | 2 +- introspection/all.xml | 4 +- ...m-wimax-device.xml => nm-device-wimax.xml} | 0 libnm-glib/Makefile.am | 12 +- libnm-glib/libnm-glib.ver | 12 +- .../{nm-wimax-device.c => nm-device-wimax.c} | 163 +-- libnm-glib/nm-device-wimax.h | 68 + libnm-glib/nm-device.c | 4 +- libnm-glib/nm-wimax-device.h | 67 - src/nm-manager.c | 4 +- src/nm-udev-manager.c | 7 +- src/wimax/Makefile.am | 17 +- src/wimax/iwmxsdk.c | 1286 +++++++++++++++++ src/wimax/iwmxsdk.h | 98 ++ src/wimax/nm-device-wimax.c | 1071 ++++++++++++++ src/wimax/nm-device-wimax.h | 68 + src/wimax/nm-wimax-device.c | 1037 ------------- src/wimax/nm-wimax-device.h | 70 - src/wimax/nm-wimax-manager.c | 139 +- src/wimax/nm-wimax-manager.h | 30 +- src/wimax/nm-wimax-util.c | 95 +- src/wimax/nm-wimax-util.h | 13 +- test/nm-tool.c | 30 +- 24 files changed, 2835 insertions(+), 1464 deletions(-) rename introspection/{nm-wimax-device.xml => nm-device-wimax.xml} (100%) rename libnm-glib/{nm-wimax-device.c => nm-device-wimax.c} (72%) create mode 100644 libnm-glib/nm-device-wimax.h delete mode 100644 libnm-glib/nm-wimax-device.h create mode 100644 src/wimax/iwmxsdk.c create mode 100644 src/wimax/iwmxsdk.h create mode 100644 src/wimax/nm-device-wimax.c create mode 100644 src/wimax/nm-device-wimax.h delete mode 100644 src/wimax/nm-wimax-device.c delete mode 100644 src/wimax/nm-wimax-device.h diff --git a/include/NetworkManager.h b/include/NetworkManager.h index 7e68855a13..b2a0098caf 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -38,7 +38,7 @@ #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_DEVICE_WIMAX 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" diff --git a/introspection/Makefile.am b/introspection/Makefile.am index 67abff899e..9c6958894d 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -11,6 +11,7 @@ EXTRA_DIST = \ nm-device-cdma.xml \ nm-device-gsm.xml \ nm-device-serial.xml \ + nm-device-wimax.xml \ nm-device.xml \ nm-ip4-config.xml \ nm-ip6-config.xml \ @@ -25,6 +26,5 @@ EXTRA_DIST = \ nm-active-connection.xml \ nm-dhcp4-config.xml \ nm-dhcp6-config.xml \ - nm-wimax-device.xml \ nm-wimax-nsp.xml diff --git a/introspection/all.xml b/introspection/all.xml index 5e0abc4876..521ab017d5 100644 --- a/introspection/all.xml +++ b/introspection/all.xml @@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + @@ -44,8 +46,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - diff --git a/introspection/nm-wimax-device.xml b/introspection/nm-device-wimax.xml similarity index 100% rename from introspection/nm-wimax-device.xml rename to introspection/nm-device-wimax.xml diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 02ba666717..a3b5577986 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -10,6 +10,7 @@ BUILT_SOURCES = \ nm-device-ethernet-bindings.h \ nm-device-wifi-bindings.h \ nm-device-bt-bindings.h \ + nm-device-wimax-bindings.h \ nm-exported-connection-glue.h \ nm-exported-connection-bindings.h \ nm-settings-glue.h \ @@ -21,8 +22,7 @@ BUILT_SOURCES = \ nm-ip4-config-bindings.h \ nm-dhcp4-config-bindings.h \ nm-ip6-config-bindings.h \ - nm-dhcp6-config-bindings.h \ - nm-wimax-device-bindings.h + nm-dhcp6-config-bindings.h ##################################################### # Deprecated original libnm_glib bits @@ -86,7 +86,7 @@ libnminclude_HEADERS = \ nm-settings-connection-interface.h \ nm-exported-connection.h \ nm-settings-service.h \ - nm-wimax-device.h \ + nm-device-wimax.h \ nm-wimax-nsp.h libnm_glib_la_SOURCES = \ @@ -123,7 +123,7 @@ libnm_glib_la_SOURCES = \ nm-settings-connection-interface.c \ nm-exported-connection.c \ nm-settings-service.c \ - nm-wimax-device.c \ + nm-device-wimax.c \ nm-wimax-nsp.c libnm_glib_la_LIBADD = \ @@ -205,8 +205,8 @@ nm-ip6-config-bindings.h: $(top_srcdir)/introspection/nm-ip6-config.xml nm-dhcp6-config-bindings.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-client --output=$@ $< -nm-wimax-device-bindings.h: $(top_srcdir)/introspection/nm-wimax-device.xml - dbus-binding-tool --prefix=nm_wimax_device --mode=glib-client --output=$@ $< +nm-device-wimax-bindings.h: $(top_srcdir)/introspection/nm-device-wimax.xml + dbus-binding-tool --prefix=nm_device_wimax --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 9ec54de9dd..e046b162d0 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -167,12 +167,12 @@ 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_device_wimax_get_hw_address; + nm_device_wimax_get_active_nsp; + nm_device_wimax_get_nsp_by_path; + nm_device_wimax_get_nsps; + nm_device_wimax_get_type; + nm_device_wimax_new; nm_wimax_nsp_get_name; nm_wimax_nsp_get_network_type; nm_wimax_nsp_get_signal_quality; diff --git a/libnm-glib/nm-wimax-device.c b/libnm-glib/nm-device-wimax.c similarity index 72% rename from libnm-glib/nm-wimax-device.c rename to libnm-glib/nm-device-wimax.c index 09a9bad64d..4d43dc8c0e 100644 --- a/libnm-glib/nm-wimax-device.c +++ b/libnm-glib/nm-device-wimax.c @@ -17,26 +17,27 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * + * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. */ #include -#include "nm-wimax-device.h" +#include "nm-device-wimax.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" +#include "nm-device-wimax-bindings.h" -G_DEFINE_TYPE (NMWimaxDevice, nm_wimax_device, NM_TYPE_DEVICE) +G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE) -#define NM_WIMAX_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_DEVICE, NMWimaxDevicePrivate)) +#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxPrivate)) static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field); -void _nm_wimax_device_set_wireless_enabled (NMWimaxDevice *wimax, gboolean enabled); +void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled); typedef struct { gboolean disposed; @@ -46,7 +47,7 @@ typedef struct { NMWimaxNsp *active_nsp; gboolean null_active_nsp; GPtrArray *nsps; -} NMWimaxDevicePrivate; +} NMDeviceWimaxPrivate; enum { PROP_0, @@ -69,46 +70,46 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; /** - * nm_wimax_device_new: + * nm_device_wimax_new: * @connection: the #DBusGConnection * @path: the DBus object path of the wimax * - * Creates a new #NMWimaxDevice. + * Creates a new #NMDeviceWimax. * * Returns: a new wimax **/ GObject * -nm_wimax_device_new (DBusGConnection *connection, const char *path) +nm_device_wimax_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, + return g_object_new (NM_TYPE_DEVICE_WIMAX, NM_OBJECT_DBUS_CONNECTION, connection, NM_OBJECT_DBUS_PATH, path, NULL); } /** - * nm_wimax_device_get_hw_address: - * @device: a #NMWimaxDevice + * nm_device_wimax_get_hw_address: + * @device: a #NMDeviceWimax * - * Gets the hardware (MAC) address of the #NMWimaxDevice + * Gets the hardware (MAC) address of the #NMDeviceWimax * * 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) +nm_device_wimax_get_hw_address (NMDeviceWimax *wimax) { - NMWimaxDevicePrivate *priv; + NMDeviceWimaxPrivate *priv; - g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); - priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); if (!priv->hw_address) { priv->hw_address = _nm_object_get_string_property (NM_OBJECT (wimax), - NM_DBUS_INTERFACE_WIMAX_DEVICE, + NM_DBUS_INTERFACE_DEVICE_WIMAX, DBUS_PROP_HW_ADDRESS); } @@ -116,22 +117,22 @@ nm_wimax_device_get_hw_address (NMWimaxDevice *wimax) } /** - * nm_wimax_device_get_active_nsp: - * @wimax: a #NMWimaxDevice + * nm_device_wimax_get_active_nsp: + * @wimax: a #NMDeviceWimax * * Gets the active #NMWimaxNsp. * * Returns: the access point or %NULL if none is active **/ NMWimaxNsp * -nm_wimax_device_get_active_nsp (NMWimaxDevice *wimax) +nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax) { - NMWimaxDevicePrivate *priv; + NMDeviceWimaxPrivate *priv; NMDeviceState state; char *path; GValue value = { 0, }; - g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); state = nm_device_get_state (NM_DEVICE (wimax)); switch (state) { @@ -146,14 +147,14 @@ nm_wimax_device_get_active_nsp (NMWimaxDevice *wimax) break; } - priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + priv = NM_DEVICE_WIMAX_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, + NM_DBUS_INTERFACE_DEVICE_WIMAX, DBUS_PROP_ACTIVE_NSP); if (path) { g_value_init (&value, DBUS_TYPE_G_OBJECT_PATH); @@ -166,26 +167,26 @@ nm_wimax_device_get_active_nsp (NMWimaxDevice *wimax) } /** - * nm_wimax_device_get_nsps: - * @wimax: a #NMWimaxDevice + * nm_device_wimax_get_nsps: + * @wimax: a #NMDeviceWimax * - * Gets all the scanned NSPs of the #NMWimaxDevice. + * Gets all the scanned NSPs of the #NMDeviceWimax. * * 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) +nm_device_wimax_get_nsps (NMDeviceWimax *wimax) { - NMWimaxDevicePrivate *priv; + NMDeviceWimaxPrivate *priv; DBusGConnection *connection; GValue value = { 0, }; GError *error = NULL; GPtrArray *temp; - g_return_val_if_fail (NM_IS_WIMAX_DEVICE (wimax), NULL); + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); - priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax); if (priv->nsps) return handle_ptr_array_return (priv->nsps); @@ -205,8 +206,8 @@ nm_wimax_device_get_nsps (NMWimaxDevice *wimax) } /** - * nm_wimax_device_get_nsp_by_path: - * @wimax: a #NMWimaxDevice + * nm_device_wimax_get_nsp_by_path: + * @wimax: a #NMDeviceWimax * @path: the object path of the NSP * * Gets a #NMWimaxNsp by path. @@ -214,17 +215,17 @@ nm_wimax_device_get_nsps (NMWimaxDevice *wimax) * Returns: the access point or %NULL if none is found. **/ NMWimaxNsp * -nm_wimax_device_get_nsp_by_path (NMWimaxDevice *wimax, +nm_device_wimax_get_nsp_by_path (NMDeviceWimax *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 (NM_IS_DEVICE_WIMAX (wimax), NULL); g_return_val_if_fail (path != NULL, NULL); - nsps = nm_wimax_device_get_nsps (wimax); + nsps = nm_device_wimax_get_nsps (wimax); if (!nsps) return NULL; @@ -242,17 +243,17 @@ nm_wimax_device_get_nsp_by_path (NMWimaxDevice *wimax, static void nsp_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data) { - NMWimaxDevice *self = NM_WIMAX_DEVICE (user_data); - NMWimaxDevicePrivate *priv; + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv; GObject *nsp; g_return_if_fail (self != NULL); - nsp = G_OBJECT (nm_wimax_device_get_nsp_by_path (self, path)); + nsp = G_OBJECT (nm_device_wimax_get_nsp_by_path (self, path)); if (!nsp) { DBusGConnection *connection = nm_object_get_connection (NM_OBJECT (self)); - priv = NM_WIMAX_DEVICE_GET_PRIVATE (self); + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); nsp = G_OBJECT (_nm_object_cache_get (path)); if (nsp) { g_ptr_array_add (priv->nsps, g_object_ref (nsp)); @@ -270,20 +271,20 @@ nsp_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data) 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); + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); NMWimaxNsp *nsp; g_return_if_fail (self != NULL); - nsp = nm_wimax_device_get_nsp_by_path (self, path); + nsp = nm_device_wimax_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); + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); } g_signal_emit (self, signals[NSP_REMOVED], 0, nsp); @@ -293,13 +294,13 @@ nsp_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data) } static void -clean_up_nsps (NMWimaxDevice *self, gboolean notify) +clean_up_nsps (NMDeviceWimax *self, gboolean notify) { - NMWimaxDevicePrivate *priv; + NMDeviceWimaxPrivate *priv; - g_return_if_fail (NM_IS_WIMAX_DEVICE (self)); + g_return_if_fail (NM_IS_DEVICE_WIMAX (self)); - priv = NM_WIMAX_DEVICE_GET_PRIVATE (self); + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); if (priv->active_nsp) { g_object_unref (priv->active_nsp); @@ -323,7 +324,7 @@ clean_up_nsps (NMWimaxDevice *self, gboolean notify) /**************************************************************/ static void -nm_wimax_device_init (NMWimaxDevice *wimax) +nm_device_wimax_init (NMDeviceWimax *wimax) { } @@ -333,14 +334,14 @@ get_property (GObject *object, GValue *value, GParamSpec *pspec) { - NMWimaxDevice *self = NM_WIMAX_DEVICE (object); + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); switch (prop_id) { case PROP_HW_ADDRESS: - g_value_set_string (value, nm_wimax_device_get_hw_address (self)); + g_value_set_string (value, nm_device_wimax_get_hw_address (self)); break; case PROP_ACTIVE_NSP: - g_value_set_object (value, nm_wimax_device_get_active_nsp (self)); + g_value_set_object (value, nm_device_wimax_get_active_nsp (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -351,8 +352,8 @@ get_property (GObject *object, 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); + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_UNKNOWN: @@ -365,7 +366,7 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) priv->active_nsp = NULL; priv->null_active_nsp = FALSE; } - _nm_object_queue_notify (NM_OBJECT (device), NM_WIMAX_DEVICE_ACTIVE_NSP); + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIMAX_ACTIVE_NSP); break; default: break; @@ -375,7 +376,7 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field) { - NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); const char *path; NMWimaxNsp *nsp = NULL; DBusGConnection *connection; @@ -408,17 +409,17 @@ demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpoint if (nsp) priv->active_nsp = nsp; - _nm_object_queue_notify (object, NM_WIMAX_DEVICE_ACTIVE_NSP); + _nm_object_queue_notify (object, NM_DEVICE_WIMAX_ACTIVE_NSP); return TRUE; } static void -register_for_property_changed (NMWimaxDevice *wimax) +register_for_property_changed (NMDeviceWimax *wimax) { - NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (wimax); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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 }, + { NM_DEVICE_WIMAX_HW_ADDRESS, _nm_object_demarshal_generic, &priv->hw_address }, + { NM_DEVICE_WIMAX_ACTIVE_NSP, demarshal_active_nsp, &priv->active_nsp }, { NULL }, }; @@ -433,20 +434,20 @@ constructor (GType type, GObjectConstructParam *construct_params) { GObject *object; - NMWimaxDevicePrivate *priv; + NMDeviceWimaxPrivate *priv; - object = G_OBJECT_CLASS (nm_wimax_device_parent_class)->constructor (type, + object = G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructor (type, n_construct_params, construct_params); if (!object) return NULL; - priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + priv = NM_DEVICE_WIMAX_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); + NM_DBUS_INTERFACE_DEVICE_WIMAX); dbus_g_proxy_add_signal (priv->proxy, "NspAdded", DBUS_TYPE_G_OBJECT_PATH, @@ -462,7 +463,7 @@ constructor (GType type, G_CALLBACK (nsp_removed_proxy), object, NULL); - register_for_property_changed (NM_WIMAX_DEVICE (object)); + register_for_property_changed (NM_DEVICE_WIMAX (object)); g_signal_connect (object, "notify::" NM_DEVICE_STATE, @@ -475,38 +476,38 @@ constructor (GType type, static void dispose (GObject *object) { - NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); if (priv->disposed) { - G_OBJECT_CLASS (nm_wimax_device_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); return; } priv->disposed = TRUE; - clean_up_nsps (NM_WIMAX_DEVICE (object), FALSE); + clean_up_nsps (NM_DEVICE_WIMAX (object), FALSE); g_object_unref (priv->proxy); - G_OBJECT_CLASS (nm_wimax_device_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); } static void finalize (GObject *object) { - NMWimaxDevicePrivate *priv = NM_WIMAX_DEVICE_GET_PRIVATE (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); if (priv->hw_address) g_free (priv->hw_address); - G_OBJECT_CLASS (nm_wimax_device_parent_class)->finalize (object); + G_OBJECT_CLASS (nm_device_wimax_parent_class)->finalize (object); } static void -nm_wimax_device_class_init (NMWimaxDeviceClass *wimax_class) +nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class) { GObjectClass *object_class = G_OBJECT_CLASS (wimax_class); - g_type_class_add_private (wimax_class, sizeof (NMWimaxDevicePrivate)); + g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate)); /* virtual methods */ object_class->constructor = constructor; @@ -517,13 +518,13 @@ nm_wimax_device_class_init (NMWimaxDeviceClass *wimax_class) /* properties */ /** - * NMWimaxDevice:active-nsp: + * NMDeviceWimax: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, + g_param_spec_object (NM_DEVICE_WIMAX_ACTIVE_NSP, "Active NSP", "Active NSP", NM_TYPE_WIMAX_NSP, @@ -532,7 +533,7 @@ nm_wimax_device_class_init (NMWimaxDeviceClass *wimax_class) /* signals */ /** - * NMWimaxDevice::nsp-added: + * NMDeviceWimax::nsp-added: * @self: the wimax device that received the signal * @nsp: the new NSP * @@ -542,14 +543,14 @@ nm_wimax_device_class_init (NMWimaxDeviceClass *wimax_class) g_signal_new ("nsp-added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMWimaxDeviceClass, nsp_added), + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); /** - * NMWimaxDevice::nsp-removed: + * NMDeviceWimax::nsp-removed: * @self: the wimax device that received the signal * @nsp: the removed NSP * @@ -559,7 +560,7 @@ nm_wimax_device_class_init (NMWimaxDeviceClass *wimax_class) g_signal_new ("nsp-removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMWimaxDeviceClass, nsp_removed), + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, diff --git a/libnm-glib/nm-device-wimax.h b/libnm-glib/nm-device-wimax.h new file mode 100644 index 0000000000..818444531b --- /dev/null +++ b/libnm-glib/nm-device-wimax.h @@ -0,0 +1,68 @@ +/* -*- 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) 2011 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_DEVICE_WIMAX_H +#define NM_DEVICE_WIMAX_H + +#include "nm-device.h" +#include "nm-wimax-nsp.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) +#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) +#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) +#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) + +#define NM_DEVICE_WIMAX_HW_ADDRESS "hw-address" +#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" + +typedef struct { + NMDevice parent; +} NMDeviceWimax; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*nsp_added) (NMDeviceWimax *self, NMWimaxNsp *nsp); + void (*nsp_removed) (NMDeviceWimax *self, NMWimaxNsp *nsp); +} NMDeviceWimaxClass; + +GType nm_device_wimax_get_type (void); + +GObject *nm_device_wimax_new (DBusGConnection *connection, + const char *path); + +const char *nm_device_wimax_get_hw_address (NMDeviceWimax *wimax); +NMWimaxNsp *nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax); +NMWimaxNsp *nm_device_wimax_get_nsp_by_path (NMDeviceWimax *wimax, + const char *path); + +const GPtrArray *nm_device_wimax_get_nsps (NMDeviceWimax *wimax); + +G_END_DECLS + +#endif /* NM_DEVICE_WIMAX_H */ diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index 74f9342ef3..b494749ada 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -32,7 +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-wimax.h" #include "nm-device.h" #include "nm-device-private.h" #include "nm-object-private.h" @@ -726,7 +726,7 @@ nm_device_new (DBusGConnection *connection, const char *path) dtype = NM_TYPE_DEVICE_BT; break; case NM_DEVICE_TYPE_WIMAX: - dtype = NM_TYPE_WIMAX_DEVICE; + dtype = NM_TYPE_DEVICE_WIMAX; break; default: g_warning ("Unknown device type %d", g_value_get_uint (&value)); diff --git a/libnm-glib/nm-wimax-device.h b/libnm-glib/nm-wimax-device.h deleted file mode 100644 index 1e59fd0d52..0000000000 --- a/libnm-glib/nm-wimax-device.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- 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/src/nm-manager.c b/src/nm-manager.c index da47f5b1bc..d74922a4f6 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -38,7 +38,7 @@ #include "nm-device-ethernet.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" -#include "nm-wimax-device.h" +#include "nm-device-wimax.h" #include "nm-device-cdma.h" #include "nm-device-gsm.h" #include "nm-system.h" @@ -2117,7 +2117,7 @@ add_device (NMManager *self, NMDevice *device) nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), priv->radio_states[RFKILL_TYPE_WWAN].enabled); */ - } else if (NM_IS_WIMAX_DEVICE (device)) { + } else if (NM_IS_DEVICE_WIMAX (device)) { nm_manager_rfkill_update (self, RFKILL_TYPE_WIMAX); enabled = radio_enabled_for_type (self, RFKILL_TYPE_WIMAX); nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index 8a590ca137..31b4e69707 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -38,7 +38,7 @@ #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" #include "nm-device-ethernet.h" -#include "nm-wimax-manager.h" +#include "nm-device-wimax.h" typedef struct { GUdevClient *client; @@ -339,6 +339,9 @@ is_olpc_mesh (GUdevDevice *device) static gboolean is_wimax (const char *driver) { + /* FIXME: check 'DEVTYPE' instead; but since we only support Intel + * WiMAX devices for now this is appropriate. + */ return g_strcmp0 (driver, "i2400m_usb") == 0; } @@ -395,7 +398,7 @@ device_creator (NMUdevManager *manager, else if (is_wireless (udev_device)) device = (GObject *) nm_device_wifi_new (path, ifname, driver); else if (is_wimax (driver)) - device = (GObject *) nm_wimax_manager_create_device (path, ifname, driver); + device = (GObject *) nm_device_wimax_new (path, ifname, driver); else device = (GObject *) nm_device_ethernet_new (path, ifname, driver); diff --git a/src/wimax/Makefile.am b/src/wimax/Makefile.am index 2b915b4b03..83e53cd2ec 100644 --- a/src/wimax/Makefile.am +++ b/src/wimax/Makefile.am @@ -1,5 +1,6 @@ INCLUDES = \ -I${top_srcdir}/src \ + -I${top_srcdir}/src/logging \ -I${top_srcdir}/include \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/marshallers @@ -7,15 +8,15 @@ INCLUDES = \ noinst_LTLIBRARIES = libwimax.la libwimax_la_SOURCES = \ - nm-wimax-device.c \ - nm-wimax-device.h \ - nm-wimax-manager.c \ - nm-wimax-manager.h \ + nm-device-wimax.c \ + nm-device-wimax.h \ nm-wimax-nsp.c \ nm-wimax-nsp.h \ nm-wimax-types.h \ nm-wimax-util.c \ - nm-wimax-util.h + nm-wimax-util.h \ + iwmxsdk.c \ + iwmxsdk.h libwimax_la_CPPFLAGS = \ $(DBUS_CFLAGS) \ @@ -29,11 +30,11 @@ libwimax_la_LIBADD = \ 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=$@ $< +nm-device-wimax-glue.h: $(top_srcdir)/introspection/nm-device-wimax.xml + dbus-binding-tool --prefix=nm_device_wimax --mode=glib-server --output=$@ $< BUILT_SOURCES = \ nm-wimax-nsp-glue.h \ - nm-wimax-device-glue.h + nm-device-wimax-glue.h CLEANFILES = $(BUILT_SOURCES) diff --git a/src/wimax/iwmxsdk.c b/src/wimax/iwmxsdk.c new file mode 100644 index 0000000000..54ad84e8d6 --- /dev/null +++ b/src/wimax/iwmxsdk.c @@ -0,0 +1,1286 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "logging/nm-logging.h" +#include "iwmxsdk.h" + +static WIMAX_API_DEVICE_ID g_api; + +static int iwmx_sdk_setup(struct wmxsdk *wmxsdk); +static void iwmx_sdk_remove(struct wmxsdk *wmxsdk); + +/* Misc utilities */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/* Misc values */ +enum { + /* + * WARNING!!!!! + * + * ONLY ONE DEVICE SUPPORTED + * + * - on removal, there is no way to know which device was + * removed (the removed device is removed from the list and + * the callback doesn't have any more information than the + * index in the list that getlistdevice would return -- racy + * as hell). + * + * - on insertion, there is not enough information provided. + */ + IWMX_SDK_DEV_MAX = 1, +}; + +/* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX */ +static struct wmxsdk *g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX]; + +static struct wmxsdk *deviceid_to_wmxsdk(WIMAX_API_DEVICE_ID *device_id) +{ + unsigned cnt; + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && + wmxsdk->device_id.deviceIndex == device_id->deviceIndex) + return wmxsdk; + } + return NULL; +} + +struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface) +{ + unsigned cnt; + + for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { + struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; + if (wmxsdk && !strcmp(wmxsdk->ifname, iface)) + return wmxsdk; + } + return NULL; +} + +/* + * 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... + * + */ +static int 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; +} + +/**************************************************************/ + +typedef struct { + WimaxNewWmxsdkFunc callback; + void *user_data; +} NewSdkCallback; + +GStaticMutex new_callbacks_mutex = G_STATIC_MUTEX_INIT; +static GSList *new_callbacks = NULL; + +void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data) +{ + NewSdkCallback *cb; + + cb = g_malloc0 (sizeof (NewSdkCallback)); + g_assert (cb); + cb->callback = callback; + cb->user_data = user_data; + + g_static_mutex_lock (&new_callbacks_mutex); + new_callbacks = g_slist_append (new_callbacks, cb); + g_static_mutex_unlock (&new_callbacks_mutex); +} + +void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data) +{ + GSList *iter; + NewSdkCallback *found = NULL; + + g_static_mutex_lock (&new_callbacks_mutex); + for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { + NewSdkCallback *cb = iter->data; + + if (cb->callback == callback && cb->user_data == user_data) { + found = cb; + break; + } + } + + if (found) { + new_callbacks = g_slist_remove (new_callbacks, found); + g_free (found); + } + g_static_mutex_unlock (&new_callbacks_mutex); +} + +/****************************************************************/ + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_DEVICE_STATUS new_status; + WIMAX_API_DEVICE_STATUS old_status; + WIMAX_API_STATUS_REASON reason; +} StateChangeInfo; + +static gboolean +state_change_handler(gpointer user_data) +{ + StateChangeInfo *info = user_data; + + if (info->wmxsdk->state_change_cb) { + info->wmxsdk->state_change_cb(info->wmxsdk, + info->new_status, + info->old_status, + info->reason, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_state_change(struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason) +{ + StateChangeInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->new_status = new_status; + info->old_status = old_status; + info->reason = reason; + + wmxsdk_ref(wmxsdk); + g_idle_add(state_change_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_NETWORK_CONNECTION_RESP result; +} ConnectResultInfo; + +static gboolean +connect_result_handler(gpointer user_data) +{ + ConnectResultInfo *info = user_data; + + if (info->wmxsdk->connect_result_cb) { + info->wmxsdk->connect_result_cb(info->wmxsdk, + info->result, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_connect_result(struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + ConnectResultInfo *info; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + info->result = resp; + + wmxsdk_ref(wmxsdk); + g_idle_add(connect_result_handler, info); +} + +typedef struct { + struct wmxsdk *wmxsdk; + WIMAX_API_NSP_INFO_EX *nsps; + guint num_nsps; +} ScanResultInfo; + +static gboolean +scan_result_handler(gpointer user_data) +{ + ScanResultInfo *info = user_data; + + if (info->wmxsdk->scan_result_cb) { + info->wmxsdk->scan_result_cb(info->wmxsdk, + info->nsps, + info->num_nsps, + info->wmxsdk->callback_data); + } + wmxsdk_unref(info->wmxsdk); + free(info->nsps); + memset(info, 0, sizeof(*info)); + free(info); + return FALSE; +} + +static void +_schedule_scan_result(struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps) +{ + ScanResultInfo *info; + size_t nsps_size; + int i, tmp; + + info = malloc(sizeof (*info)); + if (!info) + return; + + memset(info, 0, sizeof(*info)); + info->wmxsdk = wmxsdk; + + nsps_size = num_nsps * sizeof (WIMAX_API_NSP_INFO_EX); + info->nsps = malloc(nsps_size); + memcpy(info->nsps, nsps, nsps_size); + info->num_nsps = num_nsps; + + /* CAPI may report link quality as zero -- if it does check if it is a bug + * by computing it based on CINR. If it is different, use the computed one. + */ + for (i = 0; i < num_nsps; i++) { + WIMAX_API_NSP_INFO_EX *nsp = &info->nsps[i]; + + if (nsp->linkQuality == 0) { + tmp = cinr_to_percentage(nsp->CINR - 10); + if (tmp != nsp->linkQuality) + nsp->linkQuality = tmp; + } + } + + wmxsdk_ref(wmxsdk); + g_idle_add(scan_result_handler, info); +} + +static gboolean +removed_handler(gpointer user_data) +{ + struct wmxsdk *wmxsdk = user_data; + + if (wmxsdk->removed_cb) + wmxsdk->removed_cb(wmxsdk, wmxsdk->callback_data); + wmxsdk_unref(wmxsdk); + return FALSE; +} + +static void +_schedule_removed(struct wmxsdk *wmxsdk) +{ + wmxsdk_ref(wmxsdk); + g_idle_add(removed_handler, wmxsdk); +} + +/****************************************************************/ + +/* + * Convert a WiMAX API status to an string. + */ +const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status) +{ + switch (status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + return "uninitialized"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + return "rf off"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + return "rf off (hard-block)"; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + return "rf off (soft-block)"; + case WIMAX_API_DEVICE_STATUS_Ready: + return "ready"; + case WIMAX_API_DEVICE_STATUS_Scanning: + return "scanning"; + case WIMAX_API_DEVICE_STATUS_Connecting: + return "connecting"; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + return "connected"; + default: + return "unknown"; + } +} + +const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason) +{ + switch (reason) { + case WIMAX_API_STATUS_REASON_Normal: + return "normal"; + + /**< Failed to complete NW entry with the selected operator (unspecified reason). */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_to_NW: + return "unspecified failure"; + + /**< Failed to complete ranging */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_Ranging: + return "ranging failed"; + + /**< SBC phase failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_SBC: + return "sbc failed"; + + /**< Security error. EAP authentication failed device level */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_Device: + return "EAP device auth failed"; + + /**< Security error. EAP authentication failed user level */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_user: + return "EAP user auth failed"; + + /**< Security error. Handshake failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_3_Way_Handshake: + return "3 way handshake failed"; + + /**< Registration failed */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_REG: + return "registration failed"; + + /**< Failed to initialize the data path (failed to perform DSA to one UL and one DL SFs). */ + case WIMAX_API_STATUS_REASON_Fail_to_connect_datapath: + return "datapath failed"; + + default: + return "unknown"; + } +} + + +/* + * Get the device's status from the device + * + * Does NOT cache the result + * Does NOT trigger a state change in NetworkManager + * + * Returns < 0 errno code on error, status code if ok. + */ +static WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk) +{ + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + WIMAX_API_DEVICE_STATUS dev_status; + WIMAX_API_CONNECTION_PROGRESS_INFO pi; + + r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot read device state: %d (%s)", r, errstr); + dev_status = -EIO; + } + return dev_status; +} + +/* + * Get the device's status from the device but return a string describing it + * + * Same conditions as iwmx_sdk_get_device_status(). + */ +static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk) +{ + const char *result; + WIMAX_API_DEVICE_STATUS dev_status; + + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) + result = "cannot read device state"; + else + result = iwmx_sdk_dev_status_to_str(dev_status); + return result; +} + +/* + * If the device is connected but we don't know about the network, + * create the knowledge of it. + * + * Asks the WiMAX API to report which NSP we are connected to and we + * create/update a network_el in the device's network list. Then + * return it. + * + * Returns NULL on error. + * + */ +WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk) +{ + WIMAX_API_CONNECTED_NSP_INFO_EX *nsp_info = NULL; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + nsp_info = malloc(sizeof (*nsp_info)); + if (!nsp_info) { + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate NSP info"); + return NULL; + } + + r = GetConnectedNSPEx(&wmxsdk->device_id, nsp_info); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get connected NSP info: %d (%s)", r, errstr); + free (nsp_info); + nsp_info = NULL; + } else { + /* Migth be 0 sometimes; fix that up */ + if (nsp_info->linkQuality == 0) { + int linkq_expected = cinr_to_percentage(nsp_info->CINR - 10); + if (linkq_expected != nsp_info->linkQuality) + nsp_info->linkQuality = linkq_expected; + } + } + + return nsp_info; +} + +/* + * Callback for a RF State command + * + * Called by the WiMAX API when a command sent to change the RF state + * is completed. This is just a confirmation of what happened with the + * command. + * + * We don't do anything, as when the device changes state, the state + * change callback is called and that will fiddle with the NetworkManager + * internals. + */ +static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_RF_STATE rf_state) +{ + nm_log_dbg(LOGD_WIMAX, "rf_state changed to %d", rf_state); +} + +/* + * Turn the radio on or off + * + * First it checks that we are in the right state before doing + * anything; there might be no need to do anything. + * + * Issue a command to the WiMAX API, wait for a callback confirming it + * is done. Sometimes the callback is missed -- in that case, do force + * a state change evaluation. + * + * Frustration note: + * + * Geezoos efing Xist, they make difficult even the most simple + * of the operations + * + * This thing is definitely a pain. If the radio is ON already + * and you switch it on again...well, there is no way to tell + * because you don't get a callback saying it basically + * suceeded. But on the other hand, if the thing was in a + * different state and action needs to be taken, you have to wait + * for a callback to confirm it's done. However, there is also an + * state change callback, which is almost the same, so now you + * have to handle things in two "unrelated" threads of execution. + * + * How the shpx are you expected to tell the difference? Check + * status first? On timeout? Nice gap (eighteen wheeler size) for + * race conditions. + */ +int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state) +{ + int result; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF); + + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + result = -EINVAL; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: + case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: + nm_log_err(LOGD_WIMAX, "wmxsdk: cannot turn on radio: hw switch is off"); + result = -EPERM; + goto error_cant_do; + break; + case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: + if (rf_state == WIMAX_API_RF_OFF) { + result = 0; + nm_log_dbg(LOGD_WIMAX, "radio is already off"); + goto out_done; + } + 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: + if (rf_state == WIMAX_API_RF_ON) { + result = 0; + nm_log_dbg(LOGD_WIMAX, "radio is already on"); + goto out_done; + } + break; + default: + g_assert(1); + } + /* Ok, flip the radio */ + r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot flip radio to %d: %d (%s) [device is in state %s]", + rf_state, r, errstr, iwmx_sdk_get_device_status_str(wmxsdk)); + result = -EIO; + } else + result = -EINPROGRESS; +out_done: +error_cant_do: +error_get_status: + return result; +} + +/* + * Read the cached device status + */ +WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk) +{ + WIMAX_API_DEVICE_STATUS status; + + g_mutex_lock(wmxsdk->status_mutex); + status = wmxsdk->status; + g_mutex_unlock(wmxsdk->status_mutex); + return status; +} + +/* + * Callback for a Connect command + * + * Called by the WiMAX API when a command sent to connect is + * completed. This is just a confirmation of what happened with the + * command. + * + * WE DON'T DO MUCH HERE -- the real meat happens when a state change + * callback is sent, where we detect we move to connected state (or + * from disconnecting to something else); the state change callback is + * called and that will fiddle with the NetworkManager internals. + */ +static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + WIMAX_API_DEVICE_STATUS status; + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + status = iwmxsdk_status_get(wmxsdk); + if (resp == WIMAX_API_CONNECTION_SUCCESS) { + if (status != WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_err(LOGD_WIMAX, "wmxsdk: error: connect worked, but state" + " didn't change (now it is %d [%s])", + status, + iwmx_sdk_dev_status_to_str(status)); + } + } else { + nm_log_err(LOGD_WIMAX, "wmxsdk: failed to connect (status %d: %s)", + status, iwmx_sdk_dev_status_to_str(status)); + } + + _schedule_connect_result(wmxsdk, resp); +} + +/* + * Connect to a network + * + * This function starts the connection process to a given network; + * when the device changes status, the status change callback will + * tell NetworkManager if the network is finally connected or not. + * + * One of the reasons it is done like that is to allow external tools + * to control the device and the plugin just passing the status so + * NetworkManager displays the right info. + */ +int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name) +{ + int result = 0; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_mutex_lock(wmxsdk->connect_mutex); + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmxsdk_status_get(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); + result = -EINVAL; + goto error_cant_do; + 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: + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect: radio is off"); + result = -EPERM; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + break; + case WIMAX_API_DEVICE_STATUS_Connecting: + nm_log_dbg(LOGD_WIMAX, "Connect already pending, waiting for it"); + result = -EINPROGRESS; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Data_Connected: + nm_log_err(LOGD_WIMAX, "wmxsdk: BUG? need to disconnect?"); + result = -EINVAL; + goto error_cant_do; + default: + g_assert(1); + } + + /* Ok, do the connection, wait for a callback */ + r = CmdConnectToNetwork(&wmxsdk->device_id, (void *) nsp_name, 0, 0); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect to network %s: %d (%s) - device is in state '%s'", + nsp_name, r, errstr, + iwmx_sdk_get_device_status_str(wmxsdk)); + result = -EIO; + } + +error_cant_do: +error_get_status: + g_mutex_unlock(wmxsdk->connect_mutex); + return result; +} + +/* + * Callback for a Disconnect command + * + * Called by the WiMAX API when a command sent to connect is + * completed. This is just a confirmation of what happened with the + * command. + * + * When the device changes state, the state change callback is called + * and that will fiddle with the NetworkManager internals. + * + * We just update the result of the command and wake up anybody who is + * waiting for this conditional variable. + */ +static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NETWORK_CONNECTION_RESP resp) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + WIMAX_API_DEVICE_STATUS status; + + status = iwmxsdk_status_get(wmxsdk); + if (resp == WIMAX_API_CONNECTION_SUCCESS) { + if (status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + nm_log_err(LOGD_WIMAX, "wmxsdk: error: disconnect worked, " + "but state didn't change (now it is %d [%s])", status, + iwmx_sdk_dev_status_to_str(status)); + } + } else + nm_log_err(LOGD_WIMAX, "wmxsdk: failed to disconnect (status %d: %s)", + status, iwmx_sdk_dev_status_to_str(status)); +} + +/* + * Disconnect from a network + * + * This function tells the device to disconnect; the state change + * callback will take care of inform NetworkManager's internals. + */ +int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk) +{ + int result; + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + WIMAX_API_DEVICE_STATUS dev_status; + + g_mutex_lock(wmxsdk->connect_mutex); + /* Guess what the current radio state is; if it is ON + * already, don't redo it. */ + dev_status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) dev_status < 0) { + result = dev_status; + goto error_get_status; + } + switch (dev_status) { + case WIMAX_API_DEVICE_STATUS_UnInitialized: + nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); + result = -EINVAL; + goto error_cant_do; + 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: + nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, radio is off; ignoring"); + result = 0; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Ready: + case WIMAX_API_DEVICE_STATUS_Scanning: + nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, already disconnected; ignoring"); + result = 0; + goto error_cant_do; + case WIMAX_API_DEVICE_STATUS_Connecting: + case WIMAX_API_DEVICE_STATUS_Data_Connected: + break; + default: + g_assert(1); + } + /* Ok, flip the radio */ + r = CmdDisconnectFromNetwork(&wmxsdk->device_id); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot disconnect from network: %d (%s)", r, errstr); + result = -EIO; + } else + result = -EINPROGRESS; +error_cant_do: +error_get_status: + g_mutex_unlock(wmxsdk->connect_mutex); + return result; +} + +/* + * Callback for state change messages + * + * Just pass them to the state transition handler + */ +static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_DEVICE_STATUS status, + WIMAX_API_STATUS_REASON reason, + WIMAX_API_CONNECTION_PROGRESS_INFO pi) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + WIMAX_API_DEVICE_STATUS old_status; + + nm_log_dbg(LOGD_WIMAX, "wmxsdk: state change to (%d) %s reason (%d) %s", + status, iwmx_sdk_dev_status_to_str (status), + reason, iwmx_sdk_reason_to_str (reason)); + + g_mutex_lock(wmxsdk->status_mutex); + old_status = wmxsdk->status; + wmxsdk->status = status; + g_mutex_unlock(wmxsdk->status_mutex); + + _schedule_state_change(wmxsdk, status, old_status, reason); +} + +/* + * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results + * are available. + * + * From here we update NetworkManager's idea of which networks are available. + */ +static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size) +{ + struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); + + g_static_mutex_lock(&wmxsdk->network_mutex); + _schedule_scan_result(wmxsdk, nsp_list, nsp_list_size); + g_static_mutex_unlock(&wmxsdk->network_mutex); +} + +/* + * Called by the WiMAX API when we get a wide scan result + * + * We treat them same as wide, so we just call that. + */ +static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size) +{ + __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); +} + +/* + * Called by the WiMAX API when we get a normal (non wide) scan result + * + * We treat them same as wide, so we just call that. + */ +static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id, + WIMAX_API_NSP_INFO_EX *nsp_list, + UINT32 nsp_list_size, UINT32 searchProgress) +{ + __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); +} + +/* + * Called to ask the device to scan for networks + * + * We don't really scan as the WiMAX SDK daemon scans in the + * background for us. We just get the results and hand them back via + * the scan_result_cb callback. + */ +int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk) +{ + int result; + + UINT32 nsp_list_length = 10; + WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */ + + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get network list: %d (%s)", r, errstr); + result = -EIO; + goto error_scan; + } + + if (nsp_list_length == 0) { + nm_log_dbg(LOGD_WIMAX, "no networks"); + } else + __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list, + nsp_list_length); + result = 0; +error_scan: + return result; +} + +/* + * Initialize the WiMAX API, register with it, setup callbacks + * + */ +static int iwmx_sdk_setup(struct wmxsdk *wmxsdk) +{ + int result; + + WIMAX_API_RET r; + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + result = -ENFILE; + + /* device_id initialized by iwmx_sdk_dev_add */ + + r = WiMaxDeviceOpen(&wmxsdk->device_id); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot open device: %d (%s)", r, errstr); + goto error_wimaxdeviceopen; + } + + /* + * We scan in auto mode (in the background) + * + * Otherwise is messy -- if we have NetworkManager triggering a scan + * when we call iwmx_nm_scan() -> iwmx_sdk_scan(), most of the + * times that causes a race condition when the UI asks for a + * scan right before displaying the network menu. As there is + * no way to cancel an ongoing scan before connecting, we are + * stuck. So we do auto bg and have iwmx_sdk_scan() just return + * the current network list. + */ + r = SetConnectionMode(&wmxsdk->device_id, + WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set connectin mode to manual: %d (%s)", r, errstr); + goto error_connection_mode; + } + + r = SubscribeControlPowerManagement(&wmxsdk->device_id, + __iwmx_sdk_rf_state_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to radio change events: %u (%s)", r, errstr); + result = -EIO; + goto error_subscribe_rf_state; + } + + r = SubscribeDeviceStatusChange(&wmxsdk->device_id, + __iwmx_sdk_state_change_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to state chaneg events: %d (%s)", r, errstr); + goto error_subscribe_state_change; + } + + r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id, + __iwmx_sdk_wide_scan_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to wide scan events: %d (%s)", r, errstr); + goto error_subscribe_wide_scan; + } + r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to scan events: %d (%s)", r, errstr); + goto error_subscribe_scan; + } + + r = SubscribeConnectToNetwork(&wmxsdk->device_id, + __iwmx_sdk_connect_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to connect events: %d (%s)", r, errstr); + goto error_subscribe_connect; + } + + r = SubscribeDisconnectToNetwork(&wmxsdk->device_id, + __iwmx_sdk_disconnect_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to disconnect events: %d (%s)", r, errstr); + goto error_subscribe_disconnect; + } + + wmxsdk->status = iwmx_sdk_get_device_status(wmxsdk); + if ((int) wmxsdk->status < 0) + wmxsdk->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + + return 0; + + UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); +error_subscribe_disconnect: + UnsubscribeConnectToNetwork(&wmxsdk->device_id); +error_subscribe_connect: + UnsubscribeNetworkSearchEx(&wmxsdk->device_id); +error_subscribe_scan: + UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); +error_subscribe_wide_scan: + UnsubscribeDeviceStatusChange(&wmxsdk->device_id); +error_subscribe_state_change: + UnsubscribeControlPowerManagement(&wmxsdk->device_id); +error_subscribe_rf_state: +error_connection_mode: + WiMaxDeviceClose(&wmxsdk->device_id); +error_wimaxdeviceopen: + return result; +} + +/* + * Called when a device is torn down + * + * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks, + * unregister from the WiMAX API. + */ +static void iwmx_sdk_remove(struct wmxsdk *wmxsdk) +{ + UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); + UnsubscribeConnectToNetwork(&wmxsdk->device_id); + UnsubscribeNetworkSearchEx(&wmxsdk->device_id); + UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); + UnsubscribeDeviceStatusChange(&wmxsdk->device_id); + UnsubscribeControlPowerManagement(&wmxsdk->device_id); + WiMaxDeviceClose(&wmxsdk->device_id); +} + +void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, + WimaxStateChangeFunc state_change_cb, + WimaxConnectResultFunc connect_result_cb, + WimaxScanResultFunc scan_result_cb, + WimaxRemovedFunc removed_cb, + void *user_data) +{ + wmxsdk->state_change_cb = state_change_cb; + wmxsdk->connect_result_cb = connect_result_cb; + wmxsdk->scan_result_cb = scan_result_cb; + wmxsdk->removed_cb = removed_cb; + wmxsdk->callback_data = user_data; +} + +/* Initialize a [zeroed] struct wmxsdk */ +static struct wmxsdk *wmxsdk_new(void) +{ + struct wmxsdk *wmxsdk; + + wmxsdk = malloc(sizeof(*wmxsdk)); + if (wmxsdk) { + memset(wmxsdk, 0, sizeof(*wmxsdk)); + + wmxsdk->refcount = 1; + g_static_mutex_init(&wmxsdk->network_mutex); + + wmxsdk->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + wmxsdk->status_mutex = g_mutex_new(); + g_assert(wmxsdk->status_mutex); + + wmxsdk->connect_mutex = g_mutex_new(); + g_assert(wmxsdk->connect_mutex); + } + return wmxsdk; +} + +struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk) +{ + g_atomic_int_add(&wmxsdk->refcount, 1); + return wmxsdk; +} + +void wmxsdk_unref(struct wmxsdk *wmxsdk) +{ + if (g_atomic_int_dec_and_test(&wmxsdk->refcount)) { + g_mutex_free(wmxsdk->status_mutex); + g_mutex_free(wmxsdk->connect_mutex); + memset(wmxsdk, 0, sizeof(*wmxsdk)); + free(wmxsdk); + } +} + +static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name) +{ + int ifindex; + struct wmxsdk *wmxsdk; + const char *s; + + if (idx >= IWMX_SDK_DEV_MAX) { + nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); + goto error_bug; + } + if (g_iwmx_sdk_devs[idx] != NULL) { + nm_log_err(LOGD_WIMAX, "BUG! device index %u already enumerated?", idx); + goto error_bug; + } + + wmxsdk = wmxsdk_new(); + if (wmxsdk == NULL) { + nm_log_err(LOGD_WIMAX, "Can't allocate %zu bytes", sizeof(*wmxsdk)); + goto error_bug; + } + + /* + * This depends on a hack in the WiMAX Network Service; it has + * to return, as part of the device name, a string "if:IFNAME" + * where the OS's device name is stored. + */ + s = strstr(name, "if:"); + if (s == NULL + || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) { + nm_log_err(LOGD_WIMAX, "Cannot extract network interface name off '%s'", + name); + goto error_noifname; + } + nm_log_dbg(LOGD_WIMAX, "network interface name: '%s'", wmxsdk->ifname); + + ifindex = if_nametoindex(wmxsdk->ifname); + if (ifindex <= 0) { + nm_log_err(LOGD_WIMAX, "wxmsdk: %s: cannot find interface index", wmxsdk->ifname); + goto error_noifname; + } + + strncpy(wmxsdk->name, name, sizeof(wmxsdk->name)); + wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; + wmxsdk->device_id.deviceIndex = api_idx; + + if (iwmx_sdk_setup(wmxsdk) != 0) { + nm_log_err(LOGD_WIMAX, "wxmsdk: %s: cannot set up interface", wmxsdk->ifname); + goto error_setup; + } + + g_iwmx_sdk_devs[idx] = wmxsdk; + return; + +error_setup: +error_noifname: + wmxsdk_unref(wmxsdk); +error_bug: + return; +} + +static void iwmx_sdk_dev_rm(unsigned idx) +{ + struct wmxsdk *wmxsdk; + + if (idx >= IWMX_SDK_DEV_MAX) { + nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); + return; + } + + wmxsdk = g_iwmx_sdk_devs[idx]; + _schedule_removed(wmxsdk); + iwmx_sdk_remove(wmxsdk); + wmxsdk_unref(wmxsdk); + g_iwmx_sdk_devs[idx] = NULL; +} + +static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid, + BOOL presence) +{ + unsigned int cnt; + WIMAX_API_RET r; + WIMAX_API_HW_DEVICE_ID device_id_list[5]; + UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + nm_log_dbg(LOGD_WIMAX, "cb: handle %u index #%u is %d", devid->sdkHandle, + devid->deviceIndex, presence); + + r = GetListDevice(devid, device_id_list, &device_id_list_size); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(devid, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); + return; + } + + if (device_id_list_size == 0) { + nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); + } else + for (cnt = 0; cnt < device_id_list_size; cnt++) { + WIMAX_API_HW_DEVICE_ID *dev = + device_id_list + cnt; + nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, + dev->deviceIndex, dev->deviceName); + } + if (device_id_list_size < devid->deviceIndex) { + nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", + devid->deviceIndex, device_id_list_size); + return; + } + + if (presence) { + WIMAX_API_HW_DEVICE_ID *dev = + device_id_list + devid->deviceIndex; + iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex, + dev->deviceName); + } else { + iwmx_sdk_dev_rm(devid->deviceIndex); + } +} + +/* + * Initialize the WiMAX API, register with it, setup callbacks for + * device coming up / dissapearing + */ +int iwmx_sdk_api_init(void) +{ + int result; + unsigned int cnt; + WIMAX_API_RET r; + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + WIMAX_API_HW_DEVICE_ID device_id_list[5]; + UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); + + memset(&g_api, 0, sizeof(g_api)); + g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; + + result = -EIO; + r = WiMaxAPIOpen(&g_api); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIOpen failed with %d (%s)", r, errstr); + goto error_wimaxapiopen; + } + + r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: insert/remove subscribe failed with %d (%s)", r, errstr); + goto error_close; + } + + r = GetListDevice(&g_api, device_id_list, &device_id_list_size); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); + goto error_close; + } + if (device_id_list_size < g_api.deviceIndex) { + nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", + g_api.deviceIndex, device_id_list_size); + } + + if (device_id_list_size == 0) { + nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); + } else { + for (cnt = 0; cnt < device_id_list_size; cnt++) { + WIMAX_API_HW_DEVICE_ID *dev = device_id_list + cnt; + nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, dev->deviceIndex, dev->deviceName); + iwmx_sdk_dev_add(cnt, dev->deviceIndex, dev->deviceName); + } + } + return 0; + +error_close: + WiMaxAPIClose(&g_api); +error_wimaxapiopen: + return result; +} + +void iwmx_sdk_api_exit(void) +{ + WIMAX_API_RET r; + + char errstr[512]; + UINT32 errstr_size = sizeof(errstr); + + r = WiMaxAPIClose(&g_api); + if (r != WIMAX_API_RET_SUCCESS) { + GetErrorString(&g_api, r, errstr, &errstr_size); + nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIClose failed with %d (%s)", r, errstr); + } + return; +} diff --git a/src/wimax/iwmxsdk.h b/src/wimax/iwmxsdk.h new file mode 100644 index 0000000000..e065b0a83d --- /dev/null +++ b/src/wimax/iwmxsdk.h @@ -0,0 +1,98 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * + * Copyright (C) 2011 Red Hat, Inc. All rights reserved. + * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef IWMXSDK_H +#define IWMXSDK_H + +#include +#include + +struct wmxsdk; + +typedef void (*WimaxNewWmxsdkFunc) (struct wmxsdk *wmxsdk, void *user_data); + +typedef void (*WimaxStateChangeFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + void *user_data); + +typedef void (*WimaxConnectResultFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP resp, + void *user_data); + +typedef void (*WimaxScanResultFunc) (struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps, + void *user_data); + +typedef void (*WimaxRemovedFunc) (struct wmxsdk *wmxsdk, void *user_data); + +struct wmxsdk { + gint refcount; + + WIMAX_API_DEVICE_ID device_id; + + WimaxStateChangeFunc state_change_cb; + WimaxConnectResultFunc connect_result_cb; + WimaxScanResultFunc scan_result_cb; + WimaxRemovedFunc removed_cb; + void *callback_data; + + GStaticMutex network_mutex; + + WIMAX_API_DEVICE_STATUS status; + GMutex *status_mutex; + + GMutex *connect_mutex; + + char name[100]; + char ifname[16]; +}; + +struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface); + +struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk); +void wmxsdk_unref(struct wmxsdk *wmxsdk); + +/* Register/unregister callbacks when a new wmxsdk is set up */ +void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data); +void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data); + +void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, + WimaxStateChangeFunc state_change_cb, + WimaxConnectResultFunc connect_result_cb, + WimaxScanResultFunc scan_result_cb, + WimaxRemovedFunc removed_cb, + void *user_data); + +WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk); +int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name); +int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk); +WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk); +const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status); +const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason); +int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state); +int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk); +int iwmx_sdk_api_init(void); +void iwmx_sdk_api_exit(void); + +#endif /* IWMXSDK_H */ diff --git a/src/wimax/nm-device-wimax.c b/src/wimax/nm-device-wimax.c new file mode 100644 index 0000000000..ed3120315d --- /dev/null +++ b/src/wimax/nm-device-wimax.c @@ -0,0 +1,1071 @@ +/* -*- 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) 2010 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "nm-device-wimax.h" +#include "nm-wimax-util.h" +#include "nm-logging.h" +#include "nm-device-interface.h" +#include "nm-device-private.h" +#include "nm-system.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" +#include "nm-rfkill.h" +#include "iwmxsdk.h" + +static gboolean impl_device_get_nsp_list (NMDeviceWimax *device, GPtrArray **list, GError **error); + +#include "nm-device-wimax-glue.h" + +static void device_interface_init (NMDeviceInterface *iface_class); + +G_DEFINE_TYPE_EXTENDED (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_ACTIVE_NSP, + + LAST_PROP +}; + +enum { + NSP_ADDED, + NSP_REMOVED, + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_DEVICE_WIMAX, \ + NMDeviceWimaxPrivate)) + +typedef struct { + gboolean disposed; + + struct wmxsdk *sdk; + WIMAX_API_DEVICE_STATUS status; + gboolean connect_failed; + + gboolean enabled; + gboolean wimaxd_enabled; + struct ether_addr hw_addr; + guint activation_timeout_id; + + guint sdk_action_defer_id; + + GSList *nsp_list; + NMWimaxNsp *current_nsp; +} NMDeviceWimaxPrivate; + +/***********************************************************/ + +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; +} + +/***********************************************************/ + +void +nm_device_wimax_get_hw_address (NMDeviceWimax *self, struct ether_addr *addr) +{ + NMDeviceWimaxPrivate *priv; + + g_return_if_fail (NM_IS_DEVICE_WIMAX (self)); + g_return_if_fail (addr != NULL); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr)); +} + +static gboolean +impl_device_get_nsp_list (NMDeviceWimax *self, GPtrArray **nsps, GError **error) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + GSList *iter; + + *nsps = g_ptr_array_sized_new (g_slist_length (priv->nsp_list)); + for (iter = priv->nsp_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 (NMDeviceWimax *self, NMWimaxNsp *new_nsp) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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_DEVICE_WIMAX_ACTIVE_NSP); + + g_free (old_path); +} + +NMWimaxNsp * +nm_device_wimax_get_active_nsp (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), NULL); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->current_nsp; +} + +static gboolean +activation_timed_out (gpointer data) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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 +remove_all_nsps (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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 NMWimaxNsp * +get_nsp_by_name (NMDeviceWimax *self, const char *name) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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 gboolean +update_availability (NMDeviceWimax *self, gboolean old_available) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceState state; + gboolean new_available, changed = FALSE; + + new_available = nm_device_is_available (device); +nm_log_dbg (LOGD_WIMAX, "old_avail %d, new_avail %d", old_available, new_available); + if (new_available == old_available) + return FALSE; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (state == NM_DEVICE_STATE_UNAVAILABLE) { + if (new_available == TRUE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + changed = TRUE; + } + } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { + if (new_available == FALSE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + changed = TRUE; + } + } + + return changed; +} + +/* NMDeviceInterface interface */ + +static void +real_set_enabled (NMDeviceInterface *device, gboolean enabled) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + gboolean old_available; + int ret; + +nm_log_dbg (LOGD_WIMAX, "setting wimax enabled %d (was %d)", enabled, priv->enabled); + if (priv->enabled == enabled) + return; + + old_available = nm_device_is_available (NM_DEVICE (device)); + priv->enabled = enabled; +nm_log_dbg (LOGD_WIMAX, "wimax enabled changed to %d", priv->enabled); + + /* Set the WiMAX device RF state to the current user-specified enabled state */ + if (priv->sdk) { + ret = iwmx_sdk_rf_state_set (priv->sdk, + enabled ? WIMAX_API_RF_ON : WIMAX_API_RF_OFF); + if (ret != -EINPROGRESS) { + nm_log_warn (LOGD_WIMAX, "failed to %s WiMAX radio", + priv->enabled ? "enable" : "disable"); + } + } + + update_availability (self, old_available); +} + +/* NMDevice methods */ + +static void +real_take_down (NMDevice *device) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (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) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (dev); + + if (!priv->enabled || !priv->wimaxd_enabled) + return FALSE; + + 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 *dev) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (dev); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + struct ifreq req; + int fd; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_warn (LOGD_HW, "couldn't open control socket."); + return; + } + + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ); + + errno = 0; + if (ioctl (fd, SIOCGIFHWADDR, &req) < 0) { + nm_log_err (LOGD_HW | LOGD_WIMAX, + "(%s) failed to read hardware address (error %d)", + nm_device_get_iface (dev), errno); + } else { + memcpy (&priv->hw_addr, &req.ifr_hwaddr.sa_data, ETH_ALEN); + g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_HW_ADDRESS); + } + + close (fd); +} + +static gboolean +real_check_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + const char *iface = nm_device_get_iface (device); + + if (!priv->enabled) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled", iface); + return FALSE; + } + + if (!priv->wimaxd_enabled) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled in wimaxd", iface); + return FALSE; + } + + if (!nm_wimax_util_sdk_is_initialized ()) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because WiMAX SDK not initialized", iface); + return FALSE; + } + + if (!priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): not available because not known to WiMAX SDK", iface); + return FALSE; + } + + return iwmxsdk_status_get (priv->sdk) >= WIMAX_API_DEVICE_STATUS_Ready; +} + +static void +clear_activation_timeout (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->activation_timeout_id) { + g_source_remove (priv->activation_timeout_id); + priv->activation_timeout_id = 0; + } + + priv->connect_failed = FALSE; +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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_DEVICE_WIMAX (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) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + NMConnection *connection; + NMSettingWimax *s_wimax; + const char *nsp; + int ret; + + 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); + + nsp = nm_setting_wimax_get_network_name (s_wimax); + g_assert (nsp); + + priv->connect_failed = FALSE; + ret = iwmx_sdk_connect (priv->sdk, nsp); + if (ret != 0) { + nm_log_err (LOGD_WIMAX, "Failed to connect to NSP '%s'", nsp); + *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) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); + WIMAX_API_DEVICE_STATUS status; + int ret; + + clear_activation_timeout (NM_DEVICE_WIMAX (device)); + + set_current_nsp (NM_DEVICE_WIMAX (device), NULL); + + if (priv->sdk) { + /* Read explicit status here just to make sure we have the most + * up-to-date status and to ensure we disconnect if needed. + */ + status = iwmxsdk_status_get (priv->sdk); + if ((int) status < 0) { + nm_log_err (LOGD_WIMAX, "Failed to read WiMAX device status: %d", status); + } else { + if ( status == WIMAX_API_DEVICE_STATUS_Connecting + || status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + ret = iwmx_sdk_disconnect (priv->sdk); + if (ret < 0) { + nm_log_err (LOGD_WIMAX, "Failed to disconnect WiMAX device: %d", ret); + } + } + } + } +} + +/*************************************************************************/ + +static void +wmx_state_change_cb (struct wmxsdk *wmxsdk, + WIMAX_API_DEVICE_STATUS new_status, + WIMAX_API_DEVICE_STATUS old_status, + WIMAX_API_STATUS_REASON reason, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + const char *iface; + gboolean old_available = FALSE; + const char *nsp_name = NULL; + + iface = nm_device_get_iface (NM_DEVICE (self)); + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + old_available = nm_device_is_available (NM_DEVICE (self)); + + priv->status = new_status; + if (priv->current_nsp) + nsp_name = nm_wimax_nsp_get_name (priv->current_nsp); + + nm_log_dbg (LOGD_WIMAX, "(%s): wimax state change %s -> %s (reason %d)", + iface, + iwmx_sdk_dev_status_to_str (old_status), + iwmx_sdk_dev_status_to_str (new_status), + reason); + + switch (new_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: + if (priv->wimaxd_enabled) { + priv->wimaxd_enabled = FALSE; + if (update_availability (self, old_available)) + return; + } + 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: + if (priv->wimaxd_enabled == FALSE) { + priv->wimaxd_enabled = TRUE; + if (update_availability (self, old_available)) + return; + } + break; + default: + nm_log_warn (LOGD_WIMAX, "(%s): unhandled WiMAX device state %d", + iface, new_status); + break; + } + + /* Handle activation success and failure */ + if (IS_ACTIVATING_STATE (state)) { + if (new_status == WIMAX_API_DEVICE_STATUS_Data_Connected) { + /* Success */ + clear_activation_timeout (self); + + nm_log_info (LOGD_WIMAX, "(%s): connected to '%s'", + iface, nsp_name); + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); + return; + } + + if (priv->connect_failed || new_status < WIMAX_API_DEVICE_STATUS_Connecting) { + /* Connection attempt failed */ + nm_log_info (LOGD_WIMAX, "(%s): connection to '%s' failed: (%d) %s", + iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } + } + + /* Handle disconnection */ + if ( old_status == WIMAX_API_DEVICE_STATUS_Data_Connected + && new_status < WIMAX_API_DEVICE_STATUS_Connecting) { + + nm_log_info (LOGD_WIMAX, "(%s): disconnected from '%s': (%d) %s", + iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + } +} + +static void +wmx_connect_result_cb (struct wmxsdk *wmxsdk, + WIMAX_API_NETWORK_CONNECTION_RESP result, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (IS_ACTIVATING_STATE (state)) { + priv->connect_failed = (result == WIMAX_API_CONNECTION_SUCCESS); + /* Wait for the state change so we can get the reason code; we + * cache the connect failure so we don't have to wait for the + * activation timeout. + */ + } +} + +static void +remove_outdated_nsps (NMDeviceWimax *self, + WIMAX_API_NSP_INFO_EX *nsp_list, + guint32 list_size) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_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); + gboolean found = FALSE; + int i; + + for (i = 0; i < list_size; i++) { + 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 void +wmx_scan_result_cb (struct wmxsdk *wmxsdk, + WIMAX_API_NSP_INFO_EX *nsps, + guint num_nsps, + void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + int i; + + remove_outdated_nsps (self, nsps, num_nsps); + + /* Add new NSPs and update existing ones */ + for (i = 0; i < num_nsps; i++) { + WIMAX_API_NSP_INFO_EX *sdk_nsp = &nsps[i]; + const char *nsp_name = (const char *) sdk_nsp->NSPName; + NMWimaxNspNetworkType net_type; + NMWimaxNsp *nsp; + gboolean new_nsp; + + nsp = get_nsp_by_name (self, nsp_name); + new_nsp = (nsp == NULL); + if (new_nsp) { + nsp = nm_wimax_nsp_new (nsp_name); + nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX NSP '%s'", iface, nsp_name); + } + + net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); + g_object_set (nsp, + NM_WIMAX_NSP_SIGNAL_QUALITY, sdk_nsp->linkQuality, + NM_WIMAX_NSP_NETWORK_TYPE, net_type, + NULL); + + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", + iface, nsp_name, sdk_nsp->linkQuality, net_type); + + 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 +wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->sdk) { + /* Clear callbacks just in case we don't hold the last reference */ + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL); + + wmxsdk_unref (priv->sdk); + priv->sdk = NULL; + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } +} + +/*************************************************************************/ + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (new_state < NM_DEVICE_STATE_DISCONNECTED) + remove_all_nsps (self); + + if ( new_state == NM_DEVICE_STATE_DISCONNECTED + && old_state < NM_DEVICE_STATE_DISCONNECTED) { + if (priv->sdk) + iwmx_sdk_get_networks (priv->sdk); + } + + if (new_state == NM_DEVICE_STATE_FAILED || new_state <= NM_DEVICE_STATE_DISCONNECTED) + clear_activation_timeout (self); +} + +/*************************************************************************/ + +static gboolean +sdk_action_defer_cb (gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + + NM_DEVICE_WIMAX_GET_PRIVATE (self)->sdk_action_defer_id = 0; + update_availability (self, FALSE); + return FALSE; +} + +static void +wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + /* If we now have the SDK, schedule an idle handler to start the device up */ + if (!priv->sdk) { + priv->sdk = wmxsdk_ref (sdk); + iwmx_sdk_set_callbacks(priv->sdk, + wmx_state_change_cb, + wmx_connect_result_cb, + wmx_scan_result_cb, + wmx_removed_cb, + self); + + if (!priv->sdk_action_defer_id) + priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self); + } +} + +/*************************************************************************/ + +NMDevice * +nm_device_wimax_new (const char *udi, + const char *iface, + const char *driver) +{ + NMDevice *device; + + g_return_val_if_fail (udi != NULL, NULL); + g_return_val_if_fail (iface != NULL, NULL); + g_return_val_if_fail (driver != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIMAX, + 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_DEVICE_INTERFACE_RFKILL_TYPE, RFKILL_TYPE_WIMAX, + NULL); + if (device) { + struct wmxsdk *sdk; + + nm_wimax_util_sdk_ref (); + g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), NULL); + + /* See if the SDK already knows about this interface */ + sdk = iwmx_sdk_get_wmxsdk_for_iface (iface); + if (sdk) + wmx_new_sdk_cb (sdk, device); + + /* If it doesn't, we want to be notified when it does */ + iwmx_sdk_new_callback_register (wmx_new_sdk_cb, device); + } + + return device; +} + +static void +device_interface_init (NMDeviceInterface *iface_class) +{ + iface_class->set_enabled = real_set_enabled; +} + +static void +nm_device_wimax_init (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + 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) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + struct ether_addr hw_addr; + + switch (prop_id) { + case PROP_HW_ADDRESS: + nm_device_wimax_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 +dispose (GObject *object) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->disposed) + goto done; + + priv->disposed = TRUE; + + clear_activation_timeout (self); + + if (priv->sdk_action_defer_id) + g_source_remove (priv->sdk_action_defer_id); + + if (priv->sdk) { + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL); + wmxsdk_unref (priv->sdk); + } + + set_current_nsp (self, NULL); + + g_slist_foreach (priv->nsp_list, (GFunc) g_object_unref, NULL); + g_slist_free (priv->nsp_list); + + iwmx_sdk_new_callback_unregister (wmx_new_sdk_cb, self); + nm_wimax_util_sdk_unref (); + +done: + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); +} + +static void +nm_device_wimax_class_init (NMDeviceWimaxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceWimaxPrivate)); + + /* Virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + + 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_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIMAX_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_DEVICE_WIMAX_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 (NMDeviceWimaxClass, 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 (NMDeviceWimaxClass, 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 (NMDeviceWimaxClass, properties_changed)); + + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_wimax_object_info); + + dbus_g_error_domain_register (NM_WIMAX_ERROR, NULL, NM_TYPE_WIMAX_ERROR); +} diff --git a/src/wimax/nm-device-wimax.h b/src/wimax/nm-device-wimax.h new file mode 100644 index 0000000000..9dbe149e22 --- /dev/null +++ b/src/wimax/nm-device-wimax.h @@ -0,0 +1,68 @@ +/* -*- 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) 2010 Red Hat, Inc. + * Copyright (C) 2009 Novell, Inc. + */ + +#ifndef NM_DEVICE_WIMAX_H +#define NM_DEVICE_WIMAX_H + +#include +#include +#include "nm-device.h" +#include "nm-wimax-nsp.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) +#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) +#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) +#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIMAX)) +#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) + +#define NM_DEVICE_WIMAX_HW_ADDRESS "hw-address" +#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" + +typedef struct { + NMDevice parent; +} NMDeviceWimax; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*nsp_added) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); + void (*nsp_removed) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); + void (*properties_changed) (NMDeviceWimax *wimax, GHashTable *properties); +} NMDeviceWimaxClass; + +GType nm_device_wimax_get_type (void); + +NMDevice *nm_device_wimax_new (const char *udi, + const char *iface, + const char *driver); + +void nm_device_wimax_get_hw_address (NMDeviceWimax *self, + struct ether_addr *addr); + +NMWimaxNsp *nm_device_wimax_get_active_nsp (NMDeviceWimax *self); + +G_END_DECLS + +#endif /* NM_DEVICE_WIMAX_H */ diff --git a/src/wimax/nm-wimax-device.c b/src/wimax/nm-wimax-device.c deleted file mode 100644 index a98bee7d40..0000000000 --- a/src/wimax/nm-wimax-device.c +++ /dev/null @@ -1,1037 +0,0 @@ -/* -*- 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 "nm-system.h" -#include "NetworkManagerUtils.h" -#include "nm-properties-changed-signal.h" -#include "nm-connection.h" -#include "nm-setting-connection.h" -#include "nm-setting-wimax.h" -#include "nm-utils.h" - -static gboolean impl_device_get_nsp_list (NMWimaxDevice *device, GPtrArray **list, GError **error); - -#include "nm-wimax-device-glue.h" - -static void device_interface_init (NMDeviceInterface *iface_class); - -G_DEFINE_TYPE_EXTENDED (NMWimaxDevice, nm_wimax_device, NM_TYPE_DEVICE, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) - -enum { - PROP_0, - PROP_INDEX, - 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 { - WIMAX_API_DEVICE_ID device_id; - NMWimaxDevice *object; - - gboolean enabled; - struct ether_addr hw_addr; - 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, - 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, - 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)); -} - -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: - if (enable) - /* Already matches */ - goto out; - break; - default: - nm_warning ("Unhandled WiMAX device state"); - goto out; - } - - g_debug ("Changing wimax device RF state: %d", enable); - result = CmdControlPowerManagement (&priv->device_id, enable ? WIMAX_API_RF_ON : WIMAX_API_RF_OFF); - if (result != WIMAX_API_RET_SUCCESS) - nm_wimax_util_error (&priv->device_id, "WiMax device RF change failed", result); - - out: - return FALSE; -} - -static void -schedule_rf_state_update (NMWimaxDevice *self) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - - /* This is scheduled because on startup we get nm_device_interface_set_enabled() - while the device state is still unmanaged. It'll change to unavailable right - after it, so it would result in enabling RF kill, followed by disabling it again. - Pretty lame. - */ - - if (priv->rf_update_id == 0) - priv->rf_update_id = g_idle_add ((GSourceFunc) rf_state_update, self); -} - -GSList * -nm_wimax_device_get_nsps (NMWimaxDevice *self) -{ - g_return_val_if_fail (NM_IS_WIMAX_DEVICE (self), NULL); - - return GET_PRIVATE (self)->nsp_list; -} - -static gboolean -impl_device_get_nsp_list (NMWimaxDevice *device, GPtrArray **nsps, GError **error) -{ - GSList *list; - GSList *iter; - - list = nm_wimax_device_get_nsps (device); - *nsps = g_ptr_array_sized_new (g_slist_length (list)); - for (iter = list; iter; iter = iter->next) { - const char *path; - - path = nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)); - if (path) - g_ptr_array_add (*nsps, g_strdup (path)); - } - - return TRUE; -} - -static void -set_current_nsp (NMWimaxDevice *self, NMWimaxNsp *new_nsp) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - NMWimaxNsp *old_nsp; - char *old_path = NULL; - - old_nsp = priv->current_nsp; - if (old_nsp) { - old_path = g_strdup (nm_wimax_nsp_get_dbus_path (old_nsp)); - priv->current_nsp = NULL; - } - - if (new_nsp) - priv->current_nsp = g_object_ref (new_nsp); - - if (old_nsp) - g_object_unref (old_nsp); - - /* Only notify if it's really changed */ - if ((!old_path && new_nsp) - || (old_path && !new_nsp) - || (old_path && new_nsp && strcmp (old_path, nm_wimax_nsp_get_dbus_path (new_nsp)))) - g_object_notify (G_OBJECT (self), NM_WIMAX_DEVICE_ACTIVE_NSP); - - g_free (old_path); -} - -NMWimaxNsp * -nm_wimax_device_get_active_nsp (NMWimaxDevice *self) -{ - g_return_val_if_fail (NM_IS_WIMAX_DEVICE (self), NULL); - - return GET_PRIVATE (self)->current_nsp; -} - -static gboolean -activation_timed_out (gpointer data) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (data); - - priv->activation_timeout_id = 0; - nm_device_state_changed (NM_DEVICE (data), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - - return FALSE; -} - -static void -wimax_status_change_cb (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: - 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, - 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++) { - 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 (WIMAX_API_DEVICE_ID *device_id, - 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++) { - 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 (WIMAX_API_DEVICE_ID *device_id, - 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 (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 (WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_NETWORK_CONNECTION_RESP response) -{ - if (response == WIMAX_API_CONNECTION_SUCCESS) { - } else { - g_warning ("WiMax device disconnect failed"); - } -} - -static void -nm_wimax_api_close (NMWimaxDevice *self) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - - nm_debug ("Closing wimax device API"); - - UnsubscribeDisconnectToNetwork (&priv->device_id); - UnsubscribeConnectToNetwork (&priv->device_id); - UnsubscribeNetworkSearchWideScanEx (&priv->device_id); - UnsubscribeNetworkSearchEx (&priv->device_id); - UnsubscribeDeviceStatusChange (&priv->device_id); - WiMaxDeviceClose (&priv->device_id); -} - -static gboolean -nm_wimax_api_open (NMWimaxDevice *self) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - WIMAX_API_RET result; - gboolean success = FALSE; - - nm_debug ("Opening wimax device API"); - - result = WiMaxDeviceOpen (&priv->device_id); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax device open failed", result); - goto err; - } - - result = SetConnectionMode (&priv->device_id, WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax device connection mode setting failed", result); - goto err; - } - - result = SubscribeDeviceStatusChange (&priv->device_id, wimax_status_change_cb); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax subscription to device status changes failed", result); - goto err; - } - - result = SubscribeNetworkSearchEx (&priv->device_id, wimax_scan_cb); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax subscription to network scanning failed", result); - goto err; - } - - result = SubscribeNetworkSearchWideScanEx (&priv->device_id, wimax_wide_scan_cb); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax subscription to wide network scanning failed", result); - goto err; - } - - result = SubscribeConnectToNetwork (&priv->device_id, wimax_connect_cb); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax subscription to connected messages failed", result); - goto err; - } - - result = SubscribeDisconnectToNetwork (&priv->device_id, wimax_disconnect_cb); - if (result != WIMAX_API_RET_SUCCESS) { - nm_wimax_util_error (&priv->device_id, "WiMax subscription to disconnected messages failed", result); - goto err; - } - - success = TRUE; - - err: - if (!success) - nm_wimax_api_close (self); - - return success; -} - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMWimaxDevice *self = NM_WIMAX_DEVICE (device); - - switch (new_state) { - case NM_DEVICE_STATE_UNMANAGED: - case NM_DEVICE_STATE_UNAVAILABLE: - case NM_DEVICE_STATE_DISCONNECTED: - remove_all_nsps (self); - schedule_rf_state_update (self); - break; - default: - break; - } -} - -/* NMDeviceInterface interface */ - -static void -real_set_enabled (NMDeviceInterface *device, gboolean enabled) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (device); - - if (priv->enabled == enabled) - return; - - priv->enabled = enabled; - schedule_rf_state_update (NM_WIMAX_DEVICE (device)); -} - -/* NMDevice methods */ - -static void -real_take_down (NMDevice *device) -{ - NMWimaxDevice *self = NM_WIMAX_DEVICE (device); - - set_current_nsp (self, NULL); - remove_all_nsps (self); -} - -static gboolean -real_hw_is_up (NMDevice *device) -{ - return nm_system_device_is_up (device); -} - -static gboolean -real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) -{ - return nm_system_device_set_up_down (dev, TRUE, no_firmware); -} - -static void -real_hw_take_down (NMDevice *dev) -{ - nm_system_device_set_up_down (dev, FALSE, NULL); -} - -static void -real_update_hw_address (NMDevice *device) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (device); - 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_WSTRING) 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) { - - result = CmdDisconnectFromNetwork (&priv->device_id); - if (result != WIMAX_API_RET_SUCCESS) - nm_wimax_util_error (&priv->device_id, "WiMax disconnect from network failed", result); - } -} - -/* GObject methods */ - -static void -device_interface_init (NMDeviceInterface *iface_class) -{ - iface_class->set_enabled = real_set_enabled; -} - -static void -nm_wimax_device_init (NMWimaxDevice *self) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - - priv->object = self; - priv->device_id.structureSize = sizeof (NMWimaxDevicePrivate); - priv->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; - - g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), NULL); -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMWimaxDevicePrivate *priv; - - object = G_OBJECT_CLASS (nm_wimax_device_parent_class)->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - priv = GET_PRIVATE (object); - if (priv->device_id.deviceIndex == 0) { - g_warning ("Invalid or missing constructor arguments"); - g_object_unref (object); - object = NULL; - } - - if (!nm_wimax_api_open (NM_WIMAX_DEVICE (object))) { - g_object_unref (object); - object = NULL; - } - - return object; -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMWimaxDevicePrivate *priv = GET_PRIVATE (object); - - switch (prop_id) { - case PROP_INDEX: - priv->device_id.deviceIndex = g_value_get_uchar (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMWimaxDevice *self = NM_WIMAX_DEVICE (object); - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - struct ether_addr hw_addr; - - switch (prop_id) { - case PROP_HW_ADDRESS: - nm_wimax_device_get_hw_address (self, &hw_addr); - g_value_take_string (value, nm_ether_ntop (&hw_addr)); - break; - case PROP_ACTIVE_NSP: - if (priv->current_nsp) - g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp)); - else - g_value_set_boxed (value, "/"); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -finalize (GObject *object) -{ - NMWimaxDevice *self = NM_WIMAX_DEVICE (object); - NMWimaxDevicePrivate *priv = GET_PRIVATE (self); - - if (priv->rf_update_id) - g_source_remove (priv->rf_update_id); - - set_current_nsp (self, NULL); - - g_slist_foreach (priv->nsp_list, (GFunc) g_object_unref, NULL); - g_slist_free (priv->nsp_list); - - nm_wimax_api_close (self); - - G_OBJECT_CLASS (nm_wimax_device_parent_class)->finalize (object); -} - -static void -nm_wimax_device_class_init (NMWimaxDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMWimaxDevicePrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - device_class->take_down = real_take_down; - device_class->hw_is_up = real_hw_is_up; - device_class->hw_bring_up = real_hw_bring_up; - device_class->hw_take_down = real_hw_take_down; - device_class->update_hw_address = real_update_hw_address; - device_class->check_connection_compatible = real_check_connection_compatible; - device_class->get_best_auto_connection = real_get_best_auto_connection; - device_class->get_generic_capabilities = real_get_generic_capabilities; - device_class->is_available = real_is_available; - device_class->act_stage1_prepare = real_act_stage1_prepare; - device_class->act_stage2_config = real_act_stage2_config; - device_class->deactivate_quickly = real_deactivate_quickly; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_INDEX, - g_param_spec_uchar (NM_WIMAX_DEVICE_INDEX, - "Index", - "Index", - 0, 1, 0, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_WIMAX_DEVICE_HW_ADDRESS, - "MAC Address", - "Hardware MAC address", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_ACTIVE_NSP, - g_param_spec_boxed (NM_WIMAX_DEVICE_ACTIVE_NSP, - "Active NSP", - "Currently active NSP", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE)); - - /* Signals */ - signals[NSP_ADDED] = - g_signal_new ("nsp-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMWimaxDeviceClass, nsp_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[NSP_REMOVED] = - g_signal_new ("nsp-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMWimaxDeviceClass, nsp_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, G_STRUCT_OFFSET (NMWimaxDeviceClass, properties_changed)); - - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_wimax_device_object_info); - - dbus_g_error_domain_register (NM_WIMAX_ERROR, NULL, NM_TYPE_WIMAX_ERROR); -} diff --git a/src/wimax/nm-wimax-device.h b/src/wimax/nm-wimax-device.h deleted file mode 100644 index f461dad73c..0000000000 --- a/src/wimax/nm-wimax-device.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- 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_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, - guchar wimax_device_index); - -void nm_wimax_device_get_hw_address (NMWimaxDevice *self, - struct ether_addr *addr); - -GSList *nm_wimax_device_get_nsps (NMWimaxDevice *self); -NMWimaxNsp *nm_wimax_device_get_active_nsp (NMWimaxDevice *self); - -G_END_DECLS - -#endif /* NM_WIMAX_DEVICE_H */ diff --git a/src/wimax/nm-wimax-manager.c b/src/wimax/nm-wimax-manager.c index e571f96d9d..c058ae9012 100644 --- a/src/wimax/nm-wimax-manager.c +++ b/src/wimax/nm-wimax-manager.c @@ -15,120 +15,81 @@ * 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. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ -#include -#include -#include - #include "nm-wimax-manager.h" -#include "nm-wimax-device.h" -#include "nm-wimax-util.h" +#include "nm-logging.h" +#include "iwmxsdk.h" + +G_DEFINE_TYPE (NMWimaxManager, nm_wimax_manager, G_TYPE_OBJECT) + +#define NM_WIMAX_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_WIMAX_MANAGER, \ + NMWimaxManagerPrivate)) typedef struct { - WIMAX_API_DEVICE_ID device_id; - int refs; -} NMWimaxManager; + gboolean disposed; -static NMWimaxManager *global_wimax_manager = NULL; + gboolean sdk_initialized; +} NMWimaxManagerPrivate; -static NMWimaxManager * +/***************************************************/ + +/*************************************************************/ + +NMWimaxManager * nm_wimax_manager_get (void) { - WIMAX_API_RET result; + static NMWimaxManager *singleton = NULL; - if (!global_wimax_manager) { - global_wimax_manager = g_new (NMWimaxManager, 1); - global_wimax_manager->refs = 1; + if (!singleton) + singleton = NM_WIMAX_MANAGER (g_object_new (NM_TYPE_WIMAX_MANAGER, NULL)); + else + g_object_ref (singleton); - 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; + g_assert (singleton); + return singleton; } static void -nm_wimax_manager_unref (NMWimaxManager *manager) +nm_wimax_manager_init (NMWimaxManager *self) { - if (--manager->refs == 0) { - g_debug ("Closing WiMAX API"); - WiMaxAPIClose (&manager->device_id); - g_free (manager); - global_wimax_manager = NULL; + NMWimaxManagerPrivate *priv = NM_WIMAX_MANAGER_GET_PRIVATE (self); + int ret; + + ret = iwmx_sdk_api_init(); + if (ret != 0) { + nm_log_warn (LOGD_WIMAX, "Failed to initialize WiMAX: %d", ret); + return; } + + priv->sdk_initialized = TRUE; } -static gboolean -wimax_device_matches (WIMAX_API_HW_DEVICE_ID *hw_id, - const char *ifname) +static void +dispose (GObject *object) { - const char *device_name; - char *s; - char hw_ifname[16]; + NMWimaxManagerPrivate *priv = NM_WIMAX_MANAGER_GET_PRIVATE (object); - if (!hw_id) - return FALSE; + if (!priv->disposed) { + priv->disposed = TRUE; - device_name = (const char *) hw_id->deviceName; - if (!device_name) - return FALSE; + if (priv->sdk_initialized) + iwmx_sdk_api_exit (); + } - 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; - - return TRUE; + G_OBJECT_CLASS (nm_wimax_manager_parent_class)->dispose (object); } -NMDevice * -nm_wimax_manager_create_device (const char *path, - const char *ifname, - const char *driver) +static void +nm_wimax_manager_class_init (NMWimaxManagerClass *wimax_class) { - NMWimaxManager *manager; - WIMAX_API_HW_DEVICE_ID device_id_list[5]; - NMDevice *device = NULL; - guint32 device_id_list_size = 5; - WIMAX_API_RET result; + GObjectClass *object_class = G_OBJECT_CLASS (wimax_class); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (ifname != NULL, NULL); - g_return_val_if_fail (driver != NULL, NULL); + g_type_class_add_private (wimax_class, sizeof (NMWimaxManagerPrivate)); - 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)) { - device = nm_wimax_device_new (path, ifname, driver, device_id_list[0].deviceIndex); - break; - } - } - } else - nm_wimax_util_error (&manager->device_id, "Could not get WiMax device list", result); - - if (device) - g_object_weak_ref (G_OBJECT (device), (GWeakNotify) nm_wimax_manager_unref, manager); - else - nm_wimax_manager_unref (manager); - - return device; + /* virtual methods */ + object_class->dispose = dispose; } + diff --git a/src/wimax/nm-wimax-manager.h b/src/wimax/nm-wimax-manager.h index c3b2881ce5..6277370bf7 100644 --- a/src/wimax/nm-wimax-manager.h +++ b/src/wimax/nm-wimax-manager.h @@ -15,16 +15,36 @@ * 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. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #ifndef NM_WIMAX_MANAGER_H #define NM_WIMAX_MANAGER_H -#include "nm-device.h" +#include +#include -NMDevice *nm_wimax_manager_create_device (const char *path, - const char *ifname, - const char *driver); +#define NM_TYPE_WIMAX_MANAGER (nm_wimax_manager_get_type ()) +#define NM_WIMAX_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_MANAGER, NMWimaxManager)) +#define NM_WIMAX_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_MANAGER, NMWimaxManagerClass)) +#define NM_IS_WIMAX_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_MANAGER)) +#define NM_IS_WIMAX_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_WIMAX_MANAGER)) +#define NM_WIMAX_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_MANAGER, NMWimaxManagerClass)) + +#define NM_WIMAX_MANAGER_DEVICE_ADDED "device-added" +#define NM_WIMAX_MANAGER_DEVICE_REMOVED "device-removed" + +typedef struct { + GObject parent; +} NMWimaxManager; + +typedef struct { + GObjectClass parent; +} NMWimaxManagerClass; + +GType nm_wimax_manager_get_type (void); + +NMWimaxManager *nm_wimax_manager_get (void); #endif /* NM_WIMAX_MANAGER_H */ + diff --git a/src/wimax/nm-wimax-util.c b/src/wimax/nm-wimax-util.c index fcb11f1dc8..bca25a1dbf 100644 --- a/src/wimax/nm-wimax-util.c +++ b/src/wimax/nm-wimax-util.c @@ -21,21 +21,41 @@ #include #include "nm-wimax-util.h" #include "nm-utils.h" +#include "iwmxsdk.h" +#include "nm-logging.h" + +static guint sdk_refcount = 0; void -nm_wimax_util_error (WIMAX_API_DEVICE_ID *device_id, - const char *message, - WIMAX_API_RET result) +nm_wimax_util_sdk_ref (void) { - char *warning_msg; - char str[MAX_SIZE_OF_STRING_BUFFER]; - guint32 str_len = MAX_SIZE_OF_STRING_BUFFER; + int ret = 0; - 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); -} + if (sdk_refcount == 0) { + ret = iwmx_sdk_api_init (); + if (ret != 0) { + nm_log_warn (LOGD_WIMAX, "Failed to initialize WiMAX: %d", ret); + return; + } + } + sdk_refcount++; +} + +gboolean +nm_wimax_util_sdk_is_initialized (void) +{ + return sdk_refcount > 0; +} + +void +nm_wimax_util_sdk_unref (void) +{ + g_return_if_fail (sdk_refcount > 0); + + sdk_refcount--; + if (sdk_refcount == 0) + iwmx_sdk_api_exit (); +} NMWimaxNspNetworkType nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type) @@ -60,56 +80,3 @@ nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type) 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"; - } - - return "Unknown device state"; -} diff --git a/src/wimax/nm-wimax-util.h b/src/wimax/nm-wimax-util.h index 30c5bb68e6..71f5aa29d2 100644 --- a/src/wimax/nm-wimax-util.h +++ b/src/wimax/nm-wimax-util.h @@ -21,17 +21,18 @@ #ifndef NM_WIMAX_UTIL_H #define NM_WIMAX_UTIL_H +#include + #include #include #include "nm-wimax-types.h" -void nm_wimax_util_error (WIMAX_API_DEVICE_ID *device_id, - const char *message, - WIMAX_API_RET result); +void nm_wimax_util_sdk_ref (void); + +gboolean nm_wimax_util_sdk_is_initialized (void); + +void nm_wimax_util_sdk_unref (void); 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 54b7fcbbe9..e161bc7664 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -199,13 +199,13 @@ wimax_network_type_to_str (NMWimaxNspNetworkType type) { switch (type) { case NM_WIMAX_NSP_NETWORK_TYPE_HOME: - return "Home network"; + return "Home"; case NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: - return "Partner network"; + return "Partner"; case NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: - return "Roaming partner network"; + return "Roaming"; default: - return "Unknown network"; + return "Unknown"; } } @@ -225,11 +225,11 @@ detail_nsp (gpointer data, gpointer user_data) 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)); + data_str = g_strdup_printf ("%d%% (%s)", + nm_wimax_nsp_get_signal_quality (nsp), + wimax_network_type_to_str (nm_wimax_nsp_get_network_type (nsp))); - print_string (label, data); + print_string (label, data_str); g_free (label); g_free (data_str); } @@ -379,7 +379,7 @@ 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)) + else if (NM_IS_DEVICE_WIMAX (device)) print_string ("Type", "WiMAX"); print_string ("Driver", nm_device_get_driver (device) ? nm_device_get_driver (device) : "(unknown)"); @@ -396,8 +396,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))); + else if (NM_IS_DEVICE_WIMAX (device)) + tmp = g_strdup (nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device))); if (tmp) { print_string ("HW Address", tmp); @@ -463,19 +463,19 @@ detail_device (gpointer data, gpointer user_data) print_string (" Carrier", "on"); else print_string (" Carrier", "off"); - } else if (NM_IS_WIMAX_DEVICE (device)) { + } else if (NM_IS_DEVICE_WIMAX (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_nsp = nm_device_wimax_get_active_nsp (NM_DEVICE_WIMAX (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)); + nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device)); if (nsps && nsps->len) g_ptr_array_foreach ((GPtrArray *) nsps, detail_nsp, (gpointer) active_name); }