[PATCH v7 5/5] input: Automatically attempt a reconnect when required.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The HID 1.1 spec requires a host to attempt a reconnection when a
HID device goes out of range and comes back. There is test (see
TP/HCE/BV-04-I [Host Initiated Re-connection]) to ensure that the
host initiates the connection when that happens.

This patch adds a reconnection timer for HID devices trying to
reconnect every 30s for a maximum of 3 minutes after the connection
to a HID device with a ReconnectMode of "host" or "any" is closed.
---
 profiles/input/device.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/profiles/input/device.c b/profiles/input/device.c
index 6ffc199..4af95d8 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -81,10 +81,15 @@ struct input_device {
 	bool			disable_sdp;
 	char			*name;
 	enum reconnect_mode_t	reconnect_mode;
+	guint			reconnect_timer;
+	uint32_t		reconnect_attempt;
 };
 
 static GSList *devices = NULL;
 
+static void input_device_enter_reconnect_mode(struct input_device *idev);
+static const char *reconnect_mode_to_string(const enum reconnect_mode_t mode);
+
 static struct input_device *find_device_by_path(GSList *list, const char *path)
 {
 	for (; list; list = list->next) {
@@ -126,6 +131,9 @@ static void input_device_free(struct input_device *idev)
 		g_free(idev->req);
 	}
 
+	if (idev->reconnect_timer > 0)
+		g_source_remove(idev->reconnect_timer);
+
 	g_free(idev->uuid);
 
 	g_free(idev);
@@ -160,6 +168,9 @@ static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data
 	if (idev->ctrl_io && !(cond & G_IO_NVAL))
 		g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL);
 
+	/* Enter the auto-reconnect mode if needed */
+	input_device_enter_reconnect_mode(idev);
+
 	return FALSE;
 }
 
@@ -654,6 +665,62 @@ static int dev_connect(struct input_device *idev)
 	return -EIO;
 }
 
+static gboolean input_device_auto_reconnect(gpointer user_data)
+{
+	struct input_device *idev = user_data;
+
+	DBG("path=%s, attempt=%d", idev->path, idev->reconnect_attempt);
+
+	/* Stop the recurrent reconnection attempts if the device is reconnected
+	 * or is marked for removal. */
+	if (device_is_temporary(idev->device) ||
+					device_is_connected(idev->device))
+		return FALSE;
+
+	/* Only attempt an auto-reconnect for at most 3 minutes (6 * 30s). */
+	if (idev->reconnect_attempt >= 6)
+		return FALSE;
+
+	/* Check if the profile is already connected. */
+	if (idev->ctrl_io)
+		return FALSE;
+
+	if (is_connected(idev))
+		return FALSE;
+
+	idev->reconnect_attempt++;
+	dev_connect(idev);
+
+	return TRUE;
+}
+
+static void input_device_enter_reconnect_mode(struct input_device *idev)
+{
+	DBG("path=%s reconnect_mode=%s", idev->path,
+				reconnect_mode_to_string(idev->reconnect_mode));
+
+	/* Only attempt an auto-reconnect when the device is required to accept
+	 * reconnections from the host. */
+	if (idev->reconnect_mode != RECONNECT_ANY &&
+				idev->reconnect_mode != RECONNECT_HOST)
+		return;
+
+	/* If the device is temporary we are not required to reconnect with the
+	 * device. This is likely the case of a removing device. */
+	if (device_is_temporary(idev->device) ||
+					device_is_connected(idev->device))
+		return;
+
+	if (idev->reconnect_timer > 0)
+		g_source_remove(idev->reconnect_timer);
+
+	DBG("registering auto-reconnect");
+	idev->reconnect_attempt = 0;
+	idev->reconnect_timer = g_timeout_add_seconds(30,
+					input_device_auto_reconnect, idev);
+
+}
+
 int input_device_connect(struct btd_device *dev, struct btd_profile *profile)
 {
 	struct input_device *idev;
-- 
1.8.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux