43#include "HCIIoctl.hpp"
62MgmtEnv::MgmtEnv() noexcept
65 MGMT_READER_THREAD_POLL_TIMEOUT(
jau::
environment::getFractionProperty("
direct_bt.mgmt.reader.timeout", 10_s, 1500_ms , 365_d ) ),
66 MGMT_COMMAND_REPLY_TIMEOUT(
jau::
environment::getFractionProperty("
direct_bt.mgmt.cmd.timeout", 3_s, 1500_ms , 365_d ) ),
68 jau::
max(MGMT_COMMAND_REPLY_TIMEOUT, 6_s) ,
69 MGMT_COMMAND_REPLY_TIMEOUT , 365_d ) ),
72 MGMT_READ_PACKET_MAX_RETRY( MGMT_EVT_RING_CAPACITY )
83 if( !comm.is_open() ) {
85 ERR_PRINT(
"BTManager::reader: Not connected");
90 len = comm.read(rbuffer.get_wptr(), rbuffer.size(), env.MGMT_READER_THREAD_POLL_TIMEOUT);
95 WARN_PRINT(
"BTManager::reader: length mismatch %zu < MGMT_HEADER_SIZE(%u) + %u, %s", len2,
MGMT_HEADER_SIZE, paramSize, rbuffer.toString().c_str());
101 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO RECV (CMD) %s", event->toString().c_str());
102 if( mgmtEventRing.isFull() ) {
103 const jau::nsize_t dropCount = mgmtEventRing.capacity()/4;
104 mgmtEventRing.drop(dropCount);
105 WARN_PRINT(
"BTManager-IO RECV Drop (%u oldest elements of %u capacity, ring full)", dropCount, mgmtEventRing.capacity());
107 if( !mgmtEventRing.putBlocking( std::move( event ), 0_s ) ) {
108 ERR_PRINT2(
"mgmtEventRing put: %s", mgmtEventRing.toString().c_str());
113 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO RECV (ADD) %s", event->toString().c_str());
114 std::thread adapterAddedThread(&BTManager::processAdapterAdded,
this, std::move( event) );
115 adapterAddedThread.detach();
117 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO RECV (REM) %s", event->toString().c_str());
118 std::thread adapterRemovedThread(&BTManager::processAdapterRemoved,
this, std::move( event ) );
119 adapterRemovedThread.detach();
122 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO RECV (CB) %s", event->toString().c_str());
123 sendMgmtEvent( *event );
125 }
else if( 0 > len && ETIMEDOUT != errno && !comm.interrupted() ) {
126 ERR_PRINT(
"BTManager::reader: HCIComm read: Error res %d, %s", len, toString().c_str());
128 }
else if( ETIMEDOUT != errno && !comm.interrupted() ) {
129 WORDY_PRINT(
"BTManager::reader: HCIComm read: IRQed res %d, %s", len, toString().c_str());
135 WORDY_PRINT(
"BTManager::reader: Ended. Ring has %u entries flushed", mgmtEventRing.size());
136 mgmtEventRing.clear();
140 const uint16_t dev_id =
event.getDevID();
147 cb.getCallback()(event);
148 } catch (std::exception &e) {
149 ERR_PRINT(
"BTManager::sendMgmtEvent-CBs %d/%zd: MgmtAdapterEventCallback %s : Caught exception %s",
150 invokeCount+1, mgmtEventCallbackList.
size(),
157 COND_PRINT(env.DEBUG_EVENT,
"BTManager::sendMgmtEvent: Event %s -> %d/%zd callbacks", event.toString().c_str(), invokeCount, mgmtEventCallbackList.size());
162 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
163 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO SENT %s", req.toString().c_str());
165 if ( comm.write( pdu.
get_ptr(), pdu.
size() ) < 0 ) {
166 ERR_PRINT(
"BTManager::sendWithReply: HCIComm write error, req %s", req.toString().c_str());
173 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
179 int32_t retryCount = 0;
180 while( retryCount < env.MGMT_READ_PACKET_MAX_RETRY ) {
182 std::unique_ptr<MgmtEvent> res;
183 if( !mgmtEventRing.getBlocking(res, timeout) ||
nullptr == res ) {
185 ERR_PRINT(
"BTManager::sendWithReply.X: nullptr result (timeout -> abort): req %s", req.toString().c_str());
187 }
else if( !res->validate(req) ) {
190 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO RECV sendWithReply: res mismatch (drop evt, retryCount %d): res %s; req %s",
191 retryCount, res->toString().c_str(), req.toString().c_str());
194 COND_PRINT(env.DEBUG_EVENT,
"BTManager-IO RECV sendWithReply: res %s; req %s", res->toString().c_str(), req.toString().c_str());
201std::unique_ptr<AdapterInfo> BTManager::readAdapterInfo(
const uint16_t dev_id)
noexcept {
202 std::unique_ptr<AdapterInfo> adapterInfo(
nullptr);
205 std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
206 if(
nullptr == res ) {
215 if( dev_id != adapterInfo->dev_id ) {
216 ABORT(
"readAdapterSettings dev_id=%d != dev_id=%d: %s", adapterInfo->dev_id, dev_id, adapterInfo->toString().c_str());
219 DBG_PRINT(
"readAdapterSettings[%d]: End: %s", dev_id, adapterInfo->toString().c_str());
235 constexpr const uint8_t debug_keys = 0;
236 constexpr const uint8_t ssp_on_param = 0x01;
237 constexpr const uint8_t sc_on_param = 0x01;
242 std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
243 if(
nullptr == res ) {
252 if( dev_id != adapterInfo.dev_id ) {
253 ABORT(
"initializeAdapter dev_id=%d != dev_id=%d: %s", adapterInfo.dev_id, dev_id, adapterInfo.toString().c_str());
256 DBG_PRINT(
"initializeAdapter[%d, BTMode %s]: Start: %s", dev_id,
to_string(
btMode).c_str(), adapterInfo.toString().c_str());
260 DBG_PRINT(
"initializeAdapter[%d]: clearIdentityResolvingKeys: %s", dev_id,
to_string(res0).c_str());
263 current_settings = adapterInfo.getCurrentSettingMask();
268 zero_privacy_irk.
clear();
269 setPrivacy(dev_id, 0x00, zero_privacy_irk, current_settings);
275 setDiscoverable(dev_id, 0, 0, current_settings);
284 setDiscoverable(dev_id, 0, 0, current_settings);
328 std::vector<MgmtDefaultParam> params = readDefaultSysParam(dev_id);
329 DBG_PRINT(
"BTManager::initializeAdapter[%d]: SysParam-Pre: %zd", dev_id, params.size());
330 for(
size_t i=0; i<params.size(); ++i) {
334 setDefaultConnParam(dev_id);
336 std::vector<MgmtDefaultParam> params = readDefaultSysParam(dev_id);
337 DBG_PRINT(
"BTManager::initializeAdapter[%d]: SysParam-Post: %zd", dev_id, params.size());
338 for(
size_t i=0; i<params.size(); ++i) {
351 adapterInfo.setCurrentSettingMask(current_settings);
353 std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
354 if(
nullptr == res ) {
363 if( dev_id != adapterInfo.dev_id ) {
364 ABORT(
"initializeAdapter dev_id=%d != dev_id=%d: %s", adapterInfo.dev_id, dev_id, adapterInfo.toString().c_str());
368 ERR_PRINT(
"initializeAdapter[%d, BTMode %s]: Fail: Couldn't power-on: %s",
372 DBG_PRINT(
"initializeAdapter[%d, BTMode %s]: OK: %s", dev_id,
to_string(
btMode).c_str(), adapterInfo.toString().c_str());
379BTManager::BTManager() noexcept
381 rbuffer(ClientMaxMTU,
jau::
lb_endian_t::little), comm(HCI_DEV_NONE, HCI_CHANNEL_CONTROL),
386 mgmtEventRing(env.MGMT_EVT_RING_CAPACITY),
387 allowClose( comm.is_open() )
390 ERR_PRINT(
"BTManager::ctor: Setting sighandler");
394 ERR_PRINT(
"BTManager::open: Could not open mgmt control channel");
399bool BTManager::initialize(
const std::shared_ptr<BTManager>& self)
noexcept {
401 mgmt_reader_service.start();
408 std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
409 if(
nullptr == res ) {
413 ERR_PRINT(
"Wrong version response: %s", res->toString().c_str());
416 const uint8_t *data = res->getData();
417 const uint8_t version = data[0];
419 WORDY_PRINT(
"Bluetooth version %d.%d", version, revision);
421 ERR_PRINT(
"Bluetooth version >= 1.0 required");
428 std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
429 if(
nullptr == res ) {
433 const uint8_t *data = res->getData();
436 WORDY_PRINT(
"Bluetooth %d commands, %d events", num_commands, num_events);
438 const int expDataSize = 4 + num_commands * 2 + num_events * 2;
439 if( res->getDataSize() >= expDataSize ) {
440 for(
int i=0; i< num_commands; i++) {
442 DBG_PRINT(
"kernel op %d: %s", i, toString(op).c_str());
453 std::unique_ptr<MgmtEvent> res = sendWithReply(req0);
454 if(
nullptr == res ) {
458 ERR_PRINT(
"Insufficient data for adapter index: res %s", res->toString().c_str());
461 const uint8_t *data = res->getData();
466 if( res->getDataSize() < expDataSize ) {
467 ERR_PRINT(
"Insufficient data for %d adapter indices: res %s", num_adapter, res->toString().c_str());
472 std::unique_ptr<AdapterInfo> adapterInfo = readAdapterInfo(dev_id);
473 if(
nullptr != adapterInfo ) {
474 std::shared_ptr<BTAdapter> adapter = BTAdapter::make_shared(self, *adapterInfo);
475 adapters.push_back( adapter );
476 adapterIOCapability.push_back(BTManager::defaultIOCapability);
477 DBG_PRINT(
"BTManager::adapters %d/%d: dev_id %d: %s", i, num_adapter, dev_id, adapter->toString().c_str());
479 DBG_PRINT(
"BTManager::adapters %d/%d: dev_id %d: FAILED", i, num_adapter, dev_id);
534 const bool mgmt_service_stopped = mgmt_reader_service.
join();
536 DBG_PRINT(
"BTManager::close: Not open: stopped %d, %s", mgmt_service_stopped,
toString().c_str());
541 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
549 DBG_PRINT(
"BTManager::close -> adapter::close(): %d/%d processing: %s", i, adapters.
size(), a->toString().c_str());
556 adapterIOCapability.
clear();
559 mgmt_reader_service.
stop();
564 ERR_PRINT(
"BTManager.sigaction: Resetting sighandler");
573 for (; !it.
is_end(); ++it) {
574 if( (*it)->isPowered() ) {
583 for (; !it.
is_end(); ++it) {
584 if ( (*it)->dev_id == dev_id ) {
591std::shared_ptr<BTAdapter> BTManager::addAdapter(
const AdapterInfo& ai )
noexcept {
592 typename adapters_t::iterator it = adapters.begin();
593 for (; !it.is_end(); ++it) {
594 if ( (*it)->dev_id == ai.dev_id ) {
600 std::shared_ptr<BTAdapter> adapter = BTAdapter::make_shared(
BTManager::get(), ai);
601 it.push_back( adapter );
602 adapterIOCapability.push_back(BTManager::defaultIOCapability);
603 DBG_PRINT(
"BTManager::addAdapter: Adding new: %s", adapter->toString().c_str())
608 std::shared_ptr<BTAdapter> adapter = *it;
609 WARN_PRINT(
"BTManager::addAdapter: Already existing %s, overwriting %s", ai.toString().c_str(), adapter->toString().c_str())
610 adapter->adapterInfo = ai;
616 typename adapters_t::iterator it = adapters.begin();
617 for(; !it.is_end(); ++it ) {
618 std::shared_ptr<BTAdapter> & ai = *it;
619 if( ai->dev_id == dev_id ) {
620 adapterIOCapability.erase( adapterIOCapability.cbegin() + it.dist_begin() );
621 std::shared_ptr<BTAdapter> res = ai;
622 DBG_PRINT(
"BTManager::removeAdapter: Remove: %s", res->toString().c_str())
633 typename adapters_t::iterator it = adapters.begin();
634 for(; !it.is_end(); ++it ) {
635 std::shared_ptr<BTAdapter> & ai = *it;
636 if( ai.get() == adapter ) {
637 adapterIOCapability.erase( adapterIOCapability.cbegin() + it.dist_begin() );
638 DBG_PRINT(
"BTManager::removeAdapter: Remove: %p -> %s", adapter, ai->toString().c_str())
652 for (; !it.
is_end(); ++it) {
653 if( (*it)->dev_id == dev_id ) {
658 adapterIOCapability.at(index) = io_cap;
673 for (; !it.
is_end(); ++it) {
674 if( (*it)->dev_id == dev_id ) {
675 return adapterIOCapability.at( it.
dist_begin() );
681MgmtStatus BTManager::handleCurrentSettingsReply(std::unique_ptr<MgmtEvent>&& reply,
AdapterSetting& current_settings)
noexcept {
682 if(
nullptr != reply ) {
704 MgmtStatus res = handleCurrentSettingsReply(sendWithReply(req, timeout), current_settings);
705 DBG_PRINT(
"BTManager::setMode[%d, %s]: %s, result %s %s", dev_id,
713 MgmtStatus res = handleCurrentSettingsReply(sendWithReply(req), current_settings);
714 DBG_PRINT(
"BTManager::setDiscoverable[%d]: %s, result %s %s", dev_id,
721 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
722 DBG_PRINT(
"BTManager::readDefaultSysParam[%d]: %s, result %s", dev_id,
723 req.
toString().c_str(), res->toString().c_str());
730 return std::vector<MgmtDefaultParam>();
735 MgmtStatus res = handleCurrentSettingsReply(sendWithReply(req), current_settings);
736 DBG_PRINT(
"BTManager::setPrivacy[%d]: %s, result %s %s", dev_id,
742 const uint16_t conn_min_interval,
const uint16_t conn_max_interval,
743 const uint16_t conn_latency,
const uint16_t supervision_timeout)
noexcept {
745 conn_min_interval, conn_max_interval,
746 conn_latency, supervision_timeout);
747 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
748 DBG_PRINT(
"BTManager::setDefaultConnParam[%d]: %s, result %s", dev_id,
749 req.
toString().c_str(), res->toString().c_str());
750 if(
nullptr != res ) {
763 const uint16_t conn_min_interval,
const uint16_t conn_max_interval,
764 const uint16_t conn_latency,
const uint16_t supervision_timeout)
noexcept {
765 MgmtConnParam connParam{ addressAndType.
address, addressAndType.type, conn_min_interval, conn_max_interval, conn_latency, supervision_timeout };
767 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
768 if(
nullptr != res ) {
803 std::unique_ptr<MgmtEvent> reply = sendWithReply(req);
804 if(
nullptr != reply ) {
816 WARN_PRINT(
"(dev_id %d): %s, result %s", dev_id,
819 DBG_PRINT(
"BTManager::uploadLongTermKeyInfo(dev_id %d): %s, result %s", dev_id,
836 mgmt_keys.
push_back( { addressAndType.address, addressAndType.type, key_type,
838 ltk.enc_size, ltk.ediv, ltk.rand, ltk.ltk } );
840 return uploadLongTermKey(dev_id, mgmt_keys);
850 std::unique_ptr<MgmtEvent> reply = sendWithReply(req);
851 if(
nullptr != reply ) {
863 WARN_PRINT(
"(dev_id %d): %s, result %s", dev_id,
866 DBG_PRINT(
"BTManager::uploadIdentityResolvingKeyInfo(dev_id %d): %s, result %s", dev_id,
882 return uploadIdentityResolvingKey(dev_id, mgmt_keys);
893 return uploadIdentityResolvingKey(dev_id, mgmt_keys);
903 std::unique_ptr<MgmtEvent> reply = sendWithReply(req);
904 if(
nullptr != reply ) {
916 WARN_PRINT(
"(dev_id %d): %s, result %s", dev_id,
919 DBG_PRINT(
"BTManager::uploadLinkKeyInfo(dev_id %d): %s, result %s", dev_id,
931 lk.key, lk.pin_length };
932 return uploadLinkKey(dev_id, mgmt_lk_info);
941 std::unique_ptr<MgmtEvent> res = sendWithReply(cmd);
956 std::unique_ptr<MgmtEvent> res = sendWithReply(cmd);
971 std::unique_ptr<MgmtEvent> res = sendWithReply(cmd);
986 std::unique_ptr<MgmtEvent> res = sendWithReply(cmd);
1000 std::unique_ptr<MgmtEvent> res;
1003 res = sendWithReply(cmd);
1006 res = sendWithReply(cmd);
1022 std::unique_ptr<MgmtEvent> res = sendWithReply(cmd);
1036 auto it = whitelist.cbegin();
1037 for(
auto end = whitelist.cend(); it != end; ++it) {
1038 std::shared_ptr<WhitelistElem> wle = *it;
1039 if( wle->dev_id == dev_id && wle->address_and_type == addressAndType ) {
1050 if( isDeviceWhitelisted(dev_id, addressAndType) ) {
1051 ERR_PRINT(
"BTManager::addDeviceToWhitelist: Already in local whitelist, remove first: %s", req.
toString().c_str());
1054 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
1058 whitelist.push_back( std::make_shared<WhitelistElem>(dev_id, addressAndType, ctype) );
1069 DBG_PRINT(
"BTManager::removeAllDevicesFromWhitelist.A: Start %zd elements", whitelist_copy.
size());
1071 for(
auto it = whitelist_copy.
cbegin(); it != whitelist_copy.
cend(); ++it) {
1072 std::shared_ptr<WhitelistElem> wle = *it;
1078 DBG_PRINT(
"BTManager::removeAllDevicesFromWhitelist.B: Start %d elements", count);
1087 DBG_PRINT(
"BTManager::removeAllDevicesFromWhitelist: End: Removed %zu elements, remaining %zd elements",
1088 (
size_t)count, whitelist.
size());
1095 auto it = whitelist.cbegin();
1096 for(
auto end = whitelist.cend(); it != end; ) {
1097 std::shared_ptr<WhitelistElem> wle = *it;
1098 if( wle->dev_id == dev_id && wle->address_and_type == addressAndType ) {
1099 it = whitelist.erase(it);
1108 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
1120 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
1131std::shared_ptr<NameAndShortName>
BTManager::setLocalName(
const uint16_t dev_id,
const std::string & name,
const std::string & short_name)
noexcept {
1133 std::unique_ptr<MgmtEvent> res = sendWithReply(req);
1164 if( !isValidMgmtEventCallbackListsIndex(opc) ) {
1173 if( !isValidMgmtEventCallbackListsIndex(opc) ) {
1187 for(
auto & l : mgmtAdapterEventCallbackLists) {
1194 if( !isValidMgmtEventCallbackListsIndex(opc) ) {
1198 mgmtAdapterEventCallbackLists[
static_cast<uint16_t
>(opc)].
clear();
1201 for(
auto & mgmtAdapterEventCallbackList : mgmtAdapterEventCallbackLists) {
1202 mgmtAdapterEventCallbackList.clear();
1204 mgmtChangedAdapterSetCallbackList.
clear();
1207void BTManager::processAdapterAdded(std::unique_ptr<MgmtEvent> e)
noexcept {
1208 const uint16_t dev_id = e->getDevID();
1210 std::unique_ptr<AdapterInfo> adapterInfo = readAdapterInfo(dev_id);
1212 if(
nullptr != adapterInfo ) {
1213 std::shared_ptr<BTAdapter> adapter = addAdapter( *adapterInfo );
1214 DBG_PRINT(
"BTManager::Adapter[%d] Added: Start %s, added %d", dev_id, adapter->toString().c_str());
1216 DBG_PRINT(
"BTManager::Adapter[%d] Added: User_ %s", dev_id, adapter->toString().c_str());
1220 DBG_PRINT(
"BTManager::Adapter[%d] Added: End__ %s", dev_id, adapter->toString().c_str());
1222 DBG_PRINT(
"BTManager::Adapter[%d] Added: InitAI failed", dev_id);
1225void BTManager::processAdapterRemoved(std::unique_ptr<MgmtEvent> e)
noexcept {
1226 const uint16_t dev_id = e->getDevID();
1227 std::shared_ptr<BTAdapter> ai = removeAdapter(dev_id);
1228 if(
nullptr != ai ) {
1229 DBG_PRINT(
"BTManager::Adapter[%d] Removed: Start: %s", dev_id, ai->toString().c_str());
1231 DBG_PRINT(
"BTManager::Adapter[%d] Removed: User_: %s", dev_id, ai->toString().c_str());
1236 DBG_PRINT(
"BTManager::Adapter[%d] Removed: End__: %s", dev_id, ai->toString().c_str());
1238 DBG_PRINT(
"BTManager::Adapter[%d] Removed: RemoveAI failed", dev_id);
1241void BTManager::mgmtEvNewSettingsCB(
const MgmtEvent& e)
noexcept {
1243 std::shared_ptr<BTAdapter> adapter = getAdapter(event.getDevID());
1244 if(
nullptr != adapter ) {
1245 const AdapterSetting old_settings = adapter->adapterInfo.getCurrentSettingMask();
1246 const AdapterSetting new_settings = adapter->adapterInfo.setCurrentSettingMask(event.getSettings());
1247 DBG_PRINT(
"BTManager:mgmt:NewSettings: Adapter[%d] %s -> %s - %s",
1251 e.toString().c_str());
1253 DBG_PRINT(
"BTManager:mgmt:NewSettings: Adapter[%d] %s -> adapter not present - %s",
1256 e.toString().c_str());
1260void BTManager::mgmtEventAnyCB(
const MgmtEvent& e)
noexcept {
1261 DBG_PRINT(
"BTManager:mgmt:Any: %s", e.toString().c_str());
1275 mgmtChangedAdapterSetCallbackList.
push_back(l);
1295 const size_type count = mgmtChangedAdapterSetCallbackList.
size();
1296 mgmtChangedAdapterSetCallbackList.
clear();
static MgmtAdapterEventCallbackList::equal_comparator _mgmtAdapterEventCallbackEqComp_CB
static MgmtAdapterEventCallbackList::equal_comparator _mgmtAdapterEventCallbackEqComp_ID_CB
static MgmtAdapterEventCallbackList::equal_comparator _mgmtAdapterEventCallbackEqComp_ID
static ChangedAdapterSetCallbackList::equal_comparator _changedAdapterSetCallbackEqComp
ChangedAdapterSetCallback handling.
Unique Bluetooth EUI48 address and BDAddressType tuple.
BLERandomAddressType getBLERandomAddressType() const noexcept
Returns the BLERandomAddressType.
static const BDAddressAndType ANY_BREDR_DEVICE
Using EUI48::ANY_DEVICE and BDAddressType::BDADDR_BREDR to match any BREDR device.
BTAdapter represents one local Bluetooth Controller.
static BTGattEnv & get() noexcept
A thread safe singleton handler of the BTAdapter manager, e.g.
bool addDeviceToWhitelist(const uint16_t dev_id, const BDAddressAndType &addressAndType, const HCIWhitelistConnectType ctype) noexcept
Add the given device to the adapter's autoconnect whitelist.
HCIStatusCode uploadLinkKey(const uint16_t dev_id, const MgmtLinkKeyInfo &key) noexcept
MgmtStatus userPINCodeNegativeReply(const uint16_t dev_id, const BDAddressAndType &addressAndType) noexcept
std::shared_ptr< ConnectionInfo > getConnectionInfo(const uint16_t dev_id, const BDAddressAndType &addressAndType) noexcept
void clearAllCallbacks() noexcept
Removes all MgmtEventCallbacks from all MgmtEvent::Opcode lists.
~BTManager() noexcept override
HCIStatusCode clearIdentityResolvingKeys(const uint16_t dev_id) noexcept
size_type removeMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
Returns count of removed given MgmtEventCallback from the named MgmtEvent::Opcode list.
HCIStatusCode setPrivacy(const uint16_t dev_id, const uint8_t privacy, const jau::uint128dp_t &irk, AdapterSetting ¤t_settings) noexcept
MgmtStatus setDiscoverable(const uint16_t dev_id, const uint8_t state, const uint16_t timeout, AdapterSetting ¤t_settings) noexcept
HCIStatusCode uploadConnParam(const uint16_t dev_id, const BDAddressAndType &addressAndType, 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)) noexcept
Uploads given connection parameter for given device to the kernel.
HCIStatusCode unpairDevice(const uint16_t dev_id, const BDAddressAndType &addressAndType, const bool disconnect) noexcept
MgmtStatus userPasskeyReply(const uint16_t dev_id, const BDAddressAndType &addressAndType, const uint32_t passkey) noexcept
bool setMode(const uint16_t dev_id, const MgmtCommand::Opcode opc, const uint8_t mode, AdapterSetting ¤t_settings) noexcept
std::shared_ptr< NameAndShortName > setLocalName(const uint16_t dev_id, const std::string &name, const std::string &short_name) noexcept
std::shared_ptr< BTAdapter > getAdapter(const uint16_t dev_id) const noexcept
Returns the DBTAdapter with the given dev_id, or nullptr if not found.
void sendMgmtEvent(const MgmtEvent &event) noexcept
Manually send a MgmtEvent to all of its listeners.
MgmtStatus userPasskeyNegativeReply(const uint16_t dev_id, const BDAddressAndType &addressAndType) noexcept
HCIStatusCode uploadIdentityResolvingKey(const uint16_t dev_id, const jau::darray< MgmtIdentityResolvingKey > &keys) noexcept
size_type removeAllDevicesFromWhitelist() noexcept
Remove all previously added devices from the autoconnect whitelist.
HCIStatusCode uploadLongTermKey(const uint16_t dev_id, const jau::darray< MgmtLongTermKey > &keys) noexcept
MgmtStatus userPINCodeReply(const uint16_t dev_id, const BDAddressAndType &addressAndType, const std::string &pinCode) noexcept
void addChangedAdapterSetCallback(const ChangedAdapterSetCallback &l)
ChangedAdapterSetCallback handling.
size_type removeAllChangedAdapterSetCallbacks() noexcept
Remove all added ChangedAdapterSetCallback entries from this manager.
HCIStatusCode initializeAdapter(AdapterInfo &adapterInfo, const uint16_t dev_id, const BTMode btMode, const bool powerOn) noexcept
Initialize the adapter with default values, including power-on.
HCIStatusCode setDefaultConnParam(const uint16_t dev_id, 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 for given adapter to the kernel.
bool isValidLongTermKeyAddressAndType(const EUI48 &address, const BDAddressType &address_type) const noexcept
Security commands.
std::string toString() const noexcept override
static const std::shared_ptr< BTManager > & get() noexcept
Retrieves the singleton instance.
SMPIOCapability getIOCapability(const uint16_t dev_id) const noexcept
std::vector< MgmtDefaultParam > readDefaultSysParam(const uint16_t dev_id) noexcept
Read default connection parameter for given adapter to the kernel.
std::shared_ptr< BTAdapter > getDefaultAdapter() const noexcept
Returns the default AdapterInfo.
bool addMgmtEventCallback(const int dev_id, const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
MgmtEventCallback handling
bool isDeviceWhitelisted(const uint16_t dev_id, const BDAddressAndType &addressAndType) noexcept
Returns true, if the adapter's device is already whitelisted.
size_type removeChangedAdapterSetCallback(const ChangedAdapterSetCallback &l)
Remove the given ChangedAdapterSetCallback from this manager.
void clearMgmtEventCallbacks(const MgmtEvent::Opcode opc) noexcept
Removes all MgmtEventCallbacks from the to the named MgmtEvent::Opcode list.
bool removeDeviceFromWhitelist(const uint16_t dev_id, const BDAddressAndType &addressAndType) noexcept
Remove the given device from the adapter's autoconnect whitelist.
MgmtStatus userConfirmReply(const uint16_t dev_id, const BDAddressAndType &addressAndType, const bool positive) noexcept
void close() noexcept
Closing the HCI channel, locking mutex_write().
static HCIEnv & get() noexcept
A thread safe singleton handler of the HCI control channel to one controller (BT adapter)
static L2CAPEnv & get() noexcept
int getDevID() const noexcept
Unique adapter index filter or -1 to listen for all adapter.
std::string toString() const
MgmtEventCallback & getCallback() noexcept
MgmtEventCallback reference.
mgmt_addr_info { EUI48, uint8_t type }, uint8_t action
static std::string getOpcodeString(const Opcode op) noexcept
std::string toString() const noexcept override
@ SET_SECURE_CONN
LE Secure Connections: 0x01 enables SC mixed, 0x02 enables SC only mode; Core Spec >= 4....
@ SET_SSP
Secure Simple Pairing: 0x00 disabled, 0x01 enable.
Managment Singleton runtime environment properties.
uint16_t opcode, uint16_t dev-id, uint16_t param_size
static std::unique_ptr< MgmtEvent > getSpecialized(const uint8_t *buffer, jau::nsize_t const buffer_size) noexcept
Return a newly created specialized instance pointer to base class.
static std::string getOpcodeString(const Opcode opc) noexcept
@ DEVICE_WHITELIST_REMOVED
bool updateAdapterInfo(AdapterInfo &info) const noexcept
std::unique_ptr< AdapterInfo > toAdapterInfo() const noexcept
static jau::nsize_t getRequiredTotalSize() noexcept
static MgmtStatus getStatus(const uint8_t *data)
std::shared_ptr< NameAndShortName > toNameAndShortName() const noexcept
Convert this instance into ConnectionInfo if getCmdOpcode() == SET_LOCAL_NAME, getStatus() == SUCCESS...
const uint8_t * getData() const noexcept override
bool getCurrentSettings(AdapterSetting ¤t_settings) const noexcept
Returns AdapterSetting if getCmdOpcode() expects a single 4-octet AdapterSetting and hence getDataSiz...
std::shared_ptr< ConnectionInfo > toConnectionInfo() const noexcept
Convert this instance into ConnectionInfo if getCmdOpcode() == GET_CONN_INFO, getStatus() == SUCCESS ...
jau::nsize_t getDataSize() const noexcept override
MgmtStatus getStatus() const noexcept
uint8_t name[MGMT_MAX_NAME_LENGTH]; uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
mgmt_addr_info { EUI48, uint8_t type },
uint16_t param_count 2 MgmtConnParam param[] 15 = 1x
uint16_t key_count MgmtIdentityResolvingKey keys[key_count]
uint8_t debug_keys, uint16_t key_count, MgmtLinkKey keys[key_count]
uint16_t key_count MgmtLongTermKey keys[key_count]
mgmt_addr_info { EUI48, uint8_t type },
mgmt_addr_info { EUI48, uint8_t type }, uint8_t pin_len, uint8_t pin_code[16]
static std::vector< MgmtDefaultParam > getParams(const uint8_t *data, const jau::nsize_t length) noexcept
mgmt_addr_info { EUI48, uint8_t type },
MgmtDefaultParamU16 param1, MgmtDefaultParamU16 param2,.
uint8_t discoverable uint16_t timeout
uint8_t name[MGMT_MAX_NAME_LENGTH]; uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
uint8_t privacy 0x00 disabled, 0x01 always on (discoverable + pairing), 0x02 limited (not when discov...
mgmt_addr_info { EUI48, uint8_t type }, bool disconnect (1 octet)
mgmt_addr_info { EUI48, uint8_t type },
mgmt_addr_info { EUI48, uint8_t type },
mgmt_addr_info { EUI48, uint8_t type },
mgmt_addr_info { EUI48, uint8_t type }, uint32_t passkey
static SMPEnv & get() noexcept
Transient read only and endian aware octet data, i.e.
constexpr nsize_t size() const noexcept
Returns the used memory size for read and write operations, may be zero.
constexpr uint8_t const * get_ptr() const noexcept
Implementation of a Copy-On-Write (CoW) using jau::darray as the underlying storage,...
constexpr_atomic void push_back(const value_type &x)
Like std::vector::push_back(), copy.
constexpr_atomic void clear() noexcept
Like std::vector::clear(), but ending with zero capacity.
constexpr const_iterator cbegin() const noexcept
Returns an jau::cow_ro_iterator to the first element of this CoW storage.
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().
std::make_signed< size_type >::type difference_type
constexpr_atomic bool push_back_unique(const value_type &x, equal_comparator comparator)
Like std::vector::push_back(), but only if the newly added element does not yet exist.
constexpr_atomic size_type erase_matching(const value_type &x, const bool all_matching, equal_comparator comparator)
Erase either the first matching element or all matching elements.
Implementation of a Copy-On-Write (CoW) read-onlu iterator over immutable value_type storage.
constexpr difference_type dist_begin() const noexcept
Returns the distance to_begin() using zero as first index.
constexpr cow_ro_iterator cbegin() const noexcept
Returns a new const_iterator pointing to the first element, aka begin.
constexpr bool is_end() const noexcept
Returns true, if this iterator points to cend().
Implementation of a dynamic linear array storage, aka vector.
constexpr const_iterator cend() const 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 const_iterator cbegin() const noexcept
constexpr void clear() noexcept
Like std::vector::clear(), but ending with zero capacity.
Main jau environment class, supporting environment variable access and fetching elapsed time using it...
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...
static void set_terminating() noexcept
Optional path to signal early termination, i.e.
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 ...
static bool remove_sighandler() noexcept
Remove the sighandler.
static const ::pid_t pid_self
bool join() noexcept
Blocks the current thread until service is stopped or returns immediately if not running or called fr...
static bool singleton_sighandler() noexcept
Install the singleton SIGALRM sighandler instance.
#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: '.
constexpr UnaryFunction for_each_fidelity(InputIt first, InputIt last, UnaryFunction f)
Like jau::for_each(), see above.
constexpr UnaryFunction for_each_const(T &data, UnaryFunction f, std::enable_if_t< is_cow_type< T >::value, bool >=true) noexcept
constexpr uint16_t get_uint16(uint8_t const *buffer) noexcept
Returns a uint16_t value from the given byte address using packed_t to resolve a potential memory ali...
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
@ little
Identifier for little endian, equivalent to endian::little.
HCIStatusCode to_HCIStatusCode(const MgmtStatus mstatus) noexcept
constexpr const jau::fraction_i64 THREAD_SHUTDOWN_TIMEOUT_MS
Maximum time in fractions of seconds to wait for a thread shutdown.
MgmtLinkKeyType
Link Key Types compatible with Mgmt's MgmtLinkKeyInfo.
jau::function< void(const MgmtEvent &)> MgmtEventCallback
MgmtLTKType
Long Term Key Types compatible with Mgmt's MgmtLongTermKey.
SMPIOCapability
Vol 3, Part H, 2.3.2 IO capabilities.
MgmtLTKType to_MgmtLTKType(const SMPLongTermKey::Property ltk_prop_mask) noexcept
constexpr const bool USE_LINUX_BT_SECURITY
@ UNSET
Denoting unset value, i.e.
void(* ChangedAdapterSetFunc)(bool added, std::shared_ptr< BTAdapter > &adapter)
Callback function to receive change events regarding the system's adapter set, e.g.
BTMode
Bluetooth adapter operating mode.
void clear() noexcept
Clears internal list.
HCIWhitelistConnectType
HCI Whitelist connection type.
std::string to_string(const DiscoveryPolicy v) noexcept
Entry * get(const EUI48 &addr, const std::string &name, AddressNameEntryMatchFunc m) noexcept
Returns a matching BTSecurityRegistry::Entry with the given addr and/or name.
AdapterSetting
Adapter Setting Bits.
BDAddressType
BT Core Spec v5.2: Vol 3, Part C Generic Access Profile (GAP): 15.1.1.1 Public Bluetooth address.
jau::function< void(bool, std::shared_ptr< BTAdapter > &)> ChangedAdapterSetCallback
Callback jau::function to receive change events regarding the system's adapter set,...
BTRole
Bluetooth roles from the perspective of the link layer (connection initiator).
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
constexpr uint8_t number(const DiscoveryPolicy rhs) noexcept
@ STATIC_PUBLIC
Static public 'random' device address 0b11.
@ NONE
Zero mode, neither DUAL, BREDR nor LE.
@ DUAL
Dual Bluetooth mode, i.e.
@ LE
LE only Bluetooth mode.
@ BREDR
BREDR only Bluetooth mode.
@ BDADDR_LE_RANDOM
Bluetooth LE random address, see BLERandomAddressType.
@ BDADDR_LE_PUBLIC
Bluetooth LE public address.
@ Slave
Slave or peripheral role, advertising and waiting for connections to accept.
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...
jau::function< R(A...)> bind_free(R(*func)(A...)) noexcept
Bind given non-void free-function to an anonymous function using func::free_target_t.
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
void PLAIN_PRINT(const bool printPrefix, const char *format,...) noexcept
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.
Used in MgmtLoadConnParamCmd and MgmtEvtNewConnectionParam.
Used for MgmtLoadLinkKeyCmd and MgmtEvtNewLinkKey.
static constexpr uint8_t to_role(const BTRole adapterRole, const bool is_responder)
SMP Identity Resolving Key, used for platform agnostic persistence.
Local SMP Link Key, used for platform agnostic persistence, mapping to platform specific MgmtLoadLink...
SMP Long Term Key, used for platform agnostic persistence.
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
CXX_ALWAYS_INLINE bool compare_exchange_strong(_Tp &__e, _Tp __i) noexcept
A 128-bit packed uint8_t data array.