From ea9e6d3d4a3264e8b7be24f072ea276024c5c573 Mon Sep 17 00:00:00 2001 From: Lukasz Duda Date: Mon, 9 May 2022 00:40:04 +0200 Subject: [PATCH 1/2] [linux] Make BLE connection retry on SW connection abort error Signed-off-by: Lukasz Duda --- src/platform/Linux/bluez/Helper.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/platform/Linux/bluez/Helper.cpp b/src/platform/Linux/bluez/Helper.cpp index 81f59af086276c..dcb3bf33b01fdf 100644 --- a/src/platform/Linux/bluez/Helper.cpp +++ b/src/platform/Linux/bluez/Helper.cpp @@ -1740,7 +1740,7 @@ struct ConnectParams BluezEndpoint * mEndpoint; }; -static void ConnectDeviceDone(GObject * aObject, GAsyncResult * aResult, gpointer) +static void ConnectDeviceDone(GObject * aObject, GAsyncResult * aResult, gpointer apEndpoint) { BluezDevice1 * device = BLUEZ_DEVICE1(aObject); GError * error = nullptr; @@ -1748,7 +1748,28 @@ static void ConnectDeviceDone(GObject * aObject, GAsyncResult * aResult, gpointe if (!success) { - ChipLogError(DeviceLayer, "FAIL: ConnectDevice : %s", error->message); + ChipLogError(DeviceLayer, "FAIL: ConnectDevice : %s (%d)", error->message, error->code); + + // Due to radio interferences or Wi-Fi coexistence, sometimes the BLE connection may not be + // established (e.g. Connection Indication Packet is missed by BLE peripheral). In such case, + // BlueZ returns "Software caused connection abort error", and we should make a connection retry. + // It's important to make sure that the connection is correctly ceased, by calling `Disconnect()` + // D-Bus method, or else `Connect()` returns immediately without any effect. + // Note that still there is a global timeout that applies, so there is no need to limit retries. + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR) && + strstr(error->message, "Software caused connection abort")) + { + BluezEndpoint * endpoint = static_cast(apEndpoint); + assert(endpoint != nullptr); + + // Clear the error before another call. + g_clear_error(&error); + + bluez_device1_call_disconnect_sync(device, NULL, &error); + bluez_device1_call_connect(device, endpoint->mpConnectCancellable, ConnectDeviceDone, endpoint); + ExitNow(); + } + BLEManagerImpl::HandleConnectFailed(CHIP_ERROR_INTERNAL); ExitNow(); } @@ -1769,7 +1790,7 @@ static gboolean ConnectDeviceImpl(ConnectParams * apParams) assert(endpoint != nullptr); g_cancellable_reset(endpoint->mpConnectCancellable); - bluez_device1_call_connect(device, endpoint->mpConnectCancellable, ConnectDeviceDone, nullptr); + bluez_device1_call_connect(device, endpoint->mpConnectCancellable, ConnectDeviceDone, endpoint); g_object_unref(device); chip::Platform::Delete(apParams); From bdb46c2894784383bfb0c9f8e7179624f53e5e46 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Sun, 8 May 2022 22:49:24 +0000 Subject: [PATCH 2/2] Restyled by clang-format --- src/platform/Linux/bluez/Helper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/Linux/bluez/Helper.cpp b/src/platform/Linux/bluez/Helper.cpp index dcb3bf33b01fdf..e4ee40eb2bd418 100644 --- a/src/platform/Linux/bluez/Helper.cpp +++ b/src/platform/Linux/bluez/Helper.cpp @@ -1756,8 +1756,7 @@ static void ConnectDeviceDone(GObject * aObject, GAsyncResult * aResult, gpointe // It's important to make sure that the connection is correctly ceased, by calling `Disconnect()` // D-Bus method, or else `Connect()` returns immediately without any effect. // Note that still there is a global timeout that applies, so there is no need to limit retries. - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR) && - strstr(error->message, "Software caused connection abort")) + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR) && strstr(error->message, "Software caused connection abort")) { BluezEndpoint * endpoint = static_cast(apEndpoint); assert(endpoint != nullptr);