about summary refs log tree commit diff
path: root/src/devices/wwan/nm-modem.c
diff options
context:
space:
mode:
authorAron Xu <aron@debian.org>2016-12-20 20:06:37 +0800
committerAron Xu <aron@debian.org>2016-12-20 20:06:37 +0800
commit45cb5bb3c0e6edb887cf69b417fcaf7053814a9b (patch)
tree795f8d6a3aa1145e4ba8fa1564f39425ea0c6ed9 /src/devices/wwan/nm-modem.c
parent270c4830551c9810ad4e83f9a1db2b1cb946208c (diff)
Imported Upstream version 1.4.4 upstream/1.4.4
Diffstat (limited to 'src/devices/wwan/nm-modem.c')
-rw-r--r--src/devices/wwan/nm-modem.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c
index 2e3d63bb..459d212a 100644
--- a/src/devices/wwan/nm-modem.c
+++ b/src/devices/wwan/nm-modem.c
@@ -23,7 +23,9 @@
 
 #include "nm-modem.h"
 
+#include <fcntl.h>
 #include <string.h>
+#include <termios.h>
 
 #include "nm-core-internal.h"
 #include "nm-platform.h"
@@ -491,6 +493,23 @@ ppp_stats (NMPPPManager *ppp_manager,
 	}
 }
 
+static gboolean
+port_speed_is_zero (const char *port)
+{
+	struct termios options;
+	nm_auto_close int fd = -1;
+
+	fd = open (port, O_RDWR | O_NONBLOCK | O_NOCTTY | O_CLOEXEC);
+	if (fd < 0)
+		return FALSE;
+
+	memset (&options, 0, sizeof (struct termios));
+	if (tcgetattr (fd, &options) != 0)
+		return FALSE;
+
+	return cfgetospeed (&options) == B0;
+}
+
 static NMActStageReturn
 ppp_stage3_ip_config_start (NMModem *self,
                             NMActRequest *req,
@@ -501,6 +520,7 @@ ppp_stage3_ip_config_start (NMModem *self,
 	GError *error = NULL;
 	NMActStageReturn ret;
 	guint ip_timeout = 30;
+	guint baud_override = 0;
 
 	g_return_val_if_fail (NM_IS_MODEM (self), NM_ACT_STAGE_RETURN_FAILURE);
 	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE);
@@ -530,8 +550,16 @@ ppp_stage3_ip_config_start (NMModem *self,
 		ip_timeout = priv->mm_ip_timeout;
 	}
 
+	/* Some tty drivers and modems ignore port speed, but pppd requires the
+	 * port speed to be > 0 or it exits. If the port speed is 0 pass an
+	 * explicit speed to pppd to prevent the exit.
+	 * https://bugzilla.redhat.com/show_bug.cgi?id=1281731
+	 */
+	if (port_speed_is_zero (priv->data_port))
+		baud_override = 57600;
+
 	priv->ppp_manager = nm_ppp_manager_new (priv->data_port);
-	if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, &error)) {
+	if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, baud_override, &error)) {
 		g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED,
 		                  G_CALLBACK (ppp_state_changed),
 		                  self);
@@ -1327,12 +1355,12 @@ constructor (GType type,
 	priv = NM_MODEM_GET_PRIVATE (object);
 
 	if (!priv->data_port && !priv->control_port) {
-		nm_log_err (LOGD_HW, "neither modem command nor data interface provided");
+		nm_log_err (LOGD_PLATFORM, "neither modem command nor data interface provided");
 		goto err;
 	}
 
 	if (!priv->path) {
-		nm_log_err (LOGD_HW, "D-Bus path not provided");
+		nm_log_err (LOGD_PLATFORM, "D-Bus path not provided");
 		goto err;
 	}