diff --git a/include/NetworkManager.h b/include/NetworkManager.h
index b25cfbc2ba..ce2a81b228 100644
--- a/include/NetworkManager.h
+++ b/include/NetworkManager.h
@@ -366,6 +366,9 @@ typedef enum {
/* The supplicant is now available */
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
+ /* The modem could not be found */
+ NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND,
+
/* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason;
diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml
index c23b596c4b..49b77a5ba0 100644
--- a/introspection/nm-device.xml
+++ b/introspection/nm-device.xml
@@ -392,7 +392,12 @@
The 802.1x supplicant is now available.
-
+
+
+ The modem could not be found.
+
+
+
diff --git a/marshallers/nm-marshal.list b/marshallers/nm-marshal.list
index 36e0fbe6d0..e19f8befcf 100644
--- a/marshallers/nm-marshal.list
+++ b/marshallers/nm-marshal.list
@@ -21,6 +21,9 @@ VOID:OBJECT,OBJECT,ENUM
VOID:POINTER,STRING
VOID:STRING,BOXED
BOOLEAN:POINTER,STRING,BOOLEAN,UINT,STRING,STRING
+VOID:STRING,BOOLEAN,UINT,STRING,STRING
BOOLEAN:VOID
VOID:STRING,BOOLEAN
+VOID:STRING,OBJECT,POINTER
+VOID:BOOLEAN,UINT
diff --git a/src/Makefile.am b/src/Makefile.am
index db255ca357..a1505002bf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -76,6 +76,10 @@ NetworkManager_SOURCES = \
nm-device-olpc-mesh.h \
nm-device-bt.c \
nm-device-bt.h \
+ nm-device-cdma.c \
+ nm-device-cdma.h \
+ nm-device-gsm.c \
+ nm-device-gsm.h \
NetworkManagerAP.c \
NetworkManagerAP.h \
nm-dbus-manager.h \
@@ -155,6 +159,12 @@ nm-dhcp4-config-glue.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml
nm-dhcp6-config-glue.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-server --output=$@ $<
+nm-device-cdma-glue.h: $(top_srcdir)/introspection/nm-device-cdma.xml
+ dbus-binding-tool --prefix=nm_device_cdma --mode=glib-server --output=$@ $<
+
+nm-device-gsm-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml
+ dbus-binding-tool --prefix=nm_device_gsm --mode=glib-server --output=$@ $<
+
BUILT_SOURCES = \
nm-access-point-glue.h \
nm-manager-glue.h \
@@ -163,6 +173,8 @@ BUILT_SOURCES = \
nm-device-wifi-glue.h \
nm-device-olpc-mesh-glue.h \
nm-device-bt-glue.h \
+ nm-device-cdma-glue.h \
+ nm-device-gsm-glue.h \
nm-ip4-config-glue.h \
nm-ip6-config-glue.h \
nm-active-connection-glue.h \
diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am
index fef879ac44..932a041c0d 100644
--- a/src/modem-manager/Makefile.am
+++ b/src/modem-manager/Makefile.am
@@ -7,12 +7,12 @@ INCLUDES = \
noinst_LTLIBRARIES = libmodem-manager.la
libmodem_manager_la_SOURCES = \
+ nm-modem.c \
+ nm-modem.h \
nm-modem-cdma.c \
nm-modem-cdma.h \
nm-modem-gsm.c \
nm-modem-gsm.h \
- nm-modem.c \
- nm-modem.h \
nm-modem-manager.h \
nm-modem-manager.c \
nm-modem-types.h
@@ -24,18 +24,10 @@ libmodem_manager_la_LIBADD = \
$(top_builddir)/marshallers/libmarshallers.la \
$(DBUS_LIBS)
-nm-device-cdma-glue.h: $(top_srcdir)/introspection/nm-device-cdma.xml
- dbus-binding-tool --prefix=nm_device_cdma --mode=glib-server --output=$@ $<
-
-nm-device-gsm-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml
- dbus-binding-tool --prefix=nm_device_gsm --mode=glib-server --output=$@ $<
-
nm-serial-device-glue.h: $(top_srcdir)/introspection/nm-device-serial.xml
dbus-binding-tool --prefix=nm_serial_device --mode=glib-server --output=$@ $<
BUILT_SOURCES = \
- nm-device-cdma-glue.h \
- nm-device-gsm-glue.h \
nm-serial-device-glue.h
CLEANFILES = $(BUILT_SOURCES)
diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c
index 5e8405bcf4..f2a04dc076 100644
--- a/src/modem-manager/nm-modem-cdma.c
+++ b/src/modem-manager/nm-modem-cdma.c
@@ -24,18 +24,23 @@
#include "nm-dbus-glib-types.h"
#include "nm-modem-cdma.h"
#include "nm-modem-types.h"
-#include "nm-device-interface.h"
-#include "nm-device-private.h"
+#include "nm-device.h"
#include "nm-dbus-manager.h"
#include "nm-setting-connection.h"
#include "nm-setting-cdma.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
-#include "nm-device-cdma-glue.h"
-
G_DEFINE_TYPE (NMModemCdma, nm_modem_cdma, NM_TYPE_MODEM)
+#define NM_MODEM_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_CDMA, NMModemCdmaPrivate))
+
+typedef struct {
+ DBusGProxyCall *call;
+
+ GHashTable *connect_properties;
+} NMModemCdmaPrivate;
+
typedef enum {
NM_CDMA_ERROR_CONNECTION_NOT_CDMA = 0,
@@ -79,43 +84,77 @@ nm_cdma_error_get_type (void)
}
-NMDevice *
+NMModem *
nm_modem_cdma_new (const char *path,
const char *device,
const char *data_device,
- const char *driver)
+ guint32 ip_method)
{
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (data_device != NULL, NULL);
- g_return_val_if_fail (driver != NULL, NULL);
- return (NMDevice *) g_object_new (NM_TYPE_MODEM_CDMA,
- NM_DEVICE_INTERFACE_UDI, path,
- NM_DEVICE_INTERFACE_IFACE, data_device,
- NM_DEVICE_INTERFACE_DRIVER, driver,
- NM_MODEM_PATH, path,
- NM_MODEM_DEVICE, device,
- NM_DEVICE_INTERFACE_TYPE_DESC, "CDMA",
- NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA,
- NULL);
+ return (NMModem *) g_object_new (NM_TYPE_MODEM_CDMA,
+ NM_MODEM_PATH, path,
+ NM_MODEM_DEVICE, device,
+ NM_MODEM_IFACE, data_device,
+ NM_MODEM_IP_METHOD, ip_method,
+ NULL);
}
static void
-stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
+ NMModemCdma *self = NM_MODEM_CDMA (user_data);
+ NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self);
GError *error = NULL;
- dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID);
- if (!error)
- nm_device_activate_schedule_stage2_device_config (device);
+ priv->call = NULL;
+
+ if (priv->connect_properties) {
+ g_hash_table_destroy (priv->connect_properties);
+ priv->connect_properties = NULL;
+ }
+
+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE);
else {
- nm_warning ("CDMA modem connection failed: (%d) %s",
+ nm_warning ("CDMA connection failed: (%d) %s",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE);
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_NONE);
+ }
+}
+
+static void
+do_connect (NMModemCdma *self)
+{
+ NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self);
+ DBusGProxy *proxy;
+
+ proxy = nm_modem_get_proxy (NM_MODEM (self), MM_DBUS_INTERFACE_MODEM_SIMPLE);
+ priv->call = dbus_g_proxy_begin_call_with_timeout (proxy,
+ "Connect", stage1_prepare_done,
+ self, NULL, 120000,
+ DBUS_TYPE_G_MAP_OF_VARIANT, priv->connect_properties,
+ G_TYPE_INVALID);
+}
+
+static void
+stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+ NMModemCdma *self = NM_MODEM_CDMA (user_data);
+ GError *error = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID))
+ do_connect (self);
+ else {
+ nm_warning ("CDMA modem enable failed: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_error_free (error);
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
}
}
@@ -136,61 +175,48 @@ create_connect_properties (NMConnection *connection)
return properties;
}
-static void
-do_connect (NMModem *modem)
+static NMActStageReturn
+real_act_stage1_prepare (NMModem *modem,
+ NMActRequest *req,
+ GPtrArray **out_hints,
+ const char **out_setting_name,
+ NMDeviceStateReason *reason)
{
+ NMModemCdma *self = NM_MODEM_CDMA (modem);
+ NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self);
NMConnection *connection;
- GHashTable *properties;
- connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem)));
+ connection = nm_act_request_get_connection (req);
g_assert (connection);
- properties = create_connect_properties (connection);
- dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE),
- "Connect", stage1_prepare_done,
- modem, NULL, 120000,
- DBUS_TYPE_G_MAP_OF_VARIANT, properties,
- G_TYPE_INVALID);
- g_hash_table_destroy (properties);
-}
+ *out_setting_name = nm_connection_need_secrets (connection, out_hints);
+ if (!*out_setting_name) {
+ gboolean enabled = nm_modem_get_mm_enabled (modem);
+ DBusGProxy *proxy;
-static void
-stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
- NMDevice *device = NM_DEVICE (user_data);
- GError *error = NULL;
+ if (priv->connect_properties)
+ g_hash_table_destroy (priv->connect_properties);
+ priv->connect_properties = create_connect_properties (connection);
- if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID))
- do_connect (NM_MODEM (device));
- else {
- nm_warning ("CDMA modem enable failed: (%d) %s",
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_error_free (error);
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE);
- }
-}
-
-static NMActStageReturn
-real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
-{
- gboolean enabled = nm_modem_get_mm_enabled (NM_MODEM (device));
-
- if (enabled)
- do_connect (NM_MODEM (device));
- else {
- dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM),
- "Enable", stage1_enable_done,
- device, NULL, 20000,
- G_TYPE_BOOLEAN, TRUE,
- G_TYPE_INVALID);
+ if (enabled)
+ do_connect (self);
+ else {
+ proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM);
+ dbus_g_proxy_begin_call_with_timeout (proxy,
+ "Enable", stage1_enable_done,
+ modem, NULL, 20000,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_INVALID);
+ }
+ } else {
+ /* NMModem will handle requesting secrets... */
}
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMConnection *
-real_get_best_auto_connection (NMDevice *dev,
+real_get_best_auto_connection (NMModem *modem,
GSList *connections,
char **specific_object)
{
@@ -214,71 +240,8 @@ real_get_best_auto_connection (NMDevice *dev,
return NULL;
}
-static void
-real_connection_secrets_updated (NMDevice *dev,
- NMConnection *connection,
- GSList *updated_settings,
- RequestSecretsCaller caller)
-{
- NMActRequest *req;
- gboolean found = FALSE;
- GSList *iter;
-
- g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (dev)));
-
- if (caller == SECRETS_CALLER_PPP) {
- NMPPPManager *ppp_manager;
- NMSettingCdma *s_cdma = NULL;
-
- ppp_manager = nm_modem_get_ppp_manager (NM_MODEM (dev));
- g_return_if_fail (ppp_manager != NULL);
-
- s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
- if (!s_cdma) {
- /* Shouldn't ever happen */
- nm_ppp_manager_update_secrets (ppp_manager,
- nm_device_get_iface (dev),
- NULL,
- NULL,
- "missing CDMA setting; no secrets could be found.");
- } else {
- const char *username = nm_setting_cdma_get_username (s_cdma);
- const char *password = nm_setting_cdma_get_password (s_cdma);
-
- nm_ppp_manager_update_secrets (ppp_manager,
- nm_device_get_iface (dev),
- username ? username : "",
- password ? password : "",
- NULL);
- }
- return;
- }
-
- g_return_if_fail (caller == SECRETS_CALLER_CDMA);
- g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
-
- for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
- const char *setting_name = (const char *) iter->data;
-
- if (!strcmp (setting_name, NM_SETTING_CDMA_SETTING_NAME))
- found = TRUE;
- else
- nm_warning ("Ignoring updated secrets for setting '%s'.", setting_name);
- }
-
- if (!found)
- return;
-
- req = nm_device_get_act_request (dev);
- g_assert (req);
-
- g_return_if_fail (nm_act_request_get_connection (req) == connection);
-
- nm_device_activate_schedule_stage1_device_prepare (dev);
-}
-
static gboolean
-real_check_connection_compatible (NMDevice *device,
+real_check_connection_compatible (NMModem *modem,
NMConnection *connection,
GError **error)
{
@@ -306,15 +269,46 @@ real_check_connection_compatible (NMDevice *device,
return TRUE;
}
-static const char *
-real_get_ppp_name (NMModem *device, NMConnection *connection)
+static gboolean
+real_get_user_pass (NMModem *modem,
+ NMConnection *connection,
+ const char **user,
+ const char **pass)
{
NMSettingCdma *s_cdma;
s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
- g_assert (s_cdma);
+ if (!s_cdma)
+ return FALSE;
- return nm_setting_cdma_get_username (s_cdma);
+ if (user)
+ *user = nm_setting_cdma_get_username (s_cdma);
+ if (pass)
+ *pass = nm_setting_cdma_get_password (s_cdma);
+
+ return TRUE;
+}
+
+static const char *
+real_get_setting_name (NMModem *modem)
+{
+ return NM_SETTING_CDMA_SETTING_NAME;
+}
+
+static void
+real_deactivate_quickly (NMModem *modem, NMDevice *device)
+{
+ NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (modem);
+
+ if (priv->call) {
+ DBusGProxy *proxy;
+
+ proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE);
+ dbus_g_proxy_cancel_call (proxy, priv->call);
+ priv->call = NULL;
+ }
+
+ NM_MODEM_CLASS (nm_modem_cdma_parent_class)->deactivate_quickly (modem, device);
}
/*****************************************************************************/
@@ -324,22 +318,34 @@ nm_modem_cdma_init (NMModemCdma *self)
{
}
+static void
+dispose (GObject *object)
+{
+ NMModemCdma *self = NM_MODEM_CDMA (object);
+ NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self);
+
+ if (priv->connect_properties)
+ g_hash_table_destroy (priv->connect_properties);
+
+ G_OBJECT_CLASS (nm_modem_cdma_parent_class)->dispose (object);
+}
+
static void
nm_modem_cdma_class_init (NMModemCdmaClass *klass)
{
- NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMModemClass *modem_class = NM_MODEM_CLASS (klass);
+ g_type_class_add_private (object_class, sizeof (NMModemCdmaPrivate));
+
/* Virtual methods */
- device_class->get_best_auto_connection = real_get_best_auto_connection;
- device_class->connection_secrets_updated = real_connection_secrets_updated;
- device_class->act_stage1_prepare = real_act_stage1_prepare;
- device_class->check_connection_compatible = real_check_connection_compatible;
-
- modem_class->get_ppp_name = real_get_ppp_name;
-
- dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
- &dbus_glib_nm_device_cdma_object_info);
+ object_class->dispose = dispose;
+ modem_class->get_user_pass = real_get_user_pass;
+ modem_class->get_setting_name = real_get_setting_name;
+ modem_class->get_best_auto_connection = real_get_best_auto_connection;
+ modem_class->check_connection_compatible = real_check_connection_compatible;
+ modem_class->act_stage1_prepare = real_act_stage1_prepare;
+ modem_class->deactivate_quickly = real_deactivate_quickly;
dbus_g_error_domain_register (NM_CDMA_ERROR, NULL, NM_TYPE_CDMA_ERROR);
}
diff --git a/src/modem-manager/nm-modem-cdma.h b/src/modem-manager/nm-modem-cdma.h
index 7c98ab287a..0abe4e0cfa 100644
--- a/src/modem-manager/nm-modem-cdma.h
+++ b/src/modem-manager/nm-modem-cdma.h
@@ -46,10 +46,10 @@ typedef struct {
GType nm_modem_cdma_get_type (void);
-NMDevice *nm_modem_cdma_new (const char *path,
- const char *device,
- const char *data_device,
- const char *driver);
+NMModem *nm_modem_cdma_new (const char *path,
+ const char *device,
+ const char *data_device,
+ guint32 ip_method);
G_END_DECLS
diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c
index fcc811fc4c..a7bd361c0d 100644
--- a/src/modem-manager/nm-modem-gsm.c
+++ b/src/modem-manager/nm-modem-gsm.c
@@ -22,16 +22,13 @@
#include
#include "nm-dbus-glib-types.h"
#include "nm-modem-gsm.h"
-#include "nm-device-private.h"
-#include "nm-device-interface.h"
+#include "nm-device.h"
#include "nm-setting-connection.h"
#include "nm-setting-gsm.h"
#include "nm-modem-types.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
-#include "nm-device-gsm-glue.h"
-
typedef enum {
MM_MODEM_GSM_MODE_UNKNOWN = 0x00000000,
MM_MODEM_GSM_MODE_ANY = 0x00000001,
@@ -50,11 +47,17 @@ typedef enum {
} MMModemGsmMode;
-#define GSM_SECRETS_TRIES "gsm-secrets-tries"
-#define PIN_TRIES "pin-tries"
-
G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM)
+#define NM_MODEM_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_GSM, NMModemGsmPrivate))
+
+typedef struct {
+ DBusGProxyCall *call;
+
+ GHashTable *connect_properties;
+ guint32 pin_tries;
+} NMModemGsmPrivate;
+
typedef enum {
NM_GSM_ERROR_CONNECTION_NOT_GSM = 0,
@@ -98,28 +101,22 @@ nm_gsm_error_get_type (void)
}
-NMDevice *
+NMModem *
nm_modem_gsm_new (const char *path,
const char *device,
const char *data_device,
- const char *driver,
guint32 ip_method)
{
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (data_device != NULL, NULL);
- g_return_val_if_fail (driver != NULL, NULL);
- return (NMDevice *) g_object_new (NM_TYPE_MODEM_GSM,
- NM_DEVICE_INTERFACE_UDI, path,
- NM_DEVICE_INTERFACE_IFACE, data_device,
- NM_DEVICE_INTERFACE_DRIVER, driver,
- NM_MODEM_PATH, path,
- NM_MODEM_IP_METHOD, ip_method,
- NM_MODEM_DEVICE, device,
- NM_DEVICE_INTERFACE_TYPE_DESC, "GSM",
- NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM,
- NULL);
+ return (NMModem *) g_object_new (NM_TYPE_MODEM_GSM,
+ NM_MODEM_PATH, path,
+ NM_MODEM_DEVICE, device,
+ NM_MODEM_IFACE, data_device,
+ NM_MODEM_IP_METHOD, ip_method,
+ NULL);
}
static NMDeviceStateReason
@@ -158,93 +155,159 @@ translate_mm_error (GError *error)
}
static void
-clear_pin (NMDevice *device)
+ask_for_pin (NMModemGsm *self, gboolean always_ask)
{
- NMActRequest *req;
- NMConnection *connection;
- NMSettingGsm *setting;
-
- req = nm_device_get_act_request (device);
- g_assert (req);
- connection = nm_act_request_get_connection (req);
- g_assert (connection);
- setting = NM_SETTING_GSM (nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM));
- g_assert (setting);
-
- g_object_set (G_OBJECT (setting), NM_SETTING_GSM_PIN, NULL, NULL);
-}
-
-static void
-request_secrets (NMDevice *device,
- const char *setting_name,
- const char *hint1,
- const char *hint2,
- const char *tries_tag,
- gboolean always_ask)
-{
- NMActRequest *req;
- NMConnection *connection;
+ NMModemGsmPrivate *priv;
guint32 tries = 0;
- g_return_if_fail (device != NULL);
- g_return_if_fail (hint1 || hint2);
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (NM_IS_MODEM_GSM (self));
- req = nm_device_get_act_request (device);
- g_assert (req);
- connection = nm_act_request_get_connection (req);
- g_assert (connection);
-
- nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
+ priv = NM_MODEM_GSM_GET_PRIVATE (self);
if (!always_ask)
- tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), tries_tag));
+ tries = priv->pin_tries++;
- nm_act_request_get_secrets (req,
- setting_name ? setting_name : NM_SETTING_GSM_SETTING_NAME,
- (tries || always_ask) ? TRUE : FALSE,
- SECRETS_CALLER_GSM,
- hint1,
- hint2);
-
- if (!always_ask)
- g_object_set_data (G_OBJECT (connection), tries_tag, GUINT_TO_POINTER (++tries));
+ g_signal_emit_by_name (self, NM_MODEM_NEED_AUTH,
+ NM_SETTING_GSM_SETTING_NAME,
+ (tries || always_ask) ? TRUE : FALSE,
+ SECRETS_CALLER_MOBILE_BROADBAND,
+ NM_SETTING_GSM_PIN,
+ NULL);
}
static void
-stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
+ NMModemGsm *self = NM_MODEM_GSM (user_data);
+ NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
GError *error = NULL;
- dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID);
- if (!error)
- nm_device_activate_schedule_stage2_device_config (device);
- else {
- const char *required_secret = NULL;
- gboolean retry_secret = FALSE;
+ priv->call = NULL;
- if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) {
- clear_pin (device);
- required_secret = NM_SETTING_GSM_PIN;
- } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) {
- clear_pin (device);
- required_secret = NM_SETTING_GSM_PIN;
- retry_secret = TRUE;
- } else {
- nm_warning ("GSM modem connection failed: (%d) %s",
+ if (priv->connect_properties) {
+ g_hash_table_destroy (priv->connect_properties);
+ priv->connect_properties = NULL;
+ }
+
+ if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE);
+ else {
+ if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN))
+ ask_for_pin (self, FALSE);
+ else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG))
+ ask_for_pin (self, TRUE);
+ else {
+ nm_warning ("GSM connection failed: (%d) %s",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
- }
- if (required_secret)
- request_secrets (device, NULL, required_secret, NULL, PIN_TRIES, retry_secret);
- else
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, translate_mm_error (error));
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error));
+ }
g_error_free (error);
}
}
+static void
+do_connect (NMModemGsm *self)
+{
+ NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
+ DBusGProxy *proxy;
+
+ proxy = nm_modem_get_proxy (NM_MODEM (self), MM_DBUS_INTERFACE_MODEM_SIMPLE);
+ dbus_g_proxy_begin_call_with_timeout (proxy,
+ "Connect", stage1_prepare_done,
+ self, NULL, 120000,
+ DBUS_TYPE_G_MAP_OF_VARIANT, priv->connect_properties,
+ G_TYPE_INVALID);
+}
+
+static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data);
+
+static void
+do_enable (NMModemGsm *self)
+{
+ DBusGProxy *proxy;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (NM_IS_MODEM_GSM (self));
+
+ proxy = nm_modem_get_proxy (NM_MODEM (self), MM_DBUS_INTERFACE_MODEM);
+ dbus_g_proxy_begin_call_with_timeout (proxy,
+ "Enable", stage1_enable_done,
+ self, NULL, 20000,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_INVALID);
+}
+
+static void
+stage1_pin_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+ NMModemGsm *self = NM_MODEM_GSM (user_data);
+ GError *error = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) {
+ /* Success; go back and try the enable again */
+ do_enable (self);
+ } else {
+ nm_warning ("GSM PIN unlock failed: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_error_free (error);
+
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
+ }
+}
+
+static void
+handle_enable_pin_required (NMModemGsm *self)
+{
+ NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
+ const char *pin = NULL;
+ GValue *value;
+ DBusGProxy *proxy;
+
+ /* See if we have a PIN already */
+ value = g_hash_table_lookup (priv->connect_properties, "pin");
+ if (value && G_VALUE_HOLDS_STRING (value))
+ pin = g_value_get_string (value);
+
+ /* If we do, send it */
+ if (pin) {
+ proxy = nm_modem_get_proxy (NM_MODEM (self), MM_DBUS_INTERFACE_MODEM_GSM_CARD);
+ dbus_g_proxy_begin_call_with_timeout (proxy,
+ "SendPin", stage1_pin_done,
+ self, NULL, 10000,
+ G_TYPE_STRING, pin,
+ G_TYPE_INVALID);
+ } else
+ ask_for_pin (self, FALSE);
+}
+
+static void
+stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+ NMModemGsm *self = NM_MODEM_GSM (user_data);
+ GError *error = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID))
+ do_connect (self);
+ else {
+ nm_warning ("GSM modem enable failed: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+
+ if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN))
+ handle_enable_pin_required (self);
+ else
+ g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
+
+ g_error_free (error);
+ }
+}
+
+
static GHashTable *
create_connect_properties (NMConnection *connection)
{
@@ -301,149 +364,41 @@ create_connect_properties (NMConnection *connection)
return properties;
}
-static void
-do_connect (NMModem *modem)
-{
- NMConnection *connection;
- GHashTable *properties;
-
- connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem)));
- g_assert (connection);
-
- properties = create_connect_properties (connection);
- dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE),
- "Connect", stage1_prepare_done,
- modem, NULL, 120000,
- DBUS_TYPE_G_MAP_OF_VARIANT, properties,
- G_TYPE_INVALID);
- g_hash_table_destroy (properties);
-}
-
-static void
-stage1_pin_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
- NMDevice *device = NM_DEVICE (user_data);
- GError *error = NULL;
-
- if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) {
- /* Success; go back and try the enable again */
- nm_device_activate_schedule_stage1_device_prepare (device);
- } else {
- nm_warning ("GSM PIN unlock failed: (%d) %s",
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_error_free (error);
-
- clear_pin (device);
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED);
- }
-}
-
-static void
-handle_enable_pin_required (NMDevice *device)
-{
- NMActRequest *req;
- NMConnection *connection;
- NMSettingGsm *s_gsm;
- const char *pin = NULL;
-
- req = nm_device_get_act_request (device);
- g_assert (req);
- connection = nm_act_request_get_connection (req);
- g_assert (connection);
-
- /* See if we have a PIN already */
- s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
- if (s_gsm)
- pin = nm_setting_gsm_get_pin (s_gsm);
-
- /* If we do, send it */
- if (pin) {
- NMModem *modem = NM_MODEM (device);
-
- dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_CARD),
- "SendPin", stage1_pin_done,
- modem, NULL, 10000,
- G_TYPE_STRING, pin,
- G_TYPE_INVALID);
- } else {
- /* Otherwise try to get the PIN */
- request_secrets (device, NULL, NM_SETTING_GSM_PIN, NULL, PIN_TRIES, FALSE);
- }
-}
-
-static void
-stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
-{
- NMDevice *device = NM_DEVICE (user_data);
- GError *error = NULL;
-
- if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID))
- do_connect (NM_MODEM (device));
- else {
- nm_warning ("GSM modem enable failed: (%d) %s",
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
-
- if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN))
- handle_enable_pin_required (device);
- else
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, translate_mm_error (error));
-
- g_error_free (error);
- }
-}
-
static NMActStageReturn
-real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
+real_act_stage1_prepare (NMModem *modem,
+ NMActRequest *req,
+ GPtrArray **out_hints,
+ const char **out_setting_name,
+ NMDeviceStateReason *reason)
{
- NMActRequest *req;
+ NMModemGsm *self = NM_MODEM_GSM (modem);
+ NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
NMConnection *connection;
- const char *setting_name;
- GPtrArray *hints = NULL;
- const char *hint1 = NULL, *hint2 = NULL;
- req = nm_device_get_act_request (device);
- g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
- setting_name = nm_connection_need_secrets (connection, &hints);
- if (!setting_name) {
- NMModem *modem = NM_MODEM (device);
+ *out_setting_name = nm_connection_need_secrets (connection, out_hints);
+ if (!*out_setting_name) {
gboolean enabled = nm_modem_get_mm_enabled (modem);
+ if (priv->connect_properties)
+ g_hash_table_destroy (priv->connect_properties);
+ priv->connect_properties = create_connect_properties (connection);
+
if (enabled)
- do_connect (modem);
- else {
- dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM),
- "Enable", stage1_enable_done,
- modem, NULL, 20000,
- G_TYPE_BOOLEAN, TRUE,
- G_TYPE_INVALID);
- }
-
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ do_connect (self);
+ else
+ do_enable (self);
+ } else {
+ /* NMModem will handle requesting secrets... */
}
- /* Get the required secrets */
- if (hints) {
- if (hints->len > 0)
- hint1 = g_ptr_array_index (hints, 0);
- if (hints->len > 1)
- hint2 = g_ptr_array_index (hints, 1);
- }
-
- request_secrets (device, setting_name, hint1, hint2, GSM_SECRETS_TRIES, FALSE);
-
- if (hints)
- g_ptr_array_free (hints, TRUE);
-
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMConnection *
-real_get_best_auto_connection (NMDevice *dev,
+real_get_best_auto_connection (NMModem *modem,
GSList *connections,
char **specific_object)
{
@@ -467,112 +422,8 @@ real_get_best_auto_connection (NMDevice *dev,
return NULL;
}
-static void
-real_connection_secrets_updated (NMDevice *dev,
- NMConnection *connection,
- GSList *updated_settings,
- RequestSecretsCaller caller)
-{
- NMActRequest *req;
- gboolean found = FALSE;
- GSList *iter;
-
- g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (dev)));
-
- if (caller == SECRETS_CALLER_PPP) {
- NMPPPManager *ppp_manager;
- NMSettingGsm *s_gsm = NULL;
-
- ppp_manager = nm_modem_get_ppp_manager (NM_MODEM (dev));
- g_return_if_fail (ppp_manager != NULL);
-
- s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
- if (!s_gsm) {
- /* Shouldn't ever happen */
- nm_ppp_manager_update_secrets (ppp_manager,
- nm_device_get_iface (dev),
- NULL,
- NULL,
- "missing GSM setting; no secrets could be found.");
- } else {
- const char *username = nm_setting_gsm_get_username (s_gsm);
- const char *password = nm_setting_gsm_get_password (s_gsm);
-
- nm_ppp_manager_update_secrets (ppp_manager,
- nm_device_get_iface (dev),
- username ? username : "",
- password ? password : "",
- NULL);
- }
- return;
- }
-
- g_return_if_fail (caller == SECRETS_CALLER_GSM);
- g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
-
- for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
- const char *setting_name = (const char *) iter->data;
-
- if (!strcmp (setting_name, NM_SETTING_GSM_SETTING_NAME))
- found = TRUE;
- else
- nm_warning ("Ignoring updated secrets for setting '%s'.", setting_name);
- }
-
- if (!found)
- return;
-
- req = nm_device_get_act_request (dev);
- g_assert (req);
-
- g_return_if_fail (nm_act_request_get_connection (req) == connection);
-
- nm_device_activate_schedule_stage1_device_prepare (dev);
-}
-
-static NMActStageReturn
-real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
-{
- NMActRequest *req;
- NMConnection *connection;
-
- req = nm_device_get_act_request (device);
- g_assert (req);
-
- /* Clear secrets tries counter since secrets were successfully used
- * already if we get here.
- */
- connection = nm_act_request_get_connection (req);
- g_assert (connection);
- g_object_set_data (G_OBJECT (connection), GSM_SECRETS_TRIES, NULL);
-
- if (NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->act_stage2_config)
- return NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->act_stage2_config (device, reason);
-
- return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-static void
-real_deactivate_quickly (NMDevice *device)
-{
- NMActRequest *req;
- NMConnection *connection;
-
- req = nm_device_get_act_request (device);
- if (req) {
- /* Clear the secrets attempts counter */
- connection = nm_act_request_get_connection (req);
- g_assert (connection);
- g_object_set_data (G_OBJECT (connection), GSM_SECRETS_TRIES, NULL);
- g_object_set_data (G_OBJECT (connection), PIN_TRIES, NULL);
- }
-
- if (NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly)
- NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly (device);
-}
-
static gboolean
-real_check_connection_compatible (NMDevice *device,
+real_check_connection_compatible (NMModem *modem,
NMConnection *connection,
GError **error)
{
@@ -600,17 +451,51 @@ real_check_connection_compatible (NMDevice *device,
return TRUE;
}
-static const char *
-real_get_ppp_name (NMModem *device, NMConnection *connection)
+static gboolean
+real_get_user_pass (NMModem *modem,
+ NMConnection *connection,
+ const char **user,
+ const char **pass)
{
NMSettingGsm *s_gsm;
s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
- g_assert (s_gsm);
+ if (!s_gsm)
+ return FALSE;
- return nm_setting_gsm_get_username (s_gsm);
+ if (user)
+ *user = nm_setting_gsm_get_username (s_gsm);
+ if (pass)
+ *pass = nm_setting_gsm_get_password (s_gsm);
+
+ return TRUE;
}
+static const char *
+real_get_setting_name (NMModem *modem)
+{
+ return NM_SETTING_GSM_SETTING_NAME;
+}
+
+static void
+real_deactivate_quickly (NMModem *modem, NMDevice *device)
+{
+ NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (modem);
+
+ if (priv->call) {
+ DBusGProxy *proxy;
+
+ proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE);
+ dbus_g_proxy_cancel_call (proxy, priv->call);
+ priv->call = NULL;
+ }
+
+ priv->pin_tries = 0;
+
+ NM_MODEM_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly (modem, device);
+}
+
+
/*****************************************************************************/
static void
@@ -618,24 +503,34 @@ nm_modem_gsm_init (NMModemGsm *self)
{
}
+static void
+dispose (GObject *object)
+{
+ NMModemGsm *self = NM_MODEM_GSM (object);
+ NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
+
+ if (priv->connect_properties)
+ g_hash_table_destroy (priv->connect_properties);
+
+ G_OBJECT_CLASS (nm_modem_gsm_parent_class)->dispose (object);
+}
+
static void
nm_modem_gsm_class_init (NMModemGsmClass *klass)
{
- NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMModemClass *modem_class = NM_MODEM_CLASS (klass);
+ g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate));
+
/* Virtual methods */
- device_class->get_best_auto_connection = real_get_best_auto_connection;
- device_class->connection_secrets_updated = real_connection_secrets_updated;
- 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;
- device_class->check_connection_compatible = real_check_connection_compatible;
-
- modem_class->get_ppp_name = real_get_ppp_name;
-
- dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
- &dbus_glib_nm_device_gsm_object_info);
+ object_class->dispose = dispose;
+ modem_class->get_user_pass = real_get_user_pass;
+ modem_class->get_setting_name = real_get_setting_name;
+ modem_class->get_best_auto_connection = real_get_best_auto_connection;
+ modem_class->check_connection_compatible = real_check_connection_compatible;
+ modem_class->act_stage1_prepare = real_act_stage1_prepare;
+ modem_class->deactivate_quickly = real_deactivate_quickly;
dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR);
}
diff --git a/src/modem-manager/nm-modem-gsm.h b/src/modem-manager/nm-modem-gsm.h
index 84794739f9..f481bdb817 100644
--- a/src/modem-manager/nm-modem-gsm.h
+++ b/src/modem-manager/nm-modem-gsm.h
@@ -46,11 +46,10 @@ typedef struct {
GType nm_modem_gsm_get_type (void);
-NMDevice *nm_modem_gsm_new (const char *path,
- const char *device,
- const char *data_device,
- const char *driver,
- guint32 ip_method);
+NMModem *nm_modem_gsm_new (const char *path,
+ const char *device,
+ const char *data_device,
+ guint32 ip_method);
G_END_DECLS
diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c
index 94e1a111b3..6a7de07ef9 100644
--- a/src/modem-manager/nm-modem-manager.c
+++ b/src/modem-manager/nm-modem-manager.c
@@ -28,6 +28,7 @@
#include "nm-dbus-manager.h"
#include "nm-utils.h"
#include "nm-modem-types.h"
+#include "nm-marshal.h"
#define MODEM_POKE_INTERVAL 120
@@ -44,8 +45,8 @@ typedef struct {
} NMModemManagerPrivate;
enum {
- DEVICE_ADDED,
- DEVICE_REMOVED,
+ MODEM_ADDED,
+ MODEM_REMOVED,
LAST_SIGNAL
};
@@ -67,25 +68,6 @@ nm_modem_manager_get (void)
return singleton;
}
-gboolean
-nm_modem_manager_has_modem_for_iface (NMModemManager *manager,
- const gchar *iface)
-{
- NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager);
- GList *iter;
- g_assert (manager);
- g_assert (NM_IS_MODEM_MANAGER(manager));
- g_assert (iface);
-
- for (iter = g_hash_table_get_values(priv->modems); iter != NULL; iter = iter->next) {
- NMDevice *device = NM_DEVICE(iter->data);
- const gchar *device_iface = nm_device_get_iface (device);
- if (!g_strcmp0 (iface, device_iface))
- return TRUE;
- }
- return FALSE;
-}
-
static gboolean
get_modem_properties (DBusGConnection *connection,
const char *path,
@@ -182,7 +164,7 @@ static void
create_modem (NMModemManager *manager, const char *path)
{
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager);
- NMDevice *device;
+ NMModem *modem;
char *data_device = NULL, *driver = NULL, *master_device = NULL;
uint modem_type = MM_MODEM_TYPE_UNKNOWN;
uint ip_method = MM_MODEM_IP_METHOD_PPP;
@@ -218,19 +200,20 @@ create_modem (NMModemManager *manager, const char *path)
}
if (modem_type == MM_MODEM_TYPE_GSM)
- device = nm_modem_gsm_new (path, master_device, data_device, driver, ip_method);
+ modem = nm_modem_gsm_new (path, master_device, data_device, ip_method);
else if (modem_type == MM_MODEM_TYPE_CDMA)
- device = nm_modem_cdma_new (path, master_device, data_device, driver);
+ modem = nm_modem_cdma_new (path, master_device, data_device, ip_method);
else
g_error ("Invalid modem type");
g_free (data_device);
- g_free (driver);
- if (device) {
- g_hash_table_insert (priv->modems, g_strdup (path), device);
- g_signal_emit (manager, signals[DEVICE_ADDED], 0, device);
+ if (modem) {
+ g_hash_table_insert (priv->modems, g_strdup (path), modem);
+ g_signal_emit (manager, signals[MODEM_ADDED], 0, modem, driver);
}
+
+ g_free (driver);
}
static void
@@ -247,7 +230,7 @@ modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
modem = (NMModem *) g_hash_table_lookup (priv->modems, path);
if (modem) {
- g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, modem);
+ g_signal_emit (user_data, signals[MODEM_REMOVED], 0, modem);
g_hash_table_remove (priv->modems, path);
}
}
@@ -330,7 +313,7 @@ modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices)
static gboolean
remove_one_modem (gpointer key, gpointer value, gpointer user_data)
{
- g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, value);
+ g_signal_emit (user_data, signals[MODEM_REMOVED], 0, value);
return TRUE;
}
@@ -440,23 +423,21 @@ nm_modem_manager_class_init (NMModemManagerClass *klass)
object_class->dispose = dispose;
/* signals */
- signals[DEVICE_ADDED] =
- g_signal_new ("device-added",
+ signals[MODEM_ADDED] =
+ g_signal_new ("modem-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (NMModemManagerClass, device_added),
+ G_STRUCT_OFFSET (NMModemManagerClass, modem_added),
NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- G_TYPE_OBJECT);
+ _nm_marshal_VOID__OBJECT_STRING,
+ G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING);
- signals[DEVICE_REMOVED] =
- g_signal_new ("device-removed",
+ signals[MODEM_REMOVED] =
+ g_signal_new ("modem-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (NMModemManagerClass, device_removed),
+ G_STRUCT_OFFSET (NMModemManagerClass, modem_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- G_TYPE_OBJECT);
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
}
diff --git a/src/modem-manager/nm-modem-manager.h b/src/modem-manager/nm-modem-manager.h
index f9d8ded015..56427baf0d 100644
--- a/src/modem-manager/nm-modem-manager.h
+++ b/src/modem-manager/nm-modem-manager.h
@@ -24,7 +24,7 @@
#define NM_MODEM_MANAGER_H
#include
-#include "nm-device.h"
+#include "nm-modem.h"
#define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ())
#define NM_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_MANAGER, NMModemManager))
@@ -41,18 +41,13 @@ typedef struct {
GObjectClass parent;
/* Signals */
- void (*device_added) (NMModemManager *manager,
- NMDevice *device);
+ void (*modem_added) (NMModemManager *manager, NMModem *modem, const char *driver);
- void (*device_removed) (NMModemManager *manager,
- NMDevice *device);
+ void (*modem_removed) (NMModemManager *manager, NMModem *modem);
} NMModemManagerClass;
GType nm_modem_manager_get_type (void);
NMModemManager *nm_modem_manager_get (void);
-gboolean nm_modem_manager_has_modem_for_iface (NMModemManager *manager,
- const gchar *iface);
-
#endif /* NM_MODEM_MANAGER_H */
diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c
index 5b001eec52..40a76b1db5 100644
--- a/src/modem-manager/nm-modem.c
+++ b/src/modem-manager/nm-modem.c
@@ -21,31 +21,28 @@
#include
#include "nm-modem.h"
-#include "nm-device-private.h"
#include "NetworkManagerSystem.h"
-#include "nm-device-interface.h"
#include "nm-dbus-manager.h"
#include "nm-setting-connection.h"
-#include "nm-setting-gsm.h"
-#include "nm-setting-cdma.h"
#include "nm-marshal.h"
#include "nm-properties-changed-signal.h"
#include "nm-modem-types.h"
#include "nm-utils.h"
-#include "nm-serial-device-glue.h"
#include "NetworkManagerUtils.h"
+#include "nm-device-private.h"
+#include "nm-device-interface.h"
#include "nm-dbus-glib-types.h"
-static void device_interface_init (NMDeviceInterface *iface_class);
+#include "nm-serial-device-glue.h"
-G_DEFINE_TYPE_EXTENDED (NMModem, nm_modem, NM_TYPE_DEVICE, 0,
- G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init))
+G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT)
#define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate))
enum {
PROP_0,
PROP_DEVICE,
+ PROP_IFACE,
PROP_PATH,
PROP_IP_METHOD,
PROP_ENABLED,
@@ -63,6 +60,11 @@ typedef struct {
NMIP4Config *pending_ip4_config;
guint32 ip_method;
char *device;
+ char *iface;
+
+ guint32 secrets_tries;
+
+ DBusGProxyCall *call;
gboolean mm_enabled;
@@ -73,7 +75,10 @@ typedef struct {
enum {
PPP_STATS,
- PROPERTIES_CHANGED,
+ PPP_FAILED,
+ PREPARE_RESULT,
+ IP4_CONFIG_RESULT,
+ NEED_AUTH,
LAST_SIGNAL
};
@@ -120,17 +125,19 @@ nm_modem_get_proxy (NMModem *self,
return priv->proxy;
}
-const char *
-nm_modem_get_ppp_name (NMModem *self,
- NMConnection *connection)
+static void
+merge_ip4_config (NMActRequest *req, NMIP4Config *config)
{
- g_return_val_if_fail (NM_IS_MODEM (self), NULL);
- g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+ NMConnection *connection;
+ NMSettingIP4Config *s_ip4;
- if (NM_MODEM_GET_CLASS (self)->get_ppp_name)
- return NM_MODEM_GET_CLASS (self)->get_ppp_name (self, connection);
+ /* Merge user-defined overrides into the IP4Config to be applied */
+ connection = nm_act_request_get_connection (req);
+ g_assert (connection);
- return NULL;
+ s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
+ if (s_ip4)
+ nm_utils_merge_ip4_config (config, s_ip4);
}
/*****************************************************************************/
@@ -139,14 +146,12 @@ nm_modem_get_ppp_name (NMModem *self,
static void
ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
-
switch (status) {
case NM_PPP_STATUS_DISCONNECT:
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
+ g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
break;
case NM_PPP_STATUS_DEAD:
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
+ g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_FAILED);
break;
default:
break;
@@ -159,7 +164,8 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
NMIP4Config *config,
gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
+ NMModem *self = NM_MODEM (user_data);
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
guint32 i, num;
guint32 bad_dns1 = htonl (0x0A0B0C0D);
guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */
@@ -167,10 +173,6 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */
gboolean dns_workaround = FALSE;
- /* Ignore PPP IP4 events that come in after initial configuration */
- if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG)
- return;
-
/* Work around a PPP bug (#1732) which causes many mobile broadband
* providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
* Apparently fixed in ppp-2.4.5 but we've had some reports that this is
@@ -206,9 +208,8 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
nm_ip4_config_add_nameserver (config, good_dns2);
}
- nm_device_set_ip_iface (device, iface);
- NM_MODEM_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
- nm_device_activate_schedule_stage4_ip4_config_get (device);
+ priv->pending_ip4_config = g_object_ref (config);
+ g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, iface, config, NULL);
}
static void
@@ -229,36 +230,48 @@ ppp_stats (NMPPPManager *ppp_manager,
}
static NMActStageReturn
-ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
+ppp_stage3_ip4_config_start (NMModem *self,
+ NMActRequest *req,
+ NMDeviceStateReason *reason)
{
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
- NMActRequest *req;
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
const char *ppp_name = NULL;
- GError *err = NULL;
+ GError *error = NULL;
NMActStageReturn ret;
- req = nm_device_get_act_request (device);
- g_assert (req);
+ g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
- ppp_name = nm_modem_get_ppp_name (NM_MODEM (device),
- nm_act_request_get_connection (req));
+ if (NM_MODEM_GET_CLASS (self)->get_user_pass) {
+ NMConnection *connection = nm_act_request_get_connection (req);
- priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device));
- if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, 20, &err)) {
+ g_assert (connection);
+ if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL))
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ priv->ppp_manager = nm_ppp_manager_new (priv->iface);
+ if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, 20, &error)) {
g_signal_connect (priv->ppp_manager, "state-changed",
G_CALLBACK (ppp_state_changed),
- device);
+ self);
g_signal_connect (priv->ppp_manager, "ip4-config",
G_CALLBACK (ppp_ip4_config),
- device);
+ self);
g_signal_connect (priv->ppp_manager, "stats",
G_CALLBACK (ppp_stats),
- device);
+ self);
ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else {
- nm_warning ("%s", err->message);
- g_error_free (err);
+ nm_warning ("%s: error starting PPP: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_error_free (error);
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
@@ -271,20 +284,17 @@ ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
}
static NMActStageReturn
-ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
+ppp_stage4 (NMModem *self,
+ NMActRequest *req,
+ NMIP4Config **config,
+ NMDeviceStateReason *reason)
{
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
- NMConnection *connection;
- NMSettingIP4Config *s_ip4;
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
*config = priv->pending_ip4_config;
priv->pending_ip4_config = NULL;
- /* Merge user-defined overrides into the IP4Config to be applied */
- connection = nm_act_request_get_connection (nm_device_get_act_request (device));
- g_assert (connection);
- s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
- nm_utils_merge_ip4_config (*config, s_ip4);
+ merge_ip4_config (req, *config);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@@ -293,57 +303,75 @@ ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
/* IP method static */
static void
-static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
+ NMModem *self = NM_MODEM (user_data);
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
GValueArray *ret_array = NULL;
GError *error = NULL;
+ NMIP4Config *config = NULL;
- if (dbus_g_proxy_end_call (proxy, call_id, &error,
+ priv->call = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_VALUE_ARRAY, &ret_array,
G_TYPE_INVALID)) {
-
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMIP4Address *addr;
int i;
+ config = nm_ip4_config_new ();
+
addr = nm_ip4_address_new ();
nm_ip4_address_set_address (addr, g_value_get_uint (g_value_array_get_nth (ret_array, 0)));
nm_ip4_address_set_prefix (addr, 32);
+ nm_ip4_config_take_address (config, addr);
- priv->pending_ip4_config = nm_ip4_config_new ();
- nm_ip4_config_take_address (priv->pending_ip4_config, addr);
-
- for (i = 1; i < ret_array->n_values; i++)
- nm_ip4_config_add_nameserver (priv->pending_ip4_config,
- g_value_get_uint (g_value_array_get_nth (ret_array, i)));
+ for (i = 0; i < ret_array->n_values; i++) {
+ GValue *value = g_value_array_get_nth (ret_array, i);
+ nm_ip4_config_add_nameserver (config, g_value_get_uint (value));
+ }
g_value_array_free (ret_array);
- nm_device_activate_schedule_stage4_ip4_config_get (device);
- } else {
- nm_warning ("Retrieving IP4 configuration failed: %s", error->message);
- g_error_free (error);
- nm_device_state_changed (device,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+
+ priv->pending_ip4_config = g_object_ref (config);
+ g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, NULL);
}
+
+ g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, error);
+ g_clear_error (&error);
}
static NMActStageReturn
-static_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
+static_stage3_ip4_config_start (NMModem *self,
+ NMActRequest *req,
+ NMDeviceStateReason *reason)
{
- dbus_g_proxy_begin_call (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM),
- "GetIP4Config", static_stage3_done,
- device, NULL,
- G_TYPE_INVALID);
+ NMModemPrivate *priv;
+
+ g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+ priv = NM_MODEM_GET_PRIVATE (self);
+
+ priv->call = dbus_g_proxy_begin_call (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM),
+ "GetIP4Config", static_stage3_done,
+ self, NULL,
+ G_TYPE_INVALID);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMActStageReturn
-static_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
+static_stage4 (NMModem *self,
+ NMActRequest *req,
+ NMDevice *device,
+ NMIP4Config **config,
+ NMDeviceStateReason *reason)
{
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
gboolean no_firmware = FALSE;
if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) {
@@ -357,25 +385,42 @@ static_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reas
*config = priv->pending_ip4_config;
priv->pending_ip4_config = NULL;
+ merge_ip4_config (req, *config);
+
return NM_ACT_STAGE_RETURN_SUCCESS;
}
/*****************************************************************************/
-static NMActStageReturn
-real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
+NMActStageReturn
+nm_modem_stage3_ip4_config_start (NMModem *self,
+ NMDevice *device,
+ NMDeviceClass *device_class,
+ NMDeviceStateReason *reason)
{
+ NMActRequest *req;
NMActStageReturn ret;
- switch (NM_MODEM_GET_PRIVATE (device)->ip_method) {
+ g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ switch (NM_MODEM_GET_PRIVATE (self)->ip_method) {
case MM_MODEM_IP_METHOD_PPP:
- ret = ppp_stage3_ip4_config_start (device, reason);
+ ret = ppp_stage3_ip4_config_start (self, req, reason);
break;
case MM_MODEM_IP_METHOD_STATIC:
- ret = static_stage3_ip4_config_start (device, reason);
+ ret = static_stage3_ip4_config_start (self, req, reason);
break;
case MM_MODEM_IP_METHOD_DHCP:
- ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage3_ip4_config_start (device, reason);
+ ret = device_class->act_stage3_ip4_config_start (device, reason);
break;
default:
g_warning ("Invalid IP method");
@@ -386,22 +431,36 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
return ret;
}
-static NMActStageReturn
-real_act_stage4_get_ip4_config (NMDevice *device,
+NMActStageReturn
+nm_modem_stage4_get_ip4_config (NMModem *self,
+ NMDevice *device,
+ NMDeviceClass *device_class,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
+ NMActRequest *req;
NMActStageReturn ret;
- switch (NM_MODEM_GET_PRIVATE (device)->ip_method) {
+ g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE);
+ g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ switch (NM_MODEM_GET_PRIVATE (self)->ip_method) {
case MM_MODEM_IP_METHOD_PPP:
- ret = ppp_stage4 (device, config, reason);
+ ret = ppp_stage4 (self, req, config, reason);
break;
case MM_MODEM_IP_METHOD_STATIC:
- ret = static_stage4 (device, config, reason);
+ ret = static_stage4 (self, req, device, config, reason);
break;
case MM_MODEM_IP_METHOD_DHCP:
- ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage4_get_ip4_config (device, config, reason);
+ ret = device_class->act_stage4_get_ip4_config (device, config, reason);
break;
default:
g_warning ("Invalid IP method");
@@ -412,12 +471,175 @@ real_act_stage4_get_ip4_config (NMDevice *device,
return ret;
}
-static void
-real_deactivate_quickly (NMDevice *device)
+gboolean
+nm_modem_connection_secrets_updated (NMModem *self,
+ NMActRequest *req,
+ NMConnection *connection,
+ GSList *updated_settings,
+ RequestSecretsCaller caller)
{
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
+ NMModemPrivate *priv;
+ gboolean found = FALSE;
+ const char *setting_name;
+ GSList *iter;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (req != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
+ g_return_val_if_fail (connection != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
+
+ priv = NM_MODEM_GET_PRIVATE (self);
+
+ if (caller == SECRETS_CALLER_PPP) {
+ const char *user = NULL;
+ const char *pass = NULL;
+
+ g_return_val_if_fail (priv->ppp_manager != NULL, FALSE);
+
+ if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &user, &pass)) {
+ /* Shouldn't ever happen */
+ nm_ppp_manager_update_secrets (priv->ppp_manager,
+ priv->iface,
+ NULL,
+ NULL,
+ "missing GSM/CDMA setting; no secrets could be found.");
+ } else {
+ nm_ppp_manager_update_secrets (priv->ppp_manager,
+ priv->iface,
+ user ? user : "",
+ pass ? pass : "",
+ NULL);
+ }
+ return TRUE;
+ }
+
+ g_return_val_if_fail (caller == SECRETS_CALLER_MOBILE_BROADBAND, FALSE);
+
+ g_assert (NM_MODEM_GET_CLASS (self)->get_setting_name);
+ setting_name = NM_MODEM_GET_CLASS (self)->get_setting_name (self);
+
+ for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
+ const char *candidate_setting_name = (const char *) iter->data;
+
+ if (!strcmp (candidate_setting_name, setting_name))
+ found = TRUE;
+ else {
+ nm_warning ("Ignoring updated secrets for setting '%s'.",
+ candidate_setting_name);
+ }
+ }
+
+ return found;
+}
+
+static NMActStageReturn
+real_act_stage1_prepare (NMModem *modem,
+ NMActRequest *req,
+ GPtrArray **out_hints,
+ const char **out_setting_name,
+ NMDeviceStateReason *reason)
+{
+ *reason = NM_DEVICE_STATE_REASON_UNKNOWN;
+ return NM_ACT_STAGE_RETURN_FAILURE;
+}
+
+NMActStageReturn
+nm_modem_act_stage1_prepare (NMModem *self,
+ NMActRequest *req,
+ NMDeviceStateReason *reason)
+{
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
+ NMActStageReturn ret;
+ GPtrArray *hints = NULL;
+ const char *setting_name = NULL;
+
+ ret = NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self,
+ req,
+ &hints,
+ &setting_name,
+ reason);
+ if ((ret == NM_ACT_STAGE_RETURN_POSTPONE) && setting_name) {
+ const char *hint1 = NULL, *hint2 = NULL;
+
+ /* Need some secrets */
+ if (hints) {
+ if (hints->len > 0)
+ hint1 = g_ptr_array_index (hints, 0);
+ if (hints->len > 1)
+ hint2 = g_ptr_array_index (hints, 1);
+ }
+
+ g_signal_emit (self, signals[NEED_AUTH], 0,
+ setting_name,
+ priv->secrets_tries++ ? TRUE : FALSE,
+ SECRETS_CALLER_MOBILE_BROADBAND,
+ hint1,
+ hint2);
+
+ if (hints)
+ g_ptr_array_free (hints, TRUE);
+ }
+
+ return ret;
+}
+
+NMActStageReturn
+nm_modem_act_stage2_config (NMModem *self,
+ NMActRequest *req,
+ NMDeviceStateReason *reason)
+{
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
+
+ /* Clear secrets tries counter since secrets were successfully used
+ * already if we get here.
+ */
+ priv->secrets_tries = 0;
+
+ return NM_ACT_STAGE_RETURN_SUCCESS;
+}
+
+NMConnection *
+nm_modem_get_best_auto_connection (NMModem *self,
+ GSList *connections,
+ char **specific_object)
+{
+ if (NM_MODEM_GET_CLASS (self)->get_best_auto_connection)
+ return NM_MODEM_GET_CLASS (self)->get_best_auto_connection (self, connections, specific_object);
+ return NULL;
+}
+
+gboolean
+nm_modem_check_connection_compatible (NMModem *self,
+ NMConnection *connection,
+ GError **error)
+{
+ if (NM_MODEM_GET_CLASS (self)->check_connection_compatible)
+ return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection, error);
+ return FALSE;
+}
+
+static void
+real_deactivate_quickly (NMModem *self, NMDevice *device)
+{
+ NMModemPrivate *priv;
const char *iface;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (NM_IS_MODEM (self));
+ g_return_if_fail (device != NULL);
+ g_return_if_fail (NM_IS_DEVICE (device));
+
+ priv = NM_MODEM_GET_PRIVATE (self);
+
+ priv->secrets_tries = 0;
+
+ if (priv->call) {
+ dbus_g_proxy_cancel_call (priv->proxy, priv->call);
+ priv->call = NULL;
+ }
+
if (priv->pending_ip4_config) {
g_object_unref (priv->pending_ip4_config);
priv->pending_ip4_config = NULL;
@@ -425,7 +647,7 @@ real_deactivate_quickly (NMDevice *device)
priv->in_bytes = priv->out_bytes = 0;
- switch (NM_MODEM_GET_PRIVATE (device)->ip_method) {
+ switch (priv->ip_method) {
case MM_MODEM_IP_METHOD_PPP:
if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager);
@@ -434,8 +656,7 @@ real_deactivate_quickly (NMDevice *device)
break;
case MM_MODEM_IP_METHOD_STATIC:
case MM_MODEM_IP_METHOD_DHCP:
- iface = nm_device_get_iface (device);
-
+ iface = nm_device_get_ip_iface (device);
nm_system_device_flush_routes_with_iface (iface);
nm_system_device_flush_addresses_with_iface (iface);
nm_system_device_set_up_down_with_iface (iface, FALSE, NULL);
@@ -444,35 +665,32 @@ real_deactivate_quickly (NMDevice *device)
g_warning ("Invalid IP method");
break;
}
-
- if (NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate)
- NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate (device);
}
-static guint32
-real_get_generic_capabilities (NMDevice *dev)
+void
+nm_modem_deactivate_quickly (NMModem *self, NMDevice *device)
{
- return NM_DEVICE_CAP_NM_SUPPORTED;
+ NM_MODEM_GET_CLASS (self)->deactivate_quickly (self, device);
}
-static void
-device_state_changed (NMDeviceInterface *device,
- NMDeviceState new_state,
- NMDeviceState old_state,
- NMDeviceStateReason reason,
- gpointer user_data)
+void
+nm_modem_device_state_changed (NMModem *self,
+ NMDeviceState new_state,
+ NMDeviceState old_state,
+ NMDeviceStateReason reason)
{
- NMModem *self = NM_MODEM (user_data);
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
gboolean was_connected = FALSE;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (NM_IS_MODEM (self));
+
if (IS_ACTIVATING_STATE (old_state) || (old_state == NM_DEVICE_STATE_ACTIVATED))
was_connected = TRUE;
/* Make sure we don't leave the serial device open */
switch (new_state) {
case NM_DEVICE_STATE_NEED_AUTH:
- if (priv->ppp_manager)
+ if (NM_MODEM_GET_PRIVATE (self)->ppp_manager)
break;
/* else fall through */
case NM_DEVICE_STATE_UNMANAGED:
@@ -490,13 +708,13 @@ device_state_changed (NMDeviceInterface *device,
}
}
-static gboolean
-real_hw_is_up (NMDevice *device)
+gboolean
+nm_modem_hw_is_up (NMModem *self, NMDevice *device)
{
- guint32 ip_method = NM_MODEM_GET_PRIVATE (device)->ip_method;
+ guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method;
if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) {
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMDeviceState state;
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
@@ -507,13 +725,13 @@ real_hw_is_up (NMDevice *device)
return TRUE;
}
-static gboolean
-real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
+gboolean
+nm_modem_hw_bring_up (NMModem *self, NMDevice *device, gboolean *no_firmware)
{
- guint32 ip_method = NM_MODEM_GET_PRIVATE (device)->ip_method;
+ guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method;
if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) {
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMDeviceState state;
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
@@ -524,6 +742,24 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
return TRUE;
}
+const char *
+nm_modem_get_iface (NMModem *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (NM_IS_MODEM (self), NULL);
+
+ return NM_MODEM_GET_PRIVATE (self)->iface;
+}
+
+const char *
+nm_modem_get_path (NMModem *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (NM_IS_MODEM (self), NULL);
+
+ return NM_MODEM_GET_PRIVATE (self)->path;
+}
+
static void
get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
{
@@ -577,11 +813,15 @@ set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d
query_mm_enabled (NM_MODEM (user_data));
}
-static void
-real_set_enabled (NMDeviceInterface *device, gboolean enabled)
+void
+nm_modem_set_mm_enabled (NMModem *self, gboolean enabled)
{
- NMModem *self = NM_MODEM (device);
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
+ NMModemPrivate *priv;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (NM_IS_MODEM (self));
+
+ priv = NM_MODEM_GET_PRIVATE (self);
/* FIXME: For now this just toggles the ModemManager enabled state. In the
* future we want to tie this into rfkill state instead so that the user can
@@ -591,10 +831,10 @@ real_set_enabled (NMDeviceInterface *device, gboolean enabled)
if (priv->mm_enabled != enabled) {
DBusGProxy *proxy;
- proxy = nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM);
+ proxy = nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM);
dbus_g_proxy_begin_call (proxy,
"Enable", set_mm_enabled_done,
- device, NULL,
+ self, NULL,
G_TYPE_BOOLEAN, enabled,
G_TYPE_INVALID);
}
@@ -615,30 +855,13 @@ modem_properties_changed (DBusGProxy *proxy,
value = g_hash_table_lookup (props, "Enabled");
if (value && G_VALUE_HOLDS_BOOLEAN (value)) {
- NMDeviceState state;
-
priv->mm_enabled = g_value_get_boolean (value);
g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED);
-
- if (priv->mm_enabled == FALSE) {
- state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
- if (state == NM_DEVICE_STATE_ACTIVATED) {
- nm_device_state_changed (NM_DEVICE (self),
- NM_DEVICE_STATE_DISCONNECTED,
- NM_DEVICE_STATE_REASON_NONE);
- }
- }
}
}
/*****************************************************************************/
-static void
-device_interface_init (NMDeviceInterface *iface_class)
-{
- iface_class->set_enabled = real_set_enabled;
-}
-
static void
nm_modem_init (NMModem *self)
{
@@ -665,7 +888,12 @@ constructor (GType type,
priv = NM_MODEM_GET_PRIVATE (object);
if (!priv->device) {
- g_warning ("Modem device not provided");
+ g_warning ("Modem parent device not provided");
+ goto err;
+ }
+
+ if (!priv->device) {
+ g_warning ("Modem command interface not provided");
goto err;
}
@@ -696,8 +924,6 @@ constructor (GType type,
object,
NULL);
- g_signal_connect (object, "state-changed", G_CALLBACK (device_state_changed), object);
-
query_mm_enabled (NM_MODEM (object));
return object;
@@ -720,6 +946,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DEVICE:
g_value_set_string (value, priv->device);
break;
+ case PROP_IFACE:
+ g_value_set_string (value, priv->iface);
+ break;
case PROP_IP_METHOD:
g_value_set_uint (value, priv->ip_method);
break;
@@ -748,7 +977,12 @@ set_property (GObject *object, guint prop_id,
/* Construct only */
priv->device = g_value_dup_string (value);
break;
+ case PROP_IFACE:
+ /* Construct only */
+ priv->iface = g_value_dup_string (value);
+ break;
case PROP_IP_METHOD:
+ /* Construct only */
priv->ip_method = g_value_get_uint (value);
break;
case PROP_ENABLED:
@@ -772,6 +1006,7 @@ finalize (GObject *object)
g_object_unref (priv->dbus_mgr);
+ g_free (priv->iface);
g_free (priv->path);
g_free (priv->device);
@@ -782,7 +1017,6 @@ static void
nm_modem_class_init (NMModemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemPrivate));
@@ -792,12 +1026,8 @@ nm_modem_class_init (NMModemClass *klass)
object_class->get_property = get_property;
object_class->finalize = finalize;
- device_class->get_generic_capabilities = real_get_generic_capabilities;
- device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
- device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
- device_class->deactivate_quickly = real_deactivate_quickly;
- device_class->hw_is_up = real_hw_is_up;
- device_class->hw_bring_up = real_hw_bring_up;
+ klass->act_stage1_prepare = real_act_stage1_prepare;
+ klass->deactivate_quickly = real_deactivate_quickly;
/* Properties */
g_object_class_install_property
@@ -806,7 +1036,7 @@ nm_modem_class_init (NMModemClass *klass)
"DBus path",
"DBus path",
NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_DEVICE,
@@ -814,7 +1044,15 @@ nm_modem_class_init (NMModemClass *klass)
"Device",
"Master modem parent device",
NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
+ (object_class, PROP_IFACE,
+ g_param_spec_string (NM_MODEM_IFACE,
+ "Interface",
+ "Modem command interface",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_IP_METHOD,
@@ -824,7 +1062,7 @@ nm_modem_class_init (NMModemClass *klass)
MM_MODEM_IP_METHOD_PPP,
MM_MODEM_IP_METHOD_DHCP,
MM_MODEM_IP_METHOD_PPP,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_ENABLED,
@@ -845,10 +1083,47 @@ nm_modem_class_init (NMModemClass *klass)
G_TYPE_NONE, 2,
G_TYPE_UINT, G_TYPE_UINT);
- signals[PROPERTIES_CHANGED] =
- nm_properties_changed_signal_new (object_class,
- G_STRUCT_OFFSET (NMModemClass, properties_changed));
+ signals[PPP_FAILED] =
+ g_signal_new ("ppp-failed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMModemClass, ppp_failed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
- dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
- &dbus_glib_nm_serial_device_object_info);
+ signals[IP4_CONFIG_RESULT] =
+ g_signal_new (NM_MODEM_IP4_CONFIG_RESULT,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMModemClass, ip4_config_result),
+ NULL, NULL,
+ _nm_marshal_VOID__STRING_OBJECT_POINTER,
+ G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_POINTER);
+
+ signals[PREPARE_RESULT] =
+ g_signal_new (NM_MODEM_PREPARE_RESULT,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMModemClass, prepare_result),
+ NULL, NULL,
+ _nm_marshal_VOID__BOOLEAN_UINT,
+ G_TYPE_NONE, 2, G_TYPE_BOOLEAN, G_TYPE_UINT);
+
+ signals[NEED_AUTH] =
+ g_signal_new (NM_MODEM_NEED_AUTH,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMModemClass, need_auth),
+ NULL, NULL,
+ _nm_marshal_VOID__STRING_BOOLEAN_UINT_STRING_STRING,
+ G_TYPE_NONE, 5,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
}
+
+const DBusGObjectInfo *
+nm_modem_get_serial_dbus_info (void)
+{
+ return &dbus_glib_nm_serial_device_object_info;
+}
+
diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h
index 0a722764c2..a2aed57e00 100644
--- a/src/modem-manager/nm-modem.h
+++ b/src/modem-manager/nm-modem.h
@@ -23,8 +23,9 @@
#define NM_MODEM_H
#include
-#include
+#include
#include "ppp-manager/nm-ppp-manager.h"
+#include "nm-device.h"
G_BEGIN_DECLS
@@ -37,36 +38,119 @@ G_BEGIN_DECLS
#define NM_MODEM_PATH "path"
#define NM_MODEM_DEVICE "device"
+#define NM_MODEM_IFACE "iface"
#define NM_MODEM_IP_METHOD "ip-method"
#define NM_MODEM_ENABLED "enabled"
+#define NM_MODEM_PPP_STATS "ppp-stats"
+#define NM_MODEM_PPP_FAILED "ppp-failed"
+#define NM_MODEM_PREPARE_RESULT "prepare-result"
+#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result"
+#define NM_MODEM_NEED_AUTH "need-auth"
+
typedef struct {
- NMDevice parent;
+ GObject parent;
} NMModem;
typedef struct {
- NMDeviceClass parent;
+ GObjectClass parent;
- const char *(*get_ppp_name) (NMModem *self,
- NMConnection *connection);
+ gboolean (*get_user_pass) (NMModem *modem,
+ NMConnection *connection,
+ const char **user,
+ const char **pass);
+
+ const char * (*get_setting_name) (NMModem *modem);
+
+ gboolean (*check_connection_compatible) (NMModem *modem,
+ NMConnection *connection,
+ GError **error);
+
+ NMConnection * (*get_best_auto_connection) (NMModem *modem,
+ GSList *connections,
+ char **specific_object);
+
+ NMActStageReturn (*act_stage1_prepare) (NMModem *modem,
+ NMActRequest *req,
+ GPtrArray **out_hints,
+ const char **out_setting_name,
+ NMDeviceStateReason *reason);
+
+ void (*deactivate_quickly) (NMModem *self, NMDevice *device);
/* Signals */
- void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes);
- void (*properties_changed) (NMModem *self, GHashTable *properties);
+ void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes);
+ void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason);
+
+ void (*prepare_result) (NMModem *self, gboolean success, NMDeviceStateReason reason);
+ void (*ip4_config_result) (NMModem *self, const char *iface, NMIP4Config *config, GError *error);
+
+ void (*need_auth) (NMModem *self,
+ const char *setting_name,
+ gboolean retry,
+ RequestSecretsCaller caller,
+ const char *hint1,
+ const char *hint2);
} NMModemClass;
GType nm_modem_get_type (void);
/* Protected */
-NMPPPManager *nm_modem_get_ppp_manager (NMModem *self);
-DBusGProxy *nm_modem_get_proxy (NMModem *self,
- const char *interface);
+NMPPPManager *nm_modem_get_ppp_manager (NMModem *modem);
+DBusGProxy * nm_modem_get_proxy (NMModem *modem, const char *interface);
+const char * nm_modem_get_iface (NMModem *modem);
+const char * nm_modem_get_path (NMModem *modem);
-const char *nm_modem_get_ppp_name (NMModem *self,
- NMConnection *connection);
+NMConnection *nm_modem_get_best_auto_connection (NMModem *self,
+ GSList *connections,
+ char **specific_object);
-gboolean nm_modem_get_mm_enabled (NMModem *self);
+gboolean nm_modem_check_connection_compatible (NMModem *self,
+ NMConnection *connection,
+ GError **error);
+
+NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem,
+ NMActRequest *req,
+ NMDeviceStateReason *reason);
+
+NMActStageReturn nm_modem_act_stage2_config (NMModem *modem,
+ NMActRequest *req,
+ NMDeviceStateReason *reason);
+
+NMActStageReturn nm_modem_stage3_ip4_config_start (NMModem *modem,
+ NMDevice *device,
+ NMDeviceClass *device_class,
+ NMDeviceStateReason *reason);
+
+NMActStageReturn nm_modem_stage4_get_ip4_config (NMModem *modem,
+ NMDevice *device,
+ NMDeviceClass *device_class,
+ NMIP4Config **config,
+ NMDeviceStateReason *reason);
+
+void nm_modem_deactivate_quickly (NMModem *modem, NMDevice *device);
+
+void nm_modem_device_state_changed (NMModem *modem,
+ NMDeviceState new_state,
+ NMDeviceState old_state,
+ NMDeviceStateReason reason);
+
+gboolean nm_modem_hw_is_up (NMModem *modem, NMDevice *device);
+
+gboolean nm_modem_hw_bring_up (NMModem *modem, NMDevice *device, gboolean *no_firmware);
+
+gboolean nm_modem_connection_secrets_updated (NMModem *modem,
+ NMActRequest *req,
+ NMConnection *connection,
+ GSList *updated_settings,
+ RequestSecretsCaller caller);
+
+const DBusGObjectInfo *nm_modem_get_serial_dbus_info (void);
+
+gboolean nm_modem_get_mm_enabled (NMModem *self);
+
+void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled);
G_END_DECLS
diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c
index 444c7ff056..ab2572536e 100644
--- a/src/nm-device-bt.c
+++ b/src/nm-device-bt.c
@@ -52,13 +52,12 @@ typedef struct {
guint32 capabilities;
DBusGProxy *type_proxy;
+ DBusGProxy *dev_proxy;
- NMPPPManager *ppp_manager;
char *rfcomm_iface;
- guint32 in_bytes;
- guint32 out_bytes;
+ NMModem *modem;
+ guint32 timeout_id;
- NMIP4Config *pending_ip4_config;
guint32 bt_type; /* BT type of the current connection */
} NMDeviceBtPrivate;
@@ -122,31 +121,6 @@ nm_bt_error_get_type (void)
}
-NMDevice *
-nm_device_bt_new (const char *udi,
- const char *bdaddr,
- const char *name,
- guint32 capabilities,
- gboolean managed)
-{
- g_return_val_if_fail (udi != NULL, NULL);
- g_return_val_if_fail (bdaddr != NULL, NULL);
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL);
-
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT,
- NM_DEVICE_INTERFACE_UDI, udi,
- NM_DEVICE_INTERFACE_IFACE, bdaddr,
- NM_DEVICE_INTERFACE_DRIVER, "bluez",
- NM_DEVICE_BT_HW_ADDRESS, bdaddr,
- NM_DEVICE_BT_NAME, name,
- NM_DEVICE_BT_CAPABILITIES, capabilities,
- NM_DEVICE_INTERFACE_MANAGED, managed,
- NM_DEVICE_INTERFACE_TYPE_DESC, "Bluetooth",
- NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_BT,
- NULL);
-}
-
guint32 nm_device_bt_get_capabilities (NMDeviceBt *self)
{
g_return_val_if_fail (self != NULL, NM_BT_CAPABILITY_NONE);
@@ -281,16 +255,26 @@ real_get_generic_capabilities (NMDevice *dev)
/* IP method PPP */
static void
-ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
+ppp_stats (NMModem *modem,
+ guint32 in_bytes,
+ guint32 out_bytes,
+ gpointer user_data)
+{
+ g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes);
+}
+
+static void
+ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
- switch (status) {
- case NM_PPP_STATUS_DISCONNECT:
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
- break;
- case NM_PPP_STATUS_DEAD:
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
+ switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) {
+ case NM_DEVICE_STATE_PREPARE:
+ case NM_DEVICE_STATE_CONFIG:
+ case NM_DEVICE_STATE_NEED_AUTH:
+ case NM_DEVICE_STATE_IP_CONFIG:
+ case NM_DEVICE_STATE_ACTIVATED:
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
break;
default:
break;
@@ -298,68 +282,126 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_
}
static void
-ppp_ip4_config (NMPPPManager *ppp_manager,
- const char *iface,
- NMIP4Config *config,
- gpointer user_data)
+modem_need_auth (NMModem *modem,
+ const char *setting_name,
+ gboolean retry,
+ RequestSecretsCaller caller,
+ const char *hint1,
+ const char *hint2,
+ gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceBt *self = NM_DEVICE_BT (user_data);
+ NMActRequest *req;
- /* Ignore PPP IP4 events that come in after initial configuration */
- if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG)
- return;
+ req = nm_device_get_act_request (NM_DEVICE (self));
+ g_assert (req);
- nm_device_set_ip_iface (device, iface);
- NM_DEVICE_BT_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
- nm_device_activate_schedule_stage4_ip4_config_get (device);
+ nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
+ nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2);
}
static void
-ppp_stats (NMPPPManager *ppp_manager,
- guint32 in_bytes,
- guint32 out_bytes,
- gpointer user_data)
+modem_prepare_result (NMModem *modem,
+ gboolean success,
+ NMDeviceStateReason reason,
+ gpointer user_data)
{
- NMDeviceBt *self = NM_DEVICE_BT (user_data);
- NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceState state;
- if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) {
- priv->in_bytes = in_bytes;
- priv->out_bytes = out_bytes;
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
+ g_return_if_fail (state == NM_DEVICE_STATE_CONFIG);
- g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes);
+ if (success) {
+ NMActRequest *req;
+ NMActStageReturn ret;
+ NMDeviceStateReason stage2_reason = NM_DEVICE_STATE_REASON_NONE;
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ ret = nm_modem_act_stage2_config (modem, req, &stage2_reason);
+ switch (ret) {
+ case NM_ACT_STAGE_RETURN_POSTPONE:
+ break;
+ case NM_ACT_STAGE_RETURN_SUCCESS:
+ nm_device_activate_schedule_stage3_ip_config_start (device);
+ break;
+ case NM_ACT_STAGE_RETURN_FAILURE:
+ default:
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, stage2_reason);
+ break;
+ }
+ } else
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+}
+
+static void
+device_state_changed (NMDevice *device,
+ NMDeviceState new_state,
+ NMDeviceState old_state,
+ NMDeviceStateReason reason,
+ gpointer user_data)
+{
+ NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
+
+ if (priv->modem)
+ nm_modem_device_state_changed (priv->modem, new_state, old_state, reason);
+}
+
+static void
+modem_ip4_config_result (NMModem *self,
+ const char *iface,
+ NMIP4Config *config,
+ GError *error,
+ gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceState state;
+
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
+ g_return_if_fail (state == NM_DEVICE_STATE_IP_CONFIG);
+
+ if (error) {
+ nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ } else {
+ if (iface)
+ nm_device_set_ip_iface (device, iface);
+
+ nm_device_activate_schedule_stage4_ip4_config_get (device);
}
}
static gboolean
-get_ppp_credentials (NMConnection *connection,
- const char **username,
- const char **password)
+modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason)
{
- NMSettingGsm *s_gsm;
- NMSettingCdma *s_cdma = NULL;
+ NMActRequest *req;
+ NMActStageReturn ret;
- s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
- if (s_gsm) {
- if (username)
- *username = nm_setting_gsm_get_username (s_gsm);
- if (password)
- *password = nm_setting_gsm_get_password (s_gsm);
- } else {
- /* Try CDMA then */
- s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
- if (s_cdma) {
- if (username)
- *username = nm_setting_cdma_get_username (s_cdma);
- if (password)
- *password = nm_setting_cdma_get_password (s_cdma);
- }
+ g_return_val_if_fail (reason != NULL, FALSE);
+
+ req = nm_device_get_act_request (NM_DEVICE (self));
+ g_assert (req);
+
+ ret = nm_modem_act_stage1_prepare (modem, req, reason);
+ switch (ret) {
+ case NM_ACT_STAGE_RETURN_POSTPONE:
+ case NM_ACT_STAGE_RETURN_SUCCESS:
+ /* Success, wait for the 'prepare-result' signal */
+ return TRUE;
+ case NM_ACT_STAGE_RETURN_FAILURE:
+ default:
+ break;
}
- return (s_cdma || s_gsm) ? TRUE : FALSE;
+ return FALSE;
}
-
static void
real_connection_secrets_updated (NMDevice *device,
NMConnection *connection,
@@ -369,111 +411,134 @@ real_connection_secrets_updated (NMDevice *device,
NMDeviceBt *self = NM_DEVICE_BT (device);
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
NMActRequest *req;
- const char *username = NULL, *password = NULL;
- gboolean success = FALSE;
+ NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
- if (caller != SECRETS_CALLER_PPP)
- return;
-
- g_return_if_fail (priv->ppp_manager);
+ g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device)));
req = nm_device_get_act_request (device);
g_assert (req);
- success = get_ppp_credentials (nm_act_request_get_connection (req),
- &username,
- &password);
- if (success) {
- nm_ppp_manager_update_secrets (priv->ppp_manager,
- nm_device_get_ip_iface (device),
- username ? username : "",
- password ? password : "",
- NULL);
+ if (!nm_modem_connection_secrets_updated (priv->modem,
+ req,
+ connection,
+ updated_settings,
+ caller)) {
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
return;
}
- /* Shouldn't ever happen */
- nm_ppp_manager_update_secrets (priv->ppp_manager,
- nm_device_get_ip_iface (device),
- NULL,
- NULL,
- "missing GSM/CDMA setting; no secrets could be found.");
-}
+ /* PPP handles stuff itself... */
+ if (caller == SECRETS_CALLER_PPP)
+ return;
-static NMActStageReturn
-ppp_stage3_start (NMDevice *device, NMDeviceStateReason *reason)
-{
- NMDeviceBt *self = NM_DEVICE_BT (device);
- NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
- NMActRequest *req;
- const char *ppp_name = NULL;
- GError *err = NULL;
- NMActStageReturn ret;
- gboolean success;
-
- req = nm_device_get_act_request (device);
- g_assert (req);
-
- success = get_ppp_credentials (nm_act_request_get_connection (req),
- &ppp_name,
- NULL);
- if (!success) {
- // FIXME: set reason to something plausible
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- priv->ppp_manager = nm_ppp_manager_new (priv->rfcomm_iface);
- if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, 20, &err)) {
- g_signal_connect (priv->ppp_manager, "state-changed",
- G_CALLBACK (ppp_state_changed),
- device);
- g_signal_connect (priv->ppp_manager, "ip4-config",
- G_CALLBACK (ppp_ip4_config),
- device);
- g_signal_connect (priv->ppp_manager, "stats",
- G_CALLBACK (ppp_stats),
- device);
-
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
- } else {
- nm_warning ("%s", err->message);
- g_error_free (err);
-
- g_object_unref (priv->ppp_manager);
- priv->ppp_manager = NULL;
-
- *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED;
- ret = NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- return ret;
-}
-
-static NMActStageReturn
-ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
-{
- NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
- NMConnection *connection;
- NMSettingIP4Config *s_ip4;
-
- *config = priv->pending_ip4_config;
- priv->pending_ip4_config = NULL;
-
- /* Merge user-defined overrides into the IP4Config to be applied */
- connection = nm_act_request_get_connection (nm_device_get_act_request (device));
- g_assert (connection);
- s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
- nm_utils_merge_ip4_config (*config, s_ip4);
-
- return NM_ACT_STAGE_RETURN_SUCCESS;
+ /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */
+ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
+ if (!modem_stage1 (self, priv->modem, &reason))
+ nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason);
}
/*****************************************************************************/
+gboolean
+nm_device_bt_modem_added (NMDeviceBt *self,
+ NMModem *modem,
+ const char *driver)
+{
+ NMDeviceBtPrivate *priv;
+ const char *modem_iface;
+ char *base;
+ NMDeviceState state;
+ NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE);
+ g_return_val_if_fail (modem != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_MODEM (modem), FALSE);
+
+ priv = NM_DEVICE_BT_GET_PRIVATE (self);
+ modem_iface = nm_modem_get_iface (modem);
+ g_return_val_if_fail (modem_iface != NULL, FALSE);
+
+ if (!priv->rfcomm_iface)
+ return FALSE;
+
+ base = g_path_get_basename (priv->rfcomm_iface);
+ if (strcmp (base, modem_iface)) {
+ g_free (base);
+ return FALSE;
+ }
+ g_free (base);
+
+ /* Got the modem */
+ if (priv->timeout_id) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
+ /* Can only accept the modem in stage2, but since the interface matched
+ * what we were expecting, don't let anything else claim the modem either.
+ */
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
+ if (state != NM_DEVICE_STATE_CONFIG) {
+ nm_warning ("(%s): modem found but device not in correct state (%d)",
+ nm_device_get_iface (NM_DEVICE (self)),
+ nm_device_get_state (NM_DEVICE (self)));
+ return TRUE;
+ }
+
+ nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) modem found.",
+ nm_device_get_iface (NM_DEVICE (self)));
+
+ if (priv->modem) {
+ g_warn_if_reached ();
+ g_object_unref (priv->modem);
+ }
+
+ priv->modem = g_object_ref (modem);
+ g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), self);
+ g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self);
+ g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self);
+ g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self);
+ g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), self);
+
+ /* Kick off the modem connection */
+ if (!modem_stage1 (self, modem, &reason))
+ nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason);
+
+ return TRUE;
+}
+
+gboolean
+nm_device_bt_modem_removed (NMDeviceBt *self, NMModem *modem)
+{
+ NMDeviceBtPrivate *priv;
+ NMDeviceState state;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE);
+ g_return_val_if_fail (modem != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_MODEM (modem), FALSE);
+
+ priv = NM_DEVICE_BT_GET_PRIVATE (self);
+
+ if (modem != priv->modem)
+ return FALSE;
+
+ state = nm_device_get_state (NM_DEVICE (self));
+ nm_modem_device_state_changed (priv->modem,
+ NM_DEVICE_STATE_DISCONNECTED,
+ state,
+ NM_DEVICE_STATE_REASON_USER_REQUESTED);
+
+ g_object_unref (priv->modem);
+ priv->modem = NULL;
+ return TRUE;
+}
+
static void
-nm_device_bt_connect_cb (DBusGProxy *proxy,
- DBusGProxyCall *call_id,
- void *user_data)
+bluez_connect_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call_id,
+ void *user_data)
{
NMDeviceBt *self = NM_DEVICE_BT (user_data);
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
@@ -481,8 +546,8 @@ nm_device_bt_connect_cb (DBusGProxy *proxy,
char *device;
if (dbus_g_proxy_end_call (proxy, call_id, &error,
- G_TYPE_STRING, &device,
- G_TYPE_INVALID) == FALSE) {
+ G_TYPE_STRING, &device,
+ G_TYPE_INVALID) == FALSE) {
nm_warning ("Error connecting with bluez: %s",
error && error->message ? error->message : "(unknown)");
g_clear_error (&error);
@@ -510,6 +575,20 @@ nm_device_bt_connect_cb (DBusGProxy *proxy,
/* Stage 3 gets scheduled when Bluez says we're connected */
}
+static gboolean
+modem_find_timeout (gpointer user_data)
+{
+ NMDeviceBt *self = NM_DEVICE_BT (user_data);
+ NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
+
+ priv->timeout_id = 0;
+
+ nm_device_state_changed (NM_DEVICE (user_data),
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND);
+ return FALSE;
+}
+
static void
bluez_property_changed (DBusGProxy *proxy,
const char *property,
@@ -528,18 +607,29 @@ bluez_property_changed (DBusGProxy *proxy,
state = nm_device_get_state (device);
connected = g_value_get_boolean (value);
if (connected) {
- /* Bluez says we're connected now. Start IP config. */
-
if (state == NM_DEVICE_STATE_CONFIG) {
gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP);
gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN);
nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) "
- "successful. Connected via %s.",
+ "successful. Will connect via %s.",
nm_device_get_iface (device),
dun ? "DUN" : (pan ? "PAN" : "unknown"));
- nm_device_activate_schedule_stage3_ip_config_start (device);
+ if (pan) {
+ /* Bluez says we're connected now. Start IP config. */
+ nm_device_activate_schedule_stage3_ip_config_start (device);
+ } else if (dun) {
+ /* Wait for ModemManager to find the modem */
+ if (priv->timeout_id)
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = g_timeout_add_seconds (20, modem_find_timeout, self);
+
+ nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) "
+ "waiting for modem to appear.",
+ nm_device_get_iface (device));
+ } else
+ g_assert_not_reached ();
}
} else {
gboolean fail = FALSE;
@@ -567,6 +657,7 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
NMActRequest *req;
NMDBusManager *dbus_mgr;
DBusGConnection *g_connection;
+ gboolean dun = FALSE;
req = nm_device_get_act_request (device);
g_assert (req);
@@ -581,53 +672,50 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
g_connection = nm_dbus_manager_get_connection (dbus_mgr);
g_object_unref (dbus_mgr);
- if (priv->bt_type == NM_BT_CAPABILITY_DUN) {
- priv->type_proxy = dbus_g_proxy_new_for_name (g_connection,
- BLUEZ_SERVICE,
- nm_device_get_udi (device),
- BLUEZ_SERIAL_INTERFACE);
- if (!priv->type_proxy) {
- // FIXME: set a reason code
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect",
- nm_device_bt_connect_cb,
- device,
- NULL,
- 20000,
- G_TYPE_STRING, BLUETOOTH_DUN_UUID,
- G_TYPE_INVALID);
- } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) {
- priv->type_proxy = dbus_g_proxy_new_for_name (g_connection,
- BLUEZ_SERVICE,
- nm_device_get_udi (device),
- BLUEZ_NETWORK_INTERFACE);
- if (!priv->type_proxy) {
- // FIXME: set a reason code
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect",
- nm_device_bt_connect_cb,
- device,
- NULL,
- 20000,
- G_TYPE_STRING, BLUETOOTH_NAP_UUID,
- G_TYPE_INVALID);
- } else
+ if (priv->bt_type == NM_BT_CAPABILITY_DUN)
+ dun = TRUE;
+ else if (priv->bt_type == NM_BT_CAPABILITY_NAP)
+ dun = FALSE;
+ else
g_assert_not_reached ();
+ priv->dev_proxy = dbus_g_proxy_new_for_name (g_connection,
+ BLUEZ_SERVICE,
+ nm_device_get_udi (device),
+ BLUEZ_DEVICE_INTERFACE);
+ if (!priv->dev_proxy) {
+ // FIXME: set a reason code
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
/* Watch for BT device property changes */
dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED,
G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_VALUE,
G_TYPE_INVALID);
- dbus_g_proxy_add_signal (priv->type_proxy, "PropertyChanged",
+ dbus_g_proxy_add_signal (priv->dev_proxy, "PropertyChanged",
G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (priv->type_proxy, "PropertyChanged",
+ dbus_g_proxy_connect_signal (priv->dev_proxy, "PropertyChanged",
G_CALLBACK (bluez_property_changed), device, NULL);
+ priv->type_proxy = dbus_g_proxy_new_for_name (g_connection,
+ BLUEZ_SERVICE,
+ nm_device_get_udi (device),
+ dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE);
+ if (!priv->type_proxy) {
+ // FIXME: set a reason code
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ /* Connect to the BT device */
+ dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect",
+ bluez_connect_cb,
+ device,
+ NULL,
+ 20000,
+ G_TYPE_STRING, dun ? BLUETOOTH_DUN_UUID : BLUETOOTH_NAP_UUID,
+ G_TYPE_INVALID);
+
return NM_ACT_STAGE_RETURN_POSTPONE;
}
@@ -637,9 +725,12 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
NMActStageReturn ret;
- if (priv->bt_type == NM_BT_CAPABILITY_DUN)
- ret = ppp_stage3_start (device, reason);
- else
+ if (priv->bt_type == NM_BT_CAPABILITY_DUN) {
+ ret = nm_modem_stage3_ip4_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem,
+ device,
+ NM_DEVICE_CLASS (nm_device_bt_parent_class),
+ reason);
+ } else
ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, reason);
return ret;
@@ -653,9 +744,13 @@ real_act_stage4_get_ip4_config (NMDevice *device,
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
NMActStageReturn ret;
- if (priv->bt_type == NM_BT_CAPABILITY_DUN)
- ret = ppp_stage4 (device, config, reason);
- else
+ if (priv->bt_type == NM_BT_CAPABILITY_DUN) {
+ ret = nm_modem_stage4_get_ip4_config (NM_DEVICE_BT_GET_PRIVATE (device)->modem,
+ device,
+ NM_DEVICE_CLASS (nm_device_bt_parent_class),
+ config,
+ reason);
+ } else
ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage4_get_ip4_config (device, config, reason);
return ret;
@@ -666,17 +761,20 @@ real_deactivate_quickly (NMDevice *device)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
- if (priv->pending_ip4_config) {
- g_object_unref (priv->pending_ip4_config);
- priv->pending_ip4_config = NULL;
- }
-
- priv->in_bytes = priv->out_bytes = 0;
-
if (priv->bt_type == NM_BT_CAPABILITY_DUN) {
- if (priv->ppp_manager) {
- g_object_unref (priv->ppp_manager);
- priv->ppp_manager = NULL;
+
+ if (priv->modem) {
+ nm_modem_deactivate_quickly (priv->modem, device);
+
+ /* Since we're killing the Modem object before it'll get the
+ * state change signal, simulate the state change here.
+ */
+ nm_modem_device_state_changed (priv->modem,
+ NM_DEVICE_STATE_DISCONNECTED,
+ NM_DEVICE_STATE_ACTIVATED,
+ NM_DEVICE_STATE_REASON_USER_REQUESTED);
+ g_object_unref (priv->modem);
+ priv->modem = NULL;
}
if (priv->type_proxy) {
@@ -700,6 +798,16 @@ real_deactivate_quickly (NMDevice *device)
}
}
+ if (priv->dev_proxy) {
+ g_object_unref (priv->dev_proxy);
+ priv->dev_proxy = NULL;
+ }
+
+ if (priv->timeout_id) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
priv->bt_type = NM_BT_CAPABILITY_NONE;
g_free (priv->rfcomm_iface);
@@ -709,6 +817,39 @@ real_deactivate_quickly (NMDevice *device)
NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate_quickly (device);
}
+/*****************************************************************************/
+
+NMDevice *
+nm_device_bt_new (const char *udi,
+ const char *bdaddr,
+ const char *name,
+ guint32 capabilities,
+ gboolean managed)
+{
+ NMDevice *device;
+
+ g_return_val_if_fail (udi != NULL, NULL);
+ g_return_val_if_fail (bdaddr != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL);
+
+ device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT,
+ NM_DEVICE_INTERFACE_UDI, udi,
+ NM_DEVICE_INTERFACE_IFACE, bdaddr,
+ NM_DEVICE_INTERFACE_DRIVER, "bluez",
+ NM_DEVICE_BT_HW_ADDRESS, bdaddr,
+ NM_DEVICE_BT_NAME, name,
+ NM_DEVICE_BT_CAPABILITIES, capabilities,
+ NM_DEVICE_INTERFACE_MANAGED, managed,
+ NM_DEVICE_INTERFACE_TYPE_DESC, "Bluetooth",
+ NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_BT,
+ NULL);
+ if (device)
+ g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device);
+
+ return device;
+}
+
static void
nm_device_bt_init (NMDeviceBt *self)
{
@@ -766,9 +907,21 @@ finalize (GObject *object)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
+ if (priv->timeout_id) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
if (priv->type_proxy)
g_object_unref (priv->type_proxy);
+ if (priv->dev_proxy)
+ g_object_unref (priv->dev_proxy);
+
+ if (priv->modem)
+ g_object_unref (priv->modem);
+
+ g_free (priv->rfcomm_iface);
g_free (priv->bdaddr);
g_free (priv->name);
diff --git a/src/nm-device-bt.h b/src/nm-device-bt.h
index 67ef6f5f25..d3187d766f 100644
--- a/src/nm-device-bt.h
+++ b/src/nm-device-bt.h
@@ -22,6 +22,7 @@
#define NM_DEVICE_BT_H
#include
+#include "nm-modem.h"
G_BEGIN_DECLS
@@ -60,6 +61,12 @@ guint32 nm_device_bt_get_capabilities (NMDeviceBt *device);
const char *nm_device_bt_get_hw_address (NMDeviceBt *device);
+gboolean nm_device_bt_modem_added (NMDeviceBt *device,
+ NMModem *modem,
+ const char *driver);
+
+gboolean nm_device_bt_modem_removed (NMDeviceBt *device, NMModem *modem);
+
G_END_DECLS
#endif /* NM_GSM_DEVICE_H */
diff --git a/src/nm-device-cdma.c b/src/nm-device-cdma.c
new file mode 100644
index 0000000000..bc73e9dab0
--- /dev/null
+++ b/src/nm-device-cdma.c
@@ -0,0 +1,411 @@
+/* -*- 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 - 2010 Red Hat, Inc.
+ */
+
+#include
+
+#include "nm-dbus-glib-types.h"
+#include "nm-modem.h"
+#include "nm-modem-cdma.h"
+#include "nm-device-interface.h"
+#include "nm-device-private.h"
+#include "nm-device-cdma.h"
+#include "nm-utils.h"
+#include "NetworkManagerUtils.h"
+#include "nm-marshal.h"
+#include "nm-properties-changed-signal.h"
+
+#include "nm-device-cdma-glue.h"
+
+static void device_interface_init (NMDeviceInterface *iface_class);
+
+G_DEFINE_TYPE_EXTENDED (NMDeviceCdma, nm_device_cdma, NM_TYPE_DEVICE, 0,
+ G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init))
+
+#define NM_DEVICE_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaPrivate))
+
+typedef struct {
+ NMModem *modem;
+} NMDeviceCdmaPrivate;
+
+enum {
+ PPP_STATS,
+ PROPERTIES_CHANGED,
+
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+ppp_stats (NMModem *modem,
+ guint32 in_bytes,
+ guint32 out_bytes,
+ gpointer user_data)
+{
+ g_signal_emit (NM_DEVICE_CDMA (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes);
+}
+
+static void
+ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+
+ switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) {
+ case NM_DEVICE_STATE_PREPARE:
+ case NM_DEVICE_STATE_CONFIG:
+ case NM_DEVICE_STATE_NEED_AUTH:
+ case NM_DEVICE_STATE_IP_CONFIG:
+ case NM_DEVICE_STATE_ACTIVATED:
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+device_state_changed (NMDevice *device,
+ NMDeviceState new_state,
+ NMDeviceState old_state,
+ NMDeviceStateReason reason,
+ gpointer user_data)
+{
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device);
+
+ nm_modem_device_state_changed (priv->modem, new_state, old_state, reason);
+}
+
+static gboolean
+real_hw_is_up (NMDevice *device)
+{
+ return nm_modem_hw_is_up (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, device);
+}
+
+static gboolean
+real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
+{
+ return nm_modem_hw_bring_up (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, device, no_firmware);
+}
+
+static NMConnection *
+real_get_best_auto_connection (NMDevice *device,
+ GSList *connections,
+ char **specific_object)
+{
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device);
+
+ return nm_modem_get_best_auto_connection (priv->modem, connections, specific_object);
+}
+
+static void
+real_connection_secrets_updated (NMDevice *device,
+ NMConnection *connection,
+ GSList *updated_settings,
+ RequestSecretsCaller caller)
+{
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device);
+ NMActRequest *req;
+
+ g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device)));
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ if (!nm_modem_connection_secrets_updated (priv->modem,
+ req,
+ connection,
+ updated_settings,
+ caller)) {
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
+ return;
+ }
+
+ /* PPP handles stuff itself... */
+ if (caller == SECRETS_CALLER_PPP)
+ return;
+
+ /* Otherwise, on success for CDMA secrets we need to schedule stage1 again */
+ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
+ nm_device_activate_schedule_stage1_device_prepare (device);
+}
+
+static gboolean
+real_check_connection_compatible (NMDevice *device,
+ NMConnection *connection,
+ GError **error)
+{
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device);
+
+ return nm_modem_check_connection_compatible (priv->modem, connection, error);
+}
+
+
+static void
+modem_need_auth (NMModem *modem,
+ const char *setting_name,
+ gboolean retry,
+ RequestSecretsCaller caller,
+ const char *hint1,
+ const char *hint2,
+ gpointer user_data)
+{
+ NMDeviceCdma *self = NM_DEVICE_CDMA (user_data);
+ NMActRequest *req;
+
+ req = nm_device_get_act_request (NM_DEVICE (self));
+ g_assert (req);
+
+ nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
+ nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2);
+}
+
+static void
+modem_prepare_result (NMModem *modem,
+ gboolean success,
+ NMDeviceStateReason reason,
+ gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceState state;
+
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
+ g_return_if_fail (state == NM_DEVICE_STATE_PREPARE);
+
+ if (success)
+ nm_device_activate_schedule_stage2_device_config (device);
+ else
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+}
+
+static NMActStageReturn
+real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
+{
+ NMActRequest *req;
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ return nm_modem_act_stage1_prepare (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, req, reason);
+}
+
+static NMActStageReturn
+real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
+{
+ NMActRequest *req;
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ return nm_modem_act_stage2_config (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, req, reason);
+}
+
+static void
+modem_ip4_config_result (NMModem *self,
+ const char *iface,
+ NMIP4Config *config,
+ GError *error,
+ gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceState state;
+
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
+ g_return_if_fail (state == NM_DEVICE_STATE_IP_CONFIG);
+
+ if (error) {
+ nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ } else {
+ if (iface)
+ nm_device_set_ip_iface (device, iface);
+
+ nm_device_activate_schedule_stage4_ip4_config_get (device);
+ }
+}
+
+static NMActStageReturn
+real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
+{
+ return nm_modem_stage3_ip4_config_start (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem,
+ device,
+ NM_DEVICE_CLASS (nm_device_cdma_parent_class),
+ reason);
+}
+
+static NMActStageReturn
+real_act_stage4_get_ip4_config (NMDevice *device,
+ NMIP4Config **config,
+ NMDeviceStateReason *reason)
+{
+ return nm_modem_stage4_get_ip4_config (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem,
+ device,
+ NM_DEVICE_CLASS (nm_device_cdma_parent_class),
+ config,
+ reason);
+}
+
+static void
+real_deactivate_quickly (NMDevice *device)
+{
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device);
+
+ nm_modem_deactivate_quickly (priv->modem, device);
+}
+
+static guint32
+real_get_generic_capabilities (NMDevice *device)
+{
+ return NM_DEVICE_CAP_NM_SUPPORTED;
+}
+
+static void
+real_set_enabled (NMDeviceInterface *device, gboolean enabled)
+{
+ NMDeviceCdma *self = NM_DEVICE_CDMA (device);
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (self);
+ NMDeviceState state;
+
+ if (priv->modem) {
+ nm_modem_set_mm_enabled (priv->modem, enabled);
+
+ if (enabled == FALSE) {
+ state = nm_device_interface_get_state (device);
+ if (state == NM_DEVICE_STATE_ACTIVATED) {
+ nm_device_state_changed (NM_DEVICE (device),
+ NM_DEVICE_STATE_DISCONNECTED,
+ NM_DEVICE_STATE_REASON_NONE);
+ }
+ }
+ }
+}
+
+static void
+modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
+{
+ NMDeviceCdma *self = NM_DEVICE_CDMA (user_data);
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (self);
+
+ real_set_enabled (NM_DEVICE_INTERFACE (self), nm_modem_get_mm_enabled (priv->modem));
+}
+
+/*****************************************************************************/
+
+NMDevice *
+nm_device_cdma_new (NMModemCdma *modem, const char *driver)
+{
+ NMDevice *device;
+
+ g_return_val_if_fail (modem != NULL, NULL);
+ g_return_val_if_fail (NM_IS_MODEM_CDMA (modem), NULL);
+ g_return_val_if_fail (driver != NULL, NULL);
+
+ device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_CDMA,
+ NM_DEVICE_INTERFACE_UDI, nm_modem_get_path (NM_MODEM (modem)),
+ NM_DEVICE_INTERFACE_IFACE, nm_modem_get_iface (NM_MODEM (modem)),
+ NM_DEVICE_INTERFACE_DRIVER, driver,
+ NM_DEVICE_INTERFACE_TYPE_DESC, "CDMA",
+ NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA,
+ NULL);
+ if (device) {
+ g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device);
+
+ NM_DEVICE_CDMA_GET_PRIVATE (device)->modem = g_object_ref (modem);
+ g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), device);
+ g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), device);
+ g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), device);
+ g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), device);
+ g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), device);
+ g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), device);
+ }
+
+ return device;
+}
+
+static void
+device_interface_init (NMDeviceInterface *iface_class)
+{
+ iface_class->set_enabled = real_set_enabled;
+}
+
+static void
+nm_device_cdma_init (NMDeviceCdma *self)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (object);
+
+ g_object_unref (priv->modem);
+ priv->modem = NULL;
+
+ G_OBJECT_CLASS (nm_device_cdma_parent_class)->finalize (object);
+}
+
+static void
+nm_device_cdma_class_init (NMDeviceCdmaClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (NMDeviceCdmaPrivate));
+
+ /* Virtual methods */
+ object_class->finalize = finalize;
+
+ device_class->get_best_auto_connection = real_get_best_auto_connection;
+ device_class->connection_secrets_updated = real_connection_secrets_updated;
+ device_class->check_connection_compatible = real_check_connection_compatible;
+ device_class->hw_is_up = real_hw_is_up;
+ device_class->hw_bring_up = real_hw_bring_up;
+ device_class->get_generic_capabilities = real_get_generic_capabilities;
+ device_class->act_stage1_prepare = real_act_stage1_prepare;
+ device_class->act_stage2_config = real_act_stage2_config;
+ device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
+ device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
+ device_class->deactivate_quickly = real_deactivate_quickly;
+
+ /* Signals */
+ signals[PPP_STATS] =
+ g_signal_new ("ppp-stats",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMDeviceCdmaClass, ppp_stats),
+ NULL, NULL,
+ _nm_marshal_VOID__UINT_UINT,
+ G_TYPE_NONE, 2,
+ G_TYPE_UINT, G_TYPE_UINT);
+
+ signals[PROPERTIES_CHANGED] =
+ nm_properties_changed_signal_new (object_class,
+ G_STRUCT_OFFSET (NMDeviceCdmaClass, properties_changed));
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+ nm_modem_get_serial_dbus_info ());
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+ &dbus_glib_nm_device_cdma_object_info);
+}
+
diff --git a/src/nm-device-cdma.h b/src/nm-device-cdma.h
new file mode 100644
index 0000000000..ec4496d742
--- /dev/null
+++ b/src/nm-device-cdma.h
@@ -0,0 +1,56 @@
+/* -*- 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 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_CDMA_H
+#define NM_DEVICE_CDMA_H
+
+#include "nm-device.h"
+#include "nm-modem-cdma.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_CDMA (nm_device_cdma_get_type ())
+#define NM_DEVICE_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_CDMA, NMDeviceCdma))
+#define NM_DEVICE_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaClass))
+#define NM_IS_DEVICE_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_CDMA))
+#define NM_IS_DEVICE_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_CDMA))
+#define NM_DEVICE_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaClass))
+
+typedef struct {
+ NMDevice parent;
+} NMDeviceCdma;
+
+typedef struct {
+ NMDeviceClass parent;
+
+ /* Signals */
+ void (*signal_quality) (NMDeviceCdma *self, guint32 quality);
+
+ void (*ppp_stats) (NMDeviceCdma *self, guint32 in_bytes, guint32 out_bytes);
+ void (*properties_changed) (NMDeviceCdma *self, GHashTable *properties);
+} NMDeviceCdmaClass;
+
+GType nm_device_cdma_get_type (void);
+
+NMDevice *nm_device_cdma_new (NMModemCdma *modem, const char *driver);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_CDMA_H */
diff --git a/src/nm-device-gsm.c b/src/nm-device-gsm.c
new file mode 100644
index 0000000000..1bb7017533
--- /dev/null
+++ b/src/nm-device-gsm.c
@@ -0,0 +1,411 @@
+/* -*- 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 - 2010 Red Hat, Inc.
+ */
+
+#include
+
+#include "nm-dbus-glib-types.h"
+#include "nm-modem.h"
+#include "nm-modem-gsm.h"
+#include "nm-device-interface.h"
+#include "nm-device-private.h"
+#include "nm-device-gsm.h"
+#include "nm-utils.h"
+#include "NetworkManagerUtils.h"
+#include "nm-marshal.h"
+#include "nm-properties-changed-signal.h"
+
+#include "nm-device-gsm-glue.h"
+
+static void device_interface_init (NMDeviceInterface *iface_class);
+
+G_DEFINE_TYPE_EXTENDED (NMDeviceGsm, nm_device_gsm, NM_TYPE_DEVICE, 0,
+ G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init))
+
+#define NM_DEVICE_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GSM, NMDeviceGsmPrivate))
+
+typedef struct {
+ NMModem *modem;
+} NMDeviceGsmPrivate;
+
+enum {
+ PPP_STATS,
+ PROPERTIES_CHANGED,
+
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+ppp_stats (NMModem *modem,
+ guint32 in_bytes,
+ guint32 out_bytes,
+ gpointer user_data)
+{
+ g_signal_emit (NM_DEVICE_GSM (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes);
+}
+
+static void
+ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+
+ switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) {
+ case NM_DEVICE_STATE_PREPARE:
+ case NM_DEVICE_STATE_CONFIG:
+ case NM_DEVICE_STATE_NEED_AUTH:
+ case NM_DEVICE_STATE_IP_CONFIG:
+ case NM_DEVICE_STATE_ACTIVATED:
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+device_state_changed (NMDevice *device,
+ NMDeviceState new_state,
+ NMDeviceState old_state,
+ NMDeviceStateReason reason,
+ gpointer user_data)
+{
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device);
+
+ nm_modem_device_state_changed (priv->modem, new_state, old_state, reason);
+}
+
+static gboolean
+real_hw_is_up (NMDevice *device)
+{
+ return nm_modem_hw_is_up (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, device);
+}
+
+static gboolean
+real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
+{
+ return nm_modem_hw_bring_up (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, device, no_firmware);
+}
+
+static NMConnection *
+real_get_best_auto_connection (NMDevice *device,
+ GSList *connections,
+ char **specific_object)
+{
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device);
+
+ return nm_modem_get_best_auto_connection (priv->modem, connections, specific_object);
+}
+
+static void
+real_connection_secrets_updated (NMDevice *device,
+ NMConnection *connection,
+ GSList *updated_settings,
+ RequestSecretsCaller caller)
+{
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device);
+ NMActRequest *req;
+
+ g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device)));
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ if (!nm_modem_connection_secrets_updated (priv->modem,
+ req,
+ connection,
+ updated_settings,
+ caller)) {
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
+ return;
+ }
+
+ /* PPP handles stuff itself... */
+ if (caller == SECRETS_CALLER_PPP)
+ return;
+
+ /* Otherwise, on success for GSM secrets we need to schedule stage1 again */
+ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
+ nm_device_activate_schedule_stage1_device_prepare (device);
+}
+
+static gboolean
+real_check_connection_compatible (NMDevice *device,
+ NMConnection *connection,
+ GError **error)
+{
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device);
+
+ return nm_modem_check_connection_compatible (priv->modem, connection, error);
+}
+
+
+static void
+modem_need_auth (NMModem *modem,
+ const char *setting_name,
+ gboolean retry,
+ RequestSecretsCaller caller,
+ const char *hint1,
+ const char *hint2,
+ gpointer user_data)
+{
+ NMDeviceGsm *self = NM_DEVICE_GSM (user_data);
+ NMActRequest *req;
+
+ req = nm_device_get_act_request (NM_DEVICE (self));
+ g_assert (req);
+
+ nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
+ nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2);
+}
+
+static void
+modem_prepare_result (NMModem *modem,
+ gboolean success,
+ NMDeviceStateReason reason,
+ gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceState state;
+
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
+ g_return_if_fail (state == NM_DEVICE_STATE_PREPARE);
+
+ if (success)
+ nm_device_activate_schedule_stage2_device_config (device);
+ else
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+}
+
+static NMActStageReturn
+real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
+{
+ NMActRequest *req;
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ return nm_modem_act_stage1_prepare (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, req, reason);
+}
+
+static NMActStageReturn
+real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
+{
+ NMActRequest *req;
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
+ return nm_modem_act_stage2_config (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, req, reason);
+}
+
+static void
+modem_ip4_config_result (NMModem *self,
+ const char *iface,
+ NMIP4Config *config,
+ GError *error,
+ gpointer user_data)
+{
+ NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceState state;
+
+ state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
+ g_return_if_fail (state == NM_DEVICE_STATE_IP_CONFIG);
+
+ if (error) {
+ nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ } else {
+ if (iface)
+ nm_device_set_ip_iface (device, iface);
+
+ nm_device_activate_schedule_stage4_ip4_config_get (device);
+ }
+}
+
+static NMActStageReturn
+real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
+{
+ return nm_modem_stage3_ip4_config_start (NM_DEVICE_GSM_GET_PRIVATE (device)->modem,
+ device,
+ NM_DEVICE_CLASS (nm_device_gsm_parent_class),
+ reason);
+}
+
+static NMActStageReturn
+real_act_stage4_get_ip4_config (NMDevice *device,
+ NMIP4Config **config,
+ NMDeviceStateReason *reason)
+{
+ return nm_modem_stage4_get_ip4_config (NM_DEVICE_GSM_GET_PRIVATE (device)->modem,
+ device,
+ NM_DEVICE_CLASS (nm_device_gsm_parent_class),
+ config,
+ reason);
+}
+
+static void
+real_deactivate_quickly (NMDevice *device)
+{
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device);
+
+ nm_modem_deactivate_quickly (priv->modem, device);
+}
+
+static guint32
+real_get_generic_capabilities (NMDevice *device)
+{
+ return NM_DEVICE_CAP_NM_SUPPORTED;
+}
+
+static void
+real_set_enabled (NMDeviceInterface *device, gboolean enabled)
+{
+ NMDeviceGsm *self = NM_DEVICE_GSM (device);
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (self);
+ NMDeviceState state;
+
+ if (priv->modem) {
+ nm_modem_set_mm_enabled (priv->modem, enabled);
+
+ if (enabled == FALSE) {
+ state = nm_device_interface_get_state (device);
+ if (state == NM_DEVICE_STATE_ACTIVATED) {
+ nm_device_state_changed (NM_DEVICE (device),
+ NM_DEVICE_STATE_DISCONNECTED,
+ NM_DEVICE_STATE_REASON_NONE);
+ }
+ }
+ }
+}
+
+static void
+modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
+{
+ NMDeviceGsm *self = NM_DEVICE_GSM (user_data);
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (self);
+
+ real_set_enabled (NM_DEVICE_INTERFACE (self), nm_modem_get_mm_enabled (priv->modem));
+}
+
+/*****************************************************************************/
+
+NMDevice *
+nm_device_gsm_new (NMModemGsm *modem, const char *driver)
+{
+ NMDevice *device;
+
+ g_return_val_if_fail (modem != NULL, NULL);
+ g_return_val_if_fail (NM_IS_MODEM_GSM (modem), NULL);
+ g_return_val_if_fail (driver != NULL, NULL);
+
+ device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_GSM,
+ NM_DEVICE_INTERFACE_UDI, nm_modem_get_path (NM_MODEM (modem)),
+ NM_DEVICE_INTERFACE_IFACE, nm_modem_get_iface (NM_MODEM (modem)),
+ NM_DEVICE_INTERFACE_DRIVER, driver,
+ NM_DEVICE_INTERFACE_TYPE_DESC, "GSM",
+ NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM,
+ NULL);
+ if (device) {
+ g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device);
+
+ NM_DEVICE_GSM_GET_PRIVATE (device)->modem = g_object_ref (modem);
+ g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), device);
+ g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), device);
+ g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), device);
+ g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), device);
+ g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), device);
+ g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), device);
+ }
+
+ return device;
+}
+
+static void
+device_interface_init (NMDeviceInterface *iface_class)
+{
+ iface_class->set_enabled = real_set_enabled;
+}
+
+static void
+nm_device_gsm_init (NMDeviceGsm *self)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (object);
+
+ g_object_unref (priv->modem);
+ priv->modem = NULL;
+
+ G_OBJECT_CLASS (nm_device_gsm_parent_class)->finalize (object);
+}
+
+static void
+nm_device_gsm_class_init (NMDeviceGsmClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (NMDeviceGsmPrivate));
+
+ /* Virtual methods */
+ object_class->finalize = finalize;
+
+ device_class->get_best_auto_connection = real_get_best_auto_connection;
+ device_class->connection_secrets_updated = real_connection_secrets_updated;
+ device_class->check_connection_compatible = real_check_connection_compatible;
+ device_class->hw_is_up = real_hw_is_up;
+ device_class->hw_bring_up = real_hw_bring_up;
+ device_class->get_generic_capabilities = real_get_generic_capabilities;
+ device_class->act_stage1_prepare = real_act_stage1_prepare;
+ device_class->act_stage2_config = real_act_stage2_config;
+ device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
+ device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
+ device_class->deactivate_quickly = real_deactivate_quickly;
+
+ /* Signals */
+ signals[PPP_STATS] =
+ g_signal_new ("ppp-stats",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMDeviceGsmClass, ppp_stats),
+ NULL, NULL,
+ _nm_marshal_VOID__UINT_UINT,
+ G_TYPE_NONE, 2,
+ G_TYPE_UINT, G_TYPE_UINT);
+
+ signals[PROPERTIES_CHANGED] =
+ nm_properties_changed_signal_new (object_class,
+ G_STRUCT_OFFSET (NMDeviceGsmClass, properties_changed));
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+ nm_modem_get_serial_dbus_info ());
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+ &dbus_glib_nm_device_gsm_object_info);
+}
+
diff --git a/src/nm-device-gsm.h b/src/nm-device-gsm.h
new file mode 100644
index 0000000000..1a74cfa1cd
--- /dev/null
+++ b/src/nm-device-gsm.h
@@ -0,0 +1,56 @@
+/* -*- 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 Red Hat, Inc.
+ */
+
+#ifndef NM_DEVICE_GSM_H
+#define NM_DEVICE_GSM_H
+
+#include "nm-device.h"
+#include "nm-modem-gsm.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_GSM (nm_device_gsm_get_type ())
+#define NM_DEVICE_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GSM, NMDeviceGsm))
+#define NM_DEVICE_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GSM, NMDeviceGsmClass))
+#define NM_IS_DEVICE_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GSM))
+#define NM_IS_DEVICE_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GSM))
+#define NM_DEVICE_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GSM, NMDeviceGsmClass))
+
+typedef struct {
+ NMDevice parent;
+} NMDeviceGsm;
+
+typedef struct {
+ NMDeviceClass parent;
+
+ /* Signals */
+ void (*signal_quality) (NMDeviceGsm *self, guint32 quality);
+
+ void (*ppp_stats) (NMDeviceGsm *self, guint32 in_bytes, guint32 out_bytes);
+ void (*properties_changed) (NMDeviceGsm *self, GHashTable *properties);
+} NMDeviceGsmClass;
+
+GType nm_device_gsm_get_type (void);
+
+NMDevice *nm_device_gsm_new (NMModemGsm *modem, const char *driver);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_GSM_H */
diff --git a/src/nm-manager.c b/src/nm-manager.c
index ff7535591d..f49c670b2c 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -37,6 +37,8 @@
#include "nm-device-ethernet.h"
#include "nm-device-wifi.h"
#include "nm-device-olpc-mesh.h"
+#include "nm-device-cdma.h"
+#include "nm-device-gsm.h"
#include "NetworkManagerSystem.h"
#include "nm-properties-changed-signal.h"
#include "nm-setting-bluetooth.h"
@@ -127,15 +129,15 @@ static const char *internal_activate_device (NMManager *manager,
gboolean assumed,
GError **error);
-static NMDevice *
-find_device_by_iface (NMManager *self, const gchar *iface);
+static NMDevice *find_device_by_iface (NMManager *self, const gchar *iface);
-static GSList *
-remove_one_device (NMManager *manager,
- GSList *list,
- NMDevice *device,
- gboolean quitting,
- gboolean force_unmanage);
+static GSList * remove_one_device (NMManager *manager,
+ GSList *list,
+ NMDevice *device,
+ gboolean quitting,
+ gboolean force_unmanage);
+
+static NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi);
#define SSD_POKE_INTERVAL 120
#define ORIGDEV_TAG "originating-device"
@@ -310,26 +312,17 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager,
static void
modem_added (NMModemManager *modem_manager,
- NMDevice *modem,
+ NMModem *modem,
+ const char *driver,
gpointer user_data)
{
- NMManagerPrivate *priv;
- NMDeviceType type;
- NMDevice *replace_device;
- const char *type_name;
+ NMManager *self = NM_MANAGER (user_data);
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+ NMDevice *replace_device, *device = NULL;
const char *ip_iface;
+ GSList *iter;
- priv = NM_MANAGER_GET_PRIVATE (user_data);
-
- type = nm_device_get_device_type (NM_DEVICE (modem));
- if (type == NM_DEVICE_TYPE_GSM)
- type_name = "GSM modem";
- else if (type == NM_DEVICE_TYPE_CDMA)
- type_name = "CDMA modem";
- else
- type_name = "Unknown modem";
-
- ip_iface = nm_device_get_ip_iface (modem);
+ ip_iface = nm_modem_get_iface (modem);
replace_device = find_device_by_iface (NM_MANAGER (user_data), ip_iface);
if (replace_device) {
@@ -340,7 +333,34 @@ modem_added (NMModemManager *modem_manager,
TRUE);
}
- add_device (NM_MANAGER (user_data), NM_DEVICE (g_object_ref (modem)));
+ /* Give Bluetooth DUN devices first chance to claim the modem */
+ for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
+ if (NM_IS_DEVICE_BT (iter->data)) {
+ if (nm_device_bt_modem_added (NM_DEVICE_BT (iter->data), modem, driver))
+ return;
+ }
+ }
+
+ /* If it was a Bluetooth modem and no bluetooth device claimed it, ignore
+ * it. The rfcomm port (and thus the modem) gets created automatically
+ * by the Bluetooth code during the connection process.
+ */
+ if (driver && !strcmp (driver, "bluetooth")) {
+ g_message ("%s: ignoring modem '%s' (no associated Bluetooth device)",
+ __func__, ip_iface);
+ return;
+ }
+
+ /* Otherwise make a new top-level NMDevice for it */
+ if (NM_IS_MODEM_GSM (modem))
+ device = nm_device_gsm_new (NM_MODEM_GSM (modem), driver);
+ else if (NM_IS_MODEM_CDMA (modem))
+ device = nm_device_cdma_new (NM_MODEM_CDMA (modem), driver);
+ else
+ g_message ("%s: unhandled modem '%s'", __func__, ip_iface);
+
+ if (device)
+ add_device (self, device);
}
static void
@@ -438,13 +458,26 @@ remove_one_device (NMManager *manager,
static void
modem_removed (NMModemManager *modem_manager,
- NMDevice *modem,
+ NMModem *modem,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+ NMDevice *found;
+ GSList *iter;
- priv->devices = remove_one_device (self, priv->devices, modem, FALSE, TRUE);
+ /* Give Bluetooth DUN devices first chance to handle the modem removal */
+ for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
+ if (NM_IS_DEVICE_BT (iter->data)) {
+ if (nm_device_bt_modem_removed (NM_DEVICE_BT (iter->data), modem))
+ return;
+ }
+ }
+
+ /* Otherwise remove the standalone modem */
+ found = nm_manager_get_device_by_udi (self, nm_modem_get_path (modem));
+ if (found)
+ priv->devices = remove_one_device (self, priv->devices, found, FALSE, TRUE);
}
static void
@@ -1440,7 +1473,7 @@ add_device (NMManager *self, NMDevice *device)
iface = nm_device_get_ip_iface (device);
g_assert (iface);
- if (!NM_IS_MODEM(device) && nm_modem_manager_has_modem_for_iface (priv->modem_manager, iface)) {
+ if (!NM_IS_MODEM (device) && find_device_by_iface (self, iface)) {
g_object_unref (device);
return;
}
@@ -1733,12 +1766,14 @@ find_device_by_iface (NMManager *self, const gchar *iface)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *iter;
+
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
NMDevice *device = NM_DEVICE (iter->data);
const gchar *d_iface = nm_device_get_ip_iface (device);
if (!strcmp (d_iface, iface))
return device;
}
+
return NULL;
}
@@ -3124,9 +3159,9 @@ nm_manager_init (NMManager *manager)
g_object_unref);
priv->modem_manager = nm_modem_manager_get ();
- priv->modem_added_id = g_signal_connect (priv->modem_manager, "device-added",
+ priv->modem_added_id = g_signal_connect (priv->modem_manager, "modem-added",
G_CALLBACK (modem_added), manager);
- priv->modem_removed_id = g_signal_connect (priv->modem_manager, "device-removed",
+ priv->modem_removed_id = g_signal_connect (priv->modem_manager, "modem-removed",
G_CALLBACK (modem_removed), manager);
priv->vpn_manager = nm_vpn_manager_get ();
diff --git a/src/nm-secrets-provider-interface.h b/src/nm-secrets-provider-interface.h
index 299e8c2dc8..3d9e08b186 100644
--- a/src/nm-secrets-provider-interface.h
+++ b/src/nm-secrets-provider-interface.h
@@ -28,8 +28,7 @@ typedef enum {
SECRETS_CALLER_NONE = 0,
SECRETS_CALLER_ETHERNET,
SECRETS_CALLER_WIFI,
- SECRETS_CALLER_GSM,
- SECRETS_CALLER_CDMA,
+ SECRETS_CALLER_MOBILE_BROADBAND,
SECRETS_CALLER_PPP,
SECRETS_CALLER_VPN
} RequestSecretsCaller;