40#include "HCIIoctl.hpp"
60 case DiscoveryPolicy::AUTO_OFF:
return "AUTO_OFF";
61 case DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_DISCONNECTED:
return "PAUSE_CONNECTED_UNTIL_DISCONNECTED";
62 case DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_READY:
return "PAUSE_CONNECTED_UNTIL_READY";
63 case DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_PAIRED:
return "PAUSE_CONNECTED_UNTIL_PAIRED";
64 case DiscoveryPolicy::ALWAYS_ON:
return "ALWAYS_ON";
76 ( address == e->getAddressAndType().address &&
77 ( addressType == e->getAddressAndType().type || addressType == BDAddressType::BDADDR_UNDEFINED )
79 ( address == e->getVisibleAddressAndType().address &&
80 ( addressType == e->getVisibleAddressAndType().type || addressType == BDAddressType::BDADDR_UNDEFINED )
85 if( !rpa.isIdentityAddress() ) {
86 e->updateVisibleAddress(rpa);
87 hci.setResolvHCIConnectionAddr(rpa, e->getAddressAndType());
92 if( !rpa.isIdentityAddress() ) {
95 if (
nullptr != e && e->matches_irk(rpa) ) {
96 e->updateVisibleAddress(rpa);
97 hci.setResolvHCIConnectionAddr(rpa, e->getAddressAndType());
105BTDeviceRef BTAdapter::findDevice(device_list_t & devices,
BTDevice const & device)
noexcept {
109 if (
nullptr != e && device == *e ) {
117 auto end = devices.end();
118 for (
auto it = devices.begin(); it != end; ) {
119 std::weak_ptr<BTDevice> & w = *it;
123 }
else if ( ( address == e->getAddressAndType().address &&
124 ( addressType == e->getAddressAndType().type || addressType == BDAddressType::BDADDR_UNDEFINED )
126 ( address == e->getVisibleAddressAndType().address &&
127 ( addressType == e->getVisibleAddressAndType().type || addressType == BDAddressType::BDADDR_UNDEFINED )
139BTDeviceRef BTAdapter::findWeakDevice(weak_device_list_t & devices,
BTDevice const & device)
noexcept {
140 auto end = devices.end();
141 for (
auto it = devices.begin(); it != end; ) {
142 std::weak_ptr<BTDevice> & w = *it;
146 }
else if ( device == *e ) {
156 const std::lock_guard<std::mutex> lock(mtx_pausingDiscoveryDevices);
157 return findWeakDevice(pausing_discovery_devices, address, addressType);
160bool BTAdapter::addDevicePausingDiscovery(
const BTDeviceRef & device)
noexcept {
161 bool added_first =
false;
163 const std::lock_guard<std::mutex> lock(mtx_pausingDiscoveryDevices);
164 if(
nullptr != findWeakDevice(pausing_discovery_devices, *device) ) {
167 added_first = 0 == pausing_discovery_devices.size();
168 pausing_discovery_devices.push_back(device);
172 updateDeviceDiscoveringState(ScanType::LE,
false );
174 std::thread bg(&BTAdapter::stopDiscoveryImpl,
this,
false ,
true );
183bool BTAdapter::removeDevicePausingDiscovery(
const BTDevice & device)
noexcept {
184 bool removed_last =
false;
186 const std::lock_guard<std::mutex> lock(mtx_pausingDiscoveryDevices);
187 auto end = pausing_discovery_devices.end();
188 for (
auto it = pausing_discovery_devices.begin(); it != end; ) {
189 std::weak_ptr<BTDevice> & w = *it;
192 pausing_discovery_devices.erase(it);
193 }
else if ( device == *e ) {
194 pausing_discovery_devices.erase(it);
195 removed_last = 0 == pausing_discovery_devices.size();
203 discovery_service.start();
210void BTAdapter::clearDevicesPausingDiscovery() noexcept {
211 const std::lock_guard<std::mutex> lock(mtx_pausingDiscoveryDevices);
212 pausing_discovery_devices.
clear();
215jau::nsize_t BTAdapter::getDevicesPausingDiscoveryCount() noexcept {
216 const std::lock_guard<std::mutex> lock(mtx_pausingDiscoveryDevices);
217 return pausing_discovery_devices.
size();
220bool BTAdapter::addConnectedDevice(
const BTDeviceRef & device)
noexcept {
221 const std::lock_guard<std::mutex> lock(mtx_connectedDevices);
222 if(
nullptr != findDevice(connectedDevices, *device) ) {
225 connectedDevices.push_back(device);
229bool BTAdapter::removeConnectedDevice(
const BTDevice & device)
noexcept {
230 const std::lock_guard<std::mutex> lock(mtx_connectedDevices);
231 auto end = connectedDevices.end();
232 for (
auto it = connectedDevices.begin(); it != end; ++it) {
233 if (
nullptr != *it && device == **it ) {
234 connectedDevices.erase(it);
242 device_list_t devices;
245 devices = connectedDevices;
247 const size_type count = devices.size();
248 auto end = devices.end();
249 for (
auto it = devices.begin(); it != end; ++it) {
250 if(
nullptr != *it ) {
253 removeConnectedDevice(dev);
260 const std::lock_guard<std::mutex> lock(mtx_connectedDevices);
261 return findDevice(hci, connectedDevices, address, addressType);
264jau::nsize_t BTAdapter::getConnectedDeviceCount() const noexcept {
266 return connectedDevices.
size();
273bool BTAdapter::updateDataFromHCI() noexcept {
277 ERR_PRINT(
"Adapter[%d]: POWERED, LocalVersion failed %s - %s",
295 WORDY_PRINT(
"BTAdapter::updateDataFromHCI: Adapter[%d]: POWERED, %s - %s, hci_ext[scan %d, conn %d], features: %s",
297 hci_uses_ext_scan, hci_uses_ext_conn,
302bool BTAdapter::updateDataFromAdapterInfo() noexcept {
312bool BTAdapter::initialSetup() noexcept {
313 if( !mgmt->isOpen() ) {
324 if( !updateDataFromAdapterInfo() ) {
332 if( !updateDataFromHCI() ) {
345bool BTAdapter::enableListening(
const bool enable)
noexcept {
347 if( !mgmt->isOpen() ) {
348 ERR_PRINT(
"Adapter[%d]: Manager not open", dev_id);
351 if( !hci.isOpen() ) {
352 ERR_PRINT(
"Adapter[%d]: HCIHandler closed", dev_id);
357 mgmt->removeMgmtEventCallback(dev_id);
358 hci.clearAllCallbacks();
381 ERR_PRINT(
"Could not add all required MgmtEventCallbacks to DBTManager: %s", toString().c_str());
406 ERR_PRINT(
"Could not add all required MgmtEventCallbacks to HCIHandler: %s of %s", hci.toString().c_str(), toString().c_str());
409 hci.addSMPMsgCallback(
jau::bind_member(
this, &BTAdapter::hciSMPMsgCallback));
411 mgmt->removeMgmtEventCallback(dev_id);
412 hci.clearAllCallbacks();
414 WORDY_PRINT(
"BTAdapter::enableListening: Adapter[%d]: Done: %s - %s", dev_id, adapterInfo.toString().c_str(), toString().c_str());
422 mgmt( std::move(mgmt_) ),
423 adapterInfo( std::move(adapterInfo_) ),
424 adapter_initialized(
false ), adapter_poweredoff_at_init(
true ),
426 hci_uses_ext_scan(
false ), hci_uses_ext_conn(
false ), hci_uses_ext_adv(
false ),
427 visibleAddressAndType( adapterInfo_.addressAndType ),
430 dev_id( adapterInfo.dev_id ),
435 scan_filter_dup(
true ),
442 discovery_service(
"BTAdapter::discoveryServer", 400_ms,
448 adapter_operational = initialSetup();
451 DBG_PRINT(
"BTAdapter::ctor: dev_id %d: smp_watchdog.smp_timeoutfunc started %d", dev_id, r);
459 mgmt->removeAdapter(
this);
467 mgmt->removeAdapter(
this);
486 DBG_PRINT(
"BTAdapter::close removeMgmtEventCallback: %zu callbacks", (
size_t)count);
489 statusListenerList.
clear();
491 poweredOff(
true ,
"close");
493 if( adapter_poweredoff_at_init &&
isPowered() ) {
497 DBG_PRINT(
"BTAdapter::close: close[HCI, l2cap_srv]: ...");
499 l2cap_service.
stop();
500 l2cap_att_srv.
close();
501 discovery_service.
stop();
502 DBG_PRINT(
"BTAdapter::close: close[HCI, l2cap_srv, discovery_srv]: XXX");
505 const std::lock_guard<std::mutex> lock(mtx_discoveredDevices);
506 discoveredDevices.
clear();
509 const std::lock_guard<std::mutex> lock(mtx_connectedDevices);
510 connectedDevices.
clear();;
513 const std::lock_guard<std::mutex> lock(mtx_sharedDevices);
514 sharedDevices.
clear();
517 const std::lock_guard<std::mutex> lock(mtx_keys);
521 adapter_operational =
false;
525void BTAdapter::poweredOff(
bool active,
const std::string& msg)
noexcept {
527 ERR_PRINT(
"BTAdapter invalid: dev_id %d, %p", dev_id,
this);
530 DBG_PRINT(
"BTAdapter::poweredOff(active %d, %s).0: ... %p, %s", active, msg.c_str(),
this, toString().c_str());
536 if( !hci.isOpen() ) {
537 jau::INFO_PRINT(
"BTAdapter::poweredOff: HCI closed: active %d -> 0: %s", active, toString().c_str());
540 DBG_PRINT(
"BTAdapter::poweredOff: !POWERED: active %d -> 0: %s", active, toString().c_str());
546 stopDiscoveryImpl(
true ,
false );
551 removeDiscoveredDevices();
554 hci.resetAllStates(
false);
561 DBG_PRINT(
"BTAdapter::poweredOff(active %d, %s).X: %s", active, msg.c_str(), toString().c_str());
565 const size_t sz = list.size();
566 jau::PLAIN_PRINT(
true,
"- BTAdapter::%s: %zu elements", prefix.c_str(), sz);
568 for (
auto it = list.begin(); it != list.end(); ++idx, ++it) {
586 if(
nullptr != (*it) ) {
588 }
else if( (*it)->isValidInstance() ) {
591 jau::PLAIN_PRINT(
true,
" - %d / %zu: %s, name '%s', visible %s", (idx+1), sz,
592 (*it)->getAddressAndType().toString().c_str(),
593 (*it)->getName().c_str(),
594 (*it)->getVisibleAddressAndType().toString().c_str());
600 const size_t sz = list.size();
601 jau::PLAIN_PRINT(
true,
"- BTAdapter::%s: %zu elements", prefix.c_str(), sz);
603 for (
auto it = list.begin(); it != list.end(); ++idx, ++it) {
604 std::weak_ptr<BTDevice> & w = *it;
608 }
else if( !e->isValidInstance() ) {
611 jau::PLAIN_PRINT(
true,
" - %d / %zu: %s, name '%s', visible %s", (idx+1), sz,
612 e->getAddressAndType().toString().c_str(),
613 e->getName().c_str(),
614 e->getVisibleAddressAndType().toString().c_str());
620 weak_device_list_t _sharedDevices, _discoveredDevices, _connectedDevices, _pausingDiscoveryDevice;
622 const std::lock_guard<std::mutex> lock(mtx_sharedDevices);
626 const std::lock_guard<std::mutex> lock(mtx_discoveredDevices);
630 const std::lock_guard<std::mutex> lock(mtx_connectedDevices);
634 const std::lock_guard<std::mutex> lock(mtx_pausingDiscoveryDevices);
635 _pausingDiscoveryDevice = pausing_discovery_devices;
637 printWeakDeviceList(
"SharedDevices ", _sharedDevices);
638 printWeakDeviceList(
"ConnectedDevices ", _connectedDevices);
639 printWeakDeviceList(
"DiscoveredDevices ", _discoveredDevices);
640 printWeakDeviceList(
"PausingDiscoveryDevices ", _pausingDiscoveryDevice);
645 auto begin = statusListenerList.
begin();
646 jau::PLAIN_PRINT(
true,
"- BTAdapter::StatusListener : %zu elements", (
size_t)begin.size());
647 for(
int ii=0; !begin.is_end(); ++ii, ++begin ) {
648 jau::PLAIN_PRINT(
true,
" - %d / %zu: %p, %s", (ii+1), (
size_t)begin.size(), begin->listener.get(), begin->listener->toString().c_str());
656 std::shared_ptr<NameAndShortName> res = mgmt->setLocalName(dev_id, name, short_name);
669 const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(settings);
670 updateAdapterSettings(
false , new_settings,
false , 0);
677 std::unique_ptr<std::random_device> rng_hw = std::make_unique<std::random_device>();
678 for(
int i=0; i<4; ++i) {
679 std::uint32_t v = (*rng_hw)();
680 irk.
data[4*i+0] = v & 0x000000ffu;
681 irk.
data[4*i+1] = ( v & 0x0000ff00u ) >> 8;
682 irk.
data[4*i+2] = ( v & 0x00ff0000u ) >> 16;
683 irk.
data[4*i+3] = ( v & 0xff000000u ) >> 24;
689 HCIStatusCode res = mgmt->setPrivacy(dev_id, enable ? 0x01 : 0x00, irk, settings);
698 visibleAddressAndType = adapterInfo.addressAndType;
700 privacyIRK.address = adapterInfo.addressAndType.address;
701 privacyIRK.address_type = adapterInfo.addressAndType.type;
702 privacyIRK.irk.clear();
705 const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(settings);
706 updateAdapterSettings(
false , new_settings,
true , 0);
722 const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(settings);
723 updateAdapterSettings(
false , new_settings,
false , 0);
728 const uint16_t conn_latency,
const uint16_t supervision_timeout)
noexcept {
732 return mgmt->setDefaultConnParam(dev_id, conn_interval_min, conn_interval_max, conn_latency, supervision_timeout);
741 key_path = std::move(path);
745 uploadKeys(f,
false );
750 if( bin.getLocalAddrAndType() != adapterInfo.addressAndType ) {
751 if( bin.getVerbose() ) {
752 jau::PLAIN_PRINT(
true,
"BTAdapter::setSMPKeyBin: Adapter address not matching: %s, %s",
753 bin.toString().c_str(), toString().c_str());
762 ad_report.
setAddress( bin.getRemoteAddrAndType().address );
766 BTDeviceRef device = BTDevice::make_shared(*
this, ad_report);
768 addSharedDevice(device);
771 res = mgmt->unpairDevice(dev_id, bin.getRemoteAddrAndType(),
false );
773 ERR_PRINT(
"(dev_id %d): Unpair device failed %s of %s: %s",
774 dev_id,
to_string(res).c_str(), bin.getRemoteAddrAndType().toString().c_str(),
780 WARN_PRINT(
"(dev_id %d): Upload SMPKeyBin failed %s, %s (removing file)",
781 dev_id,
to_string(res).c_str(), bin.toString().c_str());
782 if( key_path.size() > 0 ) {
783 bin.remove(key_path);
787 DBG_PRINT(
"BTAdapter::setSMPKeyBin(dev_id %d): Upload OK: %s, %s",
788 dev_id, bin.toString().c_str(), toString().c_str());
790 addSMPKeyBin( std::make_shared<SMPKeyBin>(bin), write);
796 adapter_initialized =
true;
797 adapter_poweredoff_at_init = was_powered;
802 WARN_PRINT(
"Adapter[%d]: Failed initializing (1): res0 %s, powered[before %d, now %d], %s - %s",
805 adapterInfo.toString().c_str(), toString().c_str());
809 if( !enableListening(
true) ) {
812 updateAdapterSettings(
false , adapterInfo.getCurrentSettingMask(),
false , 0);
814 WORDY_PRINT(
"BTAdapter::initialize: Adapter[%d]: OK: powered[%d -> %d], %s",
815 dev_id, was_powered, is_powered, toString().c_str());
820 std::unique_lock<std::mutex> lock(mtx_single_conn_device);
823 if(
nullptr != single_conn_device_ptr ) {
824 if( device == *single_conn_device_ptr ) {
825 COND_PRINT(debug_lock,
"BTAdapter::lockConnect: Success: Already locked, same device: %s", device.toString().c_str());
830 while(
nullptr != single_conn_device_ptr ) {
831 std::cv_status s =
wait_until(cv_single_conn_device, lock, timeout_time);
832 if( std::cv_status::timeout == s &&
nullptr != single_conn_device_ptr ) {
835 jau::PLAIN_PRINT(
true,
" - locked-by-other-device %s", single_conn_device_ptr->toString().c_str());
845 jau::PLAIN_PRINT(
true,
" - locked-by-other-device %s", single_conn_device_ptr->toString().c_str());
851 single_conn_device_ptr = &device;
856 const bool res_iocap = mgmt->setIOCapability(dev_id, io_cap, pre_io_cap);
858 iocap_defaultval = pre_io_cap;
859 COND_PRINT(debug_lock,
"BTAdapter::lockConnect: Success: New lock, setIOCapability[%s -> %s], %s",
861 device.toString().c_str());
865 COND_PRINT(debug_lock,
"BTAdapter::lockConnect: Failed: setIOCapability[%s], %s",
866 to_string(io_cap).c_str(), device.toString().c_str());
867 single_conn_device_ptr =
nullptr;
869 cv_single_conn_device.notify_all();
873 COND_PRINT(debug_lock,
"BTAdapter::lockConnect: Success: New lock, ignored io-cap: %s, %s",
874 to_string(io_cap).c_str(), device.toString().c_str());
878 COND_PRINT(debug_lock,
"BTAdapter::lockConnect: Success: New lock, no io-cap: %s", device.toString().c_str());
883bool BTAdapter::unlockConnect(
const BTDevice & device)
noexcept {
884 std::unique_lock<std::mutex> lock(mtx_single_conn_device);
886 if(
nullptr != single_conn_device_ptr && device == *single_conn_device_ptr ) {
892 const bool res = mgmt->setIOCapability(dev_id, v, o);
893 COND_PRINT(debug_lock,
"BTAdapter::unlockConnect: Success: setIOCapability[res %d: %s -> %s], %s",
895 single_conn_device_ptr->toString().c_str());
897 COND_PRINT(debug_lock,
"BTAdapter::unlockConnect: Success: %s",
898 single_conn_device_ptr->toString().c_str());
900 single_conn_device_ptr =
nullptr;
902 cv_single_conn_device.notify_all();
906 const std::string other_device_str =
nullptr != single_conn_device_ptr ? single_conn_device_ptr->toString() :
"null";
908 jau::PLAIN_PRINT(
true,
" - locked-by-other-device %s", other_device_str.c_str());
909 jau::PLAIN_PRINT(
true,
" - unlock-failed-for %s", device.toString().c_str());
915bool BTAdapter::unlockConnectAny() noexcept {
916 std::unique_lock<std::mutex> lock(mtx_single_conn_device);
918 if(
nullptr != single_conn_device_ptr ) {
924 const bool res = mgmt->setIOCapability(
dev_id, v, o);
925 COND_PRINT(debug_lock,
"BTAdapter::unlockConnectAny: Success: setIOCapability[res %d: %s -> %s]; %s",
927 single_conn_device_ptr->
toString().c_str());
929 COND_PRINT(debug_lock,
"BTAdapter::unlockConnectAny: Success: %s",
930 single_conn_device_ptr->
toString().c_str());
932 single_conn_device_ptr =
nullptr;
934 cv_single_conn_device.notify_all();
938 COND_PRINT(debug_lock,
"BTAdapter::unlockConnectAny: Not locked");
955 if( 0 < connCount ) {
958 DBG_PRINT(
"BTAdapter::reset: %d connections pending - %s", connCount,
toString().c_str());
960 while( timeout > td && 0 < connCount ) {
963 connCount = getConnectedDeviceCount();
965 if( 0 < connCount ) {
968 DBG_PRINT(
"BTAdapter::reset: pending connections resolved after %" PRIi64
" ms - %s", td.
to_ms(),
toString().c_str());
980 poweredOff(
false ,
"setDefaultLE_PHY.np");
983 return hci.le_set_default_phy(Tx, Rx);
987 return mgmt->isDeviceWhitelisted(dev_id, addressAndType);
991 const uint16_t conn_interval_min,
const uint16_t conn_interval_max,
992 const uint16_t conn_latency,
const uint16_t timeout) {
994 poweredOff(
false ,
"addDeviceToWhitelist.np");
997 if( mgmt->isDeviceWhitelisted(
dev_id, addressAndType) ) {
1002 HCIStatusCode res = mgmt->uploadConnParam(
dev_id, addressAndType, conn_interval_min, conn_interval_max, conn_latency, timeout);
1004 ERR_PRINT(
"uploadConnParam(dev_id %d, address%s, interval[%u..%u], latency %u, timeout %u): Failed %s",
1005 dev_id, addressAndType.
toString().c_str(), conn_interval_min, conn_interval_max, conn_latency, timeout,
to_string(res).c_str());
1007 return mgmt->addDeviceToWhitelist(
dev_id, addressAndType, ctype);
1011 return mgmt->removeDeviceFromWhitelist(
dev_id, addressAndType);
1015 [](
const StatusListenerPair &a,
const StatusListenerPair &b) ->
bool {
return *a.listener == *b.listener; };
1018 if(
nullptr == l ) {
1019 ERR_PRINT(
"AdapterStatusListener ref is null");
1022 const bool added = statusListenerList.push_back_unique(StatusListenerPair{l, std::weak_ptr<BTDevice>{} },
1023 adapterStatusListenerRefEqComparator);
1028 jau::PLAIN_PRINT(
true,
"BTAdapter::addStatusListener.1: added %d, %s", added, toString().c_str());
1035 if(
nullptr == l ) {
1036 ERR_PRINT(
"AdapterStatusListener ref is null");
1039 if(
nullptr == d ) {
1043 const bool added = statusListenerList.push_back_unique(StatusListenerPair{l, d},
1044 adapterStatusListenerRefEqComparator);
1049 jau::PLAIN_PRINT(
true,
"BTAdapter::addStatusListener.2: added %d, %s", added, toString().c_str());
1056 return addStatusListener(getSharedDevice(d), l);
1060 if(
nullptr == l ) {
1061 ERR_PRINT(
"AdapterStatusListener ref is null");
1064 const size_type count = statusListenerList.erase_matching(StatusListenerPair{l, std::weak_ptr<BTDevice>{}},
1066 adapterStatusListenerRefEqComparator);
1068 jau::PLAIN_PRINT(
true,
"BTAdapter::removeStatusListener.1: res %d, %s", count>0, toString().c_str());
1075 if(
nullptr == l ) {
1076 ERR_PRINT(
"AdapterStatusListener ref is null");
1081 auto it = statusListenerList.begin();
1082 for (; !it.is_end(); ++it ) {
1083 if ( *it->listener == *l ) {
1092 jau::PLAIN_PRINT(
true,
"BTAdapter::removeStatusListener.2: res %d, %s", res, toString().c_str());
1099 size_type count = 0;
1101 if( 0 < statusListenerList.size() ) {
1102 auto begin = statusListenerList.begin();
1103 auto it = begin.end();
1107 if (
nullptr != sda && *sda == d ) {
1111 }
while( it != begin );
1122 statusListenerList.
clear();
1126void BTAdapter::checkDiscoveryState() noexcept {
1131 std::string msg(
"Invalid DiscoveryState: policy "+
to_string(discovery_policy)+
1132 ", currentScanType*[native "+
1133 to_string(currentNativeScanType)+
" != meta "+
1140 std::string msg(
"Invalid DiscoveryState: policy "+
to_string(discovery_policy)+
1141 ", currentScanType*[native "+
1142 to_string(currentNativeScanType)+
", meta "+
1160 clearDevicesPausingDiscovery();
1162 if( !isPowered() ) {
1163 poweredOff(
false ,
"startDiscovery.np");
1167 const std::lock_guard<std::mutex> lock(mtx_discovery);
1169 if( isAdvertising() ) {
1170 WARN_PRINT(
"Adapter in advertising mode: %s", toString(
true).c_str());
1174 l2cap_service.stop();
1176 removeDiscoveredDevices();
1180 const ScanType currentNativeScanType = hci.getCurrentScanType();
1184 if( discovery_policy == policy ) {
1185 DBG_PRINT(
"BTAdapter::startDiscovery: Already discovering, unchanged policy %s -> %s, currentScanType[native %s, meta %s] ...\n- %s",
1187 to_string(currentNativeScanType).c_str(),
to_string(currentMetaScanType).c_str(), toString(
true).c_str());
1189 DBG_PRINT(
"BTAdapter::startDiscovery: Already discovering, changed policy %s -> %s, currentScanType[native %s, meta %s] ...\n- %s",
1191 to_string(currentNativeScanType).c_str(),
to_string(currentMetaScanType).c_str(), toString(
true).c_str());
1192 discovery_policy = policy;
1194 gattServerData = gattServerData_;
1196 jau::PLAIN_PRINT(
true,
"BTAdapter::startDiscovery: End.0: Result %s, policy %s -> %s, currentScanType[native %s, meta %s] ...\n- %s",
1199 to_string(hci.getCurrentScanType()).c_str(),
to_string(currentMetaScanType).c_str(), toString().c_str());
1202 checkDiscoveryState();
1207 jau::PLAIN_PRINT(
true,
"BTAdapter::startDiscovery: Start: policy %s -> %s, currentScanType[native %s, meta %s] ...\n- %s",
1209 to_string(currentNativeScanType).c_str(),
to_string(currentMetaScanType).c_str(), toString().c_str());
1212 discovery_policy = policy;
1214 if(
nullptr != gattServerData_ ) {
1215 gattServerData_->setServicesHandles();
1223 gattServerData =
nullptr;
1225 gattServerData = gattServerData_;
1229 jau::PLAIN_PRINT(
true,
"BTAdapter::startDiscovery: End.1: Result %s, policy %s -> %s, currentScanType[native %s, meta %s] ...\n- %s",
1232 to_string(hci.getCurrentScanType()).c_str(),
to_string(currentMetaScanType).c_str(), toString().c_str());
1236 checkDiscoveryState();
1246 if( !isPowered() ) {
1247 poweredOff(
false ,
"discoveryServerWork.np");
1250 const std::lock_guard<std::mutex> lock(mtx_discovery);
1251 const ScanType currentNativeScanType = hci.getCurrentScanType();
1255 0 == getDevicesPausingDiscoveryCount() )
1258 DBG_PRINT(
"BTAdapter::startDiscoveryBackground[%u/%u]: Policy %s, currentScanType[native %s, meta %s] ... %s",
1261 to_string(currentNativeScanType).c_str(),
to_string(currentMetaScanType).c_str(), toString().c_str());
1262 const HCIStatusCode status = hci.le_enable_scan(
true , scan_filter_dup);
1264 ERR_PRINT2(
"le_enable_scan failed[%u/%u]: %s - %s",
1266 to_string(status).c_str(), toString().c_str());
1272 checkDiscoveryState();
1275 if( retry && !sr.shall_stop() ) {
1281 sr.set_shall_stop();
1286 clearDevicesPausingDiscovery();
1288 return stopDiscoveryImpl(
false ,
false );
1291HCIStatusCode BTAdapter::stopDiscoveryImpl(
const bool forceDiscoveringEvent,
const bool temporary)
noexcept {
1299 const std::lock_guard<std::mutex> lock(mtx_discovery);
1315 const ScanType currentNativeScanType = hci.getCurrentScanType();
1320 DBG_PRINT(
"BTAdapter::stopDiscovery: Start: policy %s, currentScanType[native %s, meta %s], le_scan_temp_disabled %d, forceDiscEvent %d ...",
1323 le_scan_temp_disabled, forceDiscoveringEvent);
1330 DBG_PRINT(
"BTAdapter::stopDiscovery: Already disabled, policy %s, currentScanType[native %s, meta %s] ...",
1333 checkDiscoveryState();
1338 if( !isPowered() ) {
1339 poweredOff(
false ,
"stopDiscoveryImpl.np");
1344 if( le_scan_temp_disabled ) {
1351 status = hci.le_enable_scan(
false );
1368 mgmtEvDeviceDiscoveringHCI( e );
1371 jau::PLAIN_PRINT(
true,
"BTAdapter::stopDiscovery: End: Result %s, policy %s, currentScanType[native %s, meta %s], le_scan_temp_disabled %d ...\n- %s",
1373 to_string(hci.getCurrentScanType()).c_str(),
to_string(currentMetaScanType).c_str(), le_scan_temp_disabled,
1374 toString().c_str());
1378 checkDiscoveryState();
1386 const std::lock_guard<std::mutex> lock(mtx_discoveredDevices);
1387 return findDevice(hci, discoveredDevices, address, addressType);
1390bool BTAdapter::addDiscoveredDevice(
BTDeviceRef const &device)
noexcept {
1391 const std::lock_guard<std::mutex> lock(mtx_discoveredDevices);
1392 if(
nullptr != findDevice(discoveredDevices, *device) ) {
1396 discoveredDevices.push_back(device);
1401 const std::lock_guard<std::mutex> lock(mtx_discoveredDevices);
1402 for (
auto it = discoveredDevices.begin(); it != discoveredDevices.end(); ++it) {
1404 if (
nullptr != *it && addressAndType == device.
addressAndType ) {
1405 if(
nullptr == getSharedDevice( device ) ) {
1406 removeAllStatusListener( device );
1408 discoveredDevices.erase(it);
1418 const std::lock_guard<std::mutex> lock(mtx_discoveredDevices);
1420 res = discoveredDevices.
size();
1422 auto it = discoveredDevices.
end();
1426 if(
nullptr == getSharedDevice( device ) ) {
1429 discoveredDevices.
erase(it);
1430 }
while( it != discoveredDevices.
begin() );
1448bool BTAdapter::addSharedDevice(
BTDeviceRef const &device)
noexcept {
1449 const std::lock_guard<std::mutex> lock(mtx_sharedDevices);
1450 if(
nullptr != findDevice(sharedDevices, *device) ) {
1454 sharedDevices.push_back(device);
1459 const std::lock_guard<std::mutex> lock(mtx_sharedDevices);
1460 return findDevice(sharedDevices, device);
1463void BTAdapter::removeSharedDevice(
const BTDevice & device)
noexcept {
1464 const std::lock_guard<std::mutex> lock(mtx_sharedDevices);
1465 for (
auto it = sharedDevices.begin(); it != sharedDevices.end(); ) {
1466 if (
nullptr != *it && device == **it ) {
1467 sharedDevices.erase(it);
1476 const std::lock_guard<std::mutex> lock(mtx_sharedDevices);
1477 return findDevice(hci, sharedDevices, address, addressType);
1482void BTAdapter::removeDevice(
BTDevice & device)
noexcept {
1483 WORDY_PRINT(
"DBTAdapter::removeDevice: Start %s", toString().c_str());
1484 removeAllStatusListener(device);
1487 WORDY_PRINT(
"BTAdapter::removeDevice: disconnect %s, %s",
to_string(status).c_str(), toString().c_str());
1488 unlockConnect(device);
1489 removeConnectedDevice(device);
1490 removeDiscoveredDevice(device.addressAndType);
1491 removeDevicePausingDiscovery(device);
1494 removeSharedDevice(device);
1498 jau::PLAIN_PRINT(
true,
"BTAdapter::removeDevice: End %s, %s", device.getAddressAndType().toString().c_str(), toString().c_str());
1505BTAdapter::SMPKeyBinRef BTAdapter::findSMPKeyBin(key_list_t & keys,
BDAddressAndType const & remoteAddress)
noexcept {
1508 SMPKeyBinRef& k = keys[i];
1509 if (
nullptr != k && remoteAddress == k->getRemoteAddrAndType() ) {
1515bool BTAdapter::removeSMPKeyBin(key_list_t & keys,
BDAddressAndType const & remoteAddress,
const bool remove_file,
const std::string& key_path_)
noexcept {
1516 for (
auto it = keys.begin(); it != keys.end(); ++it) {
1517 const SMPKeyBinRef& k = *it;
1518 if (
nullptr != k && remoteAddress == k->getRemoteAddrAndType() ) {
1519 DBG_PRINT(
"BTAdapter::removeSMPKeyBin(file %d): %s", remove_file, k->toString().c_str());
1520 if( remove_file && key_path_.size() > 0 ) {
1521 if( !k->remove(key_path_) ) {
1522 WARN_PRINT(
"Failed removal of SMPKeyBin file: %s", k->getFilename(key_path_).c_str());
1531BTAdapter::SMPKeyBinRef BTAdapter::findSMPKeyBin(
BDAddressAndType const & remoteAddress)
noexcept {
1532 const std::lock_guard<std::mutex> lock(mtx_keys);
1533 return findSMPKeyBin(key_list, remoteAddress);
1535bool BTAdapter::addSMPKeyBin(
const SMPKeyBinRef& key,
const bool write_file)
noexcept {
1536 const std::lock_guard<std::mutex> lock(mtx_keys);
1537 removeSMPKeyBin(key_list, key->getRemoteAddrAndType(), write_file , key_path);
1539 key->setVerbose(
true);
1540 DBG_PRINT(
"BTAdapter::addSMPKeyBin(file %d): %s", write_file, key->toString().c_str());
1542 key_list.push_back( key );
1543 if( write_file && key_path.size() > 0 ) {
1544 if( !key->write(key_path,
true ) ) {
1545 WARN_PRINT(
"Failed write of SMPKeyBin file: %s", key->getFilename(key_path).c_str());
1550bool BTAdapter::removeSMPKeyBin(
BDAddressAndType const & remoteAddress,
const bool remove_file)
noexcept {
1551 const std::lock_guard<std::mutex> lock(mtx_keys);
1552 return removeSMPKeyBin(key_list, remoteAddress, remove_file, key_path);
1563 if( !isPowered() ) {
1564 poweredOff(
false ,
"startAdvertising.np");
1568 if( isDiscovering() ) {
1569 WARN_PRINT(
"Not allowed (scan enabled): %s", toString(
true).c_str());
1572 const jau::nsize_t connCount = getConnectedDeviceCount();
1573 if( 0 < connCount ) {
1574 WARN_PRINT(
"Not allowed (%d connections open/pending): %s", connCount, toString(
true).c_str());
1579 std::vector<MgmtDefaultParam> params = mgmt->readDefaultSysParam(dev_id);
1580 DBG_PRINT(
"BTAdapter::startAdvertising[%d]: SysParam: %zd", dev_id, params.size());
1581 for(
size_t i=0; i<params.size(); ++i) {
1588 const bool res_iocap = mgmt->setIOCapability(dev_id, new_io_cap, pre_io_cap);
1589 DBG_PRINT(
"BTAdapter::startAdvertising: dev_id %u, setIOCapability[%s -> %s]: result %d",
1592 DBG_PRINT(
"BTAdapter::startAdvertising.1: dev_id %u, %s", dev_id, toString().c_str());
1593 l2cap_service.stop();
1594 l2cap_service.start();
1596 if( !l2cap_att_srv.is_open() ) {
1597 ERR_PRINT(
"l2cap_service failed: %s", toString(
true).c_str());
1598 l2cap_service.stop();
1604 eir.setName(getName());
1614 if(
nullptr != gattServerData_ ) {
1615 gattServerData_->setServicesHandles();
1618 const EUI48 peer_bdaddr=EUI48::ANY_DEVICE;
1622 HCIStatusCode status = hci.le_start_adv(eir, adv_mask, scanrsp_mask,
1623 peer_bdaddr, own_mac_type, peer_mac_type,
1626 ERR_PRINT(
"le_start_adv failed: %s - %s",
to_string(status).c_str(), toString(
true).c_str());
1627 gattServerData =
nullptr;
1628 l2cap_service.stop();
1630 gattServerData = gattServerData_;
1632 DBG_PRINT(
"BTAdapter::startAdvertising.OK: dev_id %u, %s", dev_id, toString().c_str());
1647 eir.setName(getName());
1649 if(
nullptr != gattServerData_ ) {
1656 eir, adv_mask, scanrsp_mask,
1673 poweredOff(
false ,
"stopAdvertising.np");
1677 l2cap_service.
stop();
1689 std::string random_address_info = adapterInfo.addressAndType != visibleAddressAndType ?
" ("+visibleAddressAndType.toString()+
")" :
"";
1691 ", '"+getName()+
"', curSettings"+
to_string(adapterInfo.getCurrentSettingMask())+
1694 ", scanType[native "+
to_string(hci.getCurrentScanType())+
", meta "+
to_string(currentMetaScanType)+
"]"
1696 "], "+l2cap_att_srv.toString()+
", "+javaObjectToString()+
"]");
1697 if( includeDiscoveredDevices ) {
1699 if( devices.
size() > 0 ) {
1701 for(
const auto& p : devices) {
1702 if(
nullptr != p ) {
1703 out.append(
" ").append(p->toString()).append(
"\n");
1714 const uint64_t timestampMS)
noexcept
1719 p.listener->adapterSettingsChanged(*
this, old_settings_, current_settings, changes, timestampMS);
1720 }
catch (std::exception &e) {
1721 ERR_PRINT(
"BTAdapter:CB:NewSettings-CBs %d/%zd: %s of %s: Caught exception %s",
1722 i+1, statusListenerList.size(),
1723 p.listener->toString().c_str(), toString().c_str(), e.what());
1729void BTAdapter::sendAdapterSettingsInitial(
AdapterStatusListener & asl,
const uint64_t timestampMS)
noexcept
1731 const AdapterSetting current_settings = adapterInfo.getCurrentSettingMask();
1732 COND_PRINT(debug_event,
"BTAdapter::sendAdapterSettingsInitial: NONE -> %s, changes NONE: %s",
1733 to_string(current_settings).c_str(), toString().c_str() );
1736 }
catch (std::exception &e) {
1737 ERR_PRINT(
"BTAdapter::sendAdapterSettingsChanged-CB: %s of %s: Caught exception %s",
1738 asl.toString().c_str(), toString().c_str(), e.what());
1742void BTAdapter::sendDeviceUpdated(std::string cause,
BTDeviceRef device, uint64_t timestamp,
EIRDataType updateMask)
noexcept {
1746 if( p.match(device) ) {
1747 p.listener->deviceUpdated(device, updateMask, timestamp);
1749 }
catch (std::exception &e) {
1750 ERR_PRINT(
"BTAdapter::sendDeviceUpdated-CBs (%s) %d/%zd: %s of %s: Caught exception %s",
1751 cause.c_str(), i+1, statusListenerList.size(),
1752 p.listener->toString().c_str(), device->toString().c_str(), e.what());
1760void BTAdapter::mgmtEvHCIAnyHCI(
const MgmtEvent& e)
noexcept {
1761 DBG_PRINT(
"BTAdapter:hci::Any: %s", e.toString().c_str());
1764void BTAdapter::mgmtEvMgmtAnyMgmt(
const MgmtEvent& e)
noexcept {
1765 DBG_PRINT(
"BTAdapter:mgmt:Any: %s", e.toString().c_str());
1769void BTAdapter::mgmtEvDeviceDiscoveringHCI(
const MgmtEvent& e)
noexcept {
1771 mgmtEvDeviceDiscoveringAny(event.getScanType(), event.getEnabled(), event.getTimestamp(),
true );
1774void BTAdapter::mgmtEvDeviceDiscoveringMgmt(
const MgmtEvent& e)
noexcept {
1776 mgmtEvDeviceDiscoveringAny(event.getScanType(), event.getEnabled(), event.getTimestamp(),
false );
1779void BTAdapter::updateDeviceDiscoveringState(
const ScanType eventScanType,
const bool eventEnabled)
noexcept {
1783void BTAdapter::mgmtEvDeviceDiscoveringAny(
const ScanType eventScanType,
const bool eventEnabled,
const uint64_t eventTimestamp,
1784 const bool hciSourced)
noexcept {
1785 const std::string srctkn = hciSourced ?
"hci" :
"mgmt";
1786 ScanType currentNativeScanType = hci.getCurrentScanType();
1794 if( eventEnabled ) {
1796 nextMetaScanType =
changeScanType(currentMetaScanType, eventScanType,
true);
1801 nextMetaScanType = currentMetaScanType;
1803 nextMetaScanType =
changeScanType(currentMetaScanType, eventScanType,
false);
1810 DBG_PRINT(
"BTAdapter:%s:DeviceDiscovering: dev_id %d, policy %s: scanType[native %s -> %s, meta %s -> %s])",
1811 srctkn.c_str(), dev_id,
to_string(discovery_policy).c_str(),
1814 currentNativeScanType = nextNativeScanType;
1815 hci.setCurrentScanType(currentNativeScanType);
1817 DBG_PRINT(
"BTAdapter:%s:DeviceDiscovering: dev_id %d, policy %d: scanType[native %s, meta %s -> %s])",
1818 srctkn.c_str(), dev_id,
to_string(discovery_policy).c_str(),
1819 to_string(currentNativeScanType).c_str(),
1822 currentMetaScanType = nextMetaScanType;
1823 if( isDiscovering() ) {
1827 checkDiscoveryState();
1832 p.listener->discoveringChanged(*
this, currentMetaScanType, eventScanType, eventEnabled, discovery_policy, eventTimestamp);
1833 }
catch (std::exception &except) {
1834 ERR_PRINT(
"BTAdapter:%s:DeviceDiscovering-CBs %d/%zd: %s of %s: Caught exception %s",
1835 srctkn.c_str(), i+1, statusListenerList.size(),
1836 p.listener->toString().c_str(), toString().c_str(), except.what());
1843 0 == getDevicesPausingDiscoveryCount() )
1845 discovery_service.start();
1849void BTAdapter::mgmtEvNewSettingsMgmt(
const MgmtEvent& e)
noexcept {
1850 COND_PRINT(debug_event,
"BTAdapter:mgmt:NewSettings: %s", e.toString().c_str());
1852 const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(event.getSettings());
1854 updateAdapterSettings(
true , new_settings,
true , event.getTimestamp());
1857void BTAdapter::updateAdapterSettings(
const bool off_thread,
const AdapterSetting new_settings,
const bool sendEvent,
const uint64_t timestamp)
noexcept {
1868 old_settings = new_settings;
1870 COND_PRINT(debug_event,
"BTAdapter::updateAdapterSettings: %s -> %s, changes %s: %s, sendEvent %d, offThread %d",
1873 to_string(changes).c_str(), toString().c_str(), sendEvent, off_thread );
1875 updateDataFromAdapterInfo();
1877 if( justPoweredOn ) {
1879 if( hci.resetAllStates(
true) ) {
1880 updateDataFromHCI();
1884 sendAdapterSettingsChanged(old_settings_, new_settings, changes, timestamp);
1887 if( justPoweredOff ) {
1890 std::thread bg(&BTAdapter::poweredOff,
this,
false,
"adapter_settings.0");
1893 poweredOff(
false,
"powered_off.1");
1898void BTAdapter::mgmtEvLocalNameChangedMgmt(
const MgmtEvent& e)
noexcept {
1899 COND_PRINT(debug_event,
"BTAdapter:mgmt:LocalNameChanged: %s", e.toString().c_str());
1901 std::string old_name = getName();
1902 std::string old_shortName = getShortName();
1903 const bool nameChanged = old_name !=
event.getName();
1904 const bool shortNameChanged = old_shortName !=
event.getShortName();
1906 adapterInfo.setName(event.getName());
1908 if( shortNameChanged ) {
1909 adapterInfo.setShortName(event.getShortName());
1911 COND_PRINT(debug_event,
"BTAdapter:mgmt:LocalNameChanged: Local name: %d: '%s' -> '%s'; short_name: %d: '%s' -> '%s'",
1912 nameChanged, old_name.c_str(), getName().c_str(),
1913 shortNameChanged, old_shortName.c_str(), getShortName().c_str());
1915 (void)shortNameChanged;
1923 if( !l2cap_att_srv.open() ) {
1924 ERR_PRINT(
"Adapter[%d]: L2CAP ATT open failed: %s", dev_id, l2cap_att_srv.toString().c_str());
1930 if( !l2cap_att_srv.close() ) {
1931 ERR_PRINT(
"Adapter[%d]: L2CAP ATT close failed: %s", dev_id, l2cap_att_srv.toString().c_str());
1937 std::unique_ptr<L2CAPClient> l2cap_att_ = l2cap_att_srv.accept();
1938 if(
BTRole::Slave == getRole() &&
nullptr != l2cap_att_ && l2cap_att_->getRemoteAddressAndType().isLEAddress() ) {
1939 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter::l2capServer connected.1: (public) %s", l2cap_att_->toString().c_str());
1941 std::unique_lock<std::mutex> lock(mtx_l2cap_att);
1942 l2cap_att = std::move( l2cap_att_ );
1944 cv_l2cap_att.notify_all();
1946 }
else if(
nullptr != l2cap_att_ ) {
1947 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter::l2capServer connected.2: (ignored) %s", l2cap_att_->toString().c_str());
1949 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter::l2capServer connected.0: nullptr");
1953std::unique_ptr<L2CAPClient> BTAdapter::get_l2cap_connection(
const std::shared_ptr<BTDevice>& device) {
1955 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter:get_l2cap_connection(dev_id %d): Not in server mode",
dev_id);
1960 std::unique_lock<std::mutex> lock(mtx_l2cap_att);
1962 while( device->getConnected() && (
nullptr == l2cap_att || l2cap_att->getRemoteAddressAndType() != device->getAddressAndType() ) ) {
1963 std::cv_status s =
wait_until(cv_l2cap_att, lock, timeout_time);
1964 if( std::cv_status::timeout == s && (
nullptr == l2cap_att || l2cap_att->getRemoteAddressAndType() != device->getAddressAndType() ) ) {
1965 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter:get_l2cap_connection(dev_id %d): l2cap_att TIMEOUT",
dev_id);
1969 if(
nullptr != l2cap_att && l2cap_att->getRemoteAddressAndType() == device->getAddressAndType() ) {
1970 std::unique_ptr<L2CAPClient> l2cap_att_ = std::move( l2cap_att );
1971 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter:get_l2cap_connection(dev_id %d): Accept: l2cap_att %s",
dev_id, l2cap_att_->toString().c_str());
1973 }
else if(
nullptr != l2cap_att ) {
1974 std::unique_ptr<L2CAPClient> l2cap_att_ = std::move( l2cap_att );
1975 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter:get_l2cap_connection(dev_id %d): Ignore: l2cap_att %s",
dev_id, l2cap_att_->toString().c_str());
1978 DBG_PRINT(
"L2CAP-ACCEPT: BTAdapter:get_l2cap_connection(dev_id %d): Null: Might got disconnected",
dev_id);
1987 device_list_t failed_devices;
1993 const std::lock_guard<std::mutex> lock(mtx_connectedDevices);
1995 if( device->isValidInstance() && device->getConnected() &&
1997 BTSecurityLevel::NONE < device->getConnSecurityLevel() &&
2003 const uint32_t smp_events = device->smp_events;
2004 if( 0 == smp_events ) {
2005 DBG_PRINT(
"BTAdapter::smp_timeoutfunc(dev_id %d): SMP Timeout: Pairing-Failed %u: %s", dev_id, smp_events, device->toString().c_str());
2006 failed_devices.push_back(device);
2008 DBG_PRINT(
"BTAdapter::smp_timeoutfunc(dev_id %d): SMP Timeout: Ignore-2 %u -> 0: %s", dev_id, smp_events, device->toString().c_str());
2009 device->smp_events = 0;
2012 const uint32_t smp_events = device->smp_events;
2013 if( 0 < smp_events ) {
2014 DBG_PRINT(
"BTAdapter::smp_timeoutfunc(dev_id %d): SMP Timeout: Ignore-1 %u: %s",
dev_id, smp_events, device->toString().c_str());
2015 device->smp_events = 0;
2021 const bool smp_auto = device->isConnSecurityAutoEnabled();
2022 IRQ_PRINT(
"BTAdapter(dev_id %d): SMP Timeout: Start: smp_auto %d, %s", dev_id, smp_auto, device->toString().c_str());
2028 device->hciSMPMsgCallback(device, msg, source);
2029 DBG_PRINT(
"BTAdapter::smp_timeoutfunc(dev_id %d): SMP Timeout: Done: smp_auto %d, %s", dev_id, smp_auto, device->toString().c_str());
2034void BTAdapter::mgmtEvDeviceConnectedHCI(
const MgmtEvent& e)
noexcept {
2042 ad_report.
read_data(event.getData(),
event.getDataSize());
2044 DBG_PRINT(
"BTAdapter::mgmtEvDeviceConnectedHCI(dev_id %d): Event %s, AD EIR %s",
2045 dev_id, e.toString().c_str(), ad_report.
toString(
true).c_str());
2047 int new_connect = 0;
2048 bool device_discovered =
true;
2049 bool slave_unpair =
false;
2050 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2051 if(
nullptr == device ) {
2052 device = findDiscoveredDevice(event.getAddress(), event.getAddressType());
2053 if(
nullptr != device ) {
2054 addSharedDevice(device);
2058 if(
nullptr == device ) {
2059 device = findSharedDevice(event.getAddress(), event.getAddressType());
2060 if(
nullptr != device ) {
2061 addDiscoveredDevice(device);
2069 if(
nullptr == device ) {
2072 device_discovered =
false;
2073 device = BTDevice::make_shared(*
this, ad_report);
2074 addDiscoveredDevice(device);
2075 addSharedDevice(device);
2081 has_smp_keys =
nullptr != findSMPKeyBin( device->getAddressAndType() );
2083 has_smp_keys =
false;
2086 DBG_PRINT(
"BTAdapter:hci:DeviceConnected(dev_id %d): state[role %s, new %d, discovered %d, unpair %d, has_keys %d], %s: %s",
2087 dev_id,
to_string(getRole()).c_str(), new_connect, device_discovered, slave_unpair, has_smp_keys,
2088 e.toString().c_str(), ad_report.
toString().c_str());
2090 if( slave_unpair ) {
2094 if( !has_smp_keys ) {
2096 HCIStatusCode res = mgmt->unpairDevice(dev_id, device->getAddressAndType(),
false );
2098 WARN_PRINT(
"(dev_id %d, new_connect %d): Unpair device failed %s of %s",
2099 dev_id, new_connect,
to_string(res).c_str(), device->getAddressAndType().toString().c_str());
2106 EIRDataType updateMask = device->update(ad_report);
2107 if( 0 == new_connect ) {
2108 WARN_PRINT(
"(dev_id %d, already connected, updated %s): %s, handle %s -> %s,\n %s,\n -> %s",
2109 dev_id,
to_string(updateMask).c_str(), event.toString().c_str(),
2112 device->toString().c_str());
2114 addConnectedDevice(device);
2115 COND_PRINT(debug_event,
"BTAdapter::hci:DeviceConnected(dev_id %d, new_connect %d, updated %s): %s, handle %s -> %s,\n %s,\n -> %s",
2116 dev_id, new_connect,
to_string(updateMask).c_str(), event.toString().c_str(),
2119 device->toString().c_str());
2124 device->setConnSecurity(sec_level_server, io_cap_server);
2126 device->notifyConnected(device, event.getHCIHandle(), io_cap_has);
2128 if( device->isConnSecurityAutoEnabled() ) {
2135 if( p.match(device) ) {
2136 if( EIRDataType::NONE != updateMask ) {
2137 p.listener->deviceUpdated(device, updateMask, ad_report.getTimestamp());
2139 if( 0 < new_connect ) {
2140 p.listener->deviceConnected(device, device_discovered, event.getTimestamp());
2143 }
catch (std::exception &except) {
2144 ERR_PRINT(
"BTAdapter::hci:DeviceConnected-CBs %d/%zd: %s of %s: Caught exception %s",
2145 i+1, statusListenerList.size(),
2146 p.listener->toString().c_str(), device->toString().c_str(), except.what());
2165void BTAdapter::mgmtEvDeviceConnectedMgmt(
const MgmtEvent& e)
noexcept {
2173 ad_report.
read_data(event.getData(),
event.getDataSize());
2175 DBG_PRINT(
"BTAdapter::mgmtEvDeviceConnectedMgmt(dev_id %d): Event %s, AD EIR %s",
2176 dev_id, e.toString().c_str(), ad_report.
toString(
true).c_str());
2179void BTAdapter::mgmtEvConnectFailedHCI(
const MgmtEvent& e)
noexcept {
2182 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2183 if(
nullptr != device ) {
2184 const uint16_t handle = device->getConnectionHandle();
2185 DBG_PRINT(
"BTAdapter::hci:ConnectFailed(dev_id %d): %s, handle %s -> zero,\n -> %s",
2187 device->toString().c_str());
2189 unlockConnect(*device);
2190 device->notifyDisconnected();
2191 removeConnectedDevice(*device);
2193 if( !device->isConnSecurityAutoEnabled() ) {
2197 if( p.match(device) ) {
2198 p.listener->deviceDisconnected(device, event.getHCIStatus(), handle, event.getTimestamp());
2200 }
catch (std::exception &except) {
2201 ERR_PRINT(
"BTAdapter::hci:DeviceDisconnected-CBs %d/%zd: %s of %s: Caught exception %s",
2202 i+1, statusListenerList.size(),
2203 p.listener->toString().c_str(), device->toString().c_str(), except.what());
2207 device->clearData();
2208 removeDiscoveredDevice(device->addressAndType);
2211 WORDY_PRINT(
"BTAdapter::hci:DeviceDisconnected(dev_id %d): Device not tracked: %s",
2212 dev_id, event.toString().c_str());
2216void BTAdapter::mgmtEvHCILERemoteUserFeaturesHCI(
const MgmtEvent& e)
noexcept {
2219 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2220 if(
nullptr != device ) {
2221 COND_PRINT(debug_event,
"BTAdapter::hci:LERemoteUserFeatures(dev_id %d): %s, %s",
2222 dev_id, event.toString().c_str(), device->toString().c_str());
2230 std::thread bg(&BTAdapter::stopDiscoveryImpl,
this,
false ,
true );
2237 discovery_service.start();
2240 addDevicePausingDiscovery(device);
2244 device->notifyLEFeatures(device, event.getFeatures());
2250 WORDY_PRINT(
"BTAdapter::hci:LERemoteUserFeatures(dev_id %d): Device not tracked: %s",
2251 dev_id, event.toString().c_str());
2255void BTAdapter::mgmtEvHCILEPhyUpdateCompleteHCI(
const MgmtEvent& e)
noexcept {
2258 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2259 if(
nullptr != device ) {
2260 COND_PRINT(debug_event,
"BTAdapter::hci:LEPhyUpdateComplete(dev_id %d): %s, %s",
2261 dev_id, event.toString().c_str(), device->toString().c_str());
2263 device->notifyLEPhyUpdateComplete(event.getHCIStatus(), event.getTx(), event.getRx());
2265 WORDY_PRINT(
"BTAdapter::hci:LEPhyUpdateComplete(dev_id %d): Device not tracked: %s",
2266 dev_id, event.toString().c_str());
2270void BTAdapter::mgmtEvDeviceDisconnectedHCI(
const MgmtEvent& e)
noexcept {
2273 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2274 if(
nullptr != device ) {
2275 if( device->getConnectionHandle() != event.getHCIHandle() ) {
2276 WORDY_PRINT(
"BTAdapter::hci:DeviceDisconnected(dev_id %d): ConnHandle mismatch %s\n -> %s",
2277 dev_id, event.toString().c_str(), device->toString().c_str());
2280 DBG_PRINT(
"BTAdapter::hci:DeviceDisconnected(dev_id %d): %s, handle %s -> zero,\n -> %s",
2281 dev_id, event.toString().c_str(),
jau::to_hexstring(event.getHCIHandle()).c_str(),
2282 device->toString().c_str());
2284 unlockConnect(*device);
2285 device->notifyDisconnected();
2286 removeConnectedDevice(*device);
2289 gattServerData =
nullptr;
2292 if( !device->isConnSecurityAutoEnabled() ) {
2296 if( p.match(device) ) {
2297 p.listener->deviceDisconnected(device, event.getHCIReason(), event.getHCIHandle(), event.getTimestamp());
2299 }
catch (std::exception &except) {
2300 ERR_PRINT(
"BTAdapter::hci:DeviceDisconnected-CBs %d/%zd: %s of %s: Caught exception %s",
2301 i+1, statusListenerList.size(),
2302 p.listener->toString().c_str(), device->toString().c_str(), except.what());
2306 device->clearData();
2307 removeDiscoveredDevice(device->addressAndType);
2315 removeSMPKeyBin(device->getAddressAndType(),
true );
2317 SMPKeyBinRef key = findSMPKeyBin(device->getAddressAndType());
2318 if(
nullptr != key ) {
2321 res = getManager().unpairDevice(dev_id, device->getAddressAndType(),
true );
2323 WARN_PRINT(
"(dev_id %d): Unpair device failed %s of %s",
2324 dev_id,
to_string(res).c_str(), device->getAddressAndType().toString().c_str());
2331 WARN_PRINT(
"(dev_id %d): Upload SMPKeyBin failed %s, %s (removing file)",
2332 dev_id,
to_string(res).c_str(), key->toString().c_str());
2333 removeSMPKeyBin(device->getAddressAndType(),
true );
2338 removeDevicePausingDiscovery(*device);
2340 DBG_PRINT(
"BTAdapter::hci:DeviceDisconnected(dev_id %d): Device not connected: %s",
2341 dev_id, event.toString().c_str());
2345 device = findDevicePausingDiscovery(event.getAddress(), event.getAddressType());
2346 if(
nullptr != device ) {
2347 removeDevicePausingDiscovery(*device);
2353void BTAdapter::mgmtEvLELTKReqEventHCI(
const MgmtEvent& e)
noexcept {
2356 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2357 if(
nullptr != device ) {
2361 WORDY_PRINT(
"BTAdapter::hci:LE_LTK_Request(dev_id %d): Device not tracked: %s",
2362 dev_id, event.toString().c_str());
2365void BTAdapter::mgmtEvLELTKReplyAckCmdHCI(
const MgmtEvent& e)
noexcept {
2368 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2369 if(
nullptr != device ) {
2373 WORDY_PRINT(
"BTAdapter::hci:LE_LTK_REPLY_ACK(dev_id %d): Device not tracked: %s",
2374 dev_id, event.toString().c_str());
2377void BTAdapter::mgmtEvLELTKReplyRejCmdHCI(
const MgmtEvent& e)
noexcept {
2380 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2381 DBG_PRINT(
"BTAdapter::hci:LE_LTK_REPLY_REJ(dev_id %d): Ignored: %s (tracked %d)",
2382 dev_id, event.toString().c_str(), (
nullptr!=device));
2386void BTAdapter::mgmtEvLEEnableEncryptionCmdHCI(
const MgmtEvent& e)
noexcept {
2389 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2390 if(
nullptr != device ) {
2394 WORDY_PRINT(
"BTAdapter::hci:LE_ENABLE_ENC(dev_id %d): Device not tracked: %s",
2395 dev_id, event.toString().c_str());
2399void BTAdapter::mgmtEvHCIEncryptionChangedHCI(
const MgmtEvent& e)
noexcept {
2402 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2403 if(
nullptr != device ) {
2408 device->updatePairingState(device, e, evtStatus, pstate);
2410 WORDY_PRINT(
"BTAdapter::hci:ENC_CHANGED(dev_id %d): Device not tracked: %s",
2411 dev_id, event.toString().c_str());
2415void BTAdapter::mgmtEvHCIEncryptionKeyRefreshCompleteHCI(
const MgmtEvent& e)
noexcept {
2418 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2419 if(
nullptr != device ) {
2424 device->updatePairingState(device, e, evtStatus, pstate);
2426 WORDY_PRINT(
"BTAdapter::hci:ENC_KEY_REFRESH_COMPLETE(dev_id %d): Device not tracked: %s",
2427 dev_id, event.toString().c_str());
2431void BTAdapter::mgmtEvPairDeviceCompleteMgmt(
const MgmtEvent& e)
noexcept {
2434 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2435 if(
nullptr != device ) {
2439 device->updatePairingState(device, e, evtStatus, pstate);
2441 WORDY_PRINT(
"BTAdapter::mgmt:PairDeviceComplete(dev_id %d): Device not tracked: %s",
2442 dev_id, event.toString().c_str());
2446void BTAdapter::mgmtEvNewLongTermKeyMgmt(
const MgmtEvent& e)
noexcept {
2450 if(
nullptr != device ) {
2455 WORDY_PRINT(
"BTAdapter::mgmt:NewLongTermKey(dev_id %d): Invalid LTK: %s",
2456 dev_id, event.toString().c_str());
2459 WORDY_PRINT(
"BTAdapter::mgmt:NewLongTermKey(dev_id %d): Device not tracked: %s",
2460 dev_id, event.toString().c_str());
2464void BTAdapter::mgmtEvNewLinkKeyMgmt(
const MgmtEvent& e)
noexcept {
2469 if(
nullptr != device ) {
2474 WORDY_PRINT(
"BTAdapter::mgmt:NewLinkKey(dev_id %d): Invalid LK: %s",
2475 dev_id, event.toString().c_str());
2478 WORDY_PRINT(
"BTAdapter::mgmt:NewLinkKey(dev_id %d): Device not tracked: %s",
2479 dev_id, event.toString().c_str());
2483void BTAdapter::mgmtEvNewIdentityResolvingKeyMgmt(
const MgmtEvent& e)
noexcept {
2485 const EUI48& randomAddress =
event.getRandomAddress();
2487 if( adapterInfo.addressAndType.address == irk.
address && adapterInfo.addressAndType.type == irk.
address_type ) {
2489 visibleAddressAndType.
address = randomAddress;
2493 WORDY_PRINT(
"BTAdapter::mgmt:NewIdentityResolvingKey(dev_id %d): Host Adapter: %s",
2494 dev_id, event.toString().c_str());
2497 if(
nullptr != device ) {
2499 WORDY_PRINT(
"BTAdapter::mgmt:NewIdentityResolvingKey(dev_id %d): Device found (Resolvable): %s, %s",
2500 dev_id, event.toString().c_str(), device->toString().c_str());
2502 WORDY_PRINT(
"BTAdapter::mgmt:NewIdentityResolvingKey(dev_id %d): Device not tracked: %s",
2503 dev_id, event.toString().c_str());
2508void BTAdapter::mgmtEvDeviceFoundHCI(
const MgmtEvent& e)
noexcept {
2513 if(
nullptr == eir ) {
2515 ABORT(
"BTAdapter:hci:DeviceFound: Not sourced from LE_ADVERTISING_REPORT: %s", deviceFoundEvent.
toString().c_str());
2535 if(
nullptr != dev_connected ) {
2537 DBG_PRINT(
"BTAdapter:hci:DeviceFound(1.0, dev_id %d): Discovered but already connected %s [discovered %d, shared %d] -> Drop(1) %s",
2538 dev_id, dev_connected->getAddressAndType().toString().c_str(),
2539 nullptr != dev_discovered,
nullptr != dev_shared, eir->
toString().c_str());
2543 }
else if(
nullptr == dev_discovered ) {
2544 if(
nullptr == dev_shared ) {
2548 dev_shared = BTDevice::make_shared(*
this, *eir);
2549 addDiscoveredDevice(dev_shared);
2550 addSharedDevice(dev_shared);
2551 DBG_PRINT(
"BTAdapter:hci:DeviceFound(1.1, dev_id %d): New undiscovered/unshared %s -> deviceFound(..) %s",
2552 dev_id, dev_shared->getAddressAndType().toString().c_str(), eir->
toString().c_str());
2558 const HCIStatusCode res = mgmt->unpairDevice(dev_id, dev_shared->getAddressAndType(),
false );
2560 WARN_PRINT(
"(dev_id %d): Unpair device failed %s of %s",
2561 dev_id,
to_string(res).c_str(), dev_shared->getAddressAndType().toString().c_str());
2565 bool device_used =
false;
2568 if( p.match(dev_shared) ) {
2569 device_used = p.listener->deviceFound(dev_shared, eir->getTimestamp()) || device_used;
2571 }
catch (std::exception &except) {
2572 ERR_PRINT(
"BTAdapter:hci:DeviceFound-CBs %d/%zd: %s of %s: Caught exception %s",
2573 i+1, statusListenerList.size(),
2574 p.listener->toString().c_str(), dev_shared->toString().c_str(), except.what());
2578 if( !device_used ) {
2581 removeSharedDevice(*dev_shared);
2591 EIRDataType updateMask = dev_shared->update(*eir);
2592 addDiscoveredDevice(dev_shared);
2594 DBG_PRINT(
"BTAdapter:hci:DeviceFound(1.2, dev_id %d): Undiscovered but shared %s -> deviceFound(..) [deviceUpdated(..)] %s",
2595 dev_id, dev_shared->getAddressAndType().toString().c_str(), eir->
toString().c_str());
2600 if( !dev_shared->isPrePaired() ) {
2603 WARN_PRINT(
"(dev_id %d): Unpair device failed: %s, %s",
2604 dev_id,
to_string(res).c_str(), dev_shared->getAddressAndType().toString().c_str());
2608 bool device_used =
false;
2611 if( p.match(dev_shared) ) {
2612 device_used = p.listener->deviceFound(dev_shared, eir->getTimestamp()) || device_used;
2614 }
catch (std::exception &except) {
2615 ERR_PRINT(
"BTAdapter:hci:DeviceFound: %d/%zd: %s of %s: Caught exception %s",
2616 i+1, statusListenerList.size(),
2617 p.listener->toString().c_str(), dev_shared->toString().c_str(), except.what());
2621 if( !device_used ) {
2624 removeSharedDevice(*dev_shared);
2626 sendDeviceUpdated(
"SharedDeviceFound", dev_shared, eir->
getTimestamp(), updateMask);
2633 const EIRDataType updateMask = dev_discovered->update(*eir);
2634 dev_discovered->ts_last_discovery = eir->
getTimestamp();
2635 if(
nullptr == dev_shared ) {
2642 DBG_PRINT(
"BTAdapter:hci:DeviceFound(2.1.1, dev_id %d): Discovered but unshared %s, name changed %s -> deviceFound(..) %s",
2643 dev_id, dev_discovered->getAddressAndType().toString().c_str(),
2645 addSharedDevice(dev_discovered);
2650 bool device_used =
false;
2653 if( p.match(dev_discovered) ) {
2654 device_used = p.listener->deviceFound(dev_discovered, eir->getTimestamp()) || device_used;
2656 }
catch (std::exception &except) {
2657 ERR_PRINT(
"BTAdapter:hci:DeviceFound: %d/%zd: %s of %s: Caught exception %s",
2658 i+1, statusListenerList.size(),
2659 p.listener->toString().c_str(), dev_discovered->toString().c_str(), except.what());
2663 if( !device_used ) {
2666 removeSharedDevice(*dev_discovered);
2670 COND_PRINT(debug_event,
"BTAdapter:hci:DeviceFound(2.1.2, dev_id %d): Discovered but unshared %s, no name change -> Drop(2) %s",
2671 dev_id, dev_discovered->getAddressAndType().toString().c_str(), eir->
toString().c_str());
2680 jau::PLAIN_PRINT(
true,
"BTAdapter:hci:DeviceFound(2.2.1, dev_id %d): Discovered and shared %s, updated %s -> deviceUpdated(..) %s",
2681 dev_id, dev_shared->getAddressAndType().toString().c_str(),
2687 sendDeviceUpdated(
"DiscoveredDeviceFound", dev_shared, eir->
getTimestamp(), updateMask);
2691 jau::PLAIN_PRINT(
true,
"BTAdapter:hci:DeviceFound(2.2.2, dev_id %d): Discovered and shared %s, not-updated -> Drop(3) %s",
2692 dev_id, dev_shared->getAddressAndType().toString().c_str(), eir->
toString().c_str());
2702void BTAdapter::mgmtEvDeviceUnpairedMgmt(
const MgmtEvent& e)
noexcept {
2704 DBG_PRINT(
"BTAdapter:mgmt:DeviceUnpaired: %s", event.toString().c_str());
2706void BTAdapter::mgmtEvPinCodeRequestMgmt(
const MgmtEvent& e)
noexcept {
2709 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2710 if(
nullptr == device ) {
2711 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: Device not tracked: address[%s, %s], %s",
2712 dev_id, event.getAddress().toString().c_str(),
to_string(event.getAddressType()).c_str(),
2713 event.toString().c_str());
2716 DBG_PRINT(
"BTAdapter:mgmt:PinCodeRequest: %s", event.toString().c_str());
2719void BTAdapter::mgmtEvAuthFailedMgmt(
const MgmtEvent& e)
noexcept {
2722 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2723 if(
nullptr == device ) {
2724 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: Device not tracked: address[%s, %s], %s",
2725 dev_id, event.getAddress().toString().c_str(),
to_string(event.getAddressType()).c_str(),
2726 event.toString().c_str());
2732void BTAdapter::mgmtEvUserConfirmRequestMgmt(
const MgmtEvent& e)
noexcept {
2735 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2736 if(
nullptr == device ) {
2737 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: Device not tracked: address[%s, %s], %s",
2738 dev_id, event.getAddress().toString().c_str(),
to_string(event.getAddressType()).c_str(),
2739 event.toString().c_str());
2743 DBG_PRINT(
"BTAdapter:mgmt:UserConfirmRequest: %s", event.toString().c_str());
2746void BTAdapter::mgmtEvUserPasskeyRequestMgmt(
const MgmtEvent& e)
noexcept {
2749 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2750 if(
nullptr == device ) {
2751 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: Device not tracked: address[%s, %s], %s",
2752 dev_id, event.getAddress().toString().c_str(),
to_string(event.getAddressType()).c_str(),
2753 event.toString().c_str());
2756 DBG_PRINT(
"BTAdapter:mgmt:UserPasskeyRequest: %s", event.toString().c_str());
2760void BTAdapter::mgmtEvPasskeyNotifyMgmt(
const MgmtEvent& e)
noexcept {
2763 BTDeviceRef device = findConnectedDevice(event.getAddress(), event.getAddressType());
2764 if(
nullptr == device ) {
2765 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: Device not tracked: address[%s, %s], %s",
2766 dev_id, event.getAddress().toString().c_str(),
to_string(event.getAddressType()).c_str(),
2767 event.toString().c_str());
2770 DBG_PRINT(
"BTAdapter:mgmt:PasskeyNotify: %s", event.toString().c_str());
2776 BTDeviceRef device = findConnectedDevice(addressAndType.address, addressAndType.type);
2777 if(
nullptr == device ) {
2778 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: Device not tracked: address%s: %s, %s",
2779 dev_id, addressAndType.toString().c_str(),
2780 msg.toString().c_str(), source.toString().c_str());
2783 if( device->getConnectionHandle() != source.handle ) {
2784 WORDY_PRINT(
"BTAdapter:hci:SMP: dev_id %d: ConnHandle mismatch address%s: %s, %s\n -> %s",
2785 dev_id, addressAndType.toString().c_str(),
2786 msg.toString().c_str(), source.toString().c_str(), device->toString().c_str());
2790 device->hciSMPMsgCallback(device, msg, source);
2803 DBG_PRINT(
"sendDevicePairingState (dev_id %d): created SMPKeyBin: %s", dev_id, key.
toString().c_str());
2804 addSMPKeyBin( std::make_shared<SMPKeyBin>(key),
true );
2806 WARN_PRINT(
"(dev_id %d): created SMPKeyBin invalid: %s", dev_id, key.
toString().c_str());
2810 const SMPKeyBinRef key = findSMPKeyBin( device->getAddressAndType() );
2811 if(
nullptr != key ) {
2812 bool res = device->setSMPKeyBin(*key);
2814 WARN_PRINT(
"(dev_id %d): device::setSMPKeyBin() failed %d, %s", dev_id, res, key->toString().c_str());
2820 removeSMPKeyBin(device->getAddressAndType(),
true );
2826 if( p.match(device) ) {
2827 p.listener->devicePairingState(device, state, mode, timestamp);
2829 }
catch (std::exception &except) {
2830 ERR_PRINT(
"BTAdapter::sendDevicePairingState: %d/%zd: %s of %s: Caught exception %s",
2831 i+1, statusListenerList.size(),
2832 p.listener->toString().c_str(), device->toString().c_str(), except.what());
2843void BTAdapter::notifyPairingStageDone(
const BTDeviceRef& device, uint64_t timestamp)
noexcept {
2845 removeDevicePausingDiscovery(*device);
2850void BTAdapter::sendDeviceReady(
BTDeviceRef device, uint64_t timestamp)
noexcept {
2852 removeDevicePausingDiscovery(*device);
2858 if( device->isValidInstance() && device->getConnected() && device->allowDisconnect ) {
2859 if( p.match(device) ) {
2860 p.listener->deviceReady(device, timestamp);
2863 }
catch (std::exception &except) {
2864 ERR_PRINT(
"BTAdapter::sendDeviceReady: %d/%zd: %s of %s: Caught exception %s",
2865 i+1, statusListenerList.size(),
2866 p.listener->toString().c_str(), device->toString().c_str(), except.what());
static constexpr const bool _print_device_lists
std::string toString() const noexcept
bool isCurrentSettingBitSet(const AdapterSetting bit) const noexcept
AdapterSetting getCurrentSettingMask() const noexcept
BTAdapter status listener for remote BTDevice discovery events: Added, updated and removed; as well a...
Unique Bluetooth EUI48 address and BDAddressType tuple.
std::string toString() const noexcept
BTMode getBTMode() const noexcept
Returns the current BTMode of this adapter.
HCIStatusCode setName(const std::string &name, const std::string &short_name) noexcept
Sets the name and short-name.
HCIStatusCode stopAdvertising() noexcept
Ends advertising.
HCIStatusCode setPrivacy(const bool enable) noexcept
Toggle adapter privacy address mode, i.e.
void setSMPKeyPath(const std::string path) noexcept
Set the adapter's persistent storage directory for SMPKeyBin files.
std::string toString() const noexcept override
HCIStatusCode setDefaultConnParam(const uint16_t conn_interval_min=8, const uint16_t conn_interval_max=40, const uint16_t conn_latency=0, const uint16_t supervision_timeout=getHCIConnSupervisorTimeout(0, 50)) noexcept
Set default connection parameter of incoming connections for this adapter when in server mode,...
BTDeviceRef findSharedDevice(const EUI48 &address, const BDAddressType addressType) noexcept
Returns shared BTDevice if found, otherwise nullptr.
~BTAdapter() noexcept override
Releases this instance.
HCIStatusCode reset() noexcept
Reset the adapter.
HCIStatusCode startDiscovery(const DBGattServerRef &gattServerData_=nullptr, const DiscoveryPolicy policy=DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_READY, const bool le_scan_active=true, const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint8_t filter_policy=0x00, const bool filter_dup=true) noexcept
Starts discovery.
bool isValid() const noexcept
Returns whether the adapter is valid, i.e.
size_type removeDiscoveredDevices() noexcept
Discards all discovered devices.
void printStatusListenerList() noexcept
HCIStatusCode uploadKeys(SMPKeyBin &bin, const bool write) noexcept
Associate the given SMPKeyBin with the contained remote address, i.e.
BTDeviceRef findDiscoveredDevice(const EUI48 &address, const BDAddressType addressType) noexcept
Returns shared BTDevice if found, otherwise nullptr.
HCIStatusCode initialize(const BTMode btMode, const bool powerOn) noexcept
Initialize the adapter with default values, including power-on.
void setServerConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap) noexcept
Sets the given BTSecurityLevel and SMPIOCapability for connecting device when in server (peripheral) ...
HCIStatusCode stopDiscovery() noexcept
Ends discovery.
const uint16_t dev_id
Adapter's internal temporary device id.
bool removeDeviceFromWhitelist(const BDAddressAndType &addressAndType)
Remove the given device from the adapter's autoconnect whitelist.
bool isPowered() const noexcept
Returns whether the adapter is valid, plugged in and powered.
bool isDeviceWhitelisted(const BDAddressAndType &addressAndType) noexcept
Returns true, if the adapter's device is already whitelisted.
BTRole getRole() const noexcept
Return the current BTRole of this adapter.
size_type removeAllStatusListener() noexcept
Remove all status listener from the list.
HCIStatusCode startAdvertising(const DBGattServerRef &gattServerData_, EInfoReport &eir, EIRDataType adv_mask=EIRDataType::FLAGS|EIRDataType::SERVICE_UUID, EIRDataType scanrsp_mask=EIRDataType::NAME|EIRDataType::CONN_IVAL, const uint16_t adv_interval_min=160, const uint16_t adv_interval_max=480, const AD_PDU_Type adv_type=AD_PDU_Type::ADV_IND, const uint8_t adv_chan_map=0x07, const uint8_t filter_policy=0x00) noexcept
Starts advertising.
bool removeStatusListener(const AdapterStatusListenerRef &l) noexcept
Remove the given listener from the list.
void printDeviceLists() noexcept
Print the internally maintained BTDevice lists to stderr:
HCIStatusCode setDefaultLE_PHY(const LE_PHYs Tx, const LE_PHYs Rx) noexcept
Sets default preference of LE_PHYs.
bool addDeviceToWhitelist(const BDAddressAndType &addressAndType, const HCIWhitelistConnectType ctype, const uint16_t conn_interval_min=12, const uint16_t conn_interval_max=12, const uint16_t conn_latency=0, const uint16_t supervision_timeout=getHCIConnSupervisorTimeout(0, 15))
Add the given device to the adapter's autoconnect whitelist.
BTAdapter(const BTAdapter::ctor_cookie &cc, BTManagerRef mgmt_, AdapterInfo adapterInfo_) noexcept
Private ctor for private BTAdapter::make_shared() intended for friends.
bool addStatusListener(const AdapterStatusListenerRef &l) noexcept
Add the given listener to the list if not already present.
HCIStatusCode setSecureConnections(const bool enable) noexcept
Enable or disable Secure Connections (SC) of the adapter.
jau::darray< BTDeviceRef > getDiscoveredDevices() const noexcept
Returns discovered devices from the last discovery.
bool setPowered(const bool power_on) noexcept
Set the power state of the adapter.
bool removeDiscoveredDevice(const BDAddressAndType &addressAndType) noexcept
Discards matching discovered devices.
void close() noexcept
Closes this instance, usually being called by destructor or when this adapter is being removed as rec...
BTDevice represents one remote Bluetooth device.
BDAddressAndType addressAndType
Device's unique mac address and type tuple, might be its initially reported (resolvable) random addre...
static void validateSecParam(const BTSecurityLevel sec_level, const SMPIOCapability io_cap, BTSecurityLevel &res_sec_level, SMPIOCapability &res_io_cap) noexcept
Returns the validated security parameter BTSecurityLevel and SMPIOCapability in the designated refere...
HCIStatusCode disconnect(const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION) noexcept
Disconnect the LE or BREDR peer's GATT and HCI connection.
std::string toString() const noexcept override
Collection of 'Extended Advertising Data' (EAD), 'Advertising Data' (AD) or 'Extended Inquiry Respons...
std::string toString(const bool includeServices=true) const noexcept
jau::EUI48 const & getAddress() const noexcept
void setSource(Source s, bool ext) noexcept
void setFlags(GAPFlags f) noexcept
void setAddressType(BDAddressType at) noexcept
uint64_t getTimestamp() const noexcept
bool addService(const std::shared_ptr< const jau::uuid_t > &uuid) noexcept
@ EIR
Extended Inquiry Response (EIR)
void setConnInterval(const uint16_t min, const uint16_t max) noexcept
Set slave connection interval range.
int read_data(uint8_t const *data, uint8_t const data_length) noexcept
Reads the Extended Inquiry Response (EIR) or (Extended) Advertising Data (EAD or AD) segments and ret...
void setTimestamp(uint64_t ts) noexcept
BDAddressType getAddressType() const noexcept
void setAddress(jau::EUI48 const &a) noexcept
const jau::fraction_i64 HCI_COMMAND_POLL_PERIOD
Poll period for certain HCI commands actively waiting for clearance, defaults to 125ms.
const jau::fraction_i64 HCI_COMMAND_COMPLETE_REPLY_TIMEOUT
Timeout for HCI command complete replies, defaults to 10s.
A thread safe singleton handler of the HCI control channel to one controller (BT adapter)
bool use_ext_adv() const noexcept
Use extended advertising if LE_Features::LE_Ext_Adv is set (Bluetooth 5.0).
void setBTMode(const BTMode mode) noexcept
bool use_ext_conn() const noexcept
Use extended connection if HCI_LE_Extended_Create_Connection is supported (Bluetooth 5....
bool isOpen() const noexcept
Returns true if this mgmt instance is open, connected and hence valid, otherwise false.
HCIStatusCode le_clear_resolv_list() noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.40 LE Clear Resolving List command.
HCIStatusCode le_enable_adv(const bool enable) noexcept
Enables or disabled advertising.
HCIStatusCode resetAdapter(const PostShutdownFunc &user_post_shutdown)
Complete adapter reset.
void clearAllCallbacks() noexcept
Removes all MgmtEventCallbacks from all MgmtEvent::Opcode lists and all SMPSecurityReqCallbacks.
LE_Features le_get_local_features() noexcept
Return previously fetched LE_Features for the controller via initSupCommands() via resetAllStates()
bool resetAllStates(const bool powered_on) noexcept
Reset all internal states, i.e.
ScanType getCurrentScanType() const noexcept
HCIStatusCode getLocalVersion(HCILocalVersion &version) noexcept
HCIStatusCode le_set_addr_resolv_enable(const bool enable) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.44 LE Set Address Resolution Enable command.
bool use_ext_scan() const noexcept
Use extended scanning if HCI_LE_Set_Extended_Scan_Parameters and HCI_LE_Set_Extended_Scan_Enable is s...
bool close() noexcept override
Closing the L2CAP socket, see specializations.
@ SET_SECURE_CONN
LE Secure Connections: 0x01 enables SC mixed, 0x02 enables SC only mode; Core Spec >= 4....
uint16_t opcode, uint16_t dev-id, uint16_t param_size
@ HCI_ENC_KEY_REFRESH_COMPLETE
@ HCI_LE_PHY_UPDATE_COMPLETE
std::string toString() const noexcept override
mgmt_addr_info { EUI48, uint8_t type }, uint8_t status
mgmt_addr_info { EUI48, uint8_t type }, uint8_t status
mgmt_addr_info { EUI48, uint8_t type }, uint32_t flags, uint16_t eir_len; uint8_t *eir
mgmt_addr_info { EUI48, uint8_t type }, uint8_t reason
mgmt_addr_info { EUI48, uint8_t type }, int8_t rssi, uint32_t flags, uint16_t eir_len; uint8_t *eir
const EInfoReport * getEIR() const noexcept
Returns reference to the immutable EInfoReport, assuming creation occurred via HCIHandler.
mgmt_addr_info { EUI48, uint8_t type },
mgmt_addr_info { EUI48, uint8_t type }, HCIStatusCode status (1 Octet) uint8_t enc_enabled (1 Octet)
mgmt_addr_info { EUI48, uint8_t type }, HCIStatusCode status (1 Octet)
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.24 LE Enable Encryption command.
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.25 LE Long Term Key Request Reply command.
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.26 LE Long Term Key Request Negative Reply command.
BT Core Spec v5.2: Vol 4, Part E HCI: 7.7.65.5 LE Long Term Key Request event.
mgmt_addr_info { EUI48, uint8_t type }, uint8_t Tx (8 Octets) uint8_t Rx (8 Octets)
mgmt_addr_info { EUI48, uint8_t type }, uint64_t features (8 Octets)
uint8_t name[MGMT_MAX_NAME_LENGTH]; uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
uint8_t store_hint, EUI48 random_address; MgmtIdentityResolvingKey key
uint8_t store_hint, MgmtLinkKey key
uint8_t store_hint, MgmtLongTermKey key
mgmt_addr_info { EUI48, uint8_t type }, MgmtStatus (1 octet)
mgmt_addr_info { EUI48, uint8_t type }, uint32_t passkey uint8_t entered
mgmt_addr_info { EUI48, uint8_t type }, uint8_t secure
mgmt_addr_info { EUI48, uint8_t type }, uint8_t confirm_hint uint32_t value
mgmt_addr_info { EUI48, uint8_t type },
Storage for SMP keys including required connection parameter per local adapter and remote device.
static std::vector< SMPKeyBin > readAllForLocalAdapter(const BDAddressAndType &localAddress, const std::string &dname, const bool verbose_)
std::string toString() const noexcept
constexpr bool isValid() const noexcept
Returns true if.
static SMPKeyBin create(const BTDevice &device)
Create a new SMPKeyBin instance based upon given BTDevice's BTSecurityLevel, SMPPairingState,...
Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU) encoded messages over L2CA...
Vol 3, Part H: 3.5.5 Pairing Failed message.
constexpr_atomic void clear() noexcept
Like std::vector::clear(), but ending with zero capacity.
bool(* equal_comparator)(const value_type &a, const value_type &b)
Generic value_type equal comparator to be user defined for e.g.
constexpr_atomic size_type size() const noexcept
Like std::vector::size().
constexpr iterator begin()
Returns an jau::cow_rw_iterator to the first element of this CoW storage.
constexpr iterator end() noexcept
constexpr size_type size() const noexcept
Like std::vector::size().
constexpr void push_back(const value_type &x)
Like std::vector::push_back(), copy.
constexpr iterator begin() noexcept
constexpr iterator erase(const_iterator pos)
Like std::vector::erase(), removes the elements at pos.
constexpr void clear() noexcept
Like std::vector::clear(), but ending with zero capacity.
static bool getBooleanProperty(const std::string &name, const bool default_value) noexcept
Returns the boolean value of the environment's variable 'name', or the 'default_value' if the environ...
static environment & get(const std::string &root_prefix_domain="jau") noexcept
Static singleton initialization of this project's environment with the given global root prefix_domai...
constexpr int_type to_ms() const noexcept
Convenient shortcut to to_num_of(1_ms)
This class provides a RAII-style Sequentially Consistent (SC) data race free (DRF) critical block.
Service runner, a reusable dedicated thread performing custom user services.
bool stop() noexcept
Stops this service, if running.
bool shall_stop2(int dummy) noexcept
Helper function to easy FunctionDef usage w/o creating a lambda alike capture with same semantics as ...
A simple timer for timeout and interval applications, using one dedicated service_runner thread per i...
bool stop() noexcept
Stop timer, see service_runner::stop()
bool shall_stop() const noexcept
Returns true if timer shall stop.
static const uint8_t filter_policy
static const uint16_t le_scan_interval
static const uint16_t le_scan_window
static const bool filter_dup
static bool le_scan_active
static const uint16_t adv_interval_max
static jau::sc_atomic_bool sync_data
static const uint8_t adv_chan_map
static bool startAdvertising(BTAdapter *a, std::string msg)
static const uint16_t adv_interval_min
static const AD_PDU_Type adv_type
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
#define COND_PRINT(C,...)
Use for conditional plain messages, prefix '[elapsed_time] '.
#define WORDY_PRINT(...)
Use for environment-variable environment::VERBOSE conditional verbose messages, prefix '[elapsed_time...
#define ABORT(...)
Use for unconditional ::abort() call with given messages, prefix '[elapsed_time] ABORT @ file:line fu...
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
#define ERR_PRINT2(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
#define WARN_PRINT(...)
Use for unconditional warning messages, prefix '[elapsed_time] Warning @ FILE:LINE FUNC: '.
#define IRQ_PRINT(...)
Use for unconditional interruption messages, prefix '[elapsed_time] Interrupted @ FILE:LINE FUNC: '.
constexpr UnaryFunction for_each_fidelity(InputIt first, InputIt last, UnaryFunction f)
Like jau::for_each(), see above.
std::string to_string(const alphabet &v) noexcept
#define PRAGMA_DISABLE_WARNING_PUSH
#define PRAGMA_DISABLE_WARNING_STRINGOP_OVERFLOW
#define PRAGMA_DISABLE_WARNING_POP
HCIStatusCode to_HCIStatusCode(const MgmtStatus mstatus) noexcept
constexpr const bool CONSIDER_HCI_CMD_FOR_SMP_STATE
constexpr const jau::fraction_i64 THREAD_SHUTDOWN_TIMEOUT_MS
Maximum time in fractions of seconds to wait for a thread shutdown.
SMPPairingState
SMP Pairing Process state definition.
constexpr const bool SCAN_DISABLED_POST_CONNECT
constexpr const jau::fraction_i64 L2CAP_CLIENT_CONNECT_TIMEOUT_MS
Maximum time in fractions of seconds to wait for L2CAP client connection when adapter is in server mo...
constexpr const jau::fraction_i64 SMP_NEXT_EVENT_TIMEOUT_MS
Maximum time in fractions of seconds to wait for the next SMP event.
constexpr bool hasSMPIOCapabilityAnyIO(const SMPIOCapability ioc) noexcept
SMPIOCapability
Vol 3, Part H, 2.3.2 IO capabilities.
constexpr const jau::nsize_t MAX_BACKGROUND_DISCOVERY_RETRY
Maximum number of enabling discovery in background in case of failure.
constexpr const bool USE_LINUX_BT_SECURITY
@ PASSKEY_NOTIFY
Phase 2: Authentication (MITM) PASSKEY (produced by this responder adapter, acting as peripheral GATT...
@ COMPLETED
Phase 3: Key & value distribution completed by responding (slave) device sending SMPIdentInfoMsg (#1)...
@ NUMERIC_COMPARE_EXPECTED
Phase 2: Authentication (MITM) Numeric Comparison Reply expected now, see PairingMode::NUMERIC_COMPAR...
@ NONE
No pairing in process.
@ PASSKEY_EXPECTED
Phase 2: Authentication (MITM) PASSKEY expected now, see PairingMode::PASSKEY_ENTRY_ini.
@ KEY_DISTRIBUTION
Phase 3: Key & value distribution started after SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Conn...
@ NONE
Denoting no or invalid link key type.
@ NONE
Denoting no or invalid long term key type.
@ UNSET
Denoting unset value, i.e.
@ NO_INPUT_NO_OUTPUT
No input not output, value 3.
std::shared_ptr< BTManager > BTManagerRef
BTMode
Bluetooth adapter operating mode.
std::shared_ptr< AdapterStatusListener > AdapterStatusListenerRef
HCIWhitelistConnectType
HCI Whitelist connection type.
DiscoveryPolicy
Discovery policy defines the BTAdapter discovery mode after connecting a remote BTDevice:
constexpr ScanType changeScanType(const ScanType current, const ScanType changeType, const bool changeEnable) noexcept
std::shared_ptr< BTDevice > BTDeviceRef
std::string to_string(const DiscoveryPolicy v) noexcept
LE_PHYs
LE Transport PHY bit values.
ScanType
Meta ScanType as derived from BTMode, with defined value mask consisting of BDAddressType bits.
constexpr AdapterSetting getAdapterSettingMaskDiff(const AdapterSetting setting_a, const AdapterSetting setting_b) noexcept
AdapterSetting
Adapter Setting Bits.
constexpr bool isAdapterSettingBitSet(const AdapterSetting mask, const AdapterSetting bit) noexcept
BDAddressType
BT Core Spec v5.2: Vol 3, Part C Generic Access Profile (GAP): 15.1.1.1 Public Bluetooth address.
BTSecurityLevel
Bluetooth Security Level.
AD_PDU_Type
LE Advertising (AD) Protocol Data Unit (PDU) Types.
PairingMode
Bluetooth secure pairing mode.
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
constexpr bool is_set(const LE_Features mask, const LE_Features bit) noexcept
EIRDataType
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
@ NONE
Zero mode, neither DUAL, BREDR nor LE.
@ LE_Encryption
LE_Encryption.
@ PAUSE_CONNECTED_UNTIL_PAIRED
Pause discovery until all connected BTDevice are optionally SMP paired (~120ms) without GATT service ...
@ PAUSE_CONNECTED_UNTIL_READY
Pause discovery until all connected BTDevice reach readiness inclusive optional SMP pairing (~120ms) ...
@ ALWAYS_ON
Always keep discovery enabled, i.e.
@ AUTO_OFF
Turn off discovery when connected and leave discovery disabled, if turned off by host system.
@ BDADDR_LE_RANDOM
Bluetooth LE random address, see BLERandomAddressType.
@ BDADDR_UNDEFINED
Undefined.
@ Master
Master or central role, discovering remote devices and initiating connection.
@ Slave
Slave or peripheral role, advertising and waiting for connections to accept.
@ RESOLVABLE_OR_RANDOM
Controller Resolved Private Address or Random Address.
@ PUBLIC
Public Device Address.
@ RESOLVABLE_OR_PUBLIC
Controller Resolved Private Address or Public Address.
@ ENC_AUTH
Encryption and authentication (MITM).
@ NONE
No encryption and no authentication.
@ PRE_PAIRED
Reusing encryption keys from previous pairing.
@ PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED
@ REMOTE_USER_TERMINATED_CONNECTION
std::shared_ptr< DBGattService > DBGattServiceRef
std::shared_ptr< DBGattServer > DBGattServerRef
void sync() noexcept
Synchronizes filesystems, i.e.
fraction_timespec getMonotonicTime() noexcept
Returns current monotonic time since Unix Epoch 00:00:00 UTC on 1970-01-01.
jau::function< R(A...)> bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept
Bind given class instance and non-void member function to an anonymous function using func_member_tar...
constexpr uint32_t number(const iostate rhs) noexcept
@ timeout
Input or output operation failed due to timeout.
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
void PLAIN_PRINT(const bool printPrefix, const char *format,...) noexcept
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.
void INFO_PRINT(const char *format,...) noexcept
Use for unconditional informal messages, prefix '[elapsed_time] Info: '.
std::cv_status wait_until(std::condition_variable &cv, std::unique_lock< std::mutex > &lock, const fraction_timespec &absolute_time, const bool monotonic=true) noexcept
wait_until causes the current thread to block until the condition variable is notified,...
void print_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::snsize_t skip_frames=2) noexcept
Prints the de-mangled backtrace string separated by newline excluding this function to stderr,...
uint64_t getCurrentMilliseconds() noexcept
Returns current monotonic time in milliseconds.
bool sleep_for(const fraction_timespec &relative_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_for causes the current thread to block until a specific amount of time has passed.
Representing ACL Datas' L2CAP Frame.
@ START_NON_AUTOFLUSH_HOST
0b00: Start of a non-automatically-flushable PDU from Host to Controller.
std::string toString() noexcept
Used for MgmtLoadIdentityResolvingKeyCmd and MgmtEvtNewIdentityResolvingKey.
BDAddressType address_type
Used for MgmtLoadLinkKeyCmd and MgmtEvtNewLinkKey.
Used for MgmtLoadLongTermKeyCmd and MgmtEvtNewLongTermKey.
BDAddressType address_type
0 reserved, 1 le public, 2 le static random address.
uint8_t enc_size
Encryption Size.
MgmtLTKType key_type
Describing type of key, i.e.
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
A 128-bit packed uint8_t data array.