diff options
-rw-r--r-- | api/direct_bt/DBTAdapter.hpp | 10 | ||||
-rw-r--r-- | api/direct_bt/DBTDevice.hpp | 56 | ||||
-rw-r--r-- | examples/direct_bt_scanner00/dbt_scanner00.cpp | 5 | ||||
-rw-r--r-- | examples/direct_bt_scanner01/dbt_scanner01.cpp | 5 | ||||
-rw-r--r-- | examples/direct_bt_scanner10/dbt_scanner10.cpp | 8 | ||||
-rw-r--r-- | examples/java/AsyncTinyB.java | 3 | ||||
-rw-r--r-- | examples/java/HelloTinyB.java | 3 | ||||
-rw-r--r-- | examples/java/Notification.java | 3 | ||||
-rw-r--r-- | examples/java/ScannerTinyB00.java | 8 | ||||
-rw-r--r-- | examples/java/ScannerTinyB01.java | 7 | ||||
-rw-r--r-- | examples/java/ScannerTinyB02.java | 7 | ||||
-rw-r--r-- | examples/java/ScannerTinyB10.java | 8 | ||||
-rw-r--r-- | java/direct_bt/tinyb/DBTDevice.java | 32 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTDevice.cxx | 27 | ||||
-rw-r--r-- | java/jni/tinyb/DBusDevice.cxx | 4 | ||||
-rw-r--r-- | java/org/tinyb/BluetoothDevice.java | 113 | ||||
-rw-r--r-- | java/tinyb/dbus/DBusDevice.java | 18 | ||||
-rw-r--r-- | src/direct_bt/DBTDevice.cpp | 48 |
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: |