Skip to content

Commit

Permalink
[Linux] Wrap BlueZ connection functions in a class (#29798)
Browse files Browse the repository at this point in the history
* Do not use BLE_CONNECTION_OBJECT by internal implementation

* Wrap BluezConnection in a class

* Store const ref to connection in ConnectionDataBundle

* Simplify get connection MTU method

* Add proxy method for getting device address

* Allocate ConnectionDataBundle on stack

* Add destructor to IOChannel

* Remove Bluez from public method names

* Move IO channels creation to BluezConnection

* Fix notify callback setup for additional advertising

* Fix FD leak in case of g_variant_lookup failure

* Move IO channel handlers to BluezConnection class

* Manage IOChannel members with GAutoPtr

* Use on-stack array for reading characteristic

* Document FD closing behavior by setup methods

* Fix GSource deleter
  • Loading branch information
arkq authored Oct 19, 2023
1 parent a8a9659 commit 9f37258
Show file tree
Hide file tree
Showing 5 changed files with 409 additions and 360 deletions.
61 changes: 30 additions & 31 deletions src/platform/Linux/BLEManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,21 +344,26 @@ void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEv

uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
{
BluezConnection * connection = static_cast<BluezConnection *>(conId);
return (connection != nullptr) ? connection->mMtu : 0;
uint16_t mtu = 0;
VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));
mtu = conId->GetMTU();
exit:
return mtu;
}

bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
bool result = false;

VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));
VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID),
ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid service ID"));
VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX),
ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid characteristic ID"));

VerifyOrExit(BluezSubscribeCharacteristic(conId) == CHIP_NO_ERROR,
ChipLogError(DeviceLayer, "BluezSubscribeCharacteristic() failed"));
VerifyOrExit(conId->SubscribeCharacteristic() == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "SubscribeCharacteristic() failed"));
result = true;

exit:
Expand All @@ -369,13 +374,15 @@ bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, cons
{
bool result = false;

VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));
VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID),
ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid service ID"));
VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX),
ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid characteristic ID"));

VerifyOrExit(BluezUnsubscribeCharacteristic(conId) == CHIP_NO_ERROR,
ChipLogError(DeviceLayer, "BluezUnsubscribeCharacteristic() failed"));
VerifyOrExit(conId->UnsubscribeCharacteristic() == CHIP_NO_ERROR,
ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() failed"));
result = true;

exit:
Expand All @@ -386,9 +393,11 @@ bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
{
bool result = false;

VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));
ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %p)", conId);

VerifyOrExit(CloseBluezConnection(conId) == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "CloseBluezConnection() failed"));
VerifyOrExit(conId->CloseConnection() == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "CloseConnection() failed"));
result = true;

exit:
Expand All @@ -400,8 +409,9 @@ bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUU
{
bool result = false;

VerifyOrExit(SendBluezIndication(conId, std::move(pBuf)) == CHIP_NO_ERROR,
ChipLogError(DeviceLayer, "SendBluezIndication() failed"));
VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));
VerifyOrExit(conId->SendIndication(std::move(pBuf)) == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "SendIndication() failed"));
result = true;

exit:
Expand All @@ -413,13 +423,14 @@ bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::Ch
{
bool result = false;

VerifyOrExit(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));
VerifyOrExit(Ble::UUIDsMatch(svcId, &CHIP_BLE_SVC_ID),
ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid service ID"));
VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_RX),
ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid characteristic ID"));

VerifyOrExit(BluezSendWriteRequest(conId, std::move(pBuf)) == CHIP_NO_ERROR,
ChipLogError(DeviceLayer, "BluezSendWriteRequest() failed"));
VerifyOrExit(conId->SendWriteRequest(std::move(pBuf)) == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "SendWriteRequest() failed"));
result = true;

exit:
Expand Down Expand Up @@ -541,30 +552,18 @@ void BLEManagerImpl::CHIPoBluez_ConnectionClosed(BLE_CONNECTION_OBJECT conId)

void BLEManagerImpl::HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT conId)
{
CHIP_ERROR err = CHIP_NO_ERROR;

BluezConnection * connection = static_cast<BluezConnection *>(conId);

VerifyOrExit(connection != nullptr, ChipLogError(DeviceLayer, "Connection is NULL in HandleTXCharCCCDWrite"));
VerifyOrExit(connection->mpC2 != nullptr, ChipLogError(DeviceLayer, "C2 is NULL in HandleTXCharCCCDWrite"));
VerifyOrReturn(conId != BLE_CONNECTION_UNINITIALIZED,
ChipLogError(DeviceLayer, "BLE connection is not initialized in %s", __func__));

// Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
// whether the client is enabling or disabling indications.
{
ChipDeviceEvent event;
event.Type = connection->mIsNotify ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
event.CHIPoBLESubscribe.ConId = connection;
PlatformMgr().PostEventOrDie(&event);
}

ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", connection->mIsNotify ? "subscribe" : "unsubscribe");
ChipDeviceEvent event;
event.Type = conId->IsNotifyAcquired() ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
event.CHIPoBLESubscribe.ConId = conId;
PlatformMgr().PostEventOrDie(&event);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
// TODO: fail connection
}
ChipLogProgress(DeviceLayer, "CHIPoBLE %s received",
(event.Type == DeviceEventType::kCHIPoBLESubscribe) ? "subscribe" : "unsubscribe");
}

void BLEManagerImpl::HandleTXComplete(BLE_CONNECTION_OBJECT conId)
Expand Down
4 changes: 3 additions & 1 deletion src/platform/Linux/BlePlatformConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@
namespace chip {
namespace DeviceLayer {
namespace Internal {
struct BluezConnection;
class BluezConnection;
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip

// ==================== Platform Adaptations ====================
#define BLE_CONNECTION_OBJECT chip::DeviceLayer::Internal::BluezConnection *
#define BLE_CONNECTION_UNINITIALIZED nullptr

// ========== Platform-specific Configuration Overrides =========

/* none so far */
Loading

0 comments on commit 9f37258

Please sign in to comment.