aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-09-28 10:20:11 -0500
committerDan Williams <dcbw@redhat.com>2010-09-28 10:20:11 -0500
commit8935812da4bb468992876586215b68b159fcfdd4 (patch)
treeb97e5097bbfec0808b46ebc1c7e90da402bf9149 /src
parent81d0fd148f8c72a2e50b4e6fe82496daa28a91cc (diff)
serial: kill serial port closing wait
This is the real fix for 81d0fd148f8c72a2e50b4e6fe82496daa28a91cc. Some devices don't interact well with the option driver or the usb-serial layer; they don't respond to the USB data requests and thus data never gets written to that port. When close(2) is called, that data is still pending and so the tty layer waits 30 seconds before returning from the close. This is the 'closing_wait' value, which unfortunately is not able to be modified by ModemManager because most serial drivers for 3G devices don't implement the .ioctl handler or its TCIOSSERIAL option to change closing_wait. This goes along with a kernel patch to various drivers to enable the TIOCSSERIAL ioctl to modify closing_wait which will be posted soon.
Diffstat (limited to 'src')
-rw-r--r--src/mm-serial-port.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 6a944835..94903bc8 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <string.h>
+#include <linux/serial.h>
#include "mm-serial-port.h"
#include "mm-errors.h"
@@ -685,6 +686,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
char *devfile;
const char *device;
GTimeVal tv;
+ struct serial_struct sinfo;
g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
@@ -740,6 +742,15 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
if (!MM_SERIAL_PORT_GET_CLASS (self)->config_fd (self, priv->fd, error))
goto error;
+ /* Don't wait for pending data when closing the port; this can cause some
+ * stupid devices that don't respond to URBs on a particular port to hang
+ * for 30 seconds when probin fails.
+ */
+ if (ioctl (priv->fd, TIOCGSERIAL, &sinfo) == 0) {
+ sinfo.closing_wait = ASYNC_CLOSING_WAIT_NONE;
+ ioctl (priv->fd, TIOCSSERIAL, &sinfo);
+ }
+
priv->channel = g_io_channel_unix_new (priv->fd);
g_io_channel_set_encoding (priv->channel, NULL, NULL);
priv->watch_id = g_io_add_watch (priv->channel,