diff options
author | Dan Williams <dcbw@redhat.com> | 2010-09-28 10:20:11 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2010-09-28 10:20:11 -0500 |
commit | 8935812da4bb468992876586215b68b159fcfdd4 (patch) | |
tree | b97e5097bbfec0808b46ebc1c7e90da402bf9149 | |
parent | 81d0fd148f8c72a2e50b4e6fe82496daa28a91cc (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.
-rw-r--r-- | src/mm-serial-port.c | 11 |
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, |