Merge remote branch 'origin/btdun'

This commit is contained in:
Dan Williams
2010-02-18 10:18:20 -08:00
21 changed files with 2357 additions and 979 deletions

View File

@@ -366,6 +366,9 @@ typedef enum {
/* The supplicant is now available */ /* The supplicant is now available */
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
/* The modem could not be found */
NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND,
/* Unused */ /* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason; } NMDeviceStateReason;

View File

@@ -392,6 +392,11 @@
The 802.1x supplicant is now available. The 802.1x supplicant is now available.
</tp:docstring> </tp:docstring>
</tp:enumvalue> </tp:enumvalue>
<tp:enumvalue suffix="MODEM_NOT_FOUND" value="43">
<tp:docstring>
The modem could not be found.
</tp:docstring>
</tp:enumvalue>
</tp:enum> </tp:enum>
</interface> </interface>

View File

@@ -21,6 +21,9 @@ VOID:OBJECT,OBJECT,ENUM
VOID:POINTER,STRING VOID:POINTER,STRING
VOID:STRING,BOXED VOID:STRING,BOXED
BOOLEAN:POINTER,STRING,BOOLEAN,UINT,STRING,STRING BOOLEAN:POINTER,STRING,BOOLEAN,UINT,STRING,STRING
VOID:STRING,BOOLEAN,UINT,STRING,STRING
BOOLEAN:VOID BOOLEAN:VOID
VOID:STRING,BOOLEAN VOID:STRING,BOOLEAN
VOID:STRING,OBJECT,POINTER
VOID:BOOLEAN,UINT

View File

@@ -76,6 +76,10 @@ NetworkManager_SOURCES = \
nm-device-olpc-mesh.h \ nm-device-olpc-mesh.h \
nm-device-bt.c \ nm-device-bt.c \
nm-device-bt.h \ nm-device-bt.h \
nm-device-cdma.c \
nm-device-cdma.h \
nm-device-gsm.c \
nm-device-gsm.h \
NetworkManagerAP.c \ NetworkManagerAP.c \
NetworkManagerAP.h \ NetworkManagerAP.h \
nm-dbus-manager.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 nm-dhcp6-config-glue.h: $(top_srcdir)/introspection/nm-dhcp6-config.xml
dbus-binding-tool --prefix=nm_dhcp6_config --mode=glib-server --output=$@ $< 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 = \ BUILT_SOURCES = \
nm-access-point-glue.h \ nm-access-point-glue.h \
nm-manager-glue.h \ nm-manager-glue.h \
@@ -163,6 +173,8 @@ BUILT_SOURCES = \
nm-device-wifi-glue.h \ nm-device-wifi-glue.h \
nm-device-olpc-mesh-glue.h \ nm-device-olpc-mesh-glue.h \
nm-device-bt-glue.h \ nm-device-bt-glue.h \
nm-device-cdma-glue.h \
nm-device-gsm-glue.h \
nm-ip4-config-glue.h \ nm-ip4-config-glue.h \
nm-ip6-config-glue.h \ nm-ip6-config-glue.h \
nm-active-connection-glue.h \ nm-active-connection-glue.h \

View File

@@ -7,12 +7,12 @@ INCLUDES = \
noinst_LTLIBRARIES = libmodem-manager.la noinst_LTLIBRARIES = libmodem-manager.la
libmodem_manager_la_SOURCES = \ libmodem_manager_la_SOURCES = \
nm-modem.c \
nm-modem.h \
nm-modem-cdma.c \ nm-modem-cdma.c \
nm-modem-cdma.h \ nm-modem-cdma.h \
nm-modem-gsm.c \ nm-modem-gsm.c \
nm-modem-gsm.h \ nm-modem-gsm.h \
nm-modem.c \
nm-modem.h \
nm-modem-manager.h \ nm-modem-manager.h \
nm-modem-manager.c \ nm-modem-manager.c \
nm-modem-types.h nm-modem-types.h
@@ -24,18 +24,10 @@ libmodem_manager_la_LIBADD = \
$(top_builddir)/marshallers/libmarshallers.la \ $(top_builddir)/marshallers/libmarshallers.la \
$(DBUS_LIBS) $(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 nm-serial-device-glue.h: $(top_srcdir)/introspection/nm-device-serial.xml
dbus-binding-tool --prefix=nm_serial_device --mode=glib-server --output=$@ $< dbus-binding-tool --prefix=nm_serial_device --mode=glib-server --output=$@ $<
BUILT_SOURCES = \ BUILT_SOURCES = \
nm-device-cdma-glue.h \
nm-device-gsm-glue.h \
nm-serial-device-glue.h nm-serial-device-glue.h
CLEANFILES = $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES)

View File

@@ -24,18 +24,23 @@
#include "nm-dbus-glib-types.h" #include "nm-dbus-glib-types.h"
#include "nm-modem-cdma.h" #include "nm-modem-cdma.h"
#include "nm-modem-types.h" #include "nm-modem-types.h"
#include "nm-device-interface.h" #include "nm-device.h"
#include "nm-device-private.h"
#include "nm-dbus-manager.h" #include "nm-dbus-manager.h"
#include "nm-setting-connection.h" #include "nm-setting-connection.h"
#include "nm-setting-cdma.h" #include "nm-setting-cdma.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "NetworkManagerUtils.h" #include "NetworkManagerUtils.h"
#include "nm-device-cdma-glue.h"
G_DEFINE_TYPE (NMModemCdma, nm_modem_cdma, NM_TYPE_MODEM) 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 { typedef enum {
NM_CDMA_ERROR_CONNECTION_NOT_CDMA = 0, 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, nm_modem_cdma_new (const char *path,
const char *device, const char *device,
const char *data_device, const char *data_device,
const char *driver) guint32 ip_method)
{ {
g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (device != NULL, NULL); g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (data_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, return (NMModem *) 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_PATH, path,
NM_MODEM_DEVICE, device, NM_MODEM_DEVICE, device,
NM_DEVICE_INTERFACE_TYPE_DESC, "CDMA", NM_MODEM_IFACE, data_device,
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA, NM_MODEM_IP_METHOD, ip_method,
NULL); NULL);
} }
static void 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; GError *error = NULL;
dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); priv->call = NULL;
if (!error)
nm_device_activate_schedule_stage2_device_config (device); 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 { else {
nm_warning ("CDMA modem connection failed: (%d) %s", nm_warning ("CDMA connection failed: (%d) %s",
error ? error->code : -1, error ? error->code : -1,
error && error->message ? error->message : "(unknown)"); error && error->message ? error->message : "(unknown)");
g_error_free (error); 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; return properties;
} }
static void static NMActStageReturn
do_connect (NMModem *modem) 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; 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); g_assert (connection);
properties = create_connect_properties (connection); *out_setting_name = nm_connection_need_secrets (connection, out_hints);
dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE), if (!*out_setting_name) {
"Connect", stage1_prepare_done, gboolean enabled = nm_modem_get_mm_enabled (modem);
modem, NULL, 120000, DBusGProxy *proxy;
DBUS_TYPE_G_MAP_OF_VARIANT, properties,
G_TYPE_INVALID);
g_hash_table_destroy (properties);
}
static void if (priv->connect_properties)
stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) g_hash_table_destroy (priv->connect_properties);
{ priv->connect_properties = create_connect_properties (connection);
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 ("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) if (enabled)
do_connect (NM_MODEM (device)); do_connect (self);
else { else {
dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM);
dbus_g_proxy_begin_call_with_timeout (proxy,
"Enable", stage1_enable_done, "Enable", stage1_enable_done,
device, NULL, 20000, modem, NULL, 20000,
G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, TRUE,
G_TYPE_INVALID); G_TYPE_INVALID);
} }
} else {
/* NMModem will handle requesting secrets... */
}
return NM_ACT_STAGE_RETURN_POSTPONE; return NM_ACT_STAGE_RETURN_POSTPONE;
} }
static NMConnection * static NMConnection *
real_get_best_auto_connection (NMDevice *dev, real_get_best_auto_connection (NMModem *modem,
GSList *connections, GSList *connections,
char **specific_object) char **specific_object)
{ {
@@ -214,71 +240,8 @@ real_get_best_auto_connection (NMDevice *dev,
return NULL; 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 static gboolean
real_check_connection_compatible (NMDevice *device, real_check_connection_compatible (NMModem *modem,
NMConnection *connection, NMConnection *connection,
GError **error) GError **error)
{ {
@@ -306,15 +269,46 @@ real_check_connection_compatible (NMDevice *device,
return TRUE; return TRUE;
} }
static const char * static gboolean
real_get_ppp_name (NMModem *device, NMConnection *connection) real_get_user_pass (NMModem *modem,
NMConnection *connection,
const char **user,
const char **pass)
{ {
NMSettingCdma *s_cdma; NMSettingCdma *s_cdma;
s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_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 static void
nm_modem_cdma_class_init (NMModemCdmaClass *klass) 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); NMModemClass *modem_class = NM_MODEM_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemCdmaPrivate));
/* Virtual methods */ /* Virtual methods */
device_class->get_best_auto_connection = real_get_best_auto_connection; object_class->dispose = dispose;
device_class->connection_secrets_updated = real_connection_secrets_updated; modem_class->get_user_pass = real_get_user_pass;
device_class->act_stage1_prepare = real_act_stage1_prepare; modem_class->get_setting_name = real_get_setting_name;
device_class->check_connection_compatible = real_check_connection_compatible; modem_class->get_best_auto_connection = real_get_best_auto_connection;
modem_class->check_connection_compatible = real_check_connection_compatible;
modem_class->get_ppp_name = real_get_ppp_name; modem_class->act_stage1_prepare = real_act_stage1_prepare;
modem_class->deactivate_quickly = real_deactivate_quickly;
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
&dbus_glib_nm_device_cdma_object_info);
dbus_g_error_domain_register (NM_CDMA_ERROR, NULL, NM_TYPE_CDMA_ERROR); dbus_g_error_domain_register (NM_CDMA_ERROR, NULL, NM_TYPE_CDMA_ERROR);
} }

View File

@@ -46,10 +46,10 @@ typedef struct {
GType nm_modem_cdma_get_type (void); GType nm_modem_cdma_get_type (void);
NMDevice *nm_modem_cdma_new (const char *path, NMModem *nm_modem_cdma_new (const char *path,
const char *device, const char *device,
const char *data_device, const char *data_device,
const char *driver); guint32 ip_method);
G_END_DECLS G_END_DECLS

View File

@@ -22,16 +22,13 @@
#include <string.h> #include <string.h>
#include "nm-dbus-glib-types.h" #include "nm-dbus-glib-types.h"
#include "nm-modem-gsm.h" #include "nm-modem-gsm.h"
#include "nm-device-private.h" #include "nm-device.h"
#include "nm-device-interface.h"
#include "nm-setting-connection.h" #include "nm-setting-connection.h"
#include "nm-setting-gsm.h" #include "nm-setting-gsm.h"
#include "nm-modem-types.h" #include "nm-modem-types.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "NetworkManagerUtils.h" #include "NetworkManagerUtils.h"
#include "nm-device-gsm-glue.h"
typedef enum { typedef enum {
MM_MODEM_GSM_MODE_UNKNOWN = 0x00000000, MM_MODEM_GSM_MODE_UNKNOWN = 0x00000000,
MM_MODEM_GSM_MODE_ANY = 0x00000001, MM_MODEM_GSM_MODE_ANY = 0x00000001,
@@ -50,11 +47,17 @@ typedef enum {
} MMModemGsmMode; } MMModemGsmMode;
#define GSM_SECRETS_TRIES "gsm-secrets-tries"
#define PIN_TRIES "pin-tries"
G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM) 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 { typedef enum {
NM_GSM_ERROR_CONNECTION_NOT_GSM = 0, NM_GSM_ERROR_CONNECTION_NOT_GSM = 0,
@@ -98,27 +101,21 @@ nm_gsm_error_get_type (void)
} }
NMDevice * NMModem *
nm_modem_gsm_new (const char *path, nm_modem_gsm_new (const char *path,
const char *device, const char *device,
const char *data_device, const char *data_device,
const char *driver,
guint32 ip_method) guint32 ip_method)
{ {
g_return_val_if_fail (path != NULL, NULL); g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (device != NULL, NULL); g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (data_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, return (NMModem *) 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_PATH, path,
NM_MODEM_IP_METHOD, ip_method,
NM_MODEM_DEVICE, device, NM_MODEM_DEVICE, device,
NM_DEVICE_INTERFACE_TYPE_DESC, "GSM", NM_MODEM_IFACE, data_device,
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM, NM_MODEM_IP_METHOD, ip_method,
NULL); NULL);
} }
@@ -158,93 +155,159 @@ translate_mm_error (GError *error)
} }
static void static void
clear_pin (NMDevice *device) ask_for_pin (NMModemGsm *self, gboolean always_ask)
{ {
NMActRequest *req; NMModemGsmPrivate *priv;
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;
guint32 tries = 0; guint32 tries = 0;
g_return_if_fail (device != NULL); g_return_if_fail (self != NULL);
g_return_if_fail (hint1 || hint2); g_return_if_fail (NM_IS_MODEM_GSM (self));
req = nm_device_get_act_request (device); priv = NM_MODEM_GSM_GET_PRIVATE (self);
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);
if (!always_ask) 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, g_signal_emit_by_name (self, NM_MODEM_NEED_AUTH,
setting_name ? setting_name : NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_SETTING_NAME,
(tries || always_ask) ? TRUE : FALSE, (tries || always_ask) ? TRUE : FALSE,
SECRETS_CALLER_GSM, SECRETS_CALLER_MOBILE_BROADBAND,
hint1, NM_SETTING_GSM_PIN,
hint2); NULL);
if (!always_ask)
g_object_set_data (G_OBJECT (connection), tries_tag, GUINT_TO_POINTER (++tries));
} }
static void 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; GError *error = NULL;
dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); priv->call = NULL;
if (!error)
nm_device_activate_schedule_stage2_device_config (device);
else {
const char *required_secret = NULL;
gboolean retry_secret = FALSE;
if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) { if (priv->connect_properties) {
clear_pin (device); g_hash_table_destroy (priv->connect_properties);
required_secret = NM_SETTING_GSM_PIN; priv->connect_properties = NULL;
} 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",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
} }
if (required_secret) if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
request_secrets (device, NULL, required_secret, NULL, PIN_TRIES, retry_secret); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE);
else else {
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, translate_mm_error (error)); 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)");
g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error));
}
g_error_free (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 * static GHashTable *
create_connect_properties (NMConnection *connection) create_connect_properties (NMConnection *connection)
{ {
@@ -301,149 +364,41 @@ create_connect_properties (NMConnection *connection)
return properties; 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 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; 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); connection = nm_act_request_get_connection (req);
g_assert (connection); g_assert (connection);
setting_name = nm_connection_need_secrets (connection, &hints); *out_setting_name = nm_connection_need_secrets (connection, out_hints);
if (!setting_name) { if (!*out_setting_name) {
NMModem *modem = NM_MODEM (device);
gboolean enabled = nm_modem_get_mm_enabled (modem); 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) if (enabled)
do_connect (modem); do_connect (self);
else { else
dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM), do_enable (self);
"Enable", stage1_enable_done, } else {
modem, NULL, 20000, /* NMModem will handle requesting secrets... */
G_TYPE_BOOLEAN, TRUE,
G_TYPE_INVALID);
} }
return NM_ACT_STAGE_RETURN_POSTPONE;
}
/* 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; return NM_ACT_STAGE_RETURN_POSTPONE;
} }
static NMConnection * static NMConnection *
real_get_best_auto_connection (NMDevice *dev, real_get_best_auto_connection (NMModem *modem,
GSList *connections, GSList *connections,
char **specific_object) char **specific_object)
{ {
@@ -467,112 +422,8 @@ real_get_best_auto_connection (NMDevice *dev,
return NULL; 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 static gboolean
real_check_connection_compatible (NMDevice *device, real_check_connection_compatible (NMModem *modem,
NMConnection *connection, NMConnection *connection,
GError **error) GError **error)
{ {
@@ -600,17 +451,51 @@ real_check_connection_compatible (NMDevice *device,
return TRUE; return TRUE;
} }
static const char * static gboolean
real_get_ppp_name (NMModem *device, NMConnection *connection) real_get_user_pass (NMModem *modem,
NMConnection *connection,
const char **user,
const char **pass)
{ {
NMSettingGsm *s_gsm; NMSettingGsm *s_gsm;
s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_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 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 static void
nm_modem_gsm_class_init (NMModemGsmClass *klass) 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); NMModemClass *modem_class = NM_MODEM_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate));
/* Virtual methods */ /* Virtual methods */
device_class->get_best_auto_connection = real_get_best_auto_connection; object_class->dispose = dispose;
device_class->connection_secrets_updated = real_connection_secrets_updated; modem_class->get_user_pass = real_get_user_pass;
device_class->act_stage1_prepare = real_act_stage1_prepare; modem_class->get_setting_name = real_get_setting_name;
device_class->act_stage2_config = real_act_stage2_config; modem_class->get_best_auto_connection = real_get_best_auto_connection;
device_class->deactivate_quickly = real_deactivate_quickly; modem_class->check_connection_compatible = real_check_connection_compatible;
device_class->check_connection_compatible = real_check_connection_compatible; modem_class->act_stage1_prepare = real_act_stage1_prepare;
modem_class->deactivate_quickly = real_deactivate_quickly;
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);
dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR); dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR);
} }

View File

@@ -46,10 +46,9 @@ typedef struct {
GType nm_modem_gsm_get_type (void); GType nm_modem_gsm_get_type (void);
NMDevice *nm_modem_gsm_new (const char *path, NMModem *nm_modem_gsm_new (const char *path,
const char *device, const char *device,
const char *data_device, const char *data_device,
const char *driver,
guint32 ip_method); guint32 ip_method);
G_END_DECLS G_END_DECLS

View File

@@ -28,6 +28,7 @@
#include "nm-dbus-manager.h" #include "nm-dbus-manager.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "nm-modem-types.h" #include "nm-modem-types.h"
#include "nm-marshal.h"
#define MODEM_POKE_INTERVAL 120 #define MODEM_POKE_INTERVAL 120
@@ -44,8 +45,8 @@ typedef struct {
} NMModemManagerPrivate; } NMModemManagerPrivate;
enum { enum {
DEVICE_ADDED, MODEM_ADDED,
DEVICE_REMOVED, MODEM_REMOVED,
LAST_SIGNAL LAST_SIGNAL
}; };
@@ -67,25 +68,6 @@ nm_modem_manager_get (void)
return singleton; 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 static gboolean
get_modem_properties (DBusGConnection *connection, get_modem_properties (DBusGConnection *connection,
const char *path, const char *path,
@@ -182,7 +164,7 @@ static void
create_modem (NMModemManager *manager, const char *path) create_modem (NMModemManager *manager, const char *path)
{ {
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager);
NMDevice *device; NMModem *modem;
char *data_device = NULL, *driver = NULL, *master_device = NULL; char *data_device = NULL, *driver = NULL, *master_device = NULL;
uint modem_type = MM_MODEM_TYPE_UNKNOWN; uint modem_type = MM_MODEM_TYPE_UNKNOWN;
uint ip_method = MM_MODEM_IP_METHOD_PPP; 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) 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) 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 else
g_error ("Invalid modem type"); g_error ("Invalid modem type");
g_free (data_device); g_free (data_device);
g_free (driver);
if (device) { if (modem) {
g_hash_table_insert (priv->modems, g_strdup (path), device); g_hash_table_insert (priv->modems, g_strdup (path), modem);
g_signal_emit (manager, signals[DEVICE_ADDED], 0, device); g_signal_emit (manager, signals[MODEM_ADDED], 0, modem, driver);
} }
g_free (driver);
} }
static void 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); modem = (NMModem *) g_hash_table_lookup (priv->modems, path);
if (modem) { 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); g_hash_table_remove (priv->modems, path);
} }
} }
@@ -330,7 +313,7 @@ modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices)
static gboolean static gboolean
remove_one_modem (gpointer key, gpointer value, gpointer user_data) 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; return TRUE;
} }
@@ -440,23 +423,21 @@ nm_modem_manager_class_init (NMModemManagerClass *klass)
object_class->dispose = dispose; object_class->dispose = dispose;
/* signals */ /* signals */
signals[DEVICE_ADDED] = signals[MODEM_ADDED] =
g_signal_new ("device-added", g_signal_new ("modem-added",
G_OBJECT_CLASS_TYPE (object_class), G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST, G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemManagerClass, device_added), G_STRUCT_OFFSET (NMModemManagerClass, modem_added),
NULL, NULL, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, _nm_marshal_VOID__OBJECT_STRING,
G_TYPE_NONE, 1, G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING);
G_TYPE_OBJECT);
signals[DEVICE_REMOVED] = signals[MODEM_REMOVED] =
g_signal_new ("device-removed", g_signal_new ("modem-removed",
G_OBJECT_CLASS_TYPE (object_class), G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST, G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemManagerClass, device_removed), G_STRUCT_OFFSET (NMModemManagerClass, modem_removed),
NULL, NULL, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_NONE, 1, G_TYPE_OBJECT);
G_TYPE_OBJECT);
} }

View File

@@ -24,7 +24,7 @@
#define NM_MODEM_MANAGER_H #define NM_MODEM_MANAGER_H
#include <glib-object.h> #include <glib-object.h>
#include "nm-device.h" #include "nm-modem.h"
#define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ()) #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)) #define NM_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_MANAGER, NMModemManager))
@@ -41,18 +41,13 @@ typedef struct {
GObjectClass parent; GObjectClass parent;
/* Signals */ /* Signals */
void (*device_added) (NMModemManager *manager, void (*modem_added) (NMModemManager *manager, NMModem *modem, const char *driver);
NMDevice *device);
void (*device_removed) (NMModemManager *manager, void (*modem_removed) (NMModemManager *manager, NMModem *modem);
NMDevice *device);
} NMModemManagerClass; } NMModemManagerClass;
GType nm_modem_manager_get_type (void); GType nm_modem_manager_get_type (void);
NMModemManager *nm_modem_manager_get (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 */ #endif /* NM_MODEM_MANAGER_H */

View File

@@ -21,31 +21,28 @@
#include <string.h> #include <string.h>
#include "nm-modem.h" #include "nm-modem.h"
#include "nm-device-private.h"
#include "NetworkManagerSystem.h" #include "NetworkManagerSystem.h"
#include "nm-device-interface.h"
#include "nm-dbus-manager.h" #include "nm-dbus-manager.h"
#include "nm-setting-connection.h" #include "nm-setting-connection.h"
#include "nm-setting-gsm.h"
#include "nm-setting-cdma.h"
#include "nm-marshal.h" #include "nm-marshal.h"
#include "nm-properties-changed-signal.h" #include "nm-properties-changed-signal.h"
#include "nm-modem-types.h" #include "nm-modem-types.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "nm-serial-device-glue.h"
#include "NetworkManagerUtils.h" #include "NetworkManagerUtils.h"
#include "nm-device-private.h"
#include "nm-device-interface.h"
#include "nm-dbus-glib-types.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_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT)
G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init))
#define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) #define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate))
enum { enum {
PROP_0, PROP_0,
PROP_DEVICE, PROP_DEVICE,
PROP_IFACE,
PROP_PATH, PROP_PATH,
PROP_IP_METHOD, PROP_IP_METHOD,
PROP_ENABLED, PROP_ENABLED,
@@ -63,6 +60,11 @@ typedef struct {
NMIP4Config *pending_ip4_config; NMIP4Config *pending_ip4_config;
guint32 ip_method; guint32 ip_method;
char *device; char *device;
char *iface;
guint32 secrets_tries;
DBusGProxyCall *call;
gboolean mm_enabled; gboolean mm_enabled;
@@ -73,7 +75,10 @@ typedef struct {
enum { enum {
PPP_STATS, PPP_STATS,
PROPERTIES_CHANGED, PPP_FAILED,
PREPARE_RESULT,
IP4_CONFIG_RESULT,
NEED_AUTH,
LAST_SIGNAL LAST_SIGNAL
}; };
@@ -120,17 +125,19 @@ nm_modem_get_proxy (NMModem *self,
return priv->proxy; return priv->proxy;
} }
const char * static void
nm_modem_get_ppp_name (NMModem *self, merge_ip4_config (NMActRequest *req, NMIP4Config *config)
NMConnection *connection)
{ {
g_return_val_if_fail (NM_IS_MODEM (self), NULL); NMConnection *connection;
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); NMSettingIP4Config *s_ip4;
if (NM_MODEM_GET_CLASS (self)->get_ppp_name) /* Merge user-defined overrides into the IP4Config to be applied */
return NM_MODEM_GET_CLASS (self)->get_ppp_name (self, connection); 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 static void
ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
{ {
NMDevice *device = NM_DEVICE (user_data);
switch (status) { switch (status) {
case NM_PPP_STATUS_DISCONNECT: 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; break;
case NM_PPP_STATUS_DEAD: 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; break;
default: default:
break; break;
@@ -159,7 +164,8 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
NMIP4Config *config, NMIP4Config *config,
gpointer user_data) 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 i, num;
guint32 bad_dns1 = htonl (0x0A0B0C0D); guint32 bad_dns1 = htonl (0x0A0B0C0D);
guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */ guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */
@@ -167,10 +173,6 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */ guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */
gboolean dns_workaround = FALSE; 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 /* 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. * 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 * 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_ip4_config_add_nameserver (config, good_dns2);
} }
nm_device_set_ip_iface (device, iface); priv->pending_ip4_config = g_object_ref (config);
NM_MODEM_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, iface, config, NULL);
nm_device_activate_schedule_stage4_ip4_config_get (device);
} }
static void static void
@@ -229,36 +230,48 @@ ppp_stats (NMPPPManager *ppp_manager,
} }
static NMActStageReturn 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); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMActRequest *req;
const char *ppp_name = NULL; const char *ppp_name = NULL;
GError *err = NULL; GError *error = NULL;
NMActStageReturn ret; NMActStageReturn ret;
req = nm_device_get_act_request (device); g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_assert (req); 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), if (NM_MODEM_GET_CLASS (self)->get_user_pass) {
nm_act_request_get_connection (req)); NMConnection *connection = nm_act_request_get_connection (req);
priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device)); g_assert (connection);
if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, 20, &err)) { 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_signal_connect (priv->ppp_manager, "state-changed",
G_CALLBACK (ppp_state_changed), G_CALLBACK (ppp_state_changed),
device); self);
g_signal_connect (priv->ppp_manager, "ip4-config", g_signal_connect (priv->ppp_manager, "ip4-config",
G_CALLBACK (ppp_ip4_config), G_CALLBACK (ppp_ip4_config),
device); self);
g_signal_connect (priv->ppp_manager, "stats", g_signal_connect (priv->ppp_manager, "stats",
G_CALLBACK (ppp_stats), G_CALLBACK (ppp_stats),
device); self);
ret = NM_ACT_STAGE_RETURN_POSTPONE; ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else { } else {
nm_warning ("%s", err->message); nm_warning ("%s: error starting PPP: (%d) %s",
g_error_free (err); __func__,
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
g_object_unref (priv->ppp_manager); g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL; priv->ppp_manager = NULL;
@@ -271,20 +284,17 @@ ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
} }
static NMActStageReturn 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); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMConnection *connection;
NMSettingIP4Config *s_ip4;
*config = priv->pending_ip4_config; *config = priv->pending_ip4_config;
priv->pending_ip4_config = NULL; priv->pending_ip4_config = NULL;
/* Merge user-defined overrides into the IP4Config to be applied */ merge_ip4_config (req, *config);
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; return NM_ACT_STAGE_RETURN_SUCCESS;
} }
@@ -293,57 +303,75 @@ ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
/* IP method static */ /* IP method static */
static void 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; GValueArray *ret_array = NULL;
GError *error = 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_VALUE_ARRAY, &ret_array,
G_TYPE_INVALID)) { G_TYPE_INVALID)) {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMIP4Address *addr; NMIP4Address *addr;
int i; int i;
config = nm_ip4_config_new ();
addr = nm_ip4_address_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_address (addr, g_value_get_uint (g_value_array_get_nth (ret_array, 0)));
nm_ip4_address_set_prefix (addr, 32); nm_ip4_address_set_prefix (addr, 32);
nm_ip4_config_take_address (config, addr);
priv->pending_ip4_config = nm_ip4_config_new (); for (i = 0; i < ret_array->n_values; i++) {
nm_ip4_config_take_address (priv->pending_ip4_config, addr); GValue *value = g_value_array_get_nth (ret_array, i);
for (i = 1; i < ret_array->n_values; i++) nm_ip4_config_add_nameserver (config, g_value_get_uint (value));
nm_ip4_config_add_nameserver (priv->pending_ip4_config,
g_value_get_uint (g_value_array_get_nth (ret_array, i)));
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);
} }
g_value_array_free (ret_array);
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 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), 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, "GetIP4Config", static_stage3_done,
device, NULL, self, NULL,
G_TYPE_INVALID); G_TYPE_INVALID);
return NM_ACT_STAGE_RETURN_POSTPONE; return NM_ACT_STAGE_RETURN_POSTPONE;
} }
static NMActStageReturn 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; gboolean no_firmware = FALSE;
if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) { 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; *config = priv->pending_ip4_config;
priv->pending_ip4_config = NULL; priv->pending_ip4_config = NULL;
merge_ip4_config (req, *config);
return NM_ACT_STAGE_RETURN_SUCCESS; return NM_ACT_STAGE_RETURN_SUCCESS;
} }
/*****************************************************************************/ /*****************************************************************************/
static NMActStageReturn NMActStageReturn
real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) nm_modem_stage3_ip4_config_start (NMModem *self,
NMDevice *device,
NMDeviceClass *device_class,
NMDeviceStateReason *reason)
{ {
NMActRequest *req;
NMActStageReturn ret; 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: case MM_MODEM_IP_METHOD_PPP:
ret = ppp_stage3_ip4_config_start (device, reason); ret = ppp_stage3_ip4_config_start (self, req, reason);
break; break;
case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_STATIC:
ret = static_stage3_ip4_config_start (device, reason); ret = static_stage3_ip4_config_start (self, req, reason);
break; break;
case MM_MODEM_IP_METHOD_DHCP: 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; break;
default: default:
g_warning ("Invalid IP method"); g_warning ("Invalid IP method");
@@ -386,22 +431,36 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
return ret; return ret;
} }
static NMActStageReturn NMActStageReturn
real_act_stage4_get_ip4_config (NMDevice *device, nm_modem_stage4_get_ip4_config (NMModem *self,
NMDevice *device,
NMDeviceClass *device_class,
NMIP4Config **config, NMIP4Config **config,
NMDeviceStateReason *reason) NMDeviceStateReason *reason)
{ {
NMActRequest *req;
NMActStageReturn ret; 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: case MM_MODEM_IP_METHOD_PPP:
ret = ppp_stage4 (device, config, reason); ret = ppp_stage4 (self, req, config, reason);
break; break;
case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_STATIC:
ret = static_stage4 (device, config, reason); ret = static_stage4 (self, req, device, config, reason);
break; break;
case MM_MODEM_IP_METHOD_DHCP: 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; break;
default: default:
g_warning ("Invalid IP method"); g_warning ("Invalid IP method");
@@ -412,12 +471,175 @@ real_act_stage4_get_ip4_config (NMDevice *device,
return ret; return ret;
} }
static void gboolean
real_deactivate_quickly (NMDevice *device) 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; 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) { if (priv->pending_ip4_config) {
g_object_unref (priv->pending_ip4_config); g_object_unref (priv->pending_ip4_config);
priv->pending_ip4_config = NULL; priv->pending_ip4_config = NULL;
@@ -425,7 +647,7 @@ real_deactivate_quickly (NMDevice *device)
priv->in_bytes = priv->out_bytes = 0; 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: case MM_MODEM_IP_METHOD_PPP:
if (priv->ppp_manager) { if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager); g_object_unref (priv->ppp_manager);
@@ -434,8 +656,7 @@ real_deactivate_quickly (NMDevice *device)
break; break;
case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_STATIC:
case MM_MODEM_IP_METHOD_DHCP: 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_routes_with_iface (iface);
nm_system_device_flush_addresses_with_iface (iface); nm_system_device_flush_addresses_with_iface (iface);
nm_system_device_set_up_down_with_iface (iface, FALSE, NULL); 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"); g_warning ("Invalid IP method");
break; break;
} }
if (NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate)
NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate (device);
} }
static guint32 void
real_get_generic_capabilities (NMDevice *dev) 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 void
device_state_changed (NMDeviceInterface *device, nm_modem_device_state_changed (NMModem *self,
NMDeviceState new_state, NMDeviceState new_state,
NMDeviceState old_state, NMDeviceState old_state,
NMDeviceStateReason reason, NMDeviceStateReason reason)
gpointer user_data)
{ {
NMModem *self = NM_MODEM (user_data);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
gboolean was_connected = FALSE; 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)) if (IS_ACTIVATING_STATE (old_state) || (old_state == NM_DEVICE_STATE_ACTIVATED))
was_connected = TRUE; was_connected = TRUE;
/* Make sure we don't leave the serial device open */ /* Make sure we don't leave the serial device open */
switch (new_state) { switch (new_state) {
case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_NEED_AUTH:
if (priv->ppp_manager) if (NM_MODEM_GET_PRIVATE (self)->ppp_manager)
break; break;
/* else fall through */ /* else fall through */
case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNMANAGED:
@@ -490,13 +708,13 @@ device_state_changed (NMDeviceInterface *device,
} }
} }
static gboolean gboolean
real_hw_is_up (NMDevice *device) 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) { 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; NMDeviceState state;
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
@@ -507,13 +725,13 @@ real_hw_is_up (NMDevice *device)
return TRUE; return TRUE;
} }
static gboolean gboolean
real_hw_bring_up (NMDevice *device, gboolean *no_firmware) 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) { 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; NMDeviceState state;
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); 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; 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 static void
get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) 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)); query_mm_enabled (NM_MODEM (user_data));
} }
static void void
real_set_enabled (NMDeviceInterface *device, gboolean enabled) nm_modem_set_mm_enabled (NMModem *self, gboolean enabled)
{ {
NMModem *self = NM_MODEM (device); NMModemPrivate *priv;
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
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 /* 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 * 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) { if (priv->mm_enabled != enabled) {
DBusGProxy *proxy; 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, dbus_g_proxy_begin_call (proxy,
"Enable", set_mm_enabled_done, "Enable", set_mm_enabled_done,
device, NULL, self, NULL,
G_TYPE_BOOLEAN, enabled, G_TYPE_BOOLEAN, enabled,
G_TYPE_INVALID); G_TYPE_INVALID);
} }
@@ -615,30 +855,13 @@ modem_properties_changed (DBusGProxy *proxy,
value = g_hash_table_lookup (props, "Enabled"); value = g_hash_table_lookup (props, "Enabled");
if (value && G_VALUE_HOLDS_BOOLEAN (value)) { if (value && G_VALUE_HOLDS_BOOLEAN (value)) {
NMDeviceState state;
priv->mm_enabled = g_value_get_boolean (value); priv->mm_enabled = g_value_get_boolean (value);
g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); 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 static void
nm_modem_init (NMModem *self) nm_modem_init (NMModem *self)
{ {
@@ -665,7 +888,12 @@ constructor (GType type,
priv = NM_MODEM_GET_PRIVATE (object); priv = NM_MODEM_GET_PRIVATE (object);
if (!priv->device) { 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; goto err;
} }
@@ -696,8 +924,6 @@ constructor (GType type,
object, object,
NULL); NULL);
g_signal_connect (object, "state-changed", G_CALLBACK (device_state_changed), object);
query_mm_enabled (NM_MODEM (object)); query_mm_enabled (NM_MODEM (object));
return object; return object;
@@ -720,6 +946,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DEVICE: case PROP_DEVICE:
g_value_set_string (value, priv->device); g_value_set_string (value, priv->device);
break; break;
case PROP_IFACE:
g_value_set_string (value, priv->iface);
break;
case PROP_IP_METHOD: case PROP_IP_METHOD:
g_value_set_uint (value, priv->ip_method); g_value_set_uint (value, priv->ip_method);
break; break;
@@ -748,7 +977,12 @@ set_property (GObject *object, guint prop_id,
/* Construct only */ /* Construct only */
priv->device = g_value_dup_string (value); priv->device = g_value_dup_string (value);
break; break;
case PROP_IFACE:
/* Construct only */
priv->iface = g_value_dup_string (value);
break;
case PROP_IP_METHOD: case PROP_IP_METHOD:
/* Construct only */
priv->ip_method = g_value_get_uint (value); priv->ip_method = g_value_get_uint (value);
break; break;
case PROP_ENABLED: case PROP_ENABLED:
@@ -772,6 +1006,7 @@ finalize (GObject *object)
g_object_unref (priv->dbus_mgr); g_object_unref (priv->dbus_mgr);
g_free (priv->iface);
g_free (priv->path); g_free (priv->path);
g_free (priv->device); g_free (priv->device);
@@ -782,7 +1017,6 @@ static void
nm_modem_class_init (NMModemClass *klass) nm_modem_class_init (NMModemClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemPrivate)); 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->get_property = get_property;
object_class->finalize = finalize; object_class->finalize = finalize;
device_class->get_generic_capabilities = real_get_generic_capabilities; klass->act_stage1_prepare = real_act_stage1_prepare;
device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; klass->deactivate_quickly = real_deactivate_quickly;
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;
/* Properties */ /* Properties */
g_object_class_install_property g_object_class_install_property
@@ -806,7 +1036,7 @@ nm_modem_class_init (NMModemClass *klass)
"DBus path", "DBus path",
"DBus path", "DBus path",
NULL, 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 g_object_class_install_property
(object_class, PROP_DEVICE, (object_class, PROP_DEVICE,
@@ -814,7 +1044,15 @@ nm_modem_class_init (NMModemClass *klass)
"Device", "Device",
"Master modem parent device", "Master modem parent device",
NULL, 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 g_object_class_install_property
(object_class, PROP_IP_METHOD, (object_class, PROP_IP_METHOD,
@@ -824,7 +1062,7 @@ nm_modem_class_init (NMModemClass *klass)
MM_MODEM_IP_METHOD_PPP, MM_MODEM_IP_METHOD_PPP,
MM_MODEM_IP_METHOD_DHCP, MM_MODEM_IP_METHOD_DHCP,
MM_MODEM_IP_METHOD_PPP, 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 g_object_class_install_property
(object_class, PROP_ENABLED, (object_class, PROP_ENABLED,
@@ -845,10 +1083,47 @@ nm_modem_class_init (NMModemClass *klass)
G_TYPE_NONE, 2, G_TYPE_NONE, 2,
G_TYPE_UINT, G_TYPE_UINT); G_TYPE_UINT, G_TYPE_UINT);
signals[PROPERTIES_CHANGED] = signals[PPP_FAILED] =
nm_properties_changed_signal_new (object_class, g_signal_new ("ppp-failed",
G_STRUCT_OFFSET (NMModemClass, properties_changed)); 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), signals[IP4_CONFIG_RESULT] =
&dbus_glib_nm_serial_device_object_info); 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;
}

View File

@@ -23,8 +23,9 @@
#define NM_MODEM_H #define NM_MODEM_H
#include <dbus/dbus-glib.h> #include <dbus/dbus-glib.h>
#include <nm-device.h> #include <glib-object.h>
#include "ppp-manager/nm-ppp-manager.h" #include "ppp-manager/nm-ppp-manager.h"
#include "nm-device.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -37,37 +38,120 @@ G_BEGIN_DECLS
#define NM_MODEM_PATH "path" #define NM_MODEM_PATH "path"
#define NM_MODEM_DEVICE "device" #define NM_MODEM_DEVICE "device"
#define NM_MODEM_IFACE "iface"
#define NM_MODEM_IP_METHOD "ip-method" #define NM_MODEM_IP_METHOD "ip-method"
#define NM_MODEM_ENABLED "enabled" #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 { typedef struct {
NMDevice parent; GObject parent;
} NMModem; } NMModem;
typedef struct { typedef struct {
NMDeviceClass parent; GObjectClass parent;
const char *(*get_ppp_name) (NMModem *self, gboolean (*get_user_pass) (NMModem *modem,
NMConnection *connection); 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 */ /* Signals */
void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes); void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes);
void (*properties_changed) (NMModem *self, GHashTable *properties); 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; } NMModemClass;
GType nm_modem_get_type (void); GType nm_modem_get_type (void);
/* Protected */ /* Protected */
NMPPPManager *nm_modem_get_ppp_manager (NMModem *self); NMPPPManager *nm_modem_get_ppp_manager (NMModem *modem);
DBusGProxy *nm_modem_get_proxy (NMModem *self, DBusGProxy * nm_modem_get_proxy (NMModem *modem, const char *interface);
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 *nm_modem_get_best_auto_connection (NMModem *self,
NMConnection *connection); GSList *connections,
char **specific_object);
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); gboolean nm_modem_get_mm_enabled (NMModem *self);
void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled);
G_END_DECLS G_END_DECLS
#endif /* NM_MODEM_H */ #endif /* NM_MODEM_H */

View File

@@ -52,13 +52,12 @@ typedef struct {
guint32 capabilities; guint32 capabilities;
DBusGProxy *type_proxy; DBusGProxy *type_proxy;
DBusGProxy *dev_proxy;
NMPPPManager *ppp_manager;
char *rfcomm_iface; char *rfcomm_iface;
guint32 in_bytes; NMModem *modem;
guint32 out_bytes; guint32 timeout_id;
NMIP4Config *pending_ip4_config;
guint32 bt_type; /* BT type of the current connection */ guint32 bt_type; /* BT type of the current connection */
} NMDeviceBtPrivate; } 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) guint32 nm_device_bt_get_capabilities (NMDeviceBt *self)
{ {
g_return_val_if_fail (self != NULL, NM_BT_CAPABILITY_NONE); g_return_val_if_fail (self != NULL, NM_BT_CAPABILITY_NONE);
@@ -281,16 +255,26 @@ real_get_generic_capabilities (NMDevice *dev)
/* IP method PPP */ /* IP method PPP */
static void 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); NMDevice *device = NM_DEVICE (user_data);
switch (status) { switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) {
case NM_PPP_STATUS_DISCONNECT: case NM_DEVICE_STATE_PREPARE:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); case NM_DEVICE_STATE_CONFIG:
break; case NM_DEVICE_STATE_NEED_AUTH:
case NM_PPP_STATUS_DEAD: case NM_DEVICE_STATE_IP_CONFIG:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); case NM_DEVICE_STATE_ACTIVATED:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
break; break;
default: default:
break; break;
@@ -298,68 +282,126 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_
} }
static void static void
ppp_ip4_config (NMPPPManager *ppp_manager, modem_need_auth (NMModem *modem,
const char *iface, const char *setting_name,
NMIP4Config *config, gboolean retry,
gpointer user_data) RequestSecretsCaller caller,
{ const char *hint1,
NMDevice *device = NM_DEVICE (user_data); const char *hint2,
/* Ignore PPP IP4 events that come in after initial configuration */
if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG)
return;
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);
}
static void
ppp_stats (NMPPPManager *ppp_manager,
guint32 in_bytes,
guint32 out_bytes,
gpointer user_data) gpointer user_data)
{ {
NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBt *self = NM_DEVICE_BT (user_data);
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMActRequest *req;
if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { req = nm_device_get_act_request (NM_DEVICE (self));
priv->in_bytes = in_bytes; g_assert (req);
priv->out_bytes = out_bytes;
g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes); 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_CONFIG);
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 static gboolean
get_ppp_credentials (NMConnection *connection, modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason)
const char **username,
const char **password)
{ {
NMSettingGsm *s_gsm; NMActRequest *req;
NMSettingCdma *s_cdma = NULL; NMActStageReturn ret;
s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); g_return_val_if_fail (reason != NULL, FALSE);
if (s_gsm) {
if (username) req = nm_device_get_act_request (NM_DEVICE (self));
*username = nm_setting_gsm_get_username (s_gsm); g_assert (req);
if (password)
*password = nm_setting_gsm_get_password (s_gsm); ret = nm_modem_act_stage1_prepare (modem, req, reason);
} else { switch (ret) {
/* Try CDMA then */ case NM_ACT_STAGE_RETURN_POSTPONE:
s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); case NM_ACT_STAGE_RETURN_SUCCESS:
if (s_cdma) { /* Success, wait for the 'prepare-result' signal */
if (username) return TRUE;
*username = nm_setting_cdma_get_username (s_cdma); case NM_ACT_STAGE_RETURN_FAILURE:
if (password) default:
*password = nm_setting_cdma_get_password (s_cdma); break;
}
} }
return (s_cdma || s_gsm) ? TRUE : FALSE; return FALSE;
} }
static void static void
real_connection_secrets_updated (NMDevice *device, real_connection_secrets_updated (NMDevice *device,
NMConnection *connection, NMConnection *connection,
@@ -369,109 +411,132 @@ real_connection_secrets_updated (NMDevice *device,
NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBt *self = NM_DEVICE_BT (device);
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
NMActRequest *req; NMActRequest *req;
const char *username = NULL, *password = NULL; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
gboolean success = FALSE;
if (caller != SECRETS_CALLER_PPP) g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device)));
return;
g_return_if_fail (priv->ppp_manager);
req = nm_device_get_act_request (device); req = nm_device_get_act_request (device);
g_assert (req); g_assert (req);
success = get_ppp_credentials (nm_act_request_get_connection (req), if (!nm_modem_connection_secrets_updated (priv->modem,
&username, req,
&password); connection,
if (success) { updated_settings,
nm_ppp_manager_update_secrets (priv->ppp_manager, caller)) {
nm_device_get_ip_iface (device), nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS);
username ? username : "",
password ? password : "",
NULL);
return; return;
} }
/* Shouldn't ever happen */ /* PPP handles stuff itself... */
nm_ppp_manager_update_secrets (priv->ppp_manager, if (caller == SECRETS_CALLER_PPP)
nm_device_get_ip_iface (device), return;
NULL,
NULL,
"missing GSM/CDMA setting; no secrets could be found.");
}
static NMActStageReturn /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */
ppp_stage3_start (NMDevice *device, NMDeviceStateReason *reason) g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
{ if (!modem_stage1 (self, priv->modem, &reason))
NMDeviceBt *self = NM_DEVICE_BT (device); nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason);
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;
} }
/*****************************************************************************/ /*****************************************************************************/
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 static void
nm_device_bt_connect_cb (DBusGProxy *proxy, bluez_connect_cb (DBusGProxy *proxy,
DBusGProxyCall *call_id, DBusGProxyCall *call_id,
void *user_data) void *user_data)
{ {
@@ -510,6 +575,20 @@ nm_device_bt_connect_cb (DBusGProxy *proxy,
/* Stage 3 gets scheduled when Bluez says we're connected */ /* 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 static void
bluez_property_changed (DBusGProxy *proxy, bluez_property_changed (DBusGProxy *proxy,
const char *property, const char *property,
@@ -528,18 +607,29 @@ bluez_property_changed (DBusGProxy *proxy,
state = nm_device_get_state (device); state = nm_device_get_state (device);
connected = g_value_get_boolean (value); connected = g_value_get_boolean (value);
if (connected) { if (connected) {
/* Bluez says we're connected now. Start IP config. */
if (state == NM_DEVICE_STATE_CONFIG) { if (state == NM_DEVICE_STATE_CONFIG) {
gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP); gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP);
gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN); gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN);
nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) " 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), nm_device_get_iface (device),
dun ? "DUN" : (pan ? "PAN" : "unknown")); dun ? "DUN" : (pan ? "PAN" : "unknown"));
if (pan) {
/* Bluez says we're connected now. Start IP config. */
nm_device_activate_schedule_stage3_ip_config_start (device); 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 { } else {
gboolean fail = FALSE; gboolean fail = FALSE;
@@ -567,6 +657,7 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
NMActRequest *req; NMActRequest *req;
NMDBusManager *dbus_mgr; NMDBusManager *dbus_mgr;
DBusGConnection *g_connection; DBusGConnection *g_connection;
gboolean dun = FALSE;
req = nm_device_get_act_request (device); req = nm_device_get_act_request (device);
g_assert (req); 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_connection = nm_dbus_manager_get_connection (dbus_mgr);
g_object_unref (dbus_mgr); g_object_unref (dbus_mgr);
if (priv->bt_type == NM_BT_CAPABILITY_DUN) { if (priv->bt_type == NM_BT_CAPABILITY_DUN)
priv->type_proxy = dbus_g_proxy_new_for_name (g_connection, dun = TRUE;
BLUEZ_SERVICE, else if (priv->bt_type == NM_BT_CAPABILITY_NAP)
nm_device_get_udi (device), dun = FALSE;
BLUEZ_SERIAL_INTERFACE); else
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
g_assert_not_reached (); 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 */ /* Watch for BT device property changes */
dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED,
G_TYPE_NONE, G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_STRING, G_TYPE_VALUE,
G_TYPE_INVALID); 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); 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); 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; 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); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
NMActStageReturn ret; NMActStageReturn ret;
if (priv->bt_type == NM_BT_CAPABILITY_DUN) if (priv->bt_type == NM_BT_CAPABILITY_DUN) {
ret = ppp_stage3_start (device, reason); ret = nm_modem_stage3_ip4_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem,
else 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); ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, reason);
return ret; return ret;
@@ -653,9 +744,13 @@ real_act_stage4_get_ip4_config (NMDevice *device,
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
NMActStageReturn ret; NMActStageReturn ret;
if (priv->bt_type == NM_BT_CAPABILITY_DUN) if (priv->bt_type == NM_BT_CAPABILITY_DUN) {
ret = ppp_stage4 (device, config, reason); ret = nm_modem_stage4_get_ip4_config (NM_DEVICE_BT_GET_PRIVATE (device)->modem,
else 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); ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage4_get_ip4_config (device, config, reason);
return ret; return ret;
@@ -666,17 +761,20 @@ real_deactivate_quickly (NMDevice *device)
{ {
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (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->bt_type == NM_BT_CAPABILITY_DUN) {
if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager); if (priv->modem) {
priv->ppp_manager = NULL; 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) { 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; priv->bt_type = NM_BT_CAPABILITY_NONE;
g_free (priv->rfcomm_iface); 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); 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 static void
nm_device_bt_init (NMDeviceBt *self) nm_device_bt_init (NMDeviceBt *self)
{ {
@@ -766,9 +907,21 @@ finalize (GObject *object)
{ {
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (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) if (priv->type_proxy)
g_object_unref (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->bdaddr);
g_free (priv->name); g_free (priv->name);

View File

@@ -22,6 +22,7 @@
#define NM_DEVICE_BT_H #define NM_DEVICE_BT_H
#include <nm-device.h> #include <nm-device.h>
#include "nm-modem.h"
G_BEGIN_DECLS 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); 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 G_END_DECLS
#endif /* NM_GSM_DEVICE_H */ #endif /* NM_GSM_DEVICE_H */

411
src/nm-device-cdma.c Normal file
View File

@@ -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 <string.h>
#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);
}

56
src/nm-device-cdma.h Normal file
View File

@@ -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 */

411
src/nm-device-gsm.c Normal file
View File

@@ -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 <string.h>
#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);
}

56
src/nm-device-gsm.h Normal file
View File

@@ -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 */

View File

@@ -37,6 +37,8 @@
#include "nm-device-ethernet.h" #include "nm-device-ethernet.h"
#include "nm-device-wifi.h" #include "nm-device-wifi.h"
#include "nm-device-olpc-mesh.h" #include "nm-device-olpc-mesh.h"
#include "nm-device-cdma.h"
#include "nm-device-gsm.h"
#include "NetworkManagerSystem.h" #include "NetworkManagerSystem.h"
#include "nm-properties-changed-signal.h" #include "nm-properties-changed-signal.h"
#include "nm-setting-bluetooth.h" #include "nm-setting-bluetooth.h"
@@ -127,16 +129,16 @@ static const char *internal_activate_device (NMManager *manager,
gboolean assumed, gboolean assumed,
GError **error); GError **error);
static NMDevice * static NMDevice *find_device_by_iface (NMManager *self, const gchar *iface);
find_device_by_iface (NMManager *self, const gchar *iface);
static GSList * static GSList * remove_one_device (NMManager *manager,
remove_one_device (NMManager *manager,
GSList *list, GSList *list,
NMDevice *device, NMDevice *device,
gboolean quitting, gboolean quitting,
gboolean force_unmanage); gboolean force_unmanage);
static NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi);
#define SSD_POKE_INTERVAL 120 #define SSD_POKE_INTERVAL 120
#define ORIGDEV_TAG "originating-device" #define ORIGDEV_TAG "originating-device"
@@ -310,26 +312,17 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager,
static void static void
modem_added (NMModemManager *modem_manager, modem_added (NMModemManager *modem_manager,
NMDevice *modem, NMModem *modem,
const char *driver,
gpointer user_data) gpointer user_data)
{ {
NMManagerPrivate *priv; NMManager *self = NM_MANAGER (user_data);
NMDeviceType type; NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMDevice *replace_device; NMDevice *replace_device, *device = NULL;
const char *type_name;
const char *ip_iface; const char *ip_iface;
GSList *iter;
priv = NM_MANAGER_GET_PRIVATE (user_data); ip_iface = nm_modem_get_iface (modem);
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);
replace_device = find_device_by_iface (NM_MANAGER (user_data), ip_iface); replace_device = find_device_by_iface (NM_MANAGER (user_data), ip_iface);
if (replace_device) { if (replace_device) {
@@ -340,7 +333,34 @@ modem_added (NMModemManager *modem_manager,
TRUE); 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 static void
@@ -438,13 +458,26 @@ remove_one_device (NMManager *manager,
static void static void
modem_removed (NMModemManager *modem_manager, modem_removed (NMModemManager *modem_manager,
NMDevice *modem, NMModem *modem,
gpointer user_data) gpointer user_data)
{ {
NMManager *self = NM_MANAGER (user_data); NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); 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 static void
@@ -1440,7 +1473,7 @@ add_device (NMManager *self, NMDevice *device)
iface = nm_device_get_ip_iface (device); iface = nm_device_get_ip_iface (device);
g_assert (iface); 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); g_object_unref (device);
return; return;
} }
@@ -1733,12 +1766,14 @@ find_device_by_iface (NMManager *self, const gchar *iface)
{ {
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *iter; GSList *iter;
for (iter = priv->devices; iter; iter = g_slist_next (iter)) { for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
NMDevice *device = NM_DEVICE (iter->data); NMDevice *device = NM_DEVICE (iter->data);
const gchar *d_iface = nm_device_get_ip_iface (device); const gchar *d_iface = nm_device_get_ip_iface (device);
if (!strcmp (d_iface, iface)) if (!strcmp (d_iface, iface))
return device; return device;
} }
return NULL; return NULL;
} }
@@ -3124,9 +3159,9 @@ nm_manager_init (NMManager *manager)
g_object_unref); g_object_unref);
priv->modem_manager = nm_modem_manager_get (); 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); 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); G_CALLBACK (modem_removed), manager);
priv->vpn_manager = nm_vpn_manager_get (); priv->vpn_manager = nm_vpn_manager_get ();

View File

@@ -28,8 +28,7 @@ typedef enum {
SECRETS_CALLER_NONE = 0, SECRETS_CALLER_NONE = 0,
SECRETS_CALLER_ETHERNET, SECRETS_CALLER_ETHERNET,
SECRETS_CALLER_WIFI, SECRETS_CALLER_WIFI,
SECRETS_CALLER_GSM, SECRETS_CALLER_MOBILE_BROADBAND,
SECRETS_CALLER_CDMA,
SECRETS_CALLER_PPP, SECRETS_CALLER_PPP,
SECRETS_CALLER_VPN SECRETS_CALLER_VPN
} RequestSecretsCaller; } RequestSecretsCaller;