[Linux] BLE advertising: Handle adapter removal (#32434)
* New error code for indicating missing BLE adapter
* [Linux] BLE advertising: Handle adapter removal
* Return adapter unavailable from RegisterGattApplication too
* Account for different timings of adapter removal
* Forward error from async request to the application
* Handle various scenarios when communicating with BlueZ
* Improve readability of error handling blocks
diff --git a/docs/ERROR_CODES.md b/docs/ERROR_CODES.md
index 122d188..ecfda40 100644
--- a/docs/ERROR_CODES.md
+++ b/docs/ERROR_CODES.md
@@ -202,6 +202,7 @@
| Decimal | Hex | Name |
|-----------|-------|---------------------------------------------|
+| 1025 | 0x401 | `BLE_ERROR_ADAPTER_UNAVAILABLE` |
| 1027 | 0x403 | `BLE_ERROR_NO_CONNECTION_RECEIVED_CALLBACK` |
| 1028 | 0x404 | `BLE_ERROR_CENTRAL_UNSUBSCRIBED` |
| 1029 | 0x405 | `BLE_ERROR_GATT_SUBSCRIBE_FAILED` |
diff --git a/src/ble/BleError.cpp b/src/ble/BleError.cpp
index 641efc2..10ff637 100644
--- a/src/ble/BleError.cpp
+++ b/src/ble/BleError.cpp
@@ -55,6 +55,9 @@
#if !CHIP_CONFIG_SHORT_ERROR_STR
switch (err.AsInteger())
{
+ case BLE_ERROR_ADAPTER_UNAVAILABLE.AsInteger():
+ desc = "BLE adapter unavailable";
+ break;
case BLE_ERROR_NO_CONNECTION_RECEIVED_CALLBACK.AsInteger():
desc = "No chip over BLE connection received callback set";
break;
diff --git a/src/ble/BleError.h b/src/ble/BleError.h
index f2fb342..a95681a 100644
--- a/src/ble/BleError.h
+++ b/src/ble/BleError.h
@@ -44,7 +44,15 @@
* @{
*/
-// unused CHIP_BLE_ERROR(0x01)
+/**
+ * @def BLE_ERROR_ADAPTER_UNAVAILABLE
+ *
+ * @brief
+ * Bluetooth LE adapter is (currently) unavailable.
+ *
+ */
+#define BLE_ERROR_ADAPTER_UNAVAILABLE CHIP_BLE_ERROR(0x01)
+
// unused CHIP_BLE_ERROR(0x02)
/**
diff --git a/src/ble/tests/TestBleErrorStr.cpp b/src/ble/tests/TestBleErrorStr.cpp
index e2b13f4..caaa8d9 100644
--- a/src/ble/tests/TestBleErrorStr.cpp
+++ b/src/ble/tests/TestBleErrorStr.cpp
@@ -41,6 +41,7 @@
// clang-format off
static const CHIP_ERROR kTestElements[] =
{
+ BLE_ERROR_ADAPTER_UNAVAILABLE,
BLE_ERROR_NO_CONNECTION_RECEIVED_CALLBACK,
BLE_ERROR_CENTRAL_UNSUBSCRIBED,
BLE_ERROR_GATT_SUBSCRIBE_FAILED,
diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp
index dbf3791..e472e80 100644
--- a/src/platform/Linux/BLEManagerImpl.cpp
+++ b/src/platform/Linux/BLEManagerImpl.cpp
@@ -287,7 +287,7 @@
PacketBufferHandle::Adopt(apEvent->Platform.BLEIndicationReceived.mData));
break;
case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete:
- VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStartComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
+ SuccessOrExit(err = apEvent->Platform.BLEPeripheralAdvStartComplete.mError);
sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded);
// Do not restart the timer if it is still active. This is to avoid the timer from being restarted
// if the advertising is stopped due to a premature release.
@@ -299,7 +299,7 @@
sInstance.mFlags.Set(Flags::kAdvertising);
break;
case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete:
- VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStopComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
+ SuccessOrExit(err = apEvent->Platform.BLEPeripheralAdvStopComplete.mError);
sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded);
DeviceLayer::SystemLayer().CancelTimer(HandleAdvertisingTimer, this);
@@ -316,7 +316,7 @@
DriveBLEState();
break;
case DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete:
- VerifyOrExit(apEvent->Platform.BLEPeripheralRegisterAppComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE);
+ SuccessOrExit(err = apEvent->Platform.BLEPeripheralRegisterAppComplete.mError);
mFlags.Set(Flags::kAppRegistered);
controlOpComplete = true;
break;
@@ -656,6 +656,7 @@
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
+ DeviceLayer::SystemLayer().CancelTimer(HandleAdvertisingTimer, this);
mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
}
}
@@ -790,27 +791,27 @@
return CHIP_NO_ERROR;
}
-void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess)
+void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(CHIP_ERROR error)
{
ChipDeviceEvent event;
- event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete;
- event.Platform.BLEPeripheralRegisterAppComplete.mIsSuccess = aIsSuccess;
+ event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete;
+ event.Platform.BLEPeripheralRegisterAppComplete.mError = error;
PlatformMgr().PostEventOrDie(&event);
}
-void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess)
+void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(CHIP_ERROR error)
{
ChipDeviceEvent event;
- event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete;
- event.Platform.BLEPeripheralAdvStartComplete.mIsSuccess = aIsSuccess;
+ event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete;
+ event.Platform.BLEPeripheralAdvStartComplete.mError = error;
PlatformMgr().PostEventOrDie(&event);
}
-void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess)
+void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(CHIP_ERROR error)
{
ChipDeviceEvent event;
- event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete;
- event.Platform.BLEPeripheralAdvStopComplete.mIsSuccess = aIsSuccess;
+ event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete;
+ event.Platform.BLEPeripheralAdvStopComplete.mError = error;
PlatformMgr().PostEventOrDie(&event);
}
diff --git a/src/platform/Linux/BLEManagerImpl.h b/src/platform/Linux/BLEManagerImpl.h
index 6e3c1a6..790373c 100644
--- a/src/platform/Linux/BLEManagerImpl.h
+++ b/src/platform/Linux/BLEManagerImpl.h
@@ -92,9 +92,9 @@
static void HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT user_data);
static void HandleTXComplete(BLE_CONNECTION_OBJECT user_data);
- static void NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess);
- static void NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess);
- static void NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess);
+ static void NotifyBLEPeripheralRegisterAppComplete(CHIP_ERROR error);
+ static void NotifyBLEPeripheralAdvStartComplete(CHIP_ERROR error);
+ static void NotifyBLEPeripheralAdvStopComplete(CHIP_ERROR error);
static void NotifyBLEPeripheralAdvReleased();
private:
diff --git a/src/platform/Linux/CHIPDevicePlatformEvent.h b/src/platform/Linux/CHIPDevicePlatformEvent.h
index b6e0b55..019dcb3 100644
--- a/src/platform/Linux/CHIPDevicePlatformEvent.h
+++ b/src/platform/Linux/CHIPDevicePlatformEvent.h
@@ -91,15 +91,15 @@
} BLEIndicationReceived;
struct
{
- bool mIsSuccess;
+ CHIP_ERROR mError;
} BLEPeripheralRegisterAppComplete;
struct
{
- bool mIsSuccess;
+ CHIP_ERROR mError;
} BLEPeripheralAdvStartComplete;
struct
{
- bool mIsSuccess;
+ CHIP_ERROR mError;
} BLEPeripheralAdvStopComplete;
};
};
diff --git a/src/platform/Linux/bluez/BluezAdvertisement.cpp b/src/platform/Linux/bluez/BluezAdvertisement.cpp
index d1e43c5..db44bd6 100644
--- a/src/platform/Linux/bluez/BluezAdvertisement.cpp
+++ b/src/platform/Linux/bluez/BluezAdvertisement.cpp
@@ -24,6 +24,7 @@
#include <glib-object.h>
#include <glib.h>
+#include <ble/BleError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConfigurationManager.h>
@@ -109,15 +110,13 @@
CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, const char * aAdvUUID, const char * aAdvName)
{
- GAutoPtr<char> rootPath;
- CHIP_ERROR err;
-
- VerifyOrExit(!mAdv, err = CHIP_ERROR_INCORRECT_STATE;
- ChipLogError(DeviceLayer, "FAIL: BLE advertisement already initialized in %s", __func__));
+ VerifyOrReturnError(!mAdv, CHIP_ERROR_INCORRECT_STATE,
+ ChipLogError(DeviceLayer, "FAIL: BLE advertisement already initialized in %s", __func__));
mRoot.reset(reinterpret_cast<GDBusObjectManagerServer *>(g_object_ref(aEndpoint.GetGattApplicationObjectManager())));
mAdapter.reset(reinterpret_cast<BluezAdapter1 *>(g_object_ref(aEndpoint.GetAdapter())));
+ GAutoPtr<char> rootPath;
g_object_get(G_OBJECT(mRoot.get()), "object-path", &rootPath.GetReceiver(), nullptr);
g_snprintf(mAdvPath, sizeof(mAdvPath), "%s/advertising", rootPath.get());
g_strlcpy(mAdvUUID, aAdvUUID, sizeof(mAdvUUID));
@@ -132,15 +131,13 @@
g_snprintf(mAdvName, sizeof(mAdvName), "%s%04x", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, getpid() & 0xffff);
}
- err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+ CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+[](BluezAdvertisement * self) { return self->InitImpl(); }, this);
- VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_INCORRECT_STATE,
+ VerifyOrReturnError(err == CHIP_NO_ERROR, err,
ChipLogError(Ble, "Failed to schedule BLE advertisement Init() on CHIPoBluez thread"));
mIsInitialized = true;
-
-exit:
- return err;
+ return CHIP_NO_ERROR;
}
CHIP_ERROR BluezAdvertisement::SetIntervals(AdvertisingIntervals aAdvIntervals)
@@ -224,39 +221,49 @@
void BluezAdvertisement::StartDone(GObject * aObject, GAsyncResult * aResult)
{
- auto * advMgr = reinterpret_cast<BluezLEAdvertisingManager1 *>(aObject);
GAutoPtr<GError> error;
- gboolean success = FALSE;
-
- success = bluez_leadvertising_manager1_call_register_advertisement_finish(advMgr, aResult, &error.GetReceiver());
- VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: RegisterAdvertisement : %s", error->message));
+ if (!bluez_leadvertising_manager1_call_register_advertisement_finish(reinterpret_cast<BluezLEAdvertisingManager1 *>(aObject),
+ aResult, &error.GetReceiver()))
+ {
+ ChipLogError(DeviceLayer, "FAIL: RegisterAdvertisement: %s", error->message);
+ switch (error->code)
+ {
+ case G_DBUS_ERROR_NO_REPLY: // BlueZ crashed or the D-Bus connection is broken
+ case G_DBUS_ERROR_SERVICE_UNKNOWN: // BlueZ service is not available on the bus
+ case G_DBUS_ERROR_UNKNOWN_OBJECT: // Requested BLE adapter is not available
+ BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(BLE_ERROR_ADAPTER_UNAVAILABLE);
+ break;
+ default:
+ BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(CHIP_ERROR_INTERNAL);
+ }
+ return;
+ }
mIsAdvertising = true;
- ChipLogDetail(DeviceLayer, "RegisterAdvertisement complete");
-
-exit:
- BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(success == TRUE);
+ ChipLogDetail(DeviceLayer, "BLE advertisement started successfully");
+ BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(CHIP_NO_ERROR);
}
CHIP_ERROR BluezAdvertisement::StartImpl()
{
- GDBusObject * adapterObject;
- GAutoPtr<BluezLEAdvertisingManager1> advMgr;
+ VerifyOrReturnError(mAdapter, CHIP_ERROR_UNINITIALIZED);
+
+ // If the adapter configured in the Init() was unplugged, the g_dbus_interface_get_object()
+ // or bluez_object_get_leadvertising_manager1() might return nullptr (depending on the timing,
+ // since the D-Bus communication is handled on a separate thread). In such case, we should not
+ // report internal error, but adapter unavailable, so the application can handle the situation
+ // properly.
+
+ GDBusObject * adapterObject = g_dbus_interface_get_object(reinterpret_cast<GDBusInterface *>(mAdapter.get()));
+ VerifyOrReturnError(adapterObject != nullptr, BLE_ERROR_ADAPTER_UNAVAILABLE);
+ GAutoPtr<BluezLEAdvertisingManager1> advMgr(
+ bluez_object_get_leadvertising_manager1(reinterpret_cast<BluezObject *>(adapterObject)));
+ VerifyOrReturnError(advMgr, BLE_ERROR_ADAPTER_UNAVAILABLE);
+
GVariantBuilder optionsBuilder;
- GVariant * options;
-
- VerifyOrExit(!mIsAdvertising, ChipLogError(DeviceLayer, "FAIL: Advertising has already been enabled in %s", __func__));
- VerifyOrExit(mAdapter, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__));
-
- adapterObject = g_dbus_interface_get_object(G_DBUS_INTERFACE(mAdapter.get()));
- VerifyOrExit(adapterObject != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapterObject in %s", __func__));
-
- advMgr.reset(bluez_object_get_leadvertising_manager1(reinterpret_cast<BluezObject *>(adapterObject)));
- VerifyOrExit(advMgr, ChipLogError(DeviceLayer, "FAIL: NULL advMgr in %s", __func__));
-
g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE("a{sv}"));
- options = g_variant_builder_end(&optionsBuilder);
+ GVariant * options = g_variant_builder_end(&optionsBuilder);
bluez_leadvertising_manager1_call_register_advertisement(
advMgr.get(), mAdvPath, options, nullptr,
@@ -265,51 +272,58 @@
},
this);
-exit:
return CHIP_NO_ERROR;
}
CHIP_ERROR BluezAdvertisement::Start()
{
VerifyOrReturnError(mIsInitialized, CHIP_ERROR_INCORRECT_STATE);
-
- CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+ VerifyOrReturnValue(!mIsAdvertising, CHIP_NO_ERROR, ChipLogDetail(DeviceLayer, "BLE advertising already started"));
+ return PlatformMgrImpl().GLibMatterContextInvokeSync(
+[](BluezAdvertisement * self) { return self->StartImpl(); }, this);
- VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_INCORRECT_STATE,
- ChipLogError(Ble, "Failed to schedule BLE advertisement Start() on CHIPoBluez thread"));
- return err;
}
void BluezAdvertisement::StopDone(GObject * aObject, GAsyncResult * aResult)
{
- auto * advMgr = reinterpret_cast<BluezLEAdvertisingManager1 *>(aObject);
GAutoPtr<GError> error;
- gboolean success = FALSE;
-
- success = bluez_leadvertising_manager1_call_unregister_advertisement_finish(advMgr, aResult, &error.GetReceiver());
- VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: UnregisterAdvertisement: %s", error->message));
+ if (!bluez_leadvertising_manager1_call_unregister_advertisement_finish(reinterpret_cast<BluezLEAdvertisingManager1 *>(aObject),
+ aResult, &error.GetReceiver()))
+ {
+ ChipLogError(DeviceLayer, "FAIL: UnregisterAdvertisement: %s", error->message);
+ switch (error->code)
+ {
+ case G_DBUS_ERROR_NO_REPLY: // BlueZ crashed or the D-Bus connection is broken
+ case G_DBUS_ERROR_SERVICE_UNKNOWN: // BlueZ service is not available on the bus
+ case G_DBUS_ERROR_UNKNOWN_OBJECT: // Requested BLE adapter is not available
+ BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(BLE_ERROR_ADAPTER_UNAVAILABLE);
+ break;
+ default:
+ BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(CHIP_ERROR_INTERNAL);
+ }
+ return;
+ }
mIsAdvertising = false;
- ChipLogDetail(DeviceLayer, "UnregisterAdvertisement complete");
-
-exit:
- BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(success == TRUE);
+ ChipLogDetail(DeviceLayer, "BLE advertisement stopped successfully");
+ BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(CHIP_NO_ERROR);
}
CHIP_ERROR BluezAdvertisement::StopImpl()
{
- GDBusObject * adapterObject;
- GAutoPtr<BluezLEAdvertisingManager1> advMgr;
+ VerifyOrReturnError(mAdapter, CHIP_ERROR_UNINITIALIZED);
- VerifyOrExit(mIsAdvertising, ChipLogError(DeviceLayer, "FAIL: Advertising has already been disabled in %s", __func__));
- VerifyOrExit(mAdapter, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__));
+ // If the adapter configured in the Init() was unplugged, the g_dbus_interface_get_object()
+ // or bluez_object_get_leadvertising_manager1() might return nullptr (depending on the timing,
+ // since the D-Bus communication is handled on a separate thread). In such case, we should not
+ // report internal error, but adapter unavailable, so the application can handle the situation
+ // properly.
- adapterObject = g_dbus_interface_get_object(G_DBUS_INTERFACE(mAdapter.get()));
- VerifyOrExit(adapterObject != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapterObject in %s", __func__));
-
- advMgr.reset(bluez_object_get_leadvertising_manager1(reinterpret_cast<BluezObject *>(adapterObject)));
- VerifyOrExit(advMgr, ChipLogError(DeviceLayer, "FAIL: NULL advMgr in %s", __func__));
+ GDBusObject * adapterObject = g_dbus_interface_get_object(reinterpret_cast<GDBusInterface *>(mAdapter.get()));
+ VerifyOrReturnError(adapterObject != nullptr, BLE_ERROR_ADAPTER_UNAVAILABLE);
+ GAutoPtr<BluezLEAdvertisingManager1> advMgr(
+ bluez_object_get_leadvertising_manager1(reinterpret_cast<BluezObject *>(adapterObject)));
+ VerifyOrReturnError(advMgr, BLE_ERROR_ADAPTER_UNAVAILABLE);
bluez_leadvertising_manager1_call_unregister_advertisement(
advMgr.get(), mAdvPath, nullptr,
@@ -318,19 +332,15 @@
},
this);
-exit:
return CHIP_NO_ERROR;
}
CHIP_ERROR BluezAdvertisement::Stop()
{
VerifyOrReturnError(mIsInitialized, CHIP_ERROR_INCORRECT_STATE);
-
- CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+ VerifyOrReturnValue(mIsAdvertising, CHIP_NO_ERROR, ChipLogDetail(DeviceLayer, "BLE advertising already stopped"));
+ return PlatformMgrImpl().GLibMatterContextInvokeSync(
+[](BluezAdvertisement * self) { return self->StopImpl(); }, this);
- VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_INCORRECT_STATE,
- ChipLogError(Ble, "Failed to schedule BLE advertisement Stop() on CHIPoBluez thread"));
- return err;
}
} // namespace Internal
diff --git a/src/platform/Linux/bluez/BluezEndpoint.cpp b/src/platform/Linux/bluez/BluezEndpoint.cpp
index c32b1ec..e622407 100644
--- a/src/platform/Linux/bluez/BluezEndpoint.cpp
+++ b/src/platform/Linux/bluez/BluezEndpoint.cpp
@@ -57,6 +57,7 @@
#include <glib-object.h>
#include <glib.h>
+#include <ble/BleError.h>
#include <lib/support/BitFlags.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
@@ -263,35 +264,45 @@
void BluezEndpoint::RegisterGattApplicationDone(GObject * aObject, GAsyncResult * aResult)
{
GAutoPtr<GError> error;
- gboolean success = bluez_gatt_manager1_call_register_application_finish(reinterpret_cast<BluezGattManager1 *>(aObject), aResult,
- &error.GetReceiver());
+ if (!bluez_gatt_manager1_call_register_application_finish(reinterpret_cast<BluezGattManager1 *>(aObject), aResult,
+ &error.GetReceiver()))
+ {
+ ChipLogError(DeviceLayer, "FAIL: RegisterGattApplication: %s", error->message);
+ switch (error->code)
+ {
+ case G_DBUS_ERROR_NO_REPLY: // BlueZ crashed or the D-Bus connection is broken
+ case G_DBUS_ERROR_SERVICE_UNKNOWN: // BlueZ service is not available on the bus
+ case G_DBUS_ERROR_UNKNOWN_OBJECT: // Requested BLE adapter is not available
+ BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(BLE_ERROR_ADAPTER_UNAVAILABLE);
+ break;
+ default:
+ BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(CHIP_ERROR_INTERNAL);
+ }
+ return;
+ }
- VerifyOrReturn(success == TRUE, {
- ChipLogError(DeviceLayer, "FAIL: RegisterApplication : %s", error->message);
- BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(false);
- });
-
- BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(true);
- ChipLogDetail(DeviceLayer, "BluezPeripheralRegisterAppDone done");
+ ChipLogDetail(DeviceLayer, "GATT application registered successfully");
+ BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(CHIP_NO_ERROR);
}
CHIP_ERROR BluezEndpoint::RegisterGattApplicationImpl()
{
- GDBusObject * adapterObject;
- GAutoPtr<BluezGattManager1> gattMgr;
+ VerifyOrReturnError(mAdapter, CHIP_ERROR_UNINITIALIZED);
+
+ // If the adapter configured in the Init() was unplugged, the g_dbus_interface_get_object()
+ // or bluez_object_get_gatt_manager1() might return nullptr (depending on the timing, since
+ // the D-Bus communication is handled on a separate thread). In such case, we should not
+ // report internal error, but adapter unavailable, so the application can handle the situation
+ // properly.
+
+ GDBusObject * adapterObject = g_dbus_interface_get_object(reinterpret_cast<GDBusInterface *>(mAdapter.get()));
+ VerifyOrReturnError(adapterObject != nullptr, BLE_ERROR_ADAPTER_UNAVAILABLE);
+ GAutoPtr<BluezGattManager1> gattMgr(bluez_object_get_gatt_manager1(reinterpret_cast<BluezObject *>(adapterObject)));
+ VerifyOrReturnError(gattMgr, BLE_ERROR_ADAPTER_UNAVAILABLE);
+
GVariantBuilder optionsBuilder;
- GVariant * options;
-
- VerifyOrExit(mAdapter, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__));
-
- adapterObject = g_dbus_interface_get_object(G_DBUS_INTERFACE(mAdapter.get()));
- VerifyOrExit(adapterObject != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapterObject in %s", __func__));
-
- gattMgr.reset(bluez_object_get_gatt_manager1(reinterpret_cast<BluezObject *>(adapterObject)));
- VerifyOrExit(gattMgr, ChipLogError(DeviceLayer, "FAIL: NULL gattMgr in %s", __func__));
-
g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE("a{sv}"));
- options = g_variant_builder_end(&optionsBuilder);
+ GVariant * options = g_variant_builder_end(&optionsBuilder);
bluez_gatt_manager1_call_register_application(
gattMgr.get(), mpRootPath, options, nullptr,
@@ -300,7 +311,6 @@
},
this);
-exit:
return CHIP_NO_ERROR;
}
@@ -624,11 +634,8 @@
CHIP_ERROR BluezEndpoint::RegisterGattApplication()
{
- CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+ return PlatformMgrImpl().GLibMatterContextInvokeSync(
+[](BluezEndpoint * self) { return self->RegisterGattApplicationImpl(); }, this);
- VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_INCORRECT_STATE,
- ChipLogError(Ble, "Failed to schedule RegisterGattApplication() on CHIPoBluez thread"));
- return err;
}
CHIP_ERROR BluezEndpoint::Init(bool aIsCentral, uint32_t aAdapterId)