From a6d4061fbeabe75e1789a97be2457ff1274b9a73 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 18 Jan 2021 18:44:04 +0100 Subject: DBTManager/DBTAdapter: DBTManager own zero or all DBTAdapter DBTManager/DBTAdapter Relationship (C++) aligning to Java DBTManager owning DBTAdapter to harmonize and simplify API and DBTAdapter lifecycle in respect to the event-driven ChangedAdapterSetFunc() approach. API doc reflecting this change WIP. DBTManager: - Owns all DBTAdapter - processAdapterRemoved: Issue DBTAdapter::close() (align Java + C++ behavior) - ChangedAdapterSetFunc passes 'std::shared_ptr&', instead of 'dev_id' (like Java) - Fix adding ChangedAdapterSetFunc: Only pass all known DBTAdapter through newly added callback, not all. - Aligned method names with Java - DBTAdapter: - No public ctor (DBTManager owns all); - Owns adapterInfo; - dtor unregisters instance in DBTManager; - dev_id is uint16_t; AdapterInfo: Support copy/move ctor and copy assignment --- api/direct_bt/ATTPDUTypes.hpp | 26 ++- api/direct_bt/DBTAdapter.hpp | 65 +++----- api/direct_bt/DBTManager.hpp | 76 ++++----- api/direct_bt/DBTTypes.hpp | 41 ++++- api/direct_bt/DirectBT.hpp | 5 +- api/direct_bt/MgmtTypes.hpp | 2 +- examples/direct_bt_scanner00/dbt_scanner00.cpp | 25 ++- examples/direct_bt_scanner01/dbt_scanner01.cpp | 25 ++- examples/direct_bt_scanner10/dbt_scanner10.cpp | 123 +++----------- examples/java/DBTScanner10.java | 59 ++----- java/direct_bt/tinyb/DBTAdapter.java | 8 +- java/direct_bt/tinyb/DBTManager.java | 30 +++- java/jni/direct_bt/DBTAdapter.cxx | 7 +- java/jni/direct_bt/DBTDevice.cxx | 2 + java/jni/direct_bt/DBTManager.cxx | 39 +---- java/org/tinyb/BluetoothManager.java | 4 + src/direct_bt/DBTAdapter.cpp | 66 +++----- src/direct_bt/DBTDevice.cpp | 1 + src/direct_bt/DBTManager.cpp | 216 +++++++++++++------------ src/direct_bt/GATTHandler.cpp | 1 + src/direct_bt/MgmtTypes.cpp | 4 +- 21 files changed, 367 insertions(+), 458 deletions(-) diff --git a/api/direct_bt/ATTPDUTypes.hpp b/api/direct_bt/ATTPDUTypes.hpp index 990d5362..b5af035c 100644 --- a/api/direct_bt/ATTPDUTypes.hpp +++ b/api/direct_bt/ATTPDUTypes.hpp @@ -77,17 +77,18 @@ * - - - - - - - - - - - - - - - * * From a user perspective the following hierarchy is provided - * - DBTAdapter has no or more - * - DBTDevice has no or more - * - GATTService has no or more - * - GATTCharacteristic has no or more - * - GATTDescriptor + * - DBTManager has zero or more + * - DBTAdapter has zero or more + * - DBTDevice has zero or more + * - GATTService has zero or more + * - GATTCharacteristic has zero or more + * - GATTDescriptor * * - - - - - - - - - - - - - - - * * Object lifecycle with all instances and marked weak back-references to their owner * - DBTManager singleton instance for all - * - DBTAdapter ownership by user (C++) and BluetoothManager (Java) + * - DBTAdapter ownership by DBTManager * - DBTDevice ownership by DBTAdapter * - GATTHandler ownership by DBTDevice, with weak DBTDevice back-reference * - GATTService ownership by GATTHandler, with weak GATTHandler back-reference @@ -96,6 +97,19 @@ * * - - - - - - - - - - - - - - - * + * Mapped names from C++ implementation to Java implementation and to Java interface: + * + * C++ | Java Implementation | Java Interface | + * :------------------| :---------------------| :---------------------------| + * DBTManager | DBTManager | BluetoothManager | + * DBTAdapter | DBTAdapter | BluetoothAdapter | + * DBTDevice | DBTDevice | BluetoothDevice | + * GATTService | DBTGattService | BluetoothGattService | + * GATTCharacteristic | DBTGattCharacteristic | BluetoothGattCharacteristic | + * GATTDescriptor | DBTGattDescriptor | BluetoothGattDescriptor | + * + * - - - - - - - - - - - - - - - + * * A fully event driven workflow from discovery to GATT programming is supported. * * AdapterStatusListener allows listening to adapter changes and device discovery diff --git a/api/direct_bt/DBTAdapter.hpp b/api/direct_bt/DBTAdapter.hpp index 10735eb6..1ab4fc90 100644 --- a/api/direct_bt/DBTAdapter.hpp +++ b/api/direct_bt/DBTAdapter.hpp @@ -42,11 +42,11 @@ #include "DBTDevice.hpp" #include "HCIHandler.hpp" -#include "DBTManager.hpp" namespace direct_bt { class DBTAdapter; // forward + class DBTManager; // forward /** * {@link DBTAdapter} status listener for {@link DBTDevice} discovery events: Added, updated and removed; @@ -202,8 +202,11 @@ namespace direct_bt { class DBTAdapter : public DBTObject { private: + friend DBTManager; + const bool debug_event, debug_lock; DBTManager& mgmt; + AdapterInfo adapterInfo; public: /** @@ -212,13 +215,12 @@ namespace direct_bt { * The internal device id is constant across the adapter lifecycle, * but may change after its destruction. */ - const int dev_id; + const uint16_t dev_id; private: HCIHandler hci; std::atomic old_settings; - std::shared_ptr adapterInfo; std::atomic btMode = BTMode::NONE; NameAndShortName localName; std::atomic currentMetaScanType; // = ScanType::NONE @@ -248,6 +250,8 @@ namespace direct_bt { static std::shared_ptr findDevice(device_list_t & devices, const EUI48 & address, const BDAddressType addressType) noexcept; static std::shared_ptr findDevice(device_list_t & devices, DBTDevice const & device) noexcept; + DBTAdapter(DBTManager& mgmt_, const AdapterInfo& adapterInfo_) noexcept; + /** * Closes all device connections, stops discovery and cleans up all references. *

@@ -329,35 +333,6 @@ namespace direct_bt { public: - /** - * Using the default adapter device - *

- * The default adapter is either the first POWERED adapter, - * or none - in which case this instance !isValid() - *

- */ - DBTAdapter() noexcept; - - /** - * Using the identified adapter with given mac address. - * - * @param[in] mac address - */ - DBTAdapter(EUI48 &mac) noexcept; - - /** - * Using the identified adapter with given dev_id, - * or the default adapter device if dev_id < 0. - *

- * The default adapter is either the first POWERED adapter, - * or none - in which case this instance !isValid(). - *

- * - * @param[in] dev_id an already identified HCI device id - * or use -1 to choose the default adapter. - */ - DBTAdapter(const int dev_id) noexcept; - DBTAdapter(const DBTAdapter&) = delete; void operator=(const DBTAdapter&) = delete; @@ -367,7 +342,8 @@ namespace direct_bt { ~DBTAdapter() noexcept; /** - * Closes this instance, usually being called by destructor or when this adapter is being removed. + * Closes this instance, usually being called by destructor or when this adapter is being removed + * as recognized and handled by DBTManager. *

* Renders this adapter's DBTAdapter#isValid() state to false. *

@@ -381,8 +357,6 @@ namespace direct_bt { return std::string(JAVA_DBT_PACKAGE "DBTAdapter"); } - bool hasDevId() const noexcept { return 0 <= dev_id; } - /** * Returns whether the adapter is valid, plugged in and powered. * @return true if DBTAdapter::isValid(), HCIHandler::isOpen() and AdapterSetting::POWERED state is set. @@ -390,7 +364,7 @@ namespace direct_bt { * @see #isValid() */ bool isPowered() const noexcept { - return isValid() && hci.isOpen() && adapterInfo->isCurrentSettingBitSet(AdapterSetting::POWERED); + return isValid() && hci.isOpen() && adapterInfo.isCurrentSettingBitSet(AdapterSetting::POWERED); } /** @@ -400,15 +374,15 @@ namespace direct_bt { * @see #isValid() */ bool isSuspended() const noexcept { - return isValid() && hci.isOpen() && !adapterInfo->isCurrentSettingBitSet(AdapterSetting::POWERED); + return isValid() && hci.isOpen() && !adapterInfo.isCurrentSettingBitSet(AdapterSetting::POWERED); } bool hasSecureConnections() const noexcept { - return adapterInfo->isCurrentSettingBitSet(AdapterSetting::SECURE_CONN); + return adapterInfo.isCurrentSettingBitSet(AdapterSetting::SECURE_CONN); } bool hasSecureSimplePairing() const noexcept { - return adapterInfo->isCurrentSettingBitSet(AdapterSetting::SSP); + return adapterInfo.isCurrentSettingBitSet(AdapterSetting::SSP); } /** @@ -422,18 +396,23 @@ namespace direct_bt { return DBTObject::isValid(); } - EUI48 const & getAddress() const noexcept { return adapterInfo->address; } - std::string getAddressString() const noexcept { return adapterInfo->address.toString(); } + /** + * Returns the current BTMode of this adapter. + */ + BTMode getBTMode() const noexcept { return adapterInfo.getCurrentBTMode(); } + + EUI48 const & getAddress() const noexcept { return adapterInfo.address; } + std::string getAddressString() const noexcept { return adapterInfo.address.toString(); } /** * Returns the system name. */ - std::string getName() const noexcept { return adapterInfo->getName(); } + std::string getName() const noexcept { return adapterInfo.getName(); } /** * Returns the short system name. */ - std::string getShortName() const noexcept { return adapterInfo->getShortName(); } + std::string getShortName() const noexcept { return adapterInfo.getShortName(); } /** * Returns the local friendly name and short_name. Contains empty strings if not set. diff --git a/api/direct_bt/DBTManager.hpp b/api/direct_bt/DBTManager.hpp index f158f89d..e538704d 100644 --- a/api/direct_bt/DBTManager.hpp +++ b/api/direct_bt/DBTManager.hpp @@ -45,6 +45,7 @@ #include "OctetTypes.hpp" #include "HCIComm.hpp" #include "MgmtTypes.hpp" +#include "DBTAdapter.hpp" namespace direct_bt { @@ -146,15 +147,20 @@ namespace direct_bt { * The callback is performed on a dedicated thread, * allowing the user to perform complex operations. *

+ *

+ * If an adapter is being removed from the system, + * DBTAdapter::close() is being called by DBTManager after issuing all + * ChangedAdapterSetFunc calls. + *

* * @param added true if adapter was newly added, otherwise removed from system - * @param adapterInfo the adapter's AdapterInfo, inclusive the dev_id + * @param adapter the shared DBTAdapter reference * @return ignored * @see ChangedAdapterSetCallback * @see DBTManager::addChangedAdapterSetCallback() * @see DBTManager::removeChangedAdapterSetCallback() */ - typedef bool (*ChangedAdapterSetFunc)(bool added, const AdapterInfo& adapterInfo); + typedef bool (*ChangedAdapterSetFunc)(bool added, std::shared_ptr& adapter); /** * Callback jau::FunctionDef to receive change events regarding the system's adapter set, @@ -167,15 +173,20 @@ namespace direct_bt { * The callback is performed on a dedicated thread, * allowing the user to perform complex operations. *

+ *

+ * If an adapter is being removed from the system, + * DBTAdapter::close() is being called by DBTManager after issuing all + * ChangedAdapterSetFunc calls. + *

* * @param added true if adapter was newly added, otherwise removed from system - * @param adapterInfo the adapter's AdapterInfo, inclusive the dev_id + * @param adapter the shared DBTAdapter reference * @return ignored * @see ChangedAdapterSetFunc * @see DBTManager::addChangedAdapterSetCallback() * @see DBTManager::removeChangedAdapterSetCallback() */ - typedef jau::FunctionDef ChangedAdapterSetCallback; + typedef jau::FunctionDef&> ChangedAdapterSetCallback; typedef jau::cow_darray ChangedAdapterSetCallbackList; /** @@ -197,6 +208,8 @@ namespace direct_bt { static const pid_t pidSelf; private: + friend DBTAdapter::~DBTAdapter() noexcept; + static std::mutex mtx_singleton; struct WhitelistElem { @@ -237,8 +250,8 @@ namespace direct_bt { ChangedAdapterSetCallbackList mgmtChangedAdapterSetCallbackList; - typedef jau::cow_darray> adapterInfos_t; - adapterInfos_t adapterInfos; + typedef jau::cow_darray> adapters_t; + adapters_t adapters; /** * Using defaultIOCapability on added AdapterInfo. @@ -267,27 +280,28 @@ namespace direct_bt { void operator=(const DBTManager&) = delete; void setAdapterMode(const uint16_t dev_id, const uint8_t ssp, const uint8_t bredr, const uint8_t le) noexcept; - std::shared_ptr initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept; - void shutdownAdapter(const uint16_t dev_id) noexcept; + std::unique_ptr initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept; + void shutdownAdapter(DBTAdapter& adapter) noexcept; void processAdapterAdded(std::unique_ptr e) noexcept; void processAdapterRemoved(std::unique_ptr e) noexcept; bool mgmtEvNewSettingsCB(const MgmtEvent& e) noexcept; bool mgmtEventAnyCB(const MgmtEvent& e) noexcept; - int findAdapterInfoIndex(const uint16_t dev_id) const noexcept; + std::shared_ptr addAdapter(const AdapterInfo& ai) noexcept; /** - * Adds the given AdapterInfo if representing a new dev_id. - * @return true if newly added dev_id, otherwise false if dev_id already exists. + * Removes the AdapterInfo with the given dev_id + * @return the removed instance or nullptr if not found. */ - bool addAdapterInfo(std::shared_ptr ai) noexcept; + std::shared_ptr removeAdapter(const uint16_t dev_id) noexcept; /** - * Removes the AdapterInfo with the given dev_id - * @return the removed instance or nullptr if not found. + * Removal entry for DBTAdapter::~DBTAdapter + * @param adapter pointer to the dtor'ed adapter + * @return true if contained and removed, otherwise false */ - std::shared_ptr removeAdapterInfo(const uint16_t dev_id) noexcept; + bool removeAdapter(DBTAdapter* adapter) noexcept; public: /** @@ -332,7 +346,7 @@ namespace direct_bt { } std::string toString() const noexcept override { - return "MgmtHandler[BTMode "+getBTModeString(defaultBTMode)+", "+std::to_string(adapterInfos.size())+" adapter, "+javaObjectToString()+"]"; + return "MgmtHandler[BTMode "+getBTModeString(defaultBTMode)+", "+std::to_string(adapters.size())+" adapter, "+javaObjectToString()+"]"; } /** retrieve information gathered at startup */ @@ -340,27 +354,22 @@ namespace direct_bt { /** * Returns AdapterInfo count in list */ - int getAdapterCount() const noexcept { return adapterInfos.size(); } + int getAdapterCount() const noexcept { return adapters.size(); } /** - * Returns the AdapterInfo dev_id with the given address or -1 if not found. + * Returns a list of currently added DBTAdapter. */ - int findAdapterInfoDevId(const EUI48 &mac) const noexcept; + jau::darray> getAdapters() { return *adapters.snapshot(); } /** - * Returns the AdapterInfo with the given address or nullptr if not found. + * Returns the DBTAdapter with the given address or nullptr if not found. */ - std::shared_ptr findAdapterInfo(const EUI48 &mac) const noexcept; + std::shared_ptr getAdapter(const EUI48 &mac) const noexcept; /** - * Returns the AdapterInfo with the given dev_id, or nullptr if not found. + * Returns the DBTAdapter with the given dev_id, or nullptr if not found. */ - std::shared_ptr getAdapterInfo(const uint16_t dev_id) const noexcept; - - /** - * Returns the current BTMode of given adapter dev_idx or BTMode::NONE if dev_id adapter is not available. - */ - BTMode getCurrentBTMode(uint16_t dev_id) const noexcept; + std::shared_ptr getAdapter(const uint16_t dev_id) const noexcept; /** * Returns the default AdapterInfo. @@ -369,16 +378,7 @@ namespace direct_bt { * or function returns nullptr if none is AdapterSetting::POWERED. *

*/ - std::shared_ptr getDefaultAdapterInfo() const noexcept; - - /** - * Returns the default adapter dev_id (index). - *

- * The default adapter is either the first AdapterSetting::POWERED adapter, - * or function returns -1 if none is AdapterSetting::POWERED. - *

- */ - int getDefaultAdapterDevID() const noexcept; + std::shared_ptr getDefaultAdapter() const noexcept; bool setIOCapability(const uint16_t dev_id, const SMPIOCapability io_cap, SMPIOCapability& pre_io_cap) noexcept; SMPIOCapability getIOCapability(const uint16_t dev_id) const noexcept; diff --git a/api/direct_bt/DBTTypes.hpp b/api/direct_bt/DBTTypes.hpp index 432cad26..5a81360e 100644 --- a/api/direct_bt/DBTTypes.hpp +++ b/api/direct_bt/DBTTypes.hpp @@ -30,6 +30,7 @@ #include #include +#include #include "UUID.hpp" #include "BTAddress.hpp" @@ -185,13 +186,13 @@ namespace direct_bt { friend class DBTAdapter; // direct manager public: - const int dev_id; + const uint16_t dev_id; const EUI48 address; const uint8_t version; const uint16_t manufacturer; - const AdapterSetting supported_setting; private: + AdapterSetting supported_setting; std::atomic current_setting; uint32_t dev_class; std::string name; @@ -212,16 +213,48 @@ namespace direct_bt { void setShortName(const std::string v) noexcept { short_name = v; } public: - AdapterInfo(const int dev_id_, const EUI48 & address_, + AdapterInfo(const uint16_t dev_id_, const EUI48 & address_, const uint8_t version_, const uint16_t manufacturer_, const AdapterSetting supported_setting_, const AdapterSetting current_setting_, const uint32_t dev_class_, const std::string & name_, const std::string & short_name_) noexcept : dev_id(dev_id_), address(address_), version(version_), - manufacturer(manufacturer_), supported_setting(supported_setting_), + manufacturer(manufacturer_), + supported_setting(supported_setting_), current_setting(current_setting_), dev_class(dev_class_), name(name_), short_name(short_name_) { } + AdapterInfo(const AdapterInfo &o) noexcept + : dev_id(o.dev_id), address(o.address), version(o.version), + manufacturer(o.manufacturer), + supported_setting(o.supported_setting), + current_setting(o.current_setting.load()), dev_class(o.dev_class), + name(o.name), short_name(o.short_name) + { } + AdapterInfo& operator=(const AdapterInfo &o) { + if( this != &o ) { + if( dev_id != o.dev_id || address != o.address ) { + throw jau::IllegalArgumentException("Can't assign different device id's or address "+o.toString()+" -> "+toString(), E_FILE_LINE); + } + supported_setting = o.supported_setting; + current_setting = o.current_setting.load(); + dev_class = o.dev_class; + name = o.name; + short_name = o.short_name; + } + return *this; + } + AdapterInfo(AdapterInfo&& o) noexcept + : dev_id(std::move(o.dev_id)), address(std::move(o.address)), version(std::move(o.version)), + manufacturer(std::move(o.manufacturer)), + supported_setting(std::move(o.supported_setting)), + current_setting(o.current_setting.load()), dev_class(std::move(o.dev_class)), + name(std::move(o.name)), short_name(std::move(o.short_name)) + { } + AdapterInfo& operator=(AdapterInfo &&o) noexcept = delete; + + constexpr const AdapterSetting& get_supportedSetting() const noexcept { return supported_setting; } + bool isSettingMaskSupported(const AdapterSetting setting) const noexcept { return setting == ( setting & supported_setting ); } diff --git a/api/direct_bt/DirectBT.hpp b/api/direct_bt/DirectBT.hpp index df470676..3c6f2367 100644 --- a/api/direct_bt/DirectBT.hpp +++ b/api/direct_bt/DirectBT.hpp @@ -34,15 +34,18 @@ #include #include #include -#include #include #include +#include + #include "DBTTypes.hpp" #include "DBTDevice.hpp" #include "DBTAdapter.hpp" +#include "DBTManager.hpp" + #endif /* DIRECTBT_HPP_ */ diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp index d304ad4c..f8d96dd1 100644 --- a/api/direct_bt/MgmtTypes.hpp +++ b/api/direct_bt/MgmtTypes.hpp @@ -2228,7 +2228,7 @@ namespace direct_bt { std::string getName() const noexcept { return pdu.get_string_nc(getDataOffset()+20); } std::string getShortName() const noexcept { return pdu.get_string_nc(getDataOffset()+20+MgmtConstU16::MGMT_MAX_NAME_LENGTH); } - std::shared_ptr toAdapterInfo() const noexcept; + std::unique_ptr toAdapterInfo() const noexcept; }; diff --git a/examples/direct_bt_scanner00/dbt_scanner00.cpp b/examples/direct_bt_scanner00/dbt_scanner00.cpp index 23a4e4fe..4b3fc30a 100644 --- a/examples/direct_bt_scanner00/dbt_scanner00.cpp +++ b/examples/direct_bt_scanner00/dbt_scanner00.cpp @@ -194,30 +194,29 @@ int main(int argc, char *argv[]) fprintf(stderr, "Press ENTER to continue\n"); getchar(); } + DBTManager & mngr = DBTManager::get(); - DBTAdapter adapter(dev_id); - if( !adapter.hasDevId() ) { - fprintf(stderr, "Default adapter not available.\n"); + std::shared_ptr adapter = mngr.getAdapter(dev_id); + if( nullptr == adapter ) { + fprintf(stderr, "adapter dev_id %d not available.\n", dev_id); exit(1); } - if( !adapter.isValid() ) { - fprintf(stderr, "Adapter invalid.\n"); + if( !adapter->isValid() ) { + fprintf(stderr, "Adapter invalid: %s\n", adapter->toString().c_str()); exit(1); } - if( !adapter.isPowered() ) { - fprintf(stderr, "Adapter not powered: device %s, address %s: %s\n", - adapter.getName().c_str(), adapter.getAddressString().c_str(), adapter.toString().c_str()); + if( !adapter->isPowered() ) { + fprintf(stderr, "Adapter not powered: %s\n", adapter->toString().c_str()); exit(1); } - fprintf(stderr, "Using adapter: device %s, address %s: %s\n", - adapter.getName().c_str(), adapter.getAddressString().c_str(), adapter.toString().c_str()); + fprintf(stderr, "Using adapter: %s\n", adapter->toString().c_str()); - adapter.addStatusListener(std::shared_ptr(new MyAdapterStatusListener())); + adapter->addStatusListener(std::shared_ptr(new MyAdapterStatusListener())); const uint64_t t0 = getCurrentMilliseconds(); while( ok && ( forever || !foundDevice ) ) { - ok = HCIStatusCode::SUCCESS == adapter.startDiscovery(true /* keepAlive */); + ok = HCIStatusCode::SUCCESS == adapter->startDiscovery(true /* keepAlive */); if( !ok) { perror("Adapter start discovery failed"); goto out; @@ -237,7 +236,7 @@ int main(int argc, char *argv[]) } } } - adapter.stopDiscovery(); + adapter->stopDiscovery(); if( ok && nullptr != device ) { const uint64_t t1 = getCurrentMilliseconds(); diff --git a/examples/direct_bt_scanner01/dbt_scanner01.cpp b/examples/direct_bt_scanner01/dbt_scanner01.cpp index 5a036a00..7e3a8db7 100644 --- a/examples/direct_bt_scanner01/dbt_scanner01.cpp +++ b/examples/direct_bt_scanner01/dbt_scanner01.cpp @@ -192,30 +192,29 @@ int main(int argc, char *argv[]) fprintf(stderr, "Press ENTER to continue\n"); getchar(); } + DBTManager & mngr = DBTManager::get(); - DBTAdapter adapter(dev_id); - if( !adapter.hasDevId() ) { - fprintf(stderr, "Default adapter not available.\n"); + std::shared_ptr adapter = mngr.getAdapter(dev_id); + if( nullptr == adapter ) { + fprintf(stderr, "adapter dev_id %d not available.\n", dev_id); exit(1); } - if( !adapter.isValid() ) { - fprintf(stderr, "Adapter invalid.\n"); + if( !adapter->isValid() ) { + fprintf(stderr, "Adapter invalid: %s\n", adapter->toString().c_str()); exit(1); } - if( !adapter.isPowered() ) { - fprintf(stderr, "Adapter not powered: device %s, address %s: %s\n", - adapter.getName().c_str(), adapter.getAddressString().c_str(), adapter.toString().c_str()); + if( !adapter->isPowered() ) { + fprintf(stderr, "Adapter not powered: %s\n", adapter->toString().c_str()); exit(1); } - fprintf(stderr, "Using adapter: device %s, address %s: %s\n", - adapter.getName().c_str(), adapter.getAddressString().c_str(), adapter.toString().c_str()); + fprintf(stderr, "Using adapter: %s\n", adapter->toString().c_str()); - adapter.addStatusListener(std::shared_ptr(new MyAdapterStatusListener())); + adapter->addStatusListener(std::shared_ptr(new MyAdapterStatusListener())); const uint64_t t0 = getCurrentMilliseconds(); while( ok && ( forever || !foundDevice ) ) { - ok = HCIStatusCode::SUCCESS == adapter.startDiscovery(true /* keepAlive */); + ok = HCIStatusCode::SUCCESS == adapter->startDiscovery(true /* keepAlive */); if( !ok) { perror("Adapter start discovery failed"); goto out; @@ -235,7 +234,7 @@ int main(int argc, char *argv[]) } } } - adapter.stopDiscovery(); + adapter->stopDiscovery(); if( ok && nullptr != device ) { const uint64_t t1 = getCurrentMilliseconds(); diff --git a/examples/direct_bt_scanner10/dbt_scanner10.cpp b/examples/direct_bt_scanner10/dbt_scanner10.cpp index c640072c..76e566a3 100644 --- a/examples/direct_bt_scanner10/dbt_scanner10.cpp +++ b/examples/direct_bt_scanner10/dbt_scanner10.cpp @@ -111,20 +111,16 @@ bool matches(jau::darray &cont, const BDAddressAndType &mac) { }); } -bool contains(std::unordered_set &cont, const BDAddressAndType &mac) { - return cont.end() != cont.find(mac); -} - void printList(const std::string &msg, jau::darray &cont) { fprintf(stderr, "%s ", msg.c_str()); - std::for_each(cont.begin(), cont.end(), + jau::for_each(cont.begin(), cont.end(), [](const BDAddressAndType &mac) { fprintf(stderr, "%s, ", mac.toString().c_str()); }); fprintf(stderr, "\n"); } void printList(const std::string &msg, std::unordered_set &cont) { fprintf(stderr, "%s ", msg.c_str()); - std::for_each(cont.begin(), cont.end(), + jau::for_each(cont.begin(), cont.end(), [](const BDAddressAndType &mac) { fprintf(stderr, "%s, ", mac.toString().c_str()); }); fprintf(stderr, "\n"); } @@ -135,7 +131,7 @@ static void addToDevicesProcessed(const BDAddressAndType &a) { } static bool isDeviceProcessed(const BDAddressAndType & a) { const std::lock_guard lock(mtx_devicesProcessed); // RAII-style acquire and relinquish via destructor - return contains(devicesProcessed, a); + return devicesProcessed.end() != devicesProcessed.find(a); } static size_t getDeviceProcessedCount() { const std::lock_guard lock(mtx_devicesProcessed); // RAII-style acquire and relinquish via destructor @@ -144,7 +140,7 @@ static size_t getDeviceProcessedCount() { static bool allDevicesProcessed(jau::darray &cont) { const std::lock_guard lock(mtx_devicesProcessed); // RAII-style acquire and relinquish via destructor for (auto it = cont.begin(); it != cont.end(); ++it) { - if( !contains(devicesProcessed, *it) ) { + if( devicesProcessed.end() == devicesProcessed.find(*it) ) { return false; } } @@ -171,7 +167,7 @@ static bool removeFromDevicesProcessing(const BDAddressAndType &a) { } static bool isDeviceProcessing(const BDAddressAndType & a) { const std::lock_guard lock(mtx_devicesProcessing); // RAII-style acquire and relinquish via destructor - return contains(devicesInProcessing, a); + return devicesInProcessing.end() != devicesInProcessing.find(a); } static size_t getDeviceProcessingCount() { const std::lock_guard lock(mtx_devicesProcessing); // RAII-style acquire and relinquish via destructor @@ -740,36 +736,11 @@ static bool startDiscovery(DBTAdapter *a, std::string msg) { return HCIStatusCode::SUCCESS == status; } -static std::shared_ptr createAdapter(const int dev_id0, const bool validate_dev_id) { - // pre-validate dev_id availability - int dev_id; - if( validate_dev_id ) { - DBTManager & mngr = DBTManager::get(); - if( 0 > dev_id0 ) { - dev_id = mngr.getDefaultAdapterDevID(); - } else if( nullptr != mngr.getAdapterInfo(dev_id0) ) { - dev_id = dev_id0; - } else { - dev_id = -1; - } - } else { - dev_id = dev_id0; - } - if( 0 > dev_id ) { - fprintf(stderr, "Adapter not available (1): Request %d, deduced %d\n", dev_id0, dev_id); - return nullptr; - } - - std::shared_ptr adapter(new DBTAdapter(dev_id)); // given dev_id >= 0 or default adapter (1st powered) - if( !adapter->hasDevId() ) { - fprintf(stderr, "Adapter not available (2): %d\n", dev_id); // should have been covered above - return nullptr; - } +static bool initAdapter(std::shared_ptr& adapter) { if( !adapter->isPowered() ) { // should have been covered above fprintf(stderr, "Adapter not powered (2): %s\n", adapter->toString().c_str()); - return nullptr; + return false; } - adapter->addStatusListener(std::shared_ptr(new MyAdapterStatusListener())); if( USE_WHITELIST ) { @@ -779,69 +750,21 @@ static std::shared_ptr createAdapter(const int dev_id0, const bool v } } else { if( !startDiscovery(adapter.get(), "kick-off") ) { - return nullptr; - } - } - return adapter; -} - -typedef jau::cow_darray> cow_adapter_list_t; -static cow_adapter_list_t adapterList; - -static std::shared_ptr getAdapter(const uint16_t dev_id) { - cow_adapter_list_t::const_iterator begin = adapterList.cbegin(); - cow_adapter_list_t::const_iterator end = begin.cend(); - auto it = jau::find_if(begin, end, [&](std::shared_ptr const& p) -> bool { - return p->dev_id == dev_id; - }); - if ( it == end ) { - return nullptr; - } else { - return *it; - } -} -static std::shared_ptr removeAdapter(const uint16_t dev_id) { - std::shared_ptr res = nullptr; - cow_adapter_list_t::iterator begin = adapterList.begin(); // lock, copy_store and set_store @ dtor! - const std::lock_guard lock(adapterList.get_write_mutex()); - std::shared_ptr>> store = adapterList.copy_store(); - for(auto it = store->begin(); it != store->end(); ) { - if ( (*it)->dev_id == dev_id ) { - res = *it; - it = store->erase(it); - adapterList.set_store(std::move(store)); - return res; - } else { - ++it; + return false; } } - return nullptr; + return true; } -static bool myChangedAdapterSetFunc(const bool added, const AdapterInfo& adapterInfo) { +static bool myChangedAdapterSetFunc(const bool added, std::shared_ptr& adapter) { if( added ) { - std::shared_ptr pre = getAdapter(adapterInfo.dev_id); - if( nullptr != pre ) { - fprintf(stderr, "****** Adapter ADDED__: Not new %s\n", pre->toString().c_str()); + if( initAdapter( adapter ) ) { + fprintf(stderr, "****** Adapter ADDED__: InitOK. %s\n", adapter->toString().c_str()); } else { - if( adapterInfo.isCurrentSettingBitSet(AdapterSetting::POWERED) ) { - std::shared_ptr adapter = createAdapter(adapterInfo.dev_id, false /* validate_dev_id */); - if( nullptr != adapter ) { - adapterList.push_back(adapter); - fprintf(stderr, "****** Adapter ADDED__: Created %s\n", adapter->toString().c_str()); - } - } else { - fprintf(stderr, "****** Adapter ADDED__: Ignored %s\n", adapterInfo.toString().c_str()); - } + fprintf(stderr, "****** Adapter ADDED__: Ignored %s\n", adapter->toString().c_str()); } } else { - std::shared_ptr removed = removeAdapter(adapterInfo.dev_id); - if( nullptr != removed ) { - fprintf(stderr, "****** Adapter REMOVED: %s\n", removed->toString().c_str()); - removed->close(); - } else { - fprintf(stderr, "****** Adapter REMOVED: Not found %s\n", adapterInfo.toString().c_str()); - } + fprintf(stderr, "****** Adapter REMOVED: %s\n", adapter->toString().c_str()); } return true; } @@ -869,19 +792,25 @@ void test() { } } - jau::for_each_fidelity(adapterList, [](std::shared_ptr& adapter) { + // + // just a manually controlled pull down to show status, not required + // + jau::darray> adapterList = mngr.getAdapters(); + + jau::for_each_const(adapterList, [](const std::shared_ptr& adapter) { fprintf(stderr, "****** EOL Adapter's Devices - pre close: %s\n", adapter->toString().c_str()); adapter->printSharedPtrListOfDevices(); - adapter->close(); - fprintf(stderr, "****** EOL Adapter's Devices - post close\n"); - adapter->printSharedPtrListOfDevices(); }); - fprintf(stderr, "****** EOL Adapter's Devices - post close all\n"); - { int count = mngr.removeChangedAdapterSetCallback(myChangedAdapterSetFunc); fprintf(stderr, "****** EOL Removed ChangedAdapterSetCallback %d\n", count); + + mngr.close(); } + jau::for_each_const(adapterList, [](const std::shared_ptr& adapter) { + fprintf(stderr, "****** EOL Adapter's Devices - post close: %s\n", adapter->toString().c_str()); + adapter->printSharedPtrListOfDevices(); + }); } #include diff --git a/examples/java/DBTScanner10.java b/examples/java/DBTScanner10.java index 0141e1b6..29c3ef2f 100644 --- a/examples/java/DBTScanner10.java +++ b/examples/java/DBTScanner10.java @@ -789,46 +789,12 @@ public class DBTScanner10 { return true; } - private final List adapters = new CopyOnWriteArrayList(); - - @SuppressWarnings("unused") - private BluetoothAdapter getAdapter(final int dev_id) { - for( int i=0; i() { - @Override - public boolean test(final BluetoothAdapter t) { - if( dev_id == t.getDevID() ) { - count[0]++; - return true; - } - return false; - } - }); - return count[0]; - } - private final BluetoothManager.ChangedAdapterSetListener myChangedAdapterSetListener = new BluetoothManager.ChangedAdapterSetListener() { @Override public void adapterAdded(final BluetoothAdapter adapter) { - if( adapter.isPowered() ) { - if( initAdapter( adapter ) ) { - adapters.add(adapter); - println("****** Adapter ADDED__: NewInit " + adapter); - } else { - println("****** Adapter ADDED__: Failed_ " + adapter); - } + if( initAdapter( adapter ) ) { + println("****** Adapter ADDED__: InitOK. " + adapter); } else { println("****** Adapter ADDED__: Ignored " + adapter); } @@ -836,8 +802,7 @@ public class DBTScanner10 { @Override public void adapterRemoved(final BluetoothAdapter adapter) { - final int count = removeAdapter(adapter.getDevID()); - println("****** Adapter REMOVED: count "+count+", " + adapter); + println("****** Adapter REMOVED: " + adapter); } }; @@ -867,21 +832,29 @@ public class DBTScanner10 { } } + // + // just a manually controlled pull down to show status, not required + // + final List adapters = manager.getAdapters(); + adapters.forEach(new Consumer() { @Override public void accept(final BluetoothAdapter a) { println("****** EOL Adapter's Devices - pre_ close: " + a); - a.close(); - println("****** EOL Adapter's Devices - post close: " + a); } } ); - { final int count = manager.removeChangedAdapterSetListener(myChangedAdapterSetListener); println("****** EOL Removed ChangedAdapterSetCallback " + count); + + // All implicit via destructor or shutdown hook! + manager.shutdown(); /* implies: adapter.close(); */ } + adapters.forEach(new Consumer() { + @Override + public void accept(final BluetoothAdapter a) { + println("****** EOL Adapter's Devices - post close: " + a); + } } ); - // All implicit via destructor or shutdown hook! - // manager.shutdown(); /* implies: adapter.close(); */ } public static void main(final String[] args) throws InterruptedException { diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java index ab1d25fd..5b4c2209 100644 --- a/java/direct_bt/tinyb/DBTAdapter.java +++ b/java/direct_bt/tinyb/DBTAdapter.java @@ -54,6 +54,7 @@ import org.tinyb.SMPPairingState; import org.tinyb.ScanType; import org.tinyb.AdapterStatusListener; import org.tinyb.BDAddressAndType; +import org.tinyb.BDAddressType; import org.tinyb.TransportType; public class DBTAdapter extends DBTObject implements BluetoothAdapter @@ -99,6 +100,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter @Override public void close() { + final DBTManager mngr = (DBTManager)DBTManager.getManager(); if( !isValid() ) { return; } @@ -124,11 +126,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter poweredOff(); - // notify manager that this instance is gone for good - final DBTManager mngr = (DBTManager)DBTManager.getManager(); - if( equals(mngr.getAdapter(dev_id)) ) { - mngr.removeAdapterCB(dev_id, 0x0100 /* custom opc */); - } + mngr.removeAdapter(this); // remove this instance from manager super.close(); } diff --git a/java/direct_bt/tinyb/DBTManager.java b/java/direct_bt/tinyb/DBTManager.java index 35a1cdea..5ed82c82 100644 --- a/java/direct_bt/tinyb/DBTManager.java +++ b/java/direct_bt/tinyb/DBTManager.java @@ -219,7 +219,7 @@ public class DBTManager implements BluetoothManager } @Override - public List getDevices() { return getDefaultAdapter().getDevices(); } + public List getDevices() { return getDefaultAdapter().getDiscoveredDevices(); } /** * {@inheritDoc} @@ -288,11 +288,7 @@ public class DBTManager implements BluetoothManager adapters.forEach(new Consumer() { @Override public void accept(final BluetoothAdapter adapter) { - changedAdapterSetListenerList.forEach(new Consumer() { - @Override - public void accept(final ChangedAdapterSetListener t) { - t.adapterAdded(adapter); - } } ); + l.adapterAdded(adapter); } }); } @@ -317,6 +313,25 @@ public class DBTManager implements BluetoothManager private native List getAdapterListImpl(); private native BluetoothAdapter getAdapterImpl(int dev_id); + /** + * Removal entry for DBTAdapter.close() + * @param adapter ref to the close'ed adapter + * @return true if contained and removed, otherwise false + */ + /* pp */ final boolean removeAdapter(final DBTAdapter adapter) { + if( adapters.remove(adapter) ) { + if( DEBUG ) { + System.err.println("DBTManager.removeAdapter: Removed "+adapter); + } + return true; + } else { + if( DEBUG ) { + System.err.println("DBTManager.removeAdapter: Not found "+adapter); + } + return false; + } + } + /** callback from native adapter remove */ /* pp */ final void removeAdapterCB(final int dev_id, final int opc_reason) { final BluetoothAdapter[] removed = { null }; @@ -346,8 +361,7 @@ public class DBTManager implements BluetoothManager t.adapterRemoved( removed[0] ); } } ); } - removed[0].close(); // issuing dtor on native DBTAdapter - removed[0] = null; + removed[0] = null; // DBTAdapter::close() issued by DBTManager after all callbacks } if( DEBUG ) { System.err.println("DBTManager.removeAdapterCB[dev_id "+dev_id+", opc 0x"+Integer.toHexString(opc_reason)+ diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx index 9d83bb3b..369730f8 100644 --- a/java/jni/direct_bt/DBTAdapter.cxx +++ b/java/jni/direct_bt/DBTAdapter.cxx @@ -32,6 +32,7 @@ #include "helper_dbt.hpp" #include "direct_bt/DBTAdapter.hpp" +#include "direct_bt/DBTManager.hpp" using namespace direct_bt; @@ -726,8 +727,10 @@ void Java_direct_1bt_tinyb_DBTAdapter_deleteImpl(JNIEnv *env, jobject obj, jlong (void)obj; try { DBTAdapter *adapter = jau::castInstance(nativeInstance); - DBG_PRINT("Java_direct_1bt_tinyb_DBTAdapter_deleteImpl %s", adapter->toString().c_str()); - delete adapter; + DBG_PRINT("Java_direct_1bt_tinyb_DBTAdapter_deleteImpl (close only) %s", adapter->toString().c_str()); + adapter->close(); + // No delete: DBTAdapter instance owned by DBTManager + // However, adapter->close() cleans up most.. } catch(...) { rethrow_and_raise_java_exception(env); } diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx index 38e02a57..5bee36dd 100644 --- a/java/jni/direct_bt/DBTDevice.cxx +++ b/java/jni/direct_bt/DBTDevice.cxx @@ -33,6 +33,7 @@ #include "direct_bt/DBTDevice.hpp" #include "direct_bt/DBTAdapter.hpp" +#include "direct_bt/DBTManager.hpp" using namespace direct_bt; using namespace jau; @@ -305,6 +306,7 @@ void Java_direct_1bt_tinyb_DBTDevice_deleteImpl(JNIEnv *env, jobject obj, jlong (void)obj; try { DBTDevice *device = castInstance(nativeInstance); + DBG_PRINT("Java_direct_1bt_tinyb_DBTDevice_deleteImpl (remove only) %s", device->toString().c_str()); device->remove(); // No delete: DBTDevice instance owned by DBTAdapter // However, device->remove() might issue destruction diff --git a/java/jni/direct_bt/DBTManager.cxx b/java/jni/direct_bt/DBTManager.cxx index 75aa961d..0b6ab77d 100644 --- a/java/jni/direct_bt/DBTManager.cxx +++ b/java/jni/direct_bt/DBTManager.cxx @@ -31,9 +31,9 @@ #include "helper_base.hpp" #include "helper_dbt.hpp" -#include "direct_bt/DBTManager.hpp" #include "direct_bt/DBTDevice.hpp" #include "direct_bt/DBTAdapter.hpp" +#include "direct_bt/DBTManager.hpp" using namespace direct_bt; using namespace jau; @@ -171,26 +171,8 @@ jobject Java_direct_1bt_tinyb_DBTManager_getAdapterListImpl(JNIEnv *env, jobject DBTManager *manager = getInstance(env, obj); DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_getAdapterListImpl: Manager %s", manager->toString().c_str()); - jau::darray> adapters; - const int adapterCount = manager->getAdapterCount(); - for(int dev_id = 0; dev_id < adapterCount; dev_id++) { - if( nullptr == manager->getAdapterInfo(dev_id) ) { - ERR_PRINT("DBTManager::getAdapterListImpl: Adapter dev_id %d: Not found", dev_id); - continue; - } - std::unique_ptr adapter(new DBTAdapter( dev_id ) ); - if( !adapter->isValid() ) { - throw BluetoothException("Invalid adapter @ dev_id "+std::to_string( dev_id ), E_FILE_LINE); - } - if( !adapter->hasDevId() ) { - throw BluetoothException("Invalid adapter dev-id @ dev_id "+std::to_string( dev_id ), E_FILE_LINE); - } - if( dev_id != adapter->dev_id ) { // just make sure idx == dev_id - throw BluetoothException("Invalid adapter dev-id "+std::to_string( adapter->dev_id )+" != dev_id "+std::to_string( dev_id ), E_FILE_LINE); - } - adapters.push_back(std::move(adapter)); - } - return convert_vector_uniqueptr_to_jarraylist>, DBTAdapter>( + jau::darray> adapters = manager->getAdapters(); + return convert_vector_sharedptr_to_jarraylist>, DBTAdapter>( env, adapters, _adapterClazzCtorArgs.c_str(), _createJavaAdapter); } catch(...) { rethrow_and_raise_java_exception(env); @@ -203,23 +185,14 @@ jobject Java_direct_1bt_tinyb_DBTManager_getAdapterImpl(JNIEnv *env, jobject obj try { DBTManager *manager = getInstance(env, obj); - if( nullptr == manager->getAdapterInfo(dev_id) ) { + std::shared_ptr adapter = manager->getAdapter(dev_id); + if( nullptr == adapter ) { ERR_PRINT("DBTManager::getAdapterImpl: Adapter dev_id %d: Not found", dev_id); return nullptr; } - DBTAdapter * adapter = new DBTAdapter( dev_id ); DBG_PRINT("DBTManager::getAdapterImpl: Adapter dev_id %d: %s", dev_id, adapter->toString().c_str()); - if( !adapter->isValid() ) { - throw BluetoothException("Invalid adapter @ dev_id "+std::to_string( dev_id ), E_FILE_LINE); - } - if( !adapter->hasDevId() ) { - throw BluetoothException("Invalid adapter dev-id @ dev_id "+std::to_string( dev_id ), E_FILE_LINE); - } - if( dev_id != adapter->dev_id ) { // just make sure idx == dev_id - throw BluetoothException("Invalid adapter dev-id "+std::to_string( adapter->dev_id )+" != dev_id "+std::to_string( dev_id ), E_FILE_LINE); - } - return jau::convert_instance_to_jobject(env, adapter, _adapterClazzCtorArgs.c_str(), _createJavaAdapter); + return jau::convert_instance_to_jobject(env, adapter.get(), _adapterClazzCtorArgs.c_str(), _createJavaAdapter); } catch(...) { rethrow_and_raise_java_exception(env); } diff --git a/java/org/tinyb/BluetoothManager.java b/java/org/tinyb/BluetoothManager.java index 707d15b3..fe7b5a44 100644 --- a/java/org/tinyb/BluetoothManager.java +++ b/java/org/tinyb/BluetoothManager.java @@ -101,6 +101,10 @@ public interface BluetoothManager /** * {@link BluetoothAdapter} was removed from the system. + *

+ * {@link BluetoothAdapter#close()} is being called by the native manager after issuing all + * {@link #adapterRemoved(BluetoothAdapter)} calls. + *

* @param adapter the removed {@link BluetoothAdapter} from the system */ void adapterRemoved(final BluetoothAdapter adapter); diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp index 389e55ee..82e498e3 100644 --- a/src/direct_bt/DBTAdapter.cpp +++ b/src/direct_bt/DBTAdapter.cpp @@ -40,6 +40,7 @@ #include "HCIComm.hpp" #include "DBTAdapter.hpp" +#include "DBTManager.hpp" extern "C" { #include @@ -122,10 +123,6 @@ bool DBTAdapter::validateDevInfo() noexcept { currentMetaScanType = ScanType::NONE; keep_le_scan_alive = false; - if( 0 > dev_id ) { - ERR_PRINT("DBTAdapter::validateDevInfo: Invalid negative dev_id %d", dev_id); - goto errout0; - } if( !mgmt.isOpen() ) { ERR_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: Manager not open", dev_id); goto errout0; @@ -135,34 +132,28 @@ bool DBTAdapter::validateDevInfo() noexcept { goto errout0; } - adapterInfo = mgmt.getAdapterInfo(dev_id); - if( nullptr == adapterInfo ) { - // fill in a dummy AdapterInfo for the sake of de-referencing throughout this adapter instance - ERR_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: Not existent", dev_id); - goto errout0; - } - old_settings = adapterInfo->getCurrentSettingMask(); + old_settings = adapterInfo.getCurrentSettingMask(); - btMode = adapterInfo->getCurrentBTMode(); + btMode = getBTMode(); if( BTMode::NONE == btMode ) { - ERR_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: BTMode invalid, BREDR nor LE set: %s", dev_id, adapterInfo->toString().c_str()); + ERR_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: BTMode invalid, BREDR nor LE set: %s", dev_id, adapterInfo.toString().c_str()); return false; } hci.setBTMode(btMode); - if( adapterInfo->isCurrentSettingBitSet(AdapterSetting::POWERED) ) { + if( adapterInfo.isCurrentSettingBitSet(AdapterSetting::POWERED) ) { HCILocalVersion version; HCIStatusCode status = hci.getLocalVersion(version); if( HCIStatusCode::SUCCESS != status ) { ERR_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: POWERED, LocalVersion failed %s - %s", - dev_id, getHCIStatusCodeString(status).c_str(), adapterInfo->toString().c_str()); + dev_id, getHCIStatusCodeString(status).c_str(), adapterInfo.toString().c_str()); return false; } else { WORDY_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: POWERED, %s - %s", - dev_id, version.toString().c_str(), adapterInfo->toString().c_str()); + dev_id, version.toString().c_str(), adapterInfo.toString().c_str()); } } else { - WORDY_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: Not POWERED: %s", dev_id, adapterInfo->toString().c_str()); + WORDY_PRINT("DBTAdapter::validateDevInfo: Adapter[%d]: Not POWERED: %s", dev_id, adapterInfo.toString().c_str()); } ok = true; ok = mgmt.addMgmtEventCallback(dev_id, MgmtEvent::Opcode::DISCOVERING, jau::bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceDiscoveringMgmt)) && ok; @@ -203,36 +194,15 @@ bool DBTAdapter::validateDevInfo() noexcept { return true; errout0: - adapterInfo = std::make_shared(dev_id, EUI48::ANY_DEVICE, 0, 0, - AdapterSetting::NONE, AdapterSetting::NONE, 0, "invalid", "invalid"); return false; } -DBTAdapter::DBTAdapter() noexcept -: debug_event(jau::environment::getBooleanProperty("direct_bt.debug.adapter.event", false)), - debug_lock(jau::environment::getBooleanProperty("direct_bt.debug.adapter.lock", false)), - mgmt( DBTManager::get(BTMode::NONE /* use env default */) ), - dev_id( mgmt.getDefaultAdapterDevID() ), - hci( dev_id ) -{ - valid = validateDevInfo(); -} - -DBTAdapter::DBTAdapter(EUI48 &mac) noexcept -: debug_event(jau::environment::getBooleanProperty("direct_bt.debug.adapter.event", false)), - debug_lock(jau::environment::getBooleanProperty("direct_bt.debug.adapter.lock", false)), - mgmt( DBTManager::get(BTMode::NONE /* use env default */) ), - dev_id( mgmt.findAdapterInfoDevId(mac) ), - hci( dev_id ) -{ - valid = validateDevInfo(); -} - -DBTAdapter::DBTAdapter(const int _dev_id) noexcept +DBTAdapter::DBTAdapter(DBTManager& mgmt_, const AdapterInfo& adapterInfo_) noexcept : debug_event(jau::environment::getBooleanProperty("direct_bt.debug.adapter.event", false)), debug_lock(jau::environment::getBooleanProperty("direct_bt.debug.adapter.lock", false)), - mgmt( DBTManager::get(BTMode::NONE /* use env default */) ), - dev_id( 0 <= _dev_id ? _dev_id : mgmt.getDefaultAdapterDevID() ), + mgmt( mgmt_ ), + adapterInfo( adapterInfo_ ), + dev_id( adapterInfo.dev_id ), hci( dev_id ) { valid = validateDevInfo(); @@ -241,10 +211,14 @@ DBTAdapter::DBTAdapter(const int _dev_id) noexcept DBTAdapter::~DBTAdapter() noexcept { if( !isValid() ) { DBG_PRINT("DBTAdapter::dtor: dev_id %d, invalid, %p", dev_id, this); + mgmt.removeAdapter(this); // remove this instance from manager return; } DBG_PRINT("DBTAdapter::dtor: ... %p %s", this, toString().c_str()); close(); + + mgmt.removeAdapter(this); // remove this instance from manager + DBG_PRINT("DBTAdapter::dtor: XXX"); } @@ -700,7 +674,7 @@ HCIStatusCode DBTAdapter::stopDiscovery() noexcept { } HCIStatusCode status; - if( !adapterInfo->isCurrentSettingBitSet(AdapterSetting::POWERED) ) { + if( !adapterInfo.isCurrentSettingBitSet(AdapterSetting::POWERED) ) { WARN_PRINT("DBTAdapter::stopDiscovery: Powered off: %s", toString().c_str()); hci.setCurrentScanType(ScanType::NONE); currentMetaScanType = ScanType::NONE; @@ -831,7 +805,7 @@ void DBTAdapter::removeDevice(DBTDevice & device) noexcept { std::string DBTAdapter::toString(bool includeDiscoveredDevices) const noexcept { std::string out("Adapter[BTMode "+getBTModeString(btMode)+", "+getAddressString()+", '"+getName()+"', id "+std::to_string(dev_id)+ - ", curSettings"+getAdapterSettingMaskString(adapterInfo->getCurrentSettingMask())+ + ", curSettings"+getAdapterSettingMaskString(adapterInfo.getCurrentSettingMask())+ ", scanType[native "+getScanTypeString(hci.getCurrentScanType())+", meta "+getScanTypeString(currentMetaScanType)+"]" ", valid "+std::to_string(isValid())+", open[mgmt, "+std::to_string(mgmt.isOpen())+", hci "+std::to_string(hci.isOpen())+ "], "+javaObjectToString()+"]"); @@ -868,7 +842,7 @@ void DBTAdapter::sendAdapterSettingsChanged(const AdapterSetting old_settings_, void DBTAdapter::sendAdapterSettingsInitial(AdapterStatusListener & asl, const uint64_t timestampMS) noexcept { - const AdapterSetting current_settings = adapterInfo->getCurrentSettingMask(); + const AdapterSetting current_settings = adapterInfo.getCurrentSettingMask(); COND_PRINT(debug_event, "DBTAdapter::sendAdapterSettingsInitial: NONE -> %s, changes NONE: %s", getAdapterSettingMaskString(current_settings).c_str(), toString(false).c_str() ); try { @@ -974,7 +948,7 @@ bool DBTAdapter::mgmtEvDeviceDiscoveringAny(const MgmtEvent& e, const bool hciSo bool DBTAdapter::mgmtEvNewSettingsMgmt(const MgmtEvent& e) noexcept { COND_PRINT(debug_event, "DBTAdapter:mgmt:NewSettings: %s", e.toString().c_str()); const MgmtEvtNewSettings &event = *static_cast(&e); - const AdapterSetting new_settings = adapterInfo->setCurrentSettingMask(event.getSettings()); // probably done by mgmt callback already + const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(event.getSettings()); // probably done by mgmt callback already { const BTMode _btMode = getAdapterSettingsBTMode(new_settings); if( BTMode::NONE != _btMode ) { diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp index 0f91acf4..b4a1d60e 100644 --- a/src/direct_bt/DBTDevice.cpp +++ b/src/direct_bt/DBTDevice.cpp @@ -39,6 +39,7 @@ #include "DBTDevice.hpp" #include "DBTAdapter.hpp" +#include "DBTManager.hpp" using namespace direct_bt; diff --git a/src/direct_bt/DBTManager.cpp b/src/direct_bt/DBTManager.cpp index bbfaab89..0d4136e9 100644 --- a/src/direct_bt/DBTManager.cpp +++ b/src/direct_bt/DBTManager.cpp @@ -44,6 +44,7 @@ #include "HCIIoctl.hpp" #include "HCIComm.hpp" #include "DBTTypes.hpp" +#include "DBTAdapter.hpp" #include "SMPHandler.hpp" @@ -239,7 +240,7 @@ std::unique_ptr DBTManager::sendWithReply(MgmtCommand &req) noexcept return nullptr; } -std::shared_ptr DBTManager::initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept { +std::unique_ptr DBTManager::initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept { /** * We weight on PairingMode::PASSKEY_ENTRY. FIXME: Have it configurable! * @@ -253,7 +254,7 @@ std::shared_ptr DBTManager::initAdapter(const uint16_t dev_id, cons const uint8_t sc_on_param = 0x01; // SET_SECURE_CONN 0x00 disabled, 0x01 enables SC mixed, 0x02 enables SC only mode #endif - std::shared_ptr adapterInfo = nullptr; + std::unique_ptr adapterInfo(nullptr); // nullptr AdapterSetting current_settings; MgmtCommand req0(MgmtCommand::Opcode::READ_INFO, dev_id); { @@ -352,7 +353,11 @@ fail: return adapterInfo; } -void DBTManager::shutdownAdapter(const uint16_t dev_id) noexcept { +void DBTManager::shutdownAdapter(DBTAdapter& adapter) noexcept { + DBG_PRINT("DBTManager::shutdownAdapter: %s", adapter.toString().c_str()); + const uint16_t dev_id = adapter.dev_id; + adapter.close(); // also issues removeMgmtEventCallback(dev_id); + AdapterSetting current_settings; setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, 0, current_settings); @@ -364,6 +369,7 @@ void DBTManager::shutdownAdapter(const uint16_t dev_id) noexcept { setMode(dev_id, MgmtCommand::Opcode::SET_IO_CAPABILITY, direct_bt::number(SMPIOCapability::DISPLAY_ONLY), current_settings); setMode(dev_id, MgmtCommand::Opcode::SET_SSP, 0, current_settings); setMode(dev_id, MgmtCommand::Opcode::SET_SECURE_CONN, 0, current_settings); + DBG_PRINT("DBTManager::shutdownAdapter: done: %s", adapter.toString().c_str()); } DBTManager::DBTManager(const BTMode _defaultBTMode) noexcept @@ -476,19 +482,18 @@ next1: ERR_PRINT("Insufficient data for %d adapter indices: res %s", num_adapter, res->toString().c_str()); goto fail; } - { - for(int i=0; i < num_adapter; i++) { - const uint16_t dev_id = jau::get_uint16(data, 2+i*2, true /* littleEndian */); - std::shared_ptr adapterInfo = initAdapter(dev_id, defaultBTMode); - if( nullptr != adapterInfo ) { - adapterInfos.push_back(adapterInfo); - adapterIOCapability.push_back(defaultIOCapability); - DBG_PRINT("DBTManager::adapters %d/%d: dev_id %d: %s", i, num_adapter, dev_id, adapterInfo->toString().c_str()); - } else { - DBG_PRINT("DBTManager::adapters %d/%d: dev_id %d: FAILED", i, num_adapter, dev_id); - } + for(int i=0; i < num_adapter; i++) { + const uint16_t dev_id = jau::get_uint16(data, 2+i*2, true /* littleEndian */); + std::unique_ptr adapterInfo = initAdapter(dev_id, defaultBTMode); + if( nullptr != adapterInfo ) { + // private: std::shared_ptr adapter = std::make_shared(*this, *adapterInfo); + std::shared_ptr adapter( new DBTAdapter(*this, *adapterInfo) ); + adapters.push_back( adapter ); + adapterIOCapability.push_back(defaultIOCapability); + DBG_PRINT("DBTManager::adapters %d/%d: dev_id %d: %s", i, num_adapter, dev_id, adapter->toString().c_str()); + } else { + DBG_PRINT("DBTManager::adapters %d/%d: dev_id %d: FAILED", i, num_adapter, dev_id); } - // Not required: CTOR: adapterInfos.set_store(std::move(snapshot)); } } @@ -544,7 +549,7 @@ void DBTManager::close() noexcept { DBG_PRINT("DBTManager::close: Not open"); whitelist.clear(); clearAllCallbacks(); - adapterInfos.clear(); + adapters.clear(); adapterIOCapability.clear(); comm.close(); return; @@ -556,10 +561,17 @@ void DBTManager::close() noexcept { removeAllDevicesFromWhitelist(); clearAllCallbacks(); - jau::for_each_const(adapterInfos, [&](const std::shared_ptr & a) { - shutdownAdapter(a->dev_id); - }); - adapterInfos.clear(); + { + int i=0; + jau::for_each_fidelity(adapters, [&](std::shared_ptr & a) { + DBG_PRINT("DBTManager::close::shutdownAdapter: %d/%d processing: %s", i, adapters.size(), a->toString().c_str()); + shutdownAdapter(*a); + ++i; + }); + } + + adapters.clear(); + adapterIOCapability.clear(); // Interrupt DBTManager's HCIComm::read(..), avoiding prolonged hang // and pull all underlying hci read operations! @@ -605,35 +617,27 @@ void DBTManager::close() noexcept { DBG_PRINT("DBTManager::close: End"); } -int DBTManager::findAdapterInfoIndex(const uint16_t dev_id) const noexcept { - auto it = adapterInfos.cbegin(); - for (; !it.is_end(); ++it) { - if ( (*it)->dev_id == dev_id ) { - return it - it.cend(); - } - } - return -1; -} -int DBTManager::findAdapterInfoDevId(const EUI48 &mac) const noexcept { - auto it = adapterInfos.cbegin(); +std::shared_ptr DBTManager::getDefaultAdapter() const noexcept { + typename adapters_t::const_iterator it = adapters.cbegin(); for (; !it.is_end(); ++it) { - if ( (*it)->address == mac ) { - return (*it)->dev_id; + if( (*it)->isPowered() ) { + return *it; } } - return -1; + return nullptr; } -std::shared_ptr DBTManager::findAdapterInfo(const EUI48 &mac) const noexcept { - auto it = adapterInfos.cbegin(); + +std::shared_ptr DBTManager::getAdapter(const EUI48 &mac) const noexcept { + typename adapters_t::const_iterator it = adapters.cbegin(); for (; !it.is_end(); ++it) { - if ( (*it)->address == mac ) { + if ( (*it)->adapterInfo.address == mac ) { return *it; } } return nullptr; } -std::shared_ptr DBTManager::getAdapterInfo(const uint16_t dev_id) const noexcept { - auto it = adapterInfos.cbegin(); +std::shared_ptr DBTManager::getAdapter(const uint16_t dev_id) const noexcept { + typename adapters_t::const_iterator it = adapters.cbegin(); for (; !it.is_end(); ++it) { if ( (*it)->dev_id == dev_id ) { return *it; @@ -641,76 +645,80 @@ std::shared_ptr DBTManager::getAdapterInfo(const uint16_t dev_id) c } return nullptr; } -bool DBTManager::addAdapterInfo(std::shared_ptr ai) noexcept { - auto it = adapterInfos.begin(); // lock mutex and copy_store + +std::shared_ptr DBTManager::addAdapter(const AdapterInfo& ai ) noexcept { + typename adapters_t::iterator it = adapters.begin(); // lock mutex and copy_store for (; !it.is_end(); ++it) { - if ( (*it)->dev_id == ai->dev_id ) { - it.push_back(ai); - it.write_back(); - adapterIOCapability.push_back(defaultIOCapability); - return true; + if ( (*it)->dev_id == ai.dev_id ) { + break; } } - // already existing - return false; + if( it.is_end() ) { + // new entry + // private: std::shared_ptr adapter = std::make_shared(*this, ai); + std::shared_ptr adapter( new DBTAdapter(*this, ai) ); + it.push_back( adapter ); + adapterIOCapability.push_back(defaultIOCapability); + DBG_PRINT("DBTManager::addAdapter: Adding new: %s", adapter->toString().c_str()) + it.write_back(); + return adapter; + } else { + // already existing + std::shared_ptr adapter = *it; + WARN_PRINT("DBTManager::addAdapter: Already existing %s, overwriting %s", ai.toString().c_str(), adapter->toString().c_str()) + adapter->adapterInfo = ai; + return adapter; + } } -std::shared_ptr DBTManager::removeAdapterInfo(const uint16_t dev_id) noexcept { - typename adapterInfos_t::iterator it = adapterInfos.begin(); // lock mutex and copy_store - while ( !it.is_end() ) { - std::shared_ptr & ai = *it; + +std::shared_ptr DBTManager::removeAdapter(const uint16_t dev_id) noexcept { + typename adapters_t::iterator it = adapters.begin(); // lock mutex and copy_store + for(; !it.is_end(); ++it ) { + std::shared_ptr & ai = *it; if( ai->dev_id == dev_id ) { - adapterIOCapability.erase( adapterIOCapability.begin() + ( it - it.begin() ) ); - std::shared_ptr res = ai; // copy + adapterIOCapability.erase( adapterIOCapability.cbegin() + it.dist_begin() ); + std::shared_ptr res = ai; // copy + DBG_PRINT("DBTManager::removeAdapter: Remove: %s", res->toString().c_str()) it.erase(); it.write_back(); return res; - } else { - ++it; } } + DBG_PRINT("DBTManager::removeAdapter: Not found: dev_id %d", dev_id) return nullptr; } -BTMode DBTManager::getCurrentBTMode(uint16_t dev_id) const noexcept { - std::shared_ptr ai = getAdapterInfo(dev_id); - if( nullptr == ai ) { - ERR_PRINT("dev_id %d not found", dev_id); - return BTMode::NONE; - } - return ai->getCurrentBTMode(); -} - -std::shared_ptr DBTManager::getDefaultAdapterInfo() const noexcept { - auto it = adapterInfos.cbegin(); - for (; !it.is_end(); ++it) { - if( (*it)->isCurrentSettingBitSet(AdapterSetting::POWERED) ) { - return *it; +bool DBTManager::removeAdapter(DBTAdapter* adapter) noexcept { + typename adapters_t::iterator it = adapters.begin(); // lock mutex and copy_store + for(; !it.is_end(); ++it ) { + std::shared_ptr & ai = *it; + if( ai.get() == adapter ) { + adapterIOCapability.erase( adapterIOCapability.cbegin() + it.dist_begin() ); + DBG_PRINT("DBTManager::removeAdapter: Remove: %p -> %s", adapter, ai->toString().c_str()) + it.erase(); + it.write_back(); + return true; } } - return nullptr; -} - -int DBTManager::getDefaultAdapterDevID() const noexcept { - std::shared_ptr ai = getDefaultAdapterInfo(); - if( nullptr == ai ) { - return -1; - } - return ai->dev_id; + DBG_PRINT("DBTManager::removeAdapter: Not found: %p", adapter) + return false; } bool DBTManager::setIOCapability(const uint16_t dev_id, const SMPIOCapability io_cap, SMPIOCapability& pre_io_cap) noexcept { if( SMPIOCapability::UNSET != io_cap ) { #if USE_LINUX_BT_SECURITY - auto it = adapterInfos.cbegin(); + typename adapters_t::const_iterator it = adapters.cbegin(); for (; !it.is_end(); ++it) { if( (*it)->dev_id == dev_id ) { - const typename adapterInfos_t::difference_type index = it-it.cbegin(); + const typename adapters_t::difference_type index = it.dist_begin(); const SMPIOCapability o = adapterIOCapability.at(index); AdapterSetting current_settings { AdapterSetting::NONE }; // throw away return value, unchanged on SET_IO_CAPABILITY if( setMode(dev_id, MgmtCommand::Opcode::SET_IO_CAPABILITY, direct_bt::number(io_cap), current_settings) ) { adapterIOCapability.at(index) = io_cap; pre_io_cap = o; return true; + } else { + return false; } } } @@ -720,10 +728,10 @@ bool DBTManager::setIOCapability(const uint16_t dev_id, const SMPIOCapability io } SMPIOCapability DBTManager::getIOCapability(const uint16_t dev_id) const noexcept { - auto it = adapterInfos.cbegin(); + typename adapters_t::const_iterator it = adapters.cbegin(); for (; !it.is_end(); ++it) { if( (*it)->dev_id == dev_id ) { - return adapterIOCapability.at(it-it.cbegin()); + return adapterIOCapability.at( it.dist_begin() ); } } return SMPIOCapability::UNSET; @@ -979,7 +987,7 @@ int DBTManager::removeAllDevicesFromWhitelist() noexcept { int count = 0; DBG_PRINT("DBTManager::removeAllDevicesFromWhitelist.B: Start %d elements", count); whitelist.clear(); - jau::for_each_const(adapterInfos, [&](const std::shared_ptr & a) { + jau::for_each_const(adapters, [&](const std::shared_ptr & a) { if( removeDeviceFromWhitelist(a->dev_id, BDAddressAndType::ANY_BREDR_DEVICE) ) { // flush whitelist! ++count; } @@ -1136,30 +1144,33 @@ void DBTManager::clearAllCallbacks() noexcept { void DBTManager::processAdapterAdded(std::unique_ptr e) noexcept { const uint16_t dev_id = e->getDevID(); - std::shared_ptr ai = initAdapter(dev_id, defaultBTMode); - if( nullptr != ai ) { - const bool added = addAdapterInfo(ai); - DBG_PRINT("DBTManager::Adapter[%d] Added: Start %s, added %d", dev_id, ai->toString().c_str(), added); + + std::unique_ptr adapterInfo = initAdapter(dev_id, defaultBTMode); + + if( nullptr != adapterInfo ) { + std::shared_ptr adapter = addAdapter( *adapterInfo ); + DBG_PRINT("DBTManager::Adapter[%d] Added: Start %s, added %d", dev_id, adapter->toString().c_str()); sendMgmtEvent(*e); - DBG_PRINT("DBTManager::Adapter[%d] Added: User_ %s", dev_id, ai->toString().c_str()); + DBG_PRINT("DBTManager::Adapter[%d] Added: User_ %s", dev_id, adapter->toString().c_str()); jau::for_each_fidelity(mgmtChangedAdapterSetCallbackList, [&](ChangedAdapterSetCallback &cb) { - cb.invoke(true /* added */, *ai); + cb.invoke(true /* added */, adapter); }); - DBG_PRINT("DBTManager::Adapter[%d] Added: End__ %s", dev_id, ai->toString().c_str()); + DBG_PRINT("DBTManager::Adapter[%d] Added: End__ %s", dev_id, adapter->toString().c_str()); } else { DBG_PRINT("DBTManager::Adapter[%d] Added: InitAI failed", dev_id); } } void DBTManager::processAdapterRemoved(std::unique_ptr e) noexcept { const uint16_t dev_id = e->getDevID(); - std::shared_ptr ai = removeAdapterInfo(dev_id); + std::shared_ptr ai = removeAdapter(dev_id); if( nullptr != ai ) { DBG_PRINT("DBTManager::Adapter[%d] Removed: Start: %s", dev_id, ai->toString().c_str()); sendMgmtEvent(*e); DBG_PRINT("DBTManager::Adapter[%d] Removed: User_: %s", dev_id, ai->toString().c_str()); jau::for_each_fidelity(mgmtChangedAdapterSetCallbackList, [&](ChangedAdapterSetCallback &cb) { - cb.invoke(false /* added */, *ai); + cb.invoke(false /* added */, ai); }); + ai->close(); // issuing dtor on DBTAdapter DBG_PRINT("DBTManager::Adapter[%d] Removed: End__: %s", dev_id, ai->toString().c_str()); } else { DBG_PRINT("DBTManager::Adapter[%d] Removed: RemoveAI failed", dev_id); @@ -1167,10 +1178,10 @@ void DBTManager::processAdapterRemoved(std::unique_ptr e) noexcept { } bool DBTManager::mgmtEvNewSettingsCB(const MgmtEvent& e) noexcept { const MgmtEvtNewSettings &event = *static_cast(&e); - std::shared_ptr adapterInfo = getAdapterInfo(event.getDevID()); - if( nullptr != adapterInfo ) { - const AdapterSetting old_settings = adapterInfo->getCurrentSettingMask(); - const AdapterSetting new_settings = adapterInfo->setCurrentSettingMask(event.getSettings()); + std::shared_ptr adapter = getAdapter(event.getDevID()); + if( nullptr != adapter ) { + const AdapterSetting old_settings = adapter->adapterInfo.getCurrentSettingMask(); + const AdapterSetting new_settings = adapter->adapterInfo.setCurrentSettingMask(event.getSettings()); DBG_PRINT("DBTManager:mgmt:NewSettings: Adapter[%d] %s -> %s - %s", event.getDevID(), getAdapterSettingMaskString(old_settings).c_str(), @@ -1200,12 +1211,11 @@ static ChangedAdapterSetCallbackList::equal_comparator _changedAdapterSetCallbac void DBTManager::addChangedAdapterSetCallback(const ChangedAdapterSetCallback & l) { + ChangedAdapterSetCallback* l_p = const_cast(&l); mgmtChangedAdapterSetCallbackList.push_back(l); - jau::for_each_const(adapterInfos, [&](const std::shared_ptr& ai) { - jau::for_each_fidelity(mgmtChangedAdapterSetCallbackList, [&](ChangedAdapterSetCallback &cb) { - cb.invoke(true /* added */, *ai); - }); + jau::for_each_fidelity(adapters, [&](std::shared_ptr& ai) { + l_p->invoke(true /* added */, ai); }); } int DBTManager::removeChangedAdapterSetCallback(const ChangedAdapterSetCallback & l) { @@ -1215,10 +1225,10 @@ int DBTManager::removeChangedAdapterSetCallback(const ChangedAdapterSetCallback void DBTManager::addChangedAdapterSetCallback(ChangedAdapterSetFunc f) { addChangedAdapterSetCallback( ChangedAdapterSetCallback( - jau::bindPlainFunc(f) + jau::bindPlainFunc&>(f) ) ); } int DBTManager::removeChangedAdapterSetCallback(ChangedAdapterSetFunc f) { - ChangedAdapterSetCallback l( jau::bindPlainFunc(f) ); + ChangedAdapterSetCallback l( jau::bindPlainFunc&>(f) ); return mgmtChangedAdapterSetCallbackList.erase_matching(l, true /* all_matching */, _changedAdapterSetCallbackEqComp); } diff --git a/src/direct_bt/GATTHandler.cpp b/src/direct_bt/GATTHandler.cpp index 374176f3..9ffbad42 100644 --- a/src/direct_bt/GATTHandler.cpp +++ b/src/direct_bt/GATTHandler.cpp @@ -56,6 +56,7 @@ extern "C" { #include "DBTManager.hpp" #include "DBTAdapter.hpp" +#include "DBTManager.hpp" using namespace direct_bt; diff --git a/src/direct_bt/MgmtTypes.cpp b/src/direct_bt/MgmtTypes.cpp index a8f88535..dcd85839 100644 --- a/src/direct_bt/MgmtTypes.cpp +++ b/src/direct_bt/MgmtTypes.cpp @@ -483,8 +483,8 @@ std::shared_ptr MgmtEvtLocalNameChanged::toNameAndShortName() return std::make_shared(getName(), getShortName()); } -std::shared_ptr MgmtEvtAdapterInfo::toAdapterInfo() const noexcept { - return std::make_shared( +std::unique_ptr MgmtEvtAdapterInfo::toAdapterInfo() const noexcept { + return std::make_unique( getDevID(), getAddress(), getVersion(), getManufacturer(), getSupportedSetting(), getCurrentSetting(), getDevClass(), -- cgit v1.2.3