summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-07-27 07:33:12 +0200
committerSven Gothel <[email protected]>2020-07-27 07:33:12 +0200
commit6e71e6e8fcf1a075d2b14ce5b2f18081cb436abd (patch)
tree8d047dadc1488f3a091d9df7ed58d830821c5cef
parentb7d7d08c108fb3a1d17d3542dce1f942f6bb4059 (diff)
C++/Java *Device::connect*(..), disconnect(): Return HCIStatusCode instead of just boolean, passing through potential HCI error detail
The HCIStatusCode on failed connect*/disconnect commands issued via direct_bt HCI, could help applications making a better fail-recovery decision than just having the binary result.
-rw-r--r--api/direct_bt/DBTAdapter.hpp10
-rw-r--r--api/direct_bt/DBTDevice.hpp56
-rw-r--r--examples/direct_bt_scanner00/dbt_scanner00.cpp5
-rw-r--r--examples/direct_bt_scanner01/dbt_scanner01.cpp5
-rw-r--r--examples/direct_bt_scanner10/dbt_scanner10.cpp8
-rw-r--r--examples/java/AsyncTinyB.java3
-rw-r--r--examples/java/HelloTinyB.java3
-rw-r--r--examples/java/Notification.java3
-rw-r--r--examples/java/ScannerTinyB00.java8
-rw-r--r--examples/java/ScannerTinyB01.java7
-rw-r--r--examples/java/ScannerTinyB02.java7
-rw-r--r--examples/java/ScannerTinyB10.java8
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java32
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx27
-rw-r--r--java/jni/tinyb/DBusDevice.cxx4
-rw-r--r--java/org/tinyb/BluetoothDevice.java113
-rw-r--r--java/tinyb/dbus/DBusDevice.java18
-rw-r--r--src/direct_bt/DBTDevice.cpp48
18 files changed, 224 insertions, 141 deletions
diff --git a/api/direct_bt/DBTAdapter.hpp b/api/direct_bt/DBTAdapter.hpp
index 682c0e0b..62edb663 100644
--- a/api/direct_bt/DBTAdapter.hpp
+++ b/api/direct_bt/DBTAdapter.hpp
@@ -178,12 +178,12 @@ namespace direct_bt {
friend std::shared_ptr<DBTDevice> DBTDevice::getSharedInstance() const;
friend void DBTDevice::releaseSharedInstance() const;
friend std::shared_ptr<ConnectionInfo> DBTDevice::getConnectionInfo();
- friend bool DBTDevice::disconnect(const bool sentFromManager, const bool ioErrorCause,const HCIStatusCode reason);
+ friend HCIStatusCode DBTDevice::disconnect(const bool sentFromManager, const bool ioErrorCause,const HCIStatusCode reason);
friend void DBTDevice::remove();
- friend bool DBTDevice::connectLE(uint16_t interval, uint16_t window,
- uint16_t min_interval, uint16_t max_interval,
- uint16_t latency, uint16_t supervision_timeout);
- friend bool DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offset, const uint8_t role_switch);
+ friend HCIStatusCode DBTDevice::connectLE(uint16_t interval, uint16_t window,
+ uint16_t min_interval, uint16_t max_interval,
+ uint16_t latency, uint16_t supervision_timeout);
+ friend HCIStatusCode DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offset, const uint8_t role_switch);
friend std::vector<std::shared_ptr<GATTService>> DBTDevice::getGATTServices();
bool addConnectedDevice(const std::shared_ptr<DBTDevice> & device);
diff --git a/api/direct_bt/DBTDevice.hpp b/api/direct_bt/DBTDevice.hpp
index f31af362..9ac2c6d7 100644
--- a/api/direct_bt/DBTDevice.hpp
+++ b/api/direct_bt/DBTDevice.hpp
@@ -92,8 +92,8 @@ namespace direct_bt {
void notifyDisconnected();
void notifyConnected(const uint16_t handle);
- bool disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
- const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION );
+ HCIStatusCode disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
+ const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION );
public:
const uint64_t ts_creation;
@@ -211,14 +211,16 @@ namespace direct_bt {
/**
* Establish a HCI BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM connection to this device.
* <p>
- * If this device's addressType is not BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM, 0 is being returned.
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command
* </p>
* <p>
- * Returns true if the command has been accepted, otherwise false.
+ * If this device's addressType is not BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM,
+ * HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM is being returned.
* </p>
* <p>
* The actual new connection handle will be delivered asynchronous and
- * the connection event can be caught via AdapterStatusListener::deviceConnected(..).
+ * the connection event can be caught via AdapterStatusListener::deviceConnected(..),
+ * or if failed via AdapterStatusListener::deviceDisconnected(..).
* </p>
* <p>
* The device is tracked by the managing adapter.
@@ -231,57 +233,62 @@ namespace direct_bt {
* Set window to the same value as the interval, enables continuous scanning.
* </p>
*
- * @param peer_mac_type
- * @param own_mac_type
* @param le_scan_interval in units of 0.625ms, default value 48 for 30ms, min value 4 for 2.5ms -> 0x4000 for 10.24s
* @param le_scan_window in units of 0.625ms, default value 48 for 30ms, min value 4 for 2.5ms -> 0x4000 for 10.24s. Shall be <= le_scan_interval
* @param conn_interval_min in units of 1.25ms, default value 15 for 19.75ms
* @param conn_interval_max in units of 1.25ms, default value 15 for 19.75ms
* @param conn_latency slave latency in units of connection events, default value 0
* @param supervision_timeout in units of 10ms, default value 1000 for 10000ms or 10s.
- * @return
+ * @return the HCIStatusCode result whether the command has been accepted, HCIStatusCode::SUCCESS on success.
+ * @return HCIStatusCode::SUCCESS if the command has been accepted, otherwise HCIStatusCode may disclose reason for rejection.
*/
- bool connectLE(const uint16_t le_scan_interval=48, const uint16_t le_scan_window=48,
- const uint16_t conn_interval_min=0x000F, const uint16_t conn_interval_max=0x000F,
- const uint16_t conn_latency=0x0000, const uint16_t supervision_timeout=number(HCIConstInt::LE_CONN_TIMEOUT_MS)/10);
+ HCIStatusCode connectLE(const uint16_t le_scan_interval=48, const uint16_t le_scan_window=48,
+ const uint16_t conn_interval_min=0x000F, const uint16_t conn_interval_max=0x000F,
+ const uint16_t conn_latency=0x0000, const uint16_t supervision_timeout=number(HCIConstInt::LE_CONN_TIMEOUT_MS)/10);
/**
* Establish a HCI BDADDR_BREDR connection to this device.
* <p>
- * If this device's addressType is not BDADDR_BREDR, 0 is being returned.
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.5 Create Connection command
* </p>
* <p>
- * Returns true if the command has been accepted, otherwise false.
+ * If this device's addressType is not BDADDR_BREDR,
+ * HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM is being returned.
* </p>
* <p>
* The actual new connection handle will be delivered asynchronous and
- * the connection event can be caught via AdapterStatusListener::deviceConnected(..).
+ * the connection event can be caught via AdapterStatusListener::deviceConnected(..),
+ * or if failed via AdapterStatusListener::deviceDisconnected(..).
* </p>
* <p>
* The device is tracked by the managing adapter.
* </p>
+ * @return HCIStatusCode::SUCCESS if the command has been accepted, otherwise HCIStatusCode may disclose reason for rejection.
*/
- bool connectBREDR(const uint16_t pkt_type=HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5,
- const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01);
+ HCIStatusCode connectBREDR(const uint16_t pkt_type=HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5,
+ const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01);
/**
* Establish a default HCI connection to this device, using certain default parameter.
* <p>
- * Depending on this device's addressType,
- * either a BREDR (BDADDR_BREDR) or LE (BDADDR_LE_PUBLIC, BDADDR_LE_RANDOM) connection is attempted.
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command <br>
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.5 Create Connection command
* </p>
* <p>
- * Returns true if the command has been accepted, otherwise false.
+ * Depending on this device's addressType,
+ * either a BREDR (BDADDR_BREDR) or LE (BDADDR_LE_PUBLIC, BDADDR_LE_RANDOM) connection is attempted.<br>
+ * If unacceptable, HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM is being returned.
* </p>
* <p>
* The actual new connection handle will be delivered asynchronous and
- * the connection event can be caught via AdapterStatusListener::deviceConnected(..).
- * </p>
+ * the connection event can be caught via AdapterStatusListener::deviceConnected(..),
+ * or if failed via AdapterStatusListener::deviceDisconnected(..).
* <p>
* The device is tracked by the managing adapter.
* </p>
+ * @return HCIStatusCode::SUCCESS if the command has been accepted, otherwise HCIStatusCode may disclose reason for rejection.
*/
- bool connectDefault();
+ HCIStatusCode connectDefault();
/** Return the HCI connection handle to the LE or BREDR peer, 0 if not connected. */
@@ -290,7 +297,7 @@ namespace direct_bt {
/**
* Disconnect the LE or BREDR peer's GATT and HCI connection.
* <p>
- * Returns true if the command has been accepted, otherwise false.
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.6 Disconnect command
* </p>
* <p>
* The actual disconnect event will be delivered asynchronous and
@@ -303,8 +310,9 @@ namespace direct_bt {
* <p>
* An open GATTHandler will also be closed via disconnectGATT()
* </p>
+ * @return HCIStatusCode::SUCCESS if the command has been accepted, otherwise HCIStatusCode may disclose reason for rejection.
*/
- bool disconnect(const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION ) {
+ HCIStatusCode disconnect(const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION ) {
return disconnect(false /* fromDisconnectCB */, false /* ioErrorCause */, reason);
}
diff --git a/examples/direct_bt_scanner00/dbt_scanner00.cpp b/examples/direct_bt_scanner00/dbt_scanner00.cpp
index 5408eac2..09ca4d9d 100644
--- a/examples/direct_bt_scanner00/dbt_scanner00.cpp
+++ b/examples/direct_bt_scanner00/dbt_scanner00.cpp
@@ -222,8 +222,9 @@ int main(int argc, char *argv[])
// (Without: Overall communication takes ~twice as long!!!)
//
if( doHCI_Connect ) {
- if( 0 == device->connectDefault() ) {
- fprintf(stderr, "Connect: Failed %s\n", device->toString().c_str());
+ HCIStatusCode res;
+ if( ( res = device->connectDefault() ) != HCIStatusCode::SUCCESS ) {
+ fprintf(stderr, "Connect: Failed res %s, %s\n", getHCIStatusCodeString(res).c_str(), device->toString().c_str());
// we tolerate the failed immediate connect, as it might happen at a later time
} else {
fprintf(stderr, "Connect: Success\n");
diff --git a/examples/direct_bt_scanner01/dbt_scanner01.cpp b/examples/direct_bt_scanner01/dbt_scanner01.cpp
index 720f68e0..bc3e8b2e 100644
--- a/examples/direct_bt_scanner01/dbt_scanner01.cpp
+++ b/examples/direct_bt_scanner01/dbt_scanner01.cpp
@@ -218,8 +218,9 @@ int main(int argc, char *argv[])
// (Without: Overall communication takes ~twice as long!!!)
//
if( doHCI_Connect ) {
- if( 0 == device->connectDefault() ) {
- fprintf(stderr, "Connect: Failed %s\n", device->toString().c_str());
+ HCIStatusCode res;
+ if( ( res = device->connectDefault() ) != HCIStatusCode::SUCCESS ) {
+ fprintf(stderr, "Connect: Failed res %s, %s\n", getHCIStatusCodeString(res).c_str(), device->toString().c_str());
// we tolerate the failed immediate connect, as it might happen at a later time
} else {
fprintf(stderr, "Connect: Success\n");
diff --git a/examples/direct_bt_scanner10/dbt_scanner10.cpp b/examples/direct_bt_scanner10/dbt_scanner10.cpp
index 35d22efc..a428ba72 100644
--- a/examples/direct_bt_scanner10/dbt_scanner10.cpp
+++ b/examples/direct_bt_scanner10/dbt_scanner10.cpp
@@ -234,12 +234,14 @@ class MyGATTEventListener : public AssociatedGATTCharacteristicListener {
static void connectDiscoveredDevice(std::shared_ptr<DBTDevice> device) {
fprintf(stderr, "****** Connecting Device: Start %s\n", device->toString().c_str());
device->getAdapter().stopDiscovery();
- bool res = false;
+ HCIStatusCode res;
if( !USE_WHITELIST ) {
res = device->connectDefault();
+ } else {
+ res = HCIStatusCode::SUCCESS;
}
- fprintf(stderr, "****** Connecting Device: End result %d of %s\n", res, device->toString().c_str());
- if( !USE_WHITELIST && 0 == devicesInProcessing.size() && !res ) {
+ fprintf(stderr, "****** Connecting Device: End result %s of %s\n", getHCIStatusCodeString(res).c_str(), device->toString().c_str());
+ if( !USE_WHITELIST && 0 == devicesInProcessing.size() && HCIStatusCode::SUCCESS != res ) {
device->getAdapter().startDiscovery( true );
}
}
diff --git a/examples/java/AsyncTinyB.java b/examples/java/AsyncTinyB.java
index f70b890a..20313b33 100644
--- a/examples/java/AsyncTinyB.java
+++ b/examples/java/AsyncTinyB.java
@@ -6,6 +6,7 @@ import org.tinyb.BluetoothFactory;
import org.tinyb.BluetoothGattCharacteristic;
import org.tinyb.BluetoothGattService;
import org.tinyb.BluetoothManager;
+import org.tinyb.HCIStatusCode;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.TimeUnit;
@@ -87,7 +88,7 @@ public class AsyncTinyB {
System.out.print("Found device: ");
printDevice(sensor);
- if (sensor.connect())
+ if ( HCIStatusCode.SUCCESS == sensor.connect() )
System.out.println("Sensor with the provided address connected");
else {
System.out.println("Could not connect device.");
diff --git a/examples/java/HelloTinyB.java b/examples/java/HelloTinyB.java
index 77435de6..b6709b7f 100644
--- a/examples/java/HelloTinyB.java
+++ b/examples/java/HelloTinyB.java
@@ -11,6 +11,7 @@ import org.tinyb.BluetoothFactory;
import org.tinyb.BluetoothGattCharacteristic;
import org.tinyb.BluetoothGattService;
import org.tinyb.BluetoothManager;
+import org.tinyb.HCIStatusCode;
public class HelloTinyB {
static boolean running = true;
@@ -149,7 +150,7 @@ public class HelloTinyB {
System.out.print("Found device: ");
printDevice(sensor);
- if (sensor.connect())
+ if ( HCIStatusCode.SUCCESS == sensor.connect() )
System.out.println("Sensor with the provided address connected");
else {
System.out.println("Could not connect device.");
diff --git a/examples/java/Notification.java b/examples/java/Notification.java
index c39a0a9e..5a2f5a8e 100644
--- a/examples/java/Notification.java
+++ b/examples/java/Notification.java
@@ -34,6 +34,7 @@ import org.tinyb.BluetoothGattCharacteristic;
import org.tinyb.BluetoothGattService;
import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothNotification;
+import org.tinyb.HCIStatusCode;
class ValueNotification implements BluetoothNotification<byte[]> {
@@ -141,7 +142,7 @@ public class Notification {
System.out.print("Found device: ");
printDevice(sensor);
- if (sensor.connect())
+ if ( HCIStatusCode.SUCCESS == sensor.connect() )
System.out.println("Sensor with the provided address connected");
else {
System.out.println("Could not connect device.");
diff --git a/examples/java/ScannerTinyB00.java b/examples/java/ScannerTinyB00.java
index 7a45729a..e3b00648 100644
--- a/examples/java/ScannerTinyB00.java
+++ b/examples/java/ScannerTinyB00.java
@@ -37,6 +37,7 @@ import org.tinyb.BluetoothGattService;
import org.tinyb.BluetoothManager;
import org.tinyb.BluetoothNotification;
import org.tinyb.BluetoothUtils;
+import org.tinyb.HCIStatusCode;
public class ScannerTinyB00 {
static {
@@ -165,13 +166,14 @@ public class ScannerTinyB00 {
sensor.enableServicesResolvedNotifications(servicesResolvedNotification);
final long t2;
- if ( sensor.connect() ) {
+ final HCIStatusCode res;
+ if ( ( res = sensor.connect() ) == HCIStatusCode.SUCCESS ) {
t2 = System.currentTimeMillis();
- System.err.println("Sensor connected in "+(t2-t1)+" ms");
+ System.err.println("Sensor connect command in "+(t2-t1)+" ms");
System.err.println("Sensor connectedNotification: "+connectedNotification.getValue());
} else {
t2=0;
- System.out.println("Could not connect device.");
+ System.out.println("Connect command failed, res "+res);
System.exit(-1);
}
diff --git a/examples/java/ScannerTinyB01.java b/examples/java/ScannerTinyB01.java
index d6385167..4dda480c 100644
--- a/examples/java/ScannerTinyB01.java
+++ b/examples/java/ScannerTinyB01.java
@@ -275,13 +275,14 @@ public class ScannerTinyB01 {
final long t2 = BluetoothUtils.getCurrentMilliseconds();
final long t3;
- if ( sensor.connect() ) {
+ HCIStatusCode res;
+ if ( ( res = sensor.connect() ) == HCIStatusCode.SUCCESS ) {
t3 = BluetoothUtils.getCurrentMilliseconds();
- System.err.println("Sensor connected: "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
+ System.err.println("Sensor connect issued: "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
System.err.println("Sensor connectedNotification: "+connectedNotification.getValue());
} else {
t3 = BluetoothUtils.getCurrentMilliseconds();
- System.out.println("Could not connect device: "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
+ System.out.println("connect command failed, res "+res+": "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
// we tolerate the failed immediate connect, as it might happen at a later time
}
diff --git a/examples/java/ScannerTinyB02.java b/examples/java/ScannerTinyB02.java
index d02ba9e7..a62c9742 100644
--- a/examples/java/ScannerTinyB02.java
+++ b/examples/java/ScannerTinyB02.java
@@ -282,13 +282,14 @@ public class ScannerTinyB02 {
final long t2 = BluetoothUtils.getCurrentMilliseconds();
final long t3;
- if ( sensor.connect() ) {
+ HCIStatusCode res;
+ if ( (res = sensor.connect() ) == HCIStatusCode.SUCCESS ) {
t3 = BluetoothUtils.getCurrentMilliseconds();
- System.err.println("Sensor connected: "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
+ System.err.println("Sensor connect issued: "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
System.err.println("Sensor connectedNotification: "+connectedNotification.getValue());
} else {
t3 = BluetoothUtils.getCurrentMilliseconds();
- System.out.println("Could not connect device: "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
+ System.out.println("connect command failed, res "+res+": "+(t3-t2)+" ms, total "+(t3-t0)+" ms");
// we tolerate the failed immediate connect, as it might happen at a later time
}
diff --git a/examples/java/ScannerTinyB10.java b/examples/java/ScannerTinyB10.java
index 1ec6afc3..730376d9 100644
--- a/examples/java/ScannerTinyB10.java
+++ b/examples/java/ScannerTinyB10.java
@@ -184,12 +184,14 @@ public class ScannerTinyB10 {
private void connectDiscoveredDevice(final BluetoothDevice device) {
println("****** Connecting Device: Start " + device.toString());
device.getAdapter().stopDiscovery();
- boolean res = false;
+ HCIStatusCode res;
if( !USE_WHITELIST ) {
res = device.connect();
+ } else {
+ res = HCIStatusCode.SUCCESS;
}
- println("****** Connecting Device: End result "+res+" of " + device.toString());
- if( !USE_WHITELIST && 0 == devicesInProcessing.size() && !res ) {
+ println("****** Connecting Device Command, res "+res+": End result "+res+" of " + device.toString());
+ if( !USE_WHITELIST && 0 == devicesInProcessing.size() && HCIStatusCode.SUCCESS != res ) {
device.getAdapter().startDiscovery( true );
}
}
diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java
index 65301141..601a30a7 100644
--- a/java/direct_bt/tinyb/DBTDevice.java
+++ b/java/direct_bt/tinyb/DBTDevice.java
@@ -356,36 +356,36 @@ public class DBTDevice extends DBTObject implements BluetoothDevice
public final boolean getConnected() { return isConnected.get(); }
@Override
- public final boolean disconnect() throws BluetoothException {
+ public final HCIStatusCode disconnect() throws BluetoothException {
if( isConnected.get() ) {
- return disconnectImpl(); // event callbacks will be generated by implementation
+ return HCIStatusCode.get( disconnectImpl() ); // event callbacks will be generated by implementation
}
- return false;
+ return HCIStatusCode.CONNECTION_TERMINATED_BY_LOCAL_HOST;
}
- private native boolean disconnectImpl() throws BluetoothException;
+ private native byte disconnectImpl() throws BluetoothException;
@Override
- public final boolean connect() throws BluetoothException {
+ public final HCIStatusCode connect() throws BluetoothException {
if( !isConnected.get() ) {
- return connectImpl(); // event callbacks will be generated by implementation
+ return HCIStatusCode.get( connectImpl() ); // event callbacks will be generated by implementation
}
- return false;
+ return HCIStatusCode.CONNECTION_ALREADY_EXISTS;
}
- private native boolean connectImpl() throws BluetoothException;
+ private native byte connectImpl() throws BluetoothException;
@Override
- public boolean connect(final short le_scan_interval, final short le_scan_window,
- final short conn_interval_min, final short conn_interval_max,
- final short conn_latency, final short timeout) {
+ public HCIStatusCode connect(final short le_scan_interval, final short le_scan_window,
+ final short conn_interval_min, final short conn_interval_max,
+ final short conn_latency, final short timeout) {
if( !isConnected.get() ) {
// event callbacks will be generated by implementation
- return connectImpl(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, timeout);
+ return HCIStatusCode.get( connectImpl(le_scan_interval, le_scan_window, conn_interval_min, conn_interval_max, conn_latency, timeout) );
}
- return false;
+ return HCIStatusCode.CONNECTION_ALREADY_EXISTS;
}
- private native boolean connectImpl(final short le_scan_interval, final short le_scan_window,
- final short conn_interval_min, final short conn_interval_max,
- final short conn_latency, final short timeout);
+ private native byte connectImpl(final short le_scan_interval, final short le_scan_window,
+ final short conn_interval_min, final short conn_interval_max,
+ final short conn_latency, final short timeout);
/* DBT Java callbacks */
diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx
index d28ac0c2..e426d2ce 100644
--- a/java/jni/direct_bt/DBTDevice.cxx
+++ b/java/jni/direct_bt/DBTDevice.cxx
@@ -295,16 +295,16 @@ void Java_direct_1bt_tinyb_DBTDevice_deleteImpl(JNIEnv *env, jobject obj, jlong
}
}
-jboolean Java_direct_1bt_tinyb_DBTDevice_disconnectImpl(JNIEnv *env, jobject obj)
+jbyte Java_direct_1bt_tinyb_DBTDevice_disconnectImpl(JNIEnv *env, jobject obj)
{
try {
DBTDevice *device = getDBTObject<DBTDevice>(env, obj);
JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
- return device->disconnect() ? JNI_TRUE : JNI_FALSE;
+ return (jint) number( device->disconnect() );
} catch(...) {
rethrow_and_raise_java_exception(env);
}
- return JNI_FALSE;
+ return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
}
jboolean Java_direct_1bt_tinyb_DBTDevice_removeImpl(JNIEnv *env, jobject obj)
@@ -319,28 +319,27 @@ jboolean Java_direct_1bt_tinyb_DBTDevice_removeImpl(JNIEnv *env, jobject obj)
return JNI_TRUE;
}
-jboolean Java_direct_1bt_tinyb_DBTDevice_connectImpl__(JNIEnv *env, jobject obj)
+jbyte Java_direct_1bt_tinyb_DBTDevice_connectImpl__(JNIEnv *env, jobject obj)
{
try {
DBTDevice *device = getDBTObject<DBTDevice>(env, obj);
JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
- bool res = device->connectDefault();
- return res ? JNI_TRUE : JNI_FALSE;
+ return (jbyte) number( device->connectDefault() );
} catch(...) {
rethrow_and_raise_java_exception(env);
}
- return JNI_FALSE;
+ return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
}
-jboolean Java_direct_1bt_tinyb_DBTDevice_connectImpl__SSSSSS(JNIEnv *env, jobject obj,
- jshort interval, jshort window,
- jshort min_interval, jshort max_interval,
- jshort latency, jshort timeout)
+jbyte Java_direct_1bt_tinyb_DBTDevice_connectImpl__SSSSSS(JNIEnv *env, jobject obj,
+ jshort interval, jshort window,
+ jshort min_interval, jshort max_interval,
+ jshort latency, jshort timeout)
{
try {
DBTDevice *device = getDBTObject<DBTDevice>(env, obj);
JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
- bool res;
+ HCIStatusCode res;
switch( device->addressType ) {
case BDAddressType::BDADDR_LE_PUBLIC:
/* fall through intended */
@@ -351,11 +350,11 @@ jboolean Java_direct_1bt_tinyb_DBTDevice_connectImpl__SSSSSS(JNIEnv *env, jobjec
res = device->connectDefault();
break;
}
- return res ? JNI_TRUE : JNI_FALSE;
+ return (jbyte) number(res);
} catch(...) {
rethrow_and_raise_java_exception(env);
}
- return JNI_FALSE;
+ return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
}
//
diff --git a/java/jni/tinyb/DBusDevice.cxx b/java/jni/tinyb/DBusDevice.cxx
index 5eb8581b..f810ef9d 100644
--- a/java/jni/tinyb/DBusDevice.cxx
+++ b/java/jni/tinyb/DBusDevice.cxx
@@ -72,7 +72,7 @@ jobject Java_tinyb_dbus_DBusDevice_clone(JNIEnv *env, jobject obj)
return nullptr;
}
-jboolean Java_tinyb_dbus_DBusDevice_disconnect(JNIEnv *env, jobject obj)
+jboolean Java_tinyb_dbus_DBusDevice_disconnectImpl(JNIEnv *env, jobject obj)
{
try {
BluetoothDevice *obj_device = getInstance<BluetoothDevice>(env, obj);
@@ -131,7 +131,7 @@ jboolean Java_tinyb_dbus_DBusDevice_connectAsyncFinish(JNIEnv *env, jobject obj)
return JNI_FALSE;
}
-jboolean Java_tinyb_dbus_DBusDevice_connect(JNIEnv *env, jobject obj)
+jboolean Java_tinyb_dbus_DBusDevice_connectImpl(JNIEnv *env, jobject obj)
{
try {
BluetoothDevice *obj_device = getInstance<BluetoothDevice>(env, obj);
diff --git a/java/org/tinyb/BluetoothDevice.java b/java/org/tinyb/BluetoothDevice.java
index fe84cce8..2794bde2 100644
--- a/java/org/tinyb/BluetoothDevice.java
+++ b/java/org/tinyb/BluetoothDevice.java
@@ -64,25 +64,83 @@ public interface BluetoothDevice extends BluetoothObject
*/
BluetoothGattService find(String UUID);
- /* D-Bus method calls: */
- /** The connection to this device is removed, removing all connected
- * profiles.
- * @return TRUE if the device disconnected
- */
- boolean disconnect() throws BluetoothException;
+ /* Bluetooth method calls: */
- /** A connection to this device is established, connecting each profile
- * flagged as auto-connectable.
- * @return TRUE if the device connected
- * @see #connect(short, short, short, short, short, short)
- */
- boolean connect() throws BluetoothException;
+ /**
+ * <b>direct_bt.tinyb</b>: Disconnect the LE or BREDR peer's GATT and HCI connection.
+ * <p>
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.6 Disconnect command
+ * </p>
+ * <p>
+ * The actual disconnect event will be delivered asynchronous and
+ * the connection event can be caught via AdapterStatusListener::deviceDisconnected(..).
+ * If unacceptable, {@link HCIStatusCode#UNACCEPTABLE_CONNECTION_PARAM} is being returned.
+ * </p>
+ * <p>
+ * The device will be removed from the managing adapter's connected devices
+ * when {@link AdapterStatusListener#deviceDisconnected(BluetoothDevice, HCIStatusCode, long)} has been received.
+ * </p>
+ * <p>
+ * Any open GATT connection will be closed as well.
+ * </p>
+ * <p>
+ * <b>tinyb.dbus</b> The connection to this device is removed, removing all connected
+ * profiles.
+ * </p>
+ * @return {@link HCIStatusCode#SUCCESS} if the command has been accepted, otherwise {@link HCIStatusCode} may disclose reason for rejection.
+ * @since 2.1.0 change API, i.e. return value from boolean to HCIStatusCode in favor of <i>direct_bt</i>
+ */
+ HCIStatusCode disconnect() throws BluetoothException;
+
+ /**
+ * <b>direct_bt.tinyb</b>: Establish a default HCI connection to this device, using certain default parameter.
+ * <p>
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command <br>
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.5 Create Connection command
+ * </p>
+ * <p>
+ * Depending on this device's addressType,
+ * either a BREDR (BDADDR_BREDR) or LE (BDADDR_LE_PUBLIC, BDADDR_LE_RANDOM) connection is attempted.<br>
+ * If unacceptable, {@link HCIStatusCode#UNACCEPTABLE_CONNECTION_PARAM} is being returned.
+ * </p>
+ * <p>
+ * The actual new connection handle will be delivered asynchronous and
+ * the connection event can be caught via {@link AdapterStatusListener#deviceConnected(BluetoothDevice, long)},
+ * or if failed via {@link AdapterStatusListener#deviceDisconnected(BluetoothDevice, HCIStatusCode, long)}.
+ * </p>
+ * <p>
+ * The device is tracked by the managing adapter.
+ * </p>
+ * <p>
+ * <b>tinyb.dbus</b>: A connection to this device is established, connecting each profile
+ * flagged as auto-connectable.
+ * </p>
+ * @return {@link HCIStatusCode#SUCCESS} if the command has been accepted, otherwise {@link HCIStatusCode} may disclose reason for rejection.
+ * @see #connect(short, short, short, short, short, short)
+ * @since 2.1.0 change API, i.e. return value from boolean to HCIStatusCode in favor of <i>direct_bt</i>
+ */
+ HCIStatusCode connect() throws BluetoothException;
/**
- * A connection to this device is established, see {@link #connect()}.
+ * Establish a HCI BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM connection to this device.
* <p>
- * The given LE connection parameter will be used instead of the Bluetooth implementation defaults,
- * if this device is of type {@link BluetoothAddressType#BDADDR_LE_PUBLIC} or {@link BluetoothAddressType#BDADDR_LE_RANDOM}.
+ * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command
+ * </p>
+ * <p>
+ * If this device's {@link #getAddressType()} is not BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM,
+ * {@link HCIStatusCode#UNACCEPTABLE_CONNECTION_PARAM} is being returned.
+ * </p>
+ * <p>
+ * The actual new connection handle will be delivered asynchronous and
+ * the connection event can be caught via {@link AdapterStatusListener#deviceConnected(BluetoothDevice, long)},
+ * or if failed via {@link AdapterStatusListener#deviceDisconnected(BluetoothDevice, HCIStatusCode, long)}.
+ * </p>
+ * <p>
+ * The device is tracked by the managing adapter.
+ * </p>
+ * <p>
+ * Default parameter values are chosen for using public address resolution
+ * and usual connection latency, interval etc.
* </p>
* <p>
* Set window to the same value as the interval, enables continuous scanning.
@@ -93,15 +151,16 @@ public interface BluetoothDevice extends BluetoothObject
* @param conn_interval_min in units of 1.25ms, default value 15 for 19.75ms
* @param conn_interval_max in units of 1.25ms, default value 15 for 19.75ms
* @param conn_latency slave latency in units of connection events, default value 0
- * @param timeout in units of 10ms, default value 1000 for 10000ms or 10s.
- * @return {@code true} if successful, otherwise {@code false}.
+ * @param supervision_timeout in units of 10ms, default value 1000 for 10000ms or 10s.
+ * @return {@link HCIStatusCode#SUCCESS} if the command has been accepted, otherwise {@link HCIStatusCode} may disclose reason for rejection.
*
* @see #connect()
- * @since 2.0.0
+ * @since 2.1.0 change API, i.e. return value from boolean to HCIStatusCode in favor of <i>direct_bt</i>
+ * @implNote not implemented in <b>tinyb.dbus</b>
*/
- public boolean connect(final short le_scan_interval, final short le_scan_window,
- final short conn_interval_min, final short conn_interval_max,
- final short conn_latency, final short timeout);
+ HCIStatusCode connect(final short le_scan_interval, final short le_scan_window,
+ final short conn_interval_min, final short conn_interval_max,
+ final short conn_latency, final short timeout);
/** Connects a specific profile available on the device, given by UUID
@@ -193,7 +252,7 @@ public interface BluetoothDevice extends BluetoothObject
* determining whether the device is {@link BluetoothAddressType#BDADDR_BREDR}
* or an LE device, {@link BluetoothAddressType#BDADDR_LE_PUBLIC} or {@link BluetoothAddressType#BDADDR_LE_RANDOM}.
* @since 2.0.0
- * @implNote not implemented in tinyb.dbus, returns {@link BluetoothAddressType#BDADDR_LE_PUBLIC}
+ * @implNote not implemented in <b>tinyb.dbus</b>, returns {@link BluetoothAddressType#BDADDR_LE_PUBLIC}
*/
BluetoothAddressType getAddressType();
@@ -208,7 +267,7 @@ public interface BluetoothDevice extends BluetoothObject
* method shall return {@link BLERandomAddressType#UNDEFINED}.
* </p>
* @since 2.0.0
- * @implNote not implemented in tinyb.dbus, returns {@link BLERandomAddressType#UNDEFINED}
+ * @implNote not implemented in <b>tinyb.dbus</b>, returns {@link BLERandomAddressType#UNDEFINED}
*/
BLERandomAddressType getBLERandomAddressType();
@@ -454,7 +513,7 @@ public interface BluetoothDevice extends BluetoothObject
* @see BluetoothGattCharacteristic#configNotificationIndication(boolean, boolean, boolean[])
* @see BluetoothGattCharacteristic#enableNotificationOrIndication(boolean[])
* @since 2.0.0
- * @implNote not implemented in tinyb.dbus
+ * @implNote not implemented in <b>tinyb.dbus</b>
*/
public boolean addCharacteristicListener(final GATTCharacteristicListener listener)
throws IllegalStateException;
@@ -467,7 +526,7 @@ public interface BluetoothDevice extends BluetoothObject
* @param listener A {@link GATTCharacteristicListener} instance
* @return true if the given listener is an element of the list and has been removed, otherwise false.
* @since 2.0.0
- * @implNote not implemented in tinyb.dbus
+ * @implNote not implemented in <b>tinyb.dbus</b>
*/
public boolean removeCharacteristicListener(final GATTCharacteristicListener l);
@@ -480,7 +539,7 @@ public interface BluetoothDevice extends BluetoothObject
* @param associatedCharacteristic the match criteria to remove any GATTCharacteristicListener from the list
* @return number of removed listener.
* @since 2.0.0
- * @implNote not implemented in tinyb.dbus
+ * @implNote not implemented in <b>tinyb.dbus</b>
*/
public int removeAllAssociatedCharacteristicListener(final BluetoothGattCharacteristic associatedCharacteristic);
@@ -488,7 +547,7 @@ public interface BluetoothDevice extends BluetoothObject
* Remove all {@link GATTCharacteristicListener} from the list.
* @return number of removed listener.
* @since 2.0.0
- * @implNote not implemented in tinyb.dbus
+ * @implNote not implemented in <b>tinyb.dbus</b>
*/
public int removeAllCharacteristicListener();
}
diff --git a/java/tinyb/dbus/DBusDevice.java b/java/tinyb/dbus/DBusDevice.java
index 5bbb8f7d..225b01d0 100644
--- a/java/tinyb/dbus/DBusDevice.java
+++ b/java/tinyb/dbus/DBusDevice.java
@@ -42,6 +42,7 @@ import org.tinyb.BluetoothNotification;
import org.tinyb.BluetoothType;
import org.tinyb.BluetoothUtils;
import org.tinyb.GATTCharacteristicListener;
+import org.tinyb.HCIStatusCode;
public class DBusDevice extends DBusObject implements BluetoothDevice
{
@@ -76,15 +77,22 @@ public class DBusDevice extends DBusObject implements BluetoothDevice
/* D-Bus method calls: */
@Override
- public native boolean disconnect() throws BluetoothException;
+ public final HCIStatusCode disconnect() throws BluetoothException {
+ return disconnectImpl() ? HCIStatusCode.SUCCESS : HCIStatusCode.UNSPECIFIED_ERROR ;
+ }
+ private native boolean disconnectImpl() throws BluetoothException;
+
@Override
- public native boolean connect() throws BluetoothException;
+ public final HCIStatusCode connect() throws BluetoothException {
+ return connectImpl() ? HCIStatusCode.SUCCESS : HCIStatusCode.UNSPECIFIED_ERROR ;
+ }
+ private native boolean connectImpl() throws BluetoothException;
@Override
- public boolean connect(final short interval, final short window,
- final short min_interval, final short max_interval,
- final short latency, final short timeout) {
+ public HCIStatusCode connect(final short interval, final short window,
+ final short min_interval, final short max_interval,
+ final short latency, final short timeout) {
return connect(); // FIXME connection params ...
}
diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp
index 8d1056b9..898feca4 100644
--- a/src/direct_bt/DBTDevice.cpp
+++ b/src/direct_bt/DBTDevice.cpp
@@ -260,9 +260,9 @@ std::shared_ptr<ConnectionInfo> DBTDevice::getConnectionInfo() {
return connInfo;
}
-bool DBTDevice::connectLE(uint16_t le_scan_interval, uint16_t le_scan_window,
- uint16_t conn_interval_min, uint16_t conn_interval_max,
- uint16_t conn_latency, uint16_t supervision_timeout)
+HCIStatusCode DBTDevice::connectLE(uint16_t le_scan_interval, uint16_t le_scan_window,
+ uint16_t conn_interval_min, uint16_t conn_interval_max,
+ uint16_t conn_latency, uint16_t supervision_timeout)
{
const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect); // RAII-style acquire and relinquish via destructor
adapter.checkValid();
@@ -282,13 +282,13 @@ bool DBTDevice::connectLE(uint16_t le_scan_interval, uint16_t le_scan_window,
hci_own_mac_type = HCILEOwnAddressType::RANDOM;
ERR_PRINT("LE Random address type '%s' not supported yet: %s",
getBLERandomAddressTypeString(leRandomAddressType).c_str(), toString().c_str());
- return false;
+ return HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM;
case BLERandomAddressType::RESOLVABLE_PRIVAT:
hci_peer_mac_type = HCILEPeerAddressType::PUBLIC_IDENTITY;
hci_own_mac_type = HCILEOwnAddressType::RESOLVABLE_OR_PUBLIC;
ERR_PRINT("LE Random address type '%s' not supported yet: %s",
getBLERandomAddressTypeString(leRandomAddressType).c_str(), toString().c_str());
- return false;
+ return HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM;
case BLERandomAddressType::STATIC_PUBLIC:
// FIXME: This only works for a static random address not changing at all,
// i.e. between power-cycles - hence a temporary hack.
@@ -299,19 +299,19 @@ bool DBTDevice::connectLE(uint16_t le_scan_interval, uint16_t le_scan_window,
default: {
ERR_PRINT("Can't connectLE to LE Random address type '%s': %s",
getBLERandomAddressTypeString(leRandomAddressType).c_str(), toString().c_str());
- return false;
+ return HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM;
}
}
} break;
default: {
ERR_PRINT("Can't connectLE to address type '%s': %s", getBDAddressTypeString(addressType).c_str(), toString().c_str());
- return false;
+ return HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM;
}
}
if( isConnected ) {
ERR_PRINT("DBTDevice::connectLE: Already connected: %s", toString().c_str());
- return false;
+ return HCIStatusCode::CONNECTION_ALREADY_EXISTS;
}
HCIStatusCode status = adapter.getHCI()->le_create_conn(address,
@@ -337,31 +337,28 @@ bool DBTDevice::connectLE(uint16_t le_scan_interval, uint16_t le_scan_window,
getHCILEPeerAddressTypeString(hci_peer_mac_type).c_str(),
getHCILEOwnAddressTypeString(hci_own_mac_type).c_str(),
toString().c_str());
- return false;
- }
- if ( HCIStatusCode::SUCCESS != status ) {
+ } else if ( HCIStatusCode::SUCCESS != status ) {
ERR_PRINT("DBTDevice::connectLE: Could not create connection: status 0x%2.2X (%s), errno %d %s, hci-atype[peer %s, own %s] on %s",
static_cast<uint8_t>(status), getHCIStatusCodeString(status).c_str(), errno, strerror(errno),
getHCILEPeerAddressTypeString(hci_peer_mac_type).c_str(),
getHCILEOwnAddressTypeString(hci_own_mac_type).c_str(),
toString().c_str());
- return false;
}
- return true;
+ return status;
}
-bool DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offset, const uint8_t role_switch)
+HCIStatusCode DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offset, const uint8_t role_switch)
{
const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect); // RAII-style acquire and relinquish via destructor
adapter.checkValid();
if( isConnected ) {
ERR_PRINT("DBTDevice::connectBREDR: Already connected: %s", toString().c_str());
- return false;
+ return HCIStatusCode::CONNECTION_ALREADY_EXISTS;
}
if( !isBREDRAddressType() ) {
ERR_PRINT("DBTDevice::connectBREDR: Not a BDADDR_BREDR address: %s", toString().c_str());
- return false;
+ return HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM;
}
HCIStatusCode status = adapter.getHCI()->create_conn(address, pkt_type, clock_offset, role_switch);
@@ -369,12 +366,11 @@ bool DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offse
if ( HCIStatusCode::SUCCESS != status ) {
ERR_PRINT("DBTDevice::connectBREDR: Could not create connection: status 0x%2.2X (%s), errno %d %s on %s",
static_cast<uint8_t>(status), getHCIStatusCodeString(status).c_str(), errno, strerror(errno), toString().c_str());
- return false;
}
- return true;
+ return status;
}
-bool DBTDevice::connectDefault()
+HCIStatusCode DBTDevice::connectDefault()
{
switch( addressType ) {
case BDAddressType::BDADDR_LE_PUBLIC:
@@ -385,7 +381,7 @@ bool DBTDevice::connectDefault()
return connectBREDR();
default:
ERR_PRINT("DBTDevice::connectDefault: Not a valid address type: %s", toString().c_str());
- return false;
+ return HCIStatusCode::UNACCEPTABLE_CONNECTION_PARAM;
}
}
@@ -409,7 +405,7 @@ void DBTDevice::notifyDisconnected() {
hciConnHandle = 0;
}
-bool DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause, const HCIStatusCode reason) {
+HCIStatusCode DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause, const HCIStatusCode reason) {
// Avoid disconnect re-entry -> potential deadlock
bool expConn = true; // C++11, exp as value since C++20
if( !allowDisconnect.compare_exchange_strong(expConn, false) ) {
@@ -418,7 +414,7 @@ bool DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
allowDisconnect.load(), isConnected.load(), fromDisconnectCB, ioErrorCause,
static_cast<uint8_t>(reason), getHCIStatusCodeString(reason).c_str(),
(nullptr != gattHandler), uint16HexString(hciConnHandle).c_str());
- return false;
+ return HCIStatusCode::CONNECTION_TERMINATED_BY_LOCAL_HOST;
}
// Lock to avoid other threads connecting while disconnecting
const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect); // RAII-style acquire and relinquish via destructor
@@ -430,9 +426,10 @@ bool DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
disconnectGATT();
std::shared_ptr<HCIHandler> hci = adapter.getHCI();
- bool res = false;
+ HCIStatusCode res = HCIStatusCode::UNSPECIFIED_ERROR;
if( !isConnected ) {
+ res = HCIStatusCode::CONNECTION_TERMINATED_BY_LOCAL_HOST;
goto exit;
}
@@ -445,10 +442,9 @@ bool DBTDevice::disconnect(const bool fromDisconnectCB, const bool ioErrorCause,
goto exit;
}
- if( HCIStatusCode::SUCCESS != hci->disconnect(ioErrorCause, hciConnHandle.load(), address, addressType, reason) ) {
+ res = hci->disconnect(ioErrorCause, hciConnHandle.load(), address, addressType, reason);
+ if( HCIStatusCode::SUCCESS != res ) {
DBG_PRINT("DBTDevice::disconnect: handle 0x%X, errno %d %s", hciConnHandle.load(), errno, strerror(errno));
- } else {
- res = true;
}
exit: