From c5cf3b1d9bfca3475d85afab5c5fa0916a31e643 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 4 Oct 2009 21:41:49 -0700 Subject: [PATCH 01/12] 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. --- marshallers/nm-marshal.list | 3 + src/modem-manager/Makefile.am | 4 +- src/modem-manager/nm-modem-cdma.c | 200 +++++----- src/modem-manager/nm-modem-cdma.h | 8 +- src/modem-manager/nm-modem-gsm.c | 303 +++++----------- src/modem-manager/nm-modem-gsm.h | 9 +- src/modem-manager/nm-modem-manager.c | 51 +-- src/modem-manager/nm-modem-manager.h | 8 +- src/modem-manager/nm-modem.c | 524 ++++++++++++++++++++------- src/modem-manager/nm-modem.h | 93 ++++- src/nm-secrets-provider-interface.h | 3 +- 11 files changed, 709 insertions(+), 497 deletions(-) diff --git a/marshallers/nm-marshal.list b/marshallers/nm-marshal.list index 38669dd32..85f7158be 100644 --- a/marshallers/nm-marshal.list +++ b/marshallers/nm-marshal.list @@ -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 diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am index fef879ac4..79eab85fa 100644 --- a/src/modem-manager/Makefile.am +++ b/src/modem-manager/Makefile.am @@ -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 diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index 9ba0a7827..c69559710 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -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); } diff --git a/src/modem-manager/nm-modem-cdma.h b/src/modem-manager/nm-modem-cdma.h index 25dd9dcb1..96606a735 100644 --- a/src/modem-manager/nm-modem-cdma.h +++ b/src/modem-manager/nm-modem-cdma.h @@ -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 diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index 8f5b3b2db..b178590c0 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -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); } diff --git a/src/modem-manager/nm-modem-gsm.h b/src/modem-manager/nm-modem-gsm.h index 4e4581164..41e9094d2 100644 --- a/src/modem-manager/nm-modem-gsm.h +++ b/src/modem-manager/nm-modem-gsm.h @@ -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 diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c index 3b9f6438a..cb43c7b72 100644 --- a/src/modem-manager/nm-modem-manager.c +++ b/src/modem-manager/nm-modem-manager.c @@ -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); } diff --git a/src/modem-manager/nm-modem-manager.h b/src/modem-manager/nm-modem-manager.h index 34e99f1ec..7402f534d 100644 --- a/src/modem-manager/nm-modem-manager.h +++ b/src/modem-manager/nm-modem-manager.h @@ -4,7 +4,7 @@ #define NM_MODEM_MANAGER_H #include -#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); diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 508ff6a44..fa39bc8ec 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -2,27 +2,25 @@ #include #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); } + diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index cd638039f..ec4f91fac 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -4,8 +4,9 @@ #define NM_MODEM_H #include -#include +#include #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 diff --git a/src/nm-secrets-provider-interface.h b/src/nm-secrets-provider-interface.h index 299e8c2dc..3d9e08b18 100644 --- a/src/nm-secrets-provider-interface.h +++ b/src/nm-secrets-provider-interface.h @@ -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; From e4e9d4099819b108738a2d4ab0c46713c946f6b8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 4 Oct 2009 23:35:20 -0700 Subject: [PATCH 02/12] modem: re-implement CDMA device on top of generic modem code --- src/Makefile.am | 2 + src/modem-manager/nm-modem-cdma.c | 2 - src/modem-manager/nm-modem-gsm.c | 2 - src/modem-manager/nm-modem.c | 44 +++- src/modem-manager/nm-modem.h | 11 + src/nm-device-cdma.c | 378 ++++++++++++++++++++++++++++++ src/nm-device-cdma.h | 56 +++++ src/nm-manager.c | 52 ++-- 8 files changed, 511 insertions(+), 36 deletions(-) create mode 100644 src/nm-device-cdma.c create mode 100644 src/nm-device-cdma.h diff --git a/src/Makefile.am b/src/Makefile.am index fb337a6bb..4fb955dd2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,8 @@ NetworkManager_SOURCES = \ nm-device-olpc-mesh.h \ nm-device-bt.c \ nm-device-bt.h \ + nm-device-cdma.c \ + nm-device-cdma.h \ NetworkManagerAP.c \ NetworkManagerAP.h \ nm-dbus-manager.h \ diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index c69559710..f5964d427 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -13,8 +13,6 @@ #include "nm-utils.h" #include "NetworkManagerUtils.h" -#include "nm-device-cdma-glue.h" - 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)) diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index b178590c0..0a631d3ab 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -11,8 +11,6 @@ #include "nm-utils.h" #include "NetworkManagerUtils.h" -#include "nm-device-gsm-glue.h" - typedef enum { MM_MODEM_GSM_MODE_UNKNOWN = 0x00000000, MM_MODEM_GSM_MODE_ANY = 0x00000001, diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index fa39bc8ec..0b91efd12 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -268,13 +268,13 @@ static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); GValueArray *ret_array = NULL; GError *error = NULL; + NMIP4Config *config = NULL; priv->call = NULL; if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_VALUE_ARRAY, &ret_array, G_TYPE_INVALID)) { - NMIP4Config *config; NMIP4Address *addr; int i; @@ -285,7 +285,7 @@ static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) nm_ip4_address_set_prefix (addr, 32); nm_ip4_config_take_address (config, addr); - for (i = 1; i < ret_array->n_values; i++) { + for (i = 0; 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)); @@ -294,15 +294,10 @@ static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) priv->pending_ip4_config = g_object_ref (config); g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, NULL); - } else { - 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); } + + g_signal_emit (self, signals[IP4_CONFIG_RESULT], 0, NULL, config, error); + g_clear_error (&error); } static NMActStageReturn @@ -564,6 +559,26 @@ nm_modem_act_stage2_config (NMModem *self, return NM_ACT_STAGE_RETURN_SUCCESS; } +NMConnection * +nm_modem_get_best_auto_connection (NMModem *self, + GSList *connections, + char **specific_object) +{ + if (NM_MODEM_GET_CLASS (self)->get_best_auto_connection) + return NM_MODEM_GET_CLASS (self)->get_best_auto_connection (self, connections, specific_object); + return NULL; +} + +gboolean +nm_modem_check_connection_compatible (NMModem *self, + NMConnection *connection, + GError **error) +{ + if (NM_MODEM_GET_CLASS (self)->check_connection_compatible) + return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection, error); + return FALSE; +} + static void real_deactivate_quickly (NMModem *self, NMDevice *device) { @@ -689,6 +704,15 @@ nm_modem_get_iface (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->iface; } +const char * +nm_modem_get_path (NMModem *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_MODEM (self), NULL); + + return NM_MODEM_GET_PRIVATE (self)->path; +} + /*****************************************************************************/ static void diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index ec4f91fac..b8af89fb7 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -22,6 +22,8 @@ G_BEGIN_DECLS #define NM_MODEM_IFACE "iface" #define NM_MODEM_IP_METHOD "ip-method" +#define NM_MODEM_PPP_STATS "ppp-stats" +#define NM_MODEM_PPP_FAILED "ppp-failed" #define NM_MODEM_PREPARE_RESULT "prepare-result" #define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result" #define NM_MODEM_NEED_AUTH "need-auth" @@ -78,6 +80,15 @@ GType nm_modem_get_type (void); 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_path (NMModem *modem); + +NMConnection *nm_modem_get_best_auto_connection (NMModem *self, + GSList *connections, + char **specific_object); + +gboolean nm_modem_check_connection_compatible (NMModem *self, + NMConnection *connection, + GError **error); NMActStageReturn nm_modem_act_stage1_prepare (NMModem *modem, NMActRequest *req, diff --git a/src/nm-device-cdma.c b/src/nm-device-cdma.c new file mode 100644 index 000000000..0fc721b41 --- /dev/null +++ b/src/nm-device-cdma.c @@ -0,0 +1,378 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#include + +#include "nm-dbus-glib-types.h" +#include "nm-modem.h" +#include "nm-modem-cdma.h" +#include "nm-device-interface.h" +#include "nm-device-private.h" +#include "nm-device-cdma.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-marshal.h" +#include "nm-properties-changed-signal.h" + +#include "nm-device-cdma-glue.h" +#include "nm-serial-device-glue.h" + +G_DEFINE_TYPE (NMDeviceCdma, nm_device_cdma, NM_TYPE_DEVICE) + +#define NM_DEVICE_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaPrivate)) + +typedef struct { + gboolean disposed; + + NMModem *modem; +} NMDeviceCdmaPrivate; + +enum { + PPP_STATS, + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +ppp_stats (NMModem *modem, + guint32 in_bytes, + guint32 out_bytes, + gpointer user_data) +{ + g_signal_emit (NM_DEVICE_CDMA (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); +} + +static void +ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_ACTIVATED: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + break; + default: + break; + } +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device); + + nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); +} + +static gboolean +real_hw_is_up (NMDevice *device) +{ + return nm_modem_hw_is_up (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, device); +} + +static gboolean +real_hw_bring_up (NMDevice *device, gboolean *no_firmware) +{ + return nm_modem_hw_bring_up (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, device, no_firmware); +} + +static NMConnection * +real_get_best_auto_connection (NMDevice *device, + GSList *connections, + char **specific_object) +{ + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device); + + return nm_modem_get_best_auto_connection (priv->modem, connections, specific_object); +} + +static void +real_connection_secrets_updated (NMDevice *device, + NMConnection *connection, + GSList *updated_settings, + RequestSecretsCaller caller) +{ + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device); + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + if (!nm_modem_connection_secrets_updated (priv->modem, + req, + connection, + updated_settings, + caller)) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); + return; + } + + /* PPP handles stuff itself... */ + if (caller == SECRETS_CALLER_PPP) + return; + + /* Otherwise, on success for CDMA secrets we need to schedule stage1 again */ + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); + nm_device_activate_schedule_stage1_device_prepare (device); +} + +static gboolean +real_check_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error) +{ + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device); + + return nm_modem_check_connection_compatible (priv->modem, connection, error); +} + + +static void +modem_need_auth (NMModem *modem, + const char *setting_name, + gboolean retry, + RequestSecretsCaller caller, + const char *hint1, + const char *hint2, + gpointer user_data) +{ + NMDeviceCdma *self = NM_DEVICE_CDMA (self); + NMActRequest *req; + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); + + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2); +} + +static void +modem_prepare_result (NMModem *modem, + gboolean success, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + g_return_if_fail (state == NM_DEVICE_STATE_PREPARE); + + if (success) + nm_device_activate_schedule_stage2_device_config (device); + else + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + return nm_modem_act_stage1_prepare (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, req, reason); +} + +static NMActStageReturn +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + return nm_modem_act_stage2_config (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, req, reason); +} + +static void +modem_ip4_config_result (NMModem *self, + const char *iface, + NMIP4Config *config, + GError *error, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + g_return_if_fail (state == NM_DEVICE_STATE_IP_CONFIG); + + if (error) { + nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + if (iface) + nm_device_set_ip_iface (device, iface); + + nm_device_activate_schedule_stage4_ip4_config_get (device); + } +} + +static NMActStageReturn +real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +{ + return nm_modem_stage3_ip4_config_start (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_cdma_parent_class), + reason); +} + +static NMActStageReturn +real_act_stage4_get_ip4_config (NMDevice *device, + NMIP4Config **config, + NMDeviceStateReason *reason) +{ + return nm_modem_stage4_get_ip4_config (NM_DEVICE_CDMA_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_cdma_parent_class), + config, + reason); +} + +static void +real_deactivate_quickly (NMDevice *device) +{ + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device); + + nm_modem_deactivate_quickly (priv->modem, device); +} + +static guint32 +real_get_generic_capabilities (NMDevice *device) +{ + return NM_DEVICE_CAP_NM_SUPPORTED; +} + +/*****************************************************************************/ + +NMDevice * +nm_device_cdma_new (NMModemCdma *modem, const char *driver) +{ + NMDevice *device; + + g_return_val_if_fail (modem != NULL, NULL); + g_return_val_if_fail (NM_IS_MODEM_CDMA (modem), NULL); + g_return_val_if_fail (driver != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_CDMA, + NM_DEVICE_INTERFACE_UDI, nm_modem_get_path (NM_MODEM (modem)), + NM_DEVICE_INTERFACE_IFACE, nm_modem_get_iface (NM_MODEM (modem)), + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_TYPE_DESC, "CDMA", + NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA, + NULL); + if (device) { + NM_DEVICE_CDMA_GET_PRIVATE (device)->modem = g_object_ref (modem); + g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device); + + g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), device); + g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), device); + g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), device); + g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), device); + g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), device); + } + + return device; +} + +static void +nm_device_cdma_init (NMDeviceCdma *self) +{ +} + +static void +dispose (GObject *object) +{ + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_device_cdma_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + + g_object_unref (priv->modem); + priv->modem = NULL; + + G_OBJECT_CLASS (nm_device_cdma_parent_class)->dispose (object); +} + +static void +nm_device_cdma_class_init (NMDeviceCdmaClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceCdmaPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + + device_class->get_best_auto_connection = real_get_best_auto_connection; + device_class->connection_secrets_updated = real_connection_secrets_updated; + device_class->check_connection_compatible = real_check_connection_compatible; + device_class->hw_is_up = real_hw_is_up; + device_class->hw_bring_up = real_hw_bring_up; + device_class->get_generic_capabilities = real_get_generic_capabilities; + device_class->act_stage1_prepare = real_act_stage1_prepare; + device_class->act_stage2_config = real_act_stage2_config; + device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; + device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; + device_class->deactivate_quickly = real_deactivate_quickly; + + /* Signals */ + signals[PPP_STATS] = + g_signal_new ("ppp-stats", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceCdmaClass, ppp_stats), + NULL, NULL, + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, + G_TYPE_UINT, G_TYPE_UINT); + + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMDeviceCdmaClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_serial_device_object_info); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_cdma_object_info); +} + diff --git a/src/nm-device-cdma.h b/src/nm-device-cdma.h new file mode 100644 index 000000000..ec4496d74 --- /dev/null +++ b/src/nm-device-cdma.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_CDMA_H +#define NM_DEVICE_CDMA_H + +#include "nm-device.h" +#include "nm-modem-cdma.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_CDMA (nm_device_cdma_get_type ()) +#define NM_DEVICE_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_CDMA, NMDeviceCdma)) +#define NM_DEVICE_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaClass)) +#define NM_IS_DEVICE_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_CDMA)) +#define NM_IS_DEVICE_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_CDMA)) +#define NM_DEVICE_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaClass)) + +typedef struct { + NMDevice parent; +} NMDeviceCdma; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*signal_quality) (NMDeviceCdma *self, guint32 quality); + + void (*ppp_stats) (NMDeviceCdma *self, guint32 in_bytes, guint32 out_bytes); + void (*properties_changed) (NMDeviceCdma *self, GHashTable *properties); +} NMDeviceCdmaClass; + +GType nm_device_cdma_get_type (void); + +NMDevice *nm_device_cdma_new (NMModemCdma *modem, const char *driver); + +G_END_DECLS + +#endif /* NM_DEVICE_CDMA_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 416df1ac3..18c5df462 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -37,6 +37,8 @@ #include "nm-device-ethernet.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" +#include "nm-device-cdma.h" +//#include "nm-device-gsm.h" #include "NetworkManagerSystem.h" #include "nm-properties-changed-signal.h" #include "nm-setting-bluetooth.h" @@ -135,6 +137,8 @@ remove_one_device (NMManager *manager, gboolean quitting, gboolean force_unmanage); +static NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi); + #define SSD_POKE_INTERVAL 120 #define ORIGDEV_TAG "originating-device" @@ -289,26 +293,16 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager, static void modem_added (NMModemManager *modem_manager, - NMDevice *modem, + NMModem *modem, + const char *driver, gpointer user_data) { - NMManagerPrivate *priv; - NMDeviceType type; - NMDevice *replace_device; - const char *type_name; + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMDevice *replace_device, *device = NULL; const char *ip_iface; - priv = NM_MANAGER_GET_PRIVATE (user_data); - - type = nm_device_get_device_type (NM_DEVICE (modem)); - if (type == NM_DEVICE_TYPE_GSM) - type_name = "GSM modem"; - else if (type == NM_DEVICE_TYPE_CDMA) - type_name = "CDMA modem"; - else - type_name = "Unknown modem"; - - ip_iface = nm_device_get_ip_iface (modem); + ip_iface = nm_modem_get_iface (modem); replace_device = find_device_by_iface (NM_MANAGER (user_data), ip_iface); if (replace_device) { @@ -319,7 +313,18 @@ modem_added (NMModemManager *modem_manager, TRUE); } - add_device (NM_MANAGER (user_data), NM_DEVICE (g_object_ref (modem))); +#if 0 + if (NM_IS_MODEM_GSM (modem)) + device = nm_device_gsm_new (NM_MODEM_GSM (modem), driver); + else +#endif + if (NM_IS_MODEM_CDMA (modem)) + device = nm_device_cdma_new (NM_MODEM_CDMA (modem), driver); + else + g_message ("%s: unhandled modem '%s'", __func__, ip_iface); + + if (device) + add_device (self, device); } static void @@ -417,13 +422,16 @@ remove_one_device (NMManager *manager, static void modem_removed (NMModemManager *modem_manager, - NMDevice *modem, + NMModem *modem, gpointer user_data) { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMDevice *found; - priv->devices = remove_one_device (self, priv->devices, modem, FALSE, TRUE); + found = nm_manager_get_device_by_udi (self, nm_modem_get_path (modem)); + if (found) + priv->devices = remove_one_device (self, priv->devices, found, FALSE, TRUE); } static void @@ -1208,7 +1216,7 @@ add_device (NMManager *self, NMDevice *device) iface = nm_device_get_ip_iface (device); g_assert (iface); - if (!NM_IS_MODEM(device) && nm_modem_manager_has_modem_for_iface (priv->modem_manager, iface)) { + if (!NM_IS_MODEM (device) && nm_modem_manager_has_modem_for_iface (priv->modem_manager, iface)) { g_object_unref (device); return; } @@ -2770,9 +2778,9 @@ nm_manager_init (NMManager *manager) g_object_unref); priv->modem_manager = nm_modem_manager_get (); - priv->modem_added_id = g_signal_connect (priv->modem_manager, "device-added", + priv->modem_added_id = g_signal_connect (priv->modem_manager, "modem-added", G_CALLBACK (modem_added), manager); - priv->modem_removed_id = g_signal_connect (priv->modem_manager, "device-removed", + priv->modem_removed_id = g_signal_connect (priv->modem_manager, "modem-removed", G_CALLBACK (modem_removed), manager); priv->vpn_manager = nm_vpn_manager_get (); From 66fbf31a19891224d612a6731f4c407c24d73538 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 4 Oct 2009 23:57:51 -0700 Subject: [PATCH 03/12] modem: fix stage3 IP config kickoff --- src/modem-manager/nm-modem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 0b91efd12..ace65cf35 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -371,7 +371,7 @@ nm_modem_stage3_ip4_config_start (NMModem *self, req = nm_device_get_act_request (device); g_assert (req); - switch (NM_MODEM_GET_PRIVATE (device)->ip_method) { + switch (NM_MODEM_GET_PRIVATE (self)->ip_method) { case MM_MODEM_IP_METHOD_PPP: ret = ppp_stage3_ip4_config_start (self, req, reason); break; From ac739e3311f4d91e4e42f017700b69d85619e3ea Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 4 Oct 2009 23:59:20 -0700 Subject: [PATCH 04/12] manager: fix up composite modem device detection and suppression Some modems have their ethernet interface show up only on connect, and we want NM to ignore the ethernet interface as a top-level device. --- src/modem-manager/nm-modem-manager.c | 20 -------------------- src/modem-manager/nm-modem-manager.h | 3 --- src/nm-manager.c | 16 +++++++--------- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c index cb43c7b72..df71f3d08 100644 --- a/src/modem-manager/nm-modem-manager.c +++ b/src/modem-manager/nm-modem-manager.c @@ -48,26 +48,6 @@ nm_modem_manager_get (void) return singleton; } -gboolean -nm_modem_manager_has_modem_for_iface (NMModemManager *manager, - const gchar *iface) -{ - NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager); - GList *iter; - g_assert (manager); - g_assert (NM_IS_MODEM_MANAGER(manager)); - g_assert (iface); - - for (iter = g_hash_table_get_values(priv->modems); iter != NULL; iter = iter->next) { - 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; -} - static gboolean get_modem_properties (DBusGConnection *connection, const char *path, diff --git a/src/modem-manager/nm-modem-manager.h b/src/modem-manager/nm-modem-manager.h index 7402f534d..19b991a38 100644 --- a/src/modem-manager/nm-modem-manager.h +++ b/src/modem-manager/nm-modem-manager.h @@ -30,7 +30,4 @@ GType nm_modem_manager_get_type (void); NMModemManager *nm_modem_manager_get (void); -gboolean nm_modem_manager_has_modem_for_iface (NMModemManager *manager, - const gchar *iface); - #endif /* NM_MODEM_MANAGER_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 66b50ea26..e27fb94e3 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -127,15 +127,13 @@ static const char *internal_activate_device (NMManager *manager, gboolean assumed, GError **error); -static NMDevice * -find_device_by_iface (NMManager *self, const gchar *iface); +static NMDevice *find_device_by_iface (NMManager *self, const gchar *iface); -static GSList * -remove_one_device (NMManager *manager, - GSList *list, - NMDevice *device, - gboolean quitting, - gboolean force_unmanage); +static GSList * remove_one_device (NMManager *manager, + GSList *list, + NMDevice *device, + gboolean quitting, + gboolean force_unmanage); static NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi); @@ -1214,7 +1212,7 @@ add_device (NMManager *self, NMDevice *device) iface = nm_device_get_ip_iface (device); g_assert (iface); - if (!NM_IS_MODEM (device) && nm_modem_manager_has_modem_for_iface (priv->modem_manager, iface)) { + if (!NM_IS_MODEM (device) && find_device_by_iface (self, iface)) { g_object_unref (device); return; } From 8822f7565266e60c328a61aff729c11ca64184b8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 5 Oct 2009 00:05:09 -0700 Subject: [PATCH 05/12] cdma: fix device dispose Move modem destruction from dispose -> finalize, because the superclass still needs to use the device at dispose time. --- src/nm-device-cdma.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/nm-device-cdma.c b/src/nm-device-cdma.c index 0fc721b41..4f4ee5581 100644 --- a/src/nm-device-cdma.c +++ b/src/nm-device-cdma.c @@ -39,8 +39,6 @@ G_DEFINE_TYPE (NMDeviceCdma, nm_device_cdma, NM_TYPE_DEVICE) #define NM_DEVICE_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_CDMA, NMDeviceCdmaPrivate)) typedef struct { - gboolean disposed; - NMModem *modem; } NMDeviceCdmaPrivate; @@ -315,20 +313,14 @@ nm_device_cdma_init (NMDeviceCdma *self) } static void -dispose (GObject *object) +finalize (GObject *object) { NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (object); - if (priv->disposed) { - G_OBJECT_CLASS (nm_device_cdma_parent_class)->dispose (object); - return; - } - priv->disposed = TRUE; - g_object_unref (priv->modem); priv->modem = NULL; - G_OBJECT_CLASS (nm_device_cdma_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_device_cdma_parent_class)->finalize (object); } static void @@ -340,7 +332,7 @@ nm_device_cdma_class_init (NMDeviceCdmaClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceCdmaPrivate)); /* Virtual methods */ - object_class->dispose = dispose; + object_class->finalize = finalize; device_class->get_best_auto_connection = real_get_best_auto_connection; device_class->connection_secrets_updated = real_connection_secrets_updated; From 9fb584242ca3cfa4a4a62b74fc11d8e37dc38f13 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 5 Oct 2009 00:13:01 -0700 Subject: [PATCH 06/12] modem: kill active connections on shutdown --- src/modem-manager/nm-modem.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index ace65cf35..0eb1d9102 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -624,6 +624,14 @@ 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 From 55bb7a85fd2e23f97578b0a6d912fa7ffb2bdc46 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 5 Oct 2009 00:42:53 -0700 Subject: [PATCH 07/12] modem: re-implement GSM device on top of generic modem code Serial interface D-Bus info has to be somewhere neutral. Fix a CDMA secrets bug. --- src/Makefile.am | 2 + src/modem-manager/nm-modem.c | 8 + src/modem-manager/nm-modem.h | 2 + src/nm-device-cdma.c | 7 +- src/nm-device-gsm.c | 369 +++++++++++++++++++++++++++++++++++ src/nm-device-gsm.h | 56 ++++++ src/nm-manager.c | 7 +- 7 files changed, 442 insertions(+), 9 deletions(-) create mode 100644 src/nm-device-gsm.c create mode 100644 src/nm-device-gsm.h diff --git a/src/Makefile.am b/src/Makefile.am index 4fb955dd2..36aa1e68a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,6 +76,8 @@ NetworkManager_SOURCES = \ nm-device-bt.h \ nm-device-cdma.c \ nm-device-cdma.h \ + nm-device-gsm.c \ + nm-device-gsm.h \ NetworkManagerAP.c \ NetworkManagerAP.h \ nm-dbus-manager.h \ diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 0eb1d9102..a2b37fb0d 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -13,6 +13,8 @@ #include "nm-device-private.h" #include "nm-device-interface.h" +#include "nm-serial-device-glue.h" + 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)) @@ -944,3 +946,9 @@ nm_modem_class_init (NMModemClass *klass) G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); } +const DBusGObjectInfo * +nm_modem_get_serial_dbus_info (void) +{ + return &dbus_glib_nm_serial_device_object_info; +} + diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index b8af89fb7..5c0c741c5 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -126,6 +126,8 @@ gboolean nm_modem_connection_secrets_updated (NMModem *modem, GSList *updated_settings, RequestSecretsCaller caller); +const DBusGObjectInfo *nm_modem_get_serial_dbus_info (void); + G_END_DECLS #endif /* NM_MODEM_H */ diff --git a/src/nm-device-cdma.c b/src/nm-device-cdma.c index 4f4ee5581..78f5ed335 100644 --- a/src/nm-device-cdma.c +++ b/src/nm-device-cdma.c @@ -32,7 +32,6 @@ #include "nm-properties-changed-signal.h" #include "nm-device-cdma-glue.h" -#include "nm-serial-device-glue.h" G_DEFINE_TYPE (NMDeviceCdma, nm_device_cdma, NM_TYPE_DEVICE) @@ -162,7 +161,7 @@ modem_need_auth (NMModem *modem, const char *hint2, gpointer user_data) { - NMDeviceCdma *self = NM_DEVICE_CDMA (self); + NMDeviceCdma *self = NM_DEVICE_CDMA (user_data); NMActRequest *req; req = nm_device_get_act_request (NM_DEVICE (self)); @@ -359,10 +358,10 @@ nm_device_cdma_class_init (NMDeviceCdmaClass *klass) signals[PROPERTIES_CHANGED] = nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMDeviceCdmaClass, properties_changed)); + G_STRUCT_OFFSET (NMDeviceCdmaClass, properties_changed)); dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_serial_device_object_info); + nm_modem_get_serial_dbus_info ()); dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_cdma_object_info); diff --git a/src/nm-device-gsm.c b/src/nm-device-gsm.c new file mode 100644 index 000000000..4f738ec3a --- /dev/null +++ b/src/nm-device-gsm.c @@ -0,0 +1,369 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#include + +#include "nm-dbus-glib-types.h" +#include "nm-modem.h" +#include "nm-modem-gsm.h" +#include "nm-device-interface.h" +#include "nm-device-private.h" +#include "nm-device-gsm.h" +#include "nm-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-marshal.h" +#include "nm-properties-changed-signal.h" + +#include "nm-device-gsm-glue.h" + +G_DEFINE_TYPE (NMDeviceGsm, nm_device_gsm, NM_TYPE_DEVICE) + +#define NM_DEVICE_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GSM, NMDeviceGsmPrivate)) + +typedef struct { + NMModem *modem; +} NMDeviceGsmPrivate; + +enum { + PPP_STATS, + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +ppp_stats (NMModem *modem, + guint32 in_bytes, + guint32 out_bytes, + gpointer user_data) +{ + g_signal_emit (NM_DEVICE_GSM (user_data), signals[PPP_STATS], 0, in_bytes, out_bytes); +} + +static void +ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (nm_device_interface_get_state (NM_DEVICE_INTERFACE (device))) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_ACTIVATED: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + break; + default: + break; + } +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device); + + nm_modem_device_state_changed (priv->modem, new_state, old_state, reason); +} + +static gboolean +real_hw_is_up (NMDevice *device) +{ + return nm_modem_hw_is_up (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, device); +} + +static gboolean +real_hw_bring_up (NMDevice *device, gboolean *no_firmware) +{ + return nm_modem_hw_bring_up (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, device, no_firmware); +} + +static NMConnection * +real_get_best_auto_connection (NMDevice *device, + GSList *connections, + char **specific_object) +{ + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device); + + return nm_modem_get_best_auto_connection (priv->modem, connections, specific_object); +} + +static void +real_connection_secrets_updated (NMDevice *device, + NMConnection *connection, + GSList *updated_settings, + RequestSecretsCaller caller) +{ + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device); + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + if (!nm_modem_connection_secrets_updated (priv->modem, + req, + connection, + updated_settings, + caller)) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); + return; + } + + /* PPP handles stuff itself... */ + if (caller == SECRETS_CALLER_PPP) + return; + + /* Otherwise, on success for GSM secrets we need to schedule stage1 again */ + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); + nm_device_activate_schedule_stage1_device_prepare (device); +} + +static gboolean +real_check_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error) +{ + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device); + + return nm_modem_check_connection_compatible (priv->modem, connection, error); +} + + +static void +modem_need_auth (NMModem *modem, + const char *setting_name, + gboolean retry, + RequestSecretsCaller caller, + const char *hint1, + const char *hint2, + gpointer user_data) +{ + NMDeviceGsm *self = NM_DEVICE_GSM (user_data); + NMActRequest *req; + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_assert (req); + + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + nm_act_request_get_secrets (req, setting_name, retry, caller, hint1, hint2); +} + +static void +modem_prepare_result (NMModem *modem, + gboolean success, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + g_return_if_fail (state == NM_DEVICE_STATE_PREPARE); + + if (success) + nm_device_activate_schedule_stage2_device_config (device); + else + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + return nm_modem_act_stage1_prepare (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, req, reason); +} + +static NMActStageReturn +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActRequest *req; + + req = nm_device_get_act_request (device); + g_assert (req); + + return nm_modem_act_stage2_config (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, req, reason); +} + +static void +modem_ip4_config_result (NMModem *self, + const char *iface, + NMIP4Config *config, + GError *error, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + g_return_if_fail (state == NM_DEVICE_STATE_IP_CONFIG); + + if (error) { + nm_warning ("%s: retrieving IP4 configuration failed: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + if (iface) + nm_device_set_ip_iface (device, iface); + + nm_device_activate_schedule_stage4_ip4_config_get (device); + } +} + +static NMActStageReturn +real_act_stage3_ip4_config_start (NMDevice *device, NMDeviceStateReason *reason) +{ + return nm_modem_stage3_ip4_config_start (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_gsm_parent_class), + reason); +} + +static NMActStageReturn +real_act_stage4_get_ip4_config (NMDevice *device, + NMIP4Config **config, + NMDeviceStateReason *reason) +{ + return nm_modem_stage4_get_ip4_config (NM_DEVICE_GSM_GET_PRIVATE (device)->modem, + device, + NM_DEVICE_CLASS (nm_device_gsm_parent_class), + config, + reason); +} + +static void +real_deactivate_quickly (NMDevice *device) +{ + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device); + + nm_modem_deactivate_quickly (priv->modem, device); +} + +static guint32 +real_get_generic_capabilities (NMDevice *device) +{ + return NM_DEVICE_CAP_NM_SUPPORTED; +} + +/*****************************************************************************/ + +NMDevice * +nm_device_gsm_new (NMModemGsm *modem, const char *driver) +{ + NMDevice *device; + + g_return_val_if_fail (modem != NULL, NULL); + g_return_val_if_fail (NM_IS_MODEM_GSM (modem), NULL); + g_return_val_if_fail (driver != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_GSM, + NM_DEVICE_INTERFACE_UDI, nm_modem_get_path (NM_MODEM (modem)), + NM_DEVICE_INTERFACE_IFACE, nm_modem_get_iface (NM_MODEM (modem)), + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_TYPE_DESC, "GSM", + NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM, + NULL); + if (device) { + NM_DEVICE_GSM_GET_PRIVATE (device)->modem = g_object_ref (modem); + g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device); + + g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), device); + g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), device); + g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), device); + g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), device); + g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), device); + } + + return device; +} + +static void +nm_device_gsm_init (NMDeviceGsm *self) +{ +} + +static void +finalize (GObject *object) +{ + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (object); + + g_object_unref (priv->modem); + priv->modem = NULL; + + G_OBJECT_CLASS (nm_device_gsm_parent_class)->finalize (object); +} + +static void +nm_device_gsm_class_init (NMDeviceGsmClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceGsmPrivate)); + + /* Virtual methods */ + object_class->finalize = finalize; + + device_class->get_best_auto_connection = real_get_best_auto_connection; + device_class->connection_secrets_updated = real_connection_secrets_updated; + device_class->check_connection_compatible = real_check_connection_compatible; + device_class->hw_is_up = real_hw_is_up; + device_class->hw_bring_up = real_hw_bring_up; + device_class->get_generic_capabilities = real_get_generic_capabilities; + device_class->act_stage1_prepare = real_act_stage1_prepare; + device_class->act_stage2_config = real_act_stage2_config; + device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; + device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; + device_class->deactivate_quickly = real_deactivate_quickly; + + /* Signals */ + signals[PPP_STATS] = + g_signal_new ("ppp-stats", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceGsmClass, ppp_stats), + NULL, NULL, + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, + G_TYPE_UINT, G_TYPE_UINT); + + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMDeviceGsmClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + nm_modem_get_serial_dbus_info ()); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_gsm_object_info); +} + diff --git a/src/nm-device-gsm.h b/src/nm-device-gsm.h new file mode 100644 index 000000000..1a74cfa1c --- /dev/null +++ b/src/nm-device-gsm.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef NM_DEVICE_GSM_H +#define NM_DEVICE_GSM_H + +#include "nm-device.h" +#include "nm-modem-gsm.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_GSM (nm_device_gsm_get_type ()) +#define NM_DEVICE_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GSM, NMDeviceGsm)) +#define NM_DEVICE_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GSM, NMDeviceGsmClass)) +#define NM_IS_DEVICE_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GSM)) +#define NM_IS_DEVICE_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GSM)) +#define NM_DEVICE_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GSM, NMDeviceGsmClass)) + +typedef struct { + NMDevice parent; +} NMDeviceGsm; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*signal_quality) (NMDeviceGsm *self, guint32 quality); + + void (*ppp_stats) (NMDeviceGsm *self, guint32 in_bytes, guint32 out_bytes); + void (*properties_changed) (NMDeviceGsm *self, GHashTable *properties); +} NMDeviceGsmClass; + +GType nm_device_gsm_get_type (void); + +NMDevice *nm_device_gsm_new (NMModemGsm *modem, const char *driver); + +G_END_DECLS + +#endif /* NM_DEVICE_GSM_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index e27fb94e3..f1ac17162 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -38,7 +38,7 @@ #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" #include "nm-device-cdma.h" -//#include "nm-device-gsm.h" +#include "nm-device-gsm.h" #include "NetworkManagerSystem.h" #include "nm-properties-changed-signal.h" #include "nm-setting-bluetooth.h" @@ -311,12 +311,9 @@ modem_added (NMModemManager *modem_manager, TRUE); } -#if 0 if (NM_IS_MODEM_GSM (modem)) device = nm_device_gsm_new (NM_MODEM_GSM (modem), driver); - else -#endif - if (NM_IS_MODEM_CDMA (modem)) + else if (NM_IS_MODEM_CDMA (modem)) device = nm_device_cdma_new (NM_MODEM_CDMA (modem), driver); else g_message ("%s: unhandled modem '%s'", __func__, ip_iface); From bc81b998a91e81e2a62df28dfbb13d9b2606da93 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 5 Oct 2009 00:51:29 -0700 Subject: [PATCH 08/12] build: fix generation of CDMA & GSM dbus interface data --- src/Makefile.am | 8 ++++++++ src/modem-manager/Makefile.am | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 36aa1e68a..ce3183e27 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -151,6 +151,12 @@ nm-active-connection-glue.h: $(top_srcdir)/introspection/nm-active-connection.xm nm-dhcp4-config-glue.h: $(top_srcdir)/introspection/nm-dhcp4-config.xml dbus-binding-tool --prefix=nm_dhcp4_config --mode=glib-server --output=$@ $< +nm-device-cdma-glue.h: $(top_srcdir)/introspection/nm-device-cdma.xml + dbus-binding-tool --prefix=nm_device_cdma --mode=glib-server --output=$@ $< + +nm-device-gsm-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml + dbus-binding-tool --prefix=nm_device_gsm --mode=glib-server --output=$@ $< + BUILT_SOURCES = \ nm-access-point-glue.h \ nm-manager-glue.h \ @@ -159,6 +165,8 @@ BUILT_SOURCES = \ nm-device-wifi-glue.h \ nm-device-olpc-mesh-glue.h \ nm-device-bt-glue.h \ + nm-device-cdma-glue.h \ + nm-device-gsm-glue.h \ nm-ip4-config-glue.h \ nm-ip6-config-glue.h \ nm-active-connection-glue.h \ diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am index 79eab85fa..932a041c0 100644 --- a/src/modem-manager/Makefile.am +++ b/src/modem-manager/Makefile.am @@ -24,18 +24,10 @@ libmodem_manager_la_LIBADD = \ $(top_builddir)/marshallers/libmarshallers.la \ $(DBUS_LIBS) -nm-device-cdma-glue.h: $(top_srcdir)/introspection/nm-device-cdma.xml - dbus-binding-tool --prefix=nm_device_cdma --mode=glib-server --output=$@ $< - -nm-device-gsm-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml - dbus-binding-tool --prefix=nm_device_gsm --mode=glib-server --output=$@ $< - nm-serial-device-glue.h: $(top_srcdir)/introspection/nm-device-serial.xml dbus-binding-tool --prefix=nm_serial_device --mode=glib-server --output=$@ $< BUILT_SOURCES = \ - nm-device-cdma-glue.h \ - nm-device-gsm-glue.h \ nm-serial-device-glue.h CLEANFILES = $(BUILT_SOURCES) From 75898f075b10ece1715e5a923ec6025f2eb85ffc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 27 Jan 2010 17:28:35 -0800 Subject: [PATCH 09/12] bluetooth: minor cleanup for device connect --- src/nm-device-bt.c | 59 +++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c index 444c7ff05..b2374d9a0 100644 --- a/src/nm-device-bt.c +++ b/src/nm-device-bt.c @@ -567,6 +567,7 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NMActRequest *req; NMDBusManager *dbus_mgr; DBusGConnection *g_connection; + gboolean dun = FALSE; req = nm_device_get_act_request (device); g_assert (req); @@ -581,43 +582,31 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) g_connection = nm_dbus_manager_get_connection (dbus_mgr); g_object_unref (dbus_mgr); - if (priv->bt_type == NM_BT_CAPABILITY_DUN) { - priv->type_proxy = dbus_g_proxy_new_for_name (g_connection, - BLUEZ_SERVICE, - nm_device_get_udi (device), - BLUEZ_SERIAL_INTERFACE); - if (!priv->type_proxy) { - // FIXME: set a reason code - return NM_ACT_STAGE_RETURN_FAILURE; - } - - dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", - nm_device_bt_connect_cb, - device, - NULL, - 20000, - G_TYPE_STRING, BLUETOOTH_DUN_UUID, - G_TYPE_INVALID); - } else if (priv->bt_type == NM_BT_CAPABILITY_NAP) { - priv->type_proxy = dbus_g_proxy_new_for_name (g_connection, - BLUEZ_SERVICE, - nm_device_get_udi (device), - BLUEZ_NETWORK_INTERFACE); - if (!priv->type_proxy) { - // FIXME: set a reason code - return NM_ACT_STAGE_RETURN_FAILURE; - } - - dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", - nm_device_bt_connect_cb, - device, - NULL, - 20000, - G_TYPE_STRING, BLUETOOTH_NAP_UUID, - G_TYPE_INVALID); - } else + if (priv->bt_type == NM_BT_CAPABILITY_DUN) + dun = TRUE; + else if (priv->bt_type == NM_BT_CAPABILITY_NAP) + dun = FALSE; + else g_assert_not_reached (); + priv->type_proxy = dbus_g_proxy_new_for_name (g_connection, + BLUEZ_SERVICE, + nm_device_get_udi (device), + dun ? BLUEZ_SERIAL_INTERFACE : BLUEZ_NETWORK_INTERFACE); + if (!priv->type_proxy) { + // FIXME: set a reason code + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* Connect to the BT device */ + dbus_g_proxy_begin_call_with_timeout (priv->type_proxy, "Connect", + nm_device_bt_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, From 0a5a0146f8b80dbfe871b050b7c7f4faada12f8c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 28 Jan 2010 11:21:53 -0800 Subject: [PATCH 10/12] bluetooth: finish DUN implementation --- include/NetworkManager.h | 3 + src/modem-manager/nm-modem-cdma.c | 101 +++--- src/modem-manager/nm-modem-gsm.c | 101 +++--- src/modem-manager/nm-modem.c | 35 +- src/modem-manager/nm-modem.h | 4 +- src/nm-device-bt.c | 570 +++++++++++++++++++----------- src/nm-device-bt.h | 7 + src/nm-device-cdma.c | 21 +- src/nm-device-gsm.c | 21 +- src/nm-manager.c | 32 ++ 10 files changed, 581 insertions(+), 314 deletions(-) diff --git a/include/NetworkManager.h b/include/NetworkManager.h index c8d5074a1..eb3c1a743 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 d712df690..f2a04dc07 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 bddfd809d..60d8b4f8d 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 228dcba7f..3d32e1914 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 c5e34ad03..a2aed57e0 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 b2374d9a0..ab2572536 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 67ef6f5f2..d3187d766 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 4e8acb9ed..4ab684d3c 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 bd717c2ca..efe46ba16 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 210c6ee7d..f49c670b2 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; } From 86e48439025379b033daf1ea92b43d0d2df06d23 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 28 Jan 2010 12:15:00 -0800 Subject: [PATCH 11/12] introspection: sync device state reason codes with NetworkManager.h --- introspection/nm-device.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml index c23b596c4..49b77a5ba 100644 --- a/introspection/nm-device.xml +++ b/introspection/nm-device.xml @@ -392,7 +392,12 @@ The 802.1x supplicant is now available. - + + + The modem could not be found. + + + From 183c256bad931a757e3252ecd433a001d5470104 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 11 Feb 2010 22:53:49 -0800 Subject: [PATCH 12/12] modem: deactivate device if modem is disabled underneath NM --- src/nm-device-cdma.c | 14 ++++++++++++-- src/nm-device-gsm.c | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/nm-device-cdma.c b/src/nm-device-cdma.c index 3ee797dc0..bc73e9dab 100644 --- a/src/nm-device-cdma.c +++ b/src/nm-device-cdma.c @@ -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 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #include @@ -300,6 +300,15 @@ real_set_enabled (NMDeviceInterface *device, gboolean enabled) } } +static void +modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +{ + NMDeviceCdma *self = NM_DEVICE_CDMA (user_data); + NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (self); + + real_set_enabled (NM_DEVICE_INTERFACE (self), nm_modem_get_mm_enabled (priv->modem)); +} + /*****************************************************************************/ NMDevice * @@ -319,14 +328,15 @@ nm_device_cdma_new (NMModemCdma *modem, const char *driver) NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_CDMA, NULL); if (device) { - NM_DEVICE_CDMA_GET_PRIVATE (device)->modem = g_object_ref (modem); g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device); + NM_DEVICE_CDMA_GET_PRIVATE (device)->modem = g_object_ref (modem); g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), device); g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), device); g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), device); g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), device); g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), device); + g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), device); } return device; diff --git a/src/nm-device-gsm.c b/src/nm-device-gsm.c index b99243d88..1bb701753 100644 --- a/src/nm-device-gsm.c +++ b/src/nm-device-gsm.c @@ -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 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #include @@ -300,6 +300,15 @@ real_set_enabled (NMDeviceInterface *device, gboolean enabled) } } +static void +modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +{ + NMDeviceGsm *self = NM_DEVICE_GSM (user_data); + NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (self); + + real_set_enabled (NM_DEVICE_INTERFACE (self), nm_modem_get_mm_enabled (priv->modem)); +} + /*****************************************************************************/ NMDevice * @@ -319,14 +328,15 @@ nm_device_gsm_new (NMModemGsm *modem, const char *driver) NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_GSM, NULL); if (device) { - NM_DEVICE_GSM_GET_PRIVATE (device)->modem = g_object_ref (modem); g_signal_connect (device, "state-changed", G_CALLBACK (device_state_changed), device); + NM_DEVICE_GSM_GET_PRIVATE (device)->modem = g_object_ref (modem); g_signal_connect (modem, NM_MODEM_PPP_STATS, G_CALLBACK (ppp_stats), device); g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), device); g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), device); g_signal_connect (modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK (modem_ip4_config_result), device); g_signal_connect (modem, NM_MODEM_NEED_AUTH, G_CALLBACK (modem_need_auth), device); + g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), device); } return device;