summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTambet Ingo <tambet@gmail.com>2007-11-29 14:38:07 +0000
committerTambet Ingo <tambet@gmail.com>2007-11-29 14:38:07 +0000
commitdb5a10dc4d33ebc793c21ee83e9da38e3675c132 (patch)
tree3b90c80b0bddb99b8c082eb7da95c7857cecd502 /src
parentf5fb0162719b68d9c32cf82ba0af1ed82021fd86 (diff)
downloadNetworkManager-db5a10dc4d33ebc793c21ee83e9da38e3675c132.tar.gz
2007-11-28 Tambet Ingo <tambet@gmail.com>
Merge the beginnings of the new GSM card support. * src/ppp-manager/nm-ppp-manager.c (nm_ppp_manager_stop): Remove * the ppp watch source before killing pppd - If this happens from g_object_unref() then the ppp manager is already destroyed by the time the watch callback runs. * src/nm-hal-manager.c: Add a device_type_name string to the * device creators, so that we can print a nice human readable string when a device is added. * src/nm-umts-device.c (automatic_registration_get_network): * Query for the activated network, not much is done with the result thought. * src/nm-serial-device.c (nm_serial_device_get_reply): * Implement. (ppp_ip4_config): Change the device state to activated here for now. (real_check_connection): Make sure the connection includes ppp setting. * libnm-glib/nm-client.c (get_device): Handle umts devices. * libnm-glib/Makefile.am: Add the new files to build. * libnm-glib/nm-umts-device.c: * libnm-glib/nm-umts-device.h: Implement. 2007-11-26 Tambet Ingo <tambet@gmail.com> * src/nm-umts-device.c (automatic_registration_get_network): For * now, dial immediately, nm_serial_device_get_reply() isn't implemented correctly yet. * src/nm-serial-device.c (wait_for_reply_info_destroy): Don't * try to remove the timeout source - this function is only called when the timeout source has been removed. (nm_serial_device_wait_for_reply): Allocate the duplicate responses array to be big enough to contain the terminating zero element as well. The timeout argument is meant to be in seconds now. (real_deactivate_quickly): Implement. * src/NetworkManager.conf: Allow root to own "org.freedesktop.NetworkManager.PPP", deny it for everybody else. * libnm-util/nm-setting-umts.c: Network type and band properties * are ints, (not unsigned ints). * libnm-util/nm-setting-serial.c (nm_setting_serial_class_init): * Fix a small issue with parity bounds - capital letters have lower ascii codes than lower case letters. * libnm-util/nm-connection.c (register_default_settings): * Register serial and umts settings. 2007-11-22 Tambet Ingo <tambet@gmail.com> Remove the "index" property from devices as not all device types have this. * include/NetworkManager.h (NM_DBUS_PATH_DEVICE): Remove. * src/nm-hal-manager.c (nm_get_device_index_from_hal): Remove. (wired_device_creator): Get the device interface from hal to create the device. (wireless_device_creator): Ditto. * src/nm-device.c (nm_device_init): Remove the index member. (constructor): Remove the checks for index property, make interface property a require constructor property. Use the HAL udi for DBus path for devices. (nm_device_get_index): Remove. (set_property): Remove index handling. (get_property): Ditto. (nm_device_get_dbus_path): Remove. * src/nm-device-interface.c (nm_device_interface_init): Remove * the index property. * src/nm-device-802-3-ethernet.c * (nm_device_802_3_ethernet_link_activated): Access the device index through it's interface. (nm_device_802_3_ethernet_link_deactivated): Ditto. (nm_device_802_3_ethernet_new): Remove the useless argument test_dev. Remove index argument. Add interface argument. * src/nm-device-802-11-wireless.c * (nm_device_802_11_wireless_new): Remove the useless test_dev argument. Remove index argument. Add interface arugment. * src/NetworkManagerSystem.c * (nm_system_device_set_from_ip4_config): Get the device index through interface. (nm_system_set_mtu): Ditto. * introspection/nm-device.xml: Remove the "Index" property. 2007-11-21 Tambet Ingo <tambet@gmail.com> * src/nm-serial-device.c: * src/nm-serial-device.c: * src/nm-umts-device.c: * src/nm-umts-device.h: Implement. * src/nm-hal-manager.c (nm_get_device_driver_name): * libhal_free_string the string allocated by libhal. (modem_device_creator): Implement. (register_built_in_creators): Register the modem creator. * src/nm-device-802-11-wireless.c * (nm_device_802_11_wireless_new): Remove the unused test_dev argument. * src/nm-device-802-3-ethernet.c (nm_device_802_3_ethernet_new): * Ditto. * src/Makefile.am: Add new files to build. Link in ppp-manager. * libnm-util/nm-setting-umts.c: * libnm-util/nm-setting-umts.h: * libnm-util/nm-setting-serial.c: * libnm-util/nm-setting-serial.h: Implement. * libnm-util/Makefile.am: Add new files to build. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3116 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/NetworkManager.conf9
-rw-r--r--src/NetworkManagerSystem.c12
-rw-r--r--src/nm-device-802-11-wireless.c22
-rw-r--r--src/nm-device-802-11-wireless.h9
-rw-r--r--src/nm-device-802-3-ethernet.c31
-rw-r--r--src/nm-device-802-3-ethernet.h9
-rw-r--r--src/nm-device-interface.c10
-rw-r--r--src/nm-device-interface.h2
-rw-r--r--src/nm-device.c64
-rw-r--r--src/nm-device.h2
-rw-r--r--src/nm-hal-manager.c143
-rw-r--r--src/nm-manager.c6
-rw-r--r--src/nm-serial-device.c869
-rw-r--r--src/nm-serial-device.h77
-rw-r--r--src/nm-umts-device.c364
-rw-r--r--src/nm-umts-device.h33
-rw-r--r--src/ppp-manager/nm-ppp-manager.c7
18 files changed, 1518 insertions, 156 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f8c30de2ed..012d9d3316 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -56,6 +56,10 @@ 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-umts-device.c \
+ nm-umts-device.h \
autoip.c \
autoip.h \
kernel-types.h \
@@ -123,6 +127,7 @@ NetworkManager_LDADD = \
./vpn-manager/libvpn-manager.la \
./dhcp-manager/libdhcp-manager.la \
./supplicant-manager/libsupplicant-manager.la \
+ ./ppp-manager/libppp-manager.la \
./backends/libnmbackend.la \
$(top_builddir)/libnm-util/libnm-util.la
diff --git a/src/NetworkManager.conf b/src/NetworkManager.conf
index 18dea10b50..01dfee2590 100644
--- a/src/NetworkManager.conf
+++ b/src/NetworkManager.conf
@@ -4,9 +4,12 @@
<busconfig>
<policy user="root">
<allow own="org.freedesktop.NetworkManager"/>
-
<allow send_destination="org.freedesktop.NetworkManager"/>
<allow send_interface="org.freedesktop.NetworkManager"/>
+
+ <allow own="org.freedesktop.NetworkManager.PPP"/>
+ <allow send_destination="org.freedesktop.NetworkManager.PPP"/>
+ <allow send_interface="org.freedesktop.NetworkManager.PPP"/>
</policy>
<policy at_console="true">
<allow send_destination="org.freedesktop.NetworkManager"/>
@@ -16,6 +19,10 @@
<deny own="org.freedesktop.NetworkManager"/>
<deny send_destination="org.freedesktop.NetworkManager"/>
<deny send_interface="org.freedesktop.NetworkManager"/>
+
+ <deny own="org.freedesktop.NetworkManager.PPP"/>
+ <deny send_destination="org.freedesktop.NetworkManager.PPP"/>
+ <deny send_interface="org.freedesktop.NetworkManager.PPP"/>
</policy>
<limit name="max_replies_per_connection">512</limit>
diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c
index 97db4acad1..9c77fa3b54 100644
--- a/src/NetworkManagerSystem.c
+++ b/src/NetworkManagerSystem.c
@@ -210,9 +210,13 @@ gboolean nm_system_device_set_from_ip4_config (NMDevice *dev)
if ((addr = nm_ip4_config_to_rtnl_addr (config, NM_RTNL_ADDR_DEFAULT)))
{
- rtnl_addr_set_ifindex (addr, nm_device_get_index (dev));
+ const char *iface;
+
+ iface = nm_device_get_iface (dev);
+ rtnl_addr_set_ifindex (addr, nm_netlink_iface_to_index (iface));
+
if ((err = rtnl_addr_add (nlh, addr, 0)) < 0)
- nm_warning ("(%s) error %d returned from rtnl_addr_add():\n%s", nm_device_get_iface (dev), err, nl_geterror());
+ nm_warning ("(%s) error %d returned from rtnl_addr_add():\n%s", iface, err, nl_geterror());
rtnl_addr_put (addr);
}
else
@@ -492,6 +496,7 @@ void nm_system_set_mtu (NMDevice *dev)
struct rtnl_link * old;
unsigned long mtu;
struct nl_handle * nlh;
+ guint32 idx;
mtu = nm_system_get_mtu (dev);
if (!mtu)
@@ -501,7 +506,8 @@ void nm_system_set_mtu (NMDevice *dev)
if (!request)
return;
- old = nm_netlink_index_to_rtnl_link (nm_device_get_index (dev));
+ idx = nm_netlink_iface_to_index (nm_device_get_iface (dev));
+ old = nm_netlink_index_to_rtnl_link (idx);
if (!old)
goto out_request;
diff --git a/src/nm-device-802-11-wireless.c b/src/nm-device-802-11-wireless.c
index 9c14108631..e68c7cbca6 100644
--- a/src/nm-device-802-11-wireless.c
+++ b/src/nm-device-802-11-wireless.c
@@ -3048,31 +3048,29 @@ state_changed_cb (NMDevice *device, NMDeviceState state, gpointer user_data)
NMDevice80211Wireless *
-nm_device_802_11_wireless_new (int idx,
- const char *udi,
- const char *driver,
- gboolean test_dev)
+nm_device_802_11_wireless_new (const char *udi,
+ const char *iface,
+ const char *driver)
{
GObject *obj;
- g_return_val_if_fail (idx >= 0, NULL);
g_return_val_if_fail (udi != NULL, NULL);
+ g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
obj = g_object_new (NM_TYPE_DEVICE_802_11_WIRELESS,
- NM_DEVICE_INTERFACE_UDI, udi,
- NM_DEVICE_INTERFACE_INDEX, idx,
- NM_DEVICE_INTERFACE_DRIVER, driver,
- NULL);
+ NM_DEVICE_INTERFACE_UDI, udi,
+ NM_DEVICE_INTERFACE_IFACE, iface,
+ NM_DEVICE_INTERFACE_DRIVER, driver,
+ NULL);
if (obj == NULL)
return NULL;
g_signal_connect (obj, "state-changed",
- G_CALLBACK (state_changed_cb),
- NULL);
+ G_CALLBACK (state_changed_cb),
+ NULL);
return NM_DEVICE_802_11_WIRELESS (obj);
-
}
NMAccessPoint *
diff --git a/src/nm-device-802-11-wireless.h b/src/nm-device-802-11-wireless.h
index e7b7dd4c40..cfd17bdbca 100644
--- a/src/nm-device-802-11-wireless.h
+++ b/src/nm-device-802-11-wireless.h
@@ -1,3 +1,5 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
@@ -78,10 +80,9 @@ struct _NMDevice80211WirelessClass
GType nm_device_802_11_wireless_get_type (void);
-NMDevice80211Wireless *nm_device_802_11_wireless_new (int index,
- const char *udi,
- const char *driver,
- gboolean test_dev);
+NMDevice80211Wireless *nm_device_802_11_wireless_new (const char *udi,
+ const char *iface,
+ const char *driver);
void nm_device_802_11_wireless_set_ssid (NMDevice80211Wireless *self,
const GByteArray * ssid);
diff --git a/src/nm-device-802-3-ethernet.c b/src/nm-device-802-3-ethernet.c
index 6124ad6575..589b83805f 100644
--- a/src/nm-device-802-3-ethernet.c
+++ b/src/nm-device-802-3-ethernet.c
@@ -34,6 +34,7 @@
#include "nm-activation-request.h"
#include "NetworkManagerUtils.h"
#include "nm-supplicant-manager.h"
+#include "nm-netlink.h"
#include "nm-netlink-monitor.h"
#include "NetworkManagerSystem.h"
#include "nm-setting-connection.h"
@@ -85,7 +86,7 @@ nm_device_802_3_ethernet_link_activated (NMNetlinkMonitor *monitor,
NMDevice *dev = NM_DEVICE (user_data);
/* Make sure signal is for us */
- if (nm_device_get_index (dev) == idx)
+ if (nm_netlink_iface_to_index (nm_device_get_iface (dev)) == idx)
nm_device_set_active_link (dev, TRUE);
}
@@ -97,7 +98,7 @@ nm_device_802_3_ethernet_link_deactivated (NMNetlinkMonitor *monitor,
NMDevice *dev = NM_DEVICE (user_data);
/* Make sure signal is for us */
- if (nm_device_get_index (dev) == idx)
+ if (nm_netlink_iface_to_index (nm_device_get_iface (dev)) == idx)
nm_device_set_active_link (dev, FALSE);
}
@@ -119,6 +120,7 @@ constructor (GType type,
dev = NM_DEVICE (object);
priv = NM_DEVICE_802_3_ETHERNET_GET_PRIVATE (dev);
+
priv->carrier_file_path = g_strdup_printf ("/sys/class/net/%s/carrier",
nm_device_get_iface (dev));
@@ -237,26 +239,21 @@ real_bring_down (NMDevice *dev)
NMDevice8023Ethernet *
-nm_device_802_3_ethernet_new (int idx,
- const char *udi,
- const char *driver,
- gboolean test_dev)
+nm_device_802_3_ethernet_new (const char *udi,
+ const char *iface,
+ const char *driver)
{
GObject *obj;
- g_return_val_if_fail (idx >= 0, NULL);
g_return_val_if_fail (udi != NULL, NULL);
+ g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (driver != NULL, NULL);
- obj = g_object_new (NM_TYPE_DEVICE_802_3_ETHERNET,
- NM_DEVICE_INTERFACE_UDI, udi,
- NM_DEVICE_INTERFACE_INDEX, idx,
- NM_DEVICE_INTERFACE_DRIVER, driver,
- NULL);
- if (obj == NULL)
- return NULL;
-
- return NM_DEVICE_802_3_ETHERNET (obj);
+ return (NMDevice8023Ethernet *) g_object_new (NM_TYPE_DEVICE_802_3_ETHERNET,
+ NM_DEVICE_INTERFACE_UDI, udi,
+ NM_DEVICE_INTERFACE_IFACE, iface,
+ NM_DEVICE_INTERFACE_DRIVER, driver,
+ NULL);
}
@@ -426,7 +423,7 @@ nm_device_802_3_ethernet_finalize (GObject *object)
static void
get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
+ GValue *value, GParamSpec *pspec)
{
NMDevice8023Ethernet *device = NM_DEVICE_802_3_ETHERNET (object);
struct ether_addr hw_addr;
diff --git a/src/nm-device-802-3-ethernet.h b/src/nm-device-802-3-ethernet.h
index 0413ff8400..45734bc49f 100644
--- a/src/nm-device-802-3-ethernet.h
+++ b/src/nm-device-802-3-ethernet.h
@@ -1,3 +1,5 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
@@ -51,10 +53,9 @@ typedef struct {
GType nm_device_802_3_ethernet_get_type (void);
-NMDevice8023Ethernet *nm_device_802_3_ethernet_new (int index,
- const char *udi,
- const char *driver,
- gboolean test_dev);
+NMDevice8023Ethernet *nm_device_802_3_ethernet_new (const char *udi,
+ const char *iface,
+ const char *driver);
void nm_device_802_3_ethernet_get_address (NMDevice8023Ethernet *dev,
struct ether_addr *addr);
diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c
index a2bb770856..d2d62f9725 100644
--- a/src/nm-device-interface.c
+++ b/src/nm-device-interface.c
@@ -56,19 +56,11 @@ nm_device_interface_init (gpointer g_iface)
g_object_interface_install_property
(g_iface,
- g_param_spec_uint (NM_DEVICE_INTERFACE_INDEX,
- "Index",
- "Index",
- 0, G_MAXUINT32, 0, /* FIXME */
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_interface_install_property
- (g_iface,
g_param_spec_string (NM_DEVICE_INTERFACE_IFACE,
"Interface",
"Interface",
NULL,
- G_PARAM_READABLE));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_interface_install_property
(g_iface,
diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h
index b33ad79f41..124c91427f 100644
--- a/src/nm-device-interface.h
+++ b/src/nm-device-interface.h
@@ -22,7 +22,6 @@ typedef enum
#define NM_DEVICE_INTERFACE_UDI "udi"
#define NM_DEVICE_INTERFACE_IFACE "interface"
-#define NM_DEVICE_INTERFACE_INDEX "index"
#define NM_DEVICE_INTERFACE_DRIVER "driver"
#define NM_DEVICE_INTERFACE_CAPABILITIES "capabilities"
#define NM_DEVICE_INTERFACE_IP4_ADDRESS "ip4_address"
@@ -35,7 +34,6 @@ typedef enum {
NM_DEVICE_INTERFACE_PROP_FIRST = 0x1000,
NM_DEVICE_INTERFACE_PROP_UDI = NM_DEVICE_INTERFACE_PROP_FIRST,
- NM_DEVICE_INTERFACE_PROP_INDEX,
NM_DEVICE_INTERFACE_PROP_IFACE,
NM_DEVICE_INTERFACE_PROP_DRIVER,
NM_DEVICE_INTERFACE_PROP_CAPABILITIES,
diff --git a/src/nm-device.c b/src/nm-device.c
index 74f14c326b..6f3aee071e 100644
--- a/src/nm-device.c
+++ b/src/nm-device.c
@@ -58,9 +58,7 @@ struct _NMDevicePrivate
NMDeviceState state;
- char * dbus_path;
char * udi;
- int index; /* Should always stay the same over lifetime of device */
char * iface; /* may change, could be renamed by user */
NMDeviceType type;
guint32 capabilities;
@@ -113,7 +111,6 @@ nm_device_init (NMDevice * self)
self->priv->initialized = FALSE;
self->priv->udi = NULL;
self->priv->iface = NULL;
- self->priv->index = G_MAXUINT32;
self->priv->type = DEVICE_TYPE_UNKNOWN;
self->priv->capabilities = NM_DEVICE_CAP_NONE;
self->priv->driver = NULL;
@@ -142,30 +139,27 @@ constructor (GType type,
NMDBusManager *manager;
object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
+ n_construct_params,
+ construct_params);
if (!object)
return NULL;
dev = NM_DEVICE (object);
priv = NM_DEVICE_GET_PRIVATE (dev);
- if (priv->index == G_MAXUINT32) {
- nm_warning ("Interface index is a required constructor property.");
+ if (!priv->udi) {
+ nm_warning ("No device udi provided, ignoring");
goto error;
}
- priv->iface = nm_netlink_index_to_iface (priv->index);
- if (priv->iface == NULL) {
- nm_warning ("(%u): Couldn't get interface name for device, ignoring.",
- priv->index);
+ if (!priv->iface) {
+ nm_warning ("No device interface provided, ignoring");
goto error;
}
priv->capabilities |= NM_DEVICE_GET_CLASS (dev)->get_generic_capabilities (dev);
if (!(priv->capabilities & NM_DEVICE_CAP_NM_SUPPORTED)) {
- nm_warning ("(%s): Device unsupported, ignoring.",
- nm_device_get_iface (dev));
+ nm_warning ("(%s): Device unsupported, ignoring.", priv->iface);
goto error;
}
@@ -174,27 +168,17 @@ constructor (GType type,
/* Allow distributions to flag devices as disabled */
if (nm_system_device_get_disabled (dev)) {
- nm_warning ("(%s): Device otherwise managed, ignoring.",
- nm_device_get_iface (dev));
+ nm_warning ("(%s): Device otherwise managed, ignoring.", priv->iface);
goto error;
}
nm_print_device_capabilities (dev);
manager = nm_dbus_manager_get ();
- priv->dbus_path = g_strdup_printf ("%s/%d",
- NM_DBUS_PATH_DEVICE,
- nm_device_get_index (dev));
- if (priv->dbus_path == NULL) {
- nm_warning ("(%s): Not enough memory to initialize device.",
- nm_device_get_iface (dev));
- goto error;
- }
- nm_info ("(%s): exporting device as %s", nm_device_get_iface (dev), nm_device_get_dbus_path (dev));
+ nm_info ("(%s): exporting device as %s", priv->iface, priv->udi);
dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (manager),
- nm_device_get_dbus_path (dev),
- object);
+ priv->udi, object);
g_object_unref (manager);
@@ -246,14 +230,6 @@ real_get_generic_capabilities (NMDevice *dev)
const char *
-nm_device_get_dbus_path (NMDevice *self)
-{
- g_return_val_if_fail (self != NULL, NULL);
-
- return self->priv->dbus_path;
-}
-
-const char *
nm_device_get_udi (NMDevice *self)
{
g_return_val_if_fail (self != NULL, NULL);
@@ -261,14 +237,6 @@ nm_device_get_udi (NMDevice *self)
return self->priv->udi;
}
-guint32
-nm_device_get_index (NMDevice *self)
-{
- g_return_val_if_fail (self != NULL, G_MAXUINT32);
-
- return self->priv->index;
-}
-
/*
* Get/set functions for iface
*/
@@ -1595,8 +1563,9 @@ set_property (GObject *object, guint prop_id,
/* construct-only */
priv->udi = g_strdup (g_value_get_string (value));
break;
- case NM_DEVICE_INTERFACE_PROP_INDEX:
- priv->index = g_value_get_uint (value);
+ case NM_DEVICE_INTERFACE_PROP_IFACE:
+ g_free (priv->iface);
+ priv->iface = g_value_dup_string (value);
break;
case NM_DEVICE_INTERFACE_PROP_DRIVER:
priv->driver = g_strdup (g_value_get_string (value));
@@ -1623,9 +1592,6 @@ get_property (GObject *object, guint prop_id,
case NM_DEVICE_INTERFACE_PROP_UDI:
g_value_set_string (value, priv->udi);
break;
- case NM_DEVICE_INTERFACE_PROP_INDEX:
- g_value_set_uint (value, priv->index);
- break;
case NM_DEVICE_INTERFACE_PROP_IFACE:
g_value_set_string (value, priv->iface);
break;
@@ -1688,10 +1654,6 @@ nm_device_class_init (NMDeviceClass *klass)
NM_DEVICE_INTERFACE_UDI);
g_object_class_override_property (object_class,
- NM_DEVICE_INTERFACE_PROP_INDEX,
- NM_DEVICE_INTERFACE_INDEX);
-
- g_object_class_override_property (object_class,
NM_DEVICE_INTERFACE_PROP_IFACE,
NM_DEVICE_INTERFACE_IFACE);
diff --git a/src/nm-device.h b/src/nm-device.h
index ea2b735b5c..4ed69eea14 100644
--- a/src/nm-device.h
+++ b/src/nm-device.h
@@ -118,9 +118,7 @@ struct _NMDeviceClass
GType nm_device_get_type (void);
-const char * nm_device_get_dbus_path (NMDevice *dev);
const char * nm_device_get_udi (NMDevice *dev);
-guint32 nm_device_get_index (NMDevice *dev);
const char * nm_device_get_iface (NMDevice *dev);
const char * nm_device_get_driver (NMDevice *dev);
diff --git a/src/nm-hal-manager.c b/src/nm-hal-manager.c
index 3f63c62f1a..03def21262 100644
--- a/src/nm-hal-manager.c
+++ b/src/nm-hal-manager.c
@@ -12,6 +12,7 @@
#include "nm-utils.h"
#include "nm-device-802-11-wireless.h"
#include "nm-device-802-3-ethernet.h"
+#include "nm-umts-device.h"
/* Killswitch poll frequency in seconds */
#define NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY 6
@@ -33,15 +34,16 @@ struct _NMHalManager {
/* Device creators */
typedef NMDevice *(*NMDeviceCreatorFn) (NMHalManager *manager,
- const char *udi);
+ const char *udi);
typedef struct {
+ char *device_type_name;
char *capability_str;
gboolean (*is_device_fn) (NMHalManager *manager, const char *udi);
NMDeviceCreatorFn creator_fn;
} DeviceCreator;
-static NMDeviceCreatorFn
+static DeviceCreator *
get_creator (NMHalManager *manager, const char *udi)
{
DeviceCreator *creator;
@@ -51,7 +53,7 @@ get_creator (NMHalManager *manager, const char *udi)
creator = (DeviceCreator *) iter->data;
if (creator->is_device_fn (manager, udi))
- return creator->creator_fn;
+ return creator;
}
return NULL;
@@ -61,24 +63,6 @@ get_creator (NMHalManager *manager, const char *udi)
/* Common helpers for built-in device creators */
-static int
-get_device_index_from_hal (LibHalContext *ctx, const char *udi)
-{
- int idx = -1;
-
- if (libhal_device_property_exists (ctx, udi, "net.linux.ifindex", NULL) &&
- libhal_device_property_exists (ctx, udi, "info.category", NULL)) {
-
- char *category = libhal_device_get_property_string (ctx, udi, "info.category", NULL);
- if (category && (!strcmp (category, "net.80203") || !strcmp (category, "net.80211"))) {
- idx = libhal_device_get_property_int (ctx, udi, "net.linux.ifindex", NULL);
- }
- libhal_free_string (category);
- }
-
- return idx;
-}
-
static char *
nm_get_device_driver_name (LibHalContext *ctx, const char *udi)
{
@@ -89,7 +73,7 @@ nm_get_device_driver_name (LibHalContext *ctx, const char *udi)
if (physdev_udi && libhal_device_property_exists (ctx, physdev_udi, "info.linux.driver", NULL)) {
char *drv = libhal_device_get_property_string (ctx, physdev_udi, "info.linux.driver", NULL);
driver_name = g_strdup (drv);
- g_free (drv);
+ libhal_free_string (drv);
}
libhal_free_string (physdev_udi);
@@ -121,17 +105,19 @@ static NMDevice *
wired_device_creator (NMHalManager *manager, const char *udi)
{
NMDevice *device;
- int idx;
+ char *iface;
char *driver;
- idx = get_device_index_from_hal (manager->hal_ctx, udi);
- if (idx < 0) {
- nm_warning ("Couldn't get interface index for %s, ignoring.", udi);
+ iface = libhal_device_get_property_string (manager->hal_ctx, udi, "net.interface", NULL);
+ if (!iface) {
+ nm_warning ("Couldn't get interface for %s, ignoring.", udi);
return NULL;
}
driver = nm_get_device_driver_name (manager->hal_ctx, udi);
- device = (NMDevice *) nm_device_802_3_ethernet_new (idx, udi, driver, FALSE);
+ device = (NMDevice *) nm_device_802_3_ethernet_new (udi, iface, driver);
+
+ libhal_free_string (iface);
g_free (driver);
return device;
@@ -162,22 +148,70 @@ static NMDevice *
wireless_device_creator (NMHalManager *manager, const char *udi)
{
NMDevice *device;
- int idx;
+ char *iface;
char *driver;
- idx = get_device_index_from_hal (manager->hal_ctx, udi);
- if (idx < 0) {
- nm_warning ("Couldn't get interface index for %s, ignoring.", udi);
+ iface = libhal_device_get_property_string (manager->hal_ctx, udi, "net.interface", NULL);
+ if (!iface) {
+ nm_warning ("Couldn't get interface for %s, ignoring.", udi);
return NULL;
}
driver = nm_get_device_driver_name (manager->hal_ctx, udi);
- device = (NMDevice *) nm_device_802_11_wireless_new (idx, udi, driver, FALSE);
+ device = (NMDevice *) nm_device_802_11_wireless_new (udi, iface, driver);
+
+ libhal_free_string (iface);
g_free (driver);
return device;
}
+/* Modem device creator */
+
+static gboolean
+is_modem_device (NMHalManager *manager, const char *udi)
+{
+ gboolean is_modem = FALSE;
+
+ if (libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) {
+ char *category;
+
+ category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL);
+ if (category) {
+ is_modem = strcmp (category, "serial") == 0;
+ libhal_free_string (category);
+ }
+ }
+
+ return is_modem;
+}
+
+NMDevice *
+modem_device_creator (NMHalManager *manager, const char *udi)
+{
+ char *serial_device;
+ char *parent_udi;
+ char *driver_name = NULL;
+ NMDevice *device = NULL;
+
+ serial_device = libhal_device_get_property_string (manager->hal_ctx, udi, "serial.device", NULL);
+
+ /* Get the driver */
+ parent_udi = libhal_device_get_property_string (manager->hal_ctx, udi, "info.parent", NULL);
+ if (parent_udi) {
+ driver_name = libhal_device_get_property_string (manager->hal_ctx, parent_udi, "info.linux.driver", NULL);
+ libhal_free_string (parent_udi);
+ }
+
+ if (serial_device && driver_name)
+ device = (NMDevice *) nm_umts_device_new (udi, serial_device + strlen ("/dev/"), driver_name);
+
+ libhal_free_string (serial_device);
+ libhal_free_string (driver_name);
+
+ return device;
+}
+
static void
register_built_in_creators (NMHalManager *manager)
{
@@ -185,6 +219,7 @@ register_built_in_creators (NMHalManager *manager)
/* Wired device */
creator = g_slice_new0 (DeviceCreator);
+ creator->device_type_name = g_strdup ("wired Ethernet (802.3)");
creator->capability_str = g_strdup ("net");
creator->is_device_fn = is_wired_device;
creator->creator_fn = wired_device_creator;
@@ -192,16 +227,25 @@ register_built_in_creators (NMHalManager *manager)
/* Wireless device */
creator = g_slice_new0 (DeviceCreator);
+ creator->device_type_name = g_strdup ("wireless (802.11)");
creator->capability_str = g_strdup ("net");
creator->is_device_fn = is_wireless_device;
creator->creator_fn = wireless_device_creator;
manager->device_creators = g_slist_append (manager->device_creators, creator);
+
+ /* Modem */
+ creator = g_slice_new0 (DeviceCreator);
+ creator->device_type_name = g_strdup ("UMTS (GSM)");
+ creator->capability_str = g_strdup ("modem");
+ creator->is_device_fn = is_modem_device;
+ creator->creator_fn = modem_device_creator;
+ manager->device_creators = g_slist_append (manager->device_creators, creator);
}
static NMDevice *
create_device_and_add_to_list (NMHalManager *manager,
- NMDeviceCreatorFn creator_fn,
- const char *udi)
+ DeviceCreator *creator,
+ const char *udi)
{
NMDevice *dev = NULL;
char *usb_test = NULL;
@@ -218,11 +262,11 @@ create_device_and_add_to_list (NMHalManager *manager,
return NULL;
}
- dev = creator_fn (manager, udi);
+ dev = creator->creator_fn (manager, udi);
if (dev) {
- nm_info ("Now managing %s device '%s'.",
- NM_IS_DEVICE_802_11_WIRELESS (dev) ? "wireless (802.11)" : "wired Ethernet (802.3)",
- nm_device_get_iface (dev));
+ nm_info ("Now managing %s device '%s'.",
+ creator->device_type_name,
+ nm_device_get_iface (dev));
nm_manager_add_device (manager->nm_manager, dev);
g_object_unref (dev);
@@ -235,7 +279,7 @@ static void
device_added (LibHalContext *ctx, const char *udi)
{
NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx);
- NMDeviceCreatorFn creator_fn;
+ DeviceCreator *creator;
// nm_debug ("New device added (hal udi is '%s').", udi );
@@ -249,9 +293,9 @@ device_added (LibHalContext *ctx, const char *udi)
* so this call will fail, and it will actually be added when hal sets the device's
* capabilities a bit later on.
*/
- creator_fn = get_creator (manager, udi);
- if (creator_fn)
- create_device_and_add_to_list (manager, creator_fn, udi);
+ creator = get_creator (manager, udi);
+ if (creator)
+ create_device_and_add_to_list (manager, creator, udi);
}
static void
@@ -270,7 +314,7 @@ static void
device_new_capability (LibHalContext *ctx, const char *udi, const char *capability)
{
NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx);
- NMDeviceCreatorFn creator_fn;
+ DeviceCreator *creator;
/*nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );*/
@@ -280,9 +324,9 @@ device_new_capability (LibHalContext *ctx, const char *udi, const char *capabili
if (nm_manager_get_state (manager->nm_manager) == NM_STATE_ASLEEP)
return;
- creator_fn = get_creator (manager, udi);
- if (creator_fn)
- create_device_and_add_to_list (manager, creator_fn, udi);
+ creator = get_creator (manager, udi);
+ if (creator)
+ create_device_and_add_to_list (manager, creator, udi);
}
static void
@@ -312,7 +356,7 @@ add_initial_devices (NMHalManager *manager)
if (devices) {
for (i = 0; i < num_devices; i++) {
if (creator->is_device_fn (manager, devices[i]))
- create_device_and_add_to_list (manager, creator->creator_fn, devices[i]);
+ create_device_and_add_to_list (manager, creator, devices[i]);
}
}
@@ -671,7 +715,10 @@ nm_hal_manager_new (NMManager *nm_manager)
static void
destroy_creator (gpointer data, gpointer user_data)
{
- g_free (((DeviceCreator *) data)->capability_str);
+ DeviceCreator *creator = (DeviceCreator *) data;
+
+ g_free (creator->device_type_name);
+ g_free (creator->capability_str);
g_slice_free (DeviceCreator, data);
}
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 5744b4deca..b28bc03eef 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1062,7 +1062,7 @@ impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
*devices = g_ptr_array_sized_new (g_slist_length (priv->devices));
for (iter = priv->devices; iter; iter = iter->next)
- g_ptr_array_add (*devices, g_strdup (nm_device_get_dbus_path (NM_DEVICE (iter->data))));
+ g_ptr_array_add (*devices, g_strdup (nm_device_get_udi (NM_DEVICE (iter->data))));
return TRUE;
}
@@ -1078,7 +1078,7 @@ nm_manager_get_device_by_path (NMManager *manager, const char *path)
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
NMDevice *device = NM_DEVICE (iter->data);
- if (!strcmp (nm_device_get_dbus_path (device), path))
+ if (!strcmp (nm_device_get_udi (device), path))
return device;
}
@@ -1377,7 +1377,7 @@ add_one_connection_element (NMManager *manager,
dev_array = g_ptr_array_sized_new (1);
if (!dev_array)
return NULL;
- g_ptr_array_add (dev_array, g_strdup (nm_device_get_dbus_path (device)));
+ g_ptr_array_add (dev_array, g_strdup (nm_device_get_udi (device)));
g_value_init (&entry, type);
g_value_take_boxed (&entry, dbus_g_type_specialized_construct (type));
diff --git a/src/nm-serial-device.c b/src/nm-serial-device.c
new file mode 100644
index 0000000000..9fcc9b53dd
--- /dev/null
+++ b/src/nm-serial-device.c
@@ -0,0 +1,869 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#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 <glib.h>
+
+#include "nm-serial-device.h"
+#include "nm-device-private.h"
+#include "ppp-manager/nm-ppp-manager.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-ppp.h"
+#include "nm-utils.h"
+
+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;
+ struct termios old_t;
+} NMSerialDevicePrivate;
+
+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 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;
+}
+
+static gboolean
+config_fd (NMSerialDevice *device)
+{
+ NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
+ NMSettingSerial *setting;
+ struct termio stbuf;
+ int speed;
+ int bits;
+ int parity;
+ int stopbits;
+
+ setting = NM_SETTING_SERIAL (serial_device_get_setting (device, NM_TYPE_SETTING_SERIAL));
+
+ speed = parse_baudrate (setting->baud);
+ bits = parse_bits (setting->bits);
+ parity = parse_parity (setting->parity);
+ stopbits = parse_stopbits (setting->stopbits);
+
+ 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) {
+ g_warning ("Can not control device");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+nm_serial_device_open (NMSerialDevice *device)
+{
+ NMSerialDevicePrivate *priv;
+ const char *iface;
+ char *path;
+
+ g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE);
+
+ priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
+ iface = nm_device_get_iface (NM_DEVICE (device));
+
+ nm_debug ("Opening device '%s'", 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 ("Can not open device '%s'", iface);
+ return FALSE;
+ }
+
+ if (ioctl (priv->fd, TCGETA, &priv->old_t) < 0) {
+ nm_warning ("Can not control device '%s'", iface);
+ close (priv->fd);
+ return FALSE;
+ }
+
+ config_fd (device);
+
+ 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->fd) {
+ nm_debug ("Closing device '%s'", nm_device_get_iface (NM_DEVICE (device)));
+
+ g_io_channel_unref (priv->channel);
+ 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;
+ ssize_t status;
+
+ 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));
+
+ g_print ("Sending: ");
+ for (i = 0; i < command->len; i++)
+ g_print ("%c", command->data[i]);
+ g_print ("\n");
+
+ for (i = 0; i < command->len; i++) {
+ again:
+ status = write (fd, command->data + i, 1);
+
+ if (status < 0) {
+ if (errno == EAGAIN)
+ goto again;
+
+ g_warning ("Error in writing");
+ return FALSE;
+ }
+
+ if (setting->send_delay)
+ usleep (setting->send_delay);
+ }
+
+ 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\n", 2);
+
+ ret = nm_serial_device_send_command (device, command);
+ g_byte_array_free (command, TRUE);
+
+ return ret;
+}
+
+typedef struct {
+ NMSerialDevice *device;
+ char *terminators;
+ GString *result;
+ NMSerialGetReplyFn callback;
+ gpointer user_data;
+ guint timeout_id;
+ guint got_data_id;
+} GetReplyInfo;
+
+static void
+get_reply_info_destroy (gpointer data)
+{
+ GetReplyInfo *info = (GetReplyInfo *) data;
+
+ if (info->got_data_id)
+ g_source_remove (info->got_data_id);
+
+ g_free (info->terminators);
+
+ if (info->result)
+ g_string_free (info->result, TRUE);
+
+ g_free (info);
+}
+
+static gboolean
+get_reply_timeout (gpointer data)
+{
+ GetReplyInfo *info = (GetReplyInfo *) data;
+
+ info->callback (info->device, NULL, info->user_data);
+
+ return FALSE;
+}
+
+static gboolean
+get_reply_got_data (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ GetReplyInfo *info = (GetReplyInfo *) data;
+ gsize bytes_read;
+ char buf[4096];
+ GIOStatus status;
+ gboolean done = FALSE;
+ int i;
+
+ if (condition & G_IO_IN) {
+ do {
+ GError *err = NULL;
+
+ status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, &err);
+
+ if (status == G_IO_STATUS_ERROR) {
+ g_warning ("%s", err->message);
+ g_error_free (err);
+ err = NULL;
+ }
+
+ if (bytes_read > 0) {
+ char *p;
+
+ g_print ("Got: ");
+ for (i = 0; i < bytes_read; i++)
+ g_print ("%c", buf[i]);
+ g_print ("\n");
+
+ p = &buf[0];
+ for (i = 0; i < bytes_read && !done; i++, p++) {
+ int j;
+
+ for (j = 0; j < strlen (info->terminators); j++)
+ if (*p == info->terminators[j])
+ done = TRUE;
+
+ if (!done)
+ g_string_append_c (info->result, *p);
+ }
+ }
+ } while (!done || bytes_read == 4096 || status == G_IO_STATUS_AGAIN);
+ }
+
+ if (condition & G_IO_HUP || condition & G_IO_ERR) {
+ g_string_free (info->result, TRUE);
+ info->result = NULL;
+ done = TRUE;
+ }
+
+ if (done) {
+ char *result = info->result ? g_string_free (info->result, FALSE) : NULL;
+ info->result = NULL;
+ info->callback (info->device, result, info->user_data);
+ g_free (result);
+
+ /* Clear the id - returning FALSE already removes it */
+ info->got_data_id = 0;
+ g_source_remove (info->timeout_id);
+ }
+
+ return !done;
+}
+
+void
+nm_serial_device_get_reply (NMSerialDevice *device,
+ guint timeout,
+ const char *terminators,
+ NMSerialGetReplyFn callback,
+ gpointer user_data)
+{
+ GetReplyInfo *info;
+
+ g_return_if_fail (NM_IS_SERIAL_DEVICE (device));
+ g_return_if_fail (terminators != NULL);
+ g_return_if_fail (callback != NULL);
+
+ info = g_new (GetReplyInfo, 1);
+ info->device = device;
+ info->terminators = g_strdup (terminators);
+ info->result = g_string_new (NULL);
+ info->callback = callback;
+ info->user_data = user_data;
+
+ info->got_data_id = g_io_add_watch (NM_SERIAL_DEVICE_GET_PRIVATE (device)->channel,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ get_reply_got_data,
+ info);
+
+ info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ timeout * 1000,
+ get_reply_timeout,
+ info,
+ get_reply_info_destroy);
+}
+
+typedef struct {
+ NMSerialDevice *device;
+ char **str_needles;
+ NMSerialWaitForReplyFn callback;
+ gpointer user_data;
+ guint timeout_id;
+ guint got_data_id;
+} WaitForReplyInfo;
+
+static void
+wait_for_reply_info_destroy (gpointer data)
+{
+ WaitForReplyInfo *info = (WaitForReplyInfo *) data;
+
+ if (info->got_data_id)
+ g_source_remove (info->got_data_id);
+
+ g_strfreev (info->str_needles);
+ g_free (info);
+}
+
+static gboolean
+wait_for_reply_timeout (gpointer data)
+{
+ WaitForReplyInfo *info = (WaitForReplyInfo *) data;
+
+ info->callback (info->device, -1, info->user_data);
+
+ return FALSE;
+}
+
+static gboolean
+wait_for_reply_got_data (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ WaitForReplyInfo *info = (WaitForReplyInfo *) data;
+ gsize bytes_read;
+ char buf[4096];
+ GIOStatus status;
+ gboolean done = FALSE;
+ int index = -1;
+ int i;
+
+ if (condition & G_IO_IN) {
+ do {
+ GError *err = NULL;
+
+ status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, &err);
+
+ if (status == G_IO_STATUS_ERROR) {
+ g_warning ("%s", err->message);
+ g_error_free (err);
+ err = NULL;
+ }
+
+ if (bytes_read > 0) {
+ g_print ("Got: ");
+ for (i = 0; i < bytes_read; i++)
+ g_print ("%c", buf[i]);
+ g_print ("\n");
+
+ for (i = 0; info->str_needles[i]; i++) {
+ if (strcasestr (buf, info->str_needles[i])) {
+ index = i;
+ done = TRUE;
+ }
+ }
+ }
+ } while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN);
+ }
+
+ if (condition & G_IO_HUP || condition & G_IO_ERR)
+ done = TRUE;
+
+ if (done) {
+ info->callback (info->device, index, info->user_data);
+
+ /* Clear the id - returning FALSE already removes it */
+ info->got_data_id = 0;
+ g_source_remove (info->timeout_id);
+ }
+
+ return !done;
+}
+
+void
+nm_serial_device_wait_for_reply (NMSerialDevice *device,
+ guint timeout,
+ char **responses,
+ NMSerialWaitForReplyFn callback,
+ gpointer user_data)
+{
+ WaitForReplyInfo *info;
+ char **str_array;
+ int i;
+
+ g_return_if_fail (NM_IS_SERIAL_DEVICE (device));
+ g_return_if_fail (responses != NULL);
+ g_return_if_fail (callback != NULL);
+
+ /* Copy the array */
+ str_array = g_new (char*, g_strv_length (responses) + 1);
+ i = 0;
+ while (responses[i]) {
+ str_array[i] = g_strdup (responses[i]);
+ i++;
+ }
+ str_array[i] = NULL;
+
+ info = g_new (WaitForReplyInfo, 1);
+ info->device = device;
+ info->str_needles = str_array;
+ info->callback = callback;
+ info->user_data = user_data;
+
+ info->got_data_id = g_io_add_watch (NM_SERIAL_DEVICE_GET_PRIVATE (device)->channel,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ wait_for_reply_got_data,
+ info);
+
+ info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ timeout * 1000,
+ wait_for_reply_timeout,
+ info,
+ wait_for_reply_info_destroy);
+}
+
+#if 0
+typedef struct {
+ NMSerialDevice *device;
+ gboolean timed_out;
+ NMSerialWaitQuietFn callback;
+ gpointer user_data;
+} WaitQuietInfo;
+
+static gboolean
+wait_quiet_done (gpointer data)
+{
+ WaitQuietInfo *info = (WaitQuietInfo *) data;
+
+ info->callback (info->device, info->timed_out, info->user_data);
+
+ return FALSE;
+}
+
+static gboolean
+wait_quiet_quiettime (gpointer data)
+{
+ WaitQuietInfo *info = (WaitQuietInfo *) data;
+
+ info->timed_out = FALSE;
+ wait_quiet_done (data);
+
+ 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_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);
+ }
+
+ if (condition & G_IO_HUP || condition & G_IO_ERR) {
+ wait_quiet_done (data);
+ return FALSE
+ }
+
+ 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_new (WaitQuietInfo, 1);
+
+ info->device = device;
+ info->timed_out = TRUE;
+ info->callback = callback;
+ info->user_data = user_data;
+
+ info->got_data_id = g_io_add_watch (NM_SERIAL_DEVICE_GET_PRIVATE (device)->channel,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ wait_quiet_got_data,
+ info);
+
+ info->quiet_id = g_timeout_add (quiet_time,
+ wait_quiet_timeout,
+ info);
+
+ info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ timeout,
+ wait_quiet_timeout,
+ info,
+ wait_quiet_info_destroy);
+}
+
+typedef struct {
+ NMSerialDevice *device;
+ int current_speed;
+ NMSerialFlashFn callback;
+ gpointer user_data;
+} FlashInfo;
+
+static gboolean
+flash_done (gpointer user_data)
+{
+ FlashInfo *info = (FlashInfo *) user_data;
+
+ /* FIXME: Restore the speed */
+ info->current_speed;
+
+ info->callback (info->device, info->user_data);
+
+ return FALSE;
+}
+
+void
+nm_serial_device_flash (NMSerialDevice *device,
+ guint32 flash_time,
+ NMSerialFlashFn callback,
+ gpointer user_data)
+{
+ int fd;
+ struct termio stbuf;
+ int speed;
+ FlashInfo *info;
+
+ g_return_if_fail (NM_IS_SERIAL_DEVICE (device));
+ g_return_if_fail (callback != NULL);
+
+ fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
+
+ ioctl (fd, TCGETA, &stbuf);
+ speed = stbuf.c_cflags & CBAUD;
+
+ /* FIXME: Set speed to 0 */
+
+ info = g_new (FlashInfo, 1);
+ info->device = device;
+ info->current_speed = speed;
+ info->callback = callback;
+ info->user_data = user_data;
+
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ flash_time,
+ flash_done,
+ info,
+ g_free);
+}
+
+#endif
+
+static void
+ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
+{
+ nm_debug ("ppp state changed: %d", status);
+ /* FIXME */
+}
+
+static void
+ppp_ip4_config (NMPPPManager *ppp_manager,
+ const char *iface,
+ NMIP4Config *config,
+ gpointer user_data)
+{
+ nm_debug ("got ipconfig from pppd: %s", iface);
+ /* FIXME */
+
+ nm_device_state_changed (NM_DEVICE (user_data), NM_DEVICE_STATE_ACTIVATED);
+}
+
+static NMActStageReturn
+real_act_stage2_config (NMDevice *device)
+{
+ NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
+ NMSettingPPP *setting;
+ GError *err = NULL;
+ NMActStageReturn ret;
+
+ setting = NM_SETTING_PPP (serial_device_get_setting (NM_SERIAL_DEVICE (device), NM_TYPE_SETTING_PPP));
+
+ priv->ppp_manager = nm_ppp_manager_new ();
+
+ if (nm_ppp_manager_start (priv->ppp_manager,
+ nm_device_get_iface (device),
+ setting,
+ &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);
+ 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;
+
+ ret = NM_ACT_STAGE_RETURN_FAILURE;
+ }
+
+ return ret;
+}
+
+static void
+real_deactivate_quickly (NMDevice *device)
+{
+ NMSerialDevice *self = NM_SERIAL_DEVICE (device);
+ NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
+
+ if (priv->ppp_manager) {
+ g_object_unref (priv->ppp_manager);
+ priv->ppp_manager = NULL;
+ }
+
+ nm_serial_device_close (self);
+}
+
+static gboolean
+real_check_connection (NMDevice *dev, NMConnection *connection)
+{
+ NMSettingSerial *serial;
+ NMSettingPPP *ppp;
+
+ serial = (NMSettingSerial *) nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL);
+ if (!serial) {
+ nm_warning ("Connection check failed: serial setting not present.");
+ return FALSE;
+ }
+
+ ppp = (NMSettingPPP *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP);
+ if (!ppp) {
+ nm_warning ("Connection check failed: ppp setting not present.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+static void
+nm_serial_device_init (NMSerialDevice *self)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSerialDevice *self = NM_SERIAL_DEVICE (object);
+
+ 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->check_connection = real_check_connection;
+ parent_class->act_stage2_config = real_act_stage2_config;
+ parent_class->deactivate_quickly = real_deactivate_quickly;
+}
diff --git a/src/nm-serial-device.h b/src/nm-serial-device.h
new file mode 100644
index 0000000000..b32f8fefbf
--- /dev/null
+++ b/src/nm-serial-device.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#ifndef NM_SERIAL_DEVICE_H
+#define NM_SERIAL_DEVICE_H
+
+#include <nm-device.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;
+} 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,
+ 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);
+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);
+
+void nm_serial_device_get_reply (NMSerialDevice *device,
+ guint timeout,
+ const char *terminators,
+ NMSerialGetReplyFn callback,
+ gpointer user_data);
+
+void nm_serial_device_wait_for_reply (NMSerialDevice *device,
+ guint timeout,
+ char **responses,
+ NMSerialWaitForReplyFn callback,
+ gpointer user_data);
+
+void nm_serial_device_wait_quiet (NMSerialDevice *device,
+ guint timeout,
+ guint quiet_time,
+ NMSerialWaitQuietFn callback,
+ gpointer user_data);
+
+void nm_serial_device_flash (NMSerialDevice *device,
+ guint32 flash_time,
+ NMSerialFlashFn callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* NM_SERIAL_DEVICE_H */
diff --git a/src/nm-umts-device.c b/src/nm-umts-device.c
new file mode 100644
index 0000000000..de0f77f6db
--- /dev/null
+++ b/src/nm-umts-device.c
@@ -0,0 +1,364 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include "nm-umts-device.h"
+#include "nm-device-interface.h"
+#include "nm-device-private.h"
+#include "nm-setting-umts.h"
+#include "nm-utils.h"
+
+G_DEFINE_TYPE (NMUmtsDevice, nm_umts_device, NM_TYPE_SERIAL_DEVICE)
+
+NMUmtsDevice *
+nm_umts_device_new (const char *udi,
+ const char *iface,
+ const char *driver)
+{
+ g_return_val_if_fail (udi != NULL, NULL);
+ g_return_val_if_fail (iface != NULL, NULL);
+ g_return_val_if_fail (driver != NULL, NULL);
+
+ return (NMUmtsDevice *) g_object_new (NM_TYPE_UMTS_DEVICE,
+ NM_DEVICE_INTERFACE_UDI, udi,
+ NM_DEVICE_INTERFACE_IFACE, iface,
+ NM_DEVICE_INTERFACE_DRIVER, driver,
+ NULL);
+}
+
+static NMSetting *
+umts_device_get_setting (NMUmtsDevice *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,
+ gpointer user_data)
+{
+ gboolean success = FALSE;
+
+ switch (reply_index) {
+ case 0:
+ nm_info ("Connected, Woo!");
+ success = TRUE;
+ break;
+ case 1:
+ nm_info ("Busy");
+ break;
+ case 2:
+ nm_warning ("No dial tone");
+ break;
+ case 3:
+ nm_warning ("No carrier");
+ break;
+ case -1:
+ nm_warning ("Manual registration timed out");
+ break;
+ default:
+ nm_warning ("Manual registration 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);
+}
+
+static void
+do_dial (NMSerialDevice *device)
+{
+ NMSettingUmts *setting;
+ char *command;
+ char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
+
+ setting = NM_SETTING_UMTS (umts_device_get_setting (NM_UMTS_DEVICE (device), NM_TYPE_SETTING_UMTS));
+
+ command = g_strconcat ("ATDT", setting->number, NULL);
+ nm_serial_device_send_command_string (device, command);
+ g_free (command);
+
+ nm_serial_device_wait_for_reply (device, 60, responses, dial_done, NULL);
+}
+
+static void
+manual_registration_done (NMSerialDevice *device,
+ int reply_index,
+ gpointer user_data)
+{
+ switch (reply_index) {
+ case 0:
+ do_dial (device);
+ break;
+ case -1:
+ nm_warning ("Manual registration timed out");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ default:
+ nm_warning ("Manual registration failed");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ }
+}
+
+static void
+manual_registration (NMSerialDevice *device)
+{
+ NMSettingUmts *setting;
+ char *command;
+ char *responses[] = { "OK", "ERROR", "ERR", NULL };
+
+ setting = NM_SETTING_UMTS (umts_device_get_setting (NM_UMTS_DEVICE (device), NM_TYPE_SETTING_UMTS));
+
+ command = g_strdup_printf ("AT+COPS=1,2,\"%s\"", setting->network_id);
+ nm_serial_device_send_command_string (device, command);
+ g_free (command);
+
+ nm_serial_device_wait_for_reply (device, 30, responses, manual_registration_done, NULL);
+}
+
+static void
+get_network_done (NMSerialDevice *device,
+ const char *response,
+ gpointer user_data)
+{
+ if (response)
+ nm_info ("Associated with network: %s\n", response);
+ else
+ nm_warning ("Couldn't read active network name");
+
+ do_dial (device);
+}
+
+static void
+automatic_registration_get_network (NMSerialDevice *device)
+{
+ char terminators[] = { '\r', '\n', NULL };
+
+ nm_serial_device_send_command_string (device, "AT+COPS?");
+ nm_serial_device_get_reply (device, 10, terminators, get_network_done, NULL);
+}
+
+static void
+automatic_registration_response (NMSerialDevice *device,
+ int reply_index,
+ gpointer user_data)
+{
+ switch (reply_index) {
+ case 0:
+ nm_info ("Registered on Home network");
+ automatic_registration_get_network (device);
+ break;
+ case 1:
+ nm_info ("Registered on Roaming network");
+ automatic_registration_get_network (device);
+ break;
+ case -1:
+ nm_warning ("Automatic registration timed out");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ default:
+ nm_warning ("Automatic registration failed");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ }
+}
+
+static void
+automatic_registration (NMSerialDevice *device)
+{
+ char *responses[] = { "+CREG: 0,1", "+CREG: 0,5", NULL };
+
+ nm_serial_device_send_command_string (device, "AT+CREG?");
+ nm_serial_device_wait_for_reply (device, 60, responses, automatic_registration_response, NULL);
+}
+
+static void
+do_register (NMSerialDevice *device)
+{
+ NMSettingUmts *setting;
+
+ setting = NM_SETTING_UMTS (umts_device_get_setting (NM_UMTS_DEVICE (device), NM_TYPE_SETTING_UMTS));
+
+ if (setting->network_id)
+ manual_registration (device);
+ else
+ automatic_registration (device);
+}
+
+static void
+enter_pin_done (NMSerialDevice *device,
+ int reply_index,
+ gpointer user_data)
+{
+ switch (reply_index) {
+ case 0:
+ do_register (device);
+ break;
+ case -1:
+ nm_warning ("Did not receive response for entered PIN");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ default:
+ nm_warning ("Invalid PIN");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ }
+}
+
+static void
+enter_pin (NMSerialDevice *device)
+{
+ NMSettingUmts *setting;
+ char *command;
+ char *responses[] = { "OK", "ERROR", "ERR", NULL };
+
+ setting = NM_SETTING_UMTS (umts_device_get_setting (NM_UMTS_DEVICE (device), NM_TYPE_SETTING_UMTS));
+
+ if (!setting->pin) {
+ /* FIXME: Ask PIN */
+ nm_warning ("PIN required but not provided");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ return;
+ }
+
+ command = g_strdup_printf ("AT+CPIN=\"%s\"", setting->pin);
+ nm_serial_device_send_command_string (device, command);
+ g_free (command);
+
+ nm_serial_device_wait_for_reply (device, 3, responses, enter_pin_done, NULL);
+}
+
+static void
+enter_puk (NMSerialDevice *device)
+{
+ /* FIXME */
+ nm_warning ("PUK entering not implemented at the moment");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+}
+
+static void
+check_pin_done (NMSerialDevice *device,
+ int reply_index,
+ gpointer user_data)
+{
+ switch (reply_index) {
+ case 0:
+ do_register (device);
+ break;
+ case 1:
+ enter_pin (device);
+ break;
+ case 2:
+ enter_puk (device);
+ break;
+ case -1:
+ nm_warning ("PIN checking timed out");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ default:
+ nm_warning ("PIN checking failed");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ return;
+ }
+}
+
+static void
+check_pin (NMSerialDevice *device)
+{
+ char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
+
+ nm_serial_device_send_command_string (device, "AT+CPIN?");
+ nm_serial_device_wait_for_reply (device, 3, responses, check_pin_done, NULL);
+}
+
+static void
+init_done (NMSerialDevice *device,
+ int reply_index,
+ gpointer user_data)
+{
+ switch (reply_index) {
+ case 0:
+ check_pin (device);
+ break;
+ case -1:
+ nm_warning ("Modem initialization timed out");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ break;
+ default:
+ nm_warning ("Modem initialization failed");
+ nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
+ return;
+ }
+}
+
+static NMActStageReturn
+real_act_stage1_prepare (NMDevice *device)
+{
+ NMSerialDevice *serial_device = NM_SERIAL_DEVICE (device);
+ char *responses[] = { "OK", "ERR", NULL };
+
+ if (!nm_serial_device_open (NM_SERIAL_DEVICE (device)))
+ return NM_ACT_STAGE_RETURN_FAILURE;
+
+ nm_serial_device_send_command_string (serial_device, "ATZ");
+ nm_serial_device_wait_for_reply (serial_device, 3, responses, init_done, NULL);
+
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+}
+
+static guint32
+real_get_generic_capabilities (NMDevice *dev)
+{
+ return NM_DEVICE_CAP_NM_SUPPORTED;
+}
+
+static gboolean
+real_check_connection (NMDevice *dev, NMConnection *connection)
+{
+ NMSettingUmts *umts;
+
+ umts = (NMSettingUmts *) nm_connection_get_setting (connection, NM_TYPE_SETTING_UMTS);
+ if (!umts) {
+ nm_warning ("Connection check failed: umts setting not present.");
+ return FALSE;
+ }
+
+ if (!umts->number) {
+ nm_warning ("Connection check failed: Phone number not set.");
+ return FALSE;
+ }
+
+ return NM_DEVICE_CLASS (nm_umts_device_parent_class)->check_connection (dev, connection);
+}
+
+/*****************************************************************************/
+
+static void
+nm_umts_device_init (NMUmtsDevice *self)
+{
+ nm_device_set_device_type (NM_DEVICE (self), DEVICE_TYPE_UMTS);
+}
+
+static void
+nm_umts_device_class_init (NMUmtsDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+
+ device_class->get_generic_capabilities = real_get_generic_capabilities;
+ device_class->check_connection = real_check_connection;
+ device_class->act_stage1_prepare = real_act_stage1_prepare;
+}
diff --git a/src/nm-umts-device.h b/src/nm-umts-device.h
new file mode 100644
index 0000000000..2cfa921f2a
--- /dev/null
+++ b/src/nm-umts-device.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#ifndef NM_UMTS_DEVICE_H
+#define NM_UMTS_DEVICE_H
+
+#include <nm-serial-device.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_UMTS_DEVICE (nm_umts_device_get_type ())
+#define NM_UMTS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_UMTS_DEVICE, NMUmtsDevice))
+#define NM_UMTS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_UMTS_DEVICE, NMUmtsDeviceClass))
+#define NM_IS_UMTS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_UMTS_DEVICE))
+#define NM_IS_UMTS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_UMTS_DEVICE))
+#define NM_UMTS_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_UMTS_DEVICE, NMUmtsDeviceClass))
+
+typedef struct {
+ NMSerialDevice parent;
+} NMUmtsDevice;
+
+typedef struct {
+ NMSerialDeviceClass parent;
+} NMUmtsDeviceClass;
+
+GType nm_umts_device_get_type (void);
+
+NMUmtsDevice *nm_umts_device_new (const char *udi,
+ const char *iface,
+ const char *driver);
+
+G_END_DECLS
+
+#endif /* NM_UMTS_DEVICE_H */
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 73c8ff6c8f..0fc7adad6a 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -19,6 +19,7 @@ typedef struct {
NMDBusManager *dbus_manager;
DBusGProxy *proxy;
+ guint32 ppp_watch_id;
guint32 ppp_timeout_handler;
guint32 name_owner_changed_handler;
} NMPPPManagerPrivate;
@@ -540,6 +541,7 @@ nm_ppp_manager_start (NMPPPManager *manager,
ppp_watch = g_child_watch_source_new (priv->pid);
g_source_set_callback (ppp_watch, (GSourceFunc) ppp_watch_cb, manager, NULL);
g_source_attach (ppp_watch, NULL);
+ priv->ppp_watch_id = g_source_get_id (ppp_watch);
g_source_unref (ppp_watch);
start_dbus_watcher (manager);
@@ -576,6 +578,11 @@ nm_ppp_manager_stop (NMPPPManager *manager)
priv->dbus_manager = NULL;
}
+ if (priv->ppp_watch_id) {
+ g_source_remove (priv->ppp_watch_id);
+ priv->ppp_watch_id = 0;
+ }
+
if (priv->pid) {
kill (priv->pid, SIGTERM);
priv->pid = 0;