summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-07-21 22:15:23 +0200
committerSven Gothel <[email protected]>2020-07-21 22:15:23 +0200
commitda1f91d69daa6eacb00824760b11f33a921732f5 (patch)
tree0b3620c88855e0e16677a4c7d4775888cbba2b61
parent01eec2e5f4ce0c91f64bcf1035cdda22f6f6ea3a (diff)
DBTAdapter: Make HCIHandler instance aggregated (lifecycle over full adapter lifecycle)
Since HCIHandler is being used to track all connections (direct or whitelisted), it is essential to have it running over the whole adapter lifecycle. openHCI() is now being performed within validateDevInfo(), hence also sets adapter's valid state. Call newly added checkValid() in user API on most 'action' methods, throws exception if adapter is in invalid state.
-rw-r--r--api/direct_bt/DBTAdapter.hpp23
-rw-r--r--examples/direct_bt_scanner01/dbt_scanner01.cpp9
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx4
-rw-r--r--src/direct_bt/DBTAdapter.cpp98
-rw-r--r--src/direct_bt/DBTDevice.cpp13
5 files changed, 64 insertions, 83 deletions
diff --git a/api/direct_bt/DBTAdapter.hpp b/api/direct_bt/DBTAdapter.hpp
index 2df0a867..a8725510 100644
--- a/api/direct_bt/DBTAdapter.hpp
+++ b/api/direct_bt/DBTAdapter.hpp
@@ -165,14 +165,20 @@ namespace direct_bt {
std::vector<std::shared_ptr<DBTDevice>> discoveredDevices; // all discovered devices
std::vector<std::shared_ptr<DBTDevice>> sharedDevices; // all active shared devices
std::vector<std::shared_ptr<AdapterStatusListener>> statusListenerList;
- std::recursive_mutex mtx_hci;
std::recursive_mutex mtx_connectedDevices;
std::recursive_mutex mtx_discoveredDevices;
std::recursive_mutex mtx_sharedDevices;
std::recursive_mutex mtx_statusListenerList;
std::recursive_mutex mtx_discovery;
+ inline void checkValid() {
+ if( !valid ) {
+ throw IllegalStateException("Adapter state invalid: "+toString(), E_FILE_LINE);
+ }
+ }
bool validateDevInfo();
+ bool openHCI();
+ bool closeHCI();
friend std::shared_ptr<DBTDevice> DBTDevice::getSharedInstance() const;
friend void DBTDevice::releaseSharedInstance() const;
@@ -296,20 +302,9 @@ namespace direct_bt {
DBTManager& getManager() const { return mgmt; }
/**
- * Returns a reference to the already opened HCIHandler
- * or the newly opened HCIHandler instance, otherwise nullptr if no success.
- */
- std::shared_ptr<HCIHandler> openHCI();
-
- /**
* Returns the {@link #openHCI()} HCIHandler or {@code nullptr} if closed.
*/
- std::shared_ptr<HCIHandler> getHCI() const;
-
- /**
- * Closes the HCIHandler instance
- */
- bool closeHCI();
+ std::shared_ptr<HCIHandler> getHCI() const { return hci; }
/**
* Returns true, if the adapter's device is already whitelisted.
@@ -332,7 +327,7 @@ namespace direct_bt {
* @param conn_interval_max default value 0x000F
* @param conn_latency default value 0x0000
* @param timeout in units of 10ms, default value 1000 for 10000ms or 10s.
- * @return
+ * @return true if the device was already added or has been newly added to the adapter's whitelist.
*/
bool addDeviceToWhitelist(const EUI48 &address, const BDAddressType address_type,
const HCIWhitelistConnectType ctype,
diff --git a/examples/direct_bt_scanner01/dbt_scanner01.cpp b/examples/direct_bt_scanner01/dbt_scanner01.cpp
index ca774277..10eca512 100644
--- a/examples/direct_bt_scanner01/dbt_scanner01.cpp
+++ b/examples/direct_bt_scanner01/dbt_scanner01.cpp
@@ -187,14 +187,6 @@ int main(int argc, char *argv[])
const int64_t t0 = getCurrentMilliseconds();
- if( doHCI_Connect ) {
- std::shared_ptr<HCIHandler> hci = adapter.openHCI();
- if( nullptr == hci || !hci->isOpen() ) {
- fprintf(stderr, "Couldn't open HCI from %s\n", adapter.toString().c_str());
- exit(1);
- }
- }
-
while( ok && ( forever || !foundDevice ) ) {
ok = adapter.startDiscovery(true /* keepAlive */);
if( !ok) {
@@ -327,7 +319,6 @@ int main(int argc, char *argv[])
#endif /* SHOW_STATIC_SERVICE_CHARACTERISTIC_COMPOSITION */
out:
- adapter.closeHCI();
return 0;
}
diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx
index 4aa4c434..26b3fbcb 100644
--- a/java/jni/direct_bt/DBTAdapter.cxx
+++ b/java/jni/direct_bt/DBTAdapter.cxx
@@ -624,9 +624,9 @@ jobject Java_direct_1bt_tinyb_DBTAdapter_connectDevice(JNIEnv *env, jobject obj,
const BDAddressType addressType = fromJavaAdressTypeToBDAddressType(env, jaddressType);
std::shared_ptr<DBTDevice> device = adapter->findDiscoveredDevice(address, addressType);
if( nullptr != device ) {
- std::shared_ptr<direct_bt::HCIHandler> hci = adapter->openHCI();
+ std::shared_ptr<direct_bt::HCIHandler> hci = adapter->getHCI();
if( nullptr == hci ) {
- throw BluetoothException("Couldn't get or open adapter's HCI "+adapter->toString(), E_FILE_LINE);
+ throw BluetoothException("Adapter's HCI not open "+adapter->toString(), E_FILE_LINE);
}
std::shared_ptr<JavaAnonObj> jDeviceRef = device->getJavaObject();
JavaGlobalObj::check(jDeviceRef, E_FILE_LINE);
diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp
index 56e15422..e972f277 100644
--- a/src/direct_bt/DBTAdapter.cpp
+++ b/src/direct_bt/DBTAdapter.cpp
@@ -131,11 +131,45 @@ std::shared_ptr<DBTDevice> DBTAdapter::findConnectedDevice (EUI48 const & mac, c
// *************************************************
// *************************************************
+bool DBTAdapter::openHCI()
+{
+ HCIHandler *s = new HCIHandler(btMode, dev_id, HCIHandler::Defaults::HCI_COMMAND_REPLY_TIMEOUT);
+ if( !s->isOpen() ) {
+ delete s;
+ ERR_PRINT("Could not open HCIHandler: %s of %s", s->toString().c_str(), toString().c_str());
+ return false;
+ }
+ hci = std::shared_ptr<HCIHandler>( s );
+ return true;
+}
+
+bool DBTAdapter::closeHCI()
+{
+ DBG_PRINT("DBTAdapter::closeHCI: ...");
+ if( nullptr == hci || !hci->isOpen() ) {
+ DBG_PRINT("DBTAdapter::closeHCI: Not open");
+ return false;
+ }
+ hci->close();
+ hci = nullptr;
+ DBG_PRINT("DBTAdapter::closeHCI: XXX");
+ return true;
+}
+
bool DBTAdapter::validateDevInfo() {
currentScanType = ScanType::SCAN_TYPE_NONE;
keepDiscoveringAlive = false;
- if( !mgmt.isOpen() || 0 > dev_id ) {
+ if( 0 > dev_id ) {
+ ERR_PRINT("DBTAdapter::validateDevInfo: Invalid negative dev_id: %s", toString().c_str());
+ return false;
+ }
+ if( !mgmt.isOpen() ) {
+ ERR_PRINT("DBTAdapter::validateDevInfo: Manager not open: %s", toString().c_str());
+ return false;
+ }
+ if( !openHCI() ) {
+ ERR_PRINT("DBTAdapter::validateDevInfo: Opening adapter's HCI failed: %s", toString().c_str());
return false;
}
@@ -144,6 +178,11 @@ bool DBTAdapter::validateDevInfo() {
mgmt.addMgmtEventCallback(dev_id, MgmtEvent::Opcode::NEW_SETTINGS, bindMemberFunc(this, &DBTAdapter::mgmtEvNewSettingsMgmt));
mgmt.addMgmtEventCallback(dev_id, MgmtEvent::Opcode::LOCAL_NAME_CHANGED, bindMemberFunc(this, &DBTAdapter::mgmtEvLocalNameChangedMgmt));
mgmt.addMgmtEventCallback(dev_id, MgmtEvent::Opcode::DEVICE_FOUND, bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceFoundMgmt));
+
+ hci->addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_CONNECTED, bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceConnectedHCI));
+ hci->addMgmtEventCallback(MgmtEvent::Opcode::CONNECT_FAILED, bindMemberFunc(this, &DBTAdapter::mgmtEvConnectFailedHCI));
+ hci->addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_DISCONNECTED, bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceDisconnectedHCI));
+
#ifdef VERBOSE_ON
mgmt.addMgmtEventCallback(dev_id, MgmtEvent::Opcode::DEVICE_DISCONNECTED, bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceDisconnectedMgmt));
#endif
@@ -213,54 +252,6 @@ void DBTAdapter::setBondable(bool value) {
mgmt.setMode(dev_id, MgmtOpcode::SET_BONDABLE, value ? 1 : 0);
}
-std::shared_ptr<HCIHandler> DBTAdapter::openHCI()
-{
- const std::lock_guard<std::recursive_mutex> lock(mtx_hci); // RAII-style acquire and relinquish via destructor
-
- if( !valid ) {
- return nullptr;
- }
- if( nullptr != hci ) {
- if( hci->isOpen() ) {
- DBG_PRINT("DBTAdapter::openHCI: Already open");
- return hci;
- }
- hci = nullptr;
- }
- HCIHandler *s = new HCIHandler(btMode, dev_id, HCIHandler::Defaults::HCI_COMMAND_REPLY_TIMEOUT);
- if( !s->isOpen() ) {
- delete s;
- ERR_PRINT("Could not open HCIHandler: %s of %s", s->toString().c_str(), toString().c_str());
- return nullptr;
- }
- hci = std::shared_ptr<HCIHandler>( s );
- hci->addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_CONNECTED, bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceConnectedHCI));
- hci->addMgmtEventCallback(MgmtEvent::Opcode::CONNECT_FAILED, bindMemberFunc(this, &DBTAdapter::mgmtEvConnectFailedHCI));
- hci->addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_DISCONNECTED, bindMemberFunc(this, &DBTAdapter::mgmtEvDeviceDisconnectedHCI));
- return hci;
-}
-
-std::shared_ptr<HCIHandler> DBTAdapter::getHCI() const {
- const std::lock_guard<std::recursive_mutex> lock(const_cast<DBTAdapter*>(this)->mtx_hci); // RAII-style acquire and relinquish via destructor
- return hci;
-}
-
-bool DBTAdapter::closeHCI()
-{
- const std::lock_guard<std::recursive_mutex> lock(mtx_hci); // RAII-style acquire and relinquish via destructor
-
- DBG_PRINT("DBTAdapter::closeHCI: ...");
- if( nullptr == hci || !hci->isOpen() ) {
- DBG_PRINT("DBTAdapter::closeHCI: Not open");
- return false;
- }
- disconnectAllDevices(); // FIXME ????
- hci->close();
- hci = nullptr;
- DBG_PRINT("DBTAdapter::closeHCI: XXX");
- return true;
-}
-
bool DBTAdapter::isDeviceWhitelisted(const EUI48 &address) {
return mgmt.isDeviceWhitelisted(dev_id, address);
}
@@ -268,9 +259,10 @@ bool DBTAdapter::isDeviceWhitelisted(const EUI48 &address) {
bool DBTAdapter::addDeviceToWhitelist(const EUI48 &address, const BDAddressType address_type, const HCIWhitelistConnectType ctype,
const uint16_t conn_interval_min, const uint16_t conn_interval_max,
const uint16_t conn_latency, const uint16_t timeout) {
+ checkValid();
if( mgmt.isDeviceWhitelisted(dev_id, address) ) {
ERR_PRINT("DBTAdapter::addDeviceToWhitelist: device already listed: dev_id %d, address %s", dev_id, address.toString().c_str());
- return false;
+ return true;
}
if( !mgmt.uploadConnParam(dev_id, address, address_type, conn_interval_min, conn_interval_max, conn_latency, timeout) ) {
@@ -281,10 +273,12 @@ bool DBTAdapter::addDeviceToWhitelist(const EUI48 &address, const BDAddressType
}
bool DBTAdapter::removeDeviceFromWhitelist(const EUI48 &address, const BDAddressType address_type) {
+ checkValid();
return mgmt.removeDeviceFromWhitelist(dev_id, address, address_type);
}
bool DBTAdapter::addStatusListener(std::shared_ptr<AdapterStatusListener> l) {
+ checkValid();
if( nullptr == l ) {
throw IllegalArgumentException("DBTAdapterStatusListener ref is null", E_FILE_LINE);
}
@@ -301,6 +295,7 @@ bool DBTAdapter::addStatusListener(std::shared_ptr<AdapterStatusListener> l) {
}
bool DBTAdapter::removeStatusListener(std::shared_ptr<AdapterStatusListener> l) {
+ checkValid();
if( nullptr == l ) {
throw IllegalArgumentException("DBTAdapterStatusListener ref is null", E_FILE_LINE);
}
@@ -317,6 +312,7 @@ bool DBTAdapter::removeStatusListener(std::shared_ptr<AdapterStatusListener> l)
}
bool DBTAdapter::removeStatusListener(const AdapterStatusListener * l) {
+ checkValid();
if( nullptr == l ) {
throw IllegalArgumentException("DBTAdapterStatusListener ref is null", E_FILE_LINE);
}
@@ -333,6 +329,7 @@ bool DBTAdapter::removeStatusListener(const AdapterStatusListener * l) {
}
int DBTAdapter::removeAllStatusListener() {
+ checkValid();
const std::lock_guard<std::recursive_mutex> lock(mtx_statusListenerList); // RAII-style acquire and relinquish via destructor
int count = statusListenerList.size();
statusListenerList.clear();
@@ -342,6 +339,7 @@ int DBTAdapter::removeAllStatusListener() {
bool DBTAdapter::startDiscovery(const bool keepAlive, const HCILEOwnAddressType own_mac_type,
const uint16_t le_scan_interval, const uint16_t le_scan_window)
{
+ checkValid();
const std::lock_guard<std::recursive_mutex> lock(mtx_discovery); // RAII-style acquire and relinquish via destructor
if( ScanType::SCAN_TYPE_NONE != currentScanType ) {
return true;
diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp
index fbff90c1..f5fc9713 100644
--- a/src/direct_bt/DBTDevice.cpp
+++ b/src/direct_bt/DBTDevice.cpp
@@ -313,10 +313,9 @@ bool DBTDevice::connectLE(uint16_t le_scan_interval, uint16_t le_scan_window,
return false;
}
- const std::lock_guard<std::recursive_mutex> lock_hci(adapter.mtx_hci); // RAII-style acquire and relinquish via destructor
- std::shared_ptr<HCIHandler> hci = adapter.openHCI();
+ std::shared_ptr<HCIHandler> hci = adapter.getHCI();
if( nullptr == hci || !hci->isOpen() ) {
- ERR_PRINT("DBTDevice::connectLE: Opening adapter's HCI failed: %s", toString().c_str());
+ ERR_PRINT("DBTDevice::connectLE: Adapter's HCI not open: %s", toString().c_str());
return false;
}
@@ -364,10 +363,9 @@ bool DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offse
ERR_PRINT("DBTDevice::connectBREDR: Already connected: %s", toString().c_str());
return false;
}
- const std::lock_guard<std::recursive_mutex> lock_hci(adapter.mtx_hci); // RAII-style acquire and relinquish via destructor
- std::shared_ptr<HCIHandler> hci = adapter.openHCI();
+ std::shared_ptr<HCIHandler> hci = adapter.getHCI();
if( nullptr == hci || !hci->isOpen() ) {
- ERR_PRINT("DBTDevice::connectBREDR: Opening adapter's HCI failed: %s", toString().c_str());
+ ERR_PRINT("DBTDevice::connectBREDR: Adapter's HCI not open: %s", toString().c_str());
return false;
}
if( !isBREDRAddressType() ) {
@@ -429,7 +427,6 @@ bool DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
bool res = false;
- const std::lock_guard<std::recursive_mutex> lock_hci(adapter.mtx_hci); // RAII-style acquire and relinquish via destructor
std::shared_ptr<HCIHandler> hci = adapter.getHCI();
if( !isConnected || !isConnectIssued ) {
@@ -442,7 +439,7 @@ bool DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
}
if( nullptr == hci || !hci->isOpen() ) {
- DBG_PRINT("DBTDevice::disconnect: Skip HCI disconnect: HCI not Open: %s", toString().c_str());
+ DBG_PRINT("DBTDevice::disconnect: Skip disconnect: HCI not Open: %s", toString().c_str());
goto exit;
}