Skip to content

Commit 6f7995b

Browse files
authored
[Linux] Dispatch BlueZ signals in BluezObjectManager (#32709)
* Notification facility for BLE adapter added/removed * Dispatch BlueZ signals in BluezObjectManager * Get rid of pointers in delegate public API * Fix deadlock when calling callback under mutex
1 parent 86af239 commit 6f7995b

11 files changed

+278
-125
lines changed

src/platform/Linux/BLEManagerImpl.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include <ble/BleError.h>
3939
#include <ble/CHIPBleServiceData.h>
40+
#include <lib/support/CHIPMemString.h>
4041
#include <lib/support/CodeUtils.h>
4142
#include <lib/support/SafeInt.h>
4243
#include <platform/CHIPDeviceLayer.h>
@@ -257,6 +258,22 @@ void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEv
257258
ChipLogDetail(DeviceLayer, "HandlePlatformSpecificBLEEvent %d", apEvent->Type);
258259
switch (apEvent->Type)
259260
{
261+
case DeviceEventType::kPlatformLinuxBLEAdapterAdded:
262+
ChipLogDetail(DeviceLayer, "BLE adapter added: id=%u address=%s", apEvent->Platform.BLEAdapter.mAdapterId,
263+
apEvent->Platform.BLEAdapter.mAdapterAddress);
264+
if (apEvent->Platform.BLEAdapter.mAdapterId == mAdapterId)
265+
{
266+
// TODO: Handle adapter added
267+
}
268+
break;
269+
case DeviceEventType::kPlatformLinuxBLEAdapterRemoved:
270+
ChipLogDetail(DeviceLayer, "BLE adapter removed: id=%u address=%s", apEvent->Platform.BLEAdapter.mAdapterId,
271+
apEvent->Platform.BLEAdapter.mAdapterAddress);
272+
if (apEvent->Platform.BLEAdapter.mAdapterId == mAdapterId)
273+
{
274+
// TODO: Handle adapter removed
275+
}
276+
break;
260277
case DeviceEventType::kPlatformLinuxBLECentralConnected:
261278
if (mBLEScanConfig.mBleScanState == BleScanState::kConnecting)
262279
{
@@ -792,6 +809,24 @@ CHIP_ERROR BLEManagerImpl::CancelConnection()
792809
return CHIP_NO_ERROR;
793810
}
794811

812+
void BLEManagerImpl::NotifyBLEAdapterAdded(unsigned int aAdapterId, const char * aAdapterAddress)
813+
{
814+
ChipDeviceEvent event;
815+
event.Type = DeviceEventType::kPlatformLinuxBLEAdapterAdded;
816+
event.Platform.BLEAdapter.mAdapterId = aAdapterId;
817+
Platform::CopyString(event.Platform.BLEAdapter.mAdapterAddress, aAdapterAddress);
818+
PlatformMgr().PostEventOrDie(&event);
819+
}
820+
821+
void BLEManagerImpl::NotifyBLEAdapterRemoved(unsigned int aAdapterId, const char * aAdapterAddress)
822+
{
823+
ChipDeviceEvent event;
824+
event.Type = DeviceEventType::kPlatformLinuxBLEAdapterRemoved;
825+
event.Platform.BLEAdapter.mAdapterId = aAdapterId;
826+
Platform::CopyString(event.Platform.BLEAdapter.mAdapterAddress, aAdapterAddress);
827+
PlatformMgr().PostEventOrDie(&event);
828+
}
829+
795830
void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(CHIP_ERROR error)
796831
{
797832
ChipDeviceEvent event;

src/platform/Linux/BLEManagerImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class BLEManagerImpl final : public BLEManager,
9393
static void HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT user_data);
9494
static void HandleTXComplete(BLE_CONNECTION_OBJECT user_data);
9595

96+
static void NotifyBLEAdapterAdded(unsigned int aAdapterId, const char * aAdapterAddress);
97+
static void NotifyBLEAdapterRemoved(unsigned int aAdapterId, const char * aAdapterAddress);
9698
static void NotifyBLEPeripheralRegisterAppComplete(CHIP_ERROR error);
9799
static void NotifyBLEPeripheralAdvStartComplete(CHIP_ERROR error);
98100
static void NotifyBLEPeripheralAdvStopComplete(CHIP_ERROR error);

src/platform/Linux/CHIPDevicePlatformEvent.h

+7
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ enum PublicPlatformSpecificEventTypes
4545
enum InternalPlatformSpecificEventTypes
4646
{
4747
kPlatformLinuxEvent = kRange_InternalPlatformSpecific,
48+
kPlatformLinuxBLEAdapterAdded,
49+
kPlatformLinuxBLEAdapterRemoved,
4850
kPlatformLinuxBLECentralConnected,
4951
kPlatformLinuxBLECentralConnectFailed,
5052
kPlatformLinuxBLEWriteComplete,
@@ -67,6 +69,11 @@ struct ChipDevicePlatformEvent
6769
{
6870
union
6971
{
72+
struct
73+
{
74+
unsigned int mAdapterId;
75+
char mAdapterAddress[18];
76+
} BLEAdapter;
7077
struct
7178
{
7279
BLE_CONNECTION_OBJECT mConnection;

src/platform/Linux/bluez/BluezConnection.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,22 @@ namespace {
4545
gboolean BluezIsServiceOnDevice(BluezGattService1 * aService, BluezDevice1 * aDevice)
4646
{
4747
const auto * servicePath = bluez_gatt_service1_get_device(aService);
48-
const auto * devicePath = g_dbus_proxy_get_object_path(G_DBUS_PROXY(aDevice));
48+
const auto * devicePath = g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(aDevice));
4949
return strcmp(servicePath, devicePath) == 0 ? TRUE : FALSE;
5050
}
5151

5252
gboolean BluezIsCharOnService(BluezGattCharacteristic1 * aChar, BluezGattService1 * aService)
5353
{
5454
const auto * charPath = bluez_gatt_characteristic1_get_service(aChar);
55-
const auto * servicePath = g_dbus_proxy_get_object_path(G_DBUS_PROXY(aService));
55+
const auto * servicePath = g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(aService));
5656
ChipLogDetail(DeviceLayer, "Char %s on service %s", charPath, servicePath);
5757
return strcmp(charPath, servicePath) == 0 ? TRUE : FALSE;
5858
}
5959

6060
} // namespace
6161

62-
BluezConnection::BluezConnection(const BluezEndpoint & aEndpoint, BluezDevice1 * apDevice) :
63-
mDevice(reinterpret_cast<BluezDevice1 *>(g_object_ref(apDevice)))
62+
BluezConnection::BluezConnection(const BluezEndpoint & aEndpoint, BluezDevice1 & aDevice) :
63+
mDevice(reinterpret_cast<BluezDevice1 *>(g_object_ref(&aDevice)))
6464
{
6565
Init(aEndpoint);
6666
}

src/platform/Linux/bluez/BluezConnection.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class BluezEndpoint;
3939
class BluezConnection
4040
{
4141
public:
42-
BluezConnection(const BluezEndpoint & aEndpoint, BluezDevice1 * apDevice);
42+
BluezConnection(const BluezEndpoint & aEndpoint, BluezDevice1 & aDevice);
4343
~BluezConnection() = default;
4444

4545
const char * GetPeerAddress() const;

src/platform/Linux/bluez/BluezEndpoint.cpp

+24-65
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,6 @@ static gboolean BluezCharacteristicConfirmError(BluezGattCharacteristic1 * aChar
228228
return TRUE;
229229
}
230230

231-
static gboolean BluezIsDeviceOnAdapter(BluezDevice1 * aDevice, BluezAdapter1 * aAdapter)
232-
{
233-
return strcmp(bluez_device1_get_adapter(aDevice), g_dbus_proxy_get_object_path(G_DBUS_PROXY(aAdapter))) == 0 ? TRUE : FALSE;
234-
}
235-
236231
BluezGattCharacteristic1 * BluezEndpoint::CreateGattCharacteristic(BluezGattService1 * aService, const char * aCharName,
237232
const char * aUUID, const char * const * aFlags)
238233
{
@@ -305,12 +300,12 @@ CHIP_ERROR BluezEndpoint::RegisterGattApplicationImpl()
305300
}
306301

307302
/// Update the table of open BLE connections whenever a new device is spotted or its attributes have changed.
308-
void BluezEndpoint::UpdateConnectionTable(BluezDevice1 * apDevice)
303+
void BluezEndpoint::UpdateConnectionTable(BluezDevice1 & aDevice)
309304
{
310-
const char * objectPath = g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(apDevice));
305+
const char * objectPath = g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(&aDevice));
311306
BluezConnection * connection = GetBluezConnection(objectPath);
312307

313-
if (connection != nullptr && !bluez_device1_get_connected(apDevice))
308+
if (connection != nullptr && !bluez_device1_get_connected(&aDevice))
314309
{
315310
ChipLogDetail(DeviceLayer, "Bluez disconnected");
316311
BLEManagerImpl::CHIPoBluez_ConnectionClosed(connection);
@@ -323,35 +318,22 @@ void BluezEndpoint::UpdateConnectionTable(BluezDevice1 * apDevice)
323318

324319
if (connection == nullptr)
325320
{
326-
HandleNewDevice(apDevice);
321+
HandleNewDevice(aDevice);
327322
}
328323
}
329324

330-
void BluezEndpoint::BluezSignalInterfacePropertiesChanged(GDBusObjectManagerClient * aManager, GDBusObjectProxy * aObject,
331-
GDBusProxy * aInterface, GVariant * aChangedProperties,
332-
const char * const * aInvalidatedProps)
325+
void BluezEndpoint::HandleNewDevice(BluezDevice1 & aDevice)
333326
{
334-
VerifyOrReturn(mAdapter, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__));
335-
VerifyOrReturn(strcmp(g_dbus_proxy_get_interface_name(aInterface), DEVICE_INTERFACE) == 0, );
336-
337-
BluezDevice1 * device = BLUEZ_DEVICE1(aInterface);
338-
VerifyOrReturn(BluezIsDeviceOnAdapter(device, mAdapter.get()));
339-
340-
UpdateConnectionTable(device);
341-
}
327+
VerifyOrReturn(bluez_device1_get_connected(&aDevice));
328+
VerifyOrReturn(!mIsCentral || bluez_device1_get_services_resolved(&aDevice));
342329

343-
void BluezEndpoint::HandleNewDevice(BluezDevice1 * device)
344-
{
345-
VerifyOrReturn(bluez_device1_get_connected(device));
346-
VerifyOrReturn(!mIsCentral || bluez_device1_get_services_resolved(device));
347-
348-
const char * objectPath = g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(device));
330+
const char * objectPath = g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(&aDevice));
349331
BluezConnection * conn = GetBluezConnection(objectPath);
350332
VerifyOrReturn(conn == nullptr,
351333
ChipLogError(DeviceLayer, "FAIL: Connection already tracked: conn=%p device=%s path=%s", conn,
352334
conn->GetPeerAddress(), objectPath));
353335

354-
conn = chip::Platform::New<BluezConnection>(*this, device);
336+
conn = chip::Platform::New<BluezConnection>(*this, aDevice);
355337
mpPeerDevicePath = g_strdup(objectPath);
356338
mConnMap[mpPeerDevicePath] = conn;
357339

@@ -360,24 +342,20 @@ void BluezEndpoint::HandleNewDevice(BluezDevice1 * device)
360342
BLEManagerImpl::HandleNewConnection(conn);
361343
}
362344

363-
void BluezEndpoint::BluezSignalOnObjectAdded(GDBusObjectManager * aManager, GDBusObject * aObject)
345+
void BluezEndpoint::OnDeviceAdded(BluezDevice1 & device)
364346
{
365-
// TODO: right now we do not handle addition/removal of adapters
366-
// Primary focus here is to handle addition of a device
367-
GAutoPtr<BluezDevice1> device(bluez_object_get_device1(reinterpret_cast<BluezObject *>(aObject)));
368-
VerifyOrReturn(device);
347+
HandleNewDevice(device);
348+
}
369349

370-
if (BluezIsDeviceOnAdapter(device.get(), mAdapter.get()) == TRUE)
371-
{
372-
HandleNewDevice(device.get());
373-
}
350+
void BluezEndpoint::OnDevicePropertyChanged(BluezDevice1 & device, GVariant * changedProps, const char * const * invalidatedProps)
351+
{
352+
UpdateConnectionTable(device);
374353
}
375354

376-
void BluezEndpoint::BluezSignalOnObjectRemoved(GDBusObjectManager * aManager, GDBusObject * aObject)
355+
void BluezEndpoint::OnDeviceRemoved(BluezDevice1 & device)
377356
{
378-
// TODO: for Device1, lookup connection, and call otPlatTobleHandleDisconnected
379-
// for Adapter1: unclear, crash if this pertains to our adapter? at least null out the self->mAdapter.
380-
// for Characteristic1, or GattService -- handle here via calling otPlatTobleHandleDisconnected, or ignore.
357+
// Handling device removal is not necessary because disconnection is already handled
358+
// in the OnDevicePropertyChanged() - we are checking for the "Connected" property.
381359
}
382360

383361
BluezGattService1 * BluezEndpoint::CreateGattService(const char * aUUID)
@@ -545,30 +523,7 @@ void BluezEndpoint::SetupGattServer(GDBusConnection * aConn)
545523

546524
CHIP_ERROR BluezEndpoint::SetupEndpointBindings()
547525
{
548-
GAutoPtr<GError> err;
549-
GAutoPtr<GDBusConnection> conn(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err.GetReceiver()));
550-
VerifyOrReturnError(conn != nullptr, CHIP_ERROR_INTERNAL,
551-
ChipLogError(DeviceLayer, "FAIL: get bus sync in %s, error: %s", __func__, err->message));
552-
553-
SetupGattServer(conn.get());
554-
555-
g_signal_connect(mObjectManager.GetObjectManager(), "object-added",
556-
G_CALLBACK(+[](GDBusObjectManager * aMgr, GDBusObject * aObj, BluezEndpoint * self) {
557-
return self->BluezSignalOnObjectAdded(aMgr, aObj);
558-
}),
559-
this);
560-
g_signal_connect(mObjectManager.GetObjectManager(), "object-removed",
561-
G_CALLBACK(+[](GDBusObjectManager * aMgr, GDBusObject * aObj, BluezEndpoint * self) {
562-
return self->BluezSignalOnObjectRemoved(aMgr, aObj);
563-
}),
564-
this);
565-
g_signal_connect(mObjectManager.GetObjectManager(), "interface-proxy-properties-changed",
566-
G_CALLBACK(+[](GDBusObjectManagerClient * aMgr, GDBusObjectProxy * aObj, GDBusProxy * aIface,
567-
GVariant * aChangedProps, const char * const * aInvalidatedProps, BluezEndpoint * self) {
568-
return self->BluezSignalInterfacePropertiesChanged(aMgr, aObj, aIface, aChangedProps, aInvalidatedProps);
569-
}),
570-
this);
571-
526+
SetupGattServer(mObjectManager.GetConnection());
572527
return CHIP_NO_ERROR;
573528
}
574529

@@ -586,7 +541,11 @@ CHIP_ERROR BluezEndpoint::Init(BluezAdapter1 * apAdapter, bool aIsCentral)
586541
mAdapter.reset(reinterpret_cast<BluezAdapter1 *>(g_object_ref(apAdapter)));
587542
mIsCentral = aIsCentral;
588543

589-
CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(
544+
CHIP_ERROR err = mObjectManager.SubscribeDeviceNotifications(mAdapter.get(), this);
545+
VerifyOrReturnError(err == CHIP_NO_ERROR, err,
546+
ChipLogError(DeviceLayer, "Failed to subscribe for notifications: %" CHIP_ERROR_FORMAT, err.Format()));
547+
548+
err = PlatformMgrImpl().GLibMatterContextInvokeSync(
590549
+[](BluezEndpoint * self) { return self->SetupEndpointBindings(); }, this);
591550
VerifyOrReturnError(err == CHIP_NO_ERROR, err,
592551
ChipLogError(DeviceLayer, "Failed to schedule endpoint initialization: %" CHIP_ERROR_FORMAT, err.Format()));

src/platform/Linux/bluez/BluezEndpoint.h

+8-9
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ namespace chip {
6565
namespace DeviceLayer {
6666
namespace Internal {
6767

68-
class BluezEndpoint
68+
class BluezEndpoint : public BluezObjectManagerAdapterNotificationsDelegate
6969
{
7070
public:
7171
BluezEndpoint(BluezObjectManager & aObjectManager) : mObjectManager(aObjectManager) {}
@@ -80,6 +80,11 @@ class BluezEndpoint
8080
CHIP_ERROR ConnectDevice(BluezDevice1 & aDevice);
8181
void CancelConnect();
8282

83+
// Members that implement virtual methods on BluezObjectManagerAdapterNotificationsDelegate
84+
void OnDeviceAdded(BluezDevice1 & device) override;
85+
void OnDevicePropertyChanged(BluezDevice1 & device, GVariant * changedProps, const char * const * invalidatedProps) override;
86+
void OnDeviceRemoved(BluezDevice1 & device) override;
87+
8388
private:
8489
CHIP_ERROR SetupEndpointBindings();
8590
void SetupGattServer(GDBusConnection * aConn);
@@ -89,8 +94,8 @@ class BluezEndpoint
8994
BluezGattCharacteristic1 * CreateGattCharacteristic(BluezGattService1 * aService, const char * aCharName, const char * aUUID,
9095
const char * const * aFlags);
9196

92-
void HandleNewDevice(BluezDevice1 * aDevice);
93-
void UpdateConnectionTable(BluezDevice1 * aDevice);
97+
void HandleNewDevice(BluezDevice1 & aDevice);
98+
void UpdateConnectionTable(BluezDevice1 & aDevice);
9499
BluezConnection * GetBluezConnection(const char * aPath);
95100
BluezConnection * GetBluezConnectionViaDevice();
96101

@@ -99,12 +104,6 @@ class BluezEndpoint
99104
gboolean BluezCharacteristicAcquireNotify(BluezGattCharacteristic1 * aChar, GDBusMethodInvocation * aInv, GVariant * aOptions);
100105
gboolean BluezCharacteristicConfirm(BluezGattCharacteristic1 * aChar, GDBusMethodInvocation * aInv);
101106

102-
void BluezSignalOnObjectAdded(GDBusObjectManager * aManager, GDBusObject * aObject);
103-
void BluezSignalOnObjectRemoved(GDBusObjectManager * aManager, GDBusObject * aObject);
104-
void BluezSignalInterfacePropertiesChanged(GDBusObjectManagerClient * aManager, GDBusObjectProxy * aObject,
105-
GDBusProxy * aInterface, GVariant * aChangedProperties,
106-
const char * const * aInvalidatedProps);
107-
108107
void RegisterGattApplicationDone(GObject * aObject, GAsyncResult * aResult);
109108
CHIP_ERROR RegisterGattApplicationImpl();
110109

0 commit comments

Comments
 (0)