aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2021-01-18 18:44:04 +0100
committerSven Gothel <[email protected]>2021-01-18 18:44:04 +0100
commita6d4061fbeabe75e1789a97be2457ff1274b9a73 (patch)
tree53bad95999406d5732eb66e9cb709def2051604d
parent52779efd5e925f7b59848b52e3fa5e31919851ff (diff)
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<DBTAdapter>&', 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
-rw-r--r--api/direct_bt/ATTPDUTypes.hpp26
-rw-r--r--api/direct_bt/DBTAdapter.hpp65
-rw-r--r--api/direct_bt/DBTManager.hpp76
-rw-r--r--api/direct_bt/DBTTypes.hpp41
-rw-r--r--api/direct_bt/DirectBT.hpp5
-rw-r--r--api/direct_bt/MgmtTypes.hpp2
-rw-r--r--examples/direct_bt_scanner00/dbt_scanner00.cpp25
-rw-r--r--examples/direct_bt_scanner01/dbt_scanner01.cpp25
-rw-r--r--examples/direct_bt_scanner10/dbt_scanner10.cpp123
-rw-r--r--examples/java/DBTScanner10.java59
-rw-r--r--java/direct_bt/tinyb/DBTAdapter.java8
-rw-r--r--java/direct_bt/tinyb/DBTManager.java30
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx7
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx2
-rw-r--r--java/jni/direct_bt/DBTManager.cxx39
-rw-r--r--java/org/tinyb/BluetoothManager.java4
-rw-r--r--src/direct_bt/DBTAdapter.cpp66
-rw-r--r--src/direct_bt/DBTDevice.cpp1
-rw-r--r--src/direct_bt/DBTManager.cpp216
-rw-r--r--src/direct_bt/GATTHandler.cpp1
-rw-r--r--src/direct_bt/MgmtTypes.cpp4
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<AdapterSetting> old_settings;
- std::shared_ptr<AdapterInfo> adapterInfo;
std::atomic<BTMode> btMode = BTMode::NONE;
NameAndShortName localName;
std::atomic<ScanType> currentMetaScanType; // = ScanType::NONE
@@ -248,6 +250,8 @@ namespace direct_bt {
static std::shared_ptr<DBTDevice> findDevice(device_list_t & devices, const EUI48 & address, const BDAddressType addressType) noexcept;
static std::shared_ptr<DBTDevice> 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.
* <p>
@@ -329,35 +333,6 @@ namespace direct_bt {
public:
- /**
- * Using the default adapter device
- * <p>
- * The default adapter is either the first POWERED adapter,
- * or none - in which case this instance !isValid()
- * </p>
- */
- 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.
- * <p>
- * The default adapter is either the first POWERED adapter,
- * or none - in which case this instance !isValid().
- * </p>
- *
- * @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.
* <p>
* Renders this adapter's DBTAdapter#isValid() state to false.
* </p>
@@ -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.
* </p>
+ * <p>
+ * If an adapter is being removed from the system,
+ * DBTAdapter::close() is being called by DBTManager after issuing all
+ * ChangedAdapterSetFunc calls.
+ * </p>
*
* @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<DBTAdapter>& 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.
* </p>
+ * <p>
+ * If an adapter is being removed from the system,
+ * DBTAdapter::close() is being called by DBTManager after issuing all
+ * ChangedAdapterSetFunc calls.
+ * </p>
*
* @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<bool, bool, const AdapterInfo&> ChangedAdapterSetCallback;
+ typedef jau::FunctionDef<bool, bool, std::shared_ptr<DBTAdapter>&> ChangedAdapterSetCallback;
typedef jau::cow_darray<ChangedAdapterSetCallback> 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<std::shared_ptr<AdapterInfo>> adapterInfos_t;
- adapterInfos_t adapterInfos;
+ typedef jau::cow_darray<std::shared_ptr<DBTAdapter>> 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<AdapterInfo> initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept;
- void shutdownAdapter(const uint16_t dev_id) noexcept;
+ std::unique_ptr<AdapterInfo> initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept;
+ void shutdownAdapter(DBTAdapter& adapter) noexcept;
void processAdapterAdded(std::unique_ptr<MgmtEvent> e) noexcept;
void processAdapterRemoved(std::unique_ptr<MgmtEvent> 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<DBTAdapter> 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<AdapterInfo> ai) noexcept;
+ std::shared_ptr<DBTAdapter> 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<AdapterInfo> 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<std::shared_ptr<DBTAdapter>> 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<AdapterInfo> findAdapterInfo(const EUI48 &mac) const noexcept;
+ std::shared_ptr<DBTAdapter> 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<AdapterInfo> 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<DBTAdapter> 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.
* </p>
*/
- std::shared_ptr<AdapterInfo> getDefaultAdapterInfo() const noexcept;
-
- /**
- * Returns the default adapter dev_id (index).
- * <p>
- * The default adapter is either the first AdapterSetting::POWERED adapter,
- * or function returns -1 if none is AdapterSetting::POWERED.
- * </p>
- */
- int getDefaultAdapterDevID() const noexcept;
+ std::shared_ptr<DBTAdapter> 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 <atomic>
#include <jau/java_uplink.hpp>
+#include <jau/basic_types.hpp>
#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<AdapterSetting> 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 <string>
#include <memory>
#include <cstdint>
-#include <vector>
#include <mutex>
#include <atomic>
+#include <jau/darray.hpp>
+
#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<AdapterInfo> toAdapterInfo() const noexcept;
+ std::unique_ptr<AdapterInfo> 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<DBTAdapter> 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<AdapterStatusListener>(new MyAdapterStatusListener()));
+ adapter->addStatusListener(std::shared_ptr<AdapterStatusListener>(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<DBTAdapter> 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<AdapterStatusListener>(new MyAdapterStatusListener()));
+ adapter->addStatusListener(std::shared_ptr<AdapterStatusListener>(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<BDAddressAndType> &cont, const BDAddressAndType &mac) {
});
}
-bool contains(std::unordered_set<direct_bt::BDAddressAndType> &cont, const BDAddressAndType &mac) {
- return cont.end() != cont.find(mac);
-}
-
void printList(const std::string &msg, jau::darray<BDAddressAndType> &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<BDAddressAndType> &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<std::recursive_mutex> 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<std::recursive_mutex> lock(mtx_devicesProcessed); // RAII-style acquire and relinquish via destructor
@@ -144,7 +140,7 @@ static size_t getDeviceProcessedCount() {
static bool allDevicesProcessed(jau::darray<BDAddressAndType> &cont) {
const std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<DBTAdapter> 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<DBTAdapter> 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<DBTAdapter>& 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<AdapterStatusListener>(new MyAdapterStatusListener()));
if( USE_WHITELIST ) {
@@ -779,69 +750,21 @@ static std::shared_ptr<DBTAdapter> createAdapter(const int dev_id0, const bool v
}
} else {
if( !startDiscovery(adapter.get(), "kick-off") ) {
- return nullptr;
- }
- }
- return adapter;
-}
-
-typedef jau::cow_darray<std::shared_ptr<DBTAdapter>> cow_adapter_list_t;
-static cow_adapter_list_t adapterList;
-
-static std::shared_ptr<DBTAdapter> 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<DBTAdapter> const& p) -> bool {
- return p->dev_id == dev_id;
- });
- if ( it == end ) {
- return nullptr;
- } else {
- return *it;
- }
-}
-static std::shared_ptr<DBTAdapter> removeAdapter(const uint16_t dev_id) {
- std::shared_ptr<DBTAdapter> res = nullptr;
- cow_adapter_list_t::iterator begin = adapterList.begin(); // lock, copy_store and set_store @ dtor!
- const std::lock_guard<std::recursive_mutex> lock(adapterList.get_write_mutex());
- std::shared_ptr<jau::darray<std::shared_ptr<DBTAdapter>>> 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<DBTAdapter>& adapter) {
if( added ) {
- std::shared_ptr<DBTAdapter> 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<DBTAdapter> 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<DBTAdapter> 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<DBTAdapter>& adapter) {
+ //
+ // just a manually controlled pull down to show status, not required
+ //
+ jau::darray<std::shared_ptr<DBTAdapter>> adapterList = mngr.getAdapters();
+
+ jau::for_each_const(adapterList, [](const std::shared_ptr<DBTAdapter>& 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<DBTAdapter>& adapter) {
+ fprintf(stderr, "****** EOL Adapter's Devices - post close: %s\n", adapter->toString().c_str());
+ adapter->printSharedPtrListOfDevices();
+ });
}
#include <cstdio>
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<BluetoothAdapter> adapters = new CopyOnWriteArrayList<BluetoothAdapter>();
-
- @SuppressWarnings("unused")
- private BluetoothAdapter getAdapter(final int dev_id) {
- for( int i=0; i<adapters.size(); i++) {
- final BluetoothAdapter a = adapters.get(i);
- if( dev_id == a.getDevID() ) {
- return a;
- }
- }
- return null;
- }
-
- private int removeAdapter(final int dev_id) {
- // Using removeIf allows performing test on all object and remove within one write-lock cycle
- final int count[] = { 0 };
- adapters.removeIf(new Predicate<BluetoothAdapter>() {
- @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<BluetoothAdapter> adapters = manager.getAdapters();
+
adapters.forEach(new Consumer<BluetoothAdapter>() {
@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<BluetoothAdapter>() {
+ @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<BluetoothDevice> getDevices() { return getDefaultAdapter().getDevices(); }
+ public List<BluetoothDevice> getDevices() { return getDefaultAdapter().getDiscoveredDevices(); }
/**
* {@inheritDoc}
@@ -288,11 +288,7 @@ public class DBTManager implements BluetoothManager
adapters.forEach(new Consumer<BluetoothAdapter>() {
@Override
public void accept(final BluetoothAdapter adapter) {
- changedAdapterSetListenerList.forEach(new Consumer<ChangedAdapterSetListener>() {
- @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<BluetoothAdapter> 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<DBTAdapter>(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<DBTDevice>(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<DBTManager>(env, obj);
DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_getAdapterListImpl: Manager %s", manager->toString().c_str());
- jau::darray<std::unique_ptr<DBTAdapter>> 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<DBTAdapter> 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<jau::darray<std::unique_ptr<DBTAdapter>>, DBTAdapter>(
+ jau::darray<std::shared_ptr<DBTAdapter>> adapters = manager->getAdapters();
+ return convert_vector_sharedptr_to_jarraylist<jau::darray<std::shared_ptr<DBTAdapter>>, 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<DBTManager>(env, obj);
- if( nullptr == manager->getAdapterInfo(dev_id) ) {
+ std::shared_ptr<DBTAdapter> 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<DBTAdapter>(env, adapter, _adapterClazzCtorArgs.c_str(), _createJavaAdapter);
+ return jau::convert_instance_to_jobject<DBTAdapter>(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.
+ * <p>
+ * {@link BluetoothAdapter#close()} is being called by the native manager after issuing all
+ * {@link #adapterRemoved(BluetoothAdapter)} calls.
+ * </p>
* @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 <inttypes.h>
@@ -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<AdapterInfo>(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<const MgmtEvtNewSettings *>(&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<MgmtEvent> DBTManager::sendWithReply(MgmtCommand &req) noexcept
return nullptr;
}
-std::shared_ptr<AdapterInfo> DBTManager::initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept {
+std::unique_ptr<AdapterInfo> 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<AdapterInfo> 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> adapterInfo = nullptr;
+ std::unique_ptr<AdapterInfo> 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> 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> adapterInfo = initAdapter(dev_id, defaultBTMode);
+ if( nullptr != adapterInfo ) {
+ // private: std::shared_ptr<DBTAdapter> adapter = std::make_shared<DBTAdapter>(*this, *adapterInfo);
+ std::shared_ptr<DBTAdapter> 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<AdapterInfo> & a) {
- shutdownAdapter(a->dev_id);
- });
- adapterInfos.clear();
+ {
+ int i=0;
+ jau::for_each_fidelity(adapters, [&](std::shared_ptr<DBTAdapter> & 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<DBTAdapter> 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<AdapterInfo> DBTManager::findAdapterInfo(const EUI48 &mac) const noexcept {
- auto it = adapterInfos.cbegin();
+
+std::shared_ptr<DBTAdapter> 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<AdapterInfo> DBTManager::getAdapterInfo(const uint16_t dev_id) const noexcept {
- auto it = adapterInfos.cbegin();
+std::shared_ptr<DBTAdapter> 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<AdapterInfo> DBTManager::getAdapterInfo(const uint16_t dev_id) c
}
return nullptr;
}
-bool DBTManager::addAdapterInfo(std::shared_ptr<AdapterInfo> ai) noexcept {
- auto it = adapterInfos.begin(); // lock mutex and copy_store
+
+std::shared_ptr<DBTAdapter> 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<DBTAdapter> adapter = std::make_shared<DBTAdapter>(*this, ai);
+ std::shared_ptr<DBTAdapter> 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<DBTAdapter> 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<AdapterInfo> 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<AdapterInfo> & ai = *it;
+
+std::shared_ptr<DBTAdapter> 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<DBTAdapter> & ai = *it;
if( ai->dev_id == dev_id ) {
- adapterIOCapability.erase( adapterIOCapability.begin() + ( it - it.begin() ) );
- std::shared_ptr<AdapterInfo> res = ai; // copy
+ adapterIOCapability.erase( adapterIOCapability.cbegin() + it.dist_begin() );
+ std::shared_ptr<DBTAdapter> 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<AdapterInfo> 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<AdapterInfo> 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<DBTAdapter> & 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<AdapterInfo> 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<AdapterInfo> & a) {
+ jau::for_each_const(adapters, [&](const std::shared_ptr<DBTAdapter> & 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<MgmtEvent> e) noexcept {
const uint16_t dev_id = e->getDevID();
- std::shared_ptr<AdapterInfo> 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> adapterInfo = initAdapter(dev_id, defaultBTMode);
+
+ if( nullptr != adapterInfo ) {
+ std::shared_ptr<DBTAdapter> 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<MgmtEvent> e) noexcept {
const uint16_t dev_id = e->getDevID();
- std::shared_ptr<AdapterInfo> ai = removeAdapterInfo(dev_id);
+ std::shared_ptr<DBTAdapter> 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<MgmtEvent> e) noexcept {
}
bool DBTManager::mgmtEvNewSettingsCB(const MgmtEvent& e) noexcept {
const MgmtEvtNewSettings &event = *static_cast<const MgmtEvtNewSettings *>(&e);
- std::shared_ptr<AdapterInfo> adapterInfo = getAdapterInfo(event.getDevID());
- if( nullptr != adapterInfo ) {
- const AdapterSetting old_settings = adapterInfo->getCurrentSettingMask();
- const AdapterSetting new_settings = adapterInfo->setCurrentSettingMask(event.getSettings());
+ std::shared_ptr<DBTAdapter> 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<ChangedAdapterSetCallback*>(&l);
mgmtChangedAdapterSetCallbackList.push_back(l);
- jau::for_each_const(adapterInfos, [&](const std::shared_ptr<AdapterInfo>& ai) {
- jau::for_each_fidelity(mgmtChangedAdapterSetCallbackList, [&](ChangedAdapterSetCallback &cb) {
- cb.invoke(true /* added */, *ai);
- });
+ jau::for_each_fidelity(adapters, [&](std::shared_ptr<DBTAdapter>& 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<bool, bool, const AdapterInfo&>(f)
+ jau::bindPlainFunc<bool, bool, std::shared_ptr<DBTAdapter>&>(f)
) );
}
int DBTManager::removeChangedAdapterSetCallback(ChangedAdapterSetFunc f) {
- ChangedAdapterSetCallback l( jau::bindPlainFunc<bool, bool, const AdapterInfo&>(f) );
+ ChangedAdapterSetCallback l( jau::bindPlainFunc<bool, bool, std::shared_ptr<DBTAdapter>&>(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<NameAndShortName> MgmtEvtLocalNameChanged::toNameAndShortName()
return std::make_shared<NameAndShortName>(getName(), getShortName());
}
-std::shared_ptr<AdapterInfo> MgmtEvtAdapterInfo::toAdapterInfo() const noexcept {
- return std::make_shared<AdapterInfo>(
+std::unique_ptr<AdapterInfo> MgmtEvtAdapterInfo::toAdapterInfo() const noexcept {
+ return std::make_unique<AdapterInfo>(
getDevID(), getAddress(), getVersion(),
getManufacturer(), getSupportedSetting(),
getCurrentSetting(), getDevClass(),