diff options
author | Guido Günther <agx@sigxcpu.org> | 2014-02-05 08:38:23 +0100 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2014-02-05 08:38:23 +0100 |
commit | 7fbee6ce27176bfc7ae9b34a4de9452cf5f6fa43 (patch) | |
tree | 5cabb0ab457846912d99ef675160be0dce4fbe6f /src/mm-serial-port.c | |
parent | dc645b92b9a7db3076ae34986ac219d01677d124 (diff) |
Imported Upstream version 0.4+git.20110124t203624.00b6cceupstream/0.4+git.20110124t203624.00b6cce
Diffstat (limited to 'src/mm-serial-port.c')
-rw-r--r-- | src/mm-serial-port.c | 87 |
1 files changed, 61 insertions, 26 deletions
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c index ed44167..bf2a98a 100644 --- a/src/mm-serial-port.c +++ b/src/mm-serial-port.c @@ -26,10 +26,11 @@ #include <errno.h> #include <sys/ioctl.h> #include <string.h> +#include <linux/serial.h> #include "mm-serial-port.h" #include "mm-errors.h" -#include "mm-options.h" +#include "mm-log.h" static gboolean mm_serial_port_queue_process (gpointer data); @@ -42,6 +43,7 @@ enum { PROP_PARITY, PROP_STOPBITS, PROP_SEND_DELAY, + PROP_FD, LAST_PROP }; @@ -150,10 +152,10 @@ mm_serial_port_print_config (MMSerialPort *port, const char *detail) return; } - g_message ("*** %s (%s): (%s) baud rate: %d (%s)", - __func__, detail, mm_port_get_device (MM_PORT (port)), - stbuf.c_cflag & CBAUD, - baud_to_string (stbuf.c_cflag & CBAUD)); + mm_info ("(%s): (%s) baud rate: %d (%s)", + detail, mm_port_get_device (MM_PORT (port)), + stbuf.c_cflag & CBAUD, + baud_to_string (stbuf.c_cflag & CBAUD)); } #endif @@ -348,7 +350,7 @@ serial_debug (MMSerialPort *self, const char *prefix, const char *buf, gsize len { g_return_if_fail (len > 0); - if (mm_options_debug () && MM_SERIAL_PORT_GET_CLASS (self)->debug_log) + if (MM_SERIAL_PORT_GET_CLASS (self)->debug_log) MM_SERIAL_PORT_GET_CLASS (self)->debug_log (self, prefix, buf, len); } @@ -684,6 +686,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error) MMSerialPortPrivate *priv; char *devfile; const char *device; + struct serial_struct sinfo; g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE); @@ -696,11 +699,15 @@ mm_serial_port_open (MMSerialPort *self, GError **error) goto success; } - g_message ("(%s) opening serial device...", device); - devfile = g_strdup_printf ("/dev/%s", device); - errno = 0; - priv->fd = open (devfile, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); - g_free (devfile); + mm_info ("(%s) opening serial port...", device); + + /* Only open a new file descriptor if we weren't given one already */ + if (priv->fd < 0) { + devfile = g_strdup_printf ("/dev/%s", device); + errno = 0; + priv->fd = open (devfile, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); + g_free (devfile); + } if (priv->fd < 0) { /* nozomi isn't ready yet when the port appears, and it'll return @@ -733,6 +740,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, @@ -745,13 +761,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error) success: priv->open_count++; - if (mm_options_debug ()) { - GTimeVal tv; - - g_get_current_time (&tv); - g_debug ("<%ld.%ld> (%s) device open count is %d (open)", - tv.tv_sec, tv.tv_usec, device, priv->open_count); - } + mm_dbg ("(%s) device open count is %d (open)", device, priv->open_count); return TRUE; error: @@ -785,13 +795,7 @@ mm_serial_port_close (MMSerialPort *self) priv->open_count--; - if (mm_options_debug ()) { - GTimeVal tv; - - g_get_current_time (&tv); - g_debug ("<%ld.%ld> (%s) device open count is %d (close)", - tv.tv_sec, tv.tv_usec, device, priv->open_count); - } + mm_dbg ("(%s) device open count is %d (close)", device, priv->open_count); if (priv->open_count > 0) return; @@ -802,7 +806,9 @@ mm_serial_port_close (MMSerialPort *self) } if (priv->fd >= 0) { - g_message ("(%s) closing serial device...", device); + GTimeVal tv_start, tv_end; + + mm_info ("(%s) closing serial port...", device); mm_port_set_connected (MM_PORT (self), FALSE); @@ -816,9 +822,24 @@ mm_serial_port_close (MMSerialPort *self) mm_serial_port_flash_cancel (self); + g_get_current_time (&tv_start); + tcsetattr (priv->fd, TCSANOW, &priv->old_t); + tcflush (priv->fd, TCIOFLUSH); close (priv->fd); priv->fd = -1; + + g_get_current_time (&tv_end); + + mm_info ("(%s) serial port closed", device); + + /* Some ports don't respond to data and when close is called + * the serial layer waits up to 30 second (closing_wait) for + * that data to send before giving up and returning from close(). + * Log that. See GNOME bug #630670 for more details. + */ + if (tv_end.tv_sec - tv_start.tv_sec > 20) + mm_warn ("(%s): close blocked by driver for more than 20 seconds!", device); } /* Clear the command queue */ @@ -1185,6 +1206,9 @@ set_property (GObject *object, guint prop_id, MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (object); switch (prop_id) { + case PROP_FD: + priv->fd = g_value_get_int (value); + break; case PROP_BAUD: priv->baud = g_value_get_uint (value); break; @@ -1213,6 +1237,9 @@ get_property (GObject *object, guint prop_id, MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (object); switch (prop_id) { + case PROP_FD: + g_value_set_int (value, priv->fd); + break; case PROP_BAUD: g_value_set_uint (value, priv->baud); break; @@ -1276,6 +1303,14 @@ mm_serial_port_class_init (MMSerialPortClass *klass) /* Properties */ g_object_class_install_property + (object_class, PROP_FD, + g_param_spec_int (MM_SERIAL_PORT_FD, + "File descriptor", + "Fiel descriptor", + -1, G_MAXINT, -1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_BAUD, g_param_spec_uint (MM_SERIAL_PORT_BAUD, "Baud", |