Skip to content

Commit

Permalink
Add an adapter iterator class to bluez (#4838)
Browse files Browse the repository at this point in the history
* Add an adapter iterator class to bluez

* code review updates

* Fix typo in method

* Fix compilation and off-by-one error

* Ensure we unref the adapter during listing

* Remove unused variable

* Fix typos in comments - I clobbered the fixes that Justin pushed

* Fix typos in comments - I clobbered the fixes that Justin pushed
  • Loading branch information
andy31415 authored and pull[bot] committed Mar 4, 2021
1 parent 522edeb commit 1094604
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/lib/support/CHIPMemString.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ inline char * CopyString(char * dest, const char * source, size_t length)
return dest;
}

/**
* Convenience method for CopyString to auto-detect destination size.
*/
template <size_t N>
inline char * CopyString(char (&dest)[N], const char * source)
{
return CopyString(dest, source, N);
}

/**
* This function copies a C-style string to memory newly allocated by Platform::MemoryAlloc().
*
Expand Down
91 changes: 91 additions & 0 deletions src/platform/Linux/CHIPBluezHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include <ble/CHIPBleServiceData.h>
#include <platform/CHIPDeviceLayer.h>
#include <protocols/Protocols.h>
#include <support/CHIPMemString.h>

#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <errno.h>
Expand All @@ -72,6 +73,7 @@
using namespace ::nl;
using namespace chip::SetupPayloadData;
using namespace chip::Protocols;
using chip::Platform::CopyString;

namespace chip {
namespace DeviceLayer {
Expand Down Expand Up @@ -2008,6 +2010,95 @@ CHIP_ERROR ConnectDevice(BluezDevice1 * apDevice)
return error;
}

AdapterIterator::~AdapterIterator()
{
if (mManager != nullptr)
{
g_object_unref(mManager);
}

if (mObjectList != nullptr)
{
g_list_free_full(mObjectList, g_object_unref);
}
}

void AdapterIterator::Initialize()
{
GError * error = nullptr;

mManager = g_dbus_object_manager_client_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
BLUEZ_INTERFACE, "/", bluez_object_manager_client_get_proxy_type,
nullptr /* unused user data in the Proxy Type Func */,
nullptr /*destroy notify */, nullptr /* cancellable */, &error);

VerifyOrExit(mManager != nullptr, ChipLogError(DeviceLayer, "Failed to get DBUS object manager for listing adapters."));

mObjectList = g_dbus_object_manager_get_objects(mManager);
mCurrentListItem = mObjectList;

exit:
if (error != nullptr)
{
ChipLogError(DeviceLayer, "DBus error: %s", error->message);
g_error_free(error);
}
}

bool AdapterIterator::Advance()
{
if (mCurrentListItem == nullptr)
{
return false;
}

while (mCurrentListItem != nullptr)
{
BluezAdapter1 * adapter = bluez_object_get_adapter1(BLUEZ_OBJECT(mCurrentListItem->data));
if (adapter == nullptr)
{
mCurrentListItem = mCurrentListItem->next;
continue;
}

// PATH is of the for BLUEZ_PATH / hci<nr>, i.e. like
// '/org/bluez/hci0'
// Index represents the number after hci
const char * path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(adapter));
unsigned index = 0;

if (sscanf(path, BLUEZ_PATH "/hci%u", &index) != 1)
{
ChipLogError(DeviceLayer, "Failed to extract HCI index from '%s'", path);
index = 0;
}

mCurrent.index = index;
CopyString(mCurrent.address, bluez_adapter1_get_address(adapter));
CopyString(mCurrent.alias, bluez_adapter1_get_alias(adapter));
CopyString(mCurrent.name, bluez_adapter1_get_name(adapter));
mCurrent.powered = bluez_adapter1_get_powered(adapter);

g_object_unref(adapter);

mCurrentListItem = mCurrentListItem->next;

return true;
}

return false;
}

bool AdapterIterator::Next()
{
if (mManager == nullptr)
{
Initialize();
}

return Advance();
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
Expand Down
55 changes: 55 additions & 0 deletions src/platform/Linux/CHIPBluezHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,61 @@ CHIP_ERROR StopDiscovery(BluezEndpoint * apEndpoint);

CHIP_ERROR ConnectDevice(BluezDevice1 * apDevice);

/// Iterates over available BlueZ adapters
///
/// Usage example:
///
/// AdapterIterator iterator;
/// while (iterator.Next()) {
/// std::cout << iterator.GetAddress() << std::endl;
/// }
class AdapterIterator
{
public:
~AdapterIterator();

/// Moves to the next DBUS interface.
///
/// MUST be called before any of the 'current value' methods are
/// used (iterator gets initialized on the first call of Next).
bool Next();

// Information about the current value. Safe to call only after
// "Next" has returned true.
uint32_t GetIndex() const { return mCurrent.index; }
const char * GetAddress() const { return mCurrent.address; }
const char * GetAlias() const { return mCurrent.alias; }
const char * GetName() const { return mCurrent.name; }
bool IsPowered() const { return mCurrent.powered; }

private:
/// Sets up the DBUS manager and loads the list
void Initialize();

/// Loads the next value in the list.
///
/// Returns true if a value could be loaded, false if no more items to
/// iterate through.
bool Advance();

static constexpr size_t kMaxAddressLength = 19; // xx:xx:xx:xx:xx:xx
static constexpr size_t kMaxNameLength = 64;

GDBusObjectManager * mManager = nullptr; // DBus connection
GList * mObjectList = nullptr; // listing of objects on the bus
GList * mCurrentListItem = nullptr; // current item viewed in the list

// data valid only if Next() returns true
struct
{
uint32_t index;
char address[kMaxAddressLength];
char alias[kMaxNameLength];
char name[kMaxNameLength];
bool powered;
} mCurrent = { 0 };
};

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
Expand Down

0 comments on commit 1094604

Please sign in to comment.