diff --git a/include/NetworkManager.h b/include/NetworkManager.h index c8d5074a1e..eb3c1a743a 100644 --- a/include/NetworkManager.h +++ b/include/NetworkManager.h @@ -365,6 +365,9 @@ typedef enum { /* The supplicant is now available */ NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + /* The modem could not be found */ + NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, + /* Unused */ NM_DEVICE_STATE_REASON_LAST = 0xFFFF } NMDeviceStateReason; diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index d712df6903..f2a04dc076 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -24,8 +24,7 @@ #include "nm-dbus-glib-types.h" #include "nm-modem-cdma.h" #include "nm-modem-types.h" -#include "nm-device-interface.h" -#include "nm-device-private.h" +#include "nm-device.h" #include "nm-dbus-manager.h" #include "nm-setting-connection.h" #include "nm-setting-cdma.h" @@ -38,6 +37,8 @@ G_DEFINE_TYPE (NMModemCdma, nm_modem_cdma, NM_TYPE_MODEM) typedef struct { DBusGProxyCall *call; + + GHashTable *connect_properties; } NMModemCdmaPrivate; @@ -110,6 +111,11 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data priv->call = NULL; + if (priv->connect_properties) { + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = NULL; + } + if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); else { @@ -121,6 +127,37 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data } } +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); + } +} + static GHashTable * create_connect_properties (NMConnection *connection) { @@ -138,45 +175,6 @@ create_connect_properties (NMConnection *connection) return properties; } -static void -do_connect (NMModem *modem) -{ - NMModemCdma *self = NM_MODEM_CDMA (modem); - NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); - NMConnection *connection; - DBusGProxy *proxy; - GHashTable *properties; - - connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem))); - g_assert (connection); - - 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); -} - -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 ("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 (NMModem *modem, NMActRequest *req, @@ -184,6 +182,8 @@ real_act_stage1_prepare (NMModem *modem, const char **out_setting_name, NMDeviceStateReason *reason) { + NMModemCdma *self = NM_MODEM_CDMA (modem); + NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); NMConnection *connection; connection = nm_act_request_get_connection (req); @@ -194,8 +194,12 @@ real_act_stage1_prepare (NMModem *modem, gboolean enabled = nm_modem_get_mm_enabled (modem); DBusGProxy *proxy; + if (priv->connect_properties) + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = create_connect_properties (connection); + if (enabled) - do_connect (modem); + do_connect (self); else { proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM); dbus_g_proxy_begin_call_with_timeout (proxy, @@ -314,6 +318,18 @@ nm_modem_cdma_init (NMModemCdma *self) { } +static void +dispose (GObject *object) +{ + NMModemCdma *self = NM_MODEM_CDMA (object); + NMModemCdmaPrivate *priv = NM_MODEM_CDMA_GET_PRIVATE (self); + + if (priv->connect_properties) + g_hash_table_destroy (priv->connect_properties); + + G_OBJECT_CLASS (nm_modem_cdma_parent_class)->dispose (object); +} + static void nm_modem_cdma_class_init (NMModemCdmaClass *klass) { @@ -323,6 +339,7 @@ nm_modem_cdma_class_init (NMModemCdmaClass *klass) g_type_class_add_private (object_class, sizeof (NMModemCdmaPrivate)); /* Virtual methods */ + object_class->dispose = dispose; modem_class->get_user_pass = real_get_user_pass; modem_class->get_setting_name = real_get_setting_name; modem_class->get_best_auto_connection = real_get_best_auto_connection; diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index bddfd809d0..60d8b4f8dc 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -22,8 +22,7 @@ #include #include "nm-dbus-glib-types.h" #include "nm-modem-gsm.h" -#include "nm-device-private.h" -#include "nm-device-interface.h" +#include "nm-device.h" #include "nm-setting-connection.h" #include "nm-setting-gsm.h" #include "nm-modem-types.h" @@ -54,6 +53,8 @@ G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM) typedef struct { DBusGProxyCall *call; + + GHashTable *connect_properties; } NMModemGsmPrivate; @@ -161,6 +162,11 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data priv->call = NULL; + if (priv->connect_properties) { + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = NULL; + } + if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); else { @@ -192,6 +198,37 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data } } +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) +{ + 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)"); + g_error_free (error); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); + } +} + static GHashTable * create_connect_properties (NMConnection *connection) { @@ -248,43 +285,6 @@ create_connect_properties (NMConnection *connection) return properties; } -static void -do_connect (NMModem *modem) -{ - NMConnection *connection; - DBusGProxy *proxy; - GHashTable *properties; - - connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem))); - g_assert (connection); - - properties = create_connect_properties (connection); - proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE); - dbus_g_proxy_begin_call_with_timeout (proxy, - "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_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)"); - g_error_free (error); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); - } -} - static NMActStageReturn real_act_stage1_prepare (NMModem *modem, NMActRequest *req, @@ -292,6 +292,8 @@ real_act_stage1_prepare (NMModem *modem, const char **out_setting_name, NMDeviceStateReason *reason) { + NMModemGsm *self = NM_MODEM_GSM (modem); + NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); NMConnection *connection; connection = nm_act_request_get_connection (req); @@ -302,8 +304,12 @@ real_act_stage1_prepare (NMModem *modem, gboolean enabled = nm_modem_get_mm_enabled (modem); DBusGProxy *proxy; + if (priv->connect_properties) + g_hash_table_destroy (priv->connect_properties); + priv->connect_properties = create_connect_properties (connection); + if (enabled) - do_connect (modem); + do_connect (self); else { proxy = nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM); dbus_g_proxy_begin_call_with_timeout (proxy, @@ -423,6 +429,18 @@ nm_modem_gsm_init (NMModemGsm *self) { } +static void +dispose (GObject *object) +{ + NMModemGsm *self = NM_MODEM_GSM (object); + NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); + + if (priv->connect_properties) + g_hash_table_destroy (priv->connect_properties); + + G_OBJECT_CLASS (nm_modem_gsm_parent_class)->dispose (object); +} + static void nm_modem_gsm_class_init (NMModemGsmClass *klass) { @@ -432,6 +450,7 @@ nm_modem_gsm_class_init (NMModemGsmClass *klass) g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate)); /* Virtual methods */ + object_class->dispose = dispose; modem_class->get_user_pass = real_get_user_pass; modem_class->get_setting_name = real_get_setting_name; modem_class->get_best_auto_connection = real_get_best_auto_connection; @@ -439,7 +458,5 @@ nm_modem_gsm_class_init (NMModemGsmClass *klass) modem_class->act_stage1_prepare = real_act_stage1_prepare; modem_class->deactivate_quickly = real_deactivate_quickly; -// device_class->act_stage2_config = real_act_stage2_config; - dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR); } diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 228dcba7f9..3d32e1914a 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -35,10 +35,7 @@ #include "nm-serial-device-glue.h" -static void device_interface_init (NMDeviceInterface *iface_class); - -G_DEFINE_TYPE_EXTENDED (NMModem, nm_modem, NM_TYPE_DEVICE, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) +G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) #define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) @@ -668,14 +665,6 @@ real_deactivate_quickly (NMModem *self, NMDevice *device) g_warning ("Invalid IP method"); break; } - - /* Stop the modem and any ongoing connection... */ - if (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) { - dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), - "Enable", - G_TYPE_BOOLEAN, FALSE, - G_TYPE_INVALID); - } } void @@ -824,11 +813,15 @@ set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d query_mm_enabled (NM_MODEM (user_data)); } -static void -real_set_enabled (NMDeviceInterface *device, gboolean enabled) +void +nm_modem_set_mm_enabled (NMModem *self, gboolean enabled) { - NMModem *self = NM_MODEM (device); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMModemPrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (NM_IS_MODEM (self)); + + priv = NM_MODEM_GET_PRIVATE (self); /* FIXME: For now this just toggles the ModemManager enabled state. In the * future we want to tie this into rfkill state instead so that the user can @@ -838,10 +831,10 @@ real_set_enabled (NMDeviceInterface *device, gboolean enabled) if (priv->mm_enabled != enabled) { DBusGProxy *proxy; - proxy = nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM); + proxy = nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM); dbus_g_proxy_begin_call (proxy, "Enable", set_mm_enabled_done, - device, NULL, + self, NULL, G_TYPE_BOOLEAN, enabled, G_TYPE_INVALID); } @@ -880,12 +873,6 @@ modem_properties_changed (DBusGProxy *proxy, /*****************************************************************************/ -static void -device_interface_init (NMDeviceInterface *iface_class) -{ - iface_class->set_enabled = real_set_enabled; -} - static void nm_modem_init (NMModem *self) { diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index c5e34ad039..a2aed57e00 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -148,7 +148,9 @@ gboolean nm_modem_connection_secrets_updated (NMModem *modem, 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 diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c index b2374d9a0f..ab2572536e 100644 --- a/src/nm-device-bt.c +++ b/src/nm-device-bt.c @@ -52,13 +52,12 @@ typedef struct { guint32 capabilities; DBusGProxy *type_proxy; + DBusGProxy *dev_proxy; - NMPPPManager *ppp_manager; char *rfcomm_iface; - guint32 in_bytes; - guint32 out_bytes; + NMModem *modem; + guint32 timeout_id; - NMIP4Config *pending_ip4_config; guint32 bt_type; /* BT type of the current connection */ } NMDeviceBtPrivate; @@ -122,31 +121,6 @@ nm_bt_error_get_type (void) } -NMDevice * -nm_device_bt_new (const char *udi, - const char *bdaddr, - const char *name, - guint32 capabilities, - gboolean managed) -{ - g_return_val_if_fail (udi != NULL, NULL); - g_return_val_if_fail (bdaddr != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT, - NM_DEVICE_INTERFACE_UDI, udi, - NM_DEVICE_INTERFACE_IFACE, bdaddr, - NM_DEVICE_INTERFACE_DRIVER, "bluez", - NM_DEVICE_BT_HW_ADDRESS, bdaddr, - NM_DEVICE_BT_NAME, name, - NM_DEVICE_BT_CAPABILITIES, capabilities, - NM_DEVICE_INTERFACE_MANAGED, managed, - NM_DEVICE_INTERFACE_TYPE_DESC, "Bluetooth", - NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_BT, - NULL); -} - guint32 nm_device_bt_get_capabilities (NMDeviceBt *self) { g_return_val_if_fail (self != NULL, NM_BT_CAPABILITY_NONE); @@ -281,16 +255,26 @@ real_get_generic_capabilities (NMDevice *dev) /* IP method PPP */ static void -ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +ppp_stats (NMModem *modem, + guint32 in_bytes, + guint32 out_bytes, + gpointer user_data) +{ + g_signal_emit (NM_DEVICE_BT (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); +} + +static void +ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_ACTIVATED: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); break; default: break; @@ -298,68 +282,126 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ } static void -ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) +modem_need_auth (NMModem *modem, + const char *setting_name, + gboolean retry, + RequestSecretsCaller caller, + const char *hint1, + const char *hint2, + gpointer user_data) { - NMDevice *device = NM_DEVICE (user_data); + NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMActRequest *req; - /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_get_state (device) != NM_DEVICE_STATE_IP_CONFIG) - return; + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); - nm_device_set_ip_iface (device, iface); - NM_DEVICE_BT_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); - nm_device_activate_schedule_stage4_ip4_config_get (device); + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2); } static void -ppp_stats (NMPPPManager *ppp_manager, - guint32 in_bytes, - guint32 out_bytes, - gpointer user_data) +modem_prepare_result (NMModem *modem, + gboolean success, + NMDeviceStateReason reason, + gpointer user_data) { - NMDeviceBt *self = NM_DEVICE_BT (user_data); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; - if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { - priv->in_bytes = in_bytes; - priv->out_bytes = out_bytes; + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + g_return_if_fail (state == NM_DEVICE_STATE_CONFIG); - g_signal_emit (self, signals[PPP_STATS], 0, in_bytes, out_bytes); + if (success) { + NMActRequest *req; + NMActStageReturn ret; + NMDeviceStateReason stage2_reason = NM_DEVICE_STATE_REASON_NONE; + + req = nm_device_get_act_request (device); + g_assert (req); + + ret = nm_modem_act_stage2_config (modem, req, &stage2_reason); + switch (ret) { + case NM_ACT_STAGE_RETURN_POSTPONE: + break; + case NM_ACT_STAGE_RETURN_SUCCESS: + nm_device_activate_schedule_stage3_ip_config_start (device); + break; + case NM_ACT_STAGE_RETURN_FAILURE: + default: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, stage2_reason); + break; + } + } else + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); + + if (priv->modem) + nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); +} + +static void +modem_ip4_config_result (NMModem *self, + const char *iface, + NMIP4Config *config, + GError *error, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + g_return_if_fail (state == NM_DEVICE_STATE_IP_CONFIG); + + if (error) { + nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + if (iface) + nm_device_set_ip_iface (device, iface); + + nm_device_activate_schedule_stage4_ip4_config_get (device); } } static gboolean -get_ppp_credentials (NMConnection *connection, - const char **username, - const char **password) +modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason) { - NMSettingGsm *s_gsm; - NMSettingCdma *s_cdma = NULL; + NMActRequest *req; + NMActStageReturn ret; - s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); - if (s_gsm) { - if (username) - *username = nm_setting_gsm_get_username (s_gsm); - if (password) - *password = nm_setting_gsm_get_password (s_gsm); - } else { - /* Try CDMA then */ - s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); - if (s_cdma) { - if (username) - *username = nm_setting_cdma_get_username (s_cdma); - if (password) - *password = nm_setting_cdma_get_password (s_cdma); - } + g_return_val_if_fail (reason != NULL, FALSE); + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); + + ret = nm_modem_act_stage1_prepare (modem, req, reason); + switch (ret) { + case NM_ACT_STAGE_RETURN_POSTPONE: + case NM_ACT_STAGE_RETURN_SUCCESS: + /* Success, wait for the 'prepare-result' signal */ + return TRUE; + case NM_ACT_STAGE_RETURN_FAILURE: + default: + break; } - return (s_cdma || s_gsm) ? TRUE : FALSE; + return FALSE; } - static void real_connection_secrets_updated (NMDevice *device, NMConnection *connection, @@ -369,111 +411,134 @@ real_connection_secrets_updated (NMDevice *device, NMDeviceBt *self = NM_DEVICE_BT (device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); NMActRequest *req; - const char *username = NULL, *password = NULL; - gboolean success = FALSE; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - if (caller != SECRETS_CALLER_PPP) - return; - - g_return_if_fail (priv->ppp_manager); + g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device))); req = nm_device_get_act_request (device); g_assert (req); - success = get_ppp_credentials (nm_act_request_get_connection (req), - &username, - &password); - if (success) { - nm_ppp_manager_update_secrets (priv->ppp_manager, - nm_device_get_ip_iface (device), - username ? username : "", - password ? password : "", - NULL); + if (!nm_modem_connection_secrets_updated (priv->modem, + req, + connection, + updated_settings, + caller)) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); return; } - /* Shouldn't ever happen */ - nm_ppp_manager_update_secrets (priv->ppp_manager, - nm_device_get_ip_iface (device), - NULL, - NULL, - "missing GSM/CDMA setting; no secrets could be found."); -} + /* PPP handles stuff itself... */ + if (caller == SECRETS_CALLER_PPP) + return; -static NMActStageReturn -ppp_stage3_start (NMDevice *device, NMDeviceStateReason *reason) -{ - NMDeviceBt *self = NM_DEVICE_BT (device); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - NMActRequest *req; - const char *ppp_name = NULL; - GError *err = NULL; - NMActStageReturn ret; - gboolean success; - - req = nm_device_get_act_request (device); - g_assert (req); - - success = get_ppp_credentials (nm_act_request_get_connection (req), - &ppp_name, - NULL); - if (!success) { - // FIXME: set reason to something plausible - return NM_ACT_STAGE_RETURN_FAILURE; - } - - priv->ppp_manager = nm_ppp_manager_new (priv->rfcomm_iface); - if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, 20, &err)) { - g_signal_connect (priv->ppp_manager, "state-changed", - G_CALLBACK (ppp_state_changed), - device); - g_signal_connect (priv->ppp_manager, "ip4-config", - G_CALLBACK (ppp_ip4_config), - device); - g_signal_connect (priv->ppp_manager, "stats", - G_CALLBACK (ppp_stats), - device); - - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - nm_warning ("%s", err->message); - g_error_free (err); - - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - - *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - - return ret; -} - -static NMActStageReturn -ppp_stage4 (NMDevice *device, NMIP4Config **config, NMDeviceStateReason *reason) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - NMConnection *connection; - NMSettingIP4Config *s_ip4; - - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - - /* Merge user-defined overrides into the IP4Config to be applied */ - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - nm_utils_merge_ip4_config (*config, s_ip4); - - return NM_ACT_STAGE_RETURN_SUCCESS; + /* Otherwise, on success for GSM/CDMA secrets we need to schedule modem stage1 again */ + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); + if (!modem_stage1 (self, priv->modem, &reason)) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); } /*****************************************************************************/ +gboolean +nm_device_bt_modem_added (NMDeviceBt *self, + NMModem *modem, + const char *driver) +{ + NMDeviceBtPrivate *priv; + const char *modem_iface; + char *base; + NMDeviceState state; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE); + g_return_val_if_fail (modem != NULL, FALSE); + g_return_val_if_fail (NM_IS_MODEM (modem), FALSE); + + priv = NM_DEVICE_BT_GET_PRIVATE (self); + modem_iface = nm_modem_get_iface (modem); + g_return_val_if_fail (modem_iface != NULL, FALSE); + + if (!priv->rfcomm_iface) + return FALSE; + + base = g_path_get_basename (priv->rfcomm_iface); + if (strcmp (base, modem_iface)) { + g_free (base); + return FALSE; + } + g_free (base); + + /* Got the modem */ + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + + /* Can only accept the modem in stage2, but since the interface matched + * what we were expecting, don't let anything else claim the modem either. + */ + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (state != NM_DEVICE_STATE_CONFIG) { + nm_warning ("(%s): modem found but device not in correct state (%d)", + nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_state (NM_DEVICE (self))); + return TRUE; + } + + nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) modem found.", + nm_device_get_iface (NM_DEVICE (self))); + + if (priv->modem) { + g_warn_if_reached (); + g_object_unref (priv->modem); + } + + priv->modem = g_object_ref (modem); + g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), self); + g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self); + g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self); + g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), self); + g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), self); + + /* Kick off the modem connection */ + if (!modem_stage1 (self, modem, &reason)) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, reason); + + return TRUE; +} + +gboolean +nm_device_bt_modem_removed (NMDeviceBt *self, NMModem *modem) +{ + NMDeviceBtPrivate *priv; + NMDeviceState state; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE); + g_return_val_if_fail (modem != NULL, FALSE); + g_return_val_if_fail (NM_IS_MODEM (modem), FALSE); + + priv = NM_DEVICE_BT_GET_PRIVATE (self); + + if (modem != priv->modem) + return FALSE; + + state = nm_device_get_state (NM_DEVICE (self)); + nm_modem_device_state_changed (priv->modem, + NM_DEVICE_STATE_DISCONNECTED, + state, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + + g_object_unref (priv->modem); + priv->modem = NULL; + return TRUE; +} + static void -nm_device_bt_connect_cb (DBusGProxy *proxy, - DBusGProxyCall *call_id, - void *user_data) +bluez_connect_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + void *user_data) { NMDeviceBt *self = NM_DEVICE_BT (user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); @@ -481,8 +546,8 @@ nm_device_bt_connect_cb (DBusGProxy *proxy, char *device; if (dbus_g_proxy_end_call (proxy, call_id, &error, - G_TYPE_STRING, &device, - G_TYPE_INVALID) == FALSE) { + G_TYPE_STRING, &device, + G_TYPE_INVALID) == FALSE) { nm_warning ("Error connecting with bluez: %s", error && error->message ? error->message : "(unknown)"); g_clear_error (&error); @@ -510,6 +575,20 @@ nm_device_bt_connect_cb (DBusGProxy *proxy, /* Stage 3 gets scheduled when Bluez says we're connected */ } +static gboolean +modem_find_timeout (gpointer user_data) +{ + NMDeviceBt *self = NM_DEVICE_BT (user_data); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + + priv->timeout_id = 0; + + nm_device_state_changed (NM_DEVICE (user_data), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND); + return FALSE; +} + static void bluez_property_changed (DBusGProxy *proxy, const char *property, @@ -528,18 +607,29 @@ bluez_property_changed (DBusGProxy *proxy, state = nm_device_get_state (device); connected = g_value_get_boolean (value); if (connected) { - /* Bluez says we're connected now. Start IP config. */ - if (state == NM_DEVICE_STATE_CONFIG) { gboolean pan = (priv->bt_type == NM_BT_CAPABILITY_NAP); gboolean dun = (priv->bt_type == NM_BT_CAPABILITY_DUN); nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) " - "successful. Connected via %s.", + "successful. Will connect via %s.", nm_device_get_iface (device), dun ? "DUN" : (pan ? "PAN" : "unknown")); - nm_device_activate_schedule_stage3_ip_config_start (device); + if (pan) { + /* Bluez says we're connected now. Start IP config. */ + nm_device_activate_schedule_stage3_ip_config_start (device); + } else if (dun) { + /* Wait for ModemManager to find the modem */ + if (priv->timeout_id) + g_source_remove (priv->timeout_id); + priv->timeout_id = g_timeout_add_seconds (20, modem_find_timeout, self); + + nm_info ("Activation (%s/bluetooth) Stage 2 of 5 (Device Configure) " + "waiting for modem to appear.", + nm_device_get_iface (device)); + } else + g_assert_not_reached (); } } else { gboolean fail = FALSE; @@ -589,6 +679,25 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) else g_assert_not_reached (); + priv->dev_proxy = dbus_g_proxy_new_for_name (g_connection, + BLUEZ_SERVICE, + nm_device_get_udi (device), + BLUEZ_DEVICE_INTERFACE); + if (!priv->dev_proxy) { + // FIXME: set a reason code + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* Watch for BT device property changes */ + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_VALUE, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->dev_proxy, "PropertyChanged", + G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->dev_proxy, "PropertyChanged", + G_CALLBACK (bluez_property_changed), device, NULL); + priv->type_proxy = dbus_g_proxy_new_for_name (g_connection, BLUEZ_SERVICE, nm_device_get_udi (device), @@ -600,23 +709,13 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) /* Connect to the BT device */ dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", - nm_device_bt_connect_cb, + bluez_connect_cb, device, NULL, 20000, G_TYPE_STRING, dun ? BLUETOOTH_DUN_UUID : BLUETOOTH_NAP_UUID, G_TYPE_INVALID); - /* Watch for BT device property changes */ - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_VALUE, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->type_proxy, "PropertyChanged", - G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->type_proxy, "PropertyChanged", - G_CALLBACK (bluez_property_changed), device, NULL); - return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -626,9 +725,12 @@ real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMActStageReturn ret; - if (priv->bt_type == NM_BT_CAPABILITY_DUN) - ret = ppp_stage3_start (device, reason); - else + if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + ret = nm_modem_stage3_ip4_config_start (NM_DEVICE_BT_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_bt_parent_class), + reason); + } else ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage3_ip4_config_start (device, reason); return ret; @@ -642,9 +744,13 @@ real_act_stage4_get_ip4_config (NMDevice *device, NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMActStageReturn ret; - if (priv->bt_type == NM_BT_CAPABILITY_DUN) - ret = ppp_stage4 (device, config, reason); - else + if (priv->bt_type == NM_BT_CAPABILITY_DUN) { + ret = nm_modem_stage4_get_ip4_config (NM_DEVICE_BT_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_bt_parent_class), + config, + reason); + } else ret = NM_DEVICE_CLASS (nm_device_bt_parent_class)->act_stage4_get_ip4_config (device, config, reason); return ret; @@ -655,17 +761,20 @@ real_deactivate_quickly (NMDevice *device) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - - priv->in_bytes = priv->out_bytes = 0; - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; + + if (priv->modem) { + nm_modem_deactivate_quickly (priv->modem, device); + + /* Since we're killing the Modem object before it'll get the + * state change signal, simulate the state change here. + */ + nm_modem_device_state_changed (priv->modem, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_ACTIVATED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + g_object_unref (priv->modem); + priv->modem = NULL; } if (priv->type_proxy) { @@ -689,6 +798,16 @@ real_deactivate_quickly (NMDevice *device) } } + if (priv->dev_proxy) { + g_object_unref (priv->dev_proxy); + priv->dev_proxy = NULL; + } + + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + priv->bt_type = NM_BT_CAPABILITY_NONE; g_free (priv->rfcomm_iface); @@ -698,6 +817,39 @@ real_deactivate_quickly (NMDevice *device) NM_DEVICE_CLASS (nm_device_bt_parent_class)->deactivate_quickly (device); } +/*****************************************************************************/ + +NMDevice * +nm_device_bt_new (const char *udi, + const char *bdaddr, + const char *name, + guint32 capabilities, + gboolean managed) +{ + NMDevice *device; + + g_return_val_if_fail (udi != NULL, NULL); + g_return_val_if_fail (bdaddr != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (capabilities != NM_BT_CAPABILITY_NONE, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_BT, + NM_DEVICE_INTERFACE_UDI, udi, + NM_DEVICE_INTERFACE_IFACE, bdaddr, + NM_DEVICE_INTERFACE_DRIVER, "bluez", + NM_DEVICE_BT_HW_ADDRESS, bdaddr, + NM_DEVICE_BT_NAME, name, + NM_DEVICE_BT_CAPABILITIES, capabilities, + NM_DEVICE_INTERFACE_MANAGED, managed, + NM_DEVICE_INTERFACE_TYPE_DESC, "Bluetooth", + NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_BT, + NULL); + if (device) + g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device); + + return device; +} + static void nm_device_bt_init (NMDeviceBt *self) { @@ -755,9 +907,21 @@ finalize (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + if (priv->timeout_id) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + } + if (priv->type_proxy) g_object_unref (priv->type_proxy); + if (priv->dev_proxy) + g_object_unref (priv->dev_proxy); + + if (priv->modem) + g_object_unref (priv->modem); + + g_free (priv->rfcomm_iface); g_free (priv->bdaddr); g_free (priv->name); diff --git a/src/nm-device-bt.h b/src/nm-device-bt.h index 67ef6f5f25..d3187d766f 100644 --- a/src/nm-device-bt.h +++ b/src/nm-device-bt.h @@ -22,6 +22,7 @@ #define NM_DEVICE_BT_H #include +#include "nm-modem.h" G_BEGIN_DECLS @@ -60,6 +61,12 @@ guint32 nm_device_bt_get_capabilities (NMDeviceBt *device); const char *nm_device_bt_get_hw_address (NMDeviceBt *device); +gboolean nm_device_bt_modem_added (NMDeviceBt *device, + NMModem *modem, + const char *driver); + +gboolean nm_device_bt_modem_removed (NMDeviceBt *device, NMModem *modem); + G_END_DECLS #endif /* NM_GSM_DEVICE_H */ diff --git a/src/nm-device-cdma.c b/src/nm-device-cdma.c index 4e8acb9ed8..4ab684d3ca 100644 --- a/src/nm-device-cdma.c +++ b/src/nm-device-cdma.c @@ -33,7 +33,10 @@ #include "nm-device-cdma-glue.h" -G_DEFINE_TYPE (NMDeviceCdma, nm_device_cdma, NM_TYPE_DEVICE) +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)) @@ -276,6 +279,16 @@ 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); + + if (priv->modem) + nm_modem_set_mm_enabled (priv->modem, enabled); +} + /*****************************************************************************/ NMDevice * @@ -308,6 +321,12 @@ nm_device_cdma_new (NMModemCdma *modem, const char *driver) 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) { diff --git a/src/nm-device-gsm.c b/src/nm-device-gsm.c index bd717c2ca1..efe46ba164 100644 --- a/src/nm-device-gsm.c +++ b/src/nm-device-gsm.c @@ -33,7 +33,10 @@ #include "nm-device-gsm-glue.h" -G_DEFINE_TYPE (NMDeviceGsm, nm_device_gsm, NM_TYPE_DEVICE) +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)) @@ -276,6 +279,16 @@ 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); + + if (priv->modem) + nm_modem_set_mm_enabled (priv->modem, enabled); +} + /*****************************************************************************/ NMDevice * @@ -308,6 +321,12 @@ nm_device_gsm_new (NMModemGsm *modem, const char *driver) 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) { diff --git a/src/nm-manager.c b/src/nm-manager.c index 210c6ee7da..f49c670b2c 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -320,6 +320,7 @@ modem_added (NMModemManager *modem_manager, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMDevice *replace_device, *device = NULL; const char *ip_iface; + GSList *iter; ip_iface = nm_modem_get_iface (modem); @@ -332,6 +333,25 @@ modem_added (NMModemManager *modem_manager, TRUE); } + /* 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)) @@ -444,7 +464,17 @@ modem_removed (NMModemManager *modem_manager, NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMDevice *found; + GSList *iter; + /* 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); @@ -1736,12 +1766,14 @@ find_device_by_iface (NMManager *self, const gchar *iface) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { NMDevice *device = NM_DEVICE (iter->data); const gchar *d_iface = nm_device_get_ip_iface (device); if (!strcmp (d_iface, iface)) return device; } + return NULL; }