summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-11-24 21:05:27 +0100
committerSven Gothel <[email protected]>2020-11-24 21:05:27 +0100
commitcc475330fd173ee0e38b4a9a8cb5205fa2136bed (patch)
treec6c97247cbd8f0304473caf1865f366b3ea9cab9
parent9f932fc51e5bed3d1a059131667191f56c20d7fb (diff)
DBTDevice: Clarify setConn* Security parameter API: Provide more versatile overloaded variant and simplified API entries.
setConnSecurityLevel(..) no more sets SMPIOCapability, only advise in API doc to avoid complexity.
-rw-r--r--api/direct_bt/DBTAdapter.hpp19
-rw-r--r--api/direct_bt/DBTDevice.hpp143
-rw-r--r--examples/direct_bt_scanner10/dbt_scanner10.cpp14
-rw-r--r--examples/java/DBTScanner10.java8
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java6
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx4
-rw-r--r--java/org/tinyb/BluetoothDevice.java79
-rw-r--r--java/tinyb/dbus/DBusDevice.java2
-rw-r--r--src/direct_bt/DBTAdapter.cpp17
-rw-r--r--src/direct_bt/DBTDevice.cpp82
10 files changed, 277 insertions, 97 deletions
diff --git a/api/direct_bt/DBTAdapter.hpp b/api/direct_bt/DBTAdapter.hpp
index 868c8485..ec042cee 100644
--- a/api/direct_bt/DBTAdapter.hpp
+++ b/api/direct_bt/DBTAdapter.hpp
@@ -249,9 +249,9 @@ namespace direct_bt {
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 bool DBTDevice::setConnSecurityLevel(const BTSecurityLevel sec_level, const bool blocking) noexcept;
- friend bool DBTDevice::setConnIOCapability(const SMPIOCapability io_cap, const bool blocking) noexcept;
- friend bool DBTDevice::setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, const bool blocking) noexcept;
+ friend bool DBTDevice::setConnSecurityLevel(const BTSecurityLevel sec_level) noexcept;
+ friend bool DBTDevice::setConnIOCapability(const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept;
+ friend bool DBTDevice::setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept;
friend void DBTDevice::processL2CAPSetup(std::shared_ptr<DBTDevice> sthis);
friend bool DBTDevice::updatePairingState(std::shared_ptr<DBTDevice> sthis, SMPPairingState state, std::shared_ptr<MgmtEvent> evt) noexcept;
friend void DBTDevice::hciSMPMsgCallback(std::shared_ptr<DBTDevice> sthis, std::shared_ptr<const SMPPDUMsg> msg, const HCIACLData::l2cap_frame& source) noexcept;
@@ -261,14 +261,19 @@ namespace direct_bt {
/**
* Sets the given SMPIOCapability for the next DBTDevice::connectLE() or DBTDevice::connectBREDR().
* <p>
- * The SMPIOCapability value will be reset to its previous value when connection is completed or failed.
+ * The ::SMPIOCapability value will be reset to its previous value when connection is completed or failed.
* </p>
- * @param io_cap SMPIOCapability to be applied
- * @param blocking if true, blocks until previous setting is completed,
+ * <p>
+ * A value of ::SMPIOCapability::UNSET will be ignored and method returns immediately.
+ * </p>
+ * @param[in] io_cap ::SMPIOCapability to be applied
+ * @param[in,out] blocking if true, blocks until previous setting is completed,
* i.e. until connection has been completed or failed.
* Otherwise returns immediately with false if previous connection result is still pending.
+ * On return, this parameter will be set to true if failure was caused by blocking or timeout, otherwise set to false.
+ * @param[out] pre_io_cap return the previous set ::SMPIOCapability value if successful
*/
- bool setConnIOCapability(const DBTDevice & device, const SMPIOCapability io_cap, const bool blocking) noexcept;
+ bool setConnIOCapability(const DBTDevice & device, const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept;
bool resetConnIOCapability(const DBTDevice & device) noexcept;
bool resetConnIOCapability(const DBTDevice & device, SMPIOCapability& pre_io_cap) noexcept;
bool isConnIOCapabilitySet() const noexcept { return nullptr != io_capability_device_ptr; }
diff --git a/api/direct_bt/DBTDevice.hpp b/api/direct_bt/DBTDevice.hpp
index 2ceaf62c..83aed534 100644
--- a/api/direct_bt/DBTDevice.hpp
+++ b/api/direct_bt/DBTDevice.hpp
@@ -430,64 +430,155 @@ namespace direct_bt {
HCIStatusCode disconnect(const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION ) noexcept;
/**
- * Set the ::BTSecurityLevel used to connect to this device.
+ * Set the ::BTSecurityLevel used to connect to this device on the upcoming connection.
* <p>
- * Method returns false if this device has already being connected,
+ * Method returns false if ::BTSecurityLevel::UNSET has been given,
+ * operation fails, this device has already being connected,
* or DBTDevice::connectLE() or DBTDevice::connectBREDR() has been issued already.
* </p>
* <p>
- * To ensure consistent no authentication setup,<br>
- * implementation will set ::SMPIOCapability::NO_INPUT_NO_OUTPUT if sec_level <= ::BTSecurityLevel::ENC_ONLY<br>
- * and DBTDevice::setConnIOCapability() has not been used.
+ * To ensure a consistent authentication setup,
+ * it is advised to set ::SMPIOCapability::NO_INPUT_NO_OUTPUT for sec_level <= ::BTSecurityLevel::ENC_ONLY
+ * using setConnSecurity() as well as an IO capable ::SMPIOCapability value
+ * for ::BTSecurityLevel::ENC_AUTH or ::BTSecurityLevel::ENC_AUTH_FIPS.
* </p>
- * @param sec_level ::BTSecurityLevel to be applied
- * @param blocking if true, blocks until previous ::SMPIOCapability setting is completed,
- * i.e. until connection has been completed or failed.
- * Otherwise returns immediately with false if previous connection result is still pending.
- * @return
+ * @param sec_level ::BTSecurityLevel to be applied, ::BTSecurityLevel::UNSET will be ignored and method fails.
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see getConnSecurityLevel()
+ * @see setConnIOCapability()
+ * @see getConnIOCapability()
+ * @see setConnSecurity()
*/
- bool setConnSecurityLevel(const BTSecurityLevel sec_level, const bool blocking) noexcept;
+ bool setConnSecurityLevel(const BTSecurityLevel sec_level) noexcept;
/**
- * Return the ::BTSecurityLevel, determined when connection is established.
+ * Return the ::BTSecurityLevel, determined when the connection is established.
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see setConnSecurityLevel()
+ * @see setConnIOCapability()
+ * @see getConnIOCapability()
+ * @see setConnSecurity()
*/
BTSecurityLevel getConnSecurityLevel() const noexcept { return pairing_data.sec_level_conn; }
/**
- * Sets the given ::SMPIOCapability used to connect to this device.
+ * Sets the given ::SMPIOCapability used to connect to this device temporarily for the adapter.
* <p>
- * Method returns false if operation fails, this device has already being connected,
+ * Method returns false if ::SMPIOCapability::UNSET has been given,
+ * operation fails, this device has already being connected,
* or DBTDevice::connectLE() or DBTDevice::connectBREDR() has been issued already.
* </p>
* <p>
* The ::SMPIOCapability value will be reset for the adapter to its previous value when connection is completed or failed.
* </p>
- * @param io_cap ::SMPIOCapability to be applied
- * @param blocking if true, blocks until previous ::SMPIOCapability setting is completed,
+ * @param[in] io_cap ::SMPIOCapability to be applied, ::SMPIOCapability::UNSET will be ignored and method fails.
+ * @param[in,out] blocking if true, blocks until previous ::SMPIOCapability setting is completed,
* i.e. until connection has been completed or failed.
- * Otherwise returns immediately with false if previous connection result is still pending.
+ * Otherwise returns immediately with false if previous connection result is still pending on the adapter.<br>
+ * On return, this parameter will be set to true if failure was caused by blocking or timeout, otherwise set to false.
+ * @param[out] pre_io_cap return the previous set ::SMPIOCapability value if successful
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see setConnSecurityLevel()
+ * @see getConnSecurityLevel()
+ * @see getConnIOCapability()
+ * @see setConnSecurity()
*/
- bool setConnIOCapability(const SMPIOCapability io_cap, const bool blocking=true) noexcept;
+ bool setConnIOCapability(const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept;
+
+ /**
+ * Sets the given ::SMPIOCapability used to connect to this device temporarily for the adapter.
+ * <p>
+ * Method returns false if ::SMPIOCapability::UNSET has been given,
+ * operation fails, this device has already being connected,
+ * or DBTDevice::connectLE() or DBTDevice::connectBREDR() has been issued already.
+ * </p>
+ * <p>
+ * The ::SMPIOCapability value will be reset for the adapter to its previous value when connection is completed or failed.
+ * </p>
+ * @param[in] io_cap ::SMPIOCapability to be applied, ::SMPIOCapability::UNSET will be ignored and method fails.
+ * @param[in] blocking if true, blocks until previous ::SMPIOCapability setting is completed,
+ * i.e. until connection has been completed or failed.
+ * Otherwise returns immediately with false if previous connection result is still pending on the adapter.
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see setConnSecurityLevel()
+ * @see getConnSecurityLevel()
+ * @see getConnIOCapability()
+ * @see setConnSecurity()
+ */
+ bool setConnIOCapability(const SMPIOCapability io_cap, const bool blocking) noexcept {
+ SMPIOCapability pre_io_cap { SMPIOCapability::UNSET };
+ bool blocking_in_out = blocking;
+ return setConnIOCapability(io_cap, blocking_in_out, pre_io_cap);
+ }
/**
- * Sets the given ::BTSecurityLevel and ::SMPIOCapability used to connect to this device.
+ * Sets the given ::BTSecurityLevel (on the upcoming connection) and ::SMPIOCapability (temporarily for the adapter)
+ * used to connect to this device if successful, otherwise method doesn't change either value.
* <p>
- * Method returns false if operation fails, this device has already being connected,
+ * Method returns false if ::BTSecurityLevel::UNSET or ::SMPIOCapability::UNSET has been given,
+ * operation fails, this device has already being connected,
* or DBTDevice::connectLE() or DBTDevice::connectBREDR() has been issued already.
* </p>
* <p>
* The ::SMPIOCapability value will be reset for the adapter to its previous value when connection is completed or failed.
* </p>
- * @param sec_level ::BTSecurityLevel to be applied
- * @param io_cap ::SMPIOCapability to be applied
- * @param blocking if true, blocks until previous ::SMPIOCapability setting is completed,
+ * @param[in] sec_level ::BTSecurityLevel to be applied, ::BTSecurityLevel::UNSET will be ignored and method fails.
+ * @param[in] io_cap ::SMPIOCapability to be applied, ::SMPIOCapability::UNSET will be ignored and method fails.
+ * @param[in,out] blocking if true, blocks until previous ::SMPIOCapability setting is completed,
* i.e. until connection has been completed or failed.
- * Otherwise returns immediately with false if previous connection result is still pending.
+ * Otherwise returns immediately with false if previous connection result is still pending on the adapter.<br>
+ * On return, this parameter will be set to true if failure was caused by blocking or timeout, otherwise set to false.
+ * @param[out] pre_io_cap return the previous set ::SMPIOCapability value if successful
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see setConnSecurityLevel()
+ * @see getConnSecurityLevel()
+ * @see setConnIOCapability()
+ * @see getConnIOCapability()
*/
- bool setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, const bool blocking=true) noexcept;
+ bool setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept;
+
+ /**
+ * Sets the given ::BTSecurityLevel (on the upcoming connection) and ::SMPIOCapability (temporarily for the adapter)
+ * used to connect to this device if successful, otherwise method doesn't change either value.
+ * <p>
+ * Method returns false if ::BTSecurityLevel::UNSET or ::SMPIOCapability::UNSET has been given,
+ * operation fails, this device has already being connected,
+ * or DBTDevice::connectLE() or DBTDevice::connectBREDR() has been issued already.
+ * </p>
+ * <p>
+ * The ::SMPIOCapability value will be reset for the adapter to its previous value when connection is completed or failed.
+ * </p>
+ * @param[in] sec_level ::BTSecurityLevel to be applied, ::BTSecurityLevel::UNSET will be ignored and method fails.
+ * @param[in] io_cap ::SMPIOCapability to be applied, ::SMPIOCapability::UNSET will be ignored and method fails.
+ * @param[in] blocking if true, blocks until previous ::SMPIOCapability setting is completed,
+ * i.e. until connection has been completed or failed.
+ * Otherwise returns immediately with false if previous connection result is still pending on the adapter.
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see setConnSecurityLevel()
+ * @see getConnSecurityLevel()
+ * @see setConnIOCapability()
+ * @see getConnIOCapability()
+ */
+ bool setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, const bool blocking) noexcept {
+ SMPIOCapability pre_io_cap { SMPIOCapability::UNSET };
+ bool blocking_in_out = blocking;
+ return setConnSecurity(sec_level, io_cap, blocking_in_out, pre_io_cap);
+ }
/**
- * Return the set ::SMPIOCapability value, determined when connection is established.
+ * Return the set ::SMPIOCapability value, determined when the connection is established.
+ * @see ::BTSecurityLevel
+ * @see ::SMPIOCapability
+ * @see setConnSecurityLevel()
+ * @see getConnSecurityLevel()
+ * @see setConnIOCapability()
+ * @see setConnSecurity()
*/
SMPIOCapability getConnIOCapability() const noexcept { return pairing_data.ioCap_conn; }
diff --git a/examples/direct_bt_scanner10/dbt_scanner10.cpp b/examples/direct_bt_scanner10/dbt_scanner10.cpp
index bcda886a..74565da3 100644
--- a/examples/direct_bt_scanner10/dbt_scanner10.cpp
+++ b/examples/direct_bt_scanner10/dbt_scanner10.cpp
@@ -76,8 +76,8 @@ static bool QUIET = false;
static std::vector<EUI48> waitForDevices;
-const static uint32_t NO_PASSKEY = 0xffffffffU;
-static uint32_t pairing_passkey = NO_PASSKEY;
+const static int NO_PASSKEY = -1;
+static int pairing_passkey = NO_PASSKEY;
static BTSecurityLevel sec_level = BTSecurityLevel::UNSET;
static SMPIOCapability io_capabilities = SMPIOCapability::UNSET;
@@ -250,7 +250,7 @@ class MyAdapterStatusListener : public AdapterStatusListener {
break;
case SMPPairingState::PASSKEY_EXPECTED: {
if( pairing_passkey != NO_PASSKEY ) {
- std::thread dc(&DBTDevice::setPairingPasskey, device, pairing_passkey); // @suppress("Invalid arguments")
+ std::thread dc(&DBTDevice::setPairingPasskey, device, static_cast<uint32_t>(pairing_passkey)); // @suppress("Invalid arguments")
dc.detach();
} /* else {
std::thread dc(&DBTDevice::setPairingPasskeyNegative, device); // @suppress("Invalid arguments")
@@ -367,7 +367,11 @@ static void connectDiscoveredDevice(std::shared_ptr<DBTDevice> device) {
if( BTSecurityLevel::UNSET < sec_level && SMPIOCapability::UNSET != io_capabilities ) {
device->setConnSecurity(sec_level, io_capabilities, true /* blocking */);
} else if( BTSecurityLevel::UNSET < sec_level ) {
- device->setConnSecurityLevel(sec_level, true /* blocking */);
+ if( BTSecurityLevel::ENC_ONLY >= sec_level ) {
+ device->setConnSecurity(sec_level, SMPIOCapability::NO_INPUT_NO_OUTPUT, true /* blocking */);
+ } else {
+ device->setConnSecurityLevel(sec_level);
+ }
} else if( SMPIOCapability::UNSET != io_capabilities ) {
device->setConnIOCapability(io_capabilities, true /* blocking */);
}
@@ -807,7 +811,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "SHOW_UPDATE_EVENTS %d\n", SHOW_UPDATE_EVENTS);
fprintf(stderr, "QUIET %d\n", QUIET);
fprintf(stderr, "btmode %s\n", getBTModeString(btMode).c_str());
- fprintf(stderr, "passkey %u\n", pairing_passkey);
+ fprintf(stderr, "passkey %d\n", pairing_passkey);
fprintf(stderr, "seclevel %s\n", getBTSecurityLevelString(sec_level).c_str());
fprintf(stderr, "iocap %s\n", getSMPIOCapabilityString(io_capabilities).c_str());
fprintf(stderr, "characteristic-id: %s\n", charIdentifier.c_str());
diff --git a/examples/java/DBTScanner10.java b/examples/java/DBTScanner10.java
index 33e799ca..1cbfb426 100644
--- a/examples/java/DBTScanner10.java
+++ b/examples/java/DBTScanner10.java
@@ -77,7 +77,7 @@ public class DBTScanner10 {
final List<String> waitForDevices = new ArrayList<String>();
- static final int NO_PASSKEY = 0xffffffff;
+ static final int NO_PASSKEY = -1;
int pairing_passkey = NO_PASSKEY;
BTSecurityLevel sec_level = BTSecurityLevel.UNSET;
SMPIOCapability io_capabilities = SMPIOCapability.UNSET;
@@ -295,7 +295,11 @@ public class DBTScanner10 {
if( BTSecurityLevel.UNSET.value < sec_level.value && SMPIOCapability.UNSET.value != io_capabilities.value ) {
device.setConnSecurity(sec_level, io_capabilities, true /* blocking */);
} else if( BTSecurityLevel.UNSET.value < sec_level.value ) {
- device.setConnSecurityLevel(sec_level, true /* blocking */);
+ if( BTSecurityLevel.ENC_ONLY.value >= sec_level.value ) {
+ device.setConnSecurity(sec_level, SMPIOCapability.NO_INPUT_NO_OUTPUT, true /* blocking */);
+ } else {
+ device.setConnSecurityLevel(sec_level);
+ }
} else if( SMPIOCapability.UNSET.value != io_capabilities.value ) {
device.setConnIOCapability(io_capabilities, true /* blocking */);
}
diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java
index 2895f123..c35fae23 100644
--- a/java/direct_bt/tinyb/DBTDevice.java
+++ b/java/direct_bt/tinyb/DBTDevice.java
@@ -335,10 +335,10 @@ public class DBTDevice extends DBTObject implements BluetoothDevice
}
@Override
- public final boolean setConnSecurityLevel(final BTSecurityLevel sec_level, final boolean blocking) {
- return setConnSecurityLevelImpl(sec_level.value, blocking);
+ public final boolean setConnSecurityLevel(final BTSecurityLevel sec_level) {
+ return setConnSecurityLevelImpl(sec_level.value);
}
- private final native boolean setConnSecurityLevelImpl(final byte sec_level, final boolean blocking);
+ private final native boolean setConnSecurityLevelImpl(final byte sec_level);
@Override
public final BTSecurityLevel getConnSecurityLevel() {
diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx
index ec4e6676..417c6fd7 100644
--- a/java/jni/direct_bt/DBTDevice.cxx
+++ b/java/jni/direct_bt/DBTDevice.cxx
@@ -379,12 +379,12 @@ jbyte Java_direct_1bt_tinyb_DBTDevice_connectLEImpl1(JNIEnv *env, jobject obj,
}
-jboolean Java_direct_1bt_tinyb_DBTDevice_setConnSecurityLevelImpl(JNIEnv *env, jobject obj, jbyte jsec_level, jboolean jblocking) {
+jboolean Java_direct_1bt_tinyb_DBTDevice_setConnSecurityLevelImpl(JNIEnv *env, jobject obj, jbyte jsec_level) {
try {
DBTDevice *device = getJavaUplinkObject<DBTDevice>(env, obj);
JavaGlobalObj::check(device->getJavaObject(), E_FILE_LINE);
- return device->setConnSecurityLevel( getBTSecurityLevel( static_cast<uint8_t>(jsec_level) ), JNI_TRUE == jblocking );
+ return device->setConnSecurityLevel( getBTSecurityLevel( static_cast<uint8_t>(jsec_level) ));
} catch(...) {
rethrow_and_raise_java_exception(env);
}
diff --git a/java/org/tinyb/BluetoothDevice.java b/java/org/tinyb/BluetoothDevice.java
index 53355a51..0bc82160 100644
--- a/java/org/tinyb/BluetoothDevice.java
+++ b/java/org/tinyb/BluetoothDevice.java
@@ -194,74 +194,107 @@ public interface BluetoothDevice extends BluetoothObject
boolean pair() throws BluetoothException;
/**
- * Set the {@link BTSecurityLevel} used to connect to this device.
+ * Set the {@link BTSecurityLevel} used to connect to this device on the upcoming connection.
* <p>
- * Method returns false if this device has already being connected,
+ * Method returns false if {@link BTSecurityLevel#UNSET} has been given,
+ * operation fails, this device has already being connected,
* or {@link #connectLE(short, short, short, short, short, short) connectLE} or {@link #connect()} has been issued already.
* </p>
* <p>
- * To ensure consistent no authentication setup,<br>
- * implementation will set {@link SMPIOCapability#NO_INPUT_NO_OUTPUT} if sec_level <= {@link BTSecurityLevel#ENC_ONLY}<br>
- * and {@link #setConnIOCapability(SMPIOCapability, boolean)} not used.
+ * To ensure a consistent authentication setup,
+ * it is advised to set {@link SMPIOCapability#NO_INPUT_NO_OUTPUT} for sec_level <= {@link BTSecurityLevel#ENC_ONLY}
+ * using {@link #setConnSecurity(BTSecurityLevel, SMPIOCapability, boolean) setConnSecurity(..)}
+ * as well as an IO capable {@link SMPIOCapability} value
+ * for {@link BTSecurityLevel#ENC_AUTH} or {@link BTSecurityLevel#ENC_AUTH_FIPS}.
* </p>
- * @param sec_level {@link BTSecurityLevel} to be applied
- * @param blocking if true, blocks until previous {@link SMPIOCapability} setting is completed,
- * i.e. until connection has been completed or failed.
- * Otherwise returns immediately with false if previous connection result is still pending.
+ * @param sec_level {@link BTSecurityLevel} to be applied, {@link BTSecurityLevel#UNSET} will be ignored and method fails.
* @return
* @since 2.1.0
* @implNote not implemented in tinyb.dbus
+ * @see BTSecurityLevel
+ * @see SMPIOCapability
+ * @see #getConnSecurityLevel()
+ * @see #setConnIOCapability(SMPIOCapability, boolean)
+ * @see #getConnIOCapability()
+ * @see #setConnSecurity(BTSecurityLevel, SMPIOCapability, boolean)
*/
- boolean setConnSecurityLevel(final BTSecurityLevel sec_level, boolean blocking);
+ boolean setConnSecurityLevel(final BTSecurityLevel sec_level);
/**
- * Return the {@link BTSecurityLevel}, determined when connection is established.
+ * Return the {@link BTSecurityLevel}, determined when the connection is established.
* @since 2.1.0
* @implNote not implemented in tinyb.dbus
+ * @see BTSecurityLevel
+ * @see SMPIOCapability
+ * @see #setConnSecurityLevel(BTSecurityLevel)
+ * @see #setConnIOCapability(SMPIOCapability, boolean)
+ * @see #getConnIOCapability()
+ * @see #setConnSecurity(BTSecurityLevel, SMPIOCapability, boolean)
*/
BTSecurityLevel getConnSecurityLevel();
/**
- * Sets the given {@link SMPIOCapability} used to connect to this device.
+ * Sets the given {@link SMPIOCapability} used to connect to this device temporarily for the adapter.
* <p>
- * Method returns false if operation fails, this device has already being connected,
+ * Method returns false if {@link SMPIOCapability#UNSET} has been given,
+ * operation fails, this device has already being connected,
* or {@link #connectLE(short, short, short, short, short, short) connectLE} or {@link #connect()} has been issued already.
* </p>
* <p>
- * The {@link SMPIOCapability} value will be reset to its previous value when connection is completed or failed.
+ * The {@link SMPIOCapability} value will be reset for the adapter to its previous value when connection is completed or failed.
* </p>
- * @param io_cap {@link SMPIOCapability} to be applied
+ * @param io_cap {@link SMPIOCapability} to be applied, {@link SMPIOCapability#UNSET} will be ignored and method fails.
* @param blocking if true, blocks until previous {@link SMPIOCapability} setting is completed,
* i.e. until connection has been completed or failed.
- * Otherwise returns immediately with false if previous connection result is still pending.
+ * Otherwise returns immediately with false if previous connection result is still pending on the adapter.
* @since 2.1.0
* @implNote not implemented in tinyb.dbus
+ * @see BTSecurityLevel
+ * @see SMPIOCapability
+ * @see #setConnSecurityLevel(BTSecurityLevel)
+ * @see #getConnSecurityLevel()
+ * @see #getConnIOCapability()
+ * @see #setConnSecurity(BTSecurityLevel, SMPIOCapability, boolean)
*/
boolean setConnIOCapability(final SMPIOCapability io_cap, final boolean blocking);
/**
- * Sets the given {@link BTSecurityLevel} and {@link SMPIOCapability} used to connect to this device.
+ * Sets the given {@link BTSecurityLevel} (on the upcoming connection) and {@link SMPIOCapability} (temporarily for the adapter)
+ * used to connect to this device if successful, otherwise method doesn't change either value.
* <p>
- * Method returns false if operation fails, this device has already being connected,
+ * Method returns false if {@link BTSecurityLevel#UNSET} or {@link SMPIOCapability#UNSET} has been given,
+ * operation fails, this device has already being connected,
* or {@link #connectLE(short, short, short, short, short, short) connectLE} or {@link #connect()} has been issued already.
* </p>
* <p>
- * The {@link SMPIOCapability} value will be reset to its previous value when connection is completed or failed.
+ * The {@link SMPIOCapability} value will be reset for the adapter to its previous value when connection is completed or failed.
* </p>
- * @param sec_level {@link BTSecurityLevel} to be applied
- * @param io_cap {@link SMPIOCapability} to be applied
+ * @param sec_level {@link BTSecurityLevel} to be applied, {@link BTSecurityLevel#UNSET} will be ignored and method fails.
+ * @param io_cap {@link SMPIOCapability} to be applied, {@link SMPIOCapability#UNSET} will be ignored and method fails.
* @param blocking if true, blocks until previous {@link SMPIOCapability} setting is completed,
* i.e. until connection has been completed or failed.
- * Otherwise returns immediately with false if previous connection result is still pending.
+ * Otherwise returns immediately with false if previous connection result is still pending on the adapter.
* @since 2.1.0
* @implNote not implemented in tinyb.dbus
+ * @see BTSecurityLevel
+ * @see SMPIOCapability
+ * @see #setConnSecurityLevel(BTSecurityLevel)
+ * @see #getConnSecurityLevel()
+ * @see #setConnIOCapability(SMPIOCapability, boolean)
+ * @see #getConnIOCapability()
*/
boolean setConnSecurity(final BTSecurityLevel sec_level, final SMPIOCapability io_cap, final boolean blocking);
/**
- * Return the {@link SMPIOCapability} value, determined when connection is established.
+ * Return the {@link SMPIOCapability} value, determined when the connection is established.
* @since 2.1.0
* @implNote not implemented in tinyb.dbus
+ * @see BTSecurityLevel
+ * @see SMPIOCapability
+ * @see #setConnSecurityLevel(BTSecurityLevel)
+ * @see #getConnSecurityLevel()
+ * @see #setConnIOCapability(SMPIOCapability, boolean)
+ * @see #setConnSecurity(BTSecurityLevel, SMPIOCapability, boolean)
*/
SMPIOCapability getConnIOCapability();
diff --git a/java/tinyb/dbus/DBusDevice.java b/java/tinyb/dbus/DBusDevice.java
index 526abe62..242bd1eb 100644
--- a/java/tinyb/dbus/DBusDevice.java
+++ b/java/tinyb/dbus/DBusDevice.java
@@ -110,7 +110,7 @@ public class DBusDevice extends DBusObject implements BluetoothDevice
public native boolean pair() throws BluetoothException;
@Override
- public final boolean setConnSecurityLevel(final BTSecurityLevel sec_level, final boolean blocking) { return false; } // FIXME
+ public final boolean setConnSecurityLevel(final BTSecurityLevel sec_level) { return false; } // FIXME
@Override
public final BTSecurityLevel getConnSecurityLevel() { return BTSecurityLevel.UNSET; } // FIXME
diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp
index 783ef04e..9604a359 100644
--- a/src/direct_bt/DBTAdapter.cpp
+++ b/src/direct_bt/DBTAdapter.cpp
@@ -354,7 +354,11 @@ bool DBTAdapter::setPowered(bool value) noexcept {
return mgmt.setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, value ? 1 : 0, current_settings);
}
-bool DBTAdapter::setConnIOCapability(const DBTDevice & device, const SMPIOCapability io_cap, const bool blocking) noexcept {
+bool DBTAdapter::setConnIOCapability(const DBTDevice & device, const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept {
+ if( SMPIOCapability::UNSET == io_cap ) {
+ blocking = false;
+ return false;
+ }
const DBTDevice * exp_null_device = nullptr; // C++11, exp as value since C++20
const uint32_t timeout_ms = 10000; // FIXME: Configurable?
const uint32_t poll_period_ms = 125;
@@ -362,21 +366,20 @@ bool DBTAdapter::setConnIOCapability(const DBTDevice & device, const SMPIOCapabi
while( !io_capability_device_ptr.compare_exchange_strong(exp_null_device, &device) ) {
if( blocking ) {
if( timeout_ms <= td ) {
+ blocking = true;
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(poll_period_ms));
td += poll_period_ms;
} else {
+ blocking = true;
return false;
}
}
- SMPIOCapability o;
- const bool res = mgmt.setIOCapability(dev_id, io_cap, o);
- DBG_PRINT("DBTAdapter::setConnIOCapability: result %d: %s -> %s, %s",
- res, getSMPIOCapabilityString(o).c_str(), getSMPIOCapabilityString(io_cap).c_str(),
- device.toString(false).c_str());
+ blocking = false;
+ const bool res = mgmt.setIOCapability(dev_id, io_cap, pre_io_cap);
if( res ) {
- io_capability_defaultval = o;
+ io_capability_defaultval = pre_io_cap;
return true;
} else {
io_capability_device_ptr = nullptr;
diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp
index 7ff0a05f..9720c278 100644
--- a/src/direct_bt/DBTDevice.cpp
+++ b/src/direct_bt/DBTDevice.cpp
@@ -660,44 +660,84 @@ void DBTDevice::hciSMPMsgCallback(std::shared_ptr<DBTDevice> sthis, std::shared_
DBG_PRINT("DBTDevice:hci:SMP.6: End %s", toString(false).c_str());
}
-bool DBTDevice::setConnSecurityLevel(const BTSecurityLevel sec_level, const bool blocking) noexcept {
- DBG_PRINT("DBTDevice::setSecurityLevel: %s -> %s, %s",
- getBTSecurityLevelString(pairing_data.sec_level_user).c_str(),
- getBTSecurityLevelString(sec_level).c_str(), toString(false).c_str());
+bool DBTDevice::setConnSecurityLevel(const BTSecurityLevel sec_level) noexcept {
+ if( BTSecurityLevel::UNSET == sec_level ) {
+ DBG_PRINT("DBTAdapter::setConnSecurityLevel: lvl %s, invalid value.", getBTSecurityLevelString(sec_level).c_str());
+ return false;
+ }
if( !isValid() || isConnected || allowDisconnect ) {
+ DBG_PRINT("DBTDevice::setConnSecurityLevel: lvl %s failed, invalid state %s",
+ getBTSecurityLevelString(sec_level).c_str(), toString(false).c_str());
return false;
}
+ const BTSecurityLevel old_sec_level = pairing_data.sec_level_user;
pairing_data.sec_level_user = sec_level;
+ const bool res = true;
- if( BTSecurityLevel::ENC_ONLY >= sec_level && !adapter.isConnIOCapabilitySet() )
- {
- // Adjust SMPIOCapability to match the no_auth BTSecurityLevel <= BTSecurityLevel::ENC_ONLY,
- // if connect hasn't been issued and setIOCapability() not used yet.
- return setConnIOCapability( SMPIOCapability::NO_INPUT_NO_OUTPUT, blocking);
- } else {
- return true;
- }
+ DBG_PRINT("DBTDevice::setConnSecurityLevel: result %d: lvl %s -> %s, %s", res,
+ getBTSecurityLevelString(old_sec_level).c_str(),
+ getBTSecurityLevelString(sec_level).c_str(),
+ toString(false).c_str());
+ return res;
}
-bool DBTDevice::setConnIOCapability(const SMPIOCapability io_cap, const bool blocking) noexcept {
+bool DBTDevice::setConnIOCapability(const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept {
+ if( SMPIOCapability::UNSET == io_cap ) {
+ DBG_PRINT("DBTDevice::setConnIOCapability: io %s, invalid value.", getSMPIOCapabilityString(io_cap).c_str());
+ return false;
+ }
+
if( !isValid() || isConnected || allowDisconnect ) {
+ DBG_PRINT("DBTDevice::setConnIOCapability: io %s failed, invalid state %s",
+ getSMPIOCapabilityString(io_cap).c_str(), toString(false).c_str());
return false;
}
- return adapter.setConnIOCapability(*this, io_cap, blocking);
+
+ const bool blocking_call = blocking;
+ const bool res = adapter.setConnIOCapability(*this, io_cap, blocking, pre_io_cap);
+
+ DBG_PRINT("DBTDevice::setConnIOCapability: result %d (blocked %d): io %s -> %s (blocking %d), %s",
+ res, blocking,
+ getSMPIOCapabilityString(pre_io_cap).c_str(), getSMPIOCapabilityString(io_cap).c_str(),
+ blocking_call, toString(false).c_str());
+
+ return res;
}
-bool DBTDevice::setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, const bool blocking) noexcept {
- DBG_PRINT("DBTDevice::setConnSecurity: %s -> %s, %s, %s",
- getBTSecurityLevelString(pairing_data.sec_level_user).c_str(),
- getBTSecurityLevelString(sec_level).c_str(),
- getSMPIOCapabilityString(io_cap).c_str(), toString(false).c_str());
+bool DBTDevice::setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, bool& blocking, SMPIOCapability& pre_io_cap) noexcept {
+ if( BTSecurityLevel::UNSET == sec_level ) {
+ DBG_PRINT("DBTAdapter::setConnSecurity: lvl %s, invalid value.", getBTSecurityLevelString(sec_level).c_str());
+ return false;
+ }
+ if( SMPIOCapability::UNSET == io_cap ) {
+ DBG_PRINT("DBTDevice::setConnSecurity: io %s, invalid value.", getSMPIOCapabilityString(io_cap).c_str());
+ return false;
+ }
if( !isValid() || isConnected || allowDisconnect ) {
+ DBG_PRINT("DBTDevice::setConnSecurity: lvl %s, io %s failed, invalid state %s",
+ getBTSecurityLevelString(sec_level).c_str(),
+ getSMPIOCapabilityString(io_cap).c_str(), toString(false).c_str());
return false;
}
- pairing_data.sec_level_user = sec_level;
- return adapter.setConnIOCapability(*this, io_cap, blocking);
+
+ const BTSecurityLevel pre_sec_level = pairing_data.sec_level_user;
+
+ const bool blocking_call = blocking;
+ const bool res = adapter.setConnIOCapability(*this, io_cap, blocking, pre_io_cap);
+ if( res ) {
+ pairing_data.sec_level_user = sec_level;
+ }
+
+ DBG_PRINT("DBTDevice::setConnSecurity: result %d (blocked %d): lvl %s -> %s, io %s -> %s (blocking %d), %s",
+ res, blocking,
+ getBTSecurityLevelString(pre_sec_level).c_str(),
+ getBTSecurityLevelString(pairing_data.sec_level_user).c_str(),
+ getSMPIOCapabilityString(pre_io_cap).c_str(), getSMPIOCapabilityString(io_cap).c_str(),
+ blocking_call, toString(false).c_str());
+
+ return res;
}
HCIStatusCode DBTDevice::setPairingPasskey(const uint32_t passkey) noexcept {