diff --git a/ChangeLog b/ChangeLog index fc7b442d96..e44f905eb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2008-08-14 Dan Williams + + * src/nm-activation-request.h + - Add HSO secrets caller + + * src/nm-gsm-device.c + src/nm-gsm-device.h + - (modem_wait_for_reply): add a 'user_data' argument so callers can pass + something to the callback function + - (set_apn, set_apn_done): call class dial function, not a static one + - (nm_gsm_device_class_init): add a class 'dial' function + + * src/nm-hal-manager.c + - (get_hso_netdev): find the hso-driven hardware's net device + - (modem_device_creator): recognize hso-driven hardware and create the + right type of device object for it + + * src/Makefile.am + src/nm-hso-gsm-device.c + src/nm-hso-gsm-device.h + - Implement support for devices driven by the 'hso' driver as a subclass + of NMGsmDevice + 2008-08-14 Dan Williams * src/NetworkManagerSystem.c diff --git a/src/Makefile.am b/src/Makefile.am index 91dd0d0e35..c125ed83b0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,6 +65,8 @@ NetworkManager_SOURCES = \ nm-gsm-device.h \ nm-cdma-device.c \ nm-cdma-device.h \ + nm-hso-gsm-device.c \ + nm-hso-gsm-device.h \ wpa.c \ wpa.h \ nm-netlink.c \ diff --git a/src/nm-activation-request.h b/src/nm-activation-request.h index ff26cc4e35..a76f2db80e 100644 --- a/src/nm-activation-request.h +++ b/src/nm-activation-request.h @@ -44,7 +44,8 @@ typedef enum { SECRETS_CALLER_WIFI, SECRETS_CALLER_GSM, SECRETS_CALLER_CDMA, - SECRETS_CALLER_PPP + SECRETS_CALLER_PPP, + SECRETS_CALLER_HSO_GSM } RequestSecretsCaller; typedef struct { diff --git a/src/nm-gsm-device.c b/src/nm-gsm-device.c index df8471fd6a..1388487ca2 100644 --- a/src/nm-gsm-device.c +++ b/src/nm-gsm-device.c @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ #include #include @@ -74,13 +74,14 @@ modem_wait_for_reply (NMGsmDevice *self, guint timeout, char **responses, char **terminators, - NMSerialWaitForReplyFn callback) + NMSerialWaitForReplyFn callback, + gpointer user_data) { NMSerialDevice *serial = NM_SERIAL_DEVICE (self); guint id = 0; if (nm_serial_device_send_command_string (serial, command)) - id = nm_serial_device_wait_for_reply (serial, timeout, responses, terminators, callback, NULL); + id = nm_serial_device_wait_for_reply (serial, timeout, responses, terminators, callback, user_data); if (id == 0) nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); @@ -163,7 +164,7 @@ dial_done (NMSerialDevice *device, } static void -do_dial (NMGsmDevice *device, guint cid) +real_do_dial (NMGsmDevice *device, guint cid) { NMSettingGsm *setting; char *command; @@ -185,7 +186,7 @@ do_dial (NMGsmDevice *device, guint cid) } else command = g_strconcat ("ATDT", setting->number, NULL); - modem_wait_for_reply (device, command, 60, responses, responses, dial_done); + modem_wait_for_reply (device, command, 60, responses, responses, dial_done, NULL); g_free (command); } @@ -196,7 +197,7 @@ set_apn_done (NMSerialDevice *device, { switch (reply_index) { case 0: - do_dial (NM_GSM_DEVICE (device), 1); + NM_GSM_DEVICE_GET_CLASS (device)->do_dial (NM_GSM_DEVICE (device), GPOINTER_TO_UINT (user_data)); break; default: nm_warning ("Setting APN failed"); @@ -216,15 +217,14 @@ set_apn (NMGsmDevice *device) guint cid = 1; setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM)); - if (!setting->apn) { /* APN not set, nothing to do */ - do_dial (device, 0); + NM_GSM_DEVICE_GET_CLASS (device)->do_dial (NM_GSM_DEVICE (device), 0); return; } command = g_strdup_printf ("AT+CGDCONT=%d, \"IP\", \"%s\"", cid, setting->apn); - modem_wait_for_reply (device, command, 3, responses, responses, set_apn_done); + modem_wait_for_reply (device, command, 3, responses, responses, set_apn_done, GUINT_TO_POINTER (cid)); g_free (command); } @@ -262,7 +262,7 @@ manual_registration (NMGsmDevice *device) setting = NM_SETTING_GSM (gsm_device_get_setting (device, NM_TYPE_SETTING_GSM)); command = g_strdup_printf ("AT+COPS=1,2,\"%s\"", setting->network_id); - modem_wait_for_reply (device, command, 30, responses, responses, manual_registration_done); + modem_wait_for_reply (device, command, 30, responses, responses, manual_registration_done, NULL); g_free (command); } @@ -344,7 +344,7 @@ automatic_registration (NMGsmDevice *device) char *responses[] = { "+CREG: 0,0", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,5", NULL }; char *terminators[] = { "OK", "ERROR", "ERR", NULL }; - modem_wait_for_reply (device, "AT+CREG?", 60, responses, terminators, automatic_registration_response); + modem_wait_for_reply (device, "AT+CREG?", 60, responses, terminators, automatic_registration_response, NULL); } static void @@ -393,7 +393,7 @@ init_modem_full (NMGsmDevice *device) * just breaks stuff since echo-ed commands are interpreted as replies. * rh #456770 */ - modem_wait_for_reply (device, "ATZ E0", 10, responses, responses, init_full_done); + modem_wait_for_reply (device, "ATZ E0", 10, responses, responses, init_full_done, NULL); } static void @@ -473,7 +473,7 @@ enter_pin (NMGsmDevice *device, gboolean retry) char *responses[] = { "OK", "ERROR", "ERR", NULL }; command = g_strdup_printf ("AT+CPIN=\"%s\"", secret); - modem_wait_for_reply (device, command, 3, responses, responses, enter_pin_done); + modem_wait_for_reply (device, command, 3, responses, responses, enter_pin_done, NULL); g_free (command); } else { nm_info ("(%s): GSM %s secret required", nm_device_get_iface (NM_DEVICE (device)), secret_name); @@ -527,7 +527,7 @@ check_pin (NMGsmDevice *self) char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL }; char *terminators[] = { "OK", "ERROR", "ERR", NULL }; - modem_wait_for_reply (self, "AT+CPIN?", 3, responses, terminators, check_pin_done); + modem_wait_for_reply (self, "AT+CPIN?", 3, responses, terminators, check_pin_done, NULL); } static void @@ -559,7 +559,7 @@ init_modem (NMSerialDevice *device, gpointer user_data) { char *responses[] = { "OK", "ERROR", "ERR", NULL }; - modem_wait_for_reply (NM_GSM_DEVICE (device), "AT E0", 10, responses, responses, init_done); + modem_wait_for_reply (NM_GSM_DEVICE (device), "AT E0", 10, responses, responses, init_done, NULL); } static NMActStageReturn @@ -911,6 +911,8 @@ nm_gsm_device_class_init (NMGsmDeviceClass *klass) device_class->connection_secrets_updated = real_connection_secrets_updated; device_class->deactivate_quickly = real_deactivate_quickly; + klass->do_dial = real_do_dial; + /* Properties */ g_object_class_install_property (object_class, PROP_MONITOR_IFACE, diff --git a/src/nm-gsm-device.h b/src/nm-gsm-device.h index 1cd122f7e7..5dbd1306d9 100644 --- a/src/nm-gsm-device.h +++ b/src/nm-gsm-device.h @@ -23,6 +23,8 @@ typedef struct { typedef struct { NMSerialDeviceClass parent; + void (*do_dial) (NMGsmDevice *device, guint cid); + /* Signals */ void (*properties_changed) (NMGsmDevice *device, GHashTable *properties); } NMGsmDeviceClass; diff --git a/src/nm-hal-manager.c b/src/nm-hal-manager.c index 9cf48bac16..7286a06894 100644 --- a/src/nm-hal-manager.c +++ b/src/nm-hal-manager.c @@ -14,6 +14,7 @@ #include "nm-device-wifi.h" #include "nm-device-ethernet.h" #include "nm-gsm-device.h" +#include "nm-hso-gsm-device.h" #include "nm-cdma-device.h" /* Killswitch poll frequency in seconds */ @@ -220,6 +221,50 @@ is_modem_device (NMHalManager *self, const char *udi) return is_modem; } +static char * +get_hso_netdev (LibHalContext *ctx, const char *udi) +{ + char *serial_parent, *netdev = NULL; + char **netdevs; + int num, i; + + /* Get the serial interface's originating device UDI, used to find the + * originating device's netdev. + */ + serial_parent = libhal_device_get_property_string (ctx, udi, "serial.originating_device", NULL); + if (!serial_parent) + serial_parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL); + if (!serial_parent) + return NULL; + + /* Look for the originating device's netdev */ + netdevs = libhal_find_device_by_capability (ctx, "net", &num, NULL); + for (i = 0; netdevs && !netdev && (i < num); i++) { + char *netdev_parent, *tmp; + + netdev_parent = libhal_device_get_property_string (ctx, netdevs[i], "net.originating_device", NULL); + if (!netdev_parent) + netdev_parent = libhal_device_get_property_string (ctx, netdevs[i], "net.physical_device", NULL); + if (!netdev_parent) + continue; + + if (!strcmp (netdev_parent, serial_parent)) { + /* We found it */ + tmp = libhal_device_get_property_string (ctx, netdevs[i], "net.interface", NULL); + if (tmp) { + netdev = g_strdup (tmp); + libhal_free_string (tmp); + } + } + + libhal_free_string (netdev_parent); + } + libhal_free_string_array (netdevs); + libhal_free_string (serial_parent); + + return netdev; +} + static GObject * modem_device_creator (NMHalManager *self, const char *udi, gboolean managed) { @@ -231,6 +276,7 @@ modem_device_creator (NMHalManager *self, const char *udi, gboolean managed) char **capabilities, **iter; gboolean type_gsm = FALSE; gboolean type_cdma = FALSE; + char *netdev = NULL; serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL); @@ -274,9 +320,16 @@ modem_device_creator (NMHalManager *self, const char *udi, gboolean managed) g_strfreev (capabilities); } - if (type_gsm) - device = (GObject *) nm_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); - else if (type_cdma) + /* Special handling of 'hso' cards (until punted out to a modem manager) */ + if (type_gsm && !strcmp (driver_name, "hso")) + netdev = get_hso_netdev (priv->hal_ctx, udi); + + if (type_gsm) { + if (netdev) + device = (GObject *) nm_hso_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, netdev, driver_name, managed); + else + device = (GObject *) nm_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); + } else if (type_cdma) device = (GObject *) nm_cdma_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); out: diff --git a/src/nm-hso-gsm-device.c b/src/nm-hso-gsm-device.c new file mode 100644 index 0000000000..0bb8a2fb71 --- /dev/null +++ b/src/nm-hso-gsm-device.c @@ -0,0 +1,542 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#include +#include +#include +#include +#include +#include + +#include "nm-device.h" +#include "nm-hso-gsm-device.h" +#include "nm-gsm-device.h" +#include "nm-device-interface.h" +#include "nm-device-private.h" +#include "nm-setting-gsm.h" +#include "nm-utils.h" +#include "nm-properties-changed-signal.h" +#include "nm-setting-connection.h" +#include "NetworkManagerSystem.h" + +G_DEFINE_TYPE (NMHsoGsmDevice, nm_hso_gsm_device, NM_TYPE_GSM_DEVICE) + +#define NM_HSO_GSM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_HSO_GSM_DEVICE, NMHsoGsmDevicePrivate)) + +extern const DBusGObjectInfo dbus_glib_nm_gsm_device_object_info; + +#define GSM_CID "gsm-cid" +#define HSO_SECRETS_TRIES "gsm-secrets-tries" + +typedef struct { + char *netdev_iface; + NMIP4Config *pending_ip4_config; +} NMHsoGsmDevicePrivate; + +enum { + PROP_0, + PROP_NETDEV_IFACE, + + LAST_PROP +}; + +NMHsoGsmDevice * +nm_hso_gsm_device_new (const char *udi, + const char *data_iface, + const char *monitor_iface, + const char *netdev_iface, + const char *driver, + gboolean managed) +{ + g_return_val_if_fail (udi != NULL, NULL); + g_return_val_if_fail (data_iface != NULL, NULL); + g_return_val_if_fail (driver != NULL, NULL); + g_return_val_if_fail (netdev_iface != NULL, NULL); + + return (NMHsoGsmDevice *) g_object_new (NM_TYPE_HSO_GSM_DEVICE, + NM_DEVICE_INTERFACE_UDI, udi, + NM_DEVICE_INTERFACE_IFACE, data_iface, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_GSM_DEVICE_MONITOR_IFACE, monitor_iface, + NM_HSO_GSM_DEVICE_NETDEV_IFACE, netdev_iface, + NM_DEVICE_INTERFACE_MANAGED, managed, + NULL); +} + +static void +modem_wait_for_reply (NMGsmDevice *self, + const char *command, + guint timeout, + char **responses, + char **terminators, + NMSerialWaitForReplyFn callback, + gpointer user_data) +{ + NMSerialDevice *serial = NM_SERIAL_DEVICE (self); + guint id = 0; + + if (nm_serial_device_send_command_string (serial, command)) + id = nm_serial_device_wait_for_reply (serial, timeout, responses, terminators, callback, user_data); + + if (id == 0) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); +} + +static void +modem_get_reply (NMGsmDevice *self, + const char *command, + guint timeout, + const char *terminators, + NMSerialGetReplyFn callback) +{ + NMSerialDevice *serial = NM_SERIAL_DEVICE (self); + guint id = 0; + + if (nm_serial_device_send_command_string (serial, command)) + id = nm_serial_device_get_reply (serial, timeout, terminators, callback, NULL); + + if (id == 0) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); +} + +static NMSetting * +gsm_device_get_setting (NMGsmDevice *device, GType setting_type) +{ + NMActRequest *req; + NMSetting *setting = NULL; + + req = nm_device_get_act_request (NM_DEVICE (device)); + if (req) { + NMConnection *connection; + + connection = nm_act_request_get_connection (req); + if (connection) + setting = nm_connection_get_setting (connection, setting_type); + } + + return setting; +} + +static void +hso_call_done (NMSerialDevice *device, + int reply_index, + gpointer user_data) +{ + gboolean success = FALSE; + + switch (reply_index) { + case 0: + nm_info ("Connected, Woo!"); + success = TRUE; + break; + default: + nm_warning ("Connect request failed"); + break; + } + + if (success) + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (device)); + else + nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED); +} + +static void +hso_clear_done (NMSerialDevice *device, + int reply_index, + gpointer user_data) +{ + char *responses[] = { "_OWANCALL: ", "ERROR", NULL }; + guint cid = GPOINTER_TO_UINT (user_data); + char *command; + + /* Try to connect */ + command = g_strdup_printf ("AT_OWANCALL=%d,1,1", cid); + modem_wait_for_reply (NM_GSM_DEVICE (device), command, 10, responses, responses, hso_call_done, NULL); + g_free (command); +} + +static void +hso_auth_done (NMSerialDevice *device, + int reply_index, + gpointer user_data) +{ + gboolean success = FALSE; + char *responses[] = { "_OWANCALL: ", "ERROR", "NO CARRIER", NULL }; + guint cid = GPOINTER_TO_UINT (user_data); + char *command; + + switch (reply_index) { + case 0: + nm_info ("Authentication successful!"); + success = TRUE; + break; + default: + nm_warning ("Authentication failed"); + break; + } + + if (!success) { + nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED); + return; + } + + /* Kill any existing connection */ + command = g_strdup_printf ("AT_OWANCALL=%d,0,1", cid); + modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, responses, hso_clear_done, GUINT_TO_POINTER (cid)); + g_free (command); +} + +static void +do_hso_auth (NMHsoGsmDevice *device) +{ + NMSettingGsm *s_gsm; + NMActRequest *req; + char *responses[] = { "OK", "ERROR", NULL }; + char *command; + guint cid; + + req = nm_device_get_act_request (NM_DEVICE (device)); + g_assert (req); + + cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); + + s_gsm = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM)); + + command = g_strdup_printf ("AT$QCPDPP=%d,1,\"%s\",\"%s\"", + cid, + s_gsm->password ? s_gsm->password : "", + s_gsm->username ? s_gsm->username : ""); + modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, responses, hso_auth_done, GUINT_TO_POINTER (cid)); + g_free (command); +} + +static NMActStageReturn +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMActRequest *req; + 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) { + do_hso_auth (NM_HSO_GSM_DEVICE (device)); + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + 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), HSO_SECRETS_TRIES)); + nm_act_request_request_connection_secrets (req, + setting_name, + tries ? TRUE : FALSE, + SECRETS_CALLER_HSO_GSM, + hint1, + hint2); + g_object_set_data (G_OBJECT (connection), HSO_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); + + if (hints) + g_ptr_array_free (hints, TRUE); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static void +real_do_dial (NMGsmDevice *device, guint cid) +{ + NMActRequest *req; + + req = nm_device_get_act_request (NM_DEVICE (device)); + g_assert (req); + g_object_set_data (G_OBJECT (req), GSM_CID, GUINT_TO_POINTER (cid)); + + nm_device_activate_schedule_stage2_device_config (NM_DEVICE (device)); +} + +#define OWANDATA_TAG "_OWANDATA: " + +static void +hso_ip4_config_done (NMSerialDevice *device, + const char *response, + gpointer user_data) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); + NMActRequest *req; + char **items, **iter; + guint cid, i; + NMSettingIP4Address addr = { 0, 32, 0 }; + guint32 dns1 = 0, dns2 = 0; + + if (!response || strncmp (response, OWANDATA_TAG, strlen (OWANDATA_TAG))) { + nm_device_activate_schedule_stage4_ip_config_timeout (NM_DEVICE (device)); + return; + } + + req = nm_device_get_act_request (NM_DEVICE (device)); + g_assert (req); + cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); + + items = g_strsplit (response + strlen (OWANDATA_TAG), ", ", 0); + for (iter = items, i = 0; *iter; iter++, i++) { + if (i == 0) { /* CID */ + long int tmp; + + errno = 0; + tmp = strtol (*iter, NULL, 10); + if (errno != 0 || tmp < 0 || (guint) tmp != cid) { + nm_warning ("%s: unknown CID in OWANDATA response (got %d, expected %d)", + nm_device_get_iface (NM_DEVICE (device)), + (guint) tmp, cid); + goto out; + } + } else if (i == 1) { /* IP address */ + if (inet_pton (AF_INET, *iter, &(addr.address)) <= 0) + addr.address = 0; + } else if (i == 3) { /* DNS 1 */ + if (inet_pton (AF_INET, *iter, &dns1) <= 0) + dns1 = 0; + } else if (i == 4) { /* DNS 2 */ + if (inet_pton (AF_INET, *iter, &dns2) <= 0) + dns2 = 0; + } + } + +out: + g_strfreev (items); + + if (addr.address) { + priv->pending_ip4_config = nm_ip4_config_new (); + + nm_ip4_config_add_address (priv->pending_ip4_config, &addr); + + if (dns1) + nm_ip4_config_add_nameserver (priv->pending_ip4_config, dns1); + if (dns2) + nm_ip4_config_add_nameserver (priv->pending_ip4_config, dns2); + + nm_device_activate_schedule_stage4_ip_config_get (NM_DEVICE (device)); + } else { + nm_device_state_changed (NM_DEVICE (device), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } +} + +static NMActStageReturn +real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason) +{ + const char terminators[] = { '\r', '\n', '\0' }; + NMActRequest *req; + char *command; + gint cid; + + req = nm_device_get_act_request (device); + g_assert (req); + + cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); + command = g_strdup_printf ("AT_OWANDATA=%d", cid); + modem_get_reply (NM_GSM_DEVICE (device), command, 5, terminators, hso_ip4_config_done); + g_free (command); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static NMActStageReturn +real_act_stage4_get_ip4_config (NMDevice *device, + NMIP4Config **config, + NMDeviceStateReason *reason) +{ + NMHsoGsmDevice *self = NM_HSO_GSM_DEVICE (device); + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (self); + + g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); + + nm_device_set_ip_iface (device, priv->netdev_iface); + if (!nm_device_hw_bring_up (device, TRUE)) + return NM_ACT_STAGE_RETURN_FAILURE; + + *config = priv->pending_ip4_config; + priv->pending_ip4_config = NULL; + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +real_connection_secrets_updated (NMDevice *device, + NMConnection *connection, + GSList *updated_settings, + RequestSecretsCaller caller) +{ + g_return_if_fail (caller == SECRETS_CALLER_HSO_GSM); + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); + + nm_device_activate_schedule_stage2_device_config (device); +} + +static void +real_deactivate_quickly (NMDevice *device) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); + + if (priv->pending_ip4_config) { + g_object_unref (priv->pending_ip4_config); + priv->pending_ip4_config = NULL; + } + + if (NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly) + NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly (device); +} + +static void +real_deactivate (NMDevice *device) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); + + if (priv->netdev_iface) { + nm_system_device_flush_ip4_routes_with_iface (priv->netdev_iface); + nm_system_device_flush_ip4_addresses_with_iface (priv->netdev_iface); + nm_system_device_set_up_down_with_iface (priv->netdev_iface, FALSE); + } + + if (NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate) + NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate (device); +} + +static gboolean +real_hw_is_up (NMDevice *device) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + + if ( priv->pending_ip4_config + || (state == NM_DEVICE_STATE_IP_CONFIG) + || (state == NM_DEVICE_STATE_ACTIVATED)) + return nm_system_device_is_up_with_iface (priv->netdev_iface); + + return TRUE; +} + +static gboolean +real_hw_bring_up (NMDevice *device) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); + NMDeviceState state; + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); + + if ( priv->pending_ip4_config + || (state == NM_DEVICE_STATE_IP_CONFIG) + || (state == NM_DEVICE_STATE_ACTIVATED)) + return nm_system_device_set_up_down_with_iface (priv->netdev_iface, TRUE); + + return TRUE; +} + +static void +nm_hso_gsm_device_init (NMHsoGsmDevice *self) +{ +} + +static GObject* +constructor (GType type, + guint n_params, + GObjectConstructParam *params) +{ + return G_OBJECT_CLASS (nm_hso_gsm_device_parent_class)->constructor (type, n_params, params); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NETDEV_IFACE: + /* Construct only */ + priv->netdev_iface = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_NETDEV_IFACE: + g_value_set_string (value, priv->netdev_iface); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (object); + + g_free (priv->netdev_iface); + + G_OBJECT_CLASS (nm_hso_gsm_device_parent_class)->finalize (object); +} + +static void +nm_hso_gsm_device_class_init (NMHsoGsmDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + NMGsmDeviceClass *gsm_class = NM_GSM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMHsoGsmDevicePrivate)); + + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->finalize = finalize; + + device_class->act_stage2_config = real_act_stage2_config; + device_class->act_stage3_ip_config_start = real_act_stage3_ip_config_start; + device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; + device_class->connection_secrets_updated = real_connection_secrets_updated; + device_class->deactivate_quickly = real_deactivate_quickly; + device_class->deactivate = real_deactivate; + device_class->hw_is_up = real_hw_is_up; + device_class->hw_bring_up = real_hw_bring_up; + + gsm_class->do_dial = real_do_dial; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_NETDEV_IFACE, + g_param_spec_string (NM_HSO_GSM_DEVICE_NETDEV_IFACE, + "Network interface", + "Network interface", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_gsm_device_object_info); +} diff --git a/src/nm-hso-gsm-device.h b/src/nm-hso-gsm-device.h new file mode 100644 index 0000000000..a7498c8394 --- /dev/null +++ b/src/nm-hso-gsm-device.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#ifndef NM_HSO_GSM_DEVICE_H +#define NM_HSO_GSM_DEVICE_H + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_HSO_GSM_DEVICE (nm_hso_gsm_device_get_type ()) +#define NM_HSO_GSM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HSO_GSM_DEVICE, NMHsoGsmDevice)) +#define NM_HSO_GSM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_HSO_GSM_DEVICE, NMHsoGsmDeviceClass)) +#define NM_IS_HSO_GSM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HSO_GSM_DEVICE)) +#define NM_IS_HSO_GSM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_HSO_GSM_DEVICE)) +#define NM_HSO_GSM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_HSO_GSM_DEVICE, NMHsoGsmDeviceClass)) + +#define NM_HSO_GSM_DEVICE_NETDEV_IFACE "netdev-iface" + +typedef struct { + NMGsmDevice parent; +} NMHsoGsmDevice; + +typedef struct { + NMGsmDeviceClass parent; +} NMHsoGsmDeviceClass; + +GType nm_hso_gsm_device_get_type (void); + +NMHsoGsmDevice *nm_hso_gsm_device_new (const char *udi, + const char *data_iface, + const char *monitor_iface, + const char *netdev_iface, + const char *driver, + gboolean managed); + +G_END_DECLS + +#endif /* NM_HSO_GSM_DEVICE_H */ diff --git a/src/nm-serial-device.c b/src/nm-serial-device.c index db8dc7be60..127b6bb11d 100644 --- a/src/nm-serial-device.c +++ b/src/nm-serial-device.c @@ -21,7 +21,7 @@ #include "nm-utils.h" #include "nm-serial-device-glue.h" -/* #define NM_DEBUG_SERIAL 1 */ +#define NM_DEBUG_SERIAL 1 #define SERIAL_BUF_SIZE 2048