Commit 60804250 authored by Dan Williams's avatar Dan Williams

wwan: use modem states instead of enabled/connected properties

Determining when the NMDeviceModem is available and when different
connections are available is easier if the modem's state is tracked,
instead of using the separate Enabled and Connected properties.
These properties could not accurately represent the SIM lock state
and prevented NetworkManager from making the modem available for
auto-activation when locked, even if a PIN was available.

In this new scheme, the NMDeviceModem is UNAVAILABLE when the
ModemManager modem state is FAILED, UNKNOWN, or INITIALIZING.  It
transitions to the NM DISCONNECTED state when the modem has finished
initializing and has not failed.

Once the NMDeviceModem is in DISCONNECTED state it can be activated
even if the SIM is locked and a PIN is required; the PIN will be
requested when starting activation, either from the connection itself
or via a secrets request.  This makes auto-activation of WWAN
connections possible.

This also allows us to consolidate code dealing with modem enable/disable
into the base NMModem class using the modem state, and to log more modem
information for debugging purposes.
parent bb1fece6
......@@ -552,6 +552,12 @@ typedef enum {
/* teamd control failed */
NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED = 56,
/* Modem failed or no longer available */
NM_DEVICE_STATE_REASON_MODEM_FAILED = 57,
/* Modem now ready and available */
NM_DEVICE_STATE_REASON_MODEM_AVAILABLE = 58,
/* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason;
......
......@@ -612,6 +612,16 @@
teamd control failed.
</tp:docstring>
</tp:enumvalue>
<tp:enumvalue suffix="MODEM_FAILED" value="57">
<tp:docstring>
Modem failed or no longer available.
</tp:docstring>
</tp:enumvalue>
<tp:enumvalue suffix="MODEM_AVAILABLE" value="58">
<tp:docstring>
Modem now ready and available.
</tp:docstring>
</tp:enumvalue>
</tp:enum>
<tp:struct name="NM_DEVICE_STATE_REASON_STRUCT">
......
......@@ -571,6 +571,38 @@ modem_cleanup (NMDeviceBt *self)
}
}
static void
modem_state_cb (NMModem *modem,
NMModemState new_state,
NMModemState old_state,
gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
NMDeviceState dev_state = nm_device_get_state (device);
if (new_state <= NM_MODEM_STATE_DISABLING && old_state > NM_MODEM_STATE_DISABLING) {
/* Will be called whenever something external to NM disables the
* modem directly through ModemManager.
*/
if (nm_device_is_activating (device) || dev_state == NM_DEVICE_STATE_ACTIVATED) {
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
return;
}
}
if (new_state < NM_MODEM_STATE_CONNECTING &&
old_state >= NM_MODEM_STATE_CONNECTING &&
dev_state >= NM_DEVICE_STATE_NEED_AUTH &&
dev_state <= NM_DEVICE_STATE_ACTIVATED) {
/* Fail the device if the modem disconnects unexpectedly while the
* device is activating/activated. */
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER);
return;
}
}
static void
modem_removed_cb (NMModem *modem, gpointer user_data)
{
......@@ -652,6 +684,7 @@ component_added (NMDevice *device, GObject *component)
g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self);
g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self);
g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self);
g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self);
g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self);
/* In the old ModemManager the data port is known from the very beginning;
......
......@@ -6573,6 +6573,10 @@ reason_to_string (NMDeviceStateReason reason)
return "DCB-FCoE-failed";
case NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED:
return "teamd-control-failed";
case NM_DEVICE_STATE_REASON_MODEM_FAILED:
return "modem-failed";
case NM_DEVICE_STATE_REASON_MODEM_AVAILABLE:
return "modem-available";
default:
break;
}
......
......@@ -165,38 +165,59 @@ data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
}
static void
modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
modem_state_cb (NMModem *modem,
NMModemState new_state,
NMModemState old_state,
gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
NMDeviceState state;
/* Called when the ModemManager modem enabled state is changed externally
* to NetworkManager (eg something using MM's D-Bus API directly).
*/
if (priv->rf_enabled && nm_modem_get_mm_enabled (modem) == FALSE) {
state = nm_device_get_state (device);
if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED) {
NMDeviceState dev_state = nm_device_get_state (device);
if (new_state <= NM_MODEM_STATE_DISABLING &&
old_state > NM_MODEM_STATE_DISABLING &&
priv->rf_enabled) {
/* Called when the ModemManager modem enabled state is changed externally
* to NetworkManager (eg something using MM's D-Bus API directly).
*/
if (nm_device_is_activating (device) || dev_state == NM_DEVICE_STATE_ACTIVATED) {
/* user-initiated action, hence DISCONNECTED not FAILED */
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
return;
}
}
nm_device_emit_recheck_auto_activate (device);
}
static void
modem_connected_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
{
NMDeviceModem *self = NM_DEVICE_MODEM (user_data);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
if (new_state < NM_MODEM_STATE_CONNECTING &&
old_state >= NM_MODEM_STATE_CONNECTING &&
dev_state >= NM_DEVICE_STATE_NEED_AUTH &&
dev_state <= NM_DEVICE_STATE_ACTIVATED) {
/* Fail the device if the modem disconnects unexpectedly while the
* device is activating/activated. */
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER);
return;
}
if (new_state > NM_MODEM_STATE_LOCKED && old_state == NM_MODEM_STATE_LOCKED) {
/* If the modem is now unlocked, enable/disable it according to the
* device's enabled/disabled state.
*/
nm_modem_set_mm_enabled (priv->modem, priv->rf_enabled);
}
if ( nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED
&& !nm_modem_get_mm_connected (priv->modem)) {
/* Fail the device if the modem disconnects unexpectedly */
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER);
if ((dev_state >= NM_DEVICE_STATE_DISCONNECTED) && !nm_device_is_available (device)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_MODEM_FAILED);
return;
}
if ((dev_state == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_MODEM_AVAILABLE);
return;
}
}
......@@ -233,10 +254,19 @@ device_state_changed (NMDevice *device,
NMDeviceState old_state,
NMDeviceStateReason reason)
{
nm_modem_device_state_changed (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
new_state,
old_state,
reason);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
g_assert (priv->modem);
if (new_state == NM_DEVICE_STATE_UNAVAILABLE &&
old_state < NM_DEVICE_STATE_UNAVAILABLE) {
/* Log initial modem state */
nm_log_info (LOGD_MB, "(%s): modem state '%s'",
nm_device_get_iface (device),
nm_modem_state_to_string (nm_modem_get_state (priv->modem)));
}
nm_modem_device_state_changed (priv->modem, new_state, old_state, reason);
}
static guint
......@@ -258,6 +288,33 @@ check_connection_compatible (NMDevice *device,
return nm_modem_check_connection_compatible (priv->modem, connection, error);
}
static gboolean
check_connection_available (NMDevice *device,
NMConnection *connection,
const char *specific_object)
{
NMDeviceModem *self = NM_DEVICE_MODEM (device);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
NMModemState state;
if (!priv->rf_enabled || !priv->modem)
return FALSE;
state = nm_modem_get_state (priv->modem);
if (state <= NM_MODEM_STATE_INITIALIZING)
return FALSE;
if (state == NM_MODEM_STATE_LOCKED) {
NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (connection);
/* Can't use a connection without a PIN if the modem is locked */
if (!s_gsm || !nm_setting_gsm_get_pin (s_gsm))
return FALSE;
}
return TRUE;
}
static gboolean
complete_connection (NMDevice *device,
NMConnection *connection,
......@@ -337,8 +394,9 @@ static gboolean
get_enabled (NMDevice *device)
{
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
NMModemState modem_state = nm_modem_get_state (priv->modem);
return priv->rf_enabled && nm_modem_get_mm_enabled (priv->modem);
return priv->rf_enabled && (modem_state >= NM_MODEM_STATE_LOCKED);
}
static void
......@@ -368,14 +426,24 @@ static gboolean
is_available (NMDevice *dev)
{
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (dev);
NMModemState modem_state;
/* The device is available whenever it's not rfkilled */
if (!priv->rf_enabled) {
nm_log_dbg (LOGD_MB, "(%s): not available because WWAN airplane mode is on",
nm_device_get_iface (dev));
return FALSE;
}
g_assert (priv->modem);
modem_state = nm_modem_get_state (priv->modem);
if (modem_state <= NM_MODEM_STATE_INITIALIZING) {
nm_log_dbg (LOGD_MB, "(%s): not available because modem is not ready (%s)",
nm_device_get_iface (dev),
nm_modem_state_to_string (modem_state));
return FALSE;
}
return priv->rf_enabled;
return TRUE;
}
/*****************************************************************************/
......@@ -432,8 +500,7 @@ set_modem (NMDeviceModem *self, NMModem *modem)
g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self);
g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self);
g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self);
g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), self);
g_signal_connect (modem, "notify::" NM_MODEM_CONNECTED, G_CALLBACK (modem_connected_cb), self);
g_signal_connect (modem, NM_MODEM_STATE_CHANGED, G_CALLBACK (modem_state_cb), self);
g_signal_connect (modem, NM_MODEM_REMOVED, G_CALLBACK (modem_removed_cb), self);
/* In the old ModemManager the data port is known from the very beginning;
......@@ -514,6 +581,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass)
device_class->get_hw_address_length = get_hw_address_length;
device_class->check_connection_compatible = check_connection_compatible;
device_class->check_connection_available = check_connection_available;
device_class->complete_connection = complete_connection;
device_class->deactivate = deactivate;
device_class->act_stage1_prepare = act_stage1_prepare;
......
......@@ -530,17 +530,6 @@ get_user_pass (NMModem *modem,
/*****************************************************************************/
/* Query/Update enabled state */
static void
update_mm_enabled (NMModem *self,
gboolean new_enabled)
{
if (nm_modem_get_mm_enabled (self) != new_enabled) {
g_object_set (self,
NM_MODEM_ENABLED, new_enabled,
NULL);
}
}
static void
modem_disable_ready (MMModem *modem_iface,
GAsyncResult *res,
......@@ -552,10 +541,9 @@ modem_disable_ready (MMModem *modem_iface,
nm_log_warn (LOGD_MB, "(%s) failed to disable modem: %s",
nm_modem_get_uid (NM_MODEM (self)),
error && error->message ? error->message : "(unknown)");
nm_modem_set_prev_state (NM_MODEM (self), "disable failed");
g_clear_error (&error);
} else
/* Update enabled/disabled state again */
update_mm_enabled (NM_MODEM (self), FALSE);
}
/* Balance refcount */
g_object_unref (self);
......@@ -572,9 +560,9 @@ modem_enable_ready (MMModem *modem_iface,
nm_log_warn (LOGD_MB, "(%s) failed to enable modem: %s",
nm_modem_get_uid (NM_MODEM (self)),
error && error->message ? error->message : "(unknown)");
nm_modem_set_prev_state (NM_MODEM (self), "enable failed");
g_clear_error (&error);
} else
update_mm_enabled (NM_MODEM (self), TRUE);
}
/* Balance refcount */
g_object_unref (self);
......@@ -587,14 +575,6 @@ set_mm_enabled (NMModem *_self,
NMModemBroadband *self = NM_MODEM_BROADBAND (_self);
if (enabled) {
/* Don't even try to enable if we're known to be already locked */
if (mm_modem_get_state (self->priv->modem_iface) == MM_MODEM_STATE_LOCKED) {
nm_log_warn (LOGD_MB, "(%s) cannot enable modem: locked",
nm_modem_get_uid (NM_MODEM (self)));
g_signal_emit_by_name (self, NM_MODEM_AUTH_REQUESTED, 0);
return;
}
mm_modem_enable (self->priv->modem_iface,
NULL, /* cancellable */
(GAsyncReadyCallback)modem_enable_ready,
......@@ -604,9 +584,6 @@ set_mm_enabled (NMModem *_self,
NULL, /* cancellable */
(GAsyncReadyCallback)modem_disable_ready,
g_object_ref (self));
/* When disabling don't say we're enabled */
update_mm_enabled (NM_MODEM (self), enabled);
}
}
......@@ -782,6 +759,29 @@ deactivate (NMModem *_self, NMDevice *device)
/*****************************************************************************/
#define MAP_STATE(name) case MM_MODEM_STATE_##name: return NM_MODEM_STATE_##name;
static NMModemState
mm_state_to_nm (MMModemState mm_state)
{
switch (mm_state) {
MAP_STATE(UNKNOWN)
MAP_STATE(FAILED)
MAP_STATE(INITIALIZING)
MAP_STATE(LOCKED)
MAP_STATE(DISABLED)
MAP_STATE(DISABLING)
MAP_STATE(ENABLING)
MAP_STATE(ENABLED)
MAP_STATE(SEARCHING)
MAP_STATE(REGISTERED)
MAP_STATE(DISCONNECTING)
MAP_STATE(CONNECTING)
MAP_STATE(CONNECTED)
}
return NM_MODEM_STATE_UNKNOWN;
}
static void
modem_state_changed (MMModem *modem,
MMModemState old_state,
......@@ -789,28 +789,17 @@ modem_state_changed (MMModem *modem,
MMModemStateChangeReason reason,
NMModemBroadband *self)
{
gboolean old;
gboolean new;
nm_log_info (LOGD_MB, "(%s) modem state changed, '%s' --> '%s' (reason: %s)\n",
nm_modem_get_uid (NM_MODEM (self)),
mm_modem_state_get_string (old_state),
mm_modem_state_get_string (new_state),
mm_modem_state_change_reason_get_string (reason));
old = nm_modem_get_mm_enabled (NM_MODEM (self));
new = (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_ENABLED);
if (old != new)
g_object_set (self,
NM_MODEM_ENABLED, new,
NULL);
old = nm_modem_get_mm_connected (NM_MODEM (self));
new = (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_CONNECTED);
if (old != new)
g_object_set (self,
NM_MODEM_CONNECTED, new,
NULL);
/* After the SIM is unlocked MM1 will move the device to INITIALIZING which
* is an unavailable state. That makes state handling confusing here, so
* suppress this state change and let the modem move from LOCKED to DISABLED.
*/
if (new_state == MM_MODEM_STATE_INITIALIZING && old_state == MM_MODEM_STATE_LOCKED)
return;
nm_modem_set_state (NM_MODEM (self),
mm_state_to_nm (new_state),
mm_modem_state_change_reason_get_string (reason));
}
/*****************************************************************************/
......@@ -831,16 +820,6 @@ nm_modem_broadband_new (GObject *object, GError **error)
g_return_val_if_fail (!!modem_iface, NULL);
g_return_val_if_fail (!!mm_modem_get_primary_port (modem_iface), NULL);
/* If the modem is in 'FAILED' state we cannot do anything with it.
* This happens when a severe error happened when trying to initialize it,
* like missing SIM. */
if (mm_modem_get_state (modem_iface) == MM_MODEM_STATE_FAILED) {
g_set_error (error, NM_MODEM_ERROR, NM_MODEM_ERROR_INITIALIZATION_FAILED,
"(%s): unusable modem detected",
mm_modem_get_primary_port (modem_iface));
return NULL;
}
/* Build a single string with all drivers listed */
drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers (modem_iface));
......@@ -849,6 +828,7 @@ nm_modem_broadband_new (GObject *object, GError **error)
NM_MODEM_UID, mm_modem_get_primary_port (modem_iface),
NM_MODEM_CONTROL_PORT, mm_modem_get_primary_port (modem_iface),
NM_MODEM_DATA_PORT, NULL, /* We don't know it until bearer created */
NM_MODEM_STATE, mm_state_to_nm (mm_modem_get_state (modem_iface)),
NM_MODEM_BROADBAND_MODEM, modem_object,
NM_MODEM_DRIVER, drivers,
NULL);
......@@ -883,11 +863,6 @@ set_property (GObject *object,
G_CALLBACK (modem_state_changed),
self);
g_object_set (object,
NM_MODEM_ENABLED, (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_ENABLED),
NM_MODEM_CONNECTED, (mm_modem_get_state (self->priv->modem_iface) >= MM_MODEM_STATE_CONNECTED),
NULL);
/* Note: don't grab the Simple iface here; the Modem interface is the
* only one assumed to be always valid and available */
break;
......
......@@ -43,6 +43,7 @@ typedef struct {
MMOldModemState state;
NMDeviceModemCapabilities caps;
char *unlock_required;
DBusGProxyCall *call;
GHashTable *connect_properties;
......@@ -141,6 +142,29 @@ translate_mm_error (GError *error)
return reason;
}
#define MAP_STATE(name) case MM_OLD_MODEM_STATE_##name: return NM_MODEM_STATE_##name;
static NMModemState
mm_state_to_nm (MMOldModemState mm_state, const char *unlock_required)
{
if (unlock_required && *unlock_required)
return NM_MODEM_STATE_LOCKED;
switch (mm_state) {
MAP_STATE(UNKNOWN)
MAP_STATE(DISABLED)
MAP_STATE(DISABLING)
MAP_STATE(ENABLING)
MAP_STATE(ENABLED)
MAP_STATE(SEARCHING)
MAP_STATE(REGISTERED)
MAP_STATE(DISCONNECTING)
MAP_STATE(CONNECTING)
MAP_STATE(CONNECTED)
}
return NM_MODEM_STATE_UNKNOWN;
};
/*****************************************************************************/
DBusGProxy *
......@@ -169,52 +193,6 @@ nm_modem_old_get_proxy (NMModemOld *self, const char *interface)
/*****************************************************************************/
/* Query/Update enabled state */
static void
update_mm_enabled (NMModem *self,
gboolean new_enabled)
{
if (nm_modem_get_mm_enabled (self) != new_enabled) {
g_object_set (self,
NM_MODEM_ENABLED, new_enabled,
NULL);
}
}
static void
get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
{
NMModem *self = NM_MODEM (user_data);
GError *error = NULL;
GValue value = G_VALUE_INIT;
if (!dbus_g_proxy_end_call (proxy, call_id, &error,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
nm_log_warn (LOGD_MB, "failed get modem enabled state: (%d) %s",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
return;
}
if (G_VALUE_HOLDS_BOOLEAN (&value)) {
update_mm_enabled (self, g_value_get_boolean (&value));
} else
nm_log_warn (LOGD_MB, "failed get modem enabled state: unexpected reply type");
g_value_unset (&value);
}
static void
query_mm_enabled (NMModemOld *self)
{
dbus_g_proxy_begin_call (NM_MODEM_OLD_GET_PRIVATE (self)->props_proxy,
"Get", get_mm_enabled_done,
self, NULL,
G_TYPE_STRING, MM_OLD_DBUS_INTERFACE_MODEM,
G_TYPE_STRING, "Enabled",
G_TYPE_INVALID);
}
static void
set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
{
......@@ -224,28 +202,19 @@ set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d
nm_log_warn (LOGD_MB, "failed to enable/disable modem: (%d) %s",
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
nm_modem_set_prev_state (NM_MODEM (user_data), "enable/disable failed");
}
/* Update enabled/disabled state again */
query_mm_enabled (NM_MODEM_OLD (user_data));
/* Wait for the state change signal to indicate enabled state changed */
}
static void
set_mm_enabled (NMModem *self, gboolean enabled)
{
/* 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
* toggle rfkill status of the WWAN modem.
*/
dbus_g_proxy_begin_call (nm_modem_old_get_proxy (NM_MODEM_OLD (self),
MM_OLD_DBUS_INTERFACE_MODEM),
dbus_g_proxy_begin_call (nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM),
"Enable", set_mm_enabled_done,
self, NULL,
g_object_ref (self), g_object_unref,
G_TYPE_BOOLEAN, enabled,
G_TYPE_INVALID);
/* If we are disabling the modem, stop saying that it's enabled. */
if (!enabled)
update_mm_enabled (self, enabled);
}
/*****************************************************************************/
......@@ -543,13 +512,12 @@ act_stage1_prepare (NMModem *modem,
{
NMModemOld *self = NM_MODEM_OLD (modem);
NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self);
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 (nm_modem_get_state (modem) >= NM_MODEM_STATE_ENABLING)
do_connect (self);
else
do_enable (self);
......@@ -718,18 +686,11 @@ modem_properties_changed (DBusGProxy *proxy,
NMModemOld *self = NM_MODEM_OLD (user_data);
NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self);
GValue *value;
MMOldModemState new_state;
gboolean update_state = FALSE;
if (strcmp (interface, MM_OLD_DBUS_INTERFACE_MODEM))
return;
value = g_hash_table_lookup (props, "Enabled");
if (value && G_VALUE_HOLDS_BOOLEAN (value)) {
g_object_set (self,
NM_MODEM_ENABLED, g_value_get_boolean (value),
NULL);
}
value = g_hash_table_lookup (props, "IpMethod");
if (value && G_VALUE_HOLDS_UINT (value)) {
g_object_set (self,
......@@ -737,20 +698,23 @@ modem_properties_changed (DBusGProxy *proxy,
NULL);
}
value = g_hash_table_lookup (props, "UnlockRequired");
if (value && G_VALUE_HOLDS_STRING (value)) {
g_free (priv->unlock_required);
priv->unlock_required = g_value_dup_string (value);
update_state = TRUE;
}
value = g_hash_table_lookup (props, "State");
if (value && G_VALUE_HOLDS_UINT (value)) {
new_state = g_value_get_uint (value);
if (new_state != priv->state) {
if (new_state == MM_OLD_MODEM_STATE_CONNECTED)
g_object_set (self,
NM_MODEM_CONNECTED, TRUE,
NULL);
else if (priv->state == MM_OLD_MODEM_STATE_CONNECTED)
g_object_set (self,
NM_MODEM_CONNECTED, FALSE,
NULL);
priv->state = new_state;
}
priv->state = g_value_get_uint (value);
update_state = TRUE;
}
if (update_state) {
nm_modem_set_state (NM_MODEM (self),
mm_state_to_nm (priv->state, priv->unlock_required),
NULL);
}
}
......@@ -970,6 +934,7 @@ nm_modem_old_new (const char *path, GHashTable *properties, GError **error)
const char *data_device = NULL;
const char *driver = NULL;
const char *master_device = NULL;
const char *unlock_required = NULL;
guint32 modem_type = MM_OLD_MODEM_TYPE_UNKNOWN;
guint32 ip_method = MM_MODEM_IP_METHOD_PPP;
guint32 ip_timeout = 0;
......@@ -994,6 +959,8 @@ nm_modem_old_new (const char *path, GHashTable *properties, GError **error)
ip_timeout = g_value_get_uint (value);
else if (g_strcmp0 (prop, "State") == 0)
state = g_value_get_uint (value);
else if (g_strcmp0 (prop, "UnlockRequired") == 0)
unlock_required = g_value_get_string (value);
}
if (modem_type == MM_OLD_MODEM_TYPE_UNKNOWN) {
......@@ -1028,7 +995,7 @@ nm_modem_old_new (const char *path, GHashTable *properties, GError **error)
NM_MODEM_DATA_PORT, data_device,
NM_MODEM_IP_METHOD, ip_method,
NM_MODEM_IP_TIMEOUT, ip_timeout,
NM_MODEM_CONNECTED, (state == MM_OLD_MODEM_STATE_CONNECTED),
NM_MODEM_STATE, mm_state_to_nm (state, unlock_required),
NULL);
if (self) {
if (modem_type == MM_OLD_MODEM_TYPE_CDMA)
......@@ -1037,6 +1004,8 @@ nm_modem_old_new (const char *path, GHashTable *properties, GError **error)
caps |= NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
NM_MODEM_OLD_GET_PRIVATE (self)->caps = caps;
NM_MODEM_OLD_GET_PRIVATE (self)->state = state;
NM_MODEM_OLD_GET_PRIVATE (self)->unlock_required = g_strdup (unlock_required);
}
return (NMModem *) self;
......@@ -1084,8 +1053,6 @@ constructor (GType type,
object,
NULL);
query_mm_enabled (NM_MODEM_OLD (object));
return object;
}
......@@ -1114,6 +1081,9 @@ dispose (GObject *object)
priv->enable_delay_id = 0;
}
g_free (priv->unlock_required);
priv->unlock_required = NULL;
G_OBJECT_CLASS (nm_modem_old_parent_class)->dispose (object);
}
......
......@@ -15,7 +15,7 @@
* 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 - 2011 Red Hat, Inc.
* Copyright (C) 2009 - 2014 Red Hat, Inc.
* Copyright (C) 2009 Novell, Inc.
*/
......@@ -44,8 +44,7 @@ enum {
PROP_DRIVER,
PROP_IP_METHOD,
PROP_IP_TIMEOUT,
PROP_ENABLED,
PROP_CONNECTED,
PROP_STATE,
LAST_PROP
};
......@@ -58,6 +57,8 @@ typedef struct {
char *data_port;
char *ppp_iface;
guint32 ip_method;
NMModemState state;
NMModemState prev_state; /* revert to this state if enable/disable fails */
NMPPPManager *ppp_manager;
......@@ -65,9 +66,7 @@ typedef struct {
guint32 secrets_tries;
guint32 secrets_id;
gboolean mm_enabled;
guint32 mm_ip_timeout;
gboolean mm_connected;
/* PPP stats */
guint32 in_bytes;
......@@ -82,6 +81,7 @@ enum {
AUTH_REQUESTED,