aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-05-11 10:22:39 +0200
committerSven Gothel <[email protected]>2020-05-11 10:22:39 +0200
commitb06528b908c43860ebd89f72d5f5675ac82badea (patch)
treecce1c7a079c9ef3e7f185afa23c0633113052808 /src
parent2a264bce0f6e5fffdc9488c5e00babd22d711876 (diff)
Resolving flushed discovered devices and shared device reference usage.
Commit 09cd1183b3599357b05c426e2b59e8df813304c5 describes existed issue in a multi device and hence multi-device-discovery environment. (The change has been reverted) This changed resolves the shared device reference usage, by having adapter maintaining a 'sharedDevices' list in parallel to the 'discoveredDevices'. Adapter will add a newly found and created device to both lists, shared- and discovered devices. Device may remove itself from the sharedDevices list via remove() and its destructor. Adapter will also look in sharedDevices in connected and found callback to determine if a device is known and re-adds it to the discovered devices list for consistency. (Note: discoveredDevices may be flushed via a new startDiscovery)
Diffstat (limited to 'src')
-rw-r--r--src/direct_bt/DBTAdapter.cpp115
-rw-r--r--src/direct_bt/DBTDevice.cpp91
2 files changed, 154 insertions, 52 deletions
diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp
index 0005690b..7b542051 100644
--- a/src/direct_bt/DBTAdapter.cpp
+++ b/src/direct_bt/DBTAdapter.cpp
@@ -62,28 +62,27 @@ HCISession::HCISession(DBTAdapter &a, const uint16_t channel, const int timeoutM
name(name_counter.fetch_add(1))
{}
-bool HCISession::connected(std::shared_ptr<DBTDevice> & device) {
+void HCISession::connected(const std::shared_ptr<DBTDevice> & device) {
const std::lock_guard<std::recursive_mutex> lock(mtx_connectedDevices); // RAII-style acquire and relinquish via destructor
for (auto it = connectedDevices.begin(); it != connectedDevices.end(); ++it) {
if ( *device == **it ) {
- return false; // already connected
+ throw InternalError("Device already connected: "+device->toString(), E_FILE_LINE);
}
}
connectedDevices.push_back(device);
- return true;
}
-bool HCISession::disconnected(std::shared_ptr<DBTDevice> & device) {
+void HCISession::disconnected(const DBTDevice & device) {
const std::lock_guard<std::recursive_mutex> lock(mtx_connectedDevices); // RAII-style acquire and relinquish via destructor
for (auto it = connectedDevices.begin(); it != connectedDevices.end(); ) {
- if ( **it == *device ) {
+ if ( &device == (*it).get() ) { // compare actual device address
it = connectedDevices.erase(it);
- return true;
+ return;
} else {
++it;
}
}
- return false;
+ throw InternalError("Device not connected: "+device.toString(), E_FILE_LINE);
}
int HCISession::disconnectAllDevices(const uint8_t reason) {
@@ -214,13 +213,14 @@ DBTAdapter::~DBTAdapter() {
}
statusListenerList.clear();
- removeDiscoveredDevices();
-
if( nullptr != session ) {
stopDiscovery();
session->shutdown(); // force shutdown, not only via dtor as adapter EOL has been reached!
session = nullptr;
}
+ removeDiscoveredDevices();
+ sharedDevices.clear();
+
DBG_PRINT("DBTAdapter::dtor: XXX");
}
@@ -379,6 +379,51 @@ std::vector<std::shared_ptr<DBTDevice>> DBTAdapter::getDiscoveredDevices() const
return res;
}
+bool DBTAdapter::addSharedDevice(std::shared_ptr<DBTDevice> const &device) {
+ const std::lock_guard<std::recursive_mutex> lock(mtx_sharedDevices); // RAII-style acquire and relinquish via destructor
+ for (auto it = sharedDevices.begin(); it != sharedDevices.end(); ++it) {
+ if ( *device == **it ) {
+ // already shared
+ return false;
+ }
+ }
+ sharedDevices.push_back(device);
+ return true;
+}
+
+std::shared_ptr<DBTDevice> DBTAdapter::getSharedDevice(const DBTDevice & device) {
+ const std::lock_guard<std::recursive_mutex> lock(mtx_sharedDevices); // RAII-style acquire and relinquish via destructor
+ for (auto it = sharedDevices.begin(); it != sharedDevices.end(); ++it) {
+ if ( &device == (*it).get() ) { // compare actual device address
+ return *it; // done
+ }
+ }
+ return nullptr;
+}
+
+void DBTAdapter::releaseSharedDevice(const DBTDevice & device) {
+ const std::lock_guard<std::recursive_mutex> lock(mtx_sharedDevices); // RAII-style acquire and relinquish via destructor
+ for (auto it = sharedDevices.begin(); it != sharedDevices.end(); ++it) {
+ if ( &device == (*it).get() ) { // compare actual device address
+ sharedDevices.erase(it);
+ return; // unique set
+ }
+ }
+}
+
+std::shared_ptr<DBTDevice> DBTAdapter::findSharedDevice (EUI48 const & mac) const {
+ const std::lock_guard<std::recursive_mutex> lock(const_cast<DBTAdapter*>(this)->mtx_sharedDevices); // RAII-style acquire and relinquish via destructor
+ auto begin = sharedDevices.begin();
+ auto it = std::find_if(begin, sharedDevices.end(), [&](std::shared_ptr<DBTDevice> const& p) {
+ return p->address == mac;
+ });
+ if ( it == std::end(sharedDevices) ) {
+ return nullptr;
+ } else {
+ return *it;
+ }
+}
+
std::string DBTAdapter::toString() const {
std::string out("Adapter["+getAddressString()+", '"+getName()+"', id="+std::to_string(dev_id)+", "+javaObjectToString()+"]");
std::vector<std::shared_ptr<DBTDevice>> devices = getDiscoveredDevices();
@@ -462,17 +507,24 @@ bool DBTAdapter::mgmtEvDeviceConnectedCB(std::shared_ptr<MgmtEvent> e) {
ad_report.setAddress( event.getAddress() );
ad_report.read_data(event.getData(), event.getDataSize());
}
- bool new_connect = false;
+ int new_connect = 0;
std::shared_ptr<DBTDevice> device = session->findConnectedDevice(event.getAddress());
if( nullptr == device ) {
device = findDiscoveredDevice(event.getAddress());
- new_connect = true;
+ new_connect = nullptr != device ? 1 : 0;
+ }
+ if( nullptr == device ) {
+ device = findSharedDevice(event.getAddress());
+ if( nullptr != device ) {
+ addDiscoveredDevice(device);
+ new_connect = 2;
+ }
}
if( nullptr != device ) {
EIRDataType updateMask = device->update(ad_report);
DBG_PRINT("DBTAdapter::EventCB:DeviceConnected(dev_id %d, new_connect %d, updated %s): %s,\n %s\n -> %s",
dev_id, new_connect, eirDataMaskToString(updateMask).c_str(), event.toString().c_str(), ad_report.toString().c_str(), device->toString().c_str());
- if( new_connect ) {
+ if( 0 < new_connect ) {
session->connected(device); // track it
}
for_each_idx_mtx(mtx_statusListenerList, statusListenerList, [&](std::shared_ptr<DBTAdapterStatusListener> &l) {
@@ -521,21 +573,40 @@ bool DBTAdapter::mgmtEvDeviceFoundCB(std::shared_ptr<MgmtEvent> e) {
ad_report.read_data(deviceFoundEvent.getData(), deviceFoundEvent.getDataSize());
std::shared_ptr<DBTDevice> dev = findDiscoveredDevice(ad_report.getAddress());
- if( nullptr == dev ) {
- // new device
- dev = std::shared_ptr<DBTDevice>(new DBTDevice(*this, ad_report));
- addDiscoveredDevice(dev);
-
- for_each_idx_mtx(mtx_statusListenerList, statusListenerList, [&](std::shared_ptr<DBTAdapterStatusListener> &l) {
- l->deviceFound(*this, dev, ad_report.getTimestamp());
- });
-
- } else {
+ if( nullptr != dev ) {
+ //
// existing device
+ //
+ EIRDataType updateMask = dev->update(ad_report);
+ if( EIRDataType::NONE != updateMask ) {
+ sendDeviceUpdated(dev, ad_report.getTimestamp(), updateMask);
+ }
+ return true;
+ }
+
+ dev = findSharedDevice(ad_report.getAddress());
+ if( nullptr != dev ) {
+ //
+ // active shared device, but flushed from discovered devices
+ //
+ addDiscoveredDevice(dev); // re-add to discovered devices!
EIRDataType updateMask = dev->update(ad_report);
if( EIRDataType::NONE != updateMask ) {
sendDeviceUpdated(dev, ad_report.getTimestamp(), updateMask);
}
+ return true;
}
+
+ //
+ // new device
+ //
+ dev = std::shared_ptr<DBTDevice>(new DBTDevice(*this, ad_report));
+ addDiscoveredDevice(dev);
+ addSharedDevice(dev);
+
+ for_each_idx_mtx(mtx_statusListenerList, statusListenerList, [&](std::shared_ptr<DBTAdapterStatusListener> &l) {
+ l->deviceFound(*this, dev, ad_report.getTimestamp());
+ });
+
return true;
}
diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp
index 01e232f9..983e97b8 100644
--- a/src/direct_bt/DBTDevice.cpp
+++ b/src/direct_bt/DBTDevice.cpp
@@ -55,17 +55,16 @@ DBTDevice::DBTDevice(DBTAdapter & a, EInfoReport const & r)
}
DBTDevice::~DBTDevice() {
- disconnect();
+ remove();
services.clear();
msd = nullptr;
}
std::shared_ptr<DBTDevice> DBTDevice::getSharedInstance() const {
- const std::shared_ptr<DBTDevice> myself = adapter.findDiscoveredDevice(address);
- if( nullptr == myself ) {
- throw InternalError("DBTDevice: Not present in DBTAdapter: "+toString(), E_FILE_LINE);
- }
- return myself;
+ return adapter.getSharedDevice(*this);
+}
+void DBTDevice::releaseSharedInstance() const {
+ adapter.releaseSharedDevice(*this);
}
bool DBTDevice::addService(std::shared_ptr<uuid_t> const &uuid)
@@ -190,7 +189,12 @@ std::shared_ptr<ConnectionInfo> DBTDevice::getConnectionInfo() {
setEIRDataTypeSet(updateMask, EIRDataType::TX_POWER);
}
if( EIRDataType::NONE != updateMask ) {
- adapter.sendDeviceUpdated(getSharedInstance(), getCurrentMilliseconds(), updateMask);
+ std::shared_ptr<DBTDevice> sharedInstance = getSharedInstance();
+ if( nullptr == sharedInstance ) {
+ ERR_PRINT("DBTDevice::getConnectionInfo: Device unknown to adapter and not tracked: %s", toString().c_str());
+ } else {
+ adapter.sendDeviceUpdated(sharedInstance, getCurrentMilliseconds(), updateMask);
+ }
}
}
return connInfo;
@@ -203,17 +207,23 @@ uint16_t DBTDevice::le_connect(HCIAddressType peer_mac_type, HCIAddressType own_
uint16_t min_ce_length, uint16_t max_ce_length,
uint8_t initiator_filter )
{
+ std::shared_ptr<DBTDevice> sharedInstance = getSharedInstance();
+ if( nullptr == sharedInstance ) {
+ ERR_PRINT("DBTDevice::le_connect: Device unknown to adapter and not tracked: %s", toString().c_str());
+ return 0;
+ }
if( 0 < connHandle ) {
ERR_PRINT("DBTDevice::le_connect: Already connected");
return 0;
}
if( !isLEAddressType() ) {
- ERR_PRINT("DBTDevice::connect: Not a BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM address: %s", toString().c_str());
+ ERR_PRINT("DBTDevice::le_connect: Not a BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM address: %s", toString().c_str());
+ return 0;
}
std::shared_ptr<HCISession> session = adapter.getOpenSession();
if( nullptr == session || !session->isOpen() ) {
- ERR_PRINT("DBTDevice::le_connect: Not opened");
+ ERR_PRINT("DBTDevice::le_connect: Adapter session not opened");
return 0;
}
@@ -232,14 +242,18 @@ uint16_t DBTDevice::le_connect(HCIAddressType peer_mac_type, HCIAddressType own_
ERR_PRINT("DBTDevice::le_connect: Could not create connection");
return 0;
}
- std::shared_ptr<DBTDevice> thisDevice = getSharedInstance();
- session->connected(thisDevice);
+ session->connected(sharedInstance);
return connHandle;
}
uint16_t DBTDevice::connect(const uint16_t pkt_type, const uint16_t clock_offset, const uint8_t role_switch)
{
+ std::shared_ptr<DBTDevice> sharedInstance = getSharedInstance();
+ if( nullptr == sharedInstance ) {
+ ERR_PRINT("DBTDevice::connect: Device unknown to adapter and not tracked: %s", toString().c_str());
+ return 0;
+ }
if( 0 < connHandle ) {
ERR_PRINT("DBTDevice::connect: Already connected");
return 0;
@@ -247,11 +261,12 @@ uint16_t DBTDevice::connect(const uint16_t pkt_type, const uint16_t clock_offset
if( !isBREDRAddressType() ) {
ERR_PRINT("DBTDevice::connect: Not a BDADDR_BREDR address: %s", toString().c_str());
+ return 0;
}
std::shared_ptr<HCISession> session = adapter.getOpenSession();
if( nullptr == session || !session->isOpen() ) {
- ERR_PRINT("DBTDevice::connect: Not opened");
+ ERR_PRINT("DBTDevice::connect: Adapter session Not opened");
return 0;
}
@@ -264,11 +279,10 @@ uint16_t DBTDevice::connect(const uint16_t pkt_type, const uint16_t clock_offset
connHandle = session->hciComm.create_conn(address, pkt_type, clock_offset, role_switch);
if ( 0 == connHandle ) {
- ERR_PRINT("DBTDevice::connect: Could not create connection");
+ ERR_PRINT("DBTDevice::connect: Could not create connection (yet)");
return 0;
}
- std::shared_ptr<DBTDevice> thisDevice = getSharedInstance();
- session->connected(thisDevice);
+ session->connected(sharedInstance);
return connHandle;
}
@@ -291,21 +305,24 @@ uint16_t DBTDevice::defaultConnect()
void DBTDevice::disconnect(const uint8_t reason) {
disconnectGATT();
+ std::shared_ptr<HCISession> session = adapter.getOpenSession();
+
if( 0 == connHandle ) {
DBG_PRINT("DBTDevice::disconnect: Not connected");
- return;
+ goto errout;
}
- std::shared_ptr<HCISession> session = adapter.getOpenSession();
if( nullptr == session || !session->isOpen() ) {
DBG_PRINT("DBTDevice::disconnect: Session not opened");
- return;
+ goto errout;
}
- const uint16_t _connHandle = connHandle;
- connHandle = 0;
- if( !session->hciComm.disconnect(_connHandle, reason) ) {
- DBG_PRINT("DBTDevice::disconnect: handle 0x%X, errno %d %s", _leConnHandle, errno, strerror(errno));
+ {
+ const uint16_t _connHandle = connHandle;
+ connHandle = 0;
+ if( !session->hciComm.disconnect(_connHandle, reason) ) {
+ DBG_PRINT("DBTDevice::disconnect: handle 0x%X, errno %d %s", _leConnHandle, errno, strerror(errno));
+ }
}
{
@@ -313,26 +330,40 @@ void DBTDevice::disconnect(const uint8_t reason) {
DBTManager & mngr = adapter.getManager();
mngr.disconnect(adapter.dev_id, address, addressType, reason);
}
+ session->disconnected(*this);
+ return;
+
+errout:
+ if( nullptr != session ) {
+ session->disconnected(*this);
+ }
+}
- std::shared_ptr<DBTDevice> thisDevice = getSharedInstance();
- session->disconnected(thisDevice);
+void DBTDevice::remove() {
+ disconnect(0);
+ releaseSharedInstance();
}
std::shared_ptr<GATTHandler> DBTDevice::connectGATT(int timeoutMS) {
- if( 0 == connHandle ) {
- DBG_PRINT("DBTDevice::connectGATT: Not connected");
- return nullptr;
- }
std::shared_ptr<HCISession> session = adapter.getOpenSession();
if( nullptr == session || !session->isOpen() ) {
- DBG_PRINT("DBTDevice::connectGATT: Session not opened");
+ DBG_PRINT("DBTDevice::connectGATT: Adapter session not opened");
+ return nullptr;
+ }
+ if( 0 == connHandle ) {
+ DBG_PRINT("DBTDevice::connectGATT: Device not connected");
return nullptr;
}
+ std::shared_ptr<DBTDevice> sharedInstance = getSharedInstance();
+ if( nullptr == sharedInstance ) {
+ throw InternalError("DBTDevice::connectGATT: Device unknown to adapter and not tracked: "+toString(), E_FILE_LINE);
+ }
+
const std::lock_guard<std::recursive_mutex> lock(mtx_gatt); // RAII-style acquire and relinquish via destructor
if( nullptr != gattHandler ) {
return gattHandler;
}
- std::shared_ptr<GATTHandler> _gattHandler = std::shared_ptr<GATTHandler>(new GATTHandler(this->getSharedInstance(), timeoutMS));
+ std::shared_ptr<GATTHandler> _gattHandler = std::shared_ptr<GATTHandler>(new GATTHandler(sharedInstance, timeoutMS));
if( _gattHandler->connect() ) {
gattHandler = _gattHandler;
} else {