From 0c3be5a703def35ddfcf50d66ece608411fd9976 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 26 Apr 2020 01:53:28 +0200 Subject: DBTManager / DBTDeviceStatusListener: Refine events; java: Keep alive discovery; Remove discovery thread (1) DBTAdapter: Keep alive discovery DBTDeviceStatusListener (incl Java binding: - DBTDeviceDiscoveryListener -> DBTDeviceStatusListener to cover more functionality - Rename deviceAdded -> deviceFound, to match BlueZ event naming - Rename deviceRemoved -> deviceDisconnected - Add deviceConnected HCIComm/DBTAdapter: Use HCIAddressType where applicable for clarity MgmtEvent: Add timestamp MgmtEvent: Add MgmtEvtDeviceConnectFailed, MgmtEvtDeviceAdded, MgmtEvtDeviceRemoved, MgmtEvtDeviceUnpaired +++ DBTAdapter.java remove discovery thread (part 1) - Use events, no more discovery polling required - TODO: Same for native DBTAdapter.cpp! --- api/direct_bt/DBTManager.hpp | 15 ++ api/direct_bt/DBTTypes.hpp | 65 ++++-- api/direct_bt/HCIComm.hpp | 6 +- api/direct_bt/MgmtTypes.hpp | 120 ++++++++++- examples/direct_bt_scanner/dbt_scanner.cpp | 25 ++- examples/java/ScannerTinyB01.java | 22 +- java/direct_bt/tinyb/DBTAdapter.java | 238 +++++++-------------- java/jni/direct_bt/DBTAdapter.cxx | 94 +++++--- java/org/tinyb/BluetoothAdapter.java | 6 +- .../tinyb/BluetoothDeviceDiscoveryListener.java | 42 ---- java/org/tinyb/BluetoothDeviceStatusListener.java | 44 ++++ java/tinyb/dbus/DBusAdapter.java | 4 +- src/direct_bt/BTTypes.cpp | 3 +- src/direct_bt/DBTAdapter.cpp | 126 +++++++---- src/direct_bt/DBTDevice.cpp | 4 +- src/direct_bt/DBTManager.cpp | 10 + src/direct_bt/HCIComm.cpp | 6 +- src/direct_bt/MgmtTypes.cpp | 8 + 18 files changed, 516 insertions(+), 322 deletions(-) delete mode 100644 java/org/tinyb/BluetoothDeviceDiscoveryListener.java create mode 100644 java/org/tinyb/BluetoothDeviceStatusListener.java diff --git a/api/direct_bt/DBTManager.hpp b/api/direct_bt/DBTManager.hpp index d0d8ae24..77443349 100644 --- a/api/direct_bt/DBTManager.hpp +++ b/api/direct_bt/DBTManager.hpp @@ -97,6 +97,19 @@ namespace direct_bt { bool initAdapter(const uint16_t dev_id, const BTMode btMode); void shutdownAdapter(const uint16_t dev_id); + /** + * DBTDeviceStatusListener reflecting certain MgmtEvent: + DEVICE_CONNECTED = 0x000B, * + DEVICE_DISCONNECTED = 0x000C, * + CONNECT_FAILED = 0x000D, * + DEVICE_FOUND = 0x0012, * + DEVICE_ADDED = 0x001A, * + DEVICE_REMOVED = 0x001B, * + + DEVICE_BLOCKED = 0x0014, + DEVICE_UNBLOCKED = 0x0015, + DEVICE_UNPAIRED = 0x0016, + */ bool mgmtEvClassOfDeviChangedCB(std::shared_ptr e); bool mgmtEvLocalNameChangedCB(std::shared_ptr e); bool mgmtEvDeviceDiscoveringCB(std::shared_ptr e); @@ -106,6 +119,8 @@ namespace direct_bt { bool mgmtEvConnectFailedCB(std::shared_ptr e); bool mgmtEvDeviceUnpairedCB(std::shared_ptr e); bool mgmtEvNewConnectionParamCB(std::shared_ptr e); + bool mgmtEvDeviceAddedCB(std::shared_ptr e); + bool mgmtEvDeviceRemovedCB(std::shared_ptr e); public: /** diff --git a/api/direct_bt/DBTTypes.hpp b/api/direct_bt/DBTTypes.hpp index 85603cf5..8721b113 100644 --- a/api/direct_bt/DBTTypes.hpp +++ b/api/direct_bt/DBTTypes.hpp @@ -56,9 +56,9 @@ namespace direct_bt { /** * A HCI session, using an underlying {@link HCIComm} instance, - * tracking all open LE connections. + * tracking all open connections. *

- * At destruction, all remaining LE connections will be closed. + * At destruction, all remaining connections will be closed. *

*/ class HCISession @@ -70,7 +70,7 @@ namespace direct_bt { static std::atomic_int name_counter; DBTAdapter * adapter; HCIComm hciComm; - std::vector> connectedLEDevices; + std::vector> connectedDevices; /** Opens a new HCI session on the given BT dev_id and HCI channel. */ HCISession(DBTAdapter &a, const uint16_t dev_id, const uint16_t channel, const int timeoutMS=HCI_TO_SEND_REQ_POLL_MS) @@ -78,14 +78,14 @@ namespace direct_bt { name(name_counter.fetch_add(1)) {} - /** add the new {@link DBTDevice} to the list of connected LE devices */ - void connectedLE(std::shared_ptr & device); + /** add the new {@link DBTDevice} to the list of connected devices */ + void connected(std::shared_ptr & device); - /** remove the {@link DBTDevice} from the list of connected LE devices */ - void disconnectedLE(std::shared_ptr & device); + /** remove the {@link DBTDevice} from the list of connected devices */ + void disconnected(std::shared_ptr & device); /** - * Issues {@link #disconnectAllLEDevices()} and closes the underlying HCI session. + * Issues {@link #disconnectAllDevices()} and closes the underlying HCI session. *

* This shutdown hook is solely intended for adapter's destructor. *

@@ -100,14 +100,14 @@ namespace direct_bt { */ ~HCISession(); - /** Return connected LE {@link DBTDevice}s. */ - std::vector> getConnectedLEDevices() { return connectedLEDevices; } + /** Return connected {@link DBTDevice}s. */ + std::vector> getConnectedDevices() { return connectedDevices; } - /** Disconnect all connected LE devices. Returns number of removed discovered devices. */ - int disconnectAllLEDevices(const uint8_t reason=0); + /** Disconnect all connected devices. Returns number of removed discovered devices. */ + int disconnectAllDevices(const uint8_t reason=0); - /** Returns connected LE DBTDevice if found, otherwise nullptr */ - std::shared_ptr findConnectedLEDevice (EUI48 const & mac) const; + /** Returns connected DBTDevice if found, otherwise nullptr */ + std::shared_ptr findConnectedDevice (EUI48 const & mac) const; /** * Closes this instance by {@link #disconnectAllLEDevices()} @@ -168,12 +168,27 @@ namespace direct_bt { // ************************************************* // ************************************************* - class DBTDeviceDiscoveryListener { + /** + * DBTDeviceStatusListener reflecting certain MgmtEvent: + DEVICE_CONNECTED = 0x000B, * deviceConnected + DEVICE_DISCONNECTED = 0x000C, * deviceDisconnected + CONNECT_FAILED = 0x000D, + DEVICE_FOUND = 0x0012, * deviceFound, deviceUpdated + DEVICE_ADDED = 0x001A, + DEVICE_REMOVED = 0x001B, + + DEVICE_BLOCKED = 0x0014, + DEVICE_UNBLOCKED = 0x0015, + DEVICE_UNPAIRED = 0x0016, + */ + class DBTDeviceStatusListener { public: - virtual void deviceAdded(DBTAdapter const &a, std::shared_ptr device) = 0; - virtual void deviceUpdated(DBTAdapter const &a, std::shared_ptr device) = 0; - virtual void deviceRemoved(DBTAdapter const &a, std::shared_ptr device) = 0; - virtual ~DBTDeviceDiscoveryListener() {} + virtual void deviceFound(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) = 0; + virtual void deviceUpdated(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) = 0; + virtual void deviceConnected(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) = 0; + virtual void deviceDisconnected(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) = 0; + // virtual void deviceRemoved(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) = 0; + virtual ~DBTDeviceStatusListener() {} }; class DBTDevice : public DBTObject @@ -302,7 +317,7 @@ namespace direct_bt { std::shared_ptr session; std::vector> scannedDevices; // all devices scanned std::vector> discoveredDevices; // matching all requirements for export - std::shared_ptr deviceDiscoveryListener = nullptr; + std::shared_ptr deviceStatusListener = nullptr; bool validateDevInfo(); @@ -321,6 +336,10 @@ namespace direct_bt { std::shared_ptr eventReceived = nullptr; bool mgmtEvDeviceDiscoveringCB(std::shared_ptr e); bool mgmtEvDeviceFoundCB(std::shared_ptr e); + bool mgmtEvDeviceConnectedCB(std::shared_ptr e); + bool mgmtEvDeviceDisconnectedCB(std::shared_ptr e); + + void startDiscoveryBackground(); int discoverDevicesHCI(const int waitForDeviceCount, const EUI48 &waitForDevice, const int timeoutMS, const uint32_t ad_type_req); @@ -381,9 +400,9 @@ namespace direct_bt { // device discovery aka device scanning /** - * Replaces the DBTDeviceDiscoveryListener with the given instance, returning the replaced one. + * Replaces the DBTDeviceStatusListener with the given instance, returning the replaced one. */ - std::shared_ptr setDeviceDiscoveryListener(std::shared_ptr l); + std::shared_ptr setDeviceStatusListener(std::shared_ptr l); /** * Starts a new discovery session. @@ -398,7 +417,7 @@ namespace direct_bt { * This adapter's DBTManager instance is used, i.e. the management channel. *

*/ - bool startDiscovery(uint8_t own_mac_type=HCIADDR_LE_PUBLIC, + bool startDiscovery(HCIAddressType own_mac_type=HCIAddressType::HCIADDR_LE_PUBLIC, uint16_t interval=0x0004, uint16_t window=0x0004); /** diff --git a/api/direct_bt/HCIComm.hpp b/api/direct_bt/HCIComm.hpp index 1e25b472..e3e767f9 100644 --- a/api/direct_bt/HCIComm.hpp +++ b/api/direct_bt/HCIComm.hpp @@ -99,12 +99,12 @@ namespace direct_bt { int write(const uint8_t* buffer, const int size); void le_disable_scan(); - bool le_enable_scan(const uint8_t own_type=HCIADDR_LE_PUBLIC, + bool le_enable_scan(const HCIAddressType own_type=HCIAddressType::HCIADDR_LE_PUBLIC, const uint16_t interval=0x0004, const uint16_t window=0x0004); uint16_t le_create_conn(const EUI48 &peer_bdaddr, - const uint8_t peer_mac_type=HCIADDR_LE_PUBLIC, - const uint8_t own_mac_type=HCIADDR_LE_PUBLIC, + const HCIAddressType peer_mac_type=HCIAddressType::HCIADDR_LE_PUBLIC, + const HCIAddressType own_mac_type=HCIAddressType::HCIADDR_LE_PUBLIC, const uint16_t interval=0x0004, const uint16_t window=0x0004, const uint16_t min_interval=0x000F, const uint16_t max_interval=0x000F, const uint16_t latency=0x0000, const uint16_t supervision_timeout=0x0C80, diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp index 6d8c230b..556f2de3 100644 --- a/api/direct_bt/MgmtTypes.hpp +++ b/api/direct_bt/MgmtTypes.hpp @@ -319,6 +319,7 @@ namespace direct_bt { protected: /** actual received mgmt event */ POctets pdu; + uint64_t ts_creation; static void checkOpcode(const Opcode has, const Opcode min, const Opcode max) { @@ -356,7 +357,7 @@ namespace direct_bt { /** Persistent memory, w/ ownership ..*/ MgmtEvent(const uint8_t* buffer, const int buffer_len) - : pdu(buffer, buffer_len) + : pdu(buffer, buffer_len), ts_creation(getCurrentMilliseconds()) { pdu.check_range(0, MGMT_HEADER_SIZE+getParamSize()); checkOpcode(getOpcode(), CMD_COMPLETE, PHY_CONFIGURATION_CHANGED); @@ -365,6 +366,7 @@ namespace direct_bt { int getTotalSize() const { return pdu.getSize(); } + uint64_t getTimestamp() const { return ts_creation; } Opcode getOpcode() const { return static_cast( pdu.get_uint16(0) ); } std::string getOpcodeString() const { return getOpcodeString(getOpcode()); } uint16_t getDevID() const { return pdu.get_uint16(2); } @@ -537,6 +539,37 @@ namespace direct_bt { const uint8_t* getData() const override { return getDataSize()>0 ? pdu.get_ptr(getDataOffset()) : nullptr; } }; + /** + * mgmt_addr_info { EUI48, uint8_t type }, + * uint8_t status + */ + class MgmtEvtDeviceConnectFailed : public MgmtEvent + { + public: + + protected: + std::string baseString() const override { + return MgmtEvent::baseString()+", address="+getAddress().toString()+ + ", addressType "+getBDAddressTypeString(getAddressType())+ + ", status "+uint8HexString(getStatus(), true)+" "+getMgmtStatusString(getStatus()); + } + + public: + MgmtEvtDeviceConnectFailed(const uint8_t* buffer, const int buffer_len) + : MgmtEvent(buffer, buffer_len) + { + checkOpcode(getOpcode(), CONNECT_FAILED); + } + const EUI48 getAddress() const { return EUI48(pdu.get_ptr(MGMT_HEADER_SIZE)); } // mgmt_addr_info + BDAddressType getAddressType() const { return static_cast(pdu.get_uint8(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info + + MgmtStatus getStatus() const { return static_cast( pdu.get_uint8(MGMT_HEADER_SIZE+7) ); } + + int getDataOffset() const override { return MGMT_HEADER_SIZE+8; } + int getDataSize() const override { return getParamSize()-8; } + const uint8_t* getData() const override { return getDataSize()>0 ? pdu.get_ptr(getDataOffset()) : nullptr; } + }; + /** * mgmt_addr_info { EUI48, uint8_t type }, * uint8_t reason @@ -568,6 +601,91 @@ namespace direct_bt { const uint8_t* getData() const override { return getDataSize()>0 ? pdu.get_ptr(getDataOffset()) : nullptr; } }; + /** + * mgmt_addr_info { EUI48, uint8_t type }, + * uint8_t action + */ + class MgmtEvtDeviceAdded : public MgmtEvent + { + public: + + protected: + std::string baseString() const override { + return MgmtEvent::baseString()+", address="+getAddress().toString()+ + ", addressType "+getBDAddressTypeString(getAddressType())+ + ", action "+std::to_string(getAction()); + } + + public: + MgmtEvtDeviceAdded(const uint8_t* buffer, const int buffer_len) + : MgmtEvent(buffer, buffer_len) + { + checkOpcode(getOpcode(), DEVICE_ADDED); + } + const EUI48 getAddress() const { return EUI48(pdu.get_ptr(MGMT_HEADER_SIZE)); } // mgmt_addr_info + BDAddressType getAddressType() const { return static_cast(pdu.get_uint8(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info + + uint8_t getAction() const { return pdu.get_uint8(MGMT_HEADER_SIZE+7); } + + int getDataOffset() const override { return MGMT_HEADER_SIZE+8; } + int getDataSize() const override { return getParamSize()-8; } + const uint8_t* getData() const override { return getDataSize()>0 ? pdu.get_ptr(getDataOffset()) : nullptr; } + }; + + /** + * mgmt_addr_info { EUI48, uint8_t type }, + */ + class MgmtEvtDeviceRemoved : public MgmtEvent + { + public: + + protected: + std::string baseString() const override { + return MgmtEvent::baseString()+", address="+getAddress().toString()+ + ", addressType "+getBDAddressTypeString(getAddressType()); + } + + public: + MgmtEvtDeviceRemoved(const uint8_t* buffer, const int buffer_len) + : MgmtEvent(buffer, buffer_len) + { + checkOpcode(getOpcode(), DEVICE_REMOVED); + } + const EUI48 getAddress() const { return EUI48(pdu.get_ptr(MGMT_HEADER_SIZE)); } // mgmt_addr_info + BDAddressType getAddressType() const { return static_cast(pdu.get_uint8(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info + + int getDataOffset() const override { return MGMT_HEADER_SIZE+7; } + int getDataSize() const override { return getParamSize()-7; } + const uint8_t* getData() const override { return getDataSize()>0 ? pdu.get_ptr(getDataOffset()) : nullptr; } + }; + + /** + * mgmt_addr_info { EUI48, uint8_t type }, + */ + class MgmtEvtDeviceUnpaired : public MgmtEvent + { + public: + + protected: + std::string baseString() const override { + return MgmtEvent::baseString()+", address="+getAddress().toString()+ + ", addressType "+getBDAddressTypeString(getAddressType()); + } + + public: + MgmtEvtDeviceUnpaired(const uint8_t* buffer, const int buffer_len) + : MgmtEvent(buffer, buffer_len) + { + checkOpcode(getOpcode(), DEVICE_UNPAIRED); + } + const EUI48 getAddress() const { return EUI48(pdu.get_ptr(MGMT_HEADER_SIZE)); } // mgmt_addr_info + BDAddressType getAddressType() const { return static_cast(pdu.get_uint8(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info + + int getDataOffset() const override { return MGMT_HEADER_SIZE+7; } + int getDataSize() const override { return getParamSize()-7; } + const uint8_t* getData() const override { return getDataSize()>0 ? pdu.get_ptr(getDataOffset()) : nullptr; } + }; + class MgmtEvtAdapterInfo : public MgmtEvtCmdComplete { protected: diff --git a/examples/direct_bt_scanner/dbt_scanner.cpp b/examples/direct_bt_scanner/dbt_scanner.cpp index 3d54d542..4f92d1eb 100644 --- a/examples/direct_bt_scanner/dbt_scanner.cpp +++ b/examples/direct_bt_scanner/dbt_scanner.cpp @@ -36,22 +36,33 @@ extern "C" { using namespace direct_bt; -class DeviceDiscoveryListener : public direct_bt::DBTDeviceDiscoveryListener { - void deviceAdded(direct_bt::DBTAdapter const &a, std::shared_ptr device) override { - fprintf(stderr, "****** ADDED__: %s\n", device->toString().c_str()); +class DeviceStatusListener : public direct_bt::DBTDeviceStatusListener { + void deviceFound(direct_bt::DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { + fprintf(stderr, "****** FOUND__: %s\n", device->toString().c_str()); fprintf(stderr, "Status HCIAdapter:\n"); fprintf(stderr, "%s\n", a.toString().c_str()); } - void deviceUpdated(direct_bt::DBTAdapter const &a, std::shared_ptr device) override { + void deviceUpdated(direct_bt::DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { fprintf(stderr, "****** UPDATED: %s\n", device->toString().c_str()); fprintf(stderr, "Status HCIAdapter:\n"); fprintf(stderr, "%s\n", a.toString().c_str()); } - void deviceRemoved(direct_bt::DBTAdapter const &a, std::shared_ptr device) override { - fprintf(stderr, "****** REMOVED: %s\n", device->toString().c_str()); + void deviceConnected(direct_bt::DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { + fprintf(stderr, "****** CONNECTED: %s\n", device->toString().c_str()); + fprintf(stderr, "Status HCIAdapter:\n"); + fprintf(stderr, "%s\n", a.toString().c_str()); + } + void deviceDisconnected(direct_bt::DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { + fprintf(stderr, "****** DISCONNECTED: %s\n", device->toString().c_str()); fprintf(stderr, "Status HCIAdapter:\n"); fprintf(stderr, "%s\n", a.toString().c_str()); } + /** + void deviceRemoved(direct_bt::DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { + fprintf(stderr, "****** REMOVED: %s\n", device->toString().c_str()); + fprintf(stderr, "Status HCIAdapter:\n"); + fprintf(stderr, "%s\n", a.toString().c_str()); + } */ }; static const uuid16_t _TEMPERATURE_MEASUREMENT(GattCharacteristicType::TEMPERATURE_MEASUREMENT); @@ -144,7 +155,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Adapter: device %s, address %s\n", adapter.getName().c_str(), adapter.getAddressString().c_str()); - adapter.setDeviceDiscoveryListener(std::shared_ptr(new DeviceDiscoveryListener())); + adapter.setDeviceStatusListener(std::shared_ptr(new DeviceStatusListener())); const int64_t t0 = direct_bt::getCurrentMilliseconds(); diff --git a/examples/java/ScannerTinyB01.java b/examples/java/ScannerTinyB01.java index b76d0fe9..4f64f6d2 100644 --- a/examples/java/ScannerTinyB01.java +++ b/examples/java/ScannerTinyB01.java @@ -29,7 +29,7 @@ import java.util.List; import org.tinyb.BluetoothAdapter; import org.tinyb.BluetoothDevice; -import org.tinyb.BluetoothDeviceDiscoveryListener; +import org.tinyb.BluetoothDeviceStatusListener; import org.tinyb.BluetoothException; import org.tinyb.BluetoothFactory; import org.tinyb.BluetoothGattCharacteristic; @@ -92,9 +92,9 @@ public class ScannerTinyB01 { final BluetoothAdapter adapter = manager.getDefaultAdapter(); final BluetoothDevice[] matchingDiscoveredDeviceBucket = { null }; - final BluetoothDeviceDiscoveryListener deviceDiscListener = new BluetoothDeviceDiscoveryListener() { + final BluetoothDeviceStatusListener deviceDiscListener = new BluetoothDeviceStatusListener() { @Override - public void deviceAdded(final BluetoothAdapter adapter, final BluetoothDevice device) { + public void deviceFound(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp) { final boolean matches = device.getAddress().equals(mac); System.err.println("****** ADDED__: "+device.toString()+" - match "+matches); System.err.println("Status HCIAdapter:"); @@ -109,7 +109,7 @@ public class ScannerTinyB01 { } @Override - public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device) { + public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp) { final boolean matches = device.getAddress().equals(mac); System.err.println("****** UPDATED: "+device.toString()+" - match "+matches); System.err.println("Status HCIAdapter:"); @@ -117,15 +117,23 @@ public class ScannerTinyB01 { } @Override - public void deviceRemoved(final BluetoothAdapter adapter, final BluetoothDevice device) { + public void deviceConnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp) { final boolean matches = device.getAddress().equals(mac); - System.err.println("****** REMOVED: "+device.toString()+" - match "+matches); + System.err.println("****** CONNECTED: "+device.toString()+" - match "+matches); + System.err.println("Status HCIAdapter:"); + System.err.println(adapter.toString()); + } + + @Override + public void deviceDisconnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp) { + final boolean matches = device.getAddress().equals(mac); + System.err.println("****** DISCONNECTED: "+device.toString()+" - match "+matches); System.err.println("Status HCIAdapter:"); System.err.println(adapter.toString()); } }; adapter.removeDevices(); - adapter.setDeviceDiscoveryListener(deviceDiscListener); + adapter.setDeviceStatusListener(deviceDiscListener); do { final long t0 = BluetoothUtils.getCurrentMilliseconds(); diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java index 33613c62..5b2087bc 100644 --- a/java/direct_bt/tinyb/DBTAdapter.java +++ b/java/direct_bt/tinyb/DBTAdapter.java @@ -38,28 +38,25 @@ import org.tinyb.BluetoothException; import org.tinyb.BluetoothManager; import org.tinyb.BluetoothNotification; import org.tinyb.BluetoothType; -import org.tinyb.BluetoothDeviceDiscoveryListener; +import org.tinyb.BluetoothDeviceStatusListener; import org.tinyb.TransportType; public class DBTAdapter extends DBTObject implements BluetoothAdapter { private final String address; private final String name; - private final DiscoveryThread discoveryThread; /* pp */ DBTAdapter(final long nativeInstance, final String address, final String name) { super(nativeInstance, compHash(address, name)); this.address = address; this.name = name; - this.discoveryThread = new DiscoveryThread(); - this.discoveryThread.start(null); - initImpl(this.discoveryThread.deviceDiscoveryListener); + initImpl(this.deviceDiscoveryListener); } @Override public synchronized void close() { - discoveryThread.stop(); + stopDiscovery(); super.close(); } @@ -107,11 +104,11 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter public String toString() { final StringBuilder out = new StringBuilder(); out.append("Adapter[").append(getAddress()).append(", '").append(getName()).append("', id=").append("]"); - synchronized(discoveryThread.discoveredDevicesLock) { - final int count = discoveryThread.discoveredDevices.size(); + synchronized(discoveredDevicesLock) { + final int count = discoveredDevices.size(); if( count > 0 ) { out.append("\n"); - for(final Iterator iter=discoveryThread.discoveredDevices.iterator(); iter.hasNext(); ) { + for(final Iterator iter=discoveredDevices.iterator(); iter.hasNext(); ) { final BluetoothDevice device = iter.next(); out.append(" ").append(device.toString()).append("\n"); } @@ -190,7 +187,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter /* internal */ - private native void initImpl(final BluetoothDeviceDiscoveryListener l); + private native void initImpl(final BluetoothDeviceStatusListener l); @Override protected native void deleteImpl(); @@ -199,24 +196,36 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter @Override public boolean startDiscovery() throws BluetoothException { - return discoveryThread.doDiscovery(true); + final boolean res = startDiscoveryImpl(); + isDiscovering = res; + synchronized( stateLock ) { + discoveringNotificationCB.run(res); + stateLock.notifyAll(); + } + return res; } private native boolean startDiscoveryImpl() throws BluetoothException; @Override public boolean stopDiscovery() throws BluetoothException { - return discoveryThread.doDiscovery(false); + isDiscovering = false; + final boolean res = stopDiscoveryImpl(); + synchronized( stateLock ) { + discoveringNotificationCB.run(false); + stateLock.notifyAll(); + } + return res; } private native boolean stopDiscoveryImpl() throws BluetoothException; @Override public List getDevices() { - return discoveryThread.getDiscoveredDevices(); + return getDiscoveredDevices(); } @Override public int removeDevices() throws BluetoothException { - final int cj = discoveryThread.removeDiscoveredDevices(); + final int cj = removeDiscoveredDevices(); final int cn = removeDevicesImpl(); if( cj != cn ) { throw new InternalError("Inconsistent discovered device count: Native "+cn+", callback "+cj); @@ -226,21 +235,24 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private native int removeDevicesImpl() throws BluetoothException; @Override - public boolean getDiscovering() { return discoveryThread.running && discoveryThread.doDiscovery; } + public boolean getDiscovering() { return isDiscovering; } @Override - public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener l) { - discoveryThread.setDeviceDiscoveryListener(l); + public void setDeviceStatusListener(final BluetoothDeviceStatusListener l) { + synchronized( stateLock ) { + userDeviceStatusListener = l; + stateLock.notifyAll(); + } } @Override public void enableDiscoveringNotifications(final BluetoothNotification callback) { - discoveryThread.setDiscoveringNotificationCallback(callback); + setDiscoveringNotificationCallback(callback); } @Override public void disableDiscoveringNotifications() { - discoveryThread.setDiscoveringNotificationCallback(null); + setDiscoveringNotificationCallback(null); } @Override @@ -258,160 +270,74 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter private native void setDiscoveryFilter(List uuids, int rssi, int pathloss, int transportType); - private native int discoverAnyDeviceImpl(final int timeoutMS) throws BluetoothException; // std::vector> discoveredDevices = adapter.getDiscoveredDevices(); private native List getDiscoveredDevicesImpl(); - private class DiscoveryThread implements Runnable { - private int instanceID=-1; - - private volatile boolean running = false; - private volatile boolean doDiscovery = false; - private final Object stateLock = new Object(); - private volatile BluetoothDeviceDiscoveryListener userDeviceDiscoveryListener = null; - private volatile BluetoothNotification discoveringNotificationCB = null; - private List discoveredDevices = new ArrayList(); - private final Object discoveredDevicesLock = new Object(); - - private final BluetoothDeviceDiscoveryListener deviceDiscoveryListener = new BluetoothDeviceDiscoveryListener() { - @Override - public void deviceAdded(final BluetoothAdapter a, final BluetoothDevice device) { - final BluetoothDeviceDiscoveryListener l = userDeviceDiscoveryListener; - System.err.println("DBTAdapter.DeviceDiscoveryListener.added: "+device+" on "+a); - synchronized(discoveredDevicesLock) { - discoveredDevices.add(device); - } - if( null != l ) { - l.deviceAdded(a, device); - } - } + //////////////////////////////////// - @Override - public void deviceUpdated(final BluetoothAdapter a, final BluetoothDevice device) { - System.err.println("DBTAdapter.DeviceDiscoveryListener.updated: "+device+" on "+a); - // nop on discoveredDevices - userDeviceDiscoveryListener.deviceUpdated(a, device); - } + private final Object stateLock = new Object(); + private volatile BluetoothDeviceStatusListener userDeviceStatusListener = null; + private volatile BluetoothNotification discoveringNotificationCB = null; + private List discoveredDevices = new ArrayList(); + private final Object discoveredDevicesLock = new Object(); + private volatile boolean isDiscovering = false; - @Override - public void deviceRemoved(final BluetoothAdapter a, final BluetoothDevice device) { - final BluetoothDeviceDiscoveryListener l = userDeviceDiscoveryListener; - System.err.println("DBTAdapter.DeviceDiscoveryListener.removed: "+device+" on "+a); - synchronized(discoveredDevicesLock) { - discoveredDevices.remove(device); - } - if( null != l ) { - l.deviceRemoved(a, device); - } + private final BluetoothDeviceStatusListener deviceDiscoveryListener = new BluetoothDeviceStatusListener() { + @Override + public void deviceFound(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { + final BluetoothDeviceStatusListener l = userDeviceStatusListener; + System.err.println("DBTAdapter.DeviceStatusListener.added: "+device+" on "+a); + synchronized(discoveredDevicesLock) { + discoveredDevices.add(device); } - }; - - public void start(final ThreadGroup tg) { - synchronized( stateLock ) { - if ( !running ) { - instanceID = globThreadID.addAndGet(1); - final Thread t = new Thread(tg, this, "DBTAdapter-"+instanceID); // Thread name aligned w/ 'Thread-#' - t.setDaemon(true); - t.start(); - while( !running ) { - try { - stateLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - } + if( null != l ) { + l.deviceFound(a, device, timestamp); } } - public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener l) { - synchronized( stateLock ) { - userDeviceDiscoveryListener = l; - stateLock.notifyAll(); - } + + @Override + public void deviceUpdated(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { + System.err.println("DBTAdapter.DeviceStatusListener.updated: "+device+" on "+a); + // nop on discoveredDevices + userDeviceStatusListener.deviceUpdated(a, device, timestamp); } - public void setDiscoveringNotificationCallback(final BluetoothNotification cb) { - synchronized( stateLock ) { - discoveringNotificationCB = cb; - stateLock.notifyAll(); + + @Override + public void deviceConnected(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { + final BluetoothDeviceStatusListener l = userDeviceStatusListener; + System.err.println("DBTAdapter.DeviceStatusListener.connected: "+device+" on "+a); + if( null != l ) { + l.deviceConnected(a, device, timestamp); } } - public List getDiscoveredDevices() { + @Override + public void deviceDisconnected(final BluetoothAdapter a, final BluetoothDevice device, final long timestamp) { + final BluetoothDeviceStatusListener l = userDeviceStatusListener; + System.err.println("DBTAdapter.DeviceStatusListener.disconnected: "+device+" on "+a); synchronized(discoveredDevicesLock) { - return new ArrayList(discoveredDevices); + discoveredDevices.remove(device); } - } - public int removeDiscoveredDevices() { - synchronized(discoveredDevicesLock) { - final int n = discoveredDevices.size(); - discoveredDevices = new ArrayList(); - return n; + if( null != l ) { + l.deviceDisconnected(a, device, timestamp); } } - public boolean doDiscovery(final boolean v) { - synchronized( stateLock ) { - if( v == doDiscovery ) { - return v; - } - final BluetoothNotification cb = discoveringNotificationCB; - final boolean enable; - if( v ) { - enable = startDiscoveryImpl(); - } else { - enable = false; - } - doDiscovery = enable; - if( null != cb ) { - cb.run(enable); - } - if( !v ) { - stopDiscoveryImpl(); - } - stateLock.notifyAll(); - return enable; - } + }; + public void setDiscoveringNotificationCallback(final BluetoothNotification cb) { + synchronized( stateLock ) { + discoveringNotificationCB = cb; + stateLock.notifyAll(); } - public void stop() { - synchronized( stateLock ) { - running = false; - doDiscovery = false; - stopDiscoveryImpl(); - stateLock.notifyAll(); - } + } + public List getDiscoveredDevices() { + synchronized(discoveredDevicesLock) { + return new ArrayList(discoveredDevices); } - - @Override - public void run() { - synchronized( stateLock ) { - running = true; - stateLock.notifyAll(); - } - while (running) { - synchronized( stateLock ) { - while( running && !doDiscovery ) { - try { - stateLock.wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - } - if( !running ) { - break; // end loop and thread - } - - try { - if( doDiscovery ) { - // will trigger all discovery callbacks! - discoverAnyDeviceImpl(discoverTimeoutMS); - } - } catch (final Exception e) { - System.err.println(e.toString()); - e.printStackTrace(); - doDiscovery = false; - } - } // loop - - instanceID = -1; + } + public int removeDiscoveredDevices() { + synchronized(discoveredDevicesLock) { + final int n = discoveredDevices.size(); + discoveredDevices = new ArrayList(); + return n; } } private static AtomicInteger globThreadID = new AtomicInteger(0); diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx index 26a519ad..2f9b6847 100644 --- a/java/jni/direct_bt/DBTAdapter.cxx +++ b/java/jni/direct_bt/DBTAdapter.cxx @@ -37,17 +37,19 @@ using namespace direct_bt; static const std::string _deviceClazzCtorArgs("(JLdirect_bt/tinyb/DBTAdapter;Ljava/lang/String;Ljava/lang/String;J)V"); -static const std::string _deviceDiscoveryMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/BluetoothDevice;)V"); +static const std::string _deviceStatusMethodArgs("(Lorg/tinyb/BluetoothAdapter;Lorg/tinyb/BluetoothDevice;J)V"); -class DeviceDiscoveryCallbackListener : public DBTDeviceDiscoveryListener { +class DeviceStatusCallbackListener : public DBTDeviceStatusListener { public: /** package org.tinyb; - public interface BluetoothDeviceDiscoveryListener { - public void deviceAdded(final BluetoothAdapter adapter, final BluetoothDevice device); - public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device); - public void deviceRemoved(final BluetoothAdapter adapter, final BluetoothDevice device); + public interface BluetoothDeviceStatusListener { + public void deviceFound(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + public void deviceConnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + public void deviceDisconnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + // public void deviceRemoved(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); }; */ std::shared_ptr adapterObjRef; @@ -56,11 +58,13 @@ class DeviceDiscoveryCallbackListener : public DBTDeviceDiscoveryListener { jfieldID deviceClazzTSUpdateField; std::unique_ptr listenerObjRef; std::unique_ptr listenerClazzRef; - jmethodID mDeviceAdded = nullptr; + jmethodID mDeviceFound = nullptr; jmethodID mDeviceUpdated = nullptr; - jmethodID mDeviceRemoved = nullptr; + jmethodID mDeviceConnected = nullptr; + jmethodID mDeviceDisconnected = nullptr; + // jmethodID mDeviceRemoved = nullptr; - DeviceDiscoveryCallbackListener(JNIEnv *env, DBTAdapter *adapter, jobject deviceDiscoveryListener) { + DeviceStatusCallbackListener(JNIEnv *env, DBTAdapter *adapter, jobject deviceDiscoveryListener) { adapterObjRef = adapter->getJavaObject(); JavaGlobalObj::check(adapterObjRef, E_FILE_LINE); { @@ -93,28 +97,33 @@ class DeviceDiscoveryCallbackListener : public DBTDeviceDiscoveryListener { listenerClazzRef = std::unique_ptr(new JNIGlobalRef(listenerClazz)); env->DeleteLocalRef(listenerClazz); } - mDeviceAdded = search_method(env, listenerClazzRef->getClass(), "deviceAdded", _deviceDiscoveryMethodArgs.c_str(), false); + mDeviceFound = search_method(env, listenerClazzRef->getClass(), "deviceFound", _deviceStatusMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); - if( nullptr == mDeviceAdded ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceAdded"+_deviceDiscoveryMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + if( nullptr == mDeviceFound ) { + throw InternalError("BluetoothDeviceDiscoveryListener has no deviceFound"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); } - mDeviceUpdated = search_method(env, listenerClazzRef->getClass(), "deviceUpdated", _deviceDiscoveryMethodArgs.c_str(), false); + mDeviceUpdated = search_method(env, listenerClazzRef->getClass(), "deviceUpdated", _deviceStatusMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); if( nullptr == mDeviceUpdated ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceUpdated"+_deviceDiscoveryMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + throw InternalError("BluetoothDeviceDiscoveryListener has no deviceUpdated"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); } - mDeviceRemoved = search_method(env, listenerClazzRef->getClass(), "deviceRemoved", _deviceDiscoveryMethodArgs.c_str(), false); + mDeviceConnected = search_method(env, listenerClazzRef->getClass(), "deviceConnected", _deviceStatusMethodArgs.c_str(), false); java_exception_check_and_throw(env, E_FILE_LINE); - if( nullptr == mDeviceRemoved ) { - throw InternalError("BluetoothDeviceDiscoveryListener has no deviceRemoved"+_deviceDiscoveryMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + if( nullptr == mDeviceConnected ) { + throw InternalError("BluetoothDeviceDiscoveryListener has no deviceConnected"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); + } + mDeviceDisconnected = search_method(env, listenerClazzRef->getClass(), "deviceDisconnected", _deviceStatusMethodArgs.c_str(), false); + java_exception_check_and_throw(env, E_FILE_LINE); + if( nullptr == mDeviceDisconnected ) { + throw InternalError("BluetoothDeviceDiscoveryListener has no deviceDisconnected"+_deviceStatusMethodArgs+" method, for "+adapter->toString(), E_FILE_LINE); } } - void deviceAdded(DBTAdapter const &a, std::shared_ptr device) override { + void deviceFound(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { JNIEnv *env = *jni_env; try { #ifdef VERBOSE_ON - fprintf(stderr, "****** Native Adapter Device ADDED__: %s\n", device->toString().c_str()); + fprintf(stderr, "****** Native Adapter Device FOUND__: %s\n", device->toString().c_str()); fprintf(stderr, "Status DBTAdapter:\n"); fprintf(stderr, "%s\n", a.toString().c_str()); #endif @@ -125,19 +134,20 @@ class DeviceDiscoveryCallbackListener : public DBTDeviceDiscoveryListener { const jstring name = from_string_to_jstring(env, device->getName()); if( java_exception_check(env, E_FILE_LINE) ) { return; } jobject jDevice = env->NewObject(deviceClazzRef->getClass(), deviceClazzCtor, - (jlong)device.get(), adapterObjRef, addr, name, (jlong)device->ts_creation); + (jlong)device.get(), adapterObjRef, addr, name, (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } JNIGlobalRef::check(jDevice, E_FILE_LINE); std::shared_ptr jDeviceRef = device->getJavaObject(); JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); - env->CallVoidMethod(listenerObjRef->getObject(), mDeviceAdded, JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef)); + env->CallVoidMethod(listenerObjRef->getObject(), mDeviceFound, + JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } } catch(...) { rethrow_and_raise_java_exception(env); } } - void deviceUpdated(DBTAdapter const &a, std::shared_ptr device) override { + void deviceUpdated(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { JNIEnv *env = *jni_env; try { #ifdef VERBOSE_ON @@ -148,28 +158,50 @@ class DeviceDiscoveryCallbackListener : public DBTDeviceDiscoveryListener { (void)a; std::shared_ptr jDeviceRef = device->getJavaObject(); JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); - env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)device->getUpdateTimestamp()); + env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)timestamp); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + env->CallVoidMethod(listenerObjRef->getObject(), mDeviceUpdated, + JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp); + if( java_exception_check(env, E_FILE_LINE) ) { return; } + } catch(...) { + rethrow_and_raise_java_exception(env); + } + } + void deviceConnected(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { + JNIEnv *env = *jni_env; + try { + #ifdef VERBOSE_ON + fprintf(stderr, "****** DBTAdapter Device CONNECTED: %s\n", device->toString().c_str()); + fprintf(stderr, "Status DBTAdapter:\n"); + fprintf(stderr, "%s\n", a.toString().c_str()); + #endif + (void)a; + std::shared_ptr jDeviceRef = device->getJavaObject(); + JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); + env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } - env->CallVoidMethod(listenerObjRef->getObject(), mDeviceUpdated, JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef)); + env->CallVoidMethod(listenerObjRef->getObject(), mDeviceConnected, + JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } } catch(...) { rethrow_and_raise_java_exception(env); } } - void deviceRemoved(DBTAdapter const &a, std::shared_ptr device) override { + void deviceDisconnected(DBTAdapter const &a, std::shared_ptr device, const uint64_t timestamp) override { JNIEnv *env = *jni_env; try { #ifdef VERBOSE_ON - fprintf(stderr, "****** DBTAdapter Device REMOVED: %s\n", device->toString().c_str()); + fprintf(stderr, "****** DBTAdapter Device DISCONNECTED: %s\n", device->toString().c_str()); fprintf(stderr, "Status DBTAdapter:\n"); fprintf(stderr, "%s\n", a.toString().c_str()); #endif (void)a; std::shared_ptr jDeviceRef = device->getJavaObject(); JavaGlobalObj::check(jDeviceRef, E_FILE_LINE); - env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)device->getUpdateTimestamp()); + env->SetLongField(JavaGlobalObj::GetObject(jDeviceRef), deviceClazzTSUpdateField, (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } - env->CallVoidMethod(listenerObjRef->getObject(), mDeviceRemoved, JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef)); + env->CallVoidMethod(listenerObjRef->getObject(), mDeviceDisconnected, + JavaGlobalObj::GetObject(adapterObjRef), JavaGlobalObj::GetObject(jDeviceRef), (jlong)timestamp); if( java_exception_check(env, E_FILE_LINE) ) { return; } } catch(...) { rethrow_and_raise_java_exception(env); @@ -185,8 +217,8 @@ void Java_direct_1bt_tinyb_DBTAdapter_initImpl(JNIEnv *env, jobject obj, jobject JavaGlobalObj::check(adapter->getJavaObject(), E_FILE_LINE); // set our callback discovery listener. - DeviceDiscoveryCallbackListener *l = new DeviceDiscoveryCallbackListener(env, adapter, deviceDiscoveryListener); - adapter->setDeviceDiscoveryListener(std::shared_ptr(l)); + DeviceStatusCallbackListener *l = new DeviceStatusCallbackListener(env, adapter, deviceDiscoveryListener); + adapter->setDeviceStatusListener(std::shared_ptr(l)); } catch(...) { rethrow_and_raise_java_exception(env); } @@ -197,7 +229,7 @@ void Java_direct_1bt_tinyb_DBTAdapter_deleteImpl(JNIEnv *env, jobject obj) try { DBTAdapter *adapter = getInstance(env, obj); DBG_PRINT("Java_direct_1bt_tinyb_DBTAdapter_deleteImpl %s", adapter->toString().c_str()); - adapter->setDeviceDiscoveryListener(nullptr); + adapter->setDeviceStatusListener(nullptr); delete adapter; } catch(...) { rethrow_and_raise_java_exception(env); diff --git a/java/org/tinyb/BluetoothAdapter.java b/java/org/tinyb/BluetoothAdapter.java index 2b55cf75..4a989500 100644 --- a/java/org/tinyb/BluetoothAdapter.java +++ b/java/org/tinyb/BluetoothAdapter.java @@ -242,10 +242,10 @@ public interface BluetoothAdapter extends BluetoothObject public boolean getDiscovering(); /** - * Sets the {@link BluetoothDeviceDiscoveryListener} for the respective device discovery events. - * @param listener A {@link BluetoothDeviceDiscoveryListener} instance, or {@code null} to disable notifications. + * Sets the {@link BluetoothDeviceStatusListener} for the respective device status events. + * @param listener A {@link BluetoothDeviceStatusListener} instance, or {@code null} to disable notifications. */ - public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener listener); + public void setDeviceStatusListener(final BluetoothDeviceStatusListener listener); /** * Enables notifications for the discovering property and calls run function of the diff --git a/java/org/tinyb/BluetoothDeviceDiscoveryListener.java b/java/org/tinyb/BluetoothDeviceDiscoveryListener.java deleted file mode 100644 index 737f47b9..00000000 --- a/java/org/tinyb/BluetoothDeviceDiscoveryListener.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Author: Sven Gothel - * Copyright (c) 2020 Gothel Software e.K. - * Copyright (c) 2020 ZAFENA AB - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -package org.tinyb; - -/** - * {@link BluetoothDevice} listener for the respective {@link BluetoothDevice} discovery events: Added, updated and removed. - *

- * A listener instance may be attached to a {@link BluetoothAdapter} via - * {@link BluetoothAdapter#setDeviceDiscoveryListener(BluetoothDeviceDiscoveryListener)}. - *

- */ -public interface BluetoothDeviceDiscoveryListener { - /** A {@link BluetoothDevice} has been newly discovered. */ - public void deviceAdded(final BluetoothAdapter adapter, final BluetoothDevice device); - /** An already discovered {@link BluetoothDevice} has been updated. */ - public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device); - /** An already discovered {@link BluetoothDevice} has been removed or lost. */ - public void deviceRemoved(final BluetoothAdapter adapter, final BluetoothDevice device); -}; diff --git a/java/org/tinyb/BluetoothDeviceStatusListener.java b/java/org/tinyb/BluetoothDeviceStatusListener.java new file mode 100644 index 00000000..184392ea --- /dev/null +++ b/java/org/tinyb/BluetoothDeviceStatusListener.java @@ -0,0 +1,44 @@ +/** + * Author: Sven Gothel + * Copyright (c) 2020 Gothel Software e.K. + * Copyright (c) 2020 ZAFENA AB + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.tinyb; + +/** + * {@link BluetoothDevice} listener for the respective {@link BluetoothDevice} discovery events: Added, updated and removed. + *

+ * A listener instance may be attached to a {@link BluetoothAdapter} via + * {@link BluetoothAdapter#setDeviceStatusListener(BluetoothDeviceDiscoveryListener)}. + *

+ */ +public interface BluetoothDeviceStatusListener { + /** A {@link BluetoothDevice} has been newly discovered. */ + public void deviceFound(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + /** An already discovered {@link BluetoothDevice} has been updated. */ + public void deviceUpdated(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + /** {@link BluetoothDevice} has been connected. */ + public void deviceConnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); + /** {@link BluetoothDevice} has been disconnected. */ + public void deviceDisconnected(final BluetoothAdapter adapter, final BluetoothDevice device, final long timestamp); +}; diff --git a/java/tinyb/dbus/DBusAdapter.java b/java/tinyb/dbus/DBusAdapter.java index 973d3e8d..b49e9fc7 100644 --- a/java/tinyb/dbus/DBusAdapter.java +++ b/java/tinyb/dbus/DBusAdapter.java @@ -35,7 +35,7 @@ import java.util.UUID; import org.tinyb.BluetoothAdapter; import org.tinyb.BluetoothDevice; -import org.tinyb.BluetoothDeviceDiscoveryListener; +import org.tinyb.BluetoothDeviceStatusListener; import org.tinyb.BluetoothException; import org.tinyb.BluetoothManager; import org.tinyb.BluetoothNotification; @@ -149,7 +149,7 @@ public class DBusAdapter extends DBusObject implements BluetoothAdapter public native boolean getDiscovering(); @Override - public void setDeviceDiscoveryListener(final BluetoothDeviceDiscoveryListener l) { + public void setDeviceStatusListener(final BluetoothDeviceStatusListener l) { throw new UnsupportedOperationException(); // FIXME } diff --git a/src/direct_bt/BTTypes.cpp b/src/direct_bt/BTTypes.cpp index 63f63fb8..c64c70ca 100644 --- a/src/direct_bt/BTTypes.cpp +++ b/src/direct_bt/BTTypes.cpp @@ -394,11 +394,12 @@ std::vector> EInfoReport::read_ad_reports(uint8_t c const int segment_count = 6; int read_segments = 0; int i; + const uint64_t timestamp = getCurrentMilliseconds(); for(i = 0; i < num_reports && i_octets < limes; i++) { ad_reports.push_back(std::shared_ptr(new EInfoReport())); ad_reports[i]->setSource(Source::AD); - ad_reports[i]->setTimestamp(getCurrentMilliseconds()); + ad_reports[i]->setTimestamp(timestamp); ad_reports[i]->setEvtType(*i_octets++); read_segments++; } diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp index e22263f6..d9b24a4f 100644 --- a/src/direct_bt/DBTAdapter.cpp +++ b/src/direct_bt/DBTAdapter.cpp @@ -56,32 +56,33 @@ using namespace direct_bt; std::atomic_int HCISession::name_counter(0); -void HCISession::connectedLE(std::shared_ptr & device) { - connectedLEDevices.push_back(device); +void HCISession::connected(std::shared_ptr & device) { + connectedDevices.push_back(device); } -void HCISession::disconnectedLE(std::shared_ptr & device) { - for (auto it = connectedLEDevices.begin(); it != connectedLEDevices.end(); ) { +void HCISession::disconnected(std::shared_ptr & device) { + for (auto it = connectedDevices.begin(); it != connectedDevices.end(); ) { if ( *it == device ) { - it = connectedLEDevices.erase(it); + it = connectedDevices.erase(it); } else { ++it; } } } -int HCISession::disconnectAllLEDevices(const uint8_t reason) { +int HCISession::disconnectAllDevices(const uint8_t reason) { int count = 0; - std::vector> devices(getConnectedLEDevices()); // copy! - for (auto it = connectedLEDevices.begin(); it != connectedLEDevices.end(); ++it) { + std::vector> devices(connectedDevices); // copy! + for (auto it = devices.begin(); it != devices.end(); ++it) { (*it)->le_disconnect(reason); // will erase device from list via disconnectedLE above ++count; } return count; } -std::shared_ptr HCISession::findConnectedLEDevice (EUI48 const & mac) const { - for (auto it = connectedLEDevices.begin(); it != connectedLEDevices.end(); ) { +std::shared_ptr HCISession::findConnectedDevice (EUI48 const & mac) const { + std::vector> devices(connectedDevices); // copy! + for (auto it = devices.begin(); it != devices.end(); ) { if ( mac == (*it)->getAddress() ) { return *it; } else { @@ -101,7 +102,7 @@ bool HCISession::close() DBG_PRINT("HCISession::close: Not open"); return false; } - disconnectAllLEDevices(); + disconnectAllDevices(); adapter->sessionClosing(); hciComm.close(); DBG_PRINT("HCISession::close: XXX"); @@ -115,7 +116,7 @@ void HCISession::shutdown() { if( !hciComm.isOpen() ) { DBG_PRINT("HCISession::shutdown: Not open"); } else { - disconnectAllLEDevices(); + disconnectAllDevices(); hciComm.close(); } @@ -135,7 +136,7 @@ HCISession::~HCISession() { std::string HCISession::toString() const { return "HCISession[name "+std::to_string(name)+ ", open "+std::to_string(isOpen())+ - ", "+std::to_string(this->connectedLEDevices.size())+" connected LE devices]"; + ", "+std::to_string(this->connectedDevices.size())+" connected LE devices]"; } // ************************************************* @@ -149,6 +150,8 @@ bool DBTAdapter::validateDevInfo() { adapterInfo = mgmt.getAdapter(dev_id); mgmt.addMgmtEventCallback(MgmtEvent::Opcode::DISCOVERING, bindClassFunction(this, &DBTAdapter::mgmtEvDeviceDiscoveringCB)); + mgmt.addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_CONNECTED, bindClassFunction(this, &DBTAdapter::mgmtEvDeviceConnectedCB)); + mgmt.addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_DISCONNECTED, bindClassFunction(this, &DBTAdapter::mgmtEvDeviceDisconnectedCB)); return true; } @@ -190,7 +193,7 @@ DBTAdapter::~DBTAdapter() { ERR_PRINT("DBTAdapter removeMgmtEventCallback(DISCOVERING) not 1 but %d", count); } } - deviceDiscoveryListener = nullptr; + deviceStatusListener = nullptr; scannedDevices.clear(); discoveredDevices.clear(); @@ -218,14 +221,14 @@ std::shared_ptr DBTAdapter::open() return session; } -std::shared_ptr DBTAdapter::setDeviceDiscoveryListener(std::shared_ptr l) +std::shared_ptr DBTAdapter::setDeviceStatusListener(std::shared_ptr l) { - std::shared_ptr o = deviceDiscoveryListener; - deviceDiscoveryListener = l; + std::shared_ptr o = deviceStatusListener; + deviceStatusListener = l; return o; } -bool DBTAdapter::startDiscovery(uint8_t own_mac_type, +bool DBTAdapter::startDiscovery(HCIAddressType own_mac_type, uint16_t interval, uint16_t window) { #ifdef USE_BT_MGMT @@ -234,6 +237,7 @@ bool DBTAdapter::startDiscovery(uint8_t own_mac_type, (void)interval; (void)window; + keepDiscoveringAlive = true; currentScanType = mgmt.startDiscovery(dev_id); return ScanType::SCAN_TYPE_NONE != currentScanType; #else @@ -252,6 +256,7 @@ bool DBTAdapter::startDiscovery(uint8_t own_mac_type, void DBTAdapter::stopDiscovery() { #ifdef USE_BT_MGMT DBG_PRINT("DBTAdapter::stopDiscovery: ..."); + keepDiscoveringAlive = false; if( mgmt.stopDiscovery(dev_id, currentScanType) ) { currentScanType = ScanType::SCAN_TYPE_NONE; } @@ -486,13 +491,13 @@ int DBTAdapter::discoverDevicesHCI(const int waitForDeviceCount, if( matches ) { if( addDiscoveredDevice(dev) ) { // new matching - if( nullptr != deviceDiscoveryListener ) { - deviceDiscoveryListener->deviceAdded(*this, dev); + if( nullptr != deviceStatusListener ) { + deviceStatusListener->deviceFound(*this, dev, ad_report->getTimestamp()); } } else { // update - if( nullptr != deviceDiscoveryListener ) { - deviceDiscoveryListener->deviceUpdated(*this, dev); + if( nullptr != deviceStatusListener ) { + deviceStatusListener->deviceUpdated(*this, dev, ad_report->getTimestamp()); } } } @@ -515,10 +520,12 @@ bool DBTAdapter::mgmtEvDeviceDiscoveringCB(std::shared_ptr e) { keepDiscoveringAlive, e->toString().c_str()); const MgmtEvtDiscovering &event = *static_cast(e.get()); if( keepDiscoveringAlive && !event.getEnabled() ) { - startDiscovery(); + std::thread bg(&DBTAdapter::startDiscoveryBackground, this); + bg.detach(); } return true; } +void DBTAdapter::startDiscoveryBackground() { startDiscovery(); } bool DBTAdapter::mgmtEvDeviceFoundCB(std::shared_ptr e) { DBG_PRINT("DBTAdapter::EventCB:DeviceFound: %s", e->toString().c_str()); @@ -531,6 +538,43 @@ bool DBTAdapter::mgmtEvDeviceFoundCB(std::shared_ptr e) { return true; } +bool DBTAdapter::mgmtEvDeviceConnectedCB(std::shared_ptr e) { + const MgmtEvtDeviceConnected &event = *static_cast(e.get()); + EInfoReport ad_report; + { + ad_report.setSource(EInfoReport::Source::EIR); + ad_report.setTimestamp(event.getTimestamp()); + ad_report.setAddressType(event.getAddressType()); + ad_report.setAddress( event.getAddress() ); + ad_report.read_data(event.getData(), event.getDataSize()); + } + std::shared_ptr device = session->findConnectedDevice(event.getAddress()); + if( nullptr != device ) { + DBG_PRINT("DBTAdapter::EventCB:DeviceConnected: %s,\n %s\n -> %s", + event.toString().c_str(), ad_report.toString().c_str(), device->toString().c_str()); + if( nullptr != deviceStatusListener ) { + deviceStatusListener->deviceConnected(*this, device, event.getTimestamp()); + } + } else { + DBG_PRINT("DBTAdapter::EventCB:DeviceConnected: %s,\n %s\n -> Device not tracked", + event.toString().c_str(), ad_report.toString().c_str()); + } + (void)ad_report; + return true; +} +bool DBTAdapter::mgmtEvDeviceDisconnectedCB(std::shared_ptr e) { + const MgmtEvtDeviceDisconnected &event = *static_cast(e.get()); + std::shared_ptr device = session->findConnectedDevice(event.getAddress()); + if( nullptr != device ) { + DBG_PRINT("DBTAdapter::EventCB:DeviceDisconnected: %s\n -> %s", event.toString().c_str(), device->toString().c_str()); + if( nullptr != deviceStatusListener ) { + deviceStatusListener->deviceDisconnected(*this, device, event.getTimestamp()); + } + } else { + DBG_PRINT("DBTAdapter::EventCB:DeviceDisconnected: %s\n -> Device not tracked", event.toString().c_str()); + } + return true; +} int DBTAdapter::discoverDevicesMgmt(const int waitForDeviceCount, const EUI48 &waitForDevice, const int timeoutMS, @@ -546,7 +590,7 @@ int DBTAdapter::discoverDevicesMgmt(const int waitForDeviceCount, int matchedDeviceCount = 0, loop=0; while ( !done && ( ( t1 = getCurrentMilliseconds() ) - t0 ) < timeoutMS ) { - std::shared_ptr ad_report = std::shared_ptr(new EInfoReport()); + EInfoReport ad_report; { std::shared_ptr deviceEvent = nullptr; // holding the resource const MgmtEvtDeviceFound * deviceFoundEvent = nullptr; // convenient target type access @@ -562,17 +606,17 @@ int DBTAdapter::discoverDevicesMgmt(const int waitForDeviceCount, } loop++; - ad_report->setSource(EInfoReport::Source::EIR); - ad_report->setTimestamp(getCurrentMilliseconds()); - // ad_report->setEvtType(0); ?? - ad_report->setAddressType(deviceFoundEvent->getAddressType()); - ad_report->setAddress( deviceFoundEvent->getAddress() ); - ad_report->setRSSI( deviceFoundEvent->getRSSI() ); - ad_report->read_data(deviceFoundEvent->getData(), deviceFoundEvent->getDataSize()); + ad_report.setSource(EInfoReport::Source::EIR); + ad_report.setTimestamp(deviceFoundEvent->getTimestamp()); + // ad_report.setEvtType(0); ?? + ad_report.setAddressType(deviceFoundEvent->getAddressType()); + ad_report.setAddress( deviceFoundEvent->getAddress() ); + ad_report.setRSSI( deviceFoundEvent->getRSSI() ); + ad_report.read_data(deviceFoundEvent->getData(), deviceFoundEvent->getDataSize()); } - const bool matches = ( ad_req == ( ad_req & ad_report->getDataSet() ) ) && - ( EUI48_ANY_DEVICE == waitForDevice || ad_report->getAddress() == waitForDevice ); + const bool matches = ( ad_req == ( ad_req & ad_report.getDataSet() ) ) && + ( EUI48_ANY_DEVICE == waitForDevice || ad_report.getAddress() == waitForDevice ); if( matches ) { matchedDeviceCount++; if( 0 < waitForDeviceCount && waitForDeviceCount <= matchedDeviceCount ) { @@ -582,29 +626,29 @@ int DBTAdapter::discoverDevicesMgmt(const int waitForDeviceCount, DBG_PRINT("DBTAdapter::discovery[%d]: matches %d, waitForDevice %s, ad_req %s, matchCount %d/%d, done %d", loop-1, matches, waitForDevice.toString().c_str(), EInfoReport::dataSetToString(ad_req).c_str(), matchedDeviceCount, waitForDeviceCount, done); - DBG_PRINT("DBTAdapter::discovery[%d]: %s", loop-1, ad_report->toString().c_str()); + DBG_PRINT("DBTAdapter::discovery[%d]: %s", loop-1, ad_report.toString().c_str()); - int idx = findDevice(scannedDevices, ad_report->getAddress()); + int idx = findDevice(scannedDevices, ad_report.getAddress()); std::shared_ptr dev; if( 0 > idx ) { // new device - dev = std::shared_ptr(new DBTDevice(*this, *ad_report)); + dev = std::shared_ptr(new DBTDevice(*this, ad_report)); scannedDevices.push_back(dev); } else { // existing device dev = scannedDevices.at(idx); - dev->update(*ad_report); + dev->update(ad_report); } if( matches ) { if( addDiscoveredDevice(dev) ) { // new matching - if( nullptr != deviceDiscoveryListener ) { - deviceDiscoveryListener->deviceAdded(*this, dev); + if( nullptr != deviceStatusListener ) { + deviceStatusListener->deviceFound(*this, dev, ad_report.getTimestamp()); } } else { // update - if( nullptr != deviceDiscoveryListener ) { - deviceDiscoveryListener->deviceUpdated(*this, dev); + if( nullptr != deviceStatusListener ) { + deviceStatusListener->deviceUpdated(*this, dev, ad_report.getTimestamp()); } } } diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp index d246679f..bab425ac 100644 --- a/src/direct_bt/DBTDevice.cpp +++ b/src/direct_bt/DBTDevice.cpp @@ -169,7 +169,7 @@ uint16_t DBTDevice::le_connect(HCIAddressType peer_mac_type, HCIAddressType own_ return 0; } std::shared_ptr thisDevice = getSharedInstance(); - session->connectedLE(thisDevice); + session->connected(thisDevice); return leConnHandle; } @@ -198,6 +198,6 @@ void DBTDevice::le_disconnect(const uint8_t reason) { #endif std::shared_ptr thisDevice = getSharedInstance(); - session->disconnectedLE(thisDevice); + session->disconnected(thisDevice); } diff --git a/src/direct_bt/DBTManager.cpp b/src/direct_bt/DBTManager.cpp index bbe73a8e..43008224 100644 --- a/src/direct_bt/DBTManager.cpp +++ b/src/direct_bt/DBTManager.cpp @@ -308,6 +308,8 @@ next1: addMgmtEventCallback(MgmtEvent::Opcode::CONNECT_FAILED, bindClassFunction(this, &DBTManager::mgmtEvConnectFailedCB)); addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_UNPAIRED, bindClassFunction(this, &DBTManager::mgmtEvDeviceUnpairedCB)); addMgmtEventCallback(MgmtEvent::Opcode::NEW_CONN_PARAM, bindClassFunction(this, &DBTManager::mgmtEvNewConnectionParamCB)); + addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_ADDED, bindClassFunction(this, &DBTManager::mgmtEvDeviceAddedCB)); + addMgmtEventCallback(MgmtEvent::Opcode::DEVICE_REMOVED, bindClassFunction(this, &DBTManager::mgmtEvDeviceRemovedCB)); PERF_TS_TD("DBTManager::open.ok"); return; } @@ -545,3 +547,11 @@ bool DBTManager::mgmtEvNewConnectionParamCB(std::shared_ptr e) { DBG_PRINT("DBRManager::EventCB:NewConnectionParam: %s", e->toString().c_str()); return true; } +bool DBTManager::mgmtEvDeviceAddedCB(std::shared_ptr e) { + DBG_PRINT("DBRManager::EventCB:DeviceAdded: %s", e->toString().c_str()); + return true; +} +bool DBTManager::mgmtEvDeviceRemovedCB(std::shared_ptr e) { + DBG_PRINT("DBRManager::EventCB:DeviceRemoved: %s", e->toString().c_str()); + return true; +} diff --git a/src/direct_bt/HCIComm.cpp b/src/direct_bt/HCIComm.cpp index ccb14291..9d3d3534 100644 --- a/src/direct_bt/HCIComm.cpp +++ b/src/direct_bt/HCIComm.cpp @@ -536,7 +536,7 @@ void HCIComm::le_disable_scan() { } } -bool HCIComm::le_enable_scan(const uint8_t own_type, +bool HCIComm::le_enable_scan(const HCIAddressType own_type, const uint16_t interval, const uint16_t window) { const std::lock_guard lock(mtx); // RAII-style acquire and relinquish via destructor if( 0 > _dd ) { @@ -569,8 +569,8 @@ bool HCIComm::le_enable_scan(const uint8_t own_type, } uint16_t HCIComm::le_create_conn(const EUI48 &peer_bdaddr, - const uint8_t peer_mac_type, - const uint8_t own_mac_type, + const HCIAddressType peer_mac_type, + const HCIAddressType own_mac_type, const uint16_t interval, const uint16_t window, const uint16_t min_interval, const uint16_t max_interval, const uint16_t latency, const uint16_t supervision_timeout, diff --git a/src/direct_bt/MgmtTypes.cpp b/src/direct_bt/MgmtTypes.cpp index 87d68513..96f7aa3d 100644 --- a/src/direct_bt/MgmtTypes.cpp +++ b/src/direct_bt/MgmtTypes.cpp @@ -242,8 +242,16 @@ MgmtEvent* MgmtEvent::getSpecialized(const uint8_t * buffer, int const buffer_si return new MgmtEvtDeviceFound(buffer, buffer_size); case MgmtEvent::Opcode::DEVICE_CONNECTED: return new MgmtEvtDeviceConnected(buffer, buffer_size); + case MgmtEvent::Opcode::CONNECT_FAILED: + return new MgmtEvtDeviceConnectFailed(buffer, buffer_size); case MgmtEvent::Opcode::DEVICE_DISCONNECTED: return new MgmtEvtDeviceDisconnected(buffer, buffer_size); + case MgmtEvent::Opcode::DEVICE_ADDED: + return new MgmtEvtDeviceAdded(buffer, buffer_size); + case MgmtEvent::Opcode::DEVICE_REMOVED: + return new MgmtEvtDeviceRemoved(buffer, buffer_size); + case MgmtEvent::Opcode::DEVICE_UNPAIRED: + return new MgmtEvtDeviceUnpaired(buffer, buffer_size); default: return new MgmtEvent(buffer, buffer_size); } -- cgit v1.2.3