blob: 913365ef0db2e1d2c46183b83fe27dd7fa0c483b [file] [log] [blame]
From f3d2851b74fe790896f819efbc694e288d54d819 Mon Sep 17 00:00:00 2001
From: Scott James Remnant <scott@netsplit.com>
Date: Tue, 24 Jan 2012 10:35:30 -0800
Subject: [PATCH 11/13] bonding: retry if callback returns TRUE
When a bonding completes, pass the status to any plugin bonding
callbacks; if any return TRUE than set a timer to retry the bonding
after an appropriate backoff period.
---
src/device.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/src/device.c b/src/device.c
index 9a62eef..4ad5aa0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2493,6 +2493,44 @@ void btd_device_unregister_bonding_cb(struct btd_device *device,
device->bonding_callbacks, cb);
}
+static gboolean device_bonding_retry(gpointer data)
+{
+ struct btd_device *device = data;
+ struct btd_adapter *adapter = device_get_adapter(device);
+ struct bonding_req *bonding = device->bonding;
+ int err;
+
+ if (!bonding)
+ return FALSE;
+
+ DBG("retrying bonding");
+ err = adapter_create_bonding(adapter, &device->bdaddr,
+ device->type, bonding->capability);
+ if (err < 0)
+ device_bonding_complete(device, bonding->status);
+
+ bonding->retry_timer = 0;
+ return FALSE;
+}
+
+static gboolean device_bonding_get_retry(struct btd_device *device,
+ uint8_t status)
+{
+ GSList *l;
+ btd_device_bonding_cb_t cb;
+ gboolean retry = FALSE;
+
+ for (l = device->bonding_callbacks; l != NULL; l = g_slist_next(l)) {
+ cb = l->data;
+ retry |= cb(device, TRUE, status);
+ }
+
+ g_slist_free(device->bonding_callbacks);
+ device->bonding_callbacks = NULL;
+
+ return retry;
+}
+
gboolean device_is_retrying(struct btd_device *device)
{
struct bonding_req *bonding = device->bonding;
@@ -2507,6 +2545,14 @@ void device_bonding_complete(struct btd_device *device, uint8_t status)
DBG("bonding %p status 0x%02x", bonding, status);
+ if (device_bonding_get_retry(device, status) && status) {
+ DBG("backing off and retrying");
+ bonding->status = status;
+ bonding->retry_timer = g_timeout_add(3000,
+ device_bonding_retry, device);
+ return;
+ }
+
if (auth && (auth->type == AUTH_TYPE_NOTIFY_PASSKEY
|| auth->type == AUTH_TYPE_NOTIFY_PINCODE) && auth->agent)
agent_cancel(auth->agent);
--
1.7.7.3