Blob Blame History Raw
From ea793cb9f744cd2942b66385118161b880de958a Mon Sep 17 00:00:00 2001
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date: Tue, 19 Jun 2012 12:44:43 +0300
Subject: [PATCH] input: Fix not adding watches when io channel is connected

This can leave dangling pointers in case one of the channel is never
connected which cause -EALREADY to be returned by
input_device_set_channel next time the device attempts to connect.

For the same reason the code path when acting as client now add the
watch as soon as the connection completes instead when both channels
are connected.
---
 input/device.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/input/device.c b/input/device.c
index 0e3f4a9..09a9a39 100644
--- a/input/device.c
+++ b/input/device.c
@@ -387,6 +387,11 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
 	struct input_conn *iconn = data;
 	struct input_device *idev = iconn->idev;
 	gboolean connected = FALSE;
+	char address[18];
+
+	ba2str(&iconn->idev->dst, address);
+
+	DBG("Device %s disconnected", address);
 
 	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
 	 * it's likely that ctrl_watch_cb has been queued for dispatching in
@@ -415,6 +420,11 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
 static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
 {
 	struct input_conn *iconn = data;
+	char address[18];
+
+	ba2str(&iconn->idev->dst, address);
+
+	DBG("Device %s disconnected", address);
 
 	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
 	 * it's likely that intr_watch_cb has been queued for dispatching in
@@ -811,13 +821,6 @@ static int input_device_connected(struct input_device *idev,
 	if (err < 0)
 		return err;
 
-	iconn->intr_watch = g_io_add_watch(iconn->intr_io,
-					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-					intr_watch_cb, iconn);
-	iconn->ctrl_watch = g_io_add_watch(iconn->ctrl_io,
-					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-					ctrl_watch_cb, iconn);
-
 	connected = TRUE;
 	emit_property_changed(idev->conn, idev->path, INPUT_DEVICE_INTERFACE,
 				"Connected", DBUS_TYPE_BOOLEAN, &connected);
@@ -854,6 +857,10 @@ static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
 	dbus_message_unref(iconn->pending_connect);
 	iconn->pending_connect = NULL;
 
+	iconn->intr_watch = g_io_add_watch(iconn->intr_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					intr_watch_cb, iconn);
+
 	return;
 
 failed:
@@ -913,6 +920,10 @@ static void control_connect_cb(GIOChannel *chan, GError *conn_err,
 
 	iconn->intr_io = io;
 
+	iconn->ctrl_watch = g_io_add_watch(iconn->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, iconn);
+
 	return;
 
 failed:
@@ -1272,11 +1283,17 @@ int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm,
 		if (iconn->ctrl_io)
 			return -EALREADY;
 		iconn->ctrl_io = g_io_channel_ref(io);
+		iconn->ctrl_watch = g_io_add_watch(iconn->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, iconn);
 		break;
 	case L2CAP_PSM_HIDP_INTR:
 		if (iconn->intr_io)
 			return -EALREADY;
 		iconn->intr_io = g_io_channel_ref(io);
+		iconn->intr_watch = g_io_add_watch(iconn->intr_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					intr_watch_cb, iconn);
 		break;
 	}
 
-- 
1.8.0.1