aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2021-09-15 10:50:04 +0200
committerSven Gothel <[email protected]>2021-09-15 10:50:04 +0200
commit9ce665e96f5b87d83e909330f262378810a8cbb3 (patch)
tree74484ccdde505c758bd5d0f99da78e49ebe20178
parent9b69298eb95b7a0dd7a0d28103fd9b4d03c0a06a (diff)
Multi Direct-BT application, each using 1 adapter: Have user explicitly initialize adapter with given BTMode, leave others untouched.
Only mutating the desired adapter within one application allows running multiple Direct-BT applications on one platform, each using one selected adapter. BTMode: - Use byte value, matching native counterpart BTManager: - Remove (default) BTMode BTAdapter: - Add initialze(const BTMode btMode=BTMode::DUAL), must be called by user for desired adapter when found via ChangedAdapterSetFunc/BTManager.ChangedAdapterSetListener. AdapterInfo: - Expose mutable ops to public, remove friend decl.
-rw-r--r--api/direct_bt/BTAdapter.hpp37
-rw-r--r--api/direct_bt/BTDevice.hpp1
-rw-r--r--api/direct_bt/BTManager.hpp45
-rw-r--r--api/direct_bt/BTTypes1.hpp35
-rw-r--r--api/direct_bt/HCIHandler.hpp47
-rw-r--r--api/direct_bt/MgmtTypes.hpp2
-rw-r--r--examples/direct_bt_scanner10/dbt_scanner10.cpp40
-rw-r--r--examples/java/DBTScanner10.java39
-rw-r--r--java/jau/direct_bt/DBTAdapter.java12
-rw-r--r--java/jau/direct_bt/DBTManager.java4
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx13
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx6
-rw-r--r--java/jni/direct_bt/DBTManager.cxx5
-rw-r--r--java/org/direct_bt/BTAdapter.java47
-rw-r--r--java/org/direct_bt/BTFactory.java19
-rw-r--r--java/org/direct_bt/BTMode.java22
-rw-r--r--src/direct_bt/BTAdapter.cpp89
-rw-r--r--src/direct_bt/BTDevice.cpp6
-rw-r--r--src/direct_bt/BTManager.cpp95
-rw-r--r--src/direct_bt/HCIHandler.cpp151
-rw-r--r--src/direct_bt/MgmtTypes.cpp11
21 files changed, 461 insertions, 265 deletions
diff --git a/api/direct_bt/BTAdapter.hpp b/api/direct_bt/BTAdapter.hpp
index 7acd9c41..337a9bd1 100644
--- a/api/direct_bt/BTAdapter.hpp
+++ b/api/direct_bt/BTAdapter.hpp
@@ -254,6 +254,7 @@ namespace direct_bt {
const bool debug_event, debug_lock;
BTManager& mgmt;
AdapterInfo adapterInfo;
+ jau::sc_atomic_bool adapter_initialized;
LE_Features le_features;
bool hci_uses_ext_scan;
bool hci_uses_ext_conn;
@@ -302,7 +303,8 @@ namespace direct_bt {
mutable jau::sc_atomic_bool sync_data;
bool updateDataFromHCI() noexcept;
- bool validateDevInfo() noexcept;
+ bool updateDataFromAdapterInfo() noexcept;
+ bool initialSetup() noexcept;
static std::shared_ptr<BTDevice> findDevice(device_list_t & devices, const EUI48 & address, const BDAddressType addressType) noexcept;
static std::shared_ptr<BTDevice> findDevice(device_list_t & devices, BTDevice const & device) noexcept;
@@ -359,6 +361,7 @@ namespace direct_bt {
void removeSharedDevice(const BTDevice & device) noexcept;
bool mgmtEvNewSettingsMgmt(const MgmtEvent& e) noexcept;
+ bool updateAdapterSettings(const AdapterSetting new_settings, const bool sendEvent, const uint64_t timestamp) noexcept;
bool mgmtEvDeviceDiscoveringMgmt(const MgmtEvent& e) noexcept;
bool mgmtEvLocalNameChangedMgmt(const MgmtEvent& e) noexcept;
bool mgmtEvDeviceFoundHCI(const MgmtEvent& e) noexcept;
@@ -416,8 +419,14 @@ namespace direct_bt {
* Closes this instance, usually being called by destructor or when this adapter is being removed
* as recognized and handled by BTManager.
* <p>
+ * In case initialize() or setPowered(true) has been called, i.e. this adapter has been powered-on by the user,
+ * it will be powered-off.
+ * </p>
+ * <p>
* Renders this adapter's BTAdapter#isValid() state to false.
* </p>
+ * @see initialize()
+ * @see setPowered()
*/
void close() noexcept;
@@ -548,10 +557,36 @@ namespace direct_bt {
/**
* Set the power state of the adapter.
+ * <p>
+ * Calling the method to power-on this adapter will allow close() to power-off the adapter.
+ * </p>
+ * @param value true will power on this adapter, otherwise this adapter will be powered-off.
+ * @return true for success
+ * @see close()
+ * @see initialize()
*/
bool setPowered(bool value) noexcept;
/**
+ * Initialize the adapter with default values, including power-on.
+ * <p>
+ * Method shall be issued on the desired adapter found via ChangedAdapterSetFunc.
+ * </p>
+ * <p>
+ * While initialization, the adapter is first powered-off, setup and then powered-on.
+ * </p>
+ * <p>
+ * Calling the method will allow close() to power-off the adapter.
+ * </p>
+ * @param btMode the desired adapter's BTMode, defaults to BTMode::DUAL
+ * @return HCIStatusCode::SUCCESS or an error state
+ * @see close()
+ * @see setPowered()
+ * @since 2.4.0
+ */
+ HCIStatusCode initialize(const BTMode btMode=BTMode::DUAL) noexcept;
+
+ /**
* Reset the adapter.
* <p>
* The semantics are specific to the HCI host implementation,
diff --git a/api/direct_bt/BTDevice.hpp b/api/direct_bt/BTDevice.hpp
index 2df60a5d..7a0c0785 100644
--- a/api/direct_bt/BTDevice.hpp
+++ b/api/direct_bt/BTDevice.hpp
@@ -63,6 +63,7 @@ namespace direct_bt {
L2CAPComm l2cap_att;
uint64_t ts_last_discovery;
uint64_t ts_last_update;
+ GAPFlags gap_flags;
std::string name;
int8_t rssi = 127; // The core spec defines 127 as the "not available" value
int8_t tx_power = 127; // The core spec defines 127 as the "not available" value
diff --git a/api/direct_bt/BTManager.hpp b/api/direct_bt/BTManager.hpp
index 5cfd16e9..22005be0 100644
--- a/api/direct_bt/BTManager.hpp
+++ b/api/direct_bt/BTManager.hpp
@@ -69,7 +69,6 @@ namespace direct_bt {
private:
const bool exploding; // just to trigger exploding properties
- static BTMode getEnvBTMode();
public:
/**
@@ -104,17 +103,6 @@ namespace direct_bt {
*/
const bool DEBUG_EVENT;
- /**
- * Default {@link BTMode} when initializing new adapter
- * <p>
- * Environment variable is 'direct_bt.mgmt.btmode' first, then try 'org.tinyb.btmode'.
- * </p>
- * <p>
- * Default is BTMode::DUAL, if non of the above environment variable is set.
- * </p>
- */
- const BTMode DEFAULT_BTMODE;
-
private:
/** Maximum number of packets to wait for until matching a sequential command. Won't block as timeout will limit. */
const int32_t MGMT_READ_PACKET_MAX_RETRY;
@@ -230,7 +218,6 @@ namespace direct_bt {
jau::darray<std::shared_ptr<WhitelistElem>> whitelist;
const MgmtEnv & env;
- const BTMode defaultBTMode;
POctets rbuffer;
HCIComm comm;
@@ -277,16 +264,13 @@ namespace direct_bt {
/**
* Instantiate singleton.
- * @param btMode default {@link BTMode} when initializing new adapter. If BTMode::NONE given, MgmtEnv::DEFAULT_BTMODE is being used.
*/
- BTManager(const BTMode defaultBTMode) noexcept;
+ BTManager() noexcept;
BTManager(const BTManager&) = delete;
void operator=(const BTManager&) = delete;
- void setAdapterMode(const uint16_t dev_id, const uint8_t ssp, const uint8_t bredr, const uint8_t le) noexcept;
- std::unique_ptr<AdapterInfo> initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept;
- void shutdownAdapter(BTAdapter& adapter) noexcept;
+ std::unique_ptr<AdapterInfo> readAdapterInfo(const uint16_t dev_id) noexcept;
void processAdapterAdded(std::unique_ptr<MgmtEvent> e) noexcept;
void processAdapterRemoved(std::unique_ptr<MgmtEvent> e) noexcept;
@@ -314,10 +298,9 @@ namespace direct_bt {
* <p>
* First call will open and initialize the bluetooth kernel.
* </p>
- * @param btMode default {@link BTMode} when initializing new adapter. If BTMode::NONE given (default), MgmtEnv::DEFAULT_BTMODE is being used.
* @return singleton instance.
*/
- static BTManager& get(const BTMode defaultBTMode=BTMode::NONE) {
+ static BTManager& get() {
/**
* Thread safe starting with C++11 6.7:
*
@@ -328,7 +311,7 @@ namespace direct_bt {
*
* Avoiding non-working double checked locking.
*/
- static BTManager s(defaultBTMode);
+ static BTManager s;
return s;
}
~BTManager() noexcept { close(); }
@@ -342,16 +325,13 @@ namespace direct_bt {
return std::string(JAVA_DBT_PACKAGE "DBTManager");
}
- /** Returns the default {@link BTMode}, adapters are tried to be initialized. */
- BTMode getDefaultBTMode() noexcept { return defaultBTMode; }
-
/** Returns true if this mgmt instance is open and hence valid, otherwise false */
bool isOpen() const noexcept {
return comm.isOpen();
}
std::string toString() const noexcept override {
- return "MgmtHandler[BTMode "+to_string(defaultBTMode)+", "+std::to_string(adapters.size())+" adapter, "+javaObjectToString()+"]";
+ return "MgmtHandler["+std::to_string(adapters.size())+" adapter, "+javaObjectToString()+"]";
}
/** retrieve information gathered at startup */
@@ -386,6 +366,21 @@ namespace direct_bt {
bool setMode(const uint16_t dev_id, const MgmtCommand::Opcode opc, const uint8_t mode, AdapterSetting& current_settings) noexcept;
MgmtStatus setDiscoverable(const uint16_t dev_id, const uint8_t state, const uint16_t timeout, AdapterSetting& current_settings) noexcept;
+ /**
+ * Initialize the adapter with default values, including power-on.
+ * <p>
+ * Method shall be issued on the desired adapter found via ChangedAdapterSetFunc.
+ * </p>
+ * <p>
+ * While initialization, the adapter is first powered-off, setup and then powered-on.
+ * </p>
+ * @param dev_id the adapter's device id
+ * @param btMode the desired adapter's BTMode, defaults to BTMode::DUAL
+ * @param adapterInfo reference for the AdapterInfo, updated to reflect the new initialized values.
+ * @return HCIStatusCode::SUCCESS or an error state
+ */
+ HCIStatusCode initializeAdapter(AdapterInfo& adapterInfo, const uint16_t dev_id, const BTMode btMode=BTMode::DUAL) noexcept;
+
/** Start discovery on given adapter dev_id with a ScanType matching the given BTMode. Returns set ScanType. */
ScanType startDiscovery(const uint16_t dev_id, const BTMode btMode) noexcept;
/** Start discovery on given adapter dev_id with given ScanType. Returns set ScanType. */
diff --git a/api/direct_bt/BTTypes1.hpp b/api/direct_bt/BTTypes1.hpp
index b5225f4c..d2336b6f 100644
--- a/api/direct_bt/BTTypes1.hpp
+++ b/api/direct_bt/BTTypes1.hpp
@@ -186,9 +186,6 @@ namespace direct_bt {
class AdapterInfo
{
- friend class BTManager; // top manager
- friend class BTAdapter; // direct manager
-
public:
const uint16_t dev_id;
/**
@@ -209,20 +206,6 @@ namespace direct_bt {
std::string name;
std::string short_name;
- /**
- * Assigns the given 'new_setting & supported_setting' to the current_setting.
- * @param new_setting assigned to current_setting after masking with supported_setting.
- * @return 'new_setting & supported_setting', i.e. the new current_setting.
- */
- AdapterSetting setCurrentSettingMask(const AdapterSetting new_setting) noexcept {
- const AdapterSetting _current_setting = new_setting & supported_setting;
- current_setting = _current_setting;
- return _current_setting;
- }
- void setDevClass(const uint32_t v) noexcept { dev_class = v; }
- void setName(const std::string v) noexcept { name = v; }
- void setShortName(const std::string v) noexcept { short_name = v; }
-
public:
AdapterInfo(const uint16_t dev_id_, const BDAddressAndType & addressAndType_,
const uint8_t version_, const uint16_t manufacturer_,
@@ -264,6 +247,24 @@ namespace direct_bt {
{ }
AdapterInfo& operator=(AdapterInfo &&o) noexcept = delete;
+ /**
+ * Assigns the given 'new_setting & supported_setting' to the current_setting.
+ * @param new_setting assigned to current_setting after masking with supported_setting.
+ * @return 'new_setting & supported_setting', i.e. the new current_setting.
+ */
+ AdapterSetting setCurrentSettingMask(const AdapterSetting new_setting) noexcept {
+ const AdapterSetting _current_setting = new_setting & supported_setting;
+ current_setting = _current_setting;
+ return _current_setting;
+ }
+ void setSettingMasks(const AdapterSetting supported_setting_, const AdapterSetting current_setting_) noexcept {
+ supported_setting = supported_setting_;
+ current_setting = current_setting_;
+ }
+ void setDevClass(const uint32_t v) noexcept { dev_class = v; }
+ void setName(const std::string v) noexcept { name = v; }
+ void setShortName(const std::string v) noexcept { short_name = v; }
+
constexpr const AdapterSetting& get_supportedSetting() const noexcept { return supported_setting; }
bool isSettingMaskSupported(const AdapterSetting setting) const noexcept {
diff --git a/api/direct_bt/HCIHandler.hpp b/api/direct_bt/HCIHandler.hpp
index 9fb5716b..352add0d 100644
--- a/api/direct_bt/HCIHandler.hpp
+++ b/api/direct_bt/HCIHandler.hpp
@@ -255,6 +255,7 @@ namespace direct_bt {
std::recursive_mutex mtx_sendReply; // for sendWith*Reply, process*Command, ..; Recurses from many..
+ LE_Features le_ll_feats;
/**
* Cached bitfield of Local Supported Commands, 64 octets
* <pre>
@@ -277,9 +278,6 @@ namespace direct_bt {
/** Exclusive [le] connection command (status + pending completed) one at a time */
std::mutex mtx_connect_cmd;
- void zeroSupCommands() noexcept;
- bool initSupCommands() noexcept;
-
/**
* Returns a newly added HCIConnectionRef tracker connection with given parameters, if not existing yet.
* <p>
@@ -334,18 +332,20 @@ namespace direct_bt {
std::unique_ptr<const SMPPDUMsg> getSMPPDUMsg(const HCIACLData::l2cap_frame & l2cap, const uint8_t * l2cap_data) const noexcept;
void hciReaderThreadImpl() noexcept;
- bool sendCommand(HCICommand &req) noexcept;
+ bool sendCommand(HCICommand &req, const bool quiet=false) noexcept;
std::unique_ptr<HCIEvent> getNextReply(HCICommand &req, int32_t & retryCount, const int32_t replyTimeoutMS) noexcept;
std::unique_ptr<HCIEvent> getNextCmdCompleteReply(HCICommand &req, HCICommandCompleteEvent **res) noexcept;
- std::unique_ptr<HCIEvent> processCommandStatus(HCICommand &req, HCIStatusCode *status) noexcept;
+ std::unique_ptr<HCIEvent> processCommandStatus(HCICommand &req, HCIStatusCode *status, const bool quiet=false) noexcept;
template<typename hci_cmd_event_struct>
std::unique_ptr<HCIEvent> processCommandComplete(HCICommand &req,
- const hci_cmd_event_struct **res, HCIStatusCode *status) noexcept;
+ const hci_cmd_event_struct **res, HCIStatusCode *status,
+ const bool quiet=false) noexcept;
template<typename hci_cmd_event_struct>
std::unique_ptr<HCIEvent> receiveCommandComplete(HCICommand &req,
- const hci_cmd_event_struct **res, HCIStatusCode *status) noexcept;
+ const hci_cmd_event_struct **res, HCIStatusCode *status,
+ const bool quiet=false) noexcept;
template<typename hci_cmd_event_struct>
const hci_cmd_event_struct* getReplyStruct(HCIEvent& event, HCIEventType evc, HCIStatusCode *status) noexcept;
@@ -356,6 +356,21 @@ namespace direct_bt {
public:
HCIHandler(const uint16_t dev_id, const BTMode btMode=BTMode::NONE) noexcept;
+ private:
+ void zeroSupCommands() noexcept;
+ bool initSupCommands() noexcept;
+
+ public:
+ /**
+ * Reset all internal states, i.e. connection and disconnect lists.
+ * <p>
+ * Must be explicitly called with `powered_on=true` when adapter is powered on!
+ * </p>
+ * @param powered_on indicates whether the adapter is powered on or not
+ * @see initSupCommands()
+ */
+ bool resetAllStates(const bool powered_on) noexcept;
+
HCIHandler(const HCIHandler&) = delete;
void operator=(const HCIHandler&) = delete;
@@ -376,16 +391,21 @@ namespace direct_bt {
}
/** Use extended scanning if HCI_LE_Set_Extended_Scan_Parameters and HCI_LE_Set_Extended_Scan_Enable is supported (Bluetooth 5.0). */
- bool use_ext_scan() const noexcept{
+ bool use_ext_scan() const noexcept {
return 0 != ( sup_commands[37] & ( 1 << 5 ) ) &&
0 != ( sup_commands[37] & ( 1 << 6 ) );
}
/** Use extended connection if HCI_LE_Extended_Create_Connection is supported (Bluetooth 5.0). */
- bool use_ext_conn() const noexcept{
+ bool use_ext_conn() const noexcept {
return 0 != ( sup_commands[37] & ( 1 << 7 ) );
}
+ /** Use extended advertising if LE_Features::LE_Ext_Adv is set (Bluetooth 5.0). */
+ bool use_ext_adv() const noexcept {
+ return isLEFeaturesBitSet(le_ll_feats, LE_Features::LE_Ext_Adv);
+ }
+
ScanType getCurrentScanType() const noexcept { return currentScanType.load(); }
void setCurrentScanType(const ScanType v) noexcept { currentScanType = v; }
@@ -432,7 +452,7 @@ namespace direct_bt {
HCIStatusCode getLocalVersion(HCILocalVersion &version) noexcept;
/**
- * Request and return LE_Features for the controller.
+ * Return previously fetched LE_Features for the controller via initSupCommands() via resetAllStates()
* <pre>
* BT Core Spec v5.2: Vol 6, Part B, 4.6 (LE LL) Feature Support
*
@@ -440,9 +460,12 @@ namespace direct_bt {
* </pre>
* @param res reference for the resulting LE_Features
* @return HCIStatusCode
+ * @see initSupCommands()
+ * @see resetAllStates()
*/
- HCIStatusCode le_read_local_features(LE_Features& res) noexcept;
+ LE_Features le_get_local_features() noexcept { return le_ll_feats; }
+ private:
/**
* Sets LE scanning parameters.
* <pre>
@@ -473,6 +496,7 @@ namespace direct_bt {
const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24,
const uint8_t filter_policy=0x00) noexcept;
+ public:
/**
* Starts or stops LE scanning.
* <pre>
@@ -621,7 +645,6 @@ namespace direct_bt {
* Reset all internal states, i.e. connection and disconnect lists.
* @param powered_on indicates whether the adapter is powered on or not
*/
- void resetAllStates(const bool powered_on) noexcept;
/** MgmtEventCallback handling */
diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp
index 21fd5518..4240a75d 100644
--- a/api/direct_bt/MgmtTypes.hpp
+++ b/api/direct_bt/MgmtTypes.hpp
@@ -2226,7 +2226,7 @@ namespace direct_bt {
std::string getShortName() const noexcept { return pdu.get_string_nc(getDataOffset()+20+MgmtConstU16::MGMT_MAX_NAME_LENGTH); }
std::unique_ptr<AdapterInfo> toAdapterInfo() const noexcept;
-
+ bool updateAdapterInfo(AdapterInfo& info) const noexcept;
};
typedef jau::FunctionDef<bool, const MgmtEvent&> MgmtEventCallback;
diff --git a/examples/direct_bt_scanner10/dbt_scanner10.cpp b/examples/direct_bt_scanner10/dbt_scanner10.cpp
index 396788c6..7dd74f71 100644
--- a/examples/direct_bt_scanner10/dbt_scanner10.cpp
+++ b/examples/direct_bt_scanner10/dbt_scanner10.cpp
@@ -105,6 +105,9 @@ const static std::string KEY_PATH = "keys";
static uint64_t timestamp_t0;
+static EUI48 useAdapter = EUI48::ALL_DEVICE;
+static BTMode btMode = BTMode::DUAL;
+
static int RESET_ADAPTER_EACH_CONN = 0;
static std::atomic<int> deviceReadyCount = 0;
@@ -635,12 +638,29 @@ static const uint16_t le_scan_window = 24; // default value
static const uint8_t filter_policy = 0; // default value
static bool startDiscovery(BTAdapter *a, std::string msg) {
+ if( useAdapter != EUI48::ALL_DEVICE && useAdapter != a->getAddressAndType().address ) {
+ fprintf_td(stderr, "****** Start discovery (%s): Adapter not selected: %s\n", msg.c_str(), a->toString().c_str());
+ return false;
+ }
HCIStatusCode status = a->startDiscovery( true, le_scan_active, le_scan_interval, le_scan_window, filter_policy );
- fprintf_td(stderr, "****** Start discovery (%s) result: %s\n", msg.c_str(), to_string(status).c_str());
+ fprintf_td(stderr, "****** Start discovery (%s) result: %s: %s\n", msg.c_str(), to_string(status).c_str(), a->toString().c_str());
return HCIStatusCode::SUCCESS == status;
}
static bool initAdapter(std::shared_ptr<BTAdapter>& adapter) {
+ if( useAdapter != EUI48::ALL_DEVICE && useAdapter != adapter->getAddressAndType().address ) {
+ fprintf_td(stderr, "initAdapter: Adapter not selected: %s\n", adapter->toString().c_str());
+ return false;
+ }
+ // Initialize with defaults and power-on
+ {
+ HCIStatusCode status = adapter->initialize( btMode );
+ if( HCIStatusCode::SUCCESS != status ) {
+ fprintf_td(stderr, "initAdapter: Adapter initialization failed: %s: %s\n",
+ to_string(status).c_str(), adapter->toString().c_str());
+ return false;
+ }
+ }
// Even if adapter is not yet powered, listen to it and act when it gets powered-on
adapter->addStatusListener(std::shared_ptr<AdapterStatusListener>(new MyAdapterStatusListener()));
// Flush discovered devices after registering our status listener.
@@ -648,17 +668,17 @@ static bool initAdapter(std::shared_ptr<BTAdapter>& adapter) {
adapter->removeDiscoveredDevices();
if( !adapter->isPowered() ) { // should have been covered above
- fprintf_td(stderr, "Adapter not powered (2): %s\n", adapter->toString().c_str());
+ fprintf_td(stderr, "initAdapter: Adapter not powered (2): %s\n", adapter->toString().c_str());
return false;
}
if( USE_WHITELIST ) {
for (auto it = WHITELIST.begin(); it != WHITELIST.end(); ++it) {
bool res = adapter->addDeviceToWhitelist(*it, HCIWhitelistConnectType::HCI_AUTO_CONN_ALWAYS);
- fprintf_td(stderr, "Added to WHITELIST: res %d, address %s\n", res, it->toString().c_str());
+ fprintf_td(stderr, "initAdapter: Added to WHITELIST: res %d, address %s\n", res, it->toString().c_str());
}
} else {
- if( !startDiscovery(adapter.get(), "kick-off") ) {
+ if( !startDiscovery(adapter.get(), "initAdapter") ) {
return false;
}
}
@@ -729,7 +749,6 @@ void test() {
int main(int argc, char *argv[])
{
- BTMode btMode = BTMode::DUAL;
bool waitForEnter=false;
for(int i=1; i<argc; i++) {
@@ -745,11 +764,6 @@ int main(int argc, char *argv[])
setenv("direct_bt.hci", argv[++i], 1 /* overwrite */);
} else if( !strcmp("-dbt_mgmt", argv[i]) && argc > (i+1) ) {
setenv("direct_bt.mgmt", argv[++i], 1 /* overwrite */);
- } else if( !strcmp("-btmode", argv[i]) && argc > (i+1) ) {
- btMode = to_BTMode(argv[++i]);
- if( BTMode::NONE != btMode ) {
- setenv("direct_bt.mgmt.btmode", to_string(btMode).c_str(), 1 /* overwrite */);
- }
} else if( !strcmp("-wait", argv[i]) ) {
waitForEnter = true;
} else if( !strcmp("-show_update_events", argv[i]) ) {
@@ -758,6 +772,10 @@ int main(int argc, char *argv[])
QUIET = true;
} else if( !strcmp("-scanPassive", argv[i]) ) {
le_scan_active = false;
+ } else if( !strcmp("-btmode", argv[i]) && argc > (i+1) ) {
+ btMode = to_BTMode(argv[++i]);
+ } else if( !strcmp("-adapter", argv[i]) && argc > (i+1) ) {
+ useAdapter = EUI48( std::string(argv[++i]) );
} else if( !strcmp("-dev", argv[i]) && argc > (i+1) ) {
std::string addrOrNameSub = std::string(argv[++i]);
BTDeviceRegistry::addToWaitForDevices( addrOrNameSub );
@@ -811,6 +829,7 @@ int main(int argc, char *argv[])
"[-disconnect] [-enableGATTPing] [-count <number>] [-single] [-show_update_events] [-quiet] "
"[-scanPassive]"
"[-resetEachCon connectionCount] "
+ "[-adapter <adapter_address>] "
"(-dev <device_[address|name]_sub>)* (-wl <device_address>)* "
"(-seclevel <device_[address|name]_sub> <int_sec_level>)* "
"(-iocap <device_[address|name]_sub> <int_iocap>)* "
@@ -834,6 +853,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "USE_WHITELIST %d\n", USE_WHITELIST);
fprintf(stderr, "SHOW_UPDATE_EVENTS %d\n", SHOW_UPDATE_EVENTS);
fprintf(stderr, "QUIET %d\n", QUIET);
+ fprintf(stderr, "adapter %s\n", useAdapter.toString().c_str());
fprintf(stderr, "btmode %s\n", to_string(btMode).c_str());
fprintf(stderr, "scanActive %s\n", to_string(le_scan_active).c_str());
fprintf(stderr, "characteristic-id: %s\n", charIdentifier.c_str());
diff --git a/examples/java/DBTScanner10.java b/examples/java/DBTScanner10.java
index 0caabfdc..fa5c63e3 100644
--- a/examples/java/DBTScanner10.java
+++ b/examples/java/DBTScanner10.java
@@ -80,6 +80,9 @@ public class DBTScanner10 {
long timestamp_t0;
+ EUI48 useAdapter = EUI48.ALL_DEVICE;
+ BTMode btMode = BTMode.DUAL;
+
int RESET_ADAPTER_EACH_CONN = 0;
AtomicInteger deviceReadyCount = new AtomicInteger(0);
@@ -639,12 +642,29 @@ public class DBTScanner10 {
static final byte filter_policy = (byte)0; // default value
private boolean startDiscovery(final BTAdapter adapter, final String msg) {
+ if( !useAdapter.equals(EUI48.ALL_DEVICE) && !useAdapter.equals(adapter.getAddressAndType().address) ) {
+ BTUtils.fprintf_td(System.err, "****** Start discovery (%s): Adapter not selected: %s\n", msg, adapter.toString());
+ return false;
+ }
final HCIStatusCode status = adapter.startDiscovery( true, le_scan_active, le_scan_interval, le_scan_window, filter_policy );
BTUtils.println(System.err, "****** Start discovery ("+msg+") result: "+status);
return HCIStatusCode.SUCCESS == status;
}
private boolean initAdapter(final BTAdapter adapter) {
+ if( !useAdapter.equals(EUI48.ALL_DEVICE) && !useAdapter.equals(adapter.getAddressAndType().address) ) {
+ BTUtils.fprintf_td(System.err, "initAdapter: Adapter not selected: %s\n", adapter.toString());
+ return false;
+ }
+ // Initialize with defaults and power-on
+ {
+ final HCIStatusCode status = adapter.initialize( btMode );
+ if( HCIStatusCode.SUCCESS != status ) {
+ BTUtils.fprintf_td(System.err, "initAdapter: Adapter initialization failed: %s: %s\n",
+ status.toString(), adapter.toString());
+ return false;
+ }
+ }
// Even if adapter is not yet powered, listen to it and act when it gets powered-on
adapter.addStatusListener(new MyAdapterStatusListener() );
// Flush discovered devices after registering our status listener.
@@ -652,7 +672,7 @@ public class DBTScanner10 {
adapter.removeDiscoveredDevices();
if( !adapter.isPowered() ) { // should have been covered above
- BTUtils.println(System.err, "Adapter not powered (2): "+adapter.toString());
+ BTUtils.println(System.err, "initAdapter: Adapter not powered (2): "+adapter.toString());
return false;
}
@@ -660,10 +680,10 @@ public class DBTScanner10 {
for(final Iterator<BDAddressAndType> wliter = whitelist.iterator(); wliter.hasNext(); ) {
final BDAddressAndType addr = wliter.next();
final boolean res = adapter.addDeviceToWhitelist(addr, HCIWhitelistConnectType.HCI_AUTO_CONN_ALWAYS);
- BTUtils.println(System.err, "Added to whitelist: res "+res+", address "+addr);
+ BTUtils.println(System.err, "initAdapter: Added to whitelist: res "+res+", address "+addr);
}
} else {
- if( !startDiscovery(adapter, "kick-off") ) {
+ if( !startDiscovery(adapter, "initAdapter") ) {
return false;
}
}
@@ -758,10 +778,6 @@ public class DBTScanner10 {
System.setProperty("direct_bt.hci", args[++i]);
} else if( arg.equals("-dbt_mgmt") && args.length > (i+1) ) {
System.setProperty("direct_bt.mgmt", args[++i]);
- } else if( arg.equals("-btmode") && args.length > (i+1) ) {
- final BTMode btmode = BTMode.get(args[++i]);
- System.setProperty("org.tinyb.btmode", btmode.toString());
- System.err.println("Setting 'org.tinyb.btmode' to "+btmode.toString());
}
}
final BTManager manager;
@@ -796,6 +812,10 @@ public class DBTScanner10 {
le_scan_active = false;
} else if( arg.equals("-shutdown") && args.length > (i+1) ) {
test.shutdownTest = Integer.valueOf(args[++i]).intValue();
+ } else if( arg.equals("-btmode") && args.length > (i+1) ) {
+ test.btMode = BTMode.get(args[++i]);
+ } else if( arg.equals("-adapter") && args.length > (i+1) ) {
+ test.useAdapter = new EUI48( args[++i] );
} else if( arg.equals("-dev") && args.length > (i+1) ) {
BTDeviceRegistry.addToWaitForDevices( args[++i] );
} else if( arg.equals("-wl") && args.length > (i+1) ) {
@@ -845,10 +865,10 @@ public class DBTScanner10 {
}
}
BTUtils.println(System.err, "Run with '[-btmode LE|BREDR|DUAL] "+
- "[-bluetoothManager <BluetoothManager-Implementation-Class-Name>] "+
"[-disconnect] [-enableGATTPing] [-count <number>] [-single] [-show_update_events] [-quiet] "+
"[-scanPassive]"+
"[-resetEachCon connectionCount] "+
+ "[-adapter <adapter_address>] "+
"(-dev <device_[address|name]_sub>)* (-wl <device_address>)* "+
"(-seclevel <device_[address|name]_sub> <int_sec_level>)* "+
"(-iocap <device_[address|name]_sub> <int_iocap>)* "+
@@ -873,6 +893,9 @@ public class DBTScanner10 {
BTUtils.println(System.err, "USE_WHITELIST "+test.USE_WHITELIST);
BTUtils.println(System.err, "SHOW_UPDATE_EVENTS "+test.SHOW_UPDATE_EVENTS);
BTUtils.println(System.err, "QUIET "+test.QUIET);
+ BTUtils.println(System.err, "adapter "+test.useAdapter);
+ BTUtils.println(System.err, "btmode' to "+test.btMode.toString());
+
BTUtils.println(System.err, "characteristic-id: "+test.charIdentifier);
BTUtils.println(System.err, "characteristic-value: "+test.charValue);
diff --git a/java/jau/direct_bt/DBTAdapter.java b/java/jau/direct_bt/DBTAdapter.java
index 994a2539..e12c090c 100644
--- a/java/jau/direct_bt/DBTAdapter.java
+++ b/java/jau/direct_bt/DBTAdapter.java
@@ -44,6 +44,7 @@ import org.direct_bt.BTGattChar;
import org.direct_bt.BTGattDesc;
import org.direct_bt.BTGattService;
import org.direct_bt.BTManager;
+import org.direct_bt.BTMode;
import org.direct_bt.BTObject;
import org.direct_bt.BTType;
import org.direct_bt.BTUtils;
@@ -233,6 +234,17 @@ public class DBTAdapter extends DBTObject implements BTAdapter
public native boolean setPowered(boolean value);
@Override
+ public final HCIStatusCode initialize() {
+ return initialize(BTMode.DUAL);
+ }
+
+ @Override
+ public final HCIStatusCode initialize(final BTMode btMode) {
+ return HCIStatusCode.get( initializeImpl(btMode.value) );
+ }
+ private native byte initializeImpl(final byte btModeInt);
+
+ @Override
public final HCIStatusCode reset() {
return HCIStatusCode.get( resetImpl() );
}
diff --git a/java/jau/direct_bt/DBTManager.java b/java/jau/direct_bt/DBTManager.java
index 9a943a8d..37972726 100644
--- a/java/jau/direct_bt/DBTManager.java
+++ b/java/jau/direct_bt/DBTManager.java
@@ -370,11 +370,11 @@ public class DBTManager implements BTManager
}
}
- private native void initImpl(final boolean unifyUUID128Bit, final int btMode) throws BTException;
+ private native void initImpl(final boolean unifyUUID128Bit) throws BTException;
private native void deleteImpl(long nativeInstance);
private DBTManager()
{
- initImpl(unifyUUID128Bit, BTFactory.DEFAULT_BTMODE.value);
+ initImpl(unifyUUID128Bit);
try {
adapters.addAll(getAdapterListImpl());
} catch (final BTException be) {
diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx
index 5fceee87..028011fe 100644
--- a/java/jni/direct_bt/DBTAdapter.cxx
+++ b/java/jni/direct_bt/DBTAdapter.cxx
@@ -855,6 +855,19 @@ jboolean Java_jau_direct_1bt_DBTAdapter_setPowered(JNIEnv *env, jobject obj, jbo
return JNI_FALSE;
}
+jbyte Java_jau_direct_1bt_DBTAdapter_initializeImpl(JNIEnv *env, jobject obj, jbyte jbtMode) {
+ try {
+ BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
+ jau::JavaGlobalObj::check(adapter->getJavaObject(), E_FILE_LINE);
+ const BTMode btMode = static_cast<BTMode>(jbtMode);
+ HCIStatusCode res = adapter->initialize(btMode);
+ return (jbyte) number(res);
+ } catch(...) {
+ rethrow_and_raise_java_exception(env);
+ }
+ return (jbyte) number(HCIStatusCode::INTERNAL_FAILURE);
+}
+
jbyte Java_jau_direct_1bt_DBTAdapter_resetImpl(JNIEnv *env, jobject obj) {
try {
BTAdapter *adapter = jau::getJavaUplinkObject<BTAdapter>(env, obj);
diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx
index 13d965f4..a76c0e4d 100644
--- a/java/jni/direct_bt/DBTDevice.cxx
+++ b/java/jni/direct_bt/DBTDevice.cxx
@@ -718,9 +718,9 @@ jobject Java_jau_direct_1bt_DBTDevice_getManufacturerData(JNIEnv *env, jobject o
if( nullptr != mdata ) {
result = env->NewObject(map_cls, map_ctor, 1);
- jbyteArray arr = env->NewByteArray(mdata->data.getSize());
- env->SetByteArrayRegion(arr, 0, mdata->data.getSize(), (const jbyte *)mdata->data.get_ptr());
- jobject key = env->NewObject(short_cls, short_ctor, mdata->company);
+ jbyteArray arr = env->NewByteArray(mdata->getData().getSize());
+ env->SetByteArrayRegion(arr, 0, mdata->getData().getSize(), (const jbyte *)mdata->getData().get_ptr());
+ jobject key = env->NewObject(short_cls, short_ctor, mdata->getCompany());
env->CallObjectMethod(result, map_put, key, arr);
env->DeleteLocalRef(arr);
diff --git a/java/jni/direct_bt/DBTManager.cxx b/java/jni/direct_bt/DBTManager.cxx
index b35fe37a..985cb5b8 100644
--- a/java/jni/direct_bt/DBTManager.cxx
+++ b/java/jni/direct_bt/DBTManager.cxx
@@ -109,12 +109,11 @@ static void _addMgmtCBOnce(JNIEnv *env, BTManager & mgmt, JNIGlobalRef jmgmtRef,
}
}
-void Java_jau_direct_1bt_DBTManager_initImpl(JNIEnv *env, jobject obj, jboolean unifyUUID128Bit, jint jbtMode)
+void Java_jau_direct_1bt_DBTManager_initImpl(JNIEnv *env, jobject obj, jboolean unifyUUID128Bit)
{
directBTJNISettings.setUnifyUUID128Bit(unifyUUID128Bit);
try {
- BTMode btMode = static_cast<BTMode>(jbtMode);
- BTManager *manager = &BTManager::get(btMode); // special: static singleton
+ BTManager *manager = &BTManager::get(); // special: static singleton
setInstance<BTManager>(env, obj, manager);
java_exception_check_and_throw(env, E_FILE_LINE);
manager->setJavaObject( std::shared_ptr<JavaAnon>( new JavaGlobalObj(obj, nullptr) ) );
diff --git a/java/org/direct_bt/BTAdapter.java b/java/org/direct_bt/BTAdapter.java
index 7464a026..8c945349 100644
--- a/java/org/direct_bt/BTAdapter.java
+++ b/java/org/direct_bt/BTAdapter.java
@@ -309,12 +309,59 @@ public interface BTAdapter extends BTObject
/**
* Sets the power state the adapter.
+ * <p>
+ * Calling the method to power-on this adapter will allow close() to power-off the adapter.
+ * </p>
* @apiNote return value boolean since 2.0.0
+ * @see #close()
+ * @see #initialize(BTMode)
* @since 2.0.0
*/
public boolean setPowered(boolean value);
/**
+ * Initialize the adapter with default values, including power-on.
+ * <p>
+ * Method shall be issued on the desired adapter found via {@link BTManager.ChangedAdapterSetListener}.
+ * </p>
+ * <p>
+ * While initialization, the adapter is first powered-off, setup and then powered-on.
+ * </p>
+ * <p>
+ * Calling the method will allow close() to power-off the adapter.
+ * </p>
+ * <p>
+ * This override uses {@link BTMode#DUAL}
+ * </p>
+ * @return {@link HCIStatusCode#SUCCESS} or an error state
+ * @see #initialize(BTMode)
+ * @see #close()
+ * @see #setPowered(boolean)
+ * @since 2.4.0
+ */
+ public HCIStatusCode initialize();
+
+ /**
+ * Initialize the adapter with default values, including power-on.
+ * <p>
+ * Method shall be issued on the desired adapter found via {@link BTManager.ChangedAdapterSetListener}.
+ * </p>
+ * <p>
+ * While initialization, the adapter is first powered-off, setup and then powered-on.
+ * </p>
+ * <p>
+ * Calling the method will allow close() to power-off the adapter.
+ * </p>
+ * @param btMode the desired adapter's {@link BTMode}, default shall be {@link BTMode#DUAL}
+ * @return {@link HCIStatusCode#SUCCESS} or an error state
+ * @see #initialize()
+ * @see #close()
+ * @see #setPowered(boolean)
+ * @since 2.4.0
+ */
+ public HCIStatusCode initialize(final BTMode btMode);
+
+ /**
* Reset the adapter.
* <p>
* The semantics are specific to the HCI host implementation,
diff --git a/java/org/direct_bt/BTFactory.java b/java/org/direct_bt/BTFactory.java
index f66cbd5b..4a29988d 100644
--- a/java/org/direct_bt/BTFactory.java
+++ b/java/org/direct_bt/BTFactory.java
@@ -147,15 +147,6 @@ public class BTFactory {
public static final boolean DEBUG;
/**
- * Default {@link BTMode} when initializing new adapter
- * <p>
- * System property {@code org.direct_bt.btmode}, string, default {@code DUAL} {@link BTMode#DUAL}.
- * </p>
- * @since 2.0.0
- */
- public static final BTMode DEFAULT_BTMODE;
-
- /**
* True if jaulib {@link org.jau.sys.PlatformProps} has been detected.
*/
public static final boolean JAULIB_AVAILABLE;
@@ -177,16 +168,6 @@ public class BTFactory {
final String v = System.getProperty("org.direct_bt.verbose", "false");
VERBOSE = Boolean.valueOf(v);
}
- {
- final String v = System.getProperty("org.direct_bt.btmode", "DUAL");
- BTMode btMode = BTMode.DUAL;
- try {
- btMode = BTMode.get(v);
- } catch (final IllegalArgumentException ex) {
- System.err.println("Invalid BTMode '"+v+"': "+ex.getMessage());
- }
- DEFAULT_BTMODE = btMode;
- }
implIDs.add(DirectBTImplementationID);
boolean isJaulibAvail = false;
diff --git a/java/org/direct_bt/BTMode.java b/java/org/direct_bt/BTMode.java
index cbdecbab..2395efec 100644
--- a/java/org/direct_bt/BTMode.java
+++ b/java/org/direct_bt/BTMode.java
@@ -27,21 +27,21 @@ package org.direct_bt;
/**
* Bluetooth adapter operating mode
* <p>
- * See {@link #get(int)} for its native integer mapping.
+ * See {@link #get(byte)} for its native integer mapping.
* </p>
* @since 2.0.0
*/
public enum BTMode {
/** Zero mode, neither DUAL, BREDR nor LE. Usually an error. */
- NONE (0),
+ NONE ((byte)0),
/** Dual Bluetooth mode, i.e. BREDR + LE. */
- DUAL (1),
+ DUAL ((byte)1),
/** BREDR only Bluetooth mode */
- BREDR (2),
+ BREDR ((byte)2),
/** LE only Bluetooth mode */
- LE (3);
+ LE ((byte)3);
- public final int value;
+ public final byte value;
/**
* Maps the specified name to a constant of BTMode.
@@ -63,16 +63,16 @@ public enum BTMode {
* @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 BTMode get(final int value) {
+ public static BTMode get(final byte value) {
switch(value) {
- case 0x01: return DUAL;
- case 0x02: return BREDR;
- case 0x03: return LE;
+ case (byte)0x01: return DUAL;
+ case (byte)0x02: return BREDR;
+ case (byte)0x03: return LE;
default: return NONE;
}
}
- BTMode(final int v) {
+ BTMode(final byte v) {
value = v;
}
}
diff --git a/src/direct_bt/BTAdapter.cpp b/src/direct_bt/BTAdapter.cpp
index fd460a2f..be3fd51c 100644
--- a/src/direct_bt/BTAdapter.cpp
+++ b/src/direct_bt/BTAdapter.cpp
@@ -127,56 +127,61 @@ bool BTAdapter::updateDataFromHCI() noexcept {
HCILocalVersion version;
HCIStatusCode status = hci.getLocalVersion(version);
if( HCIStatusCode::SUCCESS != status ) {
- ERR_PRINT("BTAdapter::validateDevInfo: Adapter[%d]: POWERED, LocalVersion failed %s - %s",
+ ERR_PRINT("BTAdapter::updateDataFromHCI: Adapter[%d]: POWERED, LocalVersion failed %s - %s",
dev_id, to_string(status).c_str(), adapterInfo.toString().c_str());
return false;
}
- LE_Features le_ll_feats;
- if( HCIStatusCode::SUCCESS != hci.le_read_local_features(le_ll_feats) ) {
- ERR_PRINT("BTAdapter::validateDevInfo: Adapter[%d]: le_read_local_features failed %s - %s",
- dev_id, to_string(status).c_str(), adapterInfo.toString().c_str());
- return false;
- }
- le_features = le_ll_feats;
+ le_features = hci.le_get_local_features();
hci_uses_ext_scan = hci.use_ext_scan();
hci_uses_ext_conn = hci.use_ext_conn();
WORDY_PRINT("BTAdapter::updateDataFromHCI: Adapter[%d]: POWERED, %s - %s, hci_ext[scan %d, conn %d], features: %s",
dev_id, version.toString().c_str(), adapterInfo.toString().c_str(),
hci_uses_ext_scan, hci_uses_ext_conn,
- direct_bt::to_string(le_ll_feats).c_str());
+ direct_bt::to_string(le_features).c_str());
+ return true;
+}
+
+bool BTAdapter::updateDataFromAdapterInfo() noexcept {
+ BTMode btMode = getBTMode();
+ if( BTMode::NONE == btMode ) {
+ WARN_PRINT("BTAdapter::updateDataFromAdapterInfo: Adapter[%d]: BTMode invalid, BREDR nor LE set: %s", dev_id, adapterInfo.toString().c_str());
+ return false;
+ }
+ hci.setBTMode(btMode);
return true;
}
-bool BTAdapter::validateDevInfo() noexcept {
+bool BTAdapter::initialSetup() noexcept {
bool ok = false;
currentMetaScanType = ScanType::NONE;
keep_le_scan_alive = false;
if( !mgmt.isOpen() ) {
- ERR_PRINT("BTAdapter::validateDevInfo: Adapter[%d]: Manager not open", dev_id);
+ ERR_PRINT("BTAdapter::initialSetup: Adapter[%d]: Manager not open", dev_id);
goto errout0;
}
if( !hci.isOpen() ) {
- ERR_PRINT("BTAdapter::validateDevInfo: Adapter[%d]: HCIHandler closed", dev_id);
+ ERR_PRINT("BTAdapter::initialSetup: Adapter[%d]: HCIHandler closed", dev_id);
goto errout0;
}
old_settings = adapterInfo.getCurrentSettingMask();
- btMode = getBTMode();
- if( BTMode::NONE == btMode ) {
- ERR_PRINT("BTAdapter::validateDevInfo: Adapter[%d]: BTMode invalid, BREDR nor LE set: %s", dev_id, adapterInfo.toString().c_str());
+ if( !updateDataFromAdapterInfo() ) {
return false;
}
- hci.setBTMode(btMode);
if( adapterInfo.isCurrentSettingBitSet(AdapterSetting::POWERED) ) {
+ if( !hci.resetAllStates(true) ) {
+ return false;
+ }
if( !updateDataFromHCI() ) {
return false;
}
} else {
- WORDY_PRINT("BTAdapter::validateDevInfo: Adapter[%d]: Not POWERED: %s", dev_id, adapterInfo.toString().c_str());
+ hci.resetAllStates(false);
+ WORDY_PRINT("BTAdapter::initialSetup: Adapter[%d]: Not POWERED: %s", dev_id, adapterInfo.toString().c_str());
}
ok = true;
@@ -226,13 +231,14 @@ BTAdapter::BTAdapter(const BTAdapter::ctor_cookie& cc, BTManager& mgmt_, const A
debug_lock(jau::environment::getBooleanProperty("direct_bt.debug.adapter.lock", false)),
mgmt( mgmt_ ),
adapterInfo( adapterInfo_ ),
+ adapter_initialized( false ),
le_features( LE_Features::NONE ),
visibleAddressAndType( adapterInfo_.addressAndType ),
dev_id( adapterInfo.dev_id ),
hci( dev_id )
{
(void)cc;
- valid = validateDevInfo();
+ valid = initialSetup();
}
BTAdapter::~BTAdapter() noexcept {
@@ -267,6 +273,13 @@ void BTAdapter::close() noexcept {
poweredOff();
+ if( adapter_initialized ) {
+ adapter_initialized = false;
+ if( isPowered() ) {
+ setPowered(false);
+ }
+ }
+
DBG_PRINT("BTAdapter::close: closeHCI: ...");
hci.close();
DBG_PRINT("BTAdapter::close: closeHCI: XXX");
@@ -360,10 +373,22 @@ bool BTAdapter::setBondable(bool value) noexcept {
}
bool BTAdapter::setPowered(bool value) noexcept {
+ if( value ) {
+ adapter_initialized = true;
+ }
AdapterSetting current_settings { AdapterSetting::NONE } ;
return mgmt.setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, value ? 1 : 0, current_settings);
}
+HCIStatusCode BTAdapter::initialize(const BTMode btMode) noexcept {
+ adapter_initialized = true;
+ HCIStatusCode status = mgmt.initializeAdapter(adapterInfo, dev_id, btMode);
+ if( HCIStatusCode::SUCCESS != status ) {
+ return status;
+ }
+ return updateAdapterSettings(adapterInfo.getCurrentSettingMask(), false, 0) ? HCIStatusCode::SUCCESS : HCIStatusCode::FAILED;
+}
+
bool BTAdapter::lockConnect(const BTDevice & device, const bool wait, const SMPIOCapability io_cap) noexcept {
std::unique_lock<std::mutex> lock(mtx_single_conn_device); // RAII-style acquire and relinquish via destructor
const uint32_t timeout_ms = 10000; // FIXME: Configurable?
@@ -955,7 +980,7 @@ void BTAdapter::removeDevice(BTDevice & device) 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(btMode)+", "+adapterInfo.addressAndType.toString()+random_address_info+
+ std::string out("Adapter[BTMode "+to_string(getBTMode())+", "+adapterInfo.addressAndType.toString()+random_address_info+
", '"+getName()+"', id "+std::to_string(dev_id)+
", curSettings"+to_string(adapterInfo.getCurrentSettingMask())+
", scanType[native "+to_string(hci.getCurrentScanType())+", meta "+to_string(currentMetaScanType)+"]"
@@ -1105,12 +1130,11 @@ bool BTAdapter::mgmtEvNewSettingsMgmt(const MgmtEvent& e) noexcept {
COND_PRINT(debug_event, "BTAdapter:mgmt:NewSettings: %s", e.toString().c_str());
const MgmtEvtNewSettings &event = *static_cast<const MgmtEvtNewSettings *>(&e);
const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(event.getSettings()); // probably done by mgmt callback already
- {
- const BTMode _btMode = getAdapterSettingsBTMode(new_settings);
- if( BTMode::NONE != _btMode ) {
- btMode = _btMode;
- }
- }
+
+ return updateAdapterSettings(new_settings, true, event.getTimestamp());
+}
+
+bool BTAdapter::updateAdapterSettings(const AdapterSetting new_settings, const bool sendEvent, const uint64_t timestamp) noexcept {
const AdapterSetting old_settings_ = old_settings;
const AdapterSetting changes = getAdapterSettingMaskDiff(new_settings, old_settings_);
@@ -1123,17 +1147,22 @@ bool BTAdapter::mgmtEvNewSettingsMgmt(const MgmtEvent& e) noexcept {
old_settings = new_settings;
- COND_PRINT(debug_event, "BTAdapter::mgmt:NewSettings: %s -> %s, changes %s: %s",
+ COND_PRINT(debug_event, "BTAdapter::updateAdapterSettings: %s -> %s, changes %s: %s, sendEvent %d",
to_string(old_settings_).c_str(),
to_string(new_settings).c_str(),
- to_string(changes).c_str(), toString().c_str() );
+ to_string(changes).c_str(), toString().c_str(), sendEvent );
+
+ updateDataFromAdapterInfo();
if( justPoweredOn ) {
// Adapter has been powered on, ensure all hci states are reset.
- hci.resetAllStates(true);
- updateDataFromHCI();
+ if( hci.resetAllStates(true) ) {
+ updateDataFromHCI();
+ }
+ }
+ if( sendEvent ) {
+ sendAdapterSettingsChanged(old_settings_, new_settings, changes, timestamp);
}
- sendAdapterSettingsChanged(old_settings_, new_settings, changes, event.getTimestamp());
if( justPoweredOff ) {
// Adapter has been powered off, close connections and cleanup off-thread.
diff --git a/src/direct_bt/BTDevice.cpp b/src/direct_bt/BTDevice.cpp
index 2b19fae7..322ee8da 100644
--- a/src/direct_bt/BTDevice.cpp
+++ b/src/direct_bt/BTDevice.cpp
@@ -150,7 +150,8 @@ std::string BTDevice::toString(bool includeDiscoveredServices) const noexcept {
", auto "+to_string(pairing_data.ioCap_auto)+", pairing "+to_string(pairing_data.mode)+", state "+to_string(pairing_data.state)+"]], rssi "+std::to_string(getRSSI())+
", tx-power "+std::to_string(tx_power)+
", appearance "+jau::to_hexstring(static_cast<uint16_t>(appearance))+" ("+to_string(appearance)+
- "), "+msdstr+", "+javaObjectToString()+"]");
+ "), gap "+direct_bt::to_string(gap_flags)+
+ ", "+msdstr+", "+javaObjectToString()+"]");
if( includeDiscoveredServices ) {
jau::darray<std::shared_ptr<const uuid_t>> _advServices = getAdvertisedServices();
if( _advServices.size() > 0 ) {
@@ -186,6 +187,9 @@ EIRDataType BTDevice::update(EInfoReport const & data) noexcept {
data.toString().c_str(), this->toString().c_str());
}
}
+ if( data.isSet(EIRDataType::FLAGS) ) {
+ gap_flags = data.getFlags();
+ }
if( data.isSet(EIRDataType::NAME) ) {
if( 0 == name.length() || data.getName().length() > name.length() ) {
name = data.getName();
diff --git a/src/direct_bt/BTManager.cpp b/src/direct_bt/BTManager.cpp
index 3f26e379..446fb4d0 100644
--- a/src/direct_bt/BTManager.cpp
+++ b/src/direct_bt/BTManager.cpp
@@ -57,17 +57,6 @@ extern "C" {
using namespace direct_bt;
-BTMode MgmtEnv::getEnvBTMode() {
- // Environment variable is 'direct_bt.mgmt.btmode' or 'org.tinyb.btmode'
- // Default is BTMode::LE, if non of the above environment variable is set.
- std::string val = jau::environment::getProperty("direct_bt.mgmt.btmode");
- if( val.empty() ) {
- val = jau::environment::getProperty("org.tinyb.btmode");
- }
- const BTMode res = direct_bt::to_BTMode(val);
- return BTMode::NONE != res ? res : BTMode::DUAL; // fallback to default DUAL
-}
-
MgmtEnv::MgmtEnv() noexcept
: DEBUG_GLOBAL( jau::environment::get("direct_bt").debug ),
exploding( jau::environment::getExplodingProperties("direct_bt.mgmt") ),
@@ -75,7 +64,6 @@ MgmtEnv::MgmtEnv() noexcept
MGMT_COMMAND_REPLY_TIMEOUT( jau::environment::getInt32Property("direct_bt.mgmt.cmd.timeout", 3000, 1500 /* min */, INT32_MAX /* max */) ),
MGMT_EVT_RING_CAPACITY( jau::environment::getInt32Property("direct_bt.mgmt.ringsize", 64, 64 /* min */, 1024 /* max */) ),
DEBUG_EVENT( jau::environment::getBooleanProperty("direct_bt.debug.mgmt.event", false) ),
- DEFAULT_BTMODE( getEnvBTMode() ),
MGMT_READ_PACKET_MAX_RETRY( MGMT_EVT_RING_CAPACITY )
{
}
@@ -240,7 +228,31 @@ std::unique_ptr<MgmtEvent> BTManager::sendWithReply(MgmtCommand &req) noexcept {
return nullptr;
}
-std::unique_ptr<AdapterInfo> BTManager::initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept {
+std::unique_ptr<AdapterInfo> BTManager::readAdapterInfo(const uint16_t dev_id) noexcept {
+ std::unique_ptr<AdapterInfo> adapterInfo(nullptr); // nullptr
+ MgmtCommand req0(MgmtCommand::Opcode::READ_INFO, dev_id);
+ {
+ std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
+ if( nullptr == res ) {
+ goto fail;
+ }
+ if( MgmtEvent::Opcode::CMD_COMPLETE != res->getOpcode() || res->getTotalSize() < MgmtEvtAdapterInfo::getRequiredTotalSize()) {
+ ERR_PRINT("Insufficient data for adapter info: req %d, res %s", MgmtEvtAdapterInfo::getRequiredTotalSize(), res->toString().c_str());
+ goto fail;
+ }
+ const MgmtEvtAdapterInfo * res1 = static_cast<MgmtEvtAdapterInfo*>(res.get());
+ adapterInfo = res1->toAdapterInfo();
+ if( dev_id != adapterInfo->dev_id ) {
+ ABORT("readAdapterSettings dev_id=%d != dev_id=%d: %s", adapterInfo->dev_id, dev_id, adapterInfo->toString().c_str());
+ }
+ }
+ DBG_PRINT("readAdapterSettings[%d]: End: %s", dev_id, adapterInfo->toString().c_str());
+
+fail:
+ return adapterInfo;
+}
+
+HCIStatusCode BTManager::initializeAdapter(AdapterInfo& adapterInfo, const uint16_t dev_id, const BTMode btMode) noexcept {
/**
* We weight on PairingMode::PASSKEY_ENTRY. FIXME: Have it configurable!
*
@@ -254,7 +266,6 @@ std::unique_ptr<AdapterInfo> BTManager::initAdapter(const uint16_t dev_id, const
const uint8_t sc_on_param = 0x01; // SET_SECURE_CONN 0x00 disabled, 0x01 enables SC mixed, 0x02 enables SC only mode
#endif
- std::unique_ptr<AdapterInfo> adapterInfo(nullptr); // nullptr
AdapterSetting current_settings;
MgmtCommand req0(MgmtCommand::Opcode::READ_INFO, dev_id);
{
@@ -267,13 +278,13 @@ std::unique_ptr<AdapterInfo> BTManager::initAdapter(const uint16_t dev_id, const
goto fail;
}
const MgmtEvtAdapterInfo * res1 = static_cast<MgmtEvtAdapterInfo*>(res.get());
- adapterInfo = res1->toAdapterInfo();
- if( dev_id != adapterInfo->dev_id ) {
- ABORT("AdapterInfo dev_id=%d != dev_id=%d: %s", adapterInfo->dev_id, dev_id, adapterInfo->toString().c_str());
+ res1->updateAdapterInfo(adapterInfo);
+ if( dev_id != adapterInfo.dev_id ) {
+ ABORT("initializeAdapter dev_id=%d != dev_id=%d: %s", adapterInfo.dev_id, dev_id, adapterInfo.toString().c_str());
}
}
- DBG_PRINT("initAdapter[%d, BTMode %s]: Start: %s", dev_id, to_string(btMode).c_str(), adapterInfo->toString().c_str());
- current_settings = adapterInfo->getCurrentSettingMask();
+ DBG_PRINT("initializeAdapter[%d, BTMode %s]: Start: %s", dev_id, to_string(btMode).c_str(), adapterInfo.toString().c_str());
+ current_settings = adapterInfo.getCurrentSettingMask();
setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, 0, current_settings);
@@ -330,9 +341,8 @@ std::unique_ptr<AdapterInfo> BTManager::initAdapter(const uint16_t dev_id, const
* Update AdapterSettings post settings
*/
if( AdapterSetting::NONE != current_settings ) {
- adapterInfo->setCurrentSettingMask(current_settings);
+ adapterInfo.setCurrentSettingMask(current_settings);
} else {
- adapterInfo = nullptr; // flush
std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
if( nullptr == res ) {
goto fail;
@@ -342,45 +352,26 @@ std::unique_ptr<AdapterInfo> BTManager::initAdapter(const uint16_t dev_id, const
goto fail;
}
const MgmtEvtAdapterInfo * res1 = static_cast<MgmtEvtAdapterInfo*>(res.get());
- adapterInfo = res1->toAdapterInfo();
- if( dev_id != adapterInfo->dev_id ) {
- ABORT("AdapterInfo dev_id=%d != dev_id=%d: %s", adapterInfo->dev_id, dev_id, adapterInfo->toString().c_str());
+ res1->updateAdapterInfo(adapterInfo);
+ if( dev_id != adapterInfo.dev_id ) {
+ ABORT("initializeAdapter dev_id=%d != dev_id=%d: %s", adapterInfo.dev_id, dev_id, adapterInfo.toString().c_str());
}
}
- DBG_PRINT("initAdapter[%d, BTMode %s]: End: %s", dev_id, to_string(btMode).c_str(), adapterInfo->toString().c_str());
+ DBG_PRINT("initializeAdapter[%d, BTMode %s]: End: %s", dev_id, to_string(btMode).c_str(), adapterInfo.toString().c_str());
+ return HCIStatusCode::SUCCESS;
fail:
- return adapterInfo;
-}
-
-void BTManager::shutdownAdapter(BTAdapter& adapter) noexcept {
- DBG_PRINT("DBTManager::shutdownAdapter: %s", adapter.toString().c_str());
- const uint16_t dev_id = adapter.dev_id;
- adapter.close(); // also issues removeMgmtEventCallback(dev_id);
-
- AdapterSetting current_settings;
- setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, 0, current_settings);
-
- setMode(dev_id, MgmtCommand::Opcode::SET_BONDABLE, 0, current_settings);
- setMode(dev_id, MgmtCommand::Opcode::SET_CONNECTABLE, 0, current_settings);
- setMode(dev_id, MgmtCommand::Opcode::SET_FAST_CONNECTABLE, 0, current_settings);
-
- setMode(dev_id, MgmtCommand::Opcode::SET_DEBUG_KEYS, 0, current_settings);
- setMode(dev_id, MgmtCommand::Opcode::SET_IO_CAPABILITY, direct_bt::number(SMPIOCapability::DISPLAY_ONLY), current_settings);
- setMode(dev_id, MgmtCommand::Opcode::SET_SSP, 0, current_settings);
- setMode(dev_id, MgmtCommand::Opcode::SET_SECURE_CONN, 0, current_settings);
- DBG_PRINT("DBTManager::shutdownAdapter: done: %s", adapter.toString().c_str());
+ return HCIStatusCode::FAILED;
}
-BTManager::BTManager(const BTMode _defaultBTMode) noexcept
+BTManager::BTManager() noexcept
: env(MgmtEnv::get()),
- defaultBTMode(BTMode::NONE != _defaultBTMode ? _defaultBTMode : env.DEFAULT_BTMODE),
rbuffer(ClientMaxMTU), comm(HCI_DEV_NONE, HCI_CHANNEL_CONTROL),
mgmtEventRing(nullptr, env.MGMT_EVT_RING_CAPACITY), mgmtReaderShallStop(false),
mgmtReaderThreadId(0), mgmtReaderRunning(false),
allowClose( comm.isOpen() )
{
- WORDY_PRINT("DBTManager.ctor: BTMode %s, pid %d", to_string(defaultBTMode).c_str(), BTManager::pidSelf);
+ WORDY_PRINT("DBTManager.ctor: pid %d", BTManager::pidSelf);
if( !allowClose ) {
ERR_PRINT("DBTManager::open: Could not open mgmt control channel");
return;
@@ -479,7 +470,7 @@ next1:
}
for(int i=0; i < num_adapter; i++) {
const uint16_t dev_id = jau::get_uint16(data, 2+i*2, true /* littleEndian */);
- std::unique_ptr<AdapterInfo> adapterInfo = initAdapter(dev_id, defaultBTMode);
+ std::unique_ptr<AdapterInfo> adapterInfo = readAdapterInfo(dev_id);
if( nullptr != adapterInfo ) {
std::shared_ptr<BTAdapter> adapter = BTAdapter::make_shared(*this, *adapterInfo);
adapters.push_back( adapter );
@@ -558,8 +549,8 @@ void BTManager::close() noexcept {
{
int i=0;
jau::for_each_fidelity(adapters, [&](std::shared_ptr<BTAdapter> & a) {
- DBG_PRINT("DBTManager::close::shutdownAdapter: %d/%d processing: %s", i, adapters.size(), a->toString().c_str());
- shutdownAdapter(*a);
+ DBG_PRINT("DBTManager::close -> adapter::close(): %d/%d processing: %s", i, adapters.size(), a->toString().c_str());
+ a->close(); // also issues removeMgmtEventCallback(dev_id);
++i;
});
}
@@ -1162,7 +1153,7 @@ void BTManager::clearAllCallbacks() noexcept {
void BTManager::processAdapterAdded(std::unique_ptr<MgmtEvent> e) noexcept {
const uint16_t dev_id = e->getDevID();
- std::unique_ptr<AdapterInfo> adapterInfo = initAdapter(dev_id, defaultBTMode);
+ std::unique_ptr<AdapterInfo> adapterInfo = readAdapterInfo(dev_id);
if( nullptr != adapterInfo ) {
std::shared_ptr<BTAdapter> adapter = addAdapter( *adapterInfo );
diff --git a/src/direct_bt/HCIHandler.cpp b/src/direct_bt/HCIHandler.cpp
index 4d0e6932..97ccced1 100644
--- a/src/direct_bt/HCIHandler.cpp
+++ b/src/direct_bt/HCIHandler.cpp
@@ -165,17 +165,6 @@ HCIHandler::HCIConnectionRef HCIHandler::removeHCIConnection(jau::darray<HCIConn
return nullptr;
}
-void HCIHandler::resetAllStates(const bool powered_on) noexcept {
- const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList); // RAII-style acquire and relinquish via destructor
- connectionList.clear();
- disconnectCmdList.clear();
- currentScanType = ScanType::NONE;
- zeroSupCommands();
- if( powered_on ) {
- initSupCommands();
- }
-}
-
MgmtEvent::Opcode HCIHandler::translate(HCIEventType evt, HCIMetaEventType met) noexcept {
if( HCIEventType::LE_META == evt ) {
switch( met ) {
@@ -512,12 +501,14 @@ void HCIHandler::sendMgmtEvent(const MgmtEvent& event) noexcept {
(void)invokeCount;
}
-bool HCIHandler::sendCommand(HCICommand &req) noexcept {
+bool HCIHandler::sendCommand(HCICommand &req, const bool quiet) noexcept {
COND_PRINT(env.DEBUG_EVENT, "HCIHandler-IO SENT %s", req.toString().c_str());
TROOctets & pdu = req.getPDU();
if ( comm.write( pdu.get_ptr(), pdu.getSize() ) < 0 ) {
- ERR_PRINT("HCIHandler::sendCommand: HCIComm write error, req %s - %s", req.toString().c_str(), toString().c_str());
+ if( !quiet || jau::environment::get().verbose ) {
+ ERR_PRINT("HCIHandler::sendCommand: HCIComm write error, req %s - %s", req.toString().c_str(), toString().c_str());
+ }
return false;
}
return true;
@@ -722,9 +713,7 @@ HCIHandler::HCIHandler(const uint16_t dev_id_, const BTMode btMode_) noexcept
#endif
filter_put_opcbit(mask);
}
-
- sup_commands_set = false;
- initSupCommands(); // OK to fail
+ zeroSupCommands();
PERF_TS_TD("HCIHandler::ctor.ok");
WORDY_PRINT("HCIHandler.ctor: End OK - %s", toString().c_str());
@@ -740,6 +729,7 @@ fail:
void HCIHandler::zeroSupCommands() noexcept {
bzero(sup_commands, sizeof(sup_commands));
sup_commands_set = false;
+ le_ll_feats = LE_Features::NONE;
}
bool HCIHandler::initSupCommands() noexcept {
// We avoid using a lock or an atomic-switch as we rely on sensible calls.
@@ -747,10 +737,25 @@ bool HCIHandler::initSupCommands() noexcept {
zeroSupCommands();
return false;
}
+ HCIStatusCode status;
+
+ le_ll_feats = LE_Features::NONE;
+ {
+ HCICommand req0(HCIOpcode::LE_READ_LOCAL_FEATURES, 0);
+ const hci_rp_le_read_local_features * ev_lf;
+ std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_lf, &status, true /* quiet */);
+ if( nullptr == ev || nullptr == ev_lf || HCIStatusCode::SUCCESS != status ) {
+ DBG_PRINT("HCIHandler::le_read_local_features: LE_READ_LOCAL_FEATURES: 0x%x (%s) - %s",
+ number(status), to_string(status).c_str(), toString().c_str());
+ zeroSupCommands();
+ return false;
+ }
+ le_ll_feats = static_cast<LE_Features>( jau::get_uint64(ev_lf->features, 0, true /* littleEndian */) );
+ }
+
HCICommand req0(HCIOpcode::READ_LOCAL_COMMANDS, 0);
const hci_rp_read_local_commands * ev_cmds;
- HCIStatusCode status;
- std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_cmds, &status);
+ std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_cmds, &status, true /* quiet */);
if( nullptr == ev || nullptr == ev_cmds || HCIStatusCode::SUCCESS != status ) {
DBG_PRINT("HCIHandler::ctor: READ_LOCAL_COMMANDS: 0x%x (%s) - %s",
number(status), to_string(status).c_str(), toString().c_str());
@@ -763,6 +768,20 @@ bool HCIHandler::initSupCommands() noexcept {
}
}
+bool HCIHandler::resetAllStates(const bool powered_on) noexcept {
+ const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList); // RAII-style acquire and relinquish via destructor
+ connectionList.clear();
+ disconnectCmdList.clear();
+ currentScanType = ScanType::NONE;
+ advertisingEnabled = false;
+ zeroSupCommands();
+ if( powered_on ) {
+ return initSupCommands();
+ } else {
+ return true;
+ }
+}
+
void HCIHandler::close() noexcept {
// Avoid disconnect re-entry -> potential deadlock
bool expConn = true; // C++11, exp as value since C++20
@@ -832,8 +851,7 @@ HCIStatusCode HCIHandler::startAdapter() {
return HCIStatusCode::INTERNAL_FAILURE;
}
}
- resetAllStates(true);
- return HCIStatusCode::SUCCESS;
+ return resetAllStates(true) ? HCIStatusCode::SUCCESS : HCIStatusCode::FAILED;
#else
#warning add implementation
#endif
@@ -896,7 +914,7 @@ HCIStatusCode HCIHandler::reset() noexcept {
return HCIStatusCode::INTERNAL_TIMEOUT; // timeout
}
if( HCIStatusCode::SUCCESS == status ) {
- resetAllStates(true);
+ status = resetAllStates(true) ? HCIStatusCode::SUCCESS : HCIStatusCode::FAILED;
}
return status;
}
@@ -924,25 +942,6 @@ HCIStatusCode HCIHandler::getLocalVersion(HCILocalVersion &version) noexcept {
return status;
}
-HCIStatusCode HCIHandler::le_read_local_features(LE_Features& res) noexcept {
- if( !isOpen() ) {
- ERR_PRINT("HCIHandler::le_read_local_features: Not connected %s", toString().c_str());
- return HCIStatusCode::INTERNAL_FAILURE;
- }
- res = LE_Features::NONE;
- HCICommand req0(HCIOpcode::LE_READ_LOCAL_FEATURES, 0);
- const hci_rp_le_read_local_features * ev_lf;
- HCIStatusCode status;
- std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_lf, &status);
- if( nullptr == ev || nullptr == ev_lf || HCIStatusCode::SUCCESS != status ) {
- ERR_PRINT("HCIHandler::le_read_local_features: LE_READ_LOCAL_FEATURES: 0x%x (%s) - %s",
- number(status), to_string(status).c_str(), toString().c_str());
- } else {
- res = static_cast<LE_Features>( jau::get_uint64(ev_lf->features, 0, true /* littleEndian */) );
- }
- return status;
-}
-
HCIStatusCode HCIHandler::le_set_scan_param(const bool le_scan_active,
const HCILEOwnAddressType own_mac_type,
const uint16_t le_scan_interval, const uint16_t le_scan_window,
@@ -1061,12 +1060,12 @@ HCIStatusCode HCIHandler::le_start_scan(const bool filter_dup,
if( HCIStatusCode::SUCCESS != status ) {
WARN_PRINT("HCIHandler::le_start_scan: le_set_scan_param failed: %s - %s",
to_string(status).c_str(), toString().c_str());
- } else {
- status = le_enable_scan(true /* enable */, filter_dup);
- if( HCIStatusCode::SUCCESS != status ) {
- WARN_PRINT("HCIHandler::le_start_scan: le_enable_scan failed: %s - %s",
- to_string(status).c_str(), toString().c_str());
- }
+ return status;
+ }
+ status = le_enable_scan(true /* enable */, filter_dup);
+ if( HCIStatusCode::SUCCESS != status ) {
+ WARN_PRINT("HCIHandler::le_start_scan: le_enable_scan failed: %s - %s",
+ to_string(status).c_str(), toString().c_str());
}
return status;
}
@@ -1401,7 +1400,7 @@ HCIStatusCode HCIHandler::le_read_phy(const uint16_t conn_handle, const BDAddres
return status;
}
-std::unique_ptr<HCIEvent> HCIHandler::processCommandStatus(HCICommand &req, HCIStatusCode *status) noexcept
+std::unique_ptr<HCIEvent> HCIHandler::processCommandStatus(HCICommand &req, HCIStatusCode *status, const bool quiet) noexcept
{
const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply); // RAII-style acquire and relinquish via destructor
@@ -1436,10 +1435,12 @@ std::unique_ptr<HCIEvent> HCIHandler::processCommandStatus(HCICommand &req, HCIS
}
if( nullptr == ev ) {
// timeout exit
- WARN_PRINT("HCIHandler::processCommandStatus %s -> Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
- to_string(req.getOpcode()).c_str(),
- number(*status), to_string(*status).c_str(), errno, strerror(errno),
- req.toString().c_str(), toString().c_str());
+ if( !quiet || jau::environment::get().verbose ) {
+ WARN_PRINT("HCIHandler::processCommandStatus %s -> Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
+ to_string(req.getOpcode()).c_str(),
+ number(*status), to_string(*status).c_str(), errno, strerror(errno),
+ req.toString().c_str(), toString().c_str());
+ }
}
exit:
@@ -1448,26 +1449,30 @@ exit:
template<typename hci_cmd_event_struct>
std::unique_ptr<HCIEvent> HCIHandler::processCommandComplete(HCICommand &req,
- const hci_cmd_event_struct **res, HCIStatusCode *status) noexcept
+ const hci_cmd_event_struct **res, HCIStatusCode *status,
+ const bool quiet) noexcept
{
const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply); // RAII-style acquire and relinquish via destructor
*res = nullptr;
*status = HCIStatusCode::INTERNAL_FAILURE;
- if( !sendCommand(req) ) {
- WARN_PRINT("HCIHandler::processCommandComplete Send failed: Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
- number(*status), to_string(*status).c_str(), errno, strerror(errno),
- req.toString().c_str(), toString().c_str());
+ if( !sendCommand(req, quiet) ) {
+ if( !quiet || jau::environment::get().verbose ) {
+ WARN_PRINT("HCIHandler::processCommandComplete Send failed: Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
+ number(*status), to_string(*status).c_str(), errno, strerror(errno),
+ req.toString().c_str(), toString().c_str());
+ }
return nullptr; // timeout
}
- return receiveCommandComplete(req, res, status);
+ return receiveCommandComplete(req, res, status, quiet);
}
template<typename hci_cmd_event_struct>
std::unique_ptr<HCIEvent> HCIHandler::receiveCommandComplete(HCICommand &req,
- const hci_cmd_event_struct **res, HCIStatusCode *status) noexcept
+ const hci_cmd_event_struct **res, HCIStatusCode *status,
+ const bool quiet) noexcept
{
*res = nullptr;
*status = HCIStatusCode::INTERNAL_FAILURE;
@@ -1477,24 +1482,30 @@ std::unique_ptr<HCIEvent> HCIHandler::receiveCommandComplete(HCICommand &req,
std::unique_ptr<HCIEvent> ev = getNextCmdCompleteReply(req, &ev_cc);
if( nullptr == ev ) {
*status = HCIStatusCode::INTERNAL_TIMEOUT;
- WARN_PRINT("HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
- to_string(req.getOpcode()).c_str(), to_string(evc).c_str(),
- number(*status), to_string(*status).c_str(), errno, strerror(errno),
- req.toString().c_str(), toString().c_str());
+ if( !quiet || jau::environment::get().verbose ) {
+ WARN_PRINT("HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
+ to_string(req.getOpcode()).c_str(), to_string(evc).c_str(),
+ number(*status), to_string(*status).c_str(), errno, strerror(errno),
+ req.toString().c_str(), toString().c_str());
+ }
return nullptr; // timeout
} else if( nullptr == ev_cc ) {
- WARN_PRINT("HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
- to_string(req.getOpcode()).c_str(), to_string(evc).c_str(),
- number(*status), to_string(*status).c_str(), errno, strerror(errno),
- ev->toString().c_str(), req.toString().c_str(), toString().c_str());
+ if( !quiet || jau::environment::get().verbose ) {
+ WARN_PRINT("HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
+ to_string(req.getOpcode()).c_str(), to_string(evc).c_str(),
+ number(*status), to_string(*status).c_str(), errno, strerror(errno),
+ ev->toString().c_str(), req.toString().c_str(), toString().c_str());
+ }
return ev;
}
const uint8_t returnParamSize = ev_cc->getReturnParamSize();
if( returnParamSize < sizeof(hci_cmd_event_struct) ) {
- WARN_PRINT("HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
- to_string(req.getOpcode()).c_str(), to_string(evc).c_str(),
- number(*status), to_string(*status).c_str(), errno, strerror(errno),
- ev_cc->toString().c_str(), req.toString().c_str(), toString().c_str());
+ if( !quiet || jau::environment::get().verbose ) {
+ WARN_PRINT("HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
+ to_string(req.getOpcode()).c_str(), to_string(evc).c_str(),
+ number(*status), to_string(*status).c_str(), errno, strerror(errno),
+ ev_cc->toString().c_str(), req.toString().c_str(), toString().c_str());
+ }
return ev;
}
*res = (const hci_cmd_event_struct*)(ev_cc->getReturnParam());
diff --git a/src/direct_bt/MgmtTypes.cpp b/src/direct_bt/MgmtTypes.cpp
index b9b99dcc..94923b08 100644
--- a/src/direct_bt/MgmtTypes.cpp
+++ b/src/direct_bt/MgmtTypes.cpp
@@ -493,6 +493,17 @@ std::unique_ptr<AdapterInfo> MgmtEvtAdapterInfo::toAdapterInfo() const noexcept
getName(), getShortName());
}
+bool MgmtEvtAdapterInfo::updateAdapterInfo(AdapterInfo& info) const noexcept {
+ if( info.dev_id != getDevID() || info.addressAndType.address != getAddress() ) {
+ return false;
+ }
+ info.setSettingMasks(getSupportedSetting(), getCurrentSetting());
+ info.setDevClass(getDevClass());
+ info.setName(getName());
+ info.setShortName(getShortName());
+ return true;
+}
+
std::string MgmtEvtDeviceDisconnected::getDisconnectReasonString(DisconnectReason mgmtReason) noexcept {
switch(mgmtReason) {
case DisconnectReason::TIMEOUT: return "TIMEOUT";