aboutsummaryrefslogtreecommitdiff
path: root/src/mm-serial-port.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-serial-port.c')
-rw-r--r--src/mm-serial-port.c82
1 files changed, 62 insertions, 20 deletions
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index b7fdf275..37f1bb09 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -11,7 +11,7 @@
* GNU General Public License for more details:
*
* Copyright (C) 2008 - 2009 Novell, Inc.
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
*/
#define _GNU_SOURCE /* for strcasestr() */
@@ -51,6 +51,7 @@ enum {
#define MM_SERIAL_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_SERIAL_PORT, MMSerialPortPrivate))
typedef struct {
+ guint32 open_count;
int fd;
GHashTable *reply_cache;
GIOChannel *channel;
@@ -601,7 +602,7 @@ data_available (GIOChannel *source,
if (condition & G_IO_HUP) {
if (priv->response->len)
g_byte_array_remove_range (priv->response, 0, priv->response->len);
- mm_serial_port_close (self);
+ mm_serial_port_close_force (self);
return FALSE;
}
@@ -688,13 +689,13 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
- if (priv->fd >= 0) {
+ device = mm_port_get_device (MM_PORT (self));
+
+ if (priv->open_count) {
/* Already open */
- return TRUE;
+ goto success;
}
- device = mm_port_get_device (MM_PORT (self));
-
g_message ("(%s) opening serial device...", device);
devfile = g_strdup_printf ("/dev/%s", device);
errno = 0;
@@ -716,9 +717,7 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
if (ioctl (priv->fd, TIOCEXCL) < 0) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_OPEN_FAILED,
"Could not lock serial device %s: %s", device, strerror (errno));
- close (priv->fd);
- priv->fd = -1;
- return FALSE;
+ goto error;
}
/* Flush any waiting IO */
@@ -727,17 +726,12 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
if (tcgetattr (priv->fd, &priv->old_t) < 0) {
g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_OPEN_FAILED,
"Could not open serial device %s: %s", device, strerror (errno));
- close (priv->fd);
- priv->fd = -1;
- return FALSE;
+ goto error;
}
g_warn_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->config_fd);
- if (!MM_SERIAL_PORT_GET_CLASS (self)->config_fd (self, priv->fd, error)) {
- close (priv->fd);
- priv->fd = -1;
- return FALSE;
- }
+ if (!MM_SERIAL_PORT_GET_CLASS (self)->config_fd (self, priv->fd, error))
+ goto error;
priv->channel = g_io_channel_unix_new (priv->fd);
g_io_channel_set_encoding (priv->channel, NULL, NULL);
@@ -749,7 +743,21 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
priv->connected_id = g_signal_connect (self, "notify::" MM_PORT_CONNECTED,
G_CALLBACK (port_connected), NULL);
+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);
+ }
return TRUE;
+
+error:
+ close (priv->fd);
+ priv->fd = -1;
+ return FALSE;
}
gboolean
@@ -758,18 +766,35 @@ mm_serial_port_is_open (MMSerialPort *self)
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
- return (MM_SERIAL_PORT_GET_PRIVATE (self)->fd >= 0);
+ return !!MM_SERIAL_PORT_GET_PRIVATE (self)->open_count;
}
void
mm_serial_port_close (MMSerialPort *self)
{
MMSerialPortPrivate *priv;
+ const char *device;
int i;
g_return_if_fail (MM_IS_SERIAL_PORT (self));
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
+ g_return_if_fail (priv->open_count > 0);
+
+ device = mm_port_get_device (MM_PORT (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);
+ }
+
+ if (priv->open_count > 0)
+ return;
if (priv->connected_id) {
g_signal_handler_disconnect (self, priv->connected_id);
@@ -777,7 +802,7 @@ mm_serial_port_close (MMSerialPort *self)
}
if (priv->fd >= 0) {
- g_message ("(%s) closing serial device...", mm_port_get_device (MM_PORT (self)));
+ g_message ("(%s) closing serial device...", device);
mm_port_set_connected (MM_PORT (self), FALSE);
@@ -809,6 +834,22 @@ mm_serial_port_close (MMSerialPort *self)
g_queue_clear (priv->queue);
}
+void
+mm_serial_port_close_force (MMSerialPort *self)
+{
+ MMSerialPortPrivate *priv;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (MM_IS_SERIAL_PORT (self));
+
+ priv = MM_SERIAL_PORT_GET_PRIVATE (self);
+ g_return_if_fail (priv->open_count > 0);
+
+ /* Force the port to close */
+ priv->open_count = 1;
+ mm_serial_port_close (self);
+}
+
static void
internal_queue_command (MMSerialPort *self,
GByteArray *command,
@@ -1170,7 +1211,8 @@ get_property (GObject *object, guint prop_id,
static void
dispose (GObject *object)
{
- mm_serial_port_close (MM_SERIAL_PORT (object));
+ if (mm_serial_port_is_open (MM_SERIAL_PORT (object)))
+ mm_serial_port_close_force (MM_SERIAL_PORT (object));
G_OBJECT_CLASS (mm_serial_port_parent_class)->dispose (object);
}