serial: use connected notifier only when needed
It's only relevant when the port is open anyway, and marking the port disconnected in nm_serial_port_close(), which used to be called from the finalize() function, would trigger the notifier when stuff was already cleaned up. So move the nm_serial_port_close() call to dispose() and remove the connected notifier before we clean the port up.
This commit is contained in:
@@ -79,6 +79,7 @@ typedef struct {
|
||||
guint timeout_id;
|
||||
|
||||
guint flash_id;
|
||||
guint connected_id;
|
||||
} MMSerialPortPrivate;
|
||||
|
||||
#if 0
|
||||
@@ -741,6 +742,35 @@ data_available (GIOChannel *source,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
port_connected (MMSerialPort *self, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
|
||||
gboolean connected;
|
||||
|
||||
if (priv->fd < 0)
|
||||
return;
|
||||
|
||||
/* When the port is connected, drop the serial port lock so PPP can do
|
||||
* something with the port. When the port is disconnected, grab the lock
|
||||
* again.
|
||||
*/
|
||||
connected = mm_port_get_connected (MM_PORT (self));
|
||||
|
||||
if (ioctl (priv->fd, (connected ? TIOCNXCL : TIOCEXCL)) < 0) {
|
||||
g_warning ("%s: (%s) could not %s serial port lock: (%d) %s",
|
||||
__func__,
|
||||
mm_port_get_device (MM_PORT (self)),
|
||||
connected ? "drop" : "re-acquire",
|
||||
errno,
|
||||
strerror (errno));
|
||||
if (!connected) {
|
||||
// FIXME: do something here, maybe try again in a few seconds or
|
||||
// close the port and error out?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_serial_port_open (MMSerialPort *self, GError **error)
|
||||
{
|
||||
@@ -752,9 +782,10 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
|
||||
|
||||
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
|
||||
|
||||
if (priv->fd >= 0)
|
||||
if (priv->fd >= 0) {
|
||||
/* Already open */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
device = mm_port_get_device (MM_PORT (self));
|
||||
|
||||
@@ -797,6 +828,10 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
|
||||
G_IO_IN | G_IO_ERR | G_IO_HUP,
|
||||
data_available, self);
|
||||
|
||||
g_warn_if_fail (priv->connected_id == 0);
|
||||
priv->connected_id = g_signal_connect (self, "notify::" MM_PORT_CONNECTED,
|
||||
G_CALLBACK (port_connected), NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -809,6 +844,11 @@ mm_serial_port_close (MMSerialPort *self)
|
||||
|
||||
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
|
||||
|
||||
if (priv->connected_id) {
|
||||
g_signal_handler_disconnect (self, priv->connected_id);
|
||||
priv->connected_id = 0;
|
||||
}
|
||||
|
||||
if (priv->fd >= 0) {
|
||||
g_message ("(%s) closing serial device...", mm_port_get_device (MM_PORT (self)));
|
||||
|
||||
@@ -1046,37 +1086,6 @@ mm_serial_port_flash_cancel (MMSerialPort *self)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
port_connected (MMSerialPort *self, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
|
||||
gboolean connected;
|
||||
|
||||
if (priv->fd < 0)
|
||||
return;
|
||||
|
||||
/* When the port is connected, drop the serial port lock so PPP can do
|
||||
* something with the port. When the port is disconnected, grab the lock
|
||||
* again.
|
||||
*/
|
||||
connected = mm_port_get_connected (MM_PORT (self));
|
||||
|
||||
if (ioctl (priv->fd, (connected ? TIOCNXCL : TIOCEXCL)) < 0) {
|
||||
g_warning ("%s: (%s) could not %s serial port lock: (%d) %s",
|
||||
__func__,
|
||||
mm_port_get_device (MM_PORT (self)),
|
||||
connected ? "drop" : "re-acquire",
|
||||
errno,
|
||||
strerror (errno));
|
||||
if (!connected) {
|
||||
// FIXME: do something here, maybe try again in a few seconds or
|
||||
// close the port and error out?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
MMSerialPort *
|
||||
mm_serial_port_new (const char *name, MMPortType ptype)
|
||||
{
|
||||
@@ -1104,8 +1113,6 @@ mm_serial_port_init (MMSerialPort *self)
|
||||
priv->queue = g_queue_new ();
|
||||
priv->command = g_string_new_len ("AT", SERIAL_BUF_SIZE);
|
||||
priv->response = g_string_sized_new (SERIAL_BUF_SIZE);
|
||||
|
||||
g_signal_connect (self, "notify::" MM_PORT_CONNECTED, G_CALLBACK (port_connected), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1164,14 +1171,20 @@ get_property (GObject *object, guint prop_id,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
mm_serial_port_close (MM_SERIAL_PORT (object));
|
||||
|
||||
G_OBJECT_CLASS (mm_serial_port_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
MMSerialPort *self = MM_SERIAL_PORT (object);
|
||||
MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self);
|
||||
|
||||
mm_serial_port_close (self);
|
||||
|
||||
g_hash_table_destroy (priv->reply_cache);
|
||||
g_queue_free (priv->queue);
|
||||
g_string_free (priv->command, TRUE);
|
||||
@@ -1205,6 +1218,7 @@ mm_serial_port_class_init (MMSerialPortClass *klass)
|
||||
/* Virtual methods */
|
||||
object_class->set_property = set_property;
|
||||
object_class->get_property = get_property;
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
/* Properties */
|
||||
|
Reference in New Issue
Block a user