aboutsummaryrefslogtreecommitdiff
path: root/src/mm-serial-port.c
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2014-02-05 08:38:23 +0100
committerGuido Günther <agx@sigxcpu.org>2014-02-05 08:38:23 +0100
commit7fbee6ce27176bfc7ae9b34a4de9452cf5f6fa43 (patch)
tree5cabb0ab457846912d99ef675160be0dce4fbe6f /src/mm-serial-port.c
parentdc645b92b9a7db3076ae34986ac219d01677d124 (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.c87
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",