mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-10 12:30:40 +01:00
modem: track modem state and fail device if modem disconnects
This worked fine with PPP because PPP terminates, and NM watches for that and handles it fine. But modems with pseudo-ethernet ports don't have anything like that, so we have to watch the modem's state property instead. This works only with MM 0.5.4 and later (including 0.6).
This commit is contained in:
parent
722ce46aaa
commit
052a24343e
8 changed files with 111 additions and 14 deletions
|
|
@ -64,7 +64,8 @@ NMModem *
|
|||
nm_modem_cdma_new (const char *path,
|
||||
const char *device,
|
||||
const char *data_device,
|
||||
guint32 ip_method)
|
||||
guint32 ip_method,
|
||||
NMModemState state)
|
||||
{
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
g_return_val_if_fail (device != NULL, NULL);
|
||||
|
|
@ -75,6 +76,7 @@ nm_modem_cdma_new (const char *path,
|
|||
NM_MODEM_DEVICE, device,
|
||||
NM_MODEM_IFACE, data_device,
|
||||
NM_MODEM_IP_METHOD, ip_method,
|
||||
NM_MODEM_STATE, state,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ GType nm_modem_cdma_get_type (void);
|
|||
NMModem *nm_modem_cdma_new (const char *path,
|
||||
const char *device,
|
||||
const char *data_device,
|
||||
guint32 ip_method);
|
||||
guint32 ip_method,
|
||||
NMModemState state);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,8 @@ NMModem *
|
|||
nm_modem_gsm_new (const char *path,
|
||||
const char *device,
|
||||
const char *data_device,
|
||||
guint32 ip_method)
|
||||
guint32 ip_method,
|
||||
NMModemState state)
|
||||
{
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
g_return_val_if_fail (device != NULL, NULL);
|
||||
|
|
@ -115,6 +116,7 @@ nm_modem_gsm_new (const char *path,
|
|||
NM_MODEM_DEVICE, device,
|
||||
NM_MODEM_IFACE, data_device,
|
||||
NM_MODEM_IP_METHOD, ip_method,
|
||||
NM_MODEM_STATE, state,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ GType nm_modem_gsm_get_type (void);
|
|||
NMModem *nm_modem_gsm_new (const char *path,
|
||||
const char *device,
|
||||
const char *data_device,
|
||||
guint32 ip_method);
|
||||
guint32 ip_method,
|
||||
NMModemState state);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ get_modem_properties (DBusGConnection *connection,
|
|||
char **driver,
|
||||
guint32 *type,
|
||||
guint32 *ip_method,
|
||||
guint32 *ip_timeout)
|
||||
guint32 *ip_timeout,
|
||||
NMModemState *state)
|
||||
{
|
||||
DBusGProxy *proxy;
|
||||
GError *err = NULL;
|
||||
|
|
@ -122,6 +123,8 @@ get_modem_properties (DBusGConnection *connection,
|
|||
*driver = g_value_dup_string (value);
|
||||
else if (g_strcmp0 (prop, "IpTimeout") == 0)
|
||||
*ip_timeout = g_value_get_uint (value);
|
||||
else if (g_strcmp0 (prop, "State") == 0)
|
||||
*state = g_value_get_uint (value);
|
||||
}
|
||||
g_hash_table_unref (props);
|
||||
|
||||
|
|
@ -140,6 +143,7 @@ create_modem (NMModemManager *manager, const char *path)
|
|||
uint modem_type = MM_MODEM_TYPE_UNKNOWN;
|
||||
uint ip_method = MM_MODEM_IP_METHOD_PPP;
|
||||
uint ip_timeout = 0;
|
||||
NMModemState state = NM_MODEM_STATE_UNKNOWN;
|
||||
|
||||
if (g_hash_table_lookup (priv->modems, path)) {
|
||||
nm_log_warn (LOGD_MB, "modem with path %s already exists, ignoring", path);
|
||||
|
|
@ -148,7 +152,7 @@ create_modem (NMModemManager *manager, const char *path)
|
|||
|
||||
if (!get_modem_properties (nm_dbus_manager_get_connection (priv->dbus_mgr),
|
||||
path, &master_device, &data_device, &driver,
|
||||
&modem_type, &ip_method, &ip_timeout))
|
||||
&modem_type, &ip_method, &ip_timeout, &state))
|
||||
return;
|
||||
|
||||
if (modem_type == MM_MODEM_TYPE_UNKNOWN) {
|
||||
|
|
@ -172,9 +176,9 @@ create_modem (NMModemManager *manager, const char *path)
|
|||
}
|
||||
|
||||
if (modem_type == MM_MODEM_TYPE_GSM)
|
||||
modem = nm_modem_gsm_new (path, master_device, data_device, ip_method);
|
||||
modem = nm_modem_gsm_new (path, master_device, data_device, ip_method, state);
|
||||
else if (modem_type == MM_MODEM_TYPE_CDMA)
|
||||
modem = nm_modem_cdma_new (path, master_device, data_device, ip_method);
|
||||
modem = nm_modem_cdma_new (path, master_device, data_device, ip_method, state);
|
||||
else
|
||||
nm_log_warn (LOGD_MB, "unknown modem type '%d'", modem_type);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ enum {
|
|||
PROP_IP_METHOD,
|
||||
PROP_IP_TIMEOUT,
|
||||
PROP_ENABLED,
|
||||
PROP_STATE,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -67,6 +68,7 @@ typedef struct {
|
|||
|
||||
gboolean mm_enabled;
|
||||
guint32 mm_ip_timeout;
|
||||
NMModemState state;
|
||||
|
||||
/* PPP stats */
|
||||
guint32 in_bytes;
|
||||
|
|
@ -105,6 +107,14 @@ nm_modem_get_mm_enabled (NMModem *self)
|
|||
return NM_MODEM_GET_PRIVATE (self)->mm_enabled;
|
||||
}
|
||||
|
||||
NMModemState
|
||||
nm_modem_get_state (NMModem *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_MODEM (self), NM_MODEM_STATE_UNKNOWN);
|
||||
|
||||
return NM_MODEM_GET_PRIVATE (self)->state;
|
||||
}
|
||||
|
||||
DBusGProxy *
|
||||
nm_modem_get_proxy (NMModem *self,
|
||||
const char *interface)
|
||||
|
|
@ -798,6 +808,7 @@ modem_properties_changed (DBusGProxy *proxy,
|
|||
NMModem *self = NM_MODEM (user_data);
|
||||
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
|
||||
GValue *value;
|
||||
NMModemState new_state;
|
||||
|
||||
if (strcmp (interface, MM_DBUS_INTERFACE_MODEM))
|
||||
return;
|
||||
|
|
@ -812,6 +823,15 @@ modem_properties_changed (DBusGProxy *proxy,
|
|||
priv->ip_method = g_value_get_uint (value);
|
||||
g_object_notify (G_OBJECT (self), NM_MODEM_IP_METHOD);
|
||||
}
|
||||
|
||||
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) {
|
||||
priv->state = new_state;
|
||||
g_object_notify (G_OBJECT (self), NM_MODEM_STATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -912,11 +932,13 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_ENABLED:
|
||||
g_value_set_boolean (value, priv->mm_enabled);
|
||||
break;
|
||||
case PROP_STATE:
|
||||
g_value_set_boolean (value, priv->state);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -947,6 +969,9 @@ set_property (GObject *object, guint prop_id,
|
|||
break;
|
||||
case PROP_ENABLED:
|
||||
break;
|
||||
case PROP_STATE:
|
||||
priv->state = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -954,20 +979,37 @@ set_property (GObject *object, guint prop_id,
|
|||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object);
|
||||
|
||||
if (priv->act_request)
|
||||
if (priv->act_request) {
|
||||
g_object_unref (priv->act_request);
|
||||
priv->act_request = NULL;
|
||||
}
|
||||
|
||||
if (priv->proxy)
|
||||
if (priv->proxy) {
|
||||
g_object_unref (priv->proxy);
|
||||
priv->proxy = NULL;
|
||||
}
|
||||
|
||||
if (priv->props_proxy)
|
||||
if (priv->props_proxy) {
|
||||
g_object_unref (priv->props_proxy);
|
||||
priv->props_proxy = NULL;
|
||||
}
|
||||
|
||||
g_object_unref (priv->dbus_mgr);
|
||||
if (priv->dbus_mgr) {
|
||||
g_object_unref (priv->dbus_mgr);
|
||||
priv->dbus_mgr = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_modem_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object);
|
||||
|
||||
g_free (priv->iface);
|
||||
g_free (priv->path);
|
||||
|
|
@ -987,6 +1029,7 @@ nm_modem_class_init (NMModemClass *klass)
|
|||
object_class->constructor = constructor;
|
||||
object_class->set_property = set_property;
|
||||
object_class->get_property = get_property;
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
klass->act_stage1_prepare = real_act_stage1_prepare;
|
||||
|
|
@ -1043,6 +1086,16 @@ nm_modem_class_init (NMModemClass *klass)
|
|||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
|
||||
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_STATE,
|
||||
g_param_spec_uint (NM_MODEM_STATE,
|
||||
"ModemManager modem state",
|
||||
"ModemManager modem state",
|
||||
NM_MODEM_STATE_UNKNOWN,
|
||||
NM_MODEM_STATE_LAST,
|
||||
NM_MODEM_STATE_UNKNOWN,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/* Signals */
|
||||
signals[PPP_STATS] =
|
||||
g_signal_new ("ppp-stats",
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ G_BEGIN_DECLS
|
|||
#define NM_MODEM_IP_METHOD "ip-method"
|
||||
#define NM_MODEM_IP_TIMEOUT "ip-timeout"
|
||||
#define NM_MODEM_ENABLED "enabled"
|
||||
#define NM_MODEM_STATE "state"
|
||||
|
||||
#define NM_MODEM_PPP_STATS "ppp-stats"
|
||||
#define NM_MODEM_PPP_FAILED "ppp-failed"
|
||||
|
|
@ -50,6 +51,23 @@ G_BEGIN_DECLS
|
|||
#define NM_MODEM_AUTH_REQUESTED "auth-requested"
|
||||
#define NM_MODEM_AUTH_RESULT "auth-result"
|
||||
|
||||
/* From ModemManager */
|
||||
typedef enum {
|
||||
NM_MODEM_STATE_UNKNOWN = 0,
|
||||
NM_MODEM_STATE_DISABLED = 10,
|
||||
NM_MODEM_STATE_DISABLING = 20,
|
||||
NM_MODEM_STATE_ENABLING = 30,
|
||||
NM_MODEM_STATE_ENABLED = 40,
|
||||
NM_MODEM_STATE_SEARCHING = 50,
|
||||
NM_MODEM_STATE_REGISTERED = 60,
|
||||
NM_MODEM_STATE_DISCONNECTING = 70,
|
||||
NM_MODEM_STATE_CONNECTING = 80,
|
||||
NM_MODEM_STATE_CONNECTED = 90,
|
||||
|
||||
NM_MODEM_STATE_LAST = NM_MODEM_STATE_CONNECTED
|
||||
} NMModemState;
|
||||
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} NMModem;
|
||||
|
|
@ -155,6 +173,8 @@ gboolean nm_modem_get_mm_enabled (NMModem *self);
|
|||
|
||||
void nm_modem_set_mm_enabled (NMModem *self, gboolean enabled);
|
||||
|
||||
NMModemState nm_modem_get_state (NMModem *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_MODEM_H */
|
||||
|
|
|
|||
|
|
@ -166,6 +166,19 @@ modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
|
|||
g_signal_emit (G_OBJECT (self), signals[ENABLE_CHANGED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_state_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
NMDeviceModem *self = NM_DEVICE_MODEM (user_data);
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
|
||||
|
||||
if ( nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED
|
||||
&& nm_modem_get_state (priv->modem) != NM_MODEM_STATE_CONNECTED) {
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMModem *
|
||||
|
|
@ -379,6 +392,7 @@ set_modem (NMDeviceModem *self, NMModem *modem)
|
|||
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_STATE, G_CALLBACK (modem_state_cb), self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue