Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
NetworkManager
NetworkManager-r4359-use-modem-manager.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File NetworkManager-r4359-use-modem-manager.patch of Package NetworkManager
diff --git a/configure.in b/configure.in index 8f6f425..921e0bf 100644 --- a/configure.in +++ b/configure.in @@ -488,6 +488,7 @@ src/dhcp-manager/Makefile src/supplicant-manager/Makefile src/ppp-manager/Makefile src/dnsmasq-manager/Makefile +src/modem-manager/Makefile src/backends/Makefile libnm-util/libnm-util.pc libnm-util/Makefile diff --git a/introspection/nm-device-cdma.xml b/introspection/nm-device-cdma.xml index 2b43f8f..22a612b 100644 --- a/introspection/nm-device-cdma.xml +++ b/introspection/nm-device-cdma.xml @@ -2,14 +2,5 @@ <node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <interface name="org.freedesktop.NetworkManager.Device.Cdma"> - - <signal name="PropertiesChanged"> - <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> - <tp:docstring> - A dictionary mapping property names to variant boxed values - </tp:docstring> - </arg> - </signal> - </interface> </node> diff --git a/introspection/nm-device-gsm.xml b/introspection/nm-device-gsm.xml index 650d656..0bf7b08 100644 --- a/introspection/nm-device-gsm.xml +++ b/introspection/nm-device-gsm.xml @@ -2,14 +2,5 @@ <node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <interface name="org.freedesktop.NetworkManager.Device.Gsm"> - - <signal name="PropertiesChanged"> - <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> - <tp:docstring> - A dictionary mapping property names to variant boxed values - </tp:docstring> - </arg> - </signal> - </interface> </node> diff --git a/src/Makefile.am b/src/Makefile.am index 3c4ce75..3f24eb5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,8 @@ SUBDIRS= \ supplicant-manager \ ppp-manager \ backends \ - dnsmasq-manager + dnsmasq-manager \ + modem-manager INCLUDES = -I${top_srcdir} \ -I${top_srcdir}/include \ @@ -15,6 +16,7 @@ INCLUDES = -I${top_srcdir} \ -I${top_srcdir}/src/dhcp-manager \ -I${top_srcdir}/src/supplicant-manager \ -I${top_srcdir}/src/dnsmasq-manager \ + -I${top_srcdir}/src/modem-manager \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/callouts @@ -59,14 +61,6 @@ NetworkManager_SOURCES = \ nm-activation-request.h \ nm-properties-changed-signal.c \ nm-properties-changed-signal.h \ - nm-serial-device.c \ - nm-serial-device.h \ - nm-gsm-device.c \ - 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 \ @@ -89,15 +83,6 @@ nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml dbus-binding-tool --prefix=nm_device_wifi --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=$@ $< - -nm-cdma-device-glue.h: $(top_srcdir)/introspection/nm-device-cdma.xml - dbus-binding-tool --prefix=nm_cdma_device --mode=glib-server --output=$@ $< - -nm-gsm-device-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml - dbus-binding-tool --prefix=nm_gsm_device --mode=glib-server --output=$@ $< - nm-ip4-config-glue.h: $(top_srcdir)/introspection/nm-ip4-config.xml dbus-binding-tool --prefix=nm_ip4_config --mode=glib-server --output=$@ $< @@ -113,9 +98,6 @@ BUILT_SOURCES = \ nm-device-interface-glue.h \ nm-device-ethernet-glue.h \ nm-device-wifi-glue.h \ - nm-serial-device-glue.h \ - nm-cdma-device-glue.h \ - nm-gsm-device-glue.h \ nm-ip4-config-glue.h \ nm-active-connection-glue.h \ nm-dhcp4-config-glue.h @@ -150,6 +132,7 @@ NetworkManager_LDADD = \ ./supplicant-manager/libsupplicant-manager.la \ ./dnsmasq-manager/libdnsmasq-manager.la \ ./ppp-manager/libppp-manager.la \ + ./modem-manager/libmodem-manager.la \ ./backends/libnmbackend.la \ $(top_builddir)/libnm-util/libnm-util.la diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index de85d4c..a97103c 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -34,15 +34,13 @@ #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-ethernet.h" -#include "nm-hso-gsm-device.h" -#include "nm-gsm-device.h" -#include "nm-cdma-device.h" #include "nm-dbus-manager.h" #include "nm-setting-ip4-config.h" #include "nm-setting-connection.h" #include "NetworkManagerSystem.h" #include "nm-named-manager.h" #include "nm-vpn-manager.h" +#include "nm-gsm-modem-hso.h" typedef struct LookupThread LookupThread; @@ -235,7 +233,7 @@ get_best_device (NMManager *manager, NMActRequest **out_req) } /* 'hso' devices never get a gateway from the remote end */ - if (!can_default && !NM_IS_HSO_GSM_DEVICE (dev)) + if (!can_default && !NM_IS_GSM_MODEM_HSO (dev)) continue; prio = nm_device_get_priority (dev); diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am new file mode 100644 index 0000000..5331f65 --- /dev/null +++ b/src/modem-manager/Makefile.am @@ -0,0 +1,45 @@ +INCLUDES = \ + -I${top_srcdir}/src \ + -I${top_srcdir}/include \ + -I${top_srcdir}/libnm-util \ + -I${top_builddir}/marshallers + +noinst_LTLIBRARIES = libmodem-manager.la + +libmodem_manager_la_SOURCES = \ + nm-cdma-modem.c \ + nm-cdma-modem.h \ + nm-gsm-modem.c \ + nm-gsm-modem.h \ + nm-gsm-modem-hso.c \ + nm-gsm-modem-hso.h \ + nm-gsm-modem-mbm.c \ + nm-gsm-modem-mbm.h \ + nm-modem-device.c \ + nm-modem-device.h \ + nm-modem-manager.h \ + nm-modem-manager.c \ + nm-modem-types.h + +libmodem_manager_la_CPPFLAGS = \ + $(DBUS_CFLAGS) + +libmodem_manager_la_LIBADD = \ + $(DBUS_LIBS) \ + $(top_builddir)/marshallers/libmarshallers.la + +nm-cdma-device-glue.h: $(top_srcdir)/introspection/nm-device-cdma.xml + dbus-binding-tool --prefix=nm_cdma_device --mode=glib-server --output=$@ $< + +nm-gsm-device-glue.h: $(top_srcdir)/introspection/nm-device-gsm.xml + dbus-binding-tool --prefix=nm_gsm_device --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-cdma-device-glue.h \ + nm-gsm-device-glue.h \ + nm-serial-device-glue.h + +CLEANFILES = $(BUILT_SOURCES) diff --git a/src/modem-manager/nm-cdma-modem.c b/src/modem-manager/nm-cdma-modem.c new file mode 100644 index 0000000..85532c0 --- /dev/null +++ b/src/modem-manager/nm-cdma-modem.c @@ -0,0 +1,264 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include <string.h> + +#include "nm-cdma-modem.h" +#include "nm-modem-types.h" +#include "nm-device-interface.h" +#include "nm-device-private.h" +#include "nm-dbus-manager.h" +#include "nm-setting-connection.h" +#include "nm-setting-cdma.h" +#include "nm-utils.h" + +#include "nm-cdma-device-glue.h" + +G_DEFINE_TYPE (NMCdmaModem, nm_cdma_modem, NM_TYPE_MODEM_DEVICE) + +#define NM_CDMA_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CDMA_MODEM, NMCdmaModemPrivate)) + +enum { + MODEM_STATE_BEGIN, + MODEM_STATE_ENABLE, + MODEM_STATE_CONNECT +}; + +typedef struct { + int modem_state; +} NMCdmaModemPrivate; + +enum { + SIGNAL_QUALITY, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +NMDevice * +nm_cdma_modem_new (const char *path, + const char *data_device, + const char *driver) +{ + g_return_val_if_fail (path != 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_CDMA_MODEM, + NM_DEVICE_INTERFACE_UDI, path, + NM_DEVICE_INTERFACE_IFACE, data_device, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_MANAGED, TRUE, + NM_MODEM_DEVICE_PATH, path, + NULL); +} + +static NMSetting * +get_setting (NMCdmaModem *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 +state_machine (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMCdmaModem *modem = NM_CDMA_MODEM (user_data); + NMCdmaModemPrivate *priv = NM_CDMA_MODEM_GET_PRIVATE (modem); + NMSettingCdma *setting; + GError *error = NULL; + + setting = NM_SETTING_CDMA (get_setting (modem, NM_TYPE_SETTING_CDMA)); + + if (call_id) + dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); + + if (error) { + nm_warning ("CDMA modem connection failed: %s", error->message); + nm_device_state_changed (NM_DEVICE (modem), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + return; + } + + switch (priv->modem_state) { + case MODEM_STATE_BEGIN: + priv->modem_state = MODEM_STATE_ENABLE; + dbus_g_proxy_begin_call (nm_modem_device_get_proxy (NM_MODEM_DEVICE (modem), NULL), + "Enable", state_machine, + modem, NULL, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + break; + case MODEM_STATE_ENABLE: + priv->modem_state = MODEM_STATE_CONNECT; + dbus_g_proxy_begin_call (nm_modem_device_get_proxy (NM_MODEM_DEVICE (modem), NULL), + "Connect", state_machine, + modem, NULL, + G_TYPE_STRING, nm_setting_cdma_get_number (setting), + G_TYPE_INVALID); + break; + case MODEM_STATE_CONNECT: + nm_device_activate_schedule_stage2_device_config (NM_DEVICE (modem)); + break; + default: + nm_warning ("Invalid modem state %d", priv->modem_state); + nm_device_state_changed (NM_DEVICE (modem), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + break; + } +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMCdmaModemPrivate *priv = NM_CDMA_MODEM_GET_PRIVATE (device); + + priv->modem_state = MODEM_STATE_BEGIN; + state_machine (NULL, NULL, device); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static NMConnection * +real_get_best_auto_connection (NMDevice *dev, + GSList *connections, + char **specific_object) +{ + GSList *iter; + + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + NMSettingConnection *s_con; + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert (s_con); + + if (!nm_setting_connection_get_autoconnect (s_con)) + continue; + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_CDMA_SETTING_NAME)) + continue; + + return connection; + } + 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_device_get_ppp_manager (NM_MODEM_DEVICE (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 const char * +real_get_ppp_name (NMModemDevice *device, NMConnection *connection) +{ + NMSettingCdma *s_cdma; + + s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); + g_assert (s_cdma); + + return nm_setting_cdma_get_username (s_cdma); +} + +/*****************************************************************************/ + +static void +nm_cdma_modem_init (NMCdmaModem *self) +{ + nm_device_set_device_type (NM_DEVICE (self), NM_DEVICE_TYPE_CDMA); +} + +static void +nm_cdma_modem_class_init (NMCdmaModemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + NMModemDeviceClass *modem_class = NM_MODEM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMCdmaModemPrivate)); + + /* 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; + modem_class->get_ppp_name = real_get_ppp_name; + + /* Signals */ + signals[SIGNAL_QUALITY] = + g_signal_new ("signal-quality", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMCdmaModemClass, signal_quality), + 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_cdma_device_object_info); +} diff --git a/src/modem-manager/nm-cdma-modem.h b/src/modem-manager/nm-cdma-modem.h new file mode 100644 index 0000000..5dc3c14 --- /dev/null +++ b/src/modem-manager/nm-cdma-modem.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_CDMA_MODEM_H +#define NM_CDMA_MODEM_H + +#include <nm-modem-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_CDMA_MODEM (nm_cdma_modem_get_type ()) +#define NM_CDMA_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CDMA_MODEM, NMCdmaModem)) +#define NM_CDMA_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CDMA_MODEM, NMCdmaModemClass)) +#define NM_IS_CDMA_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CDMA_MODEM)) +#define NM_IS_CDMA_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CDMA_MODEM)) +#define NM_CDMA_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CDMA_MODEM, NMCdmaModemClass)) + +typedef struct { + NMModemDevice parent; +} NMCdmaModem; + +typedef struct { + NMModemDeviceClass parent; + + /* Signals */ + void (*signal_quality) (NMCdmaModem *modem, guint32 quality); +} NMCdmaModemClass; + +GType nm_cdma_modem_get_type (void); + +NMDevice *nm_cdma_modem_new (const char *path, + const char *data_device, + const char *driver); + +G_END_DECLS + +#endif /* NM_CDMA_MODEM_H */ diff --git a/src/modem-manager/nm-gsm-modem-hso.c b/src/modem-manager/nm-gsm-modem-hso.c new file mode 100644 index 0000000..15b79b6 --- /dev/null +++ b/src/modem-manager/nm-gsm-modem-hso.c @@ -0,0 +1,348 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include "nm-gsm-modem-hso.h" +#include "nm-device-private.h" +#include "nm-device-interface.h" +#include "NetworkManagerSystem.h" +#include "nm-setting-connection.h" +#include "nm-setting-gsm.h" +#include "nm-modem-types.h" +#include "nm-utils.h" + +G_DEFINE_TYPE (NMGsmModemHso, nm_gsm_modem_hso, NM_TYPE_GSM_MODEM) + +#define NM_GSM_MODEM_HSO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_GSM_MODEM_HSO, NMGsmModemHsoPrivate)) + +typedef struct { + char *netdev_iface; + NMIP4Config *pending_ip4_config; +} NMGsmModemHsoPrivate; + +#define HSO_SECRETS_TRIES "gsm-secrets-tries" + +static char * +get_network_device (NMDevice *device) +{ + char *result = NULL; + GError *error = NULL; + GValue value = { 0, }; + + if (!dbus_g_proxy_call (nm_modem_device_get_proxy (NM_MODEM_DEVICE (device), "org.freedesktop.DBus.Properties"), + "Get", &error, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM_GSM_HSO, + G_TYPE_STRING, "NetworkDevice", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + nm_warning ("Could not get HSO device's network interface: %s", error->message); + g_error_free (error); + } else { + if (G_VALUE_HOLDS_STRING (&value)) + result = g_value_dup_string (&value); + else + nm_warning ("Could not get HSO device's network interface: wrong type '%s'", + G_VALUE_TYPE_NAME (&value)); + + g_value_unset (&value); + } + + return result; +} + +NMDevice * +nm_gsm_modem_hso_new (const char *path, + const char *data_device, + const char *driver) +{ + NMDevice *device; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (data_device != NULL, NULL); + g_return_val_if_fail (driver != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_GSM_MODEM_HSO, + NM_DEVICE_INTERFACE_UDI, path, + NM_DEVICE_INTERFACE_IFACE, data_device, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_MANAGED, TRUE, + NM_MODEM_DEVICE_PATH, path, + NULL); + + if (device) { + NMGsmModemHsoPrivate *priv; + + priv = NM_GSM_MODEM_HSO_GET_PRIVATE (device); + priv->netdev_iface = get_network_device (device); + if (!priv->netdev_iface) { + g_object_unref (device); + device = NULL; + } + } + + return device; +} + +/*****************************************************************************/ + +static NMSetting * +get_setting (NMGsmModemHso *modem, GType setting_type) +{ + NMActRequest *req; + NMSetting *setting = NULL; + + req = nm_device_get_act_request (NM_DEVICE (modem)); + 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_auth_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)) + nm_device_activate_schedule_stage3_ip_config_start (device); + else { + nm_warning ("Authentication failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED); + } +} + +static void +do_hso_auth (NMGsmModemHso *device) +{ + NMSettingGsm *s_gsm; + const char *username; + const char *password; + + s_gsm = NM_SETTING_GSM (get_setting (device, NM_TYPE_SETTING_GSM)); + username = nm_setting_gsm_get_username (s_gsm); + password = nm_setting_gsm_get_password (s_gsm); + + dbus_g_proxy_begin_call (nm_modem_device_get_proxy (NM_MODEM_DEVICE (device), MM_DBUS_INTERFACE_MODEM_GSM_HSO), + "Authenticate", hso_auth_done, + device, NULL, + G_TYPE_STRING, username ? username : "", + G_TYPE_STRING, password ? password : "", + G_TYPE_INVALID); +} + +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_GSM_MODEM_HSO (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 +get_ip4_config_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + guint32 ip4_address; + GArray *dns_array; + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, + G_TYPE_UINT, &ip4_address, + DBUS_TYPE_G_UINT_ARRAY, &dns_array, + G_TYPE_INVALID)) { + + NMGsmModemHsoPrivate *priv = NM_GSM_MODEM_HSO_GET_PRIVATE (device); + NMIP4Address *addr; + int i; + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip4_address); + nm_ip4_address_set_prefix (addr, 32); + + priv->pending_ip4_config = nm_ip4_config_new (); + nm_ip4_config_take_address (priv->pending_ip4_config, addr); + + for (i = 0; i < dns_array->len; i++) + nm_ip4_config_add_nameserver (priv->pending_ip4_config, + g_array_index (dns_array, guint32, i)); + + nm_device_activate_schedule_stage4_ip_config_get (device); + } else { + nm_warning ("Retrieving IP4 configuration failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } +} + +static NMActStageReturn +real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason) +{ + dbus_g_proxy_begin_call (nm_modem_device_get_proxy (NM_MODEM_DEVICE (device), MM_DBUS_INTERFACE_MODEM_GSM_HSO), + "GetIP4Config", get_ip4_config_done, + device, NULL, + G_TYPE_INVALID); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static NMActStageReturn +real_act_stage4_get_ip4_config (NMDevice *device, + NMIP4Config **config, + NMDeviceStateReason *reason) +{ + NMGsmModemHso *self = NM_GSM_MODEM_HSO (device); + NMGsmModemHsoPrivate *priv = NM_GSM_MODEM_HSO_GET_PRIVATE (self); + gboolean no_firmware = FALSE; + + nm_device_set_ip_iface (device, priv->netdev_iface); + if (!nm_device_hw_bring_up (device, TRUE, &no_firmware)) { + if (no_firmware) + *reason = NM_DEVICE_STATE_REASON_FIRMWARE_MISSING; + else + *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; + 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_deactivate (NMDevice *device) +{ + NMGsmModemHsoPrivate *priv = NM_GSM_MODEM_HSO_GET_PRIVATE (device); + + if (priv->pending_ip4_config) { + g_object_unref (priv->pending_ip4_config); + priv->pending_ip4_config = NULL; + } + + 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, NULL); + } + nm_device_set_ip_iface (device, NULL); + + if (NM_DEVICE_CLASS (nm_gsm_modem_hso_parent_class)->deactivate) + NM_DEVICE_CLASS (nm_gsm_modem_hso_parent_class)->deactivate (device); +} + +static gboolean +real_hw_is_up (NMDevice *device) +{ + NMGsmModemHsoPrivate *priv = NM_GSM_MODEM_HSO_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, gboolean *no_firmware) +{ + NMGsmModemHsoPrivate *priv = NM_GSM_MODEM_HSO_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, no_firmware); + + return TRUE; +} + +static void +real_connect (NMModemDevice *modem, const char *number) +{ + nm_device_activate_schedule_stage2_device_config (NM_DEVICE (modem)); +} + +/*****************************************************************************/ + +static void +nm_gsm_modem_hso_init (NMGsmModemHso *self) +{ +} + +static void +finalize (GObject *object) +{ + NMGsmModemHsoPrivate *priv = NM_GSM_MODEM_HSO_GET_PRIVATE (object); + + g_free (priv->netdev_iface); + + G_OBJECT_CLASS (nm_gsm_modem_hso_parent_class)->finalize (object); +} + +static void +nm_gsm_modem_hso_class_init (NMGsmModemHsoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + NMModemDeviceClass *modem_class = NM_MODEM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMGsmModemHsoPrivate)); + + 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->deactivate = real_deactivate; + device_class->hw_is_up = real_hw_is_up; + device_class->hw_bring_up = real_hw_bring_up; + + modem_class->connect = real_connect; +} diff --git a/src/modem-manager/nm-gsm-modem-hso.h b/src/modem-manager/nm-gsm-modem-hso.h new file mode 100644 index 0000000..9b16b0b --- /dev/null +++ b/src/modem-manager/nm-gsm-modem-hso.h @@ -0,0 +1,33 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_GSM_MODEM_HSO_H +#define NM_GSM_MODEM_HSO_H + +#include <nm-gsm-modem.h> + +G_BEGIN_DECLS + +#define NM_TYPE_GSM_MODEM_HSO (nm_gsm_modem_hso_get_type ()) +#define NM_GSM_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GSM_MODEM_HSO, NMGsmModemHso)) +#define NM_GSM_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_GSM_MODEM_HSO, NMGsmModemHsoClass)) +#define NM_IS_GSM_MODEM_HSO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_GSM_MODEM_HSO)) +#define NM_IS_GSM_MODEM_HSO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_GSM_MODEM_HSO)) +#define NM_GSM_MODEM_HSO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_GSM_MODEM_HSO, NMGsmModemHsoClass)) + +typedef struct { + NMGsmModem parent; +} NMGsmModemHso; + +typedef struct { + NMGsmModemClass parent; +} NMGsmModemHsoClass; + +GType nm_gsm_modem_hso_get_type (void); + +NMDevice *nm_gsm_modem_hso_new (const char *path, + const char *data_device, + const char *driver); + +G_END_DECLS + +#endif /* NM_GSM_MODEM_HSO_H */ diff --git a/src/modem-manager/nm-gsm-modem-mbm.c b/src/modem-manager/nm-gsm-modem-mbm.c new file mode 100644 index 0000000..37ca844 --- /dev/null +++ b/src/modem-manager/nm-gsm-modem-mbm.c @@ -0,0 +1,261 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* + Additions to NetworkManager, network-manager-applet and modemmanager + for supporting Ericsson modules like F3507g. + + Author: Per Hallsmark <per@hallsmark.se> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "nm-gsm-modem-mbm.h" +#include "nm-device-private.h" +#include "nm-device-interface.h" +#include "NetworkManagerSystem.h" +#include "nm-setting-connection.h" +#include "nm-setting-gsm.h" +#include "nm-modem-types.h" +#include "nm-utils.h" + +G_DEFINE_TYPE (NMGsmModemMbm, nm_gsm_modem_mbm, NM_TYPE_GSM_MODEM) + +#define NM_GSM_MODEM_MBM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_GSM_MODEM_MBM, NMGsmModemMbmPrivate)) + +typedef struct { + char *netdev_iface; + NMIP4Config *pending_ip4_config; +} NMGsmModemMbmPrivate; + +#define MBM_SECRETS_TRIES "gsm-secrets-tries" + +static char * +get_network_device (NMDevice *device) +{ + char *result = NULL; + GError *error = NULL; + GValue value = { 0, }; + + if (!dbus_g_proxy_call (nm_modem_device_get_proxy (NM_MODEM_DEVICE (device), "org.freedesktop.DBus.Properties"), + "Get", &error, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM_GSM_MBM, + G_TYPE_STRING, "NetworkDevice", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + nm_warning ("Could not get MBM device's network interface: %s", error->message); + g_error_free (error); + } else { + if (G_VALUE_HOLDS_STRING (&value)) + result = g_value_dup_string (&value); + else + nm_warning ("Could not get MBM device's network interface: wrong type '%s'", + G_VALUE_TYPE_NAME (&value)); + + g_value_unset (&value); + } + + return result; +} + +NMDevice * +nm_gsm_modem_mbm_new (const char *path, + const char *data_device, + const char *driver) +{ + NMDevice *device; + + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (data_device != NULL, NULL); + g_return_val_if_fail (driver != NULL, NULL); + + device = (NMDevice *) g_object_new (NM_TYPE_GSM_MODEM_MBM, + NM_DEVICE_INTERFACE_UDI, path, + NM_DEVICE_INTERFACE_IFACE, data_device, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_MANAGED, TRUE, + NM_MODEM_DEVICE_PATH, path, + NULL); + + if (device) { + NMGsmModemMbmPrivate *priv; + + priv = NM_GSM_MODEM_MBM_GET_PRIVATE (device); + priv->netdev_iface = get_network_device (device); + if (!priv->netdev_iface) { + g_object_unref (device); + device = NULL; + } + } + + return device; +} + +/*****************************************************************************/ + +#if 0 +static NMSetting * +get_setting (NMGsmModemMbm *modem, GType setting_type) +{ + NMActRequest *req; + NMSetting *setting = NULL; + + req = nm_device_get_act_request (NM_DEVICE (modem)); + if (req) { + NMConnection *connection; + + connection = nm_act_request_get_connection (req); + if (connection) + setting = nm_connection_get_setting (connection, setting_type); + } + + return setting; +} +#endif + +#if 0 +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_mbm_auth (NM_GSM_MODEM_MBM (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), MBM_SECRETS_TRIES)); + nm_act_request_request_connection_secrets (req, + setting_name, + tries ? TRUE : FALSE, + SECRETS_CALLER_MBM_GSM, + hint1, + hint2); + g_object_set_data (G_OBJECT (connection), MBM_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); + + if (hints) + g_ptr_array_free (hints, TRUE); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} +#endif + +static void +real_deactivate (NMDevice *device) +{ + NMGsmModemMbmPrivate *priv = NM_GSM_MODEM_MBM_GET_PRIVATE (device); + + if (priv->pending_ip4_config) { + g_object_unref (priv->pending_ip4_config); + priv->pending_ip4_config = NULL; + } + + 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, NULL); + } + nm_device_set_ip_iface (device, NULL); + + if (NM_DEVICE_CLASS (nm_gsm_modem_mbm_parent_class)->deactivate) + NM_DEVICE_CLASS (nm_gsm_modem_mbm_parent_class)->deactivate (device); +} + +static gboolean +real_hw_is_up (NMDevice *device) +{ + NMGsmModemMbmPrivate *priv = NM_GSM_MODEM_MBM_GET_PRIVATE (device); + + if (priv->netdev_iface) + return nm_system_device_is_up_with_iface (priv->netdev_iface); + + return TRUE; +} + +static gboolean +real_hw_bring_up (NMDevice *device, gboolean *no_firmware) +{ + NMGsmModemMbmPrivate *priv = NM_GSM_MODEM_MBM_GET_PRIVATE (device); + + if (priv->netdev_iface) + return nm_system_device_set_up_down_with_iface (priv->netdev_iface, TRUE, no_firmware); + + return TRUE; +} + +static void +real_connect (NMModemDevice *modem, const char *number) +{ + nm_device_activate_schedule_stage2_device_config (NM_DEVICE (modem)); +} + +/*****************************************************************************/ + +static void +nm_gsm_modem_mbm_init (NMGsmModemMbm *self) +{ +} + +static void +finalize (GObject *object) +{ + NMGsmModemMbmPrivate *priv = NM_GSM_MODEM_MBM_GET_PRIVATE (object); + + g_free (priv->netdev_iface); + + G_OBJECT_CLASS (nm_gsm_modem_mbm_parent_class)->finalize (object); +} + +static void +nm_gsm_modem_mbm_class_init (NMGsmModemMbmClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + NMModemDeviceClass *modem_class = NM_MODEM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMGsmModemMbmPrivate)); + + object_class->finalize = finalize; + +#if 0 + device_class->act_stage2_config = real_act_stage2_config; +#endif + device_class->deactivate = real_deactivate; + device_class->hw_is_up = real_hw_is_up; + device_class->hw_bring_up = real_hw_bring_up; + + modem_class->connect = real_connect; +} diff --git a/src/modem-manager/nm-gsm-modem-mbm.h b/src/modem-manager/nm-gsm-modem-mbm.h new file mode 100644 index 0000000..1f49fda --- /dev/null +++ b/src/modem-manager/nm-gsm-modem-mbm.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* + Additions to NetworkManager, network-manager-applet and modemmanager + for supporting Ericsson modules like F3507g. + + Author: Per Hallsmark <per@hallsmark.se> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef NM_GSM_MODEM_MBM_H +#define NM_GSM_MODEM_MBM_H + +#include <nm-gsm-modem.h> + +G_BEGIN_DECLS + +#define NM_TYPE_GSM_MODEM_MBM (nm_gsm_modem_mbm_get_type ()) +#define NM_GSM_MODEM_MBM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GSM_MODEM_MBM, NMGsmModemMbm)) +#define NM_GSM_MODEM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_GSM_MODEM_MBM, NMGsmModemMbmClass)) +#define NM_IS_GSM_MODEM_MBM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_GSM_MODEM_MBM)) +#define NM_IS_GSM_MODEM_MBM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_GSM_MODEM_MBM)) +#define NM_GSM_MODEM_MBM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_GSM_MODEM_MBM, NMGsmModemMbmClass)) + +typedef struct { + NMGsmModem parent; +} NMGsmModemMbm; + +typedef struct { + NMGsmModemClass parent; +} NMGsmModemMbmClass; + +GType nm_gsm_modem_mbm_get_type (void); + +NMDevice *nm_gsm_modem_mbm_new (const char *path, const char *data_device, + const char *driver); + +G_END_DECLS + +#endif /* NM_GSM_MODEM_MBM_H */ diff --git a/src/modem-manager/nm-gsm-modem.c b/src/modem-manager/nm-gsm-modem.c new file mode 100644 index 0000000..047e76c --- /dev/null +++ b/src/modem-manager/nm-gsm-modem.c @@ -0,0 +1,354 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include <string.h> +#include "nm-gsm-modem.h" +#include "nm-device-private.h" +#include "nm-device-interface.h" +#include "nm-setting-connection.h" +#include "nm-setting-gsm.h" +#include "nm-modem-types.h" +#include "nm-utils.h" + +#include "nm-gsm-device-glue.h" + +G_DEFINE_TYPE (NMGsmModem, nm_gsm_modem, NM_TYPE_MODEM_DEVICE) + +#define NM_GSM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_GSM_MODEM, NMGsmModemPrivate)) + +enum { + MODEM_STATE_BEGIN, + MODEM_STATE_ENABLE, + MODEM_STATE_SET_PIN, + MODEM_STATE_SET_APN, + MODEM_STATE_SET_BAND, + MODEM_STATE_SET_NETWORK_MODE, + MODEM_STATE_REGISTER, + MODEM_STATE_FAILED, +}; + +typedef struct { + int modem_state; +} NMGsmModemPrivate; + +NMDevice * +nm_gsm_modem_new (const char *path, + const char *data_device, + const char *driver) +{ + g_return_val_if_fail (path != 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_GSM_MODEM, + NM_DEVICE_INTERFACE_UDI, path, + NM_DEVICE_INTERFACE_IFACE, data_device, + NM_DEVICE_INTERFACE_DRIVER, driver, + NM_DEVICE_INTERFACE_MANAGED, TRUE, + NM_MODEM_DEVICE_PATH, path, + NULL); +} + +static NMSetting * +get_setting (NMGsmModem *modem, GType setting_type) +{ + NMActRequest *req; + NMSetting *setting = NULL; + + req = nm_device_get_act_request (NM_DEVICE (modem)); + if (req) { + NMConnection *connection; + + connection = nm_act_request_get_connection (req); + if (connection) + setting = nm_connection_get_setting (connection, setting_type); + } + + return setting; +} + +#define get_proxy(dev,iface) (nm_modem_device_get_proxy(NM_MODEM_DEVICE (dev), iface)) + +static void +state_machine (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMGsmModem *modem = NM_GSM_MODEM (user_data); + NMGsmModemPrivate *priv = NM_GSM_MODEM_GET_PRIVATE (modem); + NMSettingGsm *setting; + const char *secret = NULL; + const char *secret_name = NULL; + const char *str; + GError *error = NULL; + int i; + gboolean retry_secret = FALSE; + + setting = NM_SETTING_GSM (get_setting (modem, NM_TYPE_SETTING_GSM)); + + if (call_id) + dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); + + if (error) { + g_debug ("%s", dbus_g_error_get_name (error)); + + if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) { + secret = nm_setting_gsm_get_pin (setting); + secret_name = NM_SETTING_GSM_PIN; + priv->modem_state = MODEM_STATE_SET_PIN; + } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PUK)) { + secret = nm_setting_gsm_get_puk (setting); + secret_name = NM_SETTING_GSM_PUK; + priv->modem_state = MODEM_STATE_SET_PIN; + } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) { + g_object_set (setting, NM_SETTING_GSM_PIN, NULL, NULL); + secret_name = NM_SETTING_GSM_PIN; + retry_secret = TRUE; + priv->modem_state = MODEM_STATE_SET_PIN; + } + + /* FIXME: Hacks to ignore failures of setting band and network mode for now + since only Huawei module supports it. Remove when ModemManager rules. + */ + else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED) && + (priv->modem_state == MODEM_STATE_SET_BAND || + priv->modem_state == MODEM_STATE_SET_NETWORK_MODE)) { + + nm_warning ("Modem does not support setting %s, ignoring", + priv->modem_state == MODEM_STATE_SET_BAND ? "band" : "network mode"); + } else { + priv->modem_state = MODEM_STATE_FAILED; + nm_warning ("GSM modem connection failed: %s", error->message); + } + + g_error_free (error); + } + + again: + + switch (priv->modem_state) { + case MODEM_STATE_BEGIN: + priv->modem_state = MODEM_STATE_ENABLE; + dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM), + "Enable", state_machine, + modem, NULL, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + break; + + case MODEM_STATE_SET_PIN: + if (secret) { + priv->modem_state = MODEM_STATE_ENABLE; + dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_CARD), + "SendPin", state_machine, + modem, NULL, + G_TYPE_STRING, secret, + G_TYPE_INVALID); + } else { + nm_device_state_changed (NM_DEVICE (modem), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + nm_act_request_request_connection_secrets (nm_device_get_act_request (NM_DEVICE (modem)), + NM_SETTING_GSM_SETTING_NAME, + retry_secret, + SECRETS_CALLER_GSM, + secret_name, + NULL); + + } + break; + + case MODEM_STATE_ENABLE: + priv->modem_state = MODEM_STATE_SET_APN; + str = nm_setting_gsm_get_apn (setting); + + if (str) + dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK), + "SetApn", state_machine, + modem, NULL, + G_TYPE_STRING, str, + G_TYPE_INVALID); + else + goto again; + + break; + case MODEM_STATE_SET_APN: + priv->modem_state = MODEM_STATE_SET_BAND; + i = nm_setting_gsm_get_band (setting); + + if (i) + dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK), + "SetBand", state_machine, + modem, NULL, + G_TYPE_UINT, (guint32) i, + G_TYPE_INVALID); + else + goto again; + + break; + + case MODEM_STATE_SET_BAND: + priv->modem_state = MODEM_STATE_SET_NETWORK_MODE; + i = nm_setting_gsm_get_network_type (setting); + + if (i) + dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK), + "SetNetworkMode", state_machine, + modem, NULL, + G_TYPE_UINT, (guint32) i, + G_TYPE_INVALID); + else + goto again; + + break; + + case MODEM_STATE_SET_NETWORK_MODE: + priv->modem_state = MODEM_STATE_REGISTER; + + str = nm_setting_gsm_get_network_id (setting); + dbus_g_proxy_begin_call_with_timeout (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK), + "Register", state_machine, + modem, NULL, 120000, + G_TYPE_STRING, str ? str : "", + G_TYPE_INVALID); + break; + + case MODEM_STATE_REGISTER: + nm_modem_device_connect (NM_MODEM_DEVICE (modem), nm_setting_gsm_get_number (setting)); + break; + case MODEM_STATE_FAILED: + default: + nm_device_state_changed (NM_DEVICE (modem), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + break; + } +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMGsmModemPrivate *priv = NM_GSM_MODEM_GET_PRIVATE (device); + + priv->modem_state = MODEM_STATE_BEGIN; + state_machine (NULL, NULL, device); + + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +static NMConnection * +real_get_best_auto_connection (NMDevice *dev, + GSList *connections, + char **specific_object) +{ + GSList *iter; + + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + NMSettingConnection *s_con; + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert (s_con); + + if (!nm_setting_connection_get_autoconnect (s_con)) + continue; + + if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_GSM_SETTING_NAME)) + continue; + + return connection; + } + 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_device_get_ppp_manager (NM_MODEM_DEVICE (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 const char * +real_get_ppp_name (NMModemDevice *device, NMConnection *connection) +{ + NMSettingGsm *s_gsm; + + s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM); + g_assert (s_gsm); + + return nm_setting_gsm_get_username (s_gsm); +} + +/*****************************************************************************/ + +static void +nm_gsm_modem_init (NMGsmModem *self) +{ + nm_device_set_device_type (NM_DEVICE (self), NM_DEVICE_TYPE_GSM); +} + +static void +nm_gsm_modem_class_init (NMGsmModemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + NMModemDeviceClass *modem_class = NM_MODEM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMGsmModemPrivate)); + + /* 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; + modem_class->get_ppp_name = real_get_ppp_name; + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_gsm_device_object_info); +} diff --git a/src/modem-manager/nm-gsm-modem.h b/src/modem-manager/nm-gsm-modem.h new file mode 100644 index 0000000..8df8265 --- /dev/null +++ b/src/modem-manager/nm-gsm-modem.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_GSM_MODEM_H +#define NM_GSM_MODEM_H + +#include <nm-modem-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_GSM_MODEM (nm_gsm_modem_get_type ()) +#define NM_GSM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GSM_MODEM, NMGsmModem)) +#define NM_GSM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_GSM_MODEM, NMGsmModemClass)) +#define NM_IS_GSM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_GSM_MODEM)) +#define NM_IS_GSM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_GSM_MODEM)) +#define NM_GSM_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_GSM_MODEM, NMGsmModemClass)) + +typedef struct { + NMModemDevice parent; +} NMGsmModem; + +typedef struct { + NMModemDeviceClass parent; + + /* Signals */ + void (*signal_quality) (NMGsmModem *modem, guint32 quality); +} NMGsmModemClass; + +GType nm_gsm_modem_get_type (void); + +NMDevice *nm_gsm_modem_new (const char *path, + const char *data_device, + const char *driver); + +G_END_DECLS + +#endif /* NM_GSM_MODEM_H */ diff --git a/src/modem-manager/nm-modem-device.c b/src/modem-manager/nm-modem-device.c new file mode 100644 index 0000000..1f49acc --- /dev/null +++ b/src/modem-manager/nm-modem-device.c @@ -0,0 +1,457 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include <string.h> +#include "nm-modem-device.h" +#include "nm-device-private.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" + +G_DEFINE_TYPE (NMModemDevice, nm_modem_device, NM_TYPE_DEVICE) + +#define NM_MODEM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_DEVICE, NMModemDevicePrivate)) + +enum { + PROP_0, + PROP_PATH, + + LAST_PROP +}; + +typedef struct { + NMDBusManager *dbus_mgr; + char *path; + DBusGProxy *proxy; + NMPPPManager *ppp_manager; + NMIP4Config *pending_ip4_config; + + guint state_to_disconnected_id; + + /* PPP stats */ + guint32 in_bytes; + guint32 out_bytes; +} NMModemDevicePrivate; + +enum { + PPP_STATS, + PROPERTIES_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +NMPPPManager * +nm_modem_device_get_ppp_manager (NMModemDevice *device) +{ + g_return_val_if_fail (NM_IS_MODEM_DEVICE (device), NULL); + + return NM_MODEM_DEVICE_GET_PRIVATE (device)->ppp_manager; +} + +DBusGProxy * +nm_modem_device_get_proxy (NMModemDevice *device, + const char *interface) +{ + + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (device); + const char *current_iface; + + g_return_val_if_fail (NM_IS_MODEM_DEVICE (device), NULL); + + /* Default to the default interface. */ + if (interface == NULL) + interface = MM_DBUS_INTERFACE_MODEM; + + current_iface = dbus_g_proxy_get_interface (priv->proxy); + if (!current_iface || strcmp (current_iface, interface)) + dbus_g_proxy_set_interface (priv->proxy, interface); + + return priv->proxy; +} + +void +nm_modem_device_connect (NMModemDevice *device, + const char *number) +{ + g_return_if_fail (NM_IS_MODEM_DEVICE (device)); + + NM_MODEM_DEVICE_GET_CLASS (device)->connect (device, number); +} + +const char * +nm_modem_device_get_ppp_name (NMModemDevice *device, + NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_MODEM_DEVICE (device), NULL); + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + if (NM_MODEM_DEVICE_GET_CLASS (device)->get_ppp_name) + return NM_MODEM_DEVICE_GET_CLASS (device)->get_ppp_name (device, connection); + + return NULL; +} + +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_NETWORK: + nm_device_state_changed (device, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); + break; + 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); + break; + case NM_PPP_STATUS_AUTHENTICATE: + nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); + break; + default: + break; + } +} + +static void +ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, + NMIP4Config *config, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + nm_device_set_ip_iface (device, iface); + NM_MODEM_DEVICE_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); + nm_device_activate_schedule_stage4_ip_config_get (device); +} + +static void +ppp_stats (NMPPPManager *ppp_manager, + guint32 in_bytes, + guint32 out_bytes, + gpointer user_data) +{ + NMModemDevice *device = NM_MODEM_DEVICE (user_data); + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (device); + + if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { + priv->in_bytes = in_bytes; + priv->out_bytes = out_bytes; + + g_signal_emit (device, signals[PPP_STATS], 0, in_bytes, out_bytes); + } +} + +static NMActStageReturn +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (device); + NMActRequest *req; + const char *ppp_name = NULL; + GError *err = NULL; + NMActStageReturn ret; + + req = nm_device_get_act_request (device); + g_assert (req); + + ppp_name = nm_modem_device_get_ppp_name (NM_MODEM_DEVICE (device), + 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_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 +real_act_stage4_get_ip4_config (NMDevice *device, + NMIP4Config **config, + NMDeviceStateReason *reason) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (device); + + *config = priv->pending_ip4_config; + priv->pending_ip4_config = NULL; + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +real_deactivate_quickly (NMDevice *device) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (device); + + nm_device_set_ip_iface (device, NULL); + + 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->ppp_manager) { + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + } + + dbus_g_proxy_call_no_reply (nm_modem_device_get_proxy (NM_MODEM_DEVICE (device), NULL), + "Enable", G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID); +} + +static guint32 +real_get_generic_capabilities (NMDevice *dev) +{ + return NM_DEVICE_CAP_NM_SUPPORTED; +} + + +static void +connect_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)) + nm_device_activate_schedule_stage2_device_config (device); + else { + nm_warning ("Connect failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED); + } +} + +static void +real_connect (NMModemDevice *modem, const char *number) +{ + dbus_g_proxy_begin_call_with_timeout (nm_modem_device_get_proxy (modem, MM_DBUS_INTERFACE_MODEM), + "Connect", connect_done, + modem, NULL, 60000, + G_TYPE_STRING, number ? number : "", + G_TYPE_INVALID); +} + +static gboolean +unavailable_to_disconnected (gpointer user_data) +{ + nm_device_state_changed (NM_DEVICE (user_data), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + return FALSE; +} + +static void +device_state_changed (NMDeviceInterface *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMModemDevice *self = NM_MODEM_DEVICE (user_data); + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (self); + + /* Remove any previous delayed transition to disconnected */ + if (priv->state_to_disconnected_id) { + g_source_remove (priv->state_to_disconnected_id); + priv->state_to_disconnected_id = 0; + } + + /* If transitioning to UNAVAILBLE and we have a carrier, transition to + * DISCONNECTED because the device is ready to use. Otherwise the carrier-on + * handler will handle the transition to DISCONNECTED when the carrier is detected. + */ + if (new_state == NM_DEVICE_STATE_UNAVAILABLE) + priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, user_data); + + /* Make sure we don't leave the serial device open */ + switch (new_state) { + case NM_DEVICE_STATE_NEED_AUTH: + if (priv->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_device_get_proxy (self, NULL), + "Disconnect", G_TYPE_INVALID); + break; + default: + break; + } +} + +/*****************************************************************************/ + +static void +nm_modem_device_init (NMModemDevice *self) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (self); + + priv->dbus_mgr = nm_dbus_manager_get (); +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMModemDevicePrivate *priv; + + object = G_OBJECT_CLASS (nm_modem_device_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_MODEM_DEVICE_GET_PRIVATE (object); + + if (!priv->path) { + g_warning ("DBus path not provided"); + goto err; + } + + 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: + g_object_unref (object); + return NULL; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + /* Construct only */ + priv->path = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (object); + + if (priv->state_to_disconnected_id) { + g_source_remove (priv->state_to_disconnected_id); + priv->state_to_disconnected_id = 0; + } + + if (priv->proxy) + g_object_unref (priv->proxy); + + g_object_unref (priv->dbus_mgr); + + G_OBJECT_CLASS (nm_modem_device_parent_class)->finalize (object); +} + +static void +nm_modem_device_class_init (NMModemDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemDevicePrivate)); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + device_class->get_generic_capabilities = real_get_generic_capabilities; + device_class->act_stage2_config = real_act_stage2_config; + device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; + device_class->deactivate_quickly = real_deactivate_quickly; + + klass->connect = real_connect; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_MODEM_DEVICE_PATH, + "DBus path", + "DBus path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* Signals */ + signals[PPP_STATS] = + g_signal_new ("ppp-stats", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemDeviceClass, 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 (NMModemDeviceClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_serial_device_object_info); +} diff --git a/src/modem-manager/nm-modem-device.h b/src/modem-manager/nm-modem-device.h new file mode 100644 index 0000000..fae6d74 --- /dev/null +++ b/src/modem-manager/nm-modem-device.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_MODEM_DEVICE_H +#define NM_MODEM_DEVICE_H + +#include <dbus/dbus-glib.h> +#include <nm-device.h> +#include "ppp-manager/nm-ppp-manager.h" + +G_BEGIN_DECLS + +#define NM_TYPE_MODEM_DEVICE (nm_modem_device_get_type ()) +#define NM_MODEM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_DEVICE, NMModemDevice)) +#define NM_MODEM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_DEVICE, NMModemDeviceClass)) +#define NM_IS_MODEM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_DEVICE)) +#define NM_IS_MODEM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_DEVICE)) +#define NM_MODEM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_DEVICE, NMModemDeviceClass)) + +#define NM_MODEM_DEVICE_PATH "path" + +typedef struct { + NMDevice parent; +} NMModemDevice; + +typedef struct { + NMDeviceClass parent; + + void (*connect) (NMModemDevice *device, + const char *number); + + const char *(*get_ppp_name) (NMModemDevice *device, + NMConnection *connection); + + /* Signals */ + void (*ppp_stats) (NMModemDevice *device, guint32 in_bytes, guint32 out_bytes); + void (*properties_changed) (NMModemDevice *device, GHashTable *properties); +} NMModemDeviceClass; + +GType nm_modem_device_get_type (void); + +/* Protected */ + +NMPPPManager *nm_modem_device_get_ppp_manager (NMModemDevice *device); +DBusGProxy *nm_modem_device_get_proxy (NMModemDevice *device, + const char *interface); + +void nm_modem_device_connect (NMModemDevice *device, + const char *number); + +const char *nm_modem_device_get_ppp_name (NMModemDevice *device, + NMConnection *connection); + +G_END_DECLS + +#endif /* NM_MODEM_DEVICE_H */ diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c new file mode 100644 index 0000000..be0ca7a --- /dev/null +++ b/src/modem-manager/nm-modem-manager.c @@ -0,0 +1,395 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include <string.h> +#include "nm-modem-manager.h" +#include "nm-modem-device.h" +#include "nm-gsm-modem.h" +#include "nm-gsm-modem-hso.h" +#include "nm-gsm-modem-mbm.h" +#include "nm-cdma-modem.h" +#include "nm-dbus-manager.h" +#include "nm-utils.h" +#include "nm-modem-types.h" + +#define MODEM_POKE_INTERVAL 120000 + +G_DEFINE_TYPE (NMModemManager, nm_modem_manager, G_TYPE_OBJECT) + +#define NM_MODEM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_MANAGER, NMModemManagerPrivate)) + +typedef struct { + NMDBusManager *dbus_mgr; + DBusGProxy *proxy; + GHashTable *modems; + gboolean disposed; + guint poke_id; +} NMModemManagerPrivate; + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +NMModemManager * +nm_modem_manager_get (void) +{ + static NMModemManager *singleton = NULL; + + if (!singleton) + singleton = NM_MODEM_MANAGER (g_object_new (NM_TYPE_MODEM_MANAGER, NULL)); + else + g_object_ref (singleton); + + g_assert (singleton); + return singleton; +} + +static gboolean +get_modem_properties (DBusGConnection *connection, + const char *path, + char **data_device, + char **driver, + guint32 *type) +{ + DBusGProxy *proxy; + GValue value = { 0 }; + GError *err = NULL; + + proxy = dbus_g_proxy_new_for_name (connection, + MM_DBUS_SERVICE, + path, + "org.freedesktop.DBus.Properties"); + + if (dbus_g_proxy_call_with_timeout (proxy, "Get", 15000, &err, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM, + G_TYPE_STRING, "Type", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + *type = g_value_get_uint (&value); + g_value_unset (&value); + } else { + g_warning ("Could not get device type: %s", err->message); + goto out; + } + + if (dbus_g_proxy_call_with_timeout (proxy, "Get", 15000, &err, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM, + G_TYPE_STRING, "DataDevice", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + *data_device = g_value_dup_string (&value); + g_value_unset (&value); + } else { + g_warning ("Could not get modem data device: %s", err->message); + goto out; + } + + if (dbus_g_proxy_call_with_timeout (proxy, "Get", 15000, &err, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM, + G_TYPE_STRING, "Driver", + G_TYPE_INVALID, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + *driver = g_value_dup_string (&value); + g_value_unset (&value); + } else { + g_warning ("Could not get modem driver: %s", err->message); + goto out; + } + + out: + if (err) + g_error_free (err); + + g_object_unref (proxy); + + return *data_device && *driver; +} + +static void +create_modem (NMModemManager *manager, const char *path) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (manager); + NMDevice *device; + char *data_device = NULL; + char *driver = NULL; + uint modem_type = MM_MODEM_TYPE_UNKNOWN; + + if (g_hash_table_lookup (priv->modems, path)) { + nm_warning ("Modem with path %s already exists, ignoring", path); + return; + } + + if (!get_modem_properties (nm_dbus_manager_get_connection (priv->dbus_mgr), path, + &data_device, &driver, &modem_type)) + return; + + if (modem_type == MM_MODEM_TYPE_UNKNOWN) { + nm_warning ("Modem with path %s has unknown type, ignoring", path); + return; + } + + if (!driver || !strlen (driver)) { + nm_warning ("Modem with path %s has unknown driver, ignoring", path); + return; + } + + if (!data_device || !strlen (data_device)) { + nm_warning ("Modem with path %s has unknown data device, ignoring", path); + return; + } + + if (modem_type == MM_MODEM_TYPE_GSM) { + if (!strcmp (driver, "hso")) + device = nm_gsm_modem_hso_new (path, data_device, driver); + else if (!strcmp (driver, "mbm")) + device = nm_gsm_modem_mbm_new (path, data_device, driver); + else + device = nm_gsm_modem_new (path, data_device, driver); + } else if (modem_type == MM_MODEM_TYPE_CDMA) + device = nm_cdma_modem_new (path, data_device, driver); + 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); + } +} + +static void +modem_added (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + create_modem (NM_MODEM_MANAGER (user_data), path); +} + +static void +modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (user_data); + NMModemDevice *modem; + + modem = (NMModemDevice *) g_hash_table_lookup (priv->modems, path); + if (modem) { + g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, modem); + g_hash_table_remove (priv->modems, path); + } +} + +static gboolean +poke_modem_cb (gpointer user_data) +{ + NMModemManager *self = NM_MODEM_MANAGER (user_data); + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + DBusGConnection *g_connection; + DBusGProxy *proxy; + + g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); + proxy = dbus_g_proxy_new_for_name (g_connection, + MM_DBUS_SERVICE, + MM_DBUS_PATH, + MM_DBUS_INTERFACE); + + nm_info ("Trying to start the modem-manager..."); + dbus_g_proxy_call_no_reply (proxy, "EnumerateDevices", G_TYPE_INVALID); + g_object_unref (proxy); + + return TRUE; +} + +static void +enumerate_devices_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer data) +{ + NMModemManager *manager = NM_MODEM_MANAGER (data); + GPtrArray *modems; + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &modems, + G_TYPE_INVALID)) { + nm_warning ("Could not get modem list: %s", error->message); + g_error_free (error); + } else { + int i; + + for (i = 0; i < modems->len; i++) { + char *path = (char *) g_ptr_array_index (modems, i); + + create_modem (manager, path); + g_free (path); + } + + g_ptr_array_free (modems, TRUE); + } +} + +static void +modem_manager_appeared (NMModemManager *self, gboolean enumerate_devices) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + if (priv->poke_id) { + g_source_remove (priv->poke_id); + priv->poke_id = 0; + } + + priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + MM_DBUS_SERVICE, MM_DBUS_PATH, MM_DBUS_INTERFACE); + + dbus_g_proxy_add_signal (priv->proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "DeviceAdded", + G_CALLBACK (modem_added), self, + NULL); + + dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved", + G_CALLBACK (modem_removed), self, + NULL); + + if (enumerate_devices) + dbus_g_proxy_begin_call (priv->proxy, "EnumerateDevices", enumerate_devices_done, self, NULL, G_TYPE_INVALID); +} + +static gboolean +remove_one_modem (gpointer key, gpointer value, gpointer user_data) +{ + g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, value); + + return TRUE; +} + +static void +modem_manager_disappeared (NMModemManager *self) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + g_hash_table_foreach_remove (priv->modems, remove_one_modem, self); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + /* Try to activate the modem-manager */ + poke_modem_cb (self); + priv->poke_id = g_timeout_add (MODEM_POKE_INTERVAL, poke_modem_cb, self); +} + +static void +nm_modem_manager_name_owner_changed (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + gboolean old_owner_good; + gboolean new_owner_good; + + /* Can't handle the signal if its not from the modem service */ + if (strcmp (MM_DBUS_SERVICE, name) != 0) + return; + + old_owner_good = (old_owner && strlen (old_owner)); + new_owner_good = (new_owner && strlen (new_owner)); + + if (!old_owner_good && new_owner_good) { + nm_info ("modem manager appeared"); + modem_manager_appeared (NM_MODEM_MANAGER (user_data), FALSE); + } else if (old_owner_good && !new_owner_good) { + nm_info ("modem manager disappeared"); + modem_manager_disappeared (NM_MODEM_MANAGER (user_data)); + } +} + +/*******************************************************/ + +static void +nm_modem_manager_init (NMModemManager *self) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + priv->dbus_mgr = nm_dbus_manager_get (); + + g_signal_connect (priv->dbus_mgr, "name-owner-changed", + G_CALLBACK (nm_modem_manager_name_owner_changed), + self); + + if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_DBUS_SERVICE)) + modem_manager_appeared (self, TRUE); + else + modem_manager_disappeared (self); +} + +static void +dispose (GObject *object) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (object); + + if (priv->disposed) + return; + + priv->disposed = TRUE; + + if (priv->poke_id) { + g_source_remove (priv->poke_id); + priv->poke_id = 0; + } + + g_hash_table_foreach_remove (priv->modems, remove_one_modem, object); + g_hash_table_destroy (priv->modems); + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } + + if (priv->dbus_mgr) { + g_object_unref (priv->dbus_mgr); + priv->dbus_mgr = NULL; + } + + /* Chain up to the parent class */ + G_OBJECT_CLASS (nm_modem_manager_parent_class)->dispose (object); +} + +static void +nm_modem_manager_class_init (NMModemManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMModemManagerPrivate)); + + object_class->dispose = dispose; + + /* signals */ + signals[DEVICE_ADDED] = + g_signal_new ("device-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemManagerClass, device_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + signals[DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMModemManagerClass, device_removed), + NULL, NULL, + g_cclosure_marshal_VOID__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 new file mode 100644 index 0000000..ec62f84 --- /dev/null +++ b/src/modem-manager/nm-modem-manager.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_MODEM_MANAGER_H +#define NM_MODEM_MANAGER_H + +#include <glib-object.h> +#include "nm-device.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)) +#define NM_MODEM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_MANAGER, NMModemManagerClass)) +#define NM_IS_MODEM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_MANAGER)) +#define NM_IS_MODEM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_MANAGER)) +#define NM_MODEM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_MANAGER, NMModemManagerClass)) + +typedef struct { + GObject parent; +} NMModemManager; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*device_added) (NMModemManager *manager, + NMDevice *device); + + void (*device_removed) (NMModemManager *manager, + NMDevice *device); +} NMModemManagerClass; + +GType nm_modem_manager_get_type (void); + +NMModemManager *nm_modem_manager_get (void); + +#endif /* NM_MODEM_MANAGER_H */ diff --git a/src/modem-manager/nm-modem-types.h b/src/modem-manager/nm-modem-types.h new file mode 100644 index 0000000..de1d2de --- /dev/null +++ b/src/modem-manager/nm-modem-types.h @@ -0,0 +1,90 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_MODEM_TYPES_H +#define NM_MODEM_TYPES_H + +#define MM_DBUS_SERVICE "org.freedesktop.ModemManager" +#define MM_DBUS_PATH "/org/freedesktop/ModemManager" +#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager" +#define MM_DBUS_INTERFACE_MODEM "org.freedesktop.ModemManager.Modem" +#define MM_DBUS_INTERFACE_MODEM_CDMA "org.freedesktop.ModemManager.Modem.Cdma" + +#define MM_DBUS_INTERFACE_MODEM_GSM_CARD "org.freedesktop.ModemManager.Modem.Gsm.Card" +#define MM_DBUS_INTERFACE_MODEM_GSM_NETWORK "org.freedesktop.ModemManager.Modem.Gsm.Network" +#define MM_DBUS_INTERFACE_MODEM_GSM_HSO "org.freedesktop.ModemManager.Modem.Gsm.Hso" +#define MM_DBUS_INTERFACE_MODEM_GSM_MBM "org.freedesktop.ModemManager.Modem.Gsm.Mbm" + +#define MM_MODEM_TYPE_UNKNOWN 0 +#define MM_MODEM_TYPE_GSM 1 +#define MM_MODEM_TYPE_CDMA 2 + +/* Errors */ + +#define MM_SERIAL_OPEN_FAILED MM_DBUS_INTERFACE_MODEM ".SerialOpenFailed" +#define MM_SERIAL_SEND_FAILED MM_DBUS_INTERFACE_MODEM ".SerialSendFailed" +#define MM_SERIAL_RESPONSE_TIMEOUT MM_DBUS_INTERFACE_MODEM ".SerialResponseTimeout" + +#define MM_MODEM_ERROR_GENERAL MM_DBUS_INTERFACE_MODEM ".General" +#define MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED MM_DBUS_INTERFACE_MODEM ".OperationNotSupported" + +#define MM_MODEM_CONNECT_ERROR_NO_CARRIER MM_DBUS_INTERFACE_MODEM ".NoCarrier" +#define MM_MODEM_CONNECT_ERROR_NO_DIALTONE MM_DBUS_INTERFACE_MODEM ".NoDialtone" +#define MM_MODEM_CONNECT_ERROR_BUSY MM_DBUS_INTERFACE_MODEM ".Busy" +#define MM_MODEM_CONNECT_ERROR_NO_ANSWER MM_DBUS_INTERFACE_MODEM ".NoAnswer" + +#define MM_MODEM_ERROR "org.freedesktop.ModemManager.Modem.Gsm" + +#define MM_MODEM_ERROR_PHONE_FAILURE MM_MODEM_ERROR ".PhoneFailure" +#define MM_MODEM_ERROR_NO_CONNECTION MM_MODEM_ERROR ".NoConnection" +#define MM_MODEM_ERROR_LINK_RESERVED MM_MODEM_ERROR ".LinkReserved" +#define MM_MODEM_ERROR_NOT_ALLOWED MM_MODEM_ERROR ".OperationNotAllowed" +#define MM_MODEM_ERROR_NOT_SUPPORTED MM_MODEM_ERROR ".OperationNotSupported" +#define MM_MODEM_ERROR_PH_SIM_PIN MM_MODEM_ERROR ".PhSimPinRequired" +#define MM_MODEM_ERROR_PH_FSIM_PIN MM_MODEM_ERROR ".PhFSimPinRequired" +#define MM_MODEM_ERROR_PH_FSIM_PUK MM_MODEM_ERROR ".PhFPukRequired" +#define MM_MODEM_ERROR_SIM_NOT_INSERTED MM_MODEM_ERROR ".SimNotInserted" +#define MM_MODEM_ERROR_SIM_PIN MM_MODEM_ERROR ".SimPinRequired" +#define MM_MODEM_ERROR_SIM_PUK MM_MODEM_ERROR ".SimPukRequired" +#define MM_MODEM_ERROR_SIM_FAILURE MM_MODEM_ERROR ".SimFailure" +#define MM_MODEM_ERROR_SIM_BUSY MM_MODEM_ERROR ".SimBusy" +#define MM_MODEM_ERROR_SIM_WRONG MM_MODEM_ERROR ".SimWrong" +#define MM_MODEM_ERROR_WRONG_PASSWORD MM_MODEM_ERROR ".IncorrectPassword" +#define MM_MODEM_ERROR_SIM_PIN2 MM_MODEM_ERROR ".SimPin2Required" +#define MM_MODEM_ERROR_SIM_PUK2 MM_MODEM_ERROR ".SimPuk2Required" +#define MM_MODEM_ERROR_MEMORY_FULL MM_MODEM_ERROR ".MemoryFull" +#define MM_MODEM_ERROR_INVALID_INDEX MM_MODEM_ERROR ".InvalidIndex" +#define MM_MODEM_ERROR_NOT_FOUND MM_MODEM_ERROR ".NotFound" +#define MM_MODEM_ERROR_MEMORY_FAILURE MM_MODEM_ERROR ".MemoryFailure" +#define MM_MODEM_ERROR_TEXT_TOO_LONG MM_MODEM_ERROR ".TextTooLong" +#define MM_MODEM_ERROR_INVALID_CHARS MM_MODEM_ERROR ".InvalidChars" +#define MM_MODEM_ERROR_DIAL_STRING_TOO_LONG MM_MODEM_ERROR ".DialStringTooLong" +#define MM_MODEM_ERROR_DIAL_STRING_INVALID MM_MODEM_ERROR ".InvalidDialString" +#define MM_MODEM_ERROR_NO_NETWORK MM_MODEM_ERROR ".NoNetwork" +#define MM_MODEM_ERROR_NETWORK_TIMEOUT MM_MODEM_ERROR ".NetworkTimeout" +#define MM_MODEM_ERROR_NETWORK_NOT_ALLOWED MM_MODEM_ERROR ".NetworkNotAllowed" +#define MM_MODEM_ERROR_NETWORK_PIN MM_MODEM_ERROR ".NetworkPinRequired" +#define MM_MODEM_ERROR_NETWORK_PUK MM_MODEM_ERROR ".NetworkPukRequired" +#define MM_MODEM_ERROR_NETWORK_SUBSET_PIN MM_MODEM_ERROR ".NetworkSubsetPinRequired" +#define MM_MODEM_ERROR_NETWORK_SUBSET_PUK MM_MODEM_ERROR ".NetworkSubsetPukRequired" +#define MM_MODEM_ERROR_SERVICE_PIN MM_MODEM_ERROR ".ServicePinRequired" +#define MM_MODEM_ERROR_SERVICE_PUK MM_MODEM_ERROR ".ServicePukRequired" +#define MM_MODEM_ERROR_CORP_PIN MM_MODEM_ERROR ".CorporatePinRequired" +#define MM_MODEM_ERROR_CORP_PUK MM_MODEM_ERROR ".CorporatePukRequired" +#define MM_MODEM_ERROR_HIDDEN_KEY MM_MODEM_ERROR ".HiddenKeyRequired" +#define MM_MODEM_ERROR_EAP_NOT_SUPPORTED MM_MODEM_ERROR ".EapMethodNotSupported" +#define MM_MODEM_ERROR_INCORRECT_PARAMS MM_MODEM_ERROR ".IncorrectParams" +#define MM_MODEM_ERROR_UNKNOWN MM_MODEM_ERROR ".Unknown" +#define MM_MODEM_ERROR_GPRS_ILLEGAL_MS MM_MODEM_ERROR ".GprsIllegalMs" +#define MM_MODEM_ERROR_GPRS_ILLEGAL_ME MM_MODEM_ERROR ".GprsIllegalMe" +#define MM_MODEM_ERROR_GPRS_SERVICE_NOT_ALLOWED MM_MODEM_ERROR ".GprsServiceNotAllowed" +#define MM_MODEM_ERROR_GPRS_PLMN_NOT_ALLOWED MM_MODEM_ERROR ".GprsPlmnNotAllowed" +#define MM_MODEM_ERROR_GPRS_LOCATION_NOT_ALLOWED MM_MODEM_ERROR ".GprsLocationNotAllowed" +#define MM_MODEM_ERROR_GPRS_ROAMING_NOT_ALLOWED MM_MODEM_ERROR ".GprsRoamingNotAllowed" +#define MM_MODEM_ERROR_GPRS_OPTION_NOT_SUPPORTED MM_MODEM_ERROR ".GprsOptionNotSupported" +#define MM_MODEM_ERROR_GPRS_NOT_SUBSCRIBED MM_MODEM_ERROR ".GprsNotSubscribed" +#define MM_MODEM_ERROR_GPRS_OUT_OF_ORDER MM_MODEM_ERROR ".GprsOutOfOrder" +#define MM_MODEM_ERROR_GPRS_PDP_AUTH_FAILURE MM_MODEM_ERROR ".GprsPdpAuthFailure" +#define MM_MODEM_ERROR_GPRS_UNKNOWN MM_MODEM_ERROR ".GprsUnspecified" +#define MM_MODEM_ERROR_GPRS_INVALID_CLASS MM_MODEM_ERROR ".GprsInvalidClass" + +#endif /* NM_MODEM_TYPES_H */ diff --git a/src/nm-cdma-device.c b/src/nm-cdma-device.c deleted file mode 100644 index c1c9b06..0000000 --- a/src/nm-cdma-device.c +++ /dev/null @@ -1,593 +0,0 @@ -/* -*- 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) 2008 Red Hat, Inc. - * Copyright (C) 2008 Novell, Inc. - */ - -#include <stdio.h> -#include <string.h> -#include "nm-cdma-device.h" -#include "nm-device-interface.h" -#include "nm-device-private.h" -#include "nm-setting-cdma.h" -#include "nm-utils.h" -#include "nm-properties-changed-signal.h" -#include "nm-cdma-device-glue.h" -#include "nm-setting-connection.h" - -G_DEFINE_TYPE (NMCdmaDevice, nm_cdma_device, NM_TYPE_SERIAL_DEVICE) - -#define NM_CDMA_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CDMA_DEVICE, NMCdmaDevicePrivate)) - -typedef struct { - char *monitor_iface; - NMSerialDevice *monitor_device; - - guint state_to_disconnected_id; -} NMCdmaDevicePrivate; - -enum { - PROP_0, - PROP_MONITOR_IFACE, - - LAST_PROP -}; - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - - -NMCdmaDevice * -nm_cdma_device_new (const char *udi, - const char *data_iface, - const char *monitor_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); - - return (NMCdmaDevice *) g_object_new (NM_TYPE_CDMA_DEVICE, - NM_DEVICE_INTERFACE_UDI, udi, - NM_DEVICE_INTERFACE_IFACE, data_iface, - NM_DEVICE_INTERFACE_DRIVER, driver, - NM_CDMA_DEVICE_MONITOR_IFACE, monitor_iface, - NM_DEVICE_INTERFACE_MANAGED, managed, - NULL); -} - -static NMSetting * -cdma_device_get_setting (NMCdmaDevice *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 -dial_done (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data) -{ - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_UNKNOWN; - gboolean success = FALSE; - - switch (reply_index) { - case 0: - nm_info ("Connected, Woo!"); - success = TRUE; - break; - case 1: - nm_info ("Busy"); - reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; - break; - case 2: - nm_warning ("No dial tone"); - reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; - break; - case 3: - nm_warning ("No carrier"); - reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; - break; - case -1: - nm_warning ("Dialing timed out"); - reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; - break; - default: - nm_warning ("Dialing failed"); - break; - } - - if (success) - nm_device_activate_schedule_stage2_device_config (NM_DEVICE (device)); - else - nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED, reason); -} - -static void -do_dial (NMSerialDevice *device) -{ - NMSettingCdma *setting; - char *command; - guint id = 0; - const char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL }; - - setting = NM_SETTING_CDMA (cdma_device_get_setting (NM_CDMA_DEVICE (device), NM_TYPE_SETTING_CDMA)); - - command = g_strconcat ("ATDT", nm_setting_cdma_get_number (setting), NULL); - if (nm_serial_device_send_command_string (device, command)) - id = nm_serial_device_wait_for_reply (device, 60, responses, responses, dial_done, NULL); - g_free (command); - - if (id == 0) - nm_device_state_changed (NM_DEVICE (device), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_UNKNOWN); -} - -static void -power_up_response (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data) -{ - /* Ignore errors */ - do_dial (device); -} - -static void -power_up (NMSerialDevice *device) -{ - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; - guint id = 0; - - /* Only works on Sierra cards */ - nm_info ("(%s): powering up...", nm_device_get_iface (NM_DEVICE (device))); - if (nm_serial_device_send_command_string (device, "at!pcstate=1")) - id = nm_serial_device_wait_for_reply (device, 10, responses, responses, power_up_response, NULL); - - /* Ignore errors */ - if (id == 0) - do_dial (device); -} - -static void -init_done (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data) -{ - switch (reply_index) { - case 0: - power_up (device); - break; - case -1: - nm_warning ("Modem initialization timed out"); - nm_device_state_changed (NM_DEVICE (device), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); - break; - default: - nm_warning ("Modem initialization failed"); - nm_device_state_changed (NM_DEVICE (device), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); - return; - } -} - -static void -init_modem (NMSerialDevice *device, gpointer user_data) -{ - guint id = 0; - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; - - if (nm_serial_device_send_command_string (device, "ATZ E0")) - id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL); - - if (id == 0) - nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); -} - -static NMActStageReturn -real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) -{ - NMSerialDevice *serial_device = NM_SERIAL_DEVICE (device); - NMSettingSerial *setting; - guint id; - - setting = NM_SETTING_SERIAL (cdma_device_get_setting (NM_CDMA_DEVICE (device), NM_TYPE_SETTING_SERIAL)); - - if (!nm_serial_device_open (serial_device, setting)) { - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - id = nm_serial_device_flash (serial_device, 100, init_modem, NULL); - if (!id) - *reason = NM_DEVICE_STATE_REASON_UNKNOWN; - - return id ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE; -} - -static NMConnection * -real_get_best_auto_connection (NMDevice *dev, - GSList *connections, - char **specific_object) -{ - GSList *iter; - - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); - NMSettingConnection *s_con; - - s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); - g_assert (s_con); - - if (!nm_setting_connection_get_autoconnect (s_con)) - continue; - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_CDMA_SETTING_NAME)) - continue; - - return connection; - } - return NULL; -} - -static guint32 -real_get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -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_serial_device_get_ppp_manager (NM_SERIAL_DEVICE (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 *cdma_username = nm_setting_cdma_get_username (s_cdma); - const char *cdma_password = nm_setting_cdma_get_password (s_cdma); - - nm_ppp_manager_update_secrets (ppp_manager, - nm_device_get_iface (dev), - cdma_username ? cdma_username : "", - cdma_password ? cdma_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 const char * -real_get_ppp_name (NMSerialDevice *device, NMActRequest *req) -{ - NMConnection *connection; - NMSettingCdma *s_cdma; - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA); - g_assert (s_cdma); - - return nm_setting_cdma_get_username (s_cdma); -} - -/*****************************************************************************/ -/* Monitor device handling */ - -static gboolean -monitor_device_got_data (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - gsize bytes_read; - char buf[4096]; - GIOStatus status; - - if (condition & G_IO_IN) { - do { - status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, NULL); - - if (bytes_read) { - buf[bytes_read] = '\0'; - /* Do nothing with the data for now */ - nm_debug ("Monitor got unhandled data: '%s'", buf); - } - } while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN); - } - - if (condition & G_IO_HUP || condition & G_IO_ERR) { - return FALSE; - } - - return TRUE; -} - -static gboolean -setup_monitor_device (NMCdmaDevice *device) -{ - NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (device); - GIOChannel *channel; - NMSettingSerial *setting; - - if (!priv->monitor_iface) { - nm_debug ("No monitoring udi provided"); - return FALSE; - } - - priv->monitor_device = g_object_new (NM_TYPE_SERIAL_DEVICE, - NM_DEVICE_INTERFACE_UDI, nm_device_get_udi (NM_DEVICE (device)), - NM_DEVICE_INTERFACE_IFACE, priv->monitor_iface, - NULL); - - if (!priv->monitor_device) { - nm_warning ("Creation of the monitoring device failed"); - return FALSE; - } - - setting = NM_SETTING_SERIAL (nm_setting_serial_new ()); - if (!nm_serial_device_open (priv->monitor_device, setting)) { - nm_warning ("Monitoring device open failed"); - g_object_unref (setting); - g_object_unref (priv->monitor_device); - return FALSE; - } - - g_object_unref (setting); - - channel = nm_serial_device_get_io_channel (priv->monitor_device); - g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP, - monitor_device_got_data, device); - - g_io_channel_unref (channel); - - return TRUE; -} - -/*****************************************************************************/ - -static void -nm_cdma_device_init (NMCdmaDevice *self) -{ - nm_device_set_device_type (NM_DEVICE (self), NM_DEVICE_TYPE_CDMA); -} - -static gboolean -unavailable_to_disconnected (gpointer user_data) -{ - nm_device_state_changed (NM_DEVICE (user_data), - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - return FALSE; -} - -static void -device_state_changed (NMDeviceInterface *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) -{ - NMCdmaDevice *self = NM_CDMA_DEVICE (user_data); - NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (self); - - /* Remove any previous delayed transition to disconnected */ - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - - /* If transitioning to UNAVAILBLE and we have a carrier, transition to - * DISCONNECTED because the device is ready to use. Otherwise the carrier-on - * handler will handle the transition to DISCONNECTED when the carrier is detected. - */ - if (new_state == NM_DEVICE_STATE_UNAVAILABLE) - priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self); - - /* Make sure we don't leave the serial device open */ - switch (new_state) { - case NM_DEVICE_STATE_UNMANAGED: - case NM_DEVICE_STATE_UNAVAILABLE: - case NM_DEVICE_STATE_FAILED: - case NM_DEVICE_STATE_DISCONNECTED: - nm_serial_device_close (NM_SERIAL_DEVICE (self)); - break; - default: - break; - } -} - -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - - object = G_OBJECT_CLASS (nm_cdma_device_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - /* FIXME: Make the monitor device not required for now */ - setup_monitor_device (NM_CDMA_DEVICE (object)); -#if 0 - if (!setup_monitor_device (NM_CDMA_DEVICE (object))) { - g_object_unref (object); - object = NULL; - } -#endif - - g_signal_connect (NM_DEVICE (object), "state-changed", - G_CALLBACK (device_state_changed), NM_CDMA_DEVICE (object)); - - return object; -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_MONITOR_IFACE: - /* Construct only */ - priv->monitor_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) -{ - NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_MONITOR_IFACE: - g_value_set_string (value, priv->monitor_iface); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -finalize (GObject *object) -{ - NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (object); - - if (priv->monitor_device) - g_object_unref (priv->monitor_device); - - g_free (priv->monitor_iface); - - if (priv->state_to_disconnected_id) { - g_source_remove (priv->state_to_disconnected_id); - priv->state_to_disconnected_id = 0; - } - - G_OBJECT_CLASS (nm_cdma_device_parent_class)->finalize (object); -} - -static void -nm_cdma_device_class_init (NMCdmaDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - NMSerialDeviceClass *serial_class = NM_SERIAL_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMCdmaDevicePrivate)); - - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - object_class->finalize = finalize; - - device_class->get_best_auto_connection = real_get_best_auto_connection; - device_class->get_generic_capabilities = real_get_generic_capabilities; - device_class->act_stage1_prepare = real_act_stage1_prepare; - device_class->connection_secrets_updated = real_connection_secrets_updated; - - serial_class->get_ppp_name = real_get_ppp_name; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_MONITOR_IFACE, - g_param_spec_string (NM_CDMA_DEVICE_MONITOR_IFACE, - "Monitoring interface", - "Monitoring interface", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); - - /* Signals */ - signals[PROPERTIES_CHANGED] = - nm_properties_changed_signal_new (object_class, - G_STRUCT_OFFSET (NMCdmaDeviceClass, properties_changed)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_cdma_device_object_info); -} diff --git a/src/nm-cdma-device.h b/src/nm-cdma-device.h deleted file mode 100644 index 50c44a3..0000000 --- a/src/nm-cdma-device.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- 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) 2008 Red Hat, Inc. - * Copyright (C) 2008 Novell, Inc. - */ - -#ifndef NM_CDMA_DEVICE_H -#define NM_CDMA_DEVICE_H - -#include <nm-serial-device.h> - -G_BEGIN_DECLS - -#define NM_TYPE_CDMA_DEVICE (nm_cdma_device_get_type ()) -#define NM_CDMA_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CDMA_DEVICE, NMCdmaDevice)) -#define NM_CDMA_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CDMA_DEVICE, NMCdmaDeviceClass)) -#define NM_IS_CDMA_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CDMA_DEVICE)) -#define NM_IS_CDMA_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CDMA_DEVICE)) -#define NM_CDMA_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CDMA_DEVICE, NMCdmaDeviceClass)) - -#define NM_CDMA_DEVICE_MONITOR_IFACE "monitor-iface" - -typedef struct { - NMSerialDevice parent; -} NMCdmaDevice; - -typedef struct { - NMSerialDeviceClass parent; - - /* Signals */ - void (*properties_changed) (NMCdmaDevice *device, GHashTable *properties); -} NMCdmaDeviceClass; - -GType nm_cdma_device_get_type (void); - -NMCdmaDevice *nm_cdma_device_new (const char *udi, - const char *data_iface, - const char *monitor_iface, - const char *driver, - gboolean managed); - -G_END_DECLS - -#endif /* NM_CDMA_DEVICE_H */ diff --git a/src/nm-hal-manager.c b/src/nm-hal-manager.c index 2a97e59..b1f97ff 100644 --- a/src/nm-hal-manager.c +++ b/src/nm-hal-manager.c @@ -32,9 +32,6 @@ #include "nm-utils.h" #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 */ #define RFKILL_POLL_FREQUENCY 6 @@ -219,145 +216,6 @@ wireless_device_creator (NMHalManager *self, const char *udi, gboolean managed) return device; } -/* Modem device creator */ - -static gboolean -is_modem_device (NMHalManager *self, const char *udi) -{ - NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); - gboolean is_modem = FALSE; - - if (libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) { - char *category; - - category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL); - if (category) { - is_modem = strcmp (category, "serial") == 0; - libhal_free_string (category); - } - } - - 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) -{ - NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); - char *serial_device; - char *parent_udi; - char *driver_name = NULL; - GObject *device = NULL; - 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); - - /* Get the driver */ - parent_udi = libhal_device_get_property_string (priv->hal_ctx, udi, "info.parent", NULL); - if (parent_udi) { - driver_name = libhal_device_get_property_string (priv->hal_ctx, parent_udi, "info.linux.driver", NULL); - libhal_free_string (parent_udi); - } - - if (!serial_device || !driver_name) - goto out; - - capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "modem.command_sets", NULL); - /* 'capabilites' may be NULL */ - for (iter = capabilities; iter && *iter; iter++) { - if (!strcmp (*iter, "GSM-07.07")) { - type_gsm = TRUE; - break; - } - if (!strcmp (*iter, "IS-707-A")) { - type_cdma = TRUE; - break; - } - } - g_strfreev (capabilities); - - /* Compatiblity with the pre-specification bits */ - if (!type_gsm && !type_cdma) { - capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "info.capabilities", NULL); - for (iter = capabilities; *iter; iter++) { - if (!strcmp (*iter, "gsm")) { - type_gsm = TRUE; - break; - } - if (!strcmp (*iter, "cdma")) { - type_cdma = TRUE; - break; - } - } - g_strfreev (capabilities); - } - - /* 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: - libhal_free_string (serial_device); - libhal_free_string (driver_name); - - return device; -} - static void register_built_in_creators (NMHalManager *self) { @@ -379,14 +237,6 @@ register_built_in_creators (NMHalManager *self) creator->is_device_fn = is_wireless_device; creator->creator_fn = wireless_device_creator; priv->device_creators = g_slist_append (priv->device_creators, creator); - - /* Modem */ - creator = g_slice_new0 (DeviceCreator); - creator->device_type_name = g_strdup ("Modem"); - creator->capability_str = g_strdup ("modem"); - creator->is_device_fn = is_modem_device; - creator->creator_fn = modem_device_creator; - priv->device_creators = g_slist_append (priv->device_creators, creator); } static void diff --git a/src/nm-hso-gsm-device.c b/src/nm-hso-gsm-device.c deleted file mode 100644 index 15032a3..0000000 --- a/src/nm-hso-gsm-device.c +++ /dev/null @@ -1,593 +0,0 @@ -/* -*- 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) 2008 Red Hat, Inc. - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <arpa/inet.h> -#include <dbus/dbus-glib.h> - -#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, - const char **responses, - const 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 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, - const char *reply, - 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, - const char *reply, - gpointer user_data) -{ - const 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, - const char *reply, - gpointer user_data) -{ - gboolean success = FALSE; - const 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; - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; - char *command; - const char *gsm_username; - const char *gsm_password; - 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)); - - gsm_username = nm_setting_gsm_get_username (s_gsm); - gsm_password = nm_setting_gsm_get_password (s_gsm); - - command = g_strdup_printf ("AT$QCPDPP=%d,1,\"%s\",\"%s\"", - cid, - gsm_password ? gsm_password : "", - gsm_username ? 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_response (NMSerialDevice *device, - int reply_index, - const char *response, - gpointer user_data) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - NMActRequest *req; - char **items, **iter; - guint cid, i; - guint32 dns1 = 0, dns2 = 0, ip4_address = 0; - - if ( (reply_index < 0) - || !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, &ip4_address) <= 0) - ip4_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 (ip4_address) { - NMIP4Address *addr; - - priv->pending_ip4_config = nm_ip4_config_new (); - - addr = nm_ip4_address_new (); - nm_ip4_address_set_address (addr, ip4_address); - nm_ip4_address_set_prefix (addr, 32); - - nm_ip4_config_take_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) -{ - NMActRequest *req; - char *command; - gint cid; - const char *responses[] = { "_OWANDATA: ", NULL }; - const char *terminators[] = { "OK", "ERROR", "ERR", NULL }; - - 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_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, terminators, hso_ip4_config_response, NULL); - 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); - gboolean no_firmware = FALSE; - - 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, &no_firmware)) { - if (no_firmware) - *reason = NM_DEVICE_STATE_REASON_FIRMWARE_MISSING; - else - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - 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 (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - - if (caller == SECRETS_CALLER_HSO_GSM) { /* HSO PPP auth */ - nm_device_activate_schedule_stage2_device_config (device); - return; - } - - /* Let parent handle other auth like PIN/PUK */ - NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->connection_secrets_updated (device, connection, updated_settings, caller); -} - -static void -real_deactivate_quickly (NMDevice *device) -{ - NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device); - NMActRequest *req; - guint cid; - char *command; - - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - - /* Don't leave the modem connected */ - req = nm_device_get_act_request (device); - if (req) { - cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID)); - if (cid) { - const char *responses[] = { "OK", "ERROR", "ERR", NULL }; - int reply; - - /* Disconnect and disable asynchonous notification to keep serial - * buffer empty after the OK. - */ - command = g_strdup_printf ("AT_OWANCALL=%d,0,0", cid); - nm_serial_device_send_command_string (NM_SERIAL_DEVICE (device), command); - reply = nm_serial_device_wait_reply_blocking (NM_SERIAL_DEVICE (device), 5, responses, responses); - g_free (command); - } - } - - 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, NULL); - } - nm_device_set_ip_iface (device, NULL); - - 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, gboolean *no_firmware) -{ - 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, no_firmware); - - 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 | NM_PROPERTY_PARAM_NO_EXPORT)); - - 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 deleted file mode 100644 index 5b6b48a..0000000 --- a/src/nm-hso-gsm-device.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- 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) 2008 Red Hat, Inc. - */ - -#ifndef NM_HSO_GSM_DEVICE_H -#define NM_HSO_GSM_DEVICE_H - -#include <nm-gsm-device.h> - -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-manager.c b/src/nm-manager.c index e5ebdb2..d323ceb 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -28,6 +28,7 @@ #include "nm-utils.h" #include "nm-dbus-manager.h" #include "nm-vpn-manager.h" +#include "nm-modem-manager.h" #include "nm-device-interface.h" #include "nm-device-private.h" #include "nm-device-wifi.h" @@ -95,6 +96,10 @@ static void system_settings_properties_changed_cb (DBusGProxy *proxy, GHashTable *properties, gpointer user_data); +static void add_device (NMManager *self, NMDevice *device, const char *type_name); +static void remove_one_device (NMManager *manager, NMDevice *device); + + #define SSD_POKE_INTERVAL 120000 typedef struct { @@ -133,6 +138,10 @@ typedef struct { NMVPNManager *vpn_manager; guint vpn_manager_id; + NMModemManager *modem_manager; + guint modem_added_id; + guint modem_removed_id; + DBusGProxy *aipd_proxy; gboolean disposed; @@ -241,6 +250,36 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager, } static void +modem_added (NMModemManager *modem_manager, + NMDevice *modem, + gpointer user_data) +{ + NMDeviceType type; + const char *type_name; + + 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"; + + add_device (NM_MANAGER (user_data), NM_DEVICE (g_object_ref (modem)), type_name); +} + +static void +modem_removed (NMModemManager *modem_manager, + NMDevice *modem, + gpointer user_data) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (user_data); + + remove_one_device (NM_MANAGER (user_data), modem); + priv->devices = g_slist_remove (priv->devices, modem); +} + +static void aipd_handle_event (DBusGProxy *proxy, const char *event, const char *iface, @@ -303,6 +342,12 @@ nm_manager_init (NMManager *manager) g_free, g_object_unref); + priv->modem_manager = nm_modem_manager_get (); + priv->modem_added_id = g_signal_connect (priv->modem_manager, "device-added", + G_CALLBACK (modem_added), manager); + priv->modem_removed_id = g_signal_connect (priv->modem_manager, "device-removed", + G_CALLBACK (modem_removed), manager); + priv->vpn_manager = nm_vpn_manager_get (); id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-deactivated", G_CALLBACK (vpn_manager_connection_deactivated_cb), manager); @@ -502,6 +547,16 @@ dispose (GObject *object) } g_object_unref (priv->vpn_manager); + if (priv->modem_added_id) { + g_source_remove (priv->modem_added_id); + priv->modem_added_id = 0; + } + if (priv->modem_removed_id) { + g_source_remove (priv->modem_removed_id); + priv->modem_removed_id = 0; + } + g_object_unref (priv->modem_manager); + g_object_unref (priv->dbus_mgr); g_object_unref (priv->hal_mgr); @@ -1644,58 +1699,66 @@ next: } static void -hal_manager_udi_added_cb (NMHalManager *hal_mgr, - const char *udi, - const char *type_name, - NMDeviceCreatorFn creator_fn, - gpointer user_data) +add_device (NMManager *self, NMDevice *device, const char *type_name) { - NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GObject *device; const char *iface; - if (priv->sleeping) - return; - - /* Make sure the device is not already in the device list */ - if (nm_manager_get_device_by_udi (self, udi)) - return; - - device = creator_fn (hal_mgr, udi, nm_manager_udi_is_managed (self, udi)); - if (!device) - return; - priv->devices = g_slist_append (priv->devices, device); g_signal_connect (device, "state-changed", - G_CALLBACK (manager_device_state_changed), - self); + G_CALLBACK (manager_device_state_changed), + self); /* Attach to the access-point-added signal so that the manager can fill * non-SSID-broadcasting APs with an SSID. */ if (NM_IS_DEVICE_WIFI (device)) { g_signal_connect (device, "hidden-ap-found", - G_CALLBACK (manager_hidden_ap_found), - self); + G_CALLBACK (manager_hidden_ap_found), + self); /* Set initial rfkill state */ nm_device_wifi_set_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled); } - iface = nm_device_get_iface (NM_DEVICE (device)); + iface = nm_device_get_iface (device); nm_info ("Found new %s device '%s'.", type_name, iface); dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (priv->dbus_mgr), nm_device_get_udi (NM_DEVICE (device)), - device); - nm_info ("(%s): exported as %s", iface, udi); + G_OBJECT (device)); + nm_info ("(%s): exported as %s", iface, nm_device_get_udi (device)); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); } static void +hal_manager_udi_added_cb (NMHalManager *hal_mgr, + const char *udi, + const char *type_name, + NMDeviceCreatorFn creator_fn, + gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GObject *device; + + if (priv->sleeping) + return; + + /* Make sure the device is not already in the device list */ + if (nm_manager_get_device_by_udi (self, udi)) + return; + + device = creator_fn (hal_mgr, udi, nm_manager_udi_is_managed (self, udi)); + if (!device) + return; + + add_device (self, NM_DEVICE (device), type_name); +} + +static void hal_manager_udi_removed_cb (NMHalManager *manager, const char *udi, gpointer user_data) diff --git a/src/nm-serial-device.c b/src/nm-serial-device.c deleted file mode 100644 index 184c67c..0000000 --- a/src/nm-serial-device.c +++ /dev/null @@ -1,1178 +0,0 @@ -/* -*- 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) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#define _GNU_SOURCE /* for strcasestr() */ - -#include <termio.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <string.h> -#include <stdlib.h> -#include <glib.h> - -#include "nm-serial-device.h" -#include "nm-device-interface.h" -#include "nm-device-private.h" -#include "ppp-manager/nm-ppp-manager.h" -#include "nm-setting-ppp.h" -#include "nm-marshal.h" -#include "nm-utils.h" -#include "nm-serial-device-glue.h" -#include "NetworkManagerUtils.h" - -static gboolean serial_debug = FALSE; - -#define SERIAL_BUF_SIZE 2048 - -G_DEFINE_TYPE (NMSerialDevice, nm_serial_device, NM_TYPE_DEVICE) - -#define NM_SERIAL_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SERIAL_DEVICE, NMSerialDevicePrivate)) - -typedef struct { - int fd; - GIOChannel *channel; - NMPPPManager *ppp_manager; - NMIP4Config *pending_ip4_config; - struct termios old_t; - - guint pending_id; - guint timeout_id; - - /* PPP stats */ - guint32 in_bytes; - guint32 out_bytes; -} NMSerialDevicePrivate; - -enum { - PPP_STATS, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static int -parse_baudrate (guint i) -{ - int speed; - - switch (i) { - case 0: - speed = B0; - break; - case 50: - speed = B50; - break; - case 75: - speed = B75; - break; - case 110: - speed = B110; - break; - case 150: - speed = B150; - break; - case 300: - speed = B300; - break; - case 600: - speed = B600; - break; - case 1200: - speed = B1200; - break; - case 2400: - speed = B2400; - break; - case 4800: - speed = B4800; - break; - case 9600: - speed = B9600; - break; - case 19200: - speed = B19200; - break; - case 38400: - speed = B38400; - break; - case 57600: - speed = B57600; - break; - case 115200: - speed = B115200; - break; - case 460800: - speed = B460800; - break; - default: - g_warning ("Invalid baudrate '%d'", i); - speed = B9600; - } - - return speed; -} - -static int -parse_bits (guint i) -{ - int bits; - - switch (i) { - case 5: - bits = CS5; - break; - case 6: - bits = CS6; - break; - case 7: - bits = CS7; - break; - case 8: - bits = CS8; - break; - default: - g_warning ("Invalid bits (%d). Valid values are 5, 6, 7, 8.", i); - bits = CS8; - } - - return bits; -} - -static int -parse_parity (char c) -{ - int parity; - - switch (c) { - case 'n': - case 'N': - parity = 0; - break; - case 'e': - case 'E': - parity = PARENB; - break; - case 'o': - case 'O': - parity = PARENB | PARODD; - break; - default: - g_warning ("Invalid parity (%c). Valid values are n, e, o", c); - parity = 0; - } - - return parity; -} - -static int -parse_stopbits (guint i) -{ - int stopbits; - - switch (i) { - case 1: - stopbits = 0; - break; - case 2: - stopbits = CSTOPB; - break; - default: - g_warning ("Invalid stop bits (%d). Valid values are 1 and 2)", i); - stopbits = 0; - } - - return stopbits; -} - -static inline void -nm_serial_debug (const char *prefix, const char *data, int len) -{ - GString *str; - int i; - - if (!serial_debug) - return; - - str = g_string_sized_new (len); - for (i = 0; i < len; i++) { - if (data[i] == '\0') - g_string_append_c (str, ' '); - else if (data[i] == '\r') - g_string_append_c (str, '\n'); - else - g_string_append_c (str, data[i]); - } - - nm_debug ("%s '%s'", prefix, str->str); - g_string_free (str, TRUE); -} - -static NMSetting * -serial_device_get_setting (NMSerialDevice *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; -} - -/* Timeout handling */ - -static void -nm_serial_device_timeout_removed (gpointer data) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (data); - - priv->timeout_id = 0; -} - -static gboolean -nm_serial_device_timed_out (gpointer data) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (data); - - /* Cancel data reading */ - if (priv->pending_id) - g_source_remove (priv->pending_id); - else - nm_warning ("Timeout reached, but there's nothing to time out"); - - return FALSE; -} - -static void -nm_serial_device_add_timeout (NMSerialDevice *self, guint timeout) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self); - - if (priv->pending_id == 0) - nm_warning ("Adding a time out while not waiting for any data"); - - if (priv->timeout_id) { - nm_warning ("Trying to add a new time out while the old one still exists"); - g_source_remove (priv->timeout_id); - } - - priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, - timeout * 1000, - nm_serial_device_timed_out, - self, - nm_serial_device_timeout_removed); - if (G_UNLIKELY (priv->timeout_id == 0)) - nm_warning ("Registering serial device time out failed."); -} - -static void -nm_serial_device_remove_timeout (NMSerialDevice *self) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self); - - if (priv->timeout_id) - g_source_remove (priv->timeout_id); -} - -/* Pending data reading */ - -static guint -nm_serial_device_set_pending (NMSerialDevice *device, - guint timeout, - GIOFunc callback, - gpointer user_data, - GDestroyNotify notify) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - if (G_UNLIKELY (priv->pending_id)) { - /* FIXME: Probably should queue up pending calls instead? */ - /* Multiple pending calls on the same GIOChannel doesn't work, so let's cancel the previous one. */ - nm_warning ("Adding new pending call while previous one isn't finished."); - nm_warning ("Cancelling the previous pending call."); - g_source_remove (priv->pending_id); - } - - priv->pending_id = g_io_add_watch_full (priv->channel, - G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_ERR | G_IO_HUP, - callback, user_data, notify); - - nm_serial_device_add_timeout (device, timeout); - - return priv->pending_id; -} - -static void -nm_serial_device_pending_done (NMSerialDevice *self) -{ - NM_SERIAL_DEVICE_GET_PRIVATE (self)->pending_id = 0; - nm_serial_device_remove_timeout (self); -} - -/****/ - -static gboolean -config_fd (NMSerialDevice *device, NMSettingSerial *setting) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - struct termio stbuf; - int speed; - int bits; - int parity; - int stopbits; - - speed = parse_baudrate (nm_setting_serial_get_baud (setting)); - bits = parse_bits (nm_setting_serial_get_bits (setting)); - parity = parse_parity (nm_setting_serial_get_parity (setting)); - stopbits = parse_stopbits (nm_setting_serial_get_stopbits (setting)); - - ioctl (priv->fd, TCGETA, &stbuf); - - stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR ); - stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET); - stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL); - stbuf.c_lflag &= ~(ECHO | ECHOE); - stbuf.c_cc[VMIN] = 1; - stbuf.c_cc[VTIME] = 0; - stbuf.c_cc[VEOF] = 1; - - stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB); - stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits); - - if (ioctl (priv->fd, TCSETA, &stbuf) < 0) { - nm_warning ("(%s) cannot control device (errno %d)", - nm_device_get_iface (NM_DEVICE (device)), errno); - return FALSE; - } - - return TRUE; -} - -gboolean -nm_serial_device_open (NMSerialDevice *device, - NMSettingSerial *setting) -{ - NMSerialDevicePrivate *priv; - const char *iface; - char *path; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE); - g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), FALSE); - - priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - iface = nm_device_get_iface (NM_DEVICE (device)); - - nm_debug ("(%s) opening device...", iface); - - path = g_build_filename ("/dev", iface, NULL); - priv->fd = open (path, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); - g_free (path); - - if (priv->fd < 0) { - nm_warning ("(%s) cannot open device (errno %d)", iface, errno); - return FALSE; - } - - if (ioctl (priv->fd, TCGETA, &priv->old_t) < 0) { - nm_warning ("(%s) cannot control device (errno %d)", iface, errno); - close (priv->fd); - return FALSE; - } - - if (!config_fd (device, setting)) { - close (priv->fd); - return FALSE; - } - - priv->channel = g_io_channel_unix_new (priv->fd); - - return TRUE; -} - -void -nm_serial_device_close (NMSerialDevice *device) -{ - NMSerialDevicePrivate *priv; - - g_return_if_fail (NM_IS_SERIAL_DEVICE (device)); - - priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - if (priv->pending_id) - g_source_remove (priv->pending_id); - - if (priv->ppp_manager) { - nm_ppp_manager_stop (priv->ppp_manager); - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } - - if (priv->fd) { - nm_debug ("Closing device '%s'", nm_device_get_iface (NM_DEVICE (device))); - - if (priv->channel) { - g_io_channel_unref (priv->channel); - priv->channel = NULL; - } - - ioctl (priv->fd, TCSETA, &priv->old_t); - close (priv->fd); - priv->fd = 0; - } -} - -gboolean -nm_serial_device_send_command (NMSerialDevice *device, GByteArray *command) -{ - int fd; - NMSettingSerial *setting; - int i, eagain_count = 1000; - ssize_t written; - guint32 send_delay = 0; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE); - g_return_val_if_fail (command != NULL, FALSE); - - fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd; - setting = NM_SETTING_SERIAL (serial_device_get_setting (device, NM_TYPE_SETTING_SERIAL)); - if (setting) - send_delay = nm_setting_serial_get_send_delay (setting); - if (send_delay == 0) - send_delay = G_USEC_PER_SEC / 1000; - - nm_serial_debug ("Sending:", (char *) command->data, command->len); - - for (i = 0; i < command->len && eagain_count > 0;) { - written = write (fd, command->data + i, 1); - - if (written > 0) - i += written; - else { - /* Treat written == 0 as EAGAIN to ensure we break out of the - * for() loop eventually. - */ - if ((written < 0) && (errno != EAGAIN)) { - g_warning ("Error in writing (errno %d)", errno); - return FALSE; - } - eagain_count--; - } - g_usleep (send_delay); - } - - if (eagain_count <= 0) - nm_serial_debug ("Error: too many retries sending:", (char *) command->data, command->len); - - return TRUE; -} - -gboolean -nm_serial_device_send_command_string (NMSerialDevice *device, const char *str) -{ - GByteArray *command; - gboolean ret; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE); - g_return_val_if_fail (str != NULL, FALSE); - - command = g_byte_array_new (); - g_byte_array_append (command, (guint8 *) str, strlen (str)); - g_byte_array_append (command, (guint8 *) "\r", 1); - - ret = nm_serial_device_send_command (device, command); - g_byte_array_free (command, TRUE); - - return ret; -} - -static gboolean -find_terminator (const char *line, const char **terminators) -{ - int i; - - for (i = 0; terminators[i]; i++) { - if (!strncasecmp (line, terminators[i], strlen (terminators[i]))) - return TRUE; - } - return FALSE; -} - -static const char * -find_response (const char *line, const char **responses, gint *idx) -{ - int i; - - /* Don't look for a result again if we got one previously */ - for (i = 0; responses[i]; i++) { - if (strcasestr (line, responses[i])) { - *idx = i; - return line; - } - } - return NULL; -} - -#define RESPONSE_LINE_MAX 128 - -int -nm_serial_device_wait_reply_blocking (NMSerialDevice *device, - guint32 timeout_secs, - const char **needles, - const char **terminators) -{ - char buf[SERIAL_BUF_SIZE + 1]; - int fd, reply_index = -1, bytes_read; - GString *result = NULL; - time_t end; - const char *response = NULL; - gboolean done = FALSE; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), -1); - g_return_val_if_fail (timeout_secs <= 60, -1); - g_return_val_if_fail (needles != NULL, -1); - - fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd; - if (fd < 0) - return -1; - - end = time (NULL) + timeout_secs; - result = g_string_sized_new (20); - do { - bytes_read = read (fd, buf, SERIAL_BUF_SIZE); - if (bytes_read < 0 && errno != EAGAIN) { - nm_warning ("%s: read error: %d (%s)", - nm_device_get_iface (NM_DEVICE (device)), - errno, - strerror (errno)); - return -1; - } - - if (bytes_read == 0) - break; /* EOF */ - else if (bytes_read > 0) { - buf[bytes_read] = 0; - g_string_append (result, buf); - - nm_serial_debug ("Got:", result->str, result->len); - } - - /* Look for needles and terminators */ - if ((bytes_read > 0) && result->str) { - char *p = result->str; - - /* Break the response up into lines and process each one */ - while ((p < result->str + strlen (result->str)) && !done) { - char line[RESPONSE_LINE_MAX] = { '\0', }; - char *tmp; - int i; - gboolean got_something = FALSE; - - for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) { - /* Ignore front CR/LF */ - if ((*p == '\n') || (*p == '\r')) { - if (got_something) - break; - } else { - line[i++] = *p; - got_something = TRUE; - } - } - line[i] = '\0'; - - tmp = g_strstrip (line); - if (tmp && strlen (tmp)) { - done = find_terminator (tmp, terminators); - if (reply_index == -1) - response = find_response (tmp, needles, &reply_index); - } - } - } - - /* Limit the size of the buffer */ - if (result->len > SERIAL_BUF_SIZE) { - g_warning ("%s (%s): response buffer filled before repsonse received", - __func__, nm_device_get_iface (NM_DEVICE (device))); - break; - } - - if (!done) - g_usleep (100); - } while (!done && (time (NULL) < end)); - - return reply_index; -} - -typedef struct { - NMSerialDevice *device; - char **str_needles; - char **terminators; - GString *result; - NMSerialWaitForReplyFn callback; - gpointer user_data; - int reply_index; - char *reply_line; - time_t end; -} WaitForReplyInfo; - -static void -wait_for_reply_done (gpointer data) -{ - WaitForReplyInfo *info = (WaitForReplyInfo *) data; - - nm_serial_device_pending_done (info->device); - - /* Call the callback */ - info->callback (info->device, info->reply_index, info->reply_line, info->user_data); - - /* Free info */ - if (info->result) - g_string_free (info->result, TRUE); - - g_free (info->reply_line); - - g_strfreev (info->str_needles); - g_strfreev (info->terminators); - g_slice_free (WaitForReplyInfo, info); -} - -static gboolean -wait_for_reply_got_data (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - WaitForReplyInfo *info = (WaitForReplyInfo *) data; - gchar buf[SERIAL_BUF_SIZE + 1]; - gsize bytes_read; - GIOStatus status; - gboolean done = FALSE; - - if (condition & G_IO_HUP || condition & G_IO_ERR) - return FALSE; - - do { - GError *err = NULL; - - status = g_io_channel_read_chars (source, buf, SERIAL_BUF_SIZE, &bytes_read, &err); - if (status == G_IO_STATUS_ERROR) { - g_warning ("%s", err->message); - g_error_free (err); - err = NULL; - } - - if (bytes_read > 0) { - buf[bytes_read] = 0; - g_string_append (info->result, buf); - - nm_serial_debug ("Got:", info->result->str, info->result->len); - } - - /* Look for needles and terminators */ - if ((bytes_read > 0) && info->result->str) { - char *p = info->result->str; - - /* Break the response up into lines and process each one */ - while ((p < info->result->str + strlen (info->result->str)) && !done) { - char line[RESPONSE_LINE_MAX] = { '\0', }; - char *tmp; - int i; - gboolean got_something = FALSE; - - for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) { - /* Ignore front CR/LF */ - if ((*p == '\n') || (*p == '\r')) { - if (got_something) - break; - } else { - line[i++] = *p; - got_something = TRUE; - } - } - line[i] = '\0'; - - tmp = g_strstrip (line); - if (tmp && strlen (tmp)) { - done = find_terminator (tmp, (const char **) info->terminators); - if (info->reply_index == -1) { - if (find_response (tmp, (const char **) info->str_needles, &(info->reply_index))) - info->reply_line = g_strdup (tmp); - } - } - } - } - - /* Limit the size of the buffer */ - if (info->result->len > SERIAL_BUF_SIZE) { - nm_warning ("(%s): response buffer filled before repsonse received", - nm_device_get_iface (NM_DEVICE (info->device))); - done = TRUE; - break; - } - - /* Make sure we don't go over the timeout, in addition to the timeout - * handler that's been scheduled. If for some reason this loop doesn't - * terminate (terminator not found, whatever) then this should make - * sure that NM doesn't spin the CPU forever. - */ - if (time (NULL) > info->end) { - done = TRUE; - break; - } else if (!done) - g_usleep (50); - } while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN); - - return !done; -} - -guint -nm_serial_device_wait_for_reply (NMSerialDevice *device, - guint timeout, - const char **responses, - const char **terminators, - NMSerialWaitForReplyFn callback, - gpointer user_data) -{ - WaitForReplyInfo *info; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0); - g_return_val_if_fail (responses != NULL, 0); - g_return_val_if_fail (callback != NULL, 0); - - info = g_slice_new0 (WaitForReplyInfo); - info->device = device; - info->str_needles = g_strdupv ((char **) responses); - info->terminators = g_strdupv ((char **) terminators); - info->result = g_string_new (NULL); - info->callback = callback; - info->user_data = user_data; - info->reply_index = -1; - info->end = time (NULL) + timeout; - - return nm_serial_device_set_pending (device, timeout, wait_for_reply_got_data, info, wait_for_reply_done); -} - -#if 0 -typedef struct { - NMSerialDevice *device; - gboolean timed_out; - NMSerialWaitQuietFn callback; - gpointer user_data; -} WaitQuietInfo; - -static void -wait_quiet_done (gpointer data) -{ - WaitQuietInfo *info = (WaitQuietInfo *) data; - - nm_serial_device_pending_done (info->device); - - /* Call the callback */ - info->callback (info->device, info->timed_out, info->user_data); - - /* Free info */ - g_slice_free (WaitQuietInfo, info); -} - -static gboolean -wait_quiet_quiettime (gpointer data) -{ - WaitQuietInfo *info = (WaitQuietInfo *) data; - - info->timed_out = FALSE; - g_source_remove (NM_SERIAL_DEVICE_GET_PRIVATE (info->device)->pending); - - return FALSE; -} - -static gboolean -wait_quiet_got_data (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - WaitQuietInfo *info = (WaitQuietInfo *) data; - gsize bytes_read; - char buf[4096]; - GIOStatus status; - - if (condition & G_IO_HUP || condition & G_IO_ERR) - return FALSE; - - if (condition & G_IO_IN) { - do { - status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, NULL); - - if (bytes_read) { - /* Reset the quiet time timeout */ - g_source_remove (info->quiet_id); - info->quiet_id = g_timeout_add (info->quiet_time, wait_quiet_quiettime, info); - } - } while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN); - } - - return TRUE; -} - -void -nm_serial_device_wait_quiet (NMSerialDevice *device, - guint timeout, - guint quiet_time, - NMSerialWaitQuietFn callback, - gpointer user_data) -{ - WaitQuietInfo *info; - - g_return_if_fail (NM_IS_SERIAL_DEVICE (device)); - g_return_if_fail (callback != NULL); - - info = g_slice_new0 (WaitQuietInfo); - info->device = device; - info->timed_out = TRUE; - info->callback = callback; - info->user_data = user_data; - info->quiet_id = g_timeout_add (quiet_time, - wait_quiet_timeout, - info); - - return nm_serial_device_set_pending (device, timeout, wait_quiet_got_data, info, wait_quiet_done); -} - -#endif - -typedef struct { - NMSerialDevice *device; - speed_t current_speed; - NMSerialFlashFn callback; - gpointer user_data; -} FlashInfo; - -static speed_t -get_speed (NMSerialDevice *device) -{ - struct termios options; - - tcgetattr (NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd, &options); - - return cfgetospeed (&options); -} - -static void -set_speed (NMSerialDevice *device, speed_t speed) -{ - struct termios options; - int fd; - - fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd; - tcgetattr (fd, &options); - - cfsetispeed (&options, speed); - cfsetospeed (&options, speed); - - options.c_cflag |= (CLOCAL | CREAD); - tcsetattr (fd, TCSANOW, &options); -} - -static void -flash_done (gpointer data) -{ - FlashInfo *info = (FlashInfo *) data; - - NM_SERIAL_DEVICE_GET_PRIVATE (info->device)->pending_id = 0; - - info->callback (info->device, info->user_data); - - g_slice_free (FlashInfo, info); -} - -static gboolean -flash_do (gpointer data) -{ - FlashInfo *info = (FlashInfo *) data; - - set_speed (info->device, info->current_speed); - - return FALSE; -} - -guint -nm_serial_device_flash (NMSerialDevice *device, - guint32 flash_time, - NMSerialFlashFn callback, - gpointer user_data) -{ - FlashInfo *info; - guint id; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0); - g_return_val_if_fail (callback != NULL, 0); - - info = g_slice_new0 (FlashInfo); - info->device = device; - info->current_speed = get_speed (device); - info->callback = callback; - info->user_data = user_data; - - set_speed (device, B0); - - id = g_timeout_add_full (G_PRIORITY_DEFAULT, - flash_time, - flash_do, - info, - flash_done); - - NM_SERIAL_DEVICE_GET_PRIVATE (device)->pending_id = id; - - return id; -} - -GIOChannel * -nm_serial_device_get_io_channel (NMSerialDevice *device) -{ - NMSerialDevicePrivate *priv; - - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0); - - priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - if (priv->channel) - return g_io_channel_ref (priv->channel); - - return NULL; -} - -NMPPPManager * -nm_serial_device_get_ppp_manager (NMSerialDevice *device) -{ - g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), NULL); - - return NM_SERIAL_DEVICE_GET_PRIVATE (device)->ppp_manager; -} - -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_NETWORK: - nm_device_state_changed (device, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - break; - 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); - break; - case NM_PPP_STATUS_AUTHENTICATE: - nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - break; - default: - break; - } -} - -static void -ppp_ip4_config (NMPPPManager *ppp_manager, - const char *iface, - NMIP4Config *config, - gpointer user_data) -{ - NMDevice *device = NM_DEVICE (user_data); - - nm_device_set_ip_iface (device, iface); - NM_SERIAL_DEVICE_GET_PRIVATE (device)->pending_ip4_config = g_object_ref (config); - nm_device_activate_schedule_stage4_ip_config_get (device); -} - -static void -ppp_stats (NMPPPManager *ppp_manager, - guint32 in_bytes, - guint32 out_bytes, - gpointer user_data) -{ - NMSerialDevice *device = NM_SERIAL_DEVICE (user_data); - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { - priv->in_bytes = in_bytes; - priv->out_bytes = out_bytes; - - g_signal_emit (device, signals[PPP_STATS], 0, in_bytes, out_bytes); - } -} - -static NMActStageReturn -real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - NMSerialDeviceClass *serial_class = NM_SERIAL_DEVICE_GET_CLASS (device); - NMActRequest *req; - GError *err = NULL; - NMActStageReturn ret; - const char *ppp_name = NULL; - - req = nm_device_get_act_request (device); - g_assert (req); - - if (serial_class->get_ppp_name) - ppp_name = serial_class->get_ppp_name (NM_SERIAL_DEVICE (device), 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_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 -real_act_stage4_get_ip4_config (NMDevice *device, - NMIP4Config **config, - NMDeviceStateReason *reason) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - NMConnection *connection; - NMSettingIP4Config *s_ip4; - - g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - 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); - - *config = priv->pending_ip4_config; - priv->pending_ip4_config = NULL; - nm_utils_merge_ip4_config (*config, s_ip4); - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static void -cleanup_device (NMSerialDevice *device) -{ - NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device); - - nm_device_set_ip_iface (NM_DEVICE (device), NULL); - - if (priv->pending_ip4_config) { - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = NULL; - } - - priv->in_bytes = priv->out_bytes = 0; -} - -static void -real_deactivate_quickly (NMDevice *device) -{ - NMSerialDevice *self = NM_SERIAL_DEVICE (device); - - cleanup_device (self); - nm_serial_device_close (self); -} - -static guint32 -real_get_generic_capabilities (NMDevice *dev) -{ - return NM_DEVICE_CAP_NM_SUPPORTED; -} - -/*****************************************************************************/ - -static void -nm_serial_device_init (NMSerialDevice *self) -{ - if (getenv ("NM_SERIAL_DEBUG")) - serial_debug = TRUE; -} - -static void -finalize (GObject *object) -{ - NMSerialDevice *self = NM_SERIAL_DEVICE (object); - - cleanup_device (self); - nm_serial_device_close (self); - - G_OBJECT_CLASS (nm_serial_device_parent_class)->finalize (object); -} - -static void -nm_serial_device_class_init (NMSerialDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMSerialDevicePrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - - parent_class->get_generic_capabilities = real_get_generic_capabilities; - parent_class->act_stage2_config = real_act_stage2_config; - parent_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config; - parent_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 (NMSerialDeviceClass, ppp_stats), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_serial_device_object_info); -} diff --git a/src/nm-serial-device.h b/src/nm-serial-device.h deleted file mode 100644 index 6e9b53b..0000000 --- a/src/nm-serial-device.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- 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) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#ifndef NM_SERIAL_DEVICE_H -#define NM_SERIAL_DEVICE_H - -#include <nm-device.h> -#include <nm-setting-serial.h> -#include "ppp-manager/nm-ppp-manager.h" - -G_BEGIN_DECLS - -#define NM_TYPE_SERIAL_DEVICE (nm_serial_device_get_type ()) -#define NM_SERIAL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SERIAL_DEVICE, NMSerialDevice)) -#define NM_SERIAL_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SERIAL_DEVICE, NMSerialDeviceClass)) -#define NM_IS_SERIAL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SERIAL_DEVICE)) -#define NM_IS_SERIAL_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SERIAL_DEVICE)) -#define NM_SERIAL_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SERIAL_DEVICE, NMSerialDeviceClass)) - -typedef struct { - NMDevice parent; -} NMSerialDevice; - -typedef struct { - NMDeviceClass parent; - - const char * (*get_ppp_name) (NMSerialDevice *device, NMActRequest *req); - - /* Signals */ - void (*ppp_stats) (NMSerialDevice *device, guint32 in_bytes, guint32 out_bytes); -} NMSerialDeviceClass; - -GType nm_serial_device_get_type (void); - -typedef void (*NMSerialGetReplyFn) (NMSerialDevice *device, - const char *reply, - gpointer user_data); - -typedef void (*NMSerialWaitForReplyFn) (NMSerialDevice *device, - int reply_index, - const char *reply, - gpointer user_data); - -typedef void (*NMSerialWaitQuietFn) (NMSerialDevice *device, - gboolean timed_out, - gpointer user_data); - -typedef void (*NMSerialFlashFn) (NMSerialDevice *device, - gpointer user_data); - - - -gboolean nm_serial_device_open (NMSerialDevice *device, - NMSettingSerial *setting); - -void nm_serial_device_close (NMSerialDevice *device); -gboolean nm_serial_device_send_command (NMSerialDevice *device, - GByteArray *command); - -gboolean nm_serial_device_send_command_string (NMSerialDevice *device, - const char *str); - -int nm_serial_device_wait_reply_blocking (NMSerialDevice *device, - guint32 timeout_secs, - const char **needles, - const char **terminators); - -guint nm_serial_device_wait_for_reply (NMSerialDevice *device, - guint timeout, - const char **responses, - const char **terminators, - NMSerialWaitForReplyFn callback, - gpointer user_data); - -void nm_serial_device_wait_quiet (NMSerialDevice *device, - guint timeout, - guint quiet_time, - NMSerialWaitQuietFn callback, - gpointer user_data); - -guint nm_serial_device_flash (NMSerialDevice *device, - guint32 flash_time, - NMSerialFlashFn callback, - gpointer user_data); - -GIOChannel *nm_serial_device_get_io_channel (NMSerialDevice *device); - -NMPPPManager *nm_serial_device_get_ppp_manager (NMSerialDevice *device); - -G_END_DECLS - -#endif /* NM_SERIAL_DEVICE_H */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor