aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/direct_bt/BTAdapter.hpp17
-rw-r--r--api/direct_bt/BTDevice.hpp5
-rw-r--r--api/direct_bt/BTTypes0.hpp17
-rw-r--r--java/jau/direct_bt/DBTAdapter.java13
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx22
-rw-r--r--java/org/direct_bt/BTAdapter.java21
-rw-r--r--java/org/direct_bt/BTDevice.java10
-rw-r--r--java/org/direct_bt/BTRole.java75
-rw-r--r--src/direct_bt/BTAdapter.cpp11
-rw-r--r--src/direct_bt/BTTypes0.cpp9
10 files changed, 190 insertions, 10 deletions
diff --git a/api/direct_bt/BTAdapter.hpp b/api/direct_bt/BTAdapter.hpp
index 40317cd3..d1058738 100644
--- a/api/direct_bt/BTAdapter.hpp
+++ b/api/direct_bt/BTAdapter.hpp
@@ -240,11 +240,19 @@ namespace direct_bt {
/**
* BTAdapter represents one Bluetooth Controller.
* <p>
+ * BTAdapter roles:
+ *
+ * - ::BTRole::Master when discovery is enabled via startDiscovery(), but also per default at construction.
+ * - ::BTRole::Slave once advertising is enabled via startAdvertising(), explicit until next startDiscovery().
+ * </p>
+ * <p>
* Controlling Environment variables:
* <pre>
* - 'direct_bt.debug.adapter.event': Debug messages about events, see debug_events
* </pre>
* </p>
+ *
+ * @see [Bluetooth Specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/)
*/
class BTAdapter : public BTObject
{
@@ -260,7 +268,7 @@ namespace direct_bt {
bool hci_uses_ext_conn;
/**
- * Either the adapter's initially reported public address or a random address setup via HCI before scanning / discovery.
+ * Either the adapter's initially reported public address or a random address setup via HCI before discovery or advertising.
*/
BDAddressAndType visibleAddressAndType;
@@ -274,6 +282,7 @@ namespace direct_bt {
const uint16_t dev_id;
private:
+ std::atomic<BTRole> btRole; // = BTRole::Master (default)
HCIHandler hci;
std::atomic<AdapterSetting> old_settings;
@@ -494,6 +503,12 @@ namespace direct_bt {
}
/**
+ * Return the current BTRole of this adapter.
+ * @since 2.4.0
+ */
+ BTRole getRole() const noexcept { return btRole; }
+
+ /**
* Returns the current BTMode of this adapter.
*/
BTMode getBTMode() const noexcept { return adapterInfo.getCurrentBTMode(); }
diff --git a/api/direct_bt/BTDevice.hpp b/api/direct_bt/BTDevice.hpp
index 7a0c0785..7385d786 100644
--- a/api/direct_bt/BTDevice.hpp
+++ b/api/direct_bt/BTDevice.hpp
@@ -53,6 +53,11 @@ namespace direct_bt {
class BTAdapter; // forward
class AdapterStatusListener; // forward
+ /**
+ * BTDevice represents one Bluetooth device.
+ *
+ * @see [Bluetooth Specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/)
+ */
class BTDevice : public BTObject
{
friend BTAdapter; // managing us: ctor and update(..) during discovery
diff --git a/api/direct_bt/BTTypes0.hpp b/api/direct_bt/BTTypes0.hpp
index 8eee5bf4..92045b0d 100644
--- a/api/direct_bt/BTTypes0.hpp
+++ b/api/direct_bt/BTTypes0.hpp
@@ -51,6 +51,23 @@ namespace direct_bt {
/**
+ * Bluetooth device roles from the perspective of the link layer (connection initiator).
+ * @since 2.4.0
+ */
+ enum class BTRole : uint8_t {
+ /** Undefined role. */
+ None = 0,
+ /** Master or *central* role, discovering remote devices and initiating connection. This is a GATT client. */
+ Master = 1,
+ /** Slave or *peripheral* role, advertising and waiting for connections to accept. This is a GATT server. */
+ Slave = 2
+ };
+ constexpr uint8_t number(const BTRole rhs) noexcept {
+ return static_cast<uint8_t>(rhs);
+ }
+ std::string to_string(const BTRole v) noexcept;
+
+ /**
* Bluetooth adapter operating mode
*/
enum class BTMode : uint8_t {
diff --git a/java/jau/direct_bt/DBTAdapter.java b/java/jau/direct_bt/DBTAdapter.java
index 440b4f8e..edf97e24 100644
--- a/java/jau/direct_bt/DBTAdapter.java
+++ b/java/jau/direct_bt/DBTAdapter.java
@@ -46,6 +46,7 @@ import org.direct_bt.BTGattService;
import org.direct_bt.BTManager;
import org.direct_bt.BTMode;
import org.direct_bt.BTObject;
+import org.direct_bt.BTRole;
import org.direct_bt.BTType;
import org.direct_bt.BTUtils;
import org.direct_bt.EIRDataTypeSet;
@@ -104,6 +105,18 @@ public class DBTAdapter extends DBTObject implements BTAdapter
public final BTManager getManager() { return DBTManager.getManager(); }
@Override
+ public final BTRole getRole() {
+ return BTRole.get(getRoleImpl());
+ }
+ private native byte getRoleImpl();
+
+ @Override
+ public final BTMode getBTMode() {
+ return BTMode.get(getBTModeImpl());
+ }
+ private native byte getBTModeImpl();
+
+ @Override
public void close() {
final DBTManager mngr = (DBTManager)DBTManager.getManager();
if( !isValid() ) {
diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx
index 8f4ad701..b5bd1083 100644
--- a/java/jni/direct_bt/DBTAdapter.cxx
+++ b/java/jni/direct_bt/DBTAdapter.cxx
@@ -789,6 +789,28 @@ jbyte Java_jau_direct_1bt_DBTAdapter_stopDiscoveryImpl(JNIEnv *env, jobject obj)
return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
}
+jbyte Java_jau_direct_1bt_DBTAdapter_getRoleImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
+ return (jbyte) number( adapter->getRole() );
+ } catch(...) {
+ rethrow_and_raise_java_exception(env);
+ }
+ return (jbyte) number( BTRole::None );
+}
+
+jbyte Java_jau_direct_1bt_DBTAdapter_getBTModeImpl(JNIEnv *env, jobject obj)
+{
+ try {
+ BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
+ return (jbyte) number( adapter->getBTMode() );
+ } catch(...) {
+ rethrow_and_raise_java_exception(env);
+ }
+ return (jbyte) number( BTMode::NONE );
+}
+
jobject Java_jau_direct_1bt_DBTAdapter_getDiscoveredDevicesImpl(JNIEnv *env, jobject obj)
{
try {
diff --git a/java/org/direct_bt/BTAdapter.java b/java/org/direct_bt/BTAdapter.java
index 442d9f4e..6e4e5875 100644
--- a/java/org/direct_bt/BTAdapter.java
+++ b/java/org/direct_bt/BTAdapter.java
@@ -31,10 +31,15 @@ package org.direct_bt;
import java.util.List;
/**
- * Provides access to Bluetooth adapters.
+ * BTAdapter represents one Bluetooth Controller.
+ * <p>
+ * BTAdapter roles:
+ *
+ * - {@link BTRole#Master} discovery is enabled via {@link #startDiscovery(boolean, boolean, short, short, byte) startDiscovery(..)}, but also per default at construction.
+ * - {@link BTRole#Slave} once advertising is enabled via {@link #startAdvertising(short, short, byte, byte, byte) startAdvertising(..)}, explicit until next {@link #startDiscovery(boolean, boolean, short, short, byte) startDiscovery(..)}.
+ * </p>
*
* @see [Bluetooth Specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/)
- * @see [BlueZ adapter API](http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt)
*/
public interface BTAdapter extends BTObject
{
@@ -43,6 +48,18 @@ public interface BTAdapter extends BTObject
*/
public BTManager getManager();
+ /**
+ * Return the current {@link BTRole} of this adapter.
+ * @since 2.4.0
+ */
+ public BTRole getRole();
+
+ /**
+ * Returns the current {@link BTMode} of this adapter.
+ * @since 2.4.0
+ */
+ public BTMode getBTMode();
+
/** Find a BluetoothDevice. If parameters name and address are not null,
* the returned object will have to match them.
* It will first check for existing objects. It will not turn on discovery
diff --git a/java/org/direct_bt/BTDevice.java b/java/org/direct_bt/BTDevice.java
index 70cfdba8..03d4150f 100644
--- a/java/org/direct_bt/BTDevice.java
+++ b/java/org/direct_bt/BTDevice.java
@@ -32,12 +32,10 @@ import java.util.List;
import java.util.Map;
/**
- * Provides access to Bluetooth adapters.
- *
- * @see [Bluetooth Specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/)
- * @see [BlueZ device API](http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/device-api.txt)
- *
- */
+ * BTDevice represents one Bluetooth device.
+ *
+ * @see [Bluetooth Specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/)
+ */
public interface BTDevice extends BTObject
{
/** Find a BluetoothGattService. If parameter UUID is not null,
diff --git a/java/org/direct_bt/BTRole.java b/java/org/direct_bt/BTRole.java
new file mode 100644
index 00000000..ac50fa18
--- /dev/null
+++ b/java/org/direct_bt/BTRole.java
@@ -0,0 +1,75 @@
+/**
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2021 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.direct_bt;
+
+/**
+ * Bluetooth device roles from the perspective of the link layer (connection initiator).
+ * <p>
+ * See {@link #get(byte)} for its native integer mapping.
+ * </p>
+ * @since 2.4.0
+ */
+public enum BTRole {
+ /** Undefined role. */
+ None ((byte)0),
+ /** Master or *central* role, discovering remote devices and initiating connection. This is a GATT client. */
+ Master ((byte)1),
+ /** Slave or *peripheral* role, advertising and waiting for connections to accept. This is a GATT server. */
+ Slave ((byte)2);
+
+ public final byte value;
+
+ /**
+ * Maps the specified name to a constant of BTRole.
+ * <p>
+ * Implementation simply returns {@link #valueOf(String)}.
+ * This maps the constant names itself to their respective constant.
+ * </p>
+ * @param name the string name to be mapped to a constant of this enum type.
+ * @return the corresponding constant of this enum type.
+ * @throws IllegalArgumentException if the specified name can't be mapped to a constant of this enum type
+ * as described above.
+ */
+ public static BTRole get(final String name) throws IllegalArgumentException {
+ return valueOf(name);
+ }
+
+ /**
+ * Maps the specified integer value to a constant of {@link BTRole}.
+ * @param value the integer value to be mapped to a constant of this enum type.
+ * @return the corresponding constant of this enum type, using {@link #None} if not supported.
+ */
+ public static BTRole get(final byte value) {
+ switch(value) {
+ case (byte)0x01: return Master;
+ case (byte)0x02: return Slave;
+ default: return None;
+ }
+ }
+
+ BTRole(final byte v) {
+ value = v;
+ }
+}
diff --git a/src/direct_bt/BTAdapter.cpp b/src/direct_bt/BTAdapter.cpp
index bc671ea4..b588e5a0 100644
--- a/src/direct_bt/BTAdapter.cpp
+++ b/src/direct_bt/BTAdapter.cpp
@@ -160,6 +160,7 @@ bool BTAdapter::updateDataFromAdapterInfo() noexcept {
bool BTAdapter::initialSetup() noexcept {
bool ok = false;
currentMetaScanType = ScanType::NONE;
+ btRole = BTRole::Master;
keep_le_scan_alive = false;
if( !mgmt.isOpen() ) {
@@ -240,6 +241,7 @@ BTAdapter::BTAdapter(const BTAdapter::ctor_cookie& cc, BTManager& mgmt_, const A
le_features( LE_Features::NONE ),
visibleAddressAndType( adapterInfo_.addressAndType ),
dev_id( adapterInfo.dev_id ),
+ btRole (BTRole::Master),
hci( dev_id )
{
(void)cc;
@@ -330,6 +332,7 @@ void BTAdapter::poweredOff(const bool active) noexcept {
hci.resetAllStates(false);
currentMetaScanType = ScanType::NONE;
+ btRole = BTRole::Master;
if( active ) {
unlockConnectAny();
@@ -745,6 +748,7 @@ HCIStatusCode BTAdapter::startDiscovery(const bool keepAlive, const bool le_scan
if( hasScanType(currentNativeScanType, ScanType::LE) ) {
removeDiscoveredDevices();
+ btRole = BTRole::Master;
if( keep_le_scan_alive == keepAlive ) {
DBG_PRINT("BTAdapter::startDiscovery: Already discovering, unchanged keepAlive %d -> %d, currentScanType[native %s, meta %s] ...\n- %s",
keep_le_scan_alive.load(), keepAlive,
@@ -1054,6 +1058,8 @@ HCIStatusCode BTAdapter::startAdvertising(const uint16_t adv_interval_min, const
adv_interval_min, adv_interval_max, adv_type, adv_chan_map, filter_policy);
if( HCIStatusCode::SUCCESS != status ) {
ERR_PRINT("BTAdapter::stopAdvertising: le_start_adv failed: %s - %s", to_string(status).c_str(), toString(true).c_str());
+ } else {
+ btRole = BTRole::Slave;
}
return status;
}
@@ -1093,7 +1099,7 @@ HCIStatusCode BTAdapter::stopAdvertising() noexcept {
std::string BTAdapter::toString(bool includeDiscoveredDevices) const noexcept {
std::string random_address_info = adapterInfo.addressAndType != visibleAddressAndType ? " ("+visibleAddressAndType.toString()+")" : "";
- std::string out("Adapter[BTMode "+to_string(getBTMode())+", "+adapterInfo.addressAndType.toString()+random_address_info+
+ std::string out("Adapter[BTMode "+to_string(getBTMode())+", "+to_string(getRole())+", "+adapterInfo.addressAndType.toString()+random_address_info+
", '"+getName()+"', id "+std::to_string(dev_id)+
", curSettings"+to_string(adapterInfo.getCurrentSettingMask())+
", valid "+std::to_string(isValid())+
@@ -1218,6 +1224,9 @@ bool BTAdapter::mgmtEvDeviceDiscoveringAny(const MgmtEvent& e, const bool hciSou
event.toString().c_str());
}
currentMetaScanType = nextMetaScanType;
+ if( isDiscovering() ) {
+ btRole = BTRole::Master;
+ }
checkDiscoveryState();
diff --git a/src/direct_bt/BTTypes0.cpp b/src/direct_bt/BTTypes0.cpp
index e3687835..a47a3248 100644
--- a/src/direct_bt/BTTypes0.cpp
+++ b/src/direct_bt/BTTypes0.cpp
@@ -347,6 +347,15 @@ static inline const int8_t * const_uint8_to_const_int8_ptr(const uint8_t* p) noe
return static_cast<const int8_t *>( static_cast<void *>( const_cast<uint8_t*>( p ) ) );
}
+std::string direct_bt::to_string(const BTRole v) noexcept {
+ switch(v) {
+ case BTRole::None: return "None";
+ case BTRole::Master: return "Master";
+ case BTRole::Slave: return "Slave";
+ }
+ return "Unknown BTRole "+jau::to_hexstring(number(v));
+}
+
std::string direct_bt::to_string(const BTMode v) noexcept {
switch(v) {
case BTMode::NONE: return "NONE";