modem: generalize GSM and CDMA modem classes

So that Bluetooth can use them.  They used to be NMDevice subclasses, but
we need them to be generic objects that both bluetooth and the normal
modem stack can use.  All because GObject can't do multiple inheritance,
but that would probably be even messier.

So now that we have generic modem objects, we can create the actual
NMDevice subclasses that will wrap them for non-BT modems, and then
also have NMDeviceBt wrap them too for DUN.
This commit is contained in:
Dan Williams 2009-10-04 21:41:49 -07:00
parent 12aa505d3c
commit c5cf3b1d9b
11 changed files with 709 additions and 497 deletions

View file

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

View file

@ -7,12 +7,12 @@ INCLUDES = \
noinst_LTLIBRARIES = libmodem-manager.la
libmodem_manager_la_SOURCES = \
nm-modem.c \
nm-modem.h \
nm-modem-cdma.c \
nm-modem-cdma.h \
nm-modem-gsm.c \
nm-modem-gsm.h \
nm-modem.c \
nm-modem.h \
nm-modem-manager.h \
nm-modem-manager.c \
nm-modem-types.h

View file

@ -17,6 +17,12 @@
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;
} NMModemCdmaPrivate;
typedef enum {
NM_CDMA_ERROR_CONNECTION_NOT_CDMA = 0,
@ -60,41 +66,41 @@ nm_cdma_error_get_type (void)
}
NMDevice *
NMModem *
nm_modem_cdma_new (const char *path,
const char *device,
const char *data_device,
const char *driver)
guint32 ip_method)
{
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (data_device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
return (NMDevice *) g_object_new (NM_TYPE_MODEM_CDMA,
NM_DEVICE_INTERFACE_UDI, path,
NM_DEVICE_INTERFACE_IFACE, data_device,
NM_DEVICE_INTERFACE_DRIVER, driver,
NM_MODEM_PATH, path,
NM_MODEM_DEVICE, device,
NM_DEVICE_INTERFACE_TYPE_DESC, "CDMA",
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA,
NULL);
return (NMModem *) g_object_new (NM_TYPE_MODEM_CDMA,
NM_MODEM_PATH, path,
NM_MODEM_DEVICE, device,
NM_MODEM_IFACE, data_device,
NM_MODEM_IP_METHOD, ip_method,
NULL);
}
static void
stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
NMModemCdma *self = NM_MODEM_CDMA (user_data);
NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self);
GError *error = NULL;
dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID);
if (!error)
nm_device_activate_schedule_stage2_device_config (device);
priv->call = NULL;
if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID))
g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE);
else {
nm_warning ("CDMA modem connection failed: %s", error->message);
nm_warning ("CDMA connection failed: (%d) %s",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE);
g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_NONE);
}
}
@ -116,26 +122,41 @@ create_connect_properties (NMConnection *connection)
}
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)
{
NMModemCdma *self = NM_MODEM_CDMA (modem);
NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self);
NMConnection *connection;
GHashTable *properties;
connection = nm_act_request_get_connection (nm_device_get_act_request (device));
connection = nm_act_request_get_connection (req);
g_assert (connection);
properties = create_connect_properties (connection);
dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE),
"Connect", stage1_prepare_done,
device, NULL, 120000,
DBUS_TYPE_G_MAP_OF_VARIANT, properties,
G_TYPE_INVALID);
*out_setting_name = nm_connection_need_secrets (connection, out_hints);
if (!*out_setting_name) {
DBusGProxy *proxy;
GHashTable *properties;
properties = create_connect_properties (connection);
proxy = nm_modem_get_proxy (modem, 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, properties,
G_TYPE_INVALID);
g_hash_table_destroy (properties);
} else {
/* NMModem will handle requesting secrets... */
}
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMConnection *
real_get_best_auto_connection (NMDevice *dev,
real_get_best_auto_connection (NMModem *modem,
GSList *connections,
char **specific_object)
{
@ -159,69 +180,8 @@ real_get_best_auto_connection (NMDevice *dev,
return NULL;
}
static void
real_connection_secrets_updated (NMDevice *dev,
NMConnection *connection,
GSList *updated_settings,
RequestSecretsCaller caller)
{
NMActRequest *req;
gboolean found = FALSE;
GSList *iter;
if (caller == SECRETS_CALLER_PPP) {
NMPPPManager *ppp_manager;
NMSettingCdma *s_cdma = NULL;
ppp_manager = nm_modem_get_ppp_manager (NM_MODEM (dev));
g_return_if_fail (ppp_manager != NULL);
s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
if (!s_cdma) {
/* Shouldn't ever happen */
nm_ppp_manager_update_secrets (ppp_manager,
nm_device_get_iface (dev),
NULL,
NULL,
"missing CDMA setting; no secrets could be found.");
} else {
const char *username = nm_setting_cdma_get_username (s_cdma);
const char *password = nm_setting_cdma_get_password (s_cdma);
nm_ppp_manager_update_secrets (ppp_manager,
nm_device_get_iface (dev),
username ? username : "",
password ? password : "",
NULL);
}
return;
}
g_return_if_fail (caller == SECRETS_CALLER_CDMA);
g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
const char *setting_name = (const char *) iter->data;
if (!strcmp (setting_name, NM_SETTING_CDMA_SETTING_NAME))
found = TRUE;
else
nm_warning ("Ignoring updated secrets for setting '%s'.", setting_name);
}
if (!found)
return;
req = nm_device_get_act_request (dev);
g_assert (req);
g_return_if_fail (nm_act_request_get_connection (req) == connection);
nm_device_activate_schedule_stage1_device_prepare (dev);
}
static gboolean
real_check_connection_compatible (NMDevice *device,
real_check_connection_compatible (NMModem *modem,
NMConnection *connection,
GError **error)
{
@ -249,15 +209,46 @@ real_check_connection_compatible (NMDevice *device,
return TRUE;
}
static const char *
real_get_ppp_name (NMModem *device, NMConnection *connection)
static gboolean
real_get_user_pass (NMModem *modem,
NMConnection *connection,
const char **user,
const char **pass)
{
NMSettingCdma *s_cdma;
s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
g_assert (s_cdma);
if (!s_cdma)
return FALSE;
return nm_setting_cdma_get_username (s_cdma);
if (user)
*user = nm_setting_cdma_get_username (s_cdma);
if (pass)
*pass = nm_setting_cdma_get_password (s_cdma);
return TRUE;
}
static const char *
real_get_setting_name (NMModem *modem)
{
return NM_SETTING_CDMA_SETTING_NAME;
}
static void
real_deactivate_quickly (NMModem *modem, NMDevice *device)
{
NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (modem);
if (priv->call) {
DBusGProxy *proxy;
proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE);
dbus_g_proxy_cancel_call (proxy, priv->call);
priv->call = NULL;
}
NM_MODEM_CLASS (nm_modem_cdma_parent_class)->deactivate_quickly (modem, device);
}
/*****************************************************************************/
@ -270,19 +261,18 @@ nm_modem_cdma_init (NMModemCdma *self)
static void
nm_modem_cdma_class_init (NMModemCdmaClass *klass)
{
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMModemClass *modem_class = NM_MODEM_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemCdmaPrivate));
/* Virtual methods */
device_class->get_best_auto_connection = real_get_best_auto_connection;
device_class->connection_secrets_updated = real_connection_secrets_updated;
device_class->act_stage1_prepare = real_act_stage1_prepare;
device_class->check_connection_compatible = real_check_connection_compatible;
modem_class->get_ppp_name = real_get_ppp_name;
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
&dbus_glib_nm_device_cdma_object_info);
modem_class->get_user_pass = real_get_user_pass;
modem_class->get_setting_name = real_get_setting_name;
modem_class->get_best_auto_connection = real_get_best_auto_connection;
modem_class->check_connection_compatible = real_check_connection_compatible;
modem_class->act_stage1_prepare = real_act_stage1_prepare;
modem_class->deactivate_quickly = real_deactivate_quickly;
dbus_g_error_domain_register (NM_CDMA_ERROR, NULL, NM_TYPE_CDMA_ERROR);
}

View file

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

View file

@ -31,10 +31,14 @@ typedef enum {
} MMModemGsmMode;
#define GSM_SECRETS_TRIES "gsm-secrets-tries"
G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM)
#define NM_MODEM_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_GSM, NMModemGsmPrivate))
typedef struct {
DBusGProxyCall *call;
} NMModemGsmPrivate;
typedef enum {
NM_GSM_ERROR_CONNECTION_NOT_GSM = 0,
@ -78,28 +82,22 @@ nm_gsm_error_get_type (void)
}
NMDevice *
NMModem *
nm_modem_gsm_new (const char *path,
const char *device,
const char *data_device,
const char *driver,
guint32 ip_method)
{
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (data_device != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
return (NMDevice *) g_object_new (NM_TYPE_MODEM_GSM,
NM_DEVICE_INTERFACE_UDI, path,
NM_DEVICE_INTERFACE_IFACE, data_device,
NM_DEVICE_INTERFACE_DRIVER, driver,
NM_MODEM_PATH, path,
NM_MODEM_IP_METHOD, ip_method,
NM_MODEM_DEVICE, device,
NM_DEVICE_INTERFACE_TYPE_DESC, "GSM",
NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM,
NULL);
return (NMModem *) g_object_new (NM_TYPE_MODEM_GSM,
NM_MODEM_PATH, path,
NM_MODEM_DEVICE, device,
NM_MODEM_IFACE, data_device,
NM_MODEM_IP_METHOD, ip_method,
NULL);
}
static NMDeviceStateReason
@ -138,31 +136,16 @@ translate_mm_error (GError *error)
}
static void
clear_pin (NMDevice *device)
stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMActRequest *req;
NMConnection *connection;
NMSettingGsm *setting;
req = nm_device_get_act_request (device);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
setting = NM_SETTING_GSM (nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM));
g_assert (setting);
g_object_set (G_OBJECT (setting), NM_SETTING_GSM_PIN, NULL, NULL);
}
static void
stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
NMModemGsm *self = NM_MODEM_GSM (user_data);
NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
GError *error = NULL;
dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID);
if (!error)
nm_device_activate_schedule_stage2_device_config (device);
priv->call = 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 {
const char *required_secret = NULL;
gboolean retry_secret = FALSE;
@ -170,22 +153,23 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d
if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN))
required_secret = NM_SETTING_GSM_PIN;
else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) {
clear_pin (device);
required_secret = NM_SETTING_GSM_PIN;
retry_secret = TRUE;
} else
nm_warning ("GSM modem connection failed: %s", error->message);
} else {
nm_warning ("GSM connection failed: (%d) %s",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
}
if (required_secret) {
nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
nm_act_request_get_secrets (nm_device_get_act_request (device),
NM_SETTING_GSM_SETTING_NAME,
retry_secret,
SECRETS_CALLER_GSM,
required_secret,
NULL);
g_signal_emit_by_name (self, NM_MODEM_NEED_AUTH,
NM_SETTING_GSM_SETTING_NAME,
retry_secret,
SECRETS_CALLER_MOBILE_BROADBAND,
required_secret,
NULL);
} else
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, translate_mm_error (error));
g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error));
g_error_free (error);
}
@ -248,60 +232,41 @@ create_connect_properties (NMConnection *connection)
}
static NMActStageReturn
real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
real_act_stage1_prepare (NMModem *modem,
NMActRequest *req,
GPtrArray **out_hints,
const char **out_setting_name,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMModemGsm *self = NM_MODEM_GSM (modem);
NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self);
NMConnection *connection;
const char *setting_name;
GPtrArray *hints = NULL;
const char *hint1 = NULL, *hint2 = NULL;
guint32 tries;
req = nm_device_get_act_request (device);
g_assert (req);
connection = nm_act_request_get_connection (req);
g_assert (connection);
setting_name = nm_connection_need_secrets (connection, &hints);
if (!setting_name) {
*out_setting_name = nm_connection_need_secrets (connection, out_hints);
if (!*out_setting_name) {
DBusGProxy *proxy;
GHashTable *properties;
properties = create_connect_properties (connection);
dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE),
"Connect", stage1_prepare_done,
device, NULL, 120000,
DBUS_TYPE_G_MAP_OF_VARIANT, properties,
G_TYPE_INVALID);
return NM_ACT_STAGE_RETURN_POSTPONE;
proxy = nm_modem_get_proxy (modem, 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, properties,
G_TYPE_INVALID);
g_hash_table_destroy (properties);
} else {
/* NMModem will handle requesting 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);
}
nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), GSM_SECRETS_TRIES));
nm_act_request_get_secrets (req,
setting_name,
tries ? TRUE : FALSE,
SECRETS_CALLER_GSM,
hint1,
hint2);
g_object_set_data (G_OBJECT (connection), GSM_SECRETS_TRIES, GUINT_TO_POINTER (++tries));
if (hints)
g_ptr_array_free (hints, TRUE);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMConnection *
real_get_best_auto_connection (NMDevice *dev,
real_get_best_auto_connection (NMModem *modem,
GSList *connections,
char **specific_object)
{
@ -325,109 +290,8 @@ real_get_best_auto_connection (NMDevice *dev,
return NULL;
}
static void
real_connection_secrets_updated (NMDevice *dev,
NMConnection *connection,
GSList *updated_settings,
RequestSecretsCaller caller)
{
NMActRequest *req;
gboolean found = FALSE;
GSList *iter;
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);
}
if (NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly)
NM_DEVICE_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly (device);
}
static gboolean
real_check_connection_compatible (NMDevice *device,
real_check_connection_compatible (NMModem *modem,
NMConnection *connection,
GError **error)
{
@ -455,17 +319,49 @@ real_check_connection_compatible (NMDevice *device,
return TRUE;
}
static const char *
real_get_ppp_name (NMModem *device, NMConnection *connection)
static gboolean
real_get_user_pass (NMModem *modem,
NMConnection *connection,
const char **user,
const char **pass)
{
NMSettingGsm *s_gsm;
s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
g_assert (s_gsm);
if (!s_gsm)
return FALSE;
return nm_setting_gsm_get_username (s_gsm);
if (user)
*user = nm_setting_gsm_get_username (s_gsm);
if (pass)
*pass = nm_setting_gsm_get_password (s_gsm);
return TRUE;
}
static const char *
real_get_setting_name (NMModem *modem)
{
return NM_SETTING_GSM_SETTING_NAME;
}
static void
real_deactivate_quickly (NMModem *modem, NMDevice *device)
{
NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (modem);
if (priv->call) {
DBusGProxy *proxy;
proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE);
dbus_g_proxy_cancel_call (proxy, priv->call);
priv->call = NULL;
}
NM_MODEM_CLASS (nm_modem_gsm_parent_class)->deactivate_quickly (modem, device);
}
/*****************************************************************************/
static void
@ -476,21 +372,20 @@ nm_modem_gsm_init (NMModemGsm *self)
static void
nm_modem_gsm_class_init (NMModemGsmClass *klass)
{
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMModemClass *modem_class = NM_MODEM_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate));
/* Virtual methods */
device_class->get_best_auto_connection = real_get_best_auto_connection;
device_class->connection_secrets_updated = real_connection_secrets_updated;
device_class->act_stage1_prepare = real_act_stage1_prepare;
device_class->act_stage2_config = real_act_stage2_config;
device_class->deactivate_quickly = real_deactivate_quickly;
device_class->check_connection_compatible = real_check_connection_compatible;
modem_class->get_user_pass = real_get_user_pass;
modem_class->get_setting_name = real_get_setting_name;
modem_class->get_best_auto_connection = real_get_best_auto_connection;
modem_class->check_connection_compatible = real_check_connection_compatible;
modem_class->act_stage1_prepare = real_act_stage1_prepare;
modem_class->deactivate_quickly = real_deactivate_quickly;
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);
// device_class->act_stage2_config = real_act_stage2_config;
dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR);
}

View file

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

View file

@ -8,6 +8,7 @@
#include "nm-dbus-manager.h"
#include "nm-utils.h"
#include "nm-modem-types.h"
#include "nm-marshal.h"
#define MODEM_POKE_INTERVAL 120
@ -24,8 +25,8 @@ typedef struct {
} NMModemManagerPrivate;
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
MODEM_ADDED,
MODEM_REMOVED,
LAST_SIGNAL
};
@ -58,9 +59,10 @@ nm_modem_manager_has_modem_for_iface (NMModemManager *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))
NMModem *modem = NM_MODEM (iter->data);
const char *modem_iface = nm_modem_get_iface (modem);
if (!g_strcmp0 (iface, modem_iface))
return TRUE;
}
return FALSE;
@ -162,7 +164,7 @@ static void
create_modem (NMModemManager *manager, const char *path)
{
NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager);
NMDevice *device;
NMModem *modem;
char *data_device = NULL, *driver = NULL, *master_device = NULL;
uint modem_type = MM_MODEM_TYPE_UNKNOWN;
uint ip_method = MM_MODEM_IP_METHOD_PPP;
@ -198,19 +200,20 @@ create_modem (NMModemManager *manager, const char *path)
}
if (modem_type == MM_MODEM_TYPE_GSM)
device = nm_modem_gsm_new (path, master_device, data_device, driver, ip_method);
modem = nm_modem_gsm_new (path, master_device, data_device, ip_method);
else if (modem_type == MM_MODEM_TYPE_CDMA)
device = nm_modem_cdma_new (path, master_device, data_device, driver);
modem = nm_modem_cdma_new (path, master_device, data_device, ip_method);
else
g_error ("Invalid modem type");
g_free (data_device);
g_free (driver);
if (device) {
g_hash_table_insert (priv->modems, g_strdup (path), device);
g_signal_emit (manager, signals[DEVICE_ADDED], 0, device);
if (modem) {
g_hash_table_insert (priv->modems, g_strdup (path), modem);
g_signal_emit (manager, signals[MODEM_ADDED], 0, modem, driver);
}
g_free (driver);
}
static void
@ -227,7 +230,7 @@ modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
modem = (NMModem *) g_hash_table_lookup (priv->modems, path);
if (modem) {
g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, modem);
g_signal_emit (user_data, signals[MODEM_REMOVED], 0, modem);
g_hash_table_remove (priv->modems, path);
}
}
@ -310,7 +313,7 @@ modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices)
static gboolean
remove_one_modem (gpointer key, gpointer value, gpointer user_data)
{
g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, value);
g_signal_emit (user_data, signals[MODEM_REMOVED], 0, value);
return TRUE;
}
@ -420,23 +423,21 @@ nm_modem_manager_class_init (NMModemManagerClass *klass)
object_class->dispose = dispose;
/* signals */
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
signals[MODEM_ADDED] =
g_signal_new ("modem-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemManagerClass, device_added),
G_STRUCT_OFFSET (NMModemManagerClass, modem_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
_nm_marshal_VOID__OBJECT_STRING,
G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING);
signals[DEVICE_REMOVED] =
g_signal_new ("device-removed",
signals[MODEM_REMOVED] =
g_signal_new ("modem-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemManagerClass, device_removed),
G_STRUCT_OFFSET (NMModemManagerClass, modem_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
G_TYPE_NONE, 1, G_TYPE_OBJECT);
}

View file

@ -4,7 +4,7 @@
#define NM_MODEM_MANAGER_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_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_MANAGER, NMModemManager))
@ -21,11 +21,9 @@ typedef struct {
GObjectClass parent;
/* Signals */
void (*device_added) (NMModemManager *manager,
NMDevice *device);
void (*modem_added) (NMModemManager *manager, NMModem *modem, const char *driver);
void (*device_removed) (NMModemManager *manager,
NMDevice *device);
void (*modem_removed) (NMModemManager *manager, NMModem *modem);
} NMModemManagerClass;
GType nm_modem_manager_get_type (void);

View file

@ -2,27 +2,25 @@
#include <string.h>
#include "nm-modem.h"
#include "nm-device-private.h"
#include "NetworkManagerSystem.h"
#include "nm-device-interface.h"
#include "nm-dbus-manager.h"
#include "nm-setting-connection.h"
#include "nm-setting-gsm.h"
#include "nm-setting-cdma.h"
#include "nm-marshal.h"
#include "nm-properties-changed-signal.h"
#include "nm-modem-types.h"
#include "nm-utils.h"
#include "nm-serial-device-glue.h"
#include "NetworkManagerUtils.h"
#include "nm-device-private.h"
#include "nm-device-interface.h"
G_DEFINE_TYPE (NMModem, nm_modem, NM_TYPE_DEVICE)
G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT)
#define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate))
enum {
PROP_0,
PROP_DEVICE,
PROP_IFACE,
PROP_PATH,
PROP_IP_METHOD,
@ -37,6 +35,11 @@ typedef struct {
NMIP4Config *pending_ip4_config;
guint32 ip_method;
char *device;
char *iface;
guint32 secrets_tries;
DBusGProxyCall *call;
/* PPP stats */
guint32 in_bytes;
@ -45,7 +48,10 @@ typedef struct {
enum {
PPP_STATS,
PROPERTIES_CHANGED,
PPP_FAILED,
PREPARE_RESULT,
IP4_CONFIG_RESULT,
NEED_AUTH,
LAST_SIGNAL
};
@ -81,17 +87,19 @@ nm_modem_get_proxy (NMModem *self,
return priv->proxy;
}
const char *
nm_modem_get_ppp_name (NMModem *self,
NMConnection *connection)
static void
merge_ip4_config (NMActRequest *req, NMIP4Config *config)
{
g_return_val_if_fail (NM_IS_MODEM (self), NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
NMConnection *connection;
NMSettingIP4Config *s_ip4;
if (NM_MODEM_GET_CLASS (self)->get_ppp_name)
return NM_MODEM_GET_CLASS (self)->get_ppp_name (self, connection);
/* Merge user-defined overrides into the IP4Config to be applied */
connection = nm_act_request_get_connection (req);
g_assert (connection);
return NULL;
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (s_ip4)
nm_utils_merge_ip4_config (config, s_ip4);
}
/*****************************************************************************/
@ -100,14 +108,12 @@ nm_modem_get_ppp_name (NMModem *self,
static void
ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
switch (status) {
case NM_PPP_STATUS_DISCONNECT:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_DISCONNECT);
break;
case NM_PPP_STATUS_DEAD:
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED);
g_signal_emit (NM_MODEM (user_data), signals[PPP_FAILED], 0, NM_DEVICE_STATE_REASON_PPP_FAILED);
break;
default:
break;
@ -120,17 +126,14 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
NMIP4Config *config,
gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
NMModem *self = NM_MODEM (user_data);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
guint32 i, num;
guint32 bad_dns1 = htonl (0x0A0B0C0D);
guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */
guint32 bad_dns2 = htonl (0x0A0B0C0E);
guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */
/* Ignore PPP IP4 events that come in after initial configuration */
if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG)
return;
/* Work around a PPP bug (#1732) which causes many mobile broadband
* providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
* Apparently fixed in ppp-2.4.5 but we've had some reports that this is
@ -164,9 +167,8 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
}
}
nm_device_set_ip_iface (device, iface);
NM_MODEM_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config);
nm_device_activate_schedule_stage4_ip4_config_get (device);
priv->pending_ip4_config = g_object_ref (config);
g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, iface, config, NULL);
}
static void
@ -187,36 +189,48 @@ ppp_stats (NMPPPManager *ppp_manager,
}
static NMActStageReturn
ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
ppp_stage3_ip4_config_start (NMModem *self,
NMActRequest *req,
NMDeviceStateReason *reason)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMActRequest *req;
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
const char *ppp_name = NULL;
GError *err = NULL;
GError *error = NULL;
NMActStageReturn ret;
req = nm_device_get_act_request (device);
g_assert (req);
g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
ppp_name = nm_modem_get_ppp_name (NM_MODEM (device),
nm_act_request_get_connection (req));
if (NM_MODEM_GET_CLASS (self)->get_user_pass) {
NMConnection *connection = nm_act_request_get_connection (req);
priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device));
if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &err)) {
g_assert (connection);
if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL))
return NM_ACT_STAGE_RETURN_FAILURE;
}
priv->ppp_manager = nm_ppp_manager_new (priv->iface);
if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &error)) {
g_signal_connect (priv->ppp_manager, "state-changed",
G_CALLBACK (ppp_state_changed),
device);
self);
g_signal_connect (priv->ppp_manager, "ip4-config",
G_CALLBACK (ppp_ip4_config),
device);
self);
g_signal_connect (priv->ppp_manager, "stats",
G_CALLBACK (ppp_stats),
device);
self);
ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else {
nm_warning ("%s", err->message);
g_error_free (err);
nm_warning ("%s: error starting PPP: (%d) %s",
__func__,
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_error_free (error);
g_object_unref (priv->ppp_manager);
priv->ppp_manager = NULL;
@ -229,20 +243,17 @@ ppp_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
}
static NMActStageReturn
ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
ppp_stage4 (NMModem *self,
NMActRequest *req,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMConnection *connection;
NMSettingIP4Config *s_ip4;
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
*config = priv->pending_ip4_config;
priv->pending_ip4_config = NULL;
/* Merge user-defined overrides into the IP4Config to be applied */
connection = nm_act_request_get_connection (nm_device_get_act_request (device));
g_assert (connection);
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
nm_utils_merge_ip4_config (*config, s_ip4);
merge_ip4_config (req, *config);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@ -251,57 +262,80 @@ ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
/* IP method static */
static void
static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
NMModem *self = NM_MODEM (user_data);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
GValueArray *ret_array = NULL;
GError *error = NULL;
if (dbus_g_proxy_end_call (proxy, call_id, &error,
priv->call = NULL;
if (dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_VALUE_ARRAY, &ret_array,
G_TYPE_INVALID)) {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMIP4Config *config;
NMIP4Address *addr;
int i;
config = nm_ip4_config_new ();
addr = nm_ip4_address_new ();
nm_ip4_address_set_address (addr, g_value_get_uint (g_value_array_get_nth (ret_array, 0)));
nm_ip4_address_set_prefix (addr, 32);
nm_ip4_config_take_address (config, addr);
priv->pending_ip4_config = nm_ip4_config_new ();
nm_ip4_config_take_address (priv->pending_ip4_config, addr);
for (i = 1; i < ret_array->n_values; i++)
nm_ip4_config_add_nameserver (priv->pending_ip4_config,
g_value_get_uint (g_value_array_get_nth (ret_array, i)));
for (i = 1; i < ret_array->n_values; i++) {
GValue *value = g_value_array_get_nth (ret_array, i);
nm_ip4_config_add_nameserver (config, g_value_get_uint (value));
}
g_value_array_free (ret_array);
nm_device_activate_schedule_stage4_ip4_config_get (device);
priv->pending_ip4_config = g_object_ref (config);
g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, NULL);
} else {
nm_warning ("Retrieving IP4 configuration failed: %s", error->message);
nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s",
__func__,
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, NULL, error);
g_error_free (error);
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
}
}
static NMActStageReturn
static_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
static_stage3_ip4_config_start (NMModem *self,
NMActRequest *req,
NMDeviceStateReason *reason)
{
dbus_g_proxy_begin_call (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM),
"GetIP4Config", static_stage3_done,
device, NULL,
G_TYPE_INVALID);
NMModemPrivate *priv;
g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
priv = NM_MODEM_GET_PRIVATE (self);
priv->call = dbus_g_proxy_begin_call (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM),
"GetIP4Config", static_stage3_done,
self, NULL,
G_TYPE_INVALID);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMActStageReturn
static_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason)
static_stage4 (NMModem *self,
NMActRequest *req,
NMDevice *device,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
gboolean no_firmware = FALSE;
if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) {
@ -315,25 +349,42 @@ static_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reas
*config = priv->pending_ip4_config;
priv->pending_ip4_config = NULL;
merge_ip4_config (req, *config);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
/*****************************************************************************/
static NMActStageReturn
real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
NMActStageReturn
nm_modem_stage3_ip4_config_start (NMModem *self,
NMDevice *device,
NMDeviceClass *device_class,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMActStageReturn ret;
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 (device)->ip_method) {
case MM_MODEM_IP_METHOD_PPP:
ret = ppp_stage3_ip4_config_start (device, reason);
ret = ppp_stage3_ip4_config_start (self, req, reason);
break;
case MM_MODEM_IP_METHOD_STATIC:
ret = static_stage3_ip4_config_start (device, reason);
ret = static_stage3_ip4_config_start (self, req, reason);
break;
case MM_MODEM_IP_METHOD_DHCP:
ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage3_ip4_config_start (device, reason);
ret = device_class->act_stage3_ip4_config_start (device, reason);
break;
default:
g_warning ("Invalid IP method");
@ -344,22 +395,36 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason)
return ret;
}
static NMActStageReturn
real_act_stage4_get_ip4_config (NMDevice *device,
NMActStageReturn
nm_modem_stage4_get_ip4_config (NMModem *self,
NMDevice *device,
NMDeviceClass *device_class,
NMIP4Config **config,
NMDeviceStateReason *reason)
{
NMActRequest *req;
NMActStageReturn ret;
switch (NM_MODEM_GET_PRIVATE (device)->ip_method) {
g_return_val_if_fail (self != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (device != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_DEVICE (device), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (device_class != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (NM_IS_DEVICE_CLASS (device_class), NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
req = nm_device_get_act_request (device);
g_assert (req);
switch (NM_MODEM_GET_PRIVATE (self)->ip_method) {
case MM_MODEM_IP_METHOD_PPP:
ret = ppp_stage4 (device, config, reason);
ret = ppp_stage4 (self, req, config, reason);
break;
case MM_MODEM_IP_METHOD_STATIC:
ret = static_stage4 (device, config, reason);
ret = static_stage4 (self, req, device, config, reason);
break;
case MM_MODEM_IP_METHOD_DHCP:
ret = NM_DEVICE_CLASS (nm_modem_parent_class)->act_stage4_get_ip4_config (device, config, reason);
ret = device_class->act_stage4_get_ip4_config (device, config, reason);
break;
default:
g_warning ("Invalid IP method");
@ -370,12 +435,155 @@ real_act_stage4_get_ip4_config (NMDevice *device,
return ret;
}
static void
real_deactivate_quickly (NMDevice *device)
gboolean
nm_modem_connection_secrets_updated (NMModem *self,
NMActRequest *req,
NMConnection *connection,
GSList *updated_settings,
RequestSecretsCaller caller)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMModemPrivate *priv;
gboolean found = FALSE;
const char *setting_name;
GSList *iter;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (NM_IS_MODEM (self), FALSE);
g_return_val_if_fail (req != NULL, FALSE);
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
priv = NM_MODEM_GET_PRIVATE (self);
if (caller == SECRETS_CALLER_PPP) {
const char *user = NULL;
const char *pass = NULL;
g_return_val_if_fail (priv->ppp_manager != NULL, FALSE);
if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &user, &pass)) {
/* Shouldn't ever happen */
nm_ppp_manager_update_secrets (priv->ppp_manager,
priv->iface,
NULL,
NULL,
"missing GSM/CDMA setting; no secrets could be found.");
} else {
nm_ppp_manager_update_secrets (priv->ppp_manager,
priv->iface,
user ? user : "",
pass ? pass : "",
NULL);
}
return TRUE;
}
g_return_val_if_fail (caller == SECRETS_CALLER_MOBILE_BROADBAND, FALSE);
g_assert (NM_MODEM_GET_CLASS (self)->get_setting_name);
setting_name = NM_MODEM_GET_CLASS (self)->get_setting_name (self);
for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
const char *candidate_setting_name = (const char *) iter->data;
if (!strcmp (candidate_setting_name, setting_name))
found = TRUE;
else {
nm_warning ("Ignoring updated secrets for setting '%s'.",
candidate_setting_name);
}
}
return found;
}
static NMActStageReturn
real_act_stage1_prepare (NMModem *modem,
NMActRequest *req,
GPtrArray **out_hints,
const char **out_setting_name,
NMDeviceStateReason *reason)
{
*reason = NM_DEVICE_STATE_REASON_UNKNOWN;
return NM_ACT_STAGE_RETURN_FAILURE;
}
NMActStageReturn
nm_modem_act_stage1_prepare (NMModem *self,
NMActRequest *req,
NMDeviceStateReason *reason)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMActStageReturn ret;
GPtrArray *hints = NULL;
const char *setting_name = NULL;
ret = NM_MODEM_GET_CLASS (self)->act_stage1_prepare (self,
req,
&hints,
&setting_name,
reason);
if ((ret == NM_ACT_STAGE_RETURN_POSTPONE) && setting_name) {
const char *hint1 = NULL, *hint2 = NULL;
/* Need some secrets */
if (hints) {
if (hints->len > 0)
hint1 = g_ptr_array_index (hints, 0);
if (hints->len > 1)
hint2 = g_ptr_array_index (hints, 1);
}
g_signal_emit (self, signals[NEED_AUTH], 0,
setting_name,
priv->secrets_tries++ ? TRUE : FALSE,
SECRETS_CALLER_MOBILE_BROADBAND,
hint1,
hint2);
if (hints)
g_ptr_array_free (hints, TRUE);
}
return ret;
}
NMActStageReturn
nm_modem_act_stage2_config (NMModem *self,
NMActRequest *req,
NMDeviceStateReason *reason)
{
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
/* Clear secrets tries counter since secrets were successfully used
* already if we get here.
*/
priv->secrets_tries = 0;
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static void
real_deactivate_quickly (NMModem *self, NMDevice *device)
{
NMModemPrivate *priv;
const char *iface;
g_return_if_fail (self != NULL);
g_return_if_fail (NM_IS_MODEM (self));
g_return_if_fail (device != NULL);
g_return_if_fail (NM_IS_DEVICE (device));
priv = NM_MODEM_GET_PRIVATE (self);
priv->secrets_tries = 0;
if (priv->call) {
dbus_g_proxy_cancel_call (priv->proxy, priv->call);
priv->call = NULL;
}
if (priv->pending_ip4_config) {
g_object_unref (priv->pending_ip4_config);
priv->pending_ip4_config = NULL;
@ -383,7 +591,7 @@ real_deactivate_quickly (NMDevice *device)
priv->in_bytes = priv->out_bytes = 0;
switch (NM_MODEM_GET_PRIVATE (device)->ip_method) {
switch (priv->ip_method) {
case MM_MODEM_IP_METHOD_PPP:
if (priv->ppp_manager) {
g_object_unref (priv->ppp_manager);
@ -392,8 +600,7 @@ real_deactivate_quickly (NMDevice *device)
break;
case MM_MODEM_IP_METHOD_STATIC:
case MM_MODEM_IP_METHOD_DHCP:
iface = nm_device_get_iface (device);
iface = nm_device_get_ip_iface (device);
nm_system_device_flush_routes_with_iface (iface);
nm_system_device_flush_addresses_with_iface (iface);
nm_system_device_set_up_down_with_iface (iface, FALSE, NULL);
@ -402,38 +609,34 @@ real_deactivate_quickly (NMDevice *device)
g_warning ("Invalid IP method");
break;
}
if (NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate)
NM_DEVICE_CLASS (nm_modem_parent_class)->deactivate (device);
}
static guint32
real_get_generic_capabilities (NMDevice *dev)
void
nm_modem_deactivate_quickly (NMModem *self, NMDevice *device)
{
return NM_DEVICE_CAP_NM_SUPPORTED;
NM_MODEM_GET_CLASS (self)->deactivate_quickly (self, device);
}
static void
device_state_changed (NMDeviceInterface *device,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason,
gpointer user_data)
void
nm_modem_device_state_changed (NMModem *self,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason)
{
NMModem *self = NM_MODEM (user_data);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
g_return_if_fail (self != NULL);
g_return_if_fail (NM_IS_MODEM (self));
/* Make sure we don't leave the serial device open */
switch (new_state) {
case NM_DEVICE_STATE_NEED_AUTH:
if (priv->ppp_manager)
if (NM_MODEM_GET_PRIVATE (self)->ppp_manager)
break;
/* else fall through */
case NM_DEVICE_STATE_UNMANAGED:
case NM_DEVICE_STATE_UNAVAILABLE:
case NM_DEVICE_STATE_FAILED:
case NM_DEVICE_STATE_DISCONNECTED:
dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, NULL),
dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM),
"Enable",
G_TYPE_BOOLEAN, FALSE,
G_TYPE_INVALID);
@ -443,13 +646,13 @@ device_state_changed (NMDeviceInterface *device,
}
}
static gboolean
real_hw_is_up (NMDevice *device)
gboolean
nm_modem_hw_is_up (NMModem *self, NMDevice *device)
{
guint32 ip_method = NM_MODEM_GET_PRIVATE (device)->ip_method;
guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method;
if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMDeviceState state;
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
@ -460,13 +663,13 @@ real_hw_is_up (NMDevice *device)
return TRUE;
}
static gboolean
real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
gboolean
nm_modem_hw_bring_up (NMModem *self, NMDevice *device, gboolean *no_firmware)
{
guint32 ip_method = NM_MODEM_GET_PRIVATE (device)->ip_method;
guint32 ip_method = NM_MODEM_GET_PRIVATE (self)->ip_method;
if (ip_method == MM_MODEM_IP_METHOD_STATIC || ip_method == MM_MODEM_IP_METHOD_DHCP) {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (device);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMDeviceState state;
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
@ -477,6 +680,15 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
return TRUE;
}
const char *
nm_modem_get_iface (NMModem *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (NM_IS_MODEM (self), NULL);
return NM_MODEM_GET_PRIVATE (self)->iface;
}
/*****************************************************************************/
static void
@ -504,7 +716,12 @@ constructor (GType type,
priv = NM_MODEM_GET_PRIVATE (object);
if (!priv->device) {
g_warning ("Modem device not provided");
g_warning ("Modem parent device not provided");
goto err;
}
if (!priv->device) {
g_warning ("Modem command interface not provided");
goto err;
}
@ -516,8 +733,6 @@ constructor (GType type,
priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
MM_DBUS_SERVICE, priv->path, MM_DBUS_INTERFACE_MODEM);
g_signal_connect (object, "state-changed", G_CALLBACK (device_state_changed), object);
return object;
err:
@ -538,6 +753,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DEVICE:
g_value_set_string (value, priv->device);
break;
case PROP_IFACE:
g_value_set_string (value, priv->iface);
break;
case PROP_IP_METHOD:
g_value_set_uint (value, priv->ip_method);
break;
@ -563,7 +781,12 @@ set_property (GObject *object, guint prop_id,
/* Construct only */
priv->device = g_value_dup_string (value);
break;
case PROP_IFACE:
/* Construct only */
priv->iface = g_value_dup_string (value);
break;
case PROP_IP_METHOD:
/* Construct only */
priv->ip_method = g_value_get_uint (value);
break;
default:
@ -582,6 +805,7 @@ finalize (GObject *object)
g_object_unref (priv->dbus_mgr);
g_free (priv->iface);
g_free (priv->path);
g_free (priv->device);
@ -592,7 +816,6 @@ static void
nm_modem_class_init (NMModemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
g_type_class_add_private (object_class, sizeof (NMModemPrivate));
@ -602,12 +825,8 @@ nm_modem_class_init (NMModemClass *klass)
object_class->get_property = get_property;
object_class->finalize = finalize;
device_class->get_generic_capabilities = real_get_generic_capabilities;
device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
device_class->deactivate_quickly = real_deactivate_quickly;
device_class->hw_is_up = real_hw_is_up;
device_class->hw_bring_up = real_hw_bring_up;
klass->act_stage1_prepare = real_act_stage1_prepare;
klass->deactivate_quickly = real_deactivate_quickly;
/* Properties */
g_object_class_install_property
@ -616,7 +835,7 @@ nm_modem_class_init (NMModemClass *klass)
"DBus path",
"DBus path",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_DEVICE,
@ -624,7 +843,15 @@ nm_modem_class_init (NMModemClass *klass)
"Device",
"Master modem parent device",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_IFACE,
g_param_spec_string (NM_MODEM_IFACE,
"Interface",
"Modem command interface",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_IP_METHOD,
@ -634,7 +861,7 @@ nm_modem_class_init (NMModemClass *klass)
MM_MODEM_IP_METHOD_PPP,
MM_MODEM_IP_METHOD_DHCP,
MM_MODEM_IP_METHOD_PPP,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/* Signals */
signals[PPP_STATS] =
@ -647,10 +874,41 @@ nm_modem_class_init (NMModemClass *klass)
G_TYPE_NONE, 2,
G_TYPE_UINT, G_TYPE_UINT);
signals[PROPERTIES_CHANGED] =
nm_properties_changed_signal_new (object_class,
G_STRUCT_OFFSET (NMModemClass, properties_changed));
signals[PPP_FAILED] =
g_signal_new ("ppp-failed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemClass, ppp_failed),
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
&dbus_glib_nm_serial_device_object_info);
signals[IP4_CONFIG_RESULT] =
g_signal_new (NM_MODEM_IP4_CONFIG_RESULT,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemClass, ip4_config_result),
NULL, NULL,
_nm_marshal_VOID__STRING_OBJECT_POINTER,
G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_POINTER);
signals[PREPARE_RESULT] =
g_signal_new (NM_MODEM_PREPARE_RESULT,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemClass, prepare_result),
NULL, NULL,
_nm_marshal_VOID__BOOLEAN_UINT,
G_TYPE_NONE, 2, G_TYPE_BOOLEAN, G_TYPE_UINT);
signals[NEED_AUTH] =
g_signal_new (NM_MODEM_NEED_AUTH,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMModemClass, need_auth),
NULL, NULL,
_nm_marshal_VOID__STRING_BOOLEAN_UINT_STRING_STRING,
G_TYPE_NONE, 5,
G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
}

View file

@ -4,8 +4,9 @@
#define NM_MODEM_H
#include <dbus/dbus-glib.h>
#include <nm-device.h>
#include <glib-object.h>
#include "ppp-manager/nm-ppp-manager.h"
#include "nm-device.h"
G_BEGIN_DECLS
@ -18,33 +19,101 @@ G_BEGIN_DECLS
#define NM_MODEM_PATH "path"
#define NM_MODEM_DEVICE "device"
#define NM_MODEM_IFACE "iface"
#define NM_MODEM_IP_METHOD "ip-method"
#define NM_MODEM_PREPARE_RESULT "prepare-result"
#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result"
#define NM_MODEM_NEED_AUTH "need-auth"
typedef struct {
NMDevice parent;
GObject parent;
} NMModem;
typedef struct {
NMDeviceClass parent;
GObjectClass parent;
const char *(*get_ppp_name) (NMModem *self,
NMConnection *connection);
gboolean (*get_user_pass) (NMModem *modem,
NMConnection *connection,
const char **user,
const char **pass);
const char * (*get_setting_name) (NMModem *modem);
gboolean (*check_connection_compatible) (NMModem *modem,
NMConnection *connection,
GError **error);
NMConnection * (*get_best_auto_connection) (NMModem *modem,
GSList *connections,
char **specific_object);
NMActStageReturn (*act_stage1_prepare) (NMModem *modem,
NMActRequest *req,
GPtrArray **out_hints,
const char **out_setting_name,
NMDeviceStateReason *reason);
void (*deactivate_quickly) (NMModem *self, NMDevice *device);
/* Signals */
void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes);
void (*properties_changed) (NMModem *self, GHashTable *properties);
void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes);
void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason);
void (*prepare_result) (NMModem *self, gboolean success, NMDeviceStateReason reason);
void (*ip4_config_result) (NMModem *self, const char *iface, NMIP4Config *config, GError *error);
void (*need_auth) (NMModem *self,
const char *setting_name,
gboolean retry,
RequestSecretsCaller caller,
const char *hint1,
const char *hint2);
} NMModemClass;
GType nm_modem_get_type (void);
/* Protected */
NMPPPManager *nm_modem_get_ppp_manager (NMModem *self);
DBusGProxy *nm_modem_get_proxy (NMModem *self,
const char *interface);
NMPPPManager *nm_modem_get_ppp_manager (NMModem *modem);
DBusGProxy * nm_modem_get_proxy (NMModem *modem, const char *interface);
const char * nm_modem_get_iface (NMModem *modem);
const char *nm_modem_get_ppp_name (NMModem *self,
NMConnection *connection);
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);
G_END_DECLS

View file

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