47: adapter(a), btRole(!a.getRole()),
49 ts_last_discovery(r.getTimestamp()),
50 ts_last_update(ts_last_discovery),
60 allowDisconnect(false),
61 supervision_timeout(0),
64 ts_creation(ts_last_discovery),
65 visibleAddressAndType{r.getAddress(), r.getAddressType()},
66 addressAndType(visibleAddressAndType)
70 clearSMPStates(
false );
96 adapter.removeAllStatusListener(*
this);
101 return adapter.getSharedDevice(*
this);
114 std::string res = name;
119 const std::lock_guard<std::mutex> lock(mtx_eir);
124 const std::lock_guard<std::mutex> lock(mtx_eir);
129 const std::lock_guard<std::mutex> lock(mtx_eir);
136 std::string resaddr_s = visibleAddressAndType != addressAndType ?
", visible "+visibleAddressAndType.toString() :
"";
137 std::shared_ptr<const EInfoReport> eir_ = eir;
138 std::string eir_s =
BTRole::Slave == getRole() ?
", "+eir_->toString( includeDiscoveredServices ) :
"";
139 std::string out(
"Device["+
to_string(getRole())+
", "+addressAndType.toString()+resaddr_s+
", name['"+name+
147 ", "+javaObjectToString()+
"]");
151void BTDevice::clearData() noexcept {
165 const std::lock_guard<std::mutex> lock(mtx_eir);
166 eir = std::make_shared<EInfoReport>();
167 eir_ind = std::make_shared<EInfoReport>();
168 eir_scan_rsp = std::make_shared<EInfoReport>();
180bool BTDevice::updateIdentityAddress(
BDAddressAndType const & identityAddress,
bool sendEvent)
noexcept {
182 addressAndType = identityAddress;
183 adapter.hci.setResolvHCIConnectionAddr(visibleAddressAndType, addressAndType);
185 std::shared_ptr<BTDevice> sharedInstance = getSharedInstance();
186 if(
nullptr == sharedInstance ) {
187 ERR_PRINT(
"Device unknown to adapter and not tracked: %s", toString().c_str());
198bool BTDevice::updateVisibleAddress(
BDAddressAndType const & randomPrivateAddress)
noexcept {
199 if( visibleAddressAndType != randomPrivateAddress ) {
200 visibleAddressAndType = randomPrivateAddress;
208 const std::lock_guard<std::mutex> lock(mtx_eir);
210 btRole = !adapter.getRole();
213 std::shared_ptr<EInfoReport> eir_new( std::make_shared<EInfoReport>( *eir ) );
219 eir_ind = std::make_shared<EInfoReport>( data );
221 eir_scan_rsp = std::make_shared<EInfoReport>( data );
224 ts_last_update = data.getTimestamp();
226 if( data.getAddress() != this->addressAndType.address ) {
228 WARN_PRINT(
"BDADDR update not supported: %s for %s", data.toString().c_str(), this->toString().c_str());
232 if( data.getAddressType() != this->addressAndType.type ) {
234 WARN_PRINT(
"BDADDR_TYPE update not supported: %s for %s", data.toString().c_str(), this->toString().c_str());
238 if( data.getName().length() > 0 ) {
239 name = data.getName();
243 if( 0 == name.length() ) {
244 name = data.getShortName();
248 if( rssi != data.getRSSI() ) {
249 rssi = data.getRSSI();
253 if( tx_power != data.getTxPower() ) {
254 tx_power = data.getTxPower();
261 const std::lock_guard<std::mutex> lock(mtx_eir);
264 std::shared_ptr<EInfoReport> eir_new( std::make_shared<EInfoReport>( *eir ) );
268 ts_last_update = timestamp;
269 if( 0 == name.length() && data.deviceName.length() > 0 ) {
270 name = data.deviceName;
271 eir_new->setName( name );
276 eir_new->setAppearance( data.appearance );
287 return adapter.addStatusListener(*
this, l);
291 return adapter.removeStatusListener(l);
296 std::shared_ptr<ConnectionInfo> connInfo = mgmt->getConnectionInfo(adapter.
dev_id,
addressAndType);
297 if(
nullptr != connInfo ) {
299 if( rssi != connInfo->getRSSI() ) {
300 rssi = connInfo->getRSSI();
303 if( tx_power != connInfo->getTxPower() ) {
304 tx_power = connInfo->getTxPower();
309 if(
nullptr == sharedInstance ) {
322 const uint16_t conn_interval_min,
const uint16_t conn_interval_max,
323 const uint16_t conn_latency,
const uint16_t conn_supervision_timeout)
noexcept
325 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect);
326 if( !adapter.isPowered() ) {
327 WARN_PRINT(
"Adapter not powered: %s, %s", adapter.toString().c_str(), toString().c_str());
333 switch( addressAndType.type ) {
340 switch( leRandomAddressType ) {
354 ERR_PRINT(
"Can't connectLE to LE Random address type '%s': %s",
355 to_string(leRandomAddressType).c_str(), toString().c_str());
361 ERR_PRINT(
"Can't connectLE to address type '%s': %s",
to_string(addressAndType.type).c_str(), toString().c_str());
367 ERR_PRINT(
"Already connected: %s", toString().c_str());
373 ERR_PRINT(
"HCI closed: %s", toString().c_str());
380 bool smp_auto_done = !smp_auto;
381 int smp_auto_count = 0;
389 if( !smp_auto_done ) {
394 io_cap = smp_auto_io_cap;
397 io_cap = smp_auto_io_cap;
402 smp_auto_done =
true;
410 smp_auto_done =
true;
412 pairing_data.io_cap_auto = smp_auto_io_cap;
413 pairing_data.sec_level_user = sec_level;
414 pairing_data.io_cap_user = io_cap;
415 DBG_PRINT(
"BTDevice::connectLE: SEC AUTO.%d.1: lvl %s -> %s, io %s -> %s, %s", smp_auto_count,
423 if( !adapter.lockConnect(*
this,
true , pairing_data.io_cap_user) ) {
424 ERR_PRINT(
"adapter::lockConnect() failed: %s", toString().c_str());
429 hci_peer_mac_type, hci_own_mac_type,
431 conn_latency, conn_supervision_timeout);
432 supervision_timeout = 10 * conn_supervision_timeout;
433 allowDisconnect =
true;
435 WARN_PRINT(
"Could not yet create connection: status 0x%2.2X (%s), errno %d, hci-atype[peer %s, own %s] %s on %s",
436 static_cast<uint8_t
>(statusConnect),
to_string(statusConnect).c_str(), errno, strerror(errno),
440 adapter.unlockConnect(*
this);
441 smp_auto_done =
true;
443 ERR_PRINT(
"Could not create connection: status 0x%2.2X (%s), errno %d %s, hci-atype[peer %s, own %s] on %s",
444 static_cast<uint8_t
>(statusConnect),
to_string(statusConnect).c_str(), errno, strerror(errno),
448 adapter.unlockConnect(*
this);
449 smp_auto_done =
true;
450 }
else if( smp_auto ) {
452 bool pairing_timeout =
false;
454 std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
457 std::cv_status s = cv_pairing_state_changed.wait_until(lock_pairing, timeout_time);
458 DBG_PRINT(
"BTDevice::connectLE: SEC AUTO.%d.2c Wait for SMPPairing: state %s, %s",
459 smp_auto_count,
to_string(pairing_data.state).c_str(), toString().c_str());
462 ERR_PRINT(
"SEC AUTO.%d.X Timeout SMPPairing: Disconnecting %s", smp_auto_count, toString().c_str());
463 smp_auto_done =
true;
465 pairing_timeout =
true;
469 pstate = pairing_data.state;
470 DBG_PRINT(
"BTDevice::connectLE: SEC AUTO.%d.2d Wait for SMPPairing: state %s, %s",
471 smp_auto_count,
to_string(pstate).c_str(), toString().c_str());
473 if( pairing_timeout ) {
477 adapter.unlockConnect(*
this);
478 smp_auto_done =
true;
480 DBG_PRINT(
"BTDevice::connectLE: SEC AUTO.%d.X Done: %s", smp_auto_count, toString().c_str());
481 smp_auto_done =
true;
485 if( !smp_auto_done ) {
488 DBG_PRINT(
"BTDevice::connectLE: SEC AUTO.%d.3 Failed SMPPairing -> Disconnect: %s", smp_auto_count, toString().c_str());
499 ERR_PRINT(
"SEC AUTO.%d.4 Timeout Disconnect td_pairing %" PRIi64
" ms: %s",
500 smp_auto_count, td_disconnect.
to_ms(), toString().c_str());
503 adapter.unlockConnect(*
this);
504 smp_auto_done =
true;
509 }
while( !smp_auto_done );
513 ERR_PRINT(
"SEC AUTO.%d.X Failed SMPPairing -> Disconnect: %s", smp_auto_count, toString().c_str());
520 return statusConnect;
525 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect);
526 if( !adapter.isPowered() ) {
527 WARN_PRINT(
"Adapter not powered: %s, %s", adapter.toString().c_str(), toString().c_str());
532 ERR_PRINT(
"Already connected: %s", toString().c_str());
535 if( !addressAndType.isBREDRAddress() ) {
536 ERR_PRINT(
"Not a BDADDR_BREDR address: %s", toString().c_str());
542 ERR_PRINT(
"HCI closed: %s", toString().c_str());
548 if( !adapter.lockConnect(*
this,
true , pairing_data.io_cap_user) ) {
549 ERR_PRINT(
"adapter::lockConnect() failed: %s", toString().c_str());
554 allowDisconnect =
true;
556 ERR_PRINT(
"Could not create connection: status 0x%2.2X (%s), errno %d %s on %s",
557 static_cast<uint8_t
>(status),
to_string(status).c_str(), errno, strerror(errno), toString().c_str());
558 adapter.unlockConnect(*
this);
578void BTDevice::notifyConnected(
const std::shared_ptr<BTDevice>& sthis,
const uint16_t handle,
const SMPIOCapability io_cap_has)
noexcept {
581 DBG_PRINT(
"BTDevice::notifyConnected: Start: handle %s -> %s, io %s / %s -> %s, %s",
585 allowDisconnect =
true;
587 hciConnHandle = handle;
590 pairing_data.io_cap_conn = io_cap_has;
592 DBG_PRINT(
"BTDevice::notifyConnected: End: io_cap %s: %s / %s -> %s, %s",
593 to_string(pairing_data.io_cap_user).c_str(),
596 to_string(pairing_data.io_cap_conn).c_str(),
601void BTDevice::notifyLEFeatures(
const std::shared_ptr<BTDevice>& sthis,
const LE_Features features)
noexcept {
603 bool enc_done, using_auth, is_pre_paired;
604 getSMPEncStatus(enc_done, using_auth, is_pre_paired);
606 DBG_PRINT(
"BTDevice::notifyLEFeatures: start[local_server %d, enc_done %d, auth %d, pre_paired %d]: %s -> %s, %s",
607 is_local_server, enc_done, using_auth, is_pre_paired,
612 le_features = features;
613 if( addressAndType.isLEAddress() && ( !l2cap_att->is_open() || is_local_server ) ) {
614 std::thread bg(&BTDevice::processL2CAPSetup,
this, sthis);
620 DBG_PRINT(
"BTDevice::notifyLEPhyUpdateComplete: %s: [Tx %s, Rx %s], %s",
629void BTDevice::processL2CAPSetup(std::shared_ptr<BTDevice> sthis) {
630 bool callProcessDeviceReady =
false;
631 bool callDisconnect =
false;
632 bool smp_auto =
false;
636 std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
642 validateConnectedSecParam(sec_level, io_cap);
644 pairing_data.sec_level_conn = sec_level;
648 if( is_local_server ) {
650 std::unique_ptr<L2CAPClient> l2cap_att_new = adapter.get_l2cap_connection(sthis);
652 if(
nullptr == l2cap_att_new ) {
653 DBG_PRINT(
"L2CAP-ACCEPT: BTDevice::processL2CAPSetup: dev_id %d, td %" PRIu64
"ms, NULL l2cap_att", adapter.
dev_id, td);
656 l2cap_att = std::move(l2cap_att_new);
657 DBG_PRINT(
"L2CAP-ACCEPT: BTDevice::processL2CAPSetup: dev_id %d, td %" PRIu64
"ms, l2cap_att %s", adapter.
dev_id, td, l2cap_att->toString().c_str());
659 l2cap_open = l2cap_att->setBTSecurityLevel(sec_level);
665 l2cap_open = l2cap_att->open(*
this, sec_level);
671 DBG_PRINT(
"BTDevice::processL2CAPSetup: dev_id %u, lvl %s, connect[own_smp %d, l2cap[open %d, enc %d]]",
672 adapter.
dev_id,
to_string(sec_level).c_str(), own_smp, l2cap_open, l2cap_enc);
674 adapter.unlockConnect(*
this);
683 lock_pairing.unlock();
684 cv_pairing_state_changed.notify_all();
686 callDisconnect =
true;
689 }
else if( !l2cap_enc ) {
690 callProcessDeviceReady =
true;
691 lock_pairing.unlock();
693 adapter.notifyPairingStageDone(sthis, ts);
694 processDeviceReady(sthis, ts);
699 DBG_PRINT(
"BTDevice::processL2CAPSetup: End [dev_id %u, disconnect %d, deviceReady %d, smp_auto %d], %s",
700 adapter.
dev_id, callDisconnect, callProcessDeviceReady, smp_auto,
toString().c_str());
703void BTDevice::getSMPEncStatus(
bool& enc_done,
bool& using_auth,
bool& is_pre_paired) {
709 sec_level = pairing_data.sec_level_conn;
710 pmode = pairing_data.mode;
711 pstate = pairing_data.state;
718void BTDevice::processDeviceReady(std::shared_ptr<BTDevice> sthis,
const uint64_t timestamp) {
720 bool enc_done, using_auth, is_pre_paired;
721 getSMPEncStatus(enc_done, using_auth, is_pre_paired);
723 DBG_PRINT(
"BTDevice::processDeviceReady: start[local_server %d, enc_done %d, auth %d, pre_paired %d], %s",
724 is_local_server, enc_done, using_auth, is_pre_paired,
toString().c_str());
734 if( enc_done && !is_pre_paired ) {
744 const bool gatt_res = connectGATT(sthis);
746 if( !gatt_res && enc_done ) {
750 DBG_PRINT(
"BTDevice::processDeviceReady: done[GATT %d, unpair %s], %s",
754 adapter.sendDeviceReady(sthis, timestamp);
763bool BTDevice::checkPairingKeyDistributionComplete() const noexcept {
766 if( pairing_data.encryption_enabled &&
771 if( ( pairing_data.keys_init_has & key_mask ) == ( pairing_data.keys_init_exp & key_mask ) &&
772 ( pairing_data.keys_resp_has & key_mask ) == ( pairing_data.keys_resp_exp & key_mask ) ) {
779std::string BTDevice::PairingData::toString(
const uint16_t dev_id,
const BDAddressAndType& addrAndType,
const BTRole& role)
const {
781 res.append(
" Status: Encrypted "+
std::to_string(encryption_enabled)+
784 res.append(
" Setup:\n");
788 res.append(
" - Level conn "+
to_string(sec_level_conn)+
", user "+
to_string(sec_level_user)+
"\n");
789 res.append(
" Initiator (master) Set:\n");
790 res.append(
" - OOB "+
to_string(oobFlag_init)+
"\n");
791 res.append(
" - Auth "+
to_string(authReqs_init)+
"\n");
792 res.append(
" - IOCap "+
to_string(ioCap_init)+
"\n");
795 res.append(
" - "+ltk_init.toString()+
"\n");
796 res.append(
" - "+lk_init.toString()+
"\n");
797 res.append(
" - "+irk_init.toString()+
"\n");
798 res.append(
" - "+csrk_init.toString()+
"\n");
799 res.append(
" - IdAdr "+id_address_init.toString()+
"\n");
800 res.append(
" Responder (slave) Set:\n");
801 res.append(
" - OOB "+
to_string(oobFlag_resp)+
"\n");
802 res.append(
" - Auth "+
to_string(authReqs_resp)+
"\n");
803 res.append(
" - IOCap "+
to_string(ioCap_resp)+
"\n");
807 res.append(
" - "+ltk_resp.toString()+
"\n");
808 res.append(
" - "+lk_resp.toString()+
"\n");
809 res.append(
" - "+irk_resp.toString()+
"\n");
810 res.append(
" - "+csrk_resp.toString()+
"\n");
811 res.append(
" - IdAdr "+id_address_resp.toString()+
" ]");
816 std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
820 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.0: state %s -> claimed %s, mode %s",
823 jau::PLAIN_PRINT(
false,
"[%s] %s", timestamp.c_str(), evt.toString().c_str());
829 bool check_pairing_complete =
false;
830 bool is_device_ready =
false;
840 if( pairing_data.state != claimed_state ) {
842 switch( claimed_state ) {
845 claimed_state = pairing_data.state;
856 DBG_PRINT(
"BTDevice::updatePairingState.1a: state %s [ignored %s, sending PASSKEY 0 reply], mode %s",
859 claimed_state = pairing_data.state;
870 DBG_PRINT(
"BTDevice::updatePairingState.1b: state %s [ignored %s, sending CONFIRM reply], mode %s",
873 claimed_state = pairing_data.state;
883 pairing_data.passKey_resp =
event.getPasskey();
907 const SMPLongTermKey smp_ltk =
event.toSMPLongTermKey(pairing_data.use_sc, use_auth);
909 if( pairing_data.use_sc ) {
913 pairing_data.ltk_resp = smp_ltk;
915 if( pairing_data.use_sc &&
918 pairing_data.ltk_init = smp_ltk;
927 claimed_state = pairing_data.state;
938 pairing_data.encryption_enabled =
true;
939 is_device_ready =
true;
947 pairing_data.encryption_enabled =
true;
948 is_device_ready =
true;
963 const SMPLongTermKey smp_ltk =
event.toSMPLongTermKey(pairing_data.use_sc, use_auth);
965 if( pairing_data.use_sc ) {
969 pairing_data.ltk_resp = smp_ltk;
971 if( pairing_data.use_sc &&
974 pairing_data.ltk_init = smp_ltk;
982 claimed_state = pairing_data.state;
989 const SMPLongTermKey smp_ltk =
event.toSMPLongTermKey(pairing_data.use_sc, use_auth);
991 if( pairing_data.use_sc ) {
994 pairing_data.ltk_resp = smp_ltk;
1000 claimed_state = pairing_data.state;
1008 smp_ltk.
ltk =
event.getLTK();
1010 if( pairing_data.use_sc ) {
1014 pairing_data.ltk_resp = smp_ltk;
1016 if( pairing_data.use_sc &&
1019 pairing_data.ltk_init = smp_ltk;
1023 check_pairing_complete =
true;
1027 if( !check_pairing_complete ) {
1028 claimed_state = pairing_data.state;
1036 pairing_data.encryption_enabled =
true;
1037 check_pairing_complete =
true;
1046 if( pairing_data.use_sc || smp_ltk.
isResponder() ) {
1048 pairing_data.ltk_resp = smp_ltk;
1049 pairing_data.ltk_resp.
properties |= SMPLongTermKey::Property::RESPONDER;
1051 check_pairing_complete =
true;
1054 if( pairing_data.use_sc || !smp_ltk.
isResponder() ) {
1056 pairing_data.ltk_init = smp_ltk;
1059 check_pairing_complete =
true;
1063 if( !check_pairing_complete ) {
1064 claimed_state = pairing_data.state;
1072 const BTRole hostRole = !btRole;
1077 pairing_data.lk_resp = smp_lk;
1079 check_pairing_complete =
true;
1084 pairing_data.lk_init = smp_lk;
1090 pairing_data.lk_init = smp_lk;
1092 check_pairing_complete =
true;
1097 pairing_data.lk_resp = smp_lk;
1103 if( !check_pairing_complete ) {
1104 claimed_state = pairing_data.state;
1109 claimed_state = pairing_data.state;
1114 claimed_state = pairing_data.state;
1121 if( !is_device_ready && check_pairing_complete ) {
1122 is_device_ready = checkPairingKeyDistributionComplete();
1123 if( !is_device_ready ) {
1124 claimed_state = pairing_data.state;
1127 if( is_device_ready ) {
1128 pairing_data.is_pre_paired =
true;
1129 pairing_data.sec_level_conn = l2cap_att->getBTSecurityLevel();
1134 if( pairing_data.state != claimed_state ) {
1146 is_device_ready =
false;
1147 DBG_PRINT(
"BTDevice:updatePairingState:Sec-Failure: Requested Sec-Level %s > Actual %s",
1148 to_string(pairing_data.sec_level_user).c_str(),
1149 to_string(pairing_data.sec_level_conn).c_str());
1155 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.5b: state %s -> %s, mode %s -> %s, ready %d, checkedPState %d",
1158 to_string(pairing_data.mode).c_str(),
to_string(mode).c_str(), is_device_ready, check_pairing_complete);
1159 jau::PLAIN_PRINT(
false,
"[%s] %s", timestamp.c_str(), evt.toString().c_str());
1161 pairing_data.mode = mode;
1162 pairing_data.state = claimed_state;
1166 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.5b: %s", timestamp.c_str(),
1167 pairing_data.toString(adapter.dev_id, addressAndType, btRole).c_str());
1171 adapter.sendDevicePairingState(sthis, claimed_state, mode, evt.getTimestamp());
1173 if( is_device_ready ) {
1175 adapter.notifyPairingStageDone(sthis, evt.getTimestamp());
1176 std::thread dc(&BTDevice::processDeviceReady,
this, sthis, evt.getTimestamp());
1181 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.5b: End: state %s",
1182 timestamp.c_str(),
to_string(pairing_data.state).c_str());
1186 lock_pairing.unlock();
1187 cv_pairing_state_changed.notify_all();
1193 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.5a: state %s == %s, mode %s -> %s, ready %d, checkedPState %d",
1196 to_string(pairing_data.mode).c_str(),
to_string(mode).c_str(), is_device_ready, check_pairing_complete);
1197 jau::PLAIN_PRINT(
false,
"[%s] %s", timestamp.c_str(), evt.toString().c_str());
1199 pairing_data.mode = mode;
1202 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.5a: %s", timestamp.c_str(),
1203 pairing_data.toString(adapter.dev_id, addressAndType, btRole).c_str());
1205 jau::PLAIN_PRINT(
false,
"[%s] BTDevice::updatePairingState.5a: End: state %s",
1206 timestamp.c_str(),
to_string(pairing_data.state).c_str());
1214 std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
1216 const std::string msg_sent_s = msg_sent ?
"sent" :
"received";
1217 const BTRole localRole = !btRole;
1219 const std::string msg_dir_s = msg_from_initiator ?
"from_initiator_master" :
"from_responder_slave";
1226 bool check_pairing_complete =
false;
1227 bool is_device_ready =
false;
1232 jau::PLAIN_PRINT(
false,
"[%s] BTDevice:hci:SMP.0: %s: msg %s, local %s, remote %s @ address%s",
1233 timestamp.c_str(), msg_sent_s.c_str(), msg_dir_s.c_str(),
to_string(localRole).c_str(),
1234 to_string(btRole).c_str(), addressAndType.toString().c_str());
1235 jau::PLAIN_PRINT(
false,
"[%s] - %s", timestamp.c_str(), msg.toString().c_str());
1236 jau::PLAIN_PRINT(
false,
"[%s] - %s", timestamp.c_str(), source.toString().c_str());
1237 jau::PLAIN_PRINT(
false,
"[%s] - %s", timestamp.c_str(), toString().c_str());
1252 pairing_data.res_requested_sec =
true;
1258 if( msg_from_initiator ) {
1272 if( !msg_from_initiator ) {
1283 pairing_data.use_sc = use_sc;
1286 pairing_data.authReqs_init, pairing_data.ioCap_init, pairing_data.oobFlag_init,
1287 pairing_data.authReqs_resp, pairing_data.ioCap_resp, pairing_data.oobFlag_resp);
1322 if( !msg_from_initiator ) {
1324 pairing_data.ltk_resp.properties |= SMPLongTermKey::Property::RESPONDER;
1328 if( pairing_data.use_sc ) {
1331 pairing_data.ltk_resp.enc_size = pairing_data.maxEncsz_resp;
1332 pairing_data.ltk_resp.ltk = msg1.
getLTK();
1339 if( pairing_data.use_sc ) {
1342 pairing_data.ltk_init.enc_size = pairing_data.maxEncsz_init;
1343 pairing_data.ltk_init.ltk = msg1.
getLTK();
1351 if( !msg_from_initiator ) {
1354 pairing_data.ltk_resp.ediv = msg1.
getEDIV();
1355 pairing_data.ltk_resp.rand = msg1.
getRand();
1359 pairing_data.ltk_init.ediv = msg1.
getEDIV();
1360 pairing_data.ltk_init.rand = msg1.
getRand();
1362 check_pairing_complete =
true;
1369 if( !msg_from_initiator ) {
1372 pairing_data.irk_resp.properties |= SMPIdentityResolvingKey::Property::RESPONDER;
1373 pairing_data.irk_resp.irk = msg1.
getIRK();
1375 pairing_data.irk_resp.id_address = pairing_data.id_address_resp.address;
1380 pairing_data.irk_init.irk = msg1.
getIRK();
1382 pairing_data.irk_init.id_address = pairing_data.id_address_init.address;
1395 const BDAddressAndType& responderAddress = self_is_responder ? msg_addr : adapter.getAddressAndType();
1396 const BDAddressAndType& initiatorAddress = self_is_responder ? adapter.getAddressAndType() : msg_addr;
1398 if( !msg_from_initiator ) {
1401 if( msg_addr != responderAddress ) {
1402 DBG_PRINT(
"BTDevice:hci:SMP.id: Responder ID Address Mismatch: msg %s != responder %s", msg1.
toString().c_str(), responderAddress.
toString().c_str());
1404 pairing_data.id_address_resp = msg_addr;
1406 pairing_data.irk_resp.id_address = pairing_data.id_address_resp.address;
1409 updateIdentityAddress(pairing_data.id_address_resp,
true );
1415 if( msg_addr != initiatorAddress ) {
1416 DBG_PRINT(
"BTDevice:hci:SMP.id: Initiator ID Address Mismatch: msg %s != initiator %s", msg1.
toString().c_str(), initiatorAddress.
toString().c_str());
1418 pairing_data.id_address_init = msg_addr;
1420 pairing_data.irk_init.id_address = pairing_data.id_address_init.address;
1423 updateIdentityAddress(pairing_data.id_address_init,
true );
1433 if( !msg_from_initiator ) {
1437 pairing_data.csrk_resp.properties |= SMPSignatureResolvingKey::Property::RESPONDER;
1441 pairing_data.csrk_resp.csrk = msg1.
getCSRK();
1450 pairing_data.csrk_init.csrk = msg1.
getCSRK();
1452 check_pairing_complete =
true;
1461 check_pairing_complete =
false;
1465 if( check_pairing_complete && checkPairingKeyDistributionComplete() ) {
1467 is_device_ready =
true;
1468 pairing_data.is_pre_paired =
true;
1469 pairing_data.sec_level_conn = l2cap_att->getBTSecurityLevel();
1473 if( old_pstate == pstate ) {
1476 addressAndType.toString().c_str());
1480 addressAndType.toString().c_str());
1490 if( old_pstate == pstate ) {
1495 pairing_data.toString(adapter.dev_id, addressAndType, btRole).c_str());
1512 is_device_ready =
false;
1513 DBG_PRINT(
"BTDevice:hci:SMP:Sec-Failure: Requested Sec-Level %s > Actual %s",
1514 to_string(pairing_data.sec_level_user).c_str(),
1515 to_string(pairing_data.sec_level_conn).c_str());
1520 pairing_data.mode = pmode;
1521 pairing_data.state = pstate;
1526 pairing_data.toString(adapter.dev_id, addressAndType, btRole).c_str());
1530 adapter.sendDevicePairingState(sthis, pstate, pmode, msg.getTimestamp());
1532 if( is_device_ready ) {
1534 adapter.notifyPairingStageDone(sthis, msg.getTimestamp());
1535 std::thread dc(&BTDevice::processDeviceReady,
this, sthis, msg.getTimestamp());
1540 jau::PLAIN_PRINT(
false,
"[%s] Debug: BTDevice:hci:SMP.5b: End", timestamp.c_str());
1541 jau::PLAIN_PRINT(
false,
"[%s] - %s", timestamp.c_str(), toString().c_str());
1543 lock_pairing.unlock();
1544 cv_pairing_state_changed.notify_all();
1550 return pairing_data.keys_resp_has;
1552 return pairing_data.keys_init_has;
1557 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
1559 if( !isValidInstance() ) {
1564 if( bin.getLocalAddrAndType() != getAdapter().getAddressAndType() ) {
1565 DBG_PRINT(
"SMPKeyBin::readAndApply: Local address mismatch: Has %s, SMPKeyBin %s: %s",
1566 getAdapter().getAddressAndType().toString().c_str(),
1567 bin.getLocalAddrAndType().toString().c_str(),
1568 bin.toString().c_str());
1571 if( bin.getRemoteAddrAndType() != getAddressAndType() ) {
1572 DBG_PRINT(
"SMPKeyBin::readAndApply: Remote address mismatch: Has %s, SMPKeyBin %s: %s",
1573 getAddressAndType().toString().c_str(),
1574 bin.getRemoteAddrAndType().toString().c_str(),
1575 bin.toString().c_str());
1581 if( !bin.isValid() || (
BTSecurityLevel::NONE != bin.getSecLevel() && !bin.hasLTKInit() && !bin.hasLTKResp() ) ) {
1582 DBG_PRINT(
"BTDevice::setSMPKeyBin(): Apply SMPKeyBin failed, all invalid or sec level w/o LTK: %s, %s",
1583 bin.toString().c_str(), toString().c_str());
1587 const BTRole btRoleAdapter = !btRole;
1588 if( btRoleAdapter != bin.getLocalRole() ) {
1589 DBG_PRINT(
"BTDevice::setSMPKeyBin(): Apply SMPKeyBin failed, local adapter role %s mismatch: %s, %s",
1590 to_string(btRoleAdapter).c_str(), bin.toString().c_str(), toString().c_str());
1599 DBG_PRINT(
"BTDevice::setSMPKeyBin: Failure, pairing in progress: %s, %s",
1600 pairing_data.toString(adapter.dev_id, addressAndType, btRole).c_str(), toString().c_str());
1604 if( getConnected() ) {
1605 DBG_PRINT(
"BTDevice::setSMPKeyBin: Failure, device connected: %s", toString().c_str());
1612 DBG_PRINT(
"BTDevice::setSMPKeyBin: Setting security failed: Device Connected/ing: %s, %s", bin.toString().c_str(), toString().c_str());
1616 pairing_data.use_sc = bin.uses_SC();
1618 if( bin.hasLTKInit() ) {
1619 setLongTermKey( bin.getLTKInit() );
1621 if( bin.hasLTKResp() ) {
1622 setLongTermKey( bin.getLTKResp() );
1625 if( bin.hasIRKInit() ) {
1626 setIdentityResolvingKey( bin.getIRKInit() );
1628 if( bin.hasIRKResp() ) {
1629 setIdentityResolvingKey( bin.getIRKResp() );
1632 if( bin.hasCSRKInit() ) {
1633 setSignatureResolvingKey( bin.getCSRKInit() );
1635 if( bin.hasCSRKResp() ) {
1636 setSignatureResolvingKey( bin.getCSRKResp() );
1639 if( bin.hasLKInit() ) {
1640 setLinkKey( bin.getLKInit() );
1642 if( bin.hasLKResp() ) {
1643 setLinkKey( bin.getLKResp() );
1645 DBG_PRINT(
"BTDevice::setSMPKeyBin.OK: %s", pairing_data.toString(adapter.dev_id, addressAndType, btRole).c_str());
1654 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
1668 if( ltks.
size() > 0 ) {
1686 if( irks.
size() > 0 ) {
1687 res = mngr->uploadIdentityResolvingKey(adapter.
dev_id, irks);
1697 DBG_PRINT(
"BTDevice::uploadKeys: Upload LK for LE address not supported -> ignored: %s",
toString().c_str());
1698 pairing_data.is_pre_paired =
true;
1716 pairing_data.is_pre_paired =
true;
1728 return responder ? pairing_data.ltk_resp : pairing_data.ltk_init;
1733 if( ltk.isResponder() ) {
1734 pairing_data.ltk_resp = ltk;
1738 pairing_data.ltk_init = ltk;
1746 return responder ? pairing_data.irk_resp : pairing_data.irk_init;
1751 if( irk.isResponder() ) {
1752 pairing_data.irk_resp = irk;
1757 pairing_data.irk_init = irk;
1769 return irk.
matches(rpa.address);
1777 return responder ? pairing_data.csrk_resp : pairing_data.csrk_init;
1782 if( csrk.isResponder() ) {
1783 pairing_data.csrk_resp = csrk;
1787 pairing_data.csrk_init = csrk;
1795 return responder ? pairing_data.lk_resp : pairing_data.lk_init;
1800 if( lk.isResponder() ) {
1801 pairing_data.lk_resp = lk;
1805 pairing_data.lk_init = lk;
1813 return pairing_data.sec_level_conn;
1818 return pairing_data.io_cap_conn;
1826 res_io_cap = io_cap_conn;
1829 DBG_PRINT(
"BTDevice::validateConnectedSecParam: dev_id %u, sec_lvl %s, io_cap %s (preset)", adapter.dev_id,
1832 res_sec_level = sec_level_conn;
1841 res_sec_level = sec_level_user;
1842 }
else if( responderLikesEncryption ) {
1845 if( adapter.hasSecureConnections() ) {
1857 DBG_PRINT(
"BTDevice::validateConnectedSecParam: dev_id %u, user[sec_lvl %s, io_cap %s], conn[sec_lvl %s, io_cap %s] -> sec_lvl %s, io_cap %s",
1872 res_sec_level = sec_level;
1876 res_sec_level = sec_level;
1877 res_io_cap = io_cap;
1884 res_sec_level = sec_level;
1885 res_io_cap = io_cap;
1889 res_io_cap = io_cap;
1891 DBG_PRINT(
"BTDevice::validateSecurityParams: lvl %s -> %s, io %s -> %s",
1897 if( !isValidInstance() ) {
1901 if( isConnected || allowDisconnect ) {
1902 ERR_PRINT(
"Invalid State: Connected: dev_id %u, lvl %s, io %s failed, %s",
1903 adapter.dev_id,
to_string(sec_level).c_str(),
1904 to_string(io_cap).c_str(), toString().c_str());
1909 if( !pairing_data.is_pre_paired ) {
1910 validateSecParam(sec_level, io_cap, pairing_data.sec_level_user, pairing_data.io_cap_user);
1914 DBG_PRINT(
"BTDevice::setConnSecurity: dev_id %u, pre-paired %d: lvl %s -> %s, io %s -> %s, %s",
1915 adapter.dev_id, pairing_data.is_pre_paired,
1918 toString().c_str());
1924 if( !isValidInstance() ) {
1928 if( isConnected || allowDisconnect ) {
1929 ERR_PRINT(
"Invalid State: Connected: dev_id %d, io %s failed, %s",
1930 adapter.dev_id,
to_string(iocap_auto).c_str(), toString().c_str());
1933 if( pairing_data.is_pre_paired ) {
1934 DBG_PRINT(
"BTDevice::setConnSecurityAuto: io %s failed, is pre-paired: %s",
1936 toString().c_str());
1942 DBG_PRINT(
"BTDevice::setConnSecurityAuto: io %s failed, user connection sec_level %s or io %s set %s",
1944 to_string(pairing_data.sec_level_user).c_str(),
1945 to_string(pairing_data.io_cap_user).c_str(),
1946 toString().c_str());
1950 DBG_PRINT(
"BTDevice::setConnSecurityAuto: Not allowed with remote device in master mode: %s",
1951 to_string(iocap_auto).c_str(), toString().c_str());
1956 const bool res =
true;
1957 pairing_data.io_cap_auto = iocap_auto;
1958 DBG_PRINT(
"BTDevice::setConnSecurityAuto: result %d: io %s, %s", res,
1959 to_string(iocap_auto).c_str(), toString().c_str());
1969 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
1974 WARN_PRINT(
"BTDevice:mgmt:SMP: PINCODE '%s', state %s, wrong state", pinCode.c_str(),
to_string(pairing_data.state).c_str());
1978 MgmtStatus res = mngr->userPINCodeReply(adapter.dev_id, addressAndType, pinCode);
1979 DBG_PRINT(
"BTDevice:mgmt:SMP: PINCODE '%s', state %s, result %s",
1990 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
1995 WARN_PRINT(
"BTDevice:mgmt:SMP: PINCODE_NEGATIVE, state %s, wrong state",
to_string(pairing_data.state).c_str());
2000 DBG_PRINT(
"BTDevice:mgmt:SMP: PINCODE NEGATIVE, state %s, result %s",
2011 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
2016 WARN_PRINT(
"BTDevice:mgmt:SMP: PASSKEY '%u', state %s, wrong state", passkey,
to_string(pairing_data.state).c_str());
2020 MgmtStatus res = mngr->userPasskeyReply(adapter.dev_id, addressAndType, passkey);
2021 DBG_PRINT(
"BTDevice:mgmt:SMP: PASSKEY '%u', state %s, result %s",
2032 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
2037 WARN_PRINT(
"BTDevice:mgmt:SMP: PASSKEY_NEGATIVE, state %s, wrong state",
to_string(pairing_data.state).c_str());
2042 DBG_PRINT(
"BTDevice:mgmt:SMP: PASSKEY NEGATIVE, state %s, result %s",
2053 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
2058 WARN_PRINT(
"BTDevice:mgmt:SMP: CONFIRM '%d', state %s, wrong state", positive,
to_string(pairing_data.state).c_str());
2062 MgmtStatus res = mngr->userConfirmReply(adapter.dev_id, addressAndType, positive);
2063 DBG_PRINT(
"BTDevice:mgmt:SMP: CONFIRM '%d', state %s, result %s",
2075 return pairing_data.mode;
2080 return pairing_data.state;
2083void BTDevice::clearSMPStates(
const bool connected)
noexcept {
2086 const std::unique_lock<std::recursive_mutex> lock_pairing(mtx_pairing);
2089 DBG_PRINT(
"BTDevice::clearSMPStates(connected %d): %s", connected, toString().c_str());
2100 pairing_data.is_pre_paired =
false;
2103 pairing_data.res_requested_sec =
false;
2104 pairing_data.use_sc =
false;
2105 pairing_data.encryption_enabled =
false;
2107 pairing_data.passKey_resp = 0;
2112 pairing_data.maxEncsz_resp = 0;
2115 pairing_data.ltk_resp.clear();
2116 pairing_data.irk_resp.clear();
2117 pairing_data.id_address_resp.clear();
2118 pairing_data.csrk_resp.clear();
2119 pairing_data.lk_resp.clear();
2124 pairing_data.maxEncsz_init = 0;
2127 pairing_data.ltk_init.clear();
2128 pairing_data.irk_init.clear();
2129 pairing_data.id_address_init.clear();
2130 pairing_data.csrk_init.clear();
2131 pairing_data.lk_init.clear();
2134void BTDevice::disconnectSMP(
const int caller)
noexcept {
2136 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_smpHandler);
2137 if(
nullptr != smpHandler ) {
2138 DBG_PRINT(
"BTDevice::disconnectSMP: start (has smpHandler, caller %d)", caller);
2139 smpHandler->disconnect(
false ,
false );
2141 DBG_PRINT(
"BTDevice::disconnectSMP: start (nil smpHandler, caller %d)", caller);
2143 smpHandler =
nullptr;
2144 DBG_PRINT(
"BTDevice::disconnectSMP: end");
2150bool BTDevice::connectSMP(std::shared_ptr<BTDevice> sthis,
const BTSecurityLevel sec_level)
noexcept {
2152 if( !isConnected || !allowDisconnect) {
2153 ERR_PRINT(
"connectSMP(%u): Device not connected: %s", sec_level, toString().c_str());
2158 DBG_PRINT(
"BTDevice::connectSMP(%u): SMP Not supported by OS (1): %s", sec_level, toString().c_str());
2166 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_gattHandler);
2167 if(
nullptr != smpHandler ) {
2168 if( smpHandler->isConnected() ) {
2169 return smpHandler->establishSecurity(sec_level);
2171 smpHandler =
nullptr;
2174 smpHandler = std::make_shared<SMPHandler>(sthis);
2175 if( !smpHandler->isConnected() ) {
2177 smpHandler =
nullptr;
2180 return smpHandler->establishSecurity(sec_level);
2182 DBG_PRINT(
"BTDevice::connectSMP: SMP Not supported by OS (0): %s", toString().c_str());
2189void BTDevice::disconnectGATT(
const int caller)
noexcept {
2190 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_gattHandler);
2191 if(
nullptr != gattHandler ) {
2192 DBG_PRINT(
"BTDevice::disconnectGATT: start (has gattHandler, caller %d)", caller);
2193 gattHandler->disconnect(
false ,
false );
2195 DBG_PRINT(
"BTDevice::disconnectGATT: start (nil gattHandler, caller %d)", caller);
2197 gattHandler =
nullptr;
2198 DBG_PRINT(
"BTDevice::disconnectGATT: end");
2201bool BTDevice::connectGATT(
const std::shared_ptr<BTDevice>& sthis)
noexcept {
2202 if( !isConnected || !allowDisconnect) {
2203 ERR_PRINT(
"Device not connected: %s", toString().c_str());
2206 if( !l2cap_att->is_open() ) {
2207 ERR_PRINT(
"L2CAP not open: %s", toString().c_str());
2211 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_gattHandler);
2212 if(
nullptr != gattHandler ) {
2213 if( gattHandler->isConnected() ) {
2216 gattHandler =
nullptr;
2219 DBG_PRINT(
"BTDevice::connectGATT: Start: %s", toString().c_str());
2222 gattHandler = std::make_shared<BTGattHandler>(sthis, *l2cap_att, supervision_timeout);
2223 if( !gattHandler->isConnected() ) {
2225 gattHandler =
nullptr;
2228 DBG_PRINT(
"BTDevice::connectGATT: Local GATT Server: Done: %s", toString().c_str());
2230 DBG_PRINT(
"BTDevice::connectGATT: Local GATT Client: Done: %s", toString().c_str());
2236 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_gattHandler);
2242 if(
nullptr == gh ) {
2252 bool gatt_already_init =
false;
2253 if( !gh->initClientGatt(gh, gatt_already_init) ) {
2254 ERR_PRINT2(
"Client GATT Initialization failed");
2257 if( gatt_already_init ) {
2258 return gh->getServices();
2262 if( result.
size() == 0 ) {
2263 ERR_PRINT2(
"No primary services discovered");
2268 std::shared_ptr<GattGenericAccessSvc> gattGenericAccess = gh->getGenericAccess();
2269 if(
nullptr == gattGenericAccess ) {
2276 EIRDataType updateMask = update(*gattGenericAccess, ts);
2277 DBG_PRINT(
"BTDevice::getGattServices: GenericAccess updated %s:\n %s\n -> %s",
2278 to_string(updateMask).c_str(), gattGenericAccess->toString().c_str(),
toString().c_str());
2281 if(
nullptr == sharedInstance ) {
2284 adapter.sendDeviceUpdated(
"getGattServices", sharedInstance, ts, updateMask);
2292 if(
nullptr == gh ) {
2296 return gh->getGenericAccess();
2302 if (
nullptr != s && service_uuid.equivalent( *(s->type) ) ) {
2311 if(
nullptr == service ) {
2314 return service->findGattChar(char_uuid);
2320 if (
nullptr != s ) {
2322 if (
nullptr != c ) {
2331 if( !isValidInstance() ) {
2335 std::shared_ptr<BTGattHandler> gh = getGattHandler();
2336 if(
nullptr == gh || !gh->isConnected() ) {
2337 WARN_PRINT(
"GATTHandler not connected -> disconnected on %s", toString().c_str());
2340 return gh->sendNotification(char_value_handle, value);
2344 if( !isValidInstance() ) {
2348 std::shared_ptr<BTGattHandler> gh = getGattHandler();
2349 if(
nullptr == gh || !gh->isConnected() ) {
2350 WARN_PRINT(
"GATTHandler not connected -> disconnected on %s", toString().c_str());
2353 return gh->sendIndication(char_value_handle, value);
2359 if(
nullptr == gh || !gh->isConnected() ) {
2368 std::shared_ptr<BTGattHandler> gatt = getGattHandler();
2369 if(
nullptr == gatt ) {
2370 ERR_PRINT(
"Device's GATTHandle not connected: %s", toString().c_str());
2373 return gatt->addCharListener(l);
2377 std::shared_ptr<BTGattHandler> gatt = getGattHandler();
2378 if(
nullptr == gatt ) {
2379 ERR_PRINT(
"Device's GATTHandle not connected: %s", toString().c_str());
2382 return gatt->addCharListener(l, d);
2386 std::shared_ptr<BTGattHandler> gatt = getGattHandler();
2387 if(
nullptr == gatt ) {
2389 DBG_PRINT(
"Device's GATTHandle not connected: %s", toString().c_str());
2392 return gatt->removeCharListener(l);
2396 std::shared_ptr<BTGattHandler> gatt = getGattHandler();
2397 if(
nullptr == gatt ) {
2399 DBG_PRINT(
"Device's GATTHandle not connected: %s", toString().c_str());
2402 return gatt->removeAllAssociatedCharListener( associatedCharacteristic );
2406 std::shared_ptr<BTGattHandler> gatt = getGattHandler();
2407 if(
nullptr == gatt ) {
2409 DBG_PRINT(
"Device's GATTHandle not connected: %s", toString().c_str());
2412 return gatt->removeAllAssociatedCharListener( associatedCharacteristic );
2417 if(
nullptr == gatt ) {
2422 return gatt->removeAllCharListener();
2426 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect);
2428 if( !isConnected ) {
2432 if( 0 == hciConnHandle ) {
2436 if( !adapter.isPowered() ) {
2450 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect);
2452 if( !isConnected ) {
2456 if( 0 == hciConnHandle ) {
2460 if( !adapter.isPowered() ) {
2465 return hci.
le_set_phy(hciConnHandle, addressAndType, Tx, Rx);
2468void BTDevice::notifyDisconnected() noexcept {
2470 DBG_PRINT(
"BTDevice::notifyDisconnected: handle %s -> zero, %s",
2472 allowDisconnect =
false;
2473 supervision_timeout = 0;
2474 isConnected =
false;
2484void BTDevice::sendMgmtEvDeviceDisconnected(std::unique_ptr<MgmtEvent> evt)
noexcept {
2485 adapter.mgmtEvDeviceDisconnectedHCI(*evt);
2490 bool expConn =
true;
2491 if( !allowDisconnect.compare_exchange_strong(expConn,
false) ) {
2493 DBG_PRINT(
"BTDevice::disconnect: Not connected: isConnected %d/%d, reason 0x%X (%s), gattHandler %d, hciConnHandle %s",
2494 allowDisconnect.load(), isConnected.load(),
2495 static_cast<uint8_t
>(reason),
to_string(reason).c_str(),
2499 if( !isConnected ) {
2500 WARN_PRINT(
"allowConnect true -> false, but !isConnected on %s", toString().c_str());
2510 const std::lock_guard<std::recursive_mutex> lock_conn(mtx_connect);
2512 WORDY_PRINT(
"BTDevice::disconnect: Start: isConnected %d/%d, reason 0x%X (%s), gattHandler %d, hciConnHandle %s",
2513 allowDisconnect.load(), isConnected.load(),
2514 static_cast<uint8_t
>(reason),
to_string(reason).c_str(),
2520 if( 0 == hciConnHandle ) {
2525 if( !adapter.isPowered() ) {
2526 WARN_PRINT(
"Adapter not powered: %s, %s", adapter.toString().c_str(), toString().c_str());
2531 res = hci.
disconnect(hciConnHandle, addressAndType, reason);
2533 ERR_PRINT(
"status %s, handle 0x%X, isConnected %d/%d: errno %d %s on %s",
2534 to_string(res).c_str(), hciConnHandle.load(),
2535 allowDisconnect.load(), isConnected.load(),
2536 errno, strerror(errno),
2537 toString().c_str());
2545 jau::INFO_PRINT(
"BTDevice::disconnect: DEL FROM RESOLV LIST failed %s for %s",
2546 to_string(res2).c_str(), toString().c_str());
2555 std::thread bg(&BTDevice::sendMgmtEvDeviceDisconnected,
this,
2556 std::make_unique<MgmtEvtDeviceDisconnected>(adapter.dev_id, addressAndType, reason, hciConnHandle) );
2560 WORDY_PRINT(
"BTDevice::disconnect: End: status %s, handle 0x%X, isConnected %d/%d on %s",
2562 hciConnHandle.load(), allowDisconnect.load(), isConnected.load(),
2563 toString().c_str());
2569 return pairing_data.passKey_resp;
2589 adapter.removeDevice(*
this);
static const SMPKeyType _key_mask_legacy
static const SMPKeyType _key_mask_sc
Unique Bluetooth EUI48 address and BDAddressType tuple.
static BLERandomAddressType getBLERandomAddressType(const jau::EUI48 &address, const BDAddressType addressType) noexcept
Returns the BLERandomAddressType.
constexpr bool isLEAddress() const noexcept
Returns true if the BDAddressType is a LE address type.
std::string toString() const noexcept
BTAdapter represents one local Bluetooth Controller.
const uint16_t dev_id
Adapter's internal temporary device id.
BTRole getRole() const noexcept
Return the current BTRole of this adapter.
const BTManagerRef & getManager() const noexcept
Returns a reference to the used singleton BTManager instance, used to create this adapter.
BDAddressAndType addressAndType
Device's unique mac address and type tuple, might be its initially reported (resolvable) random addre...
std::shared_ptr< GattGenericAccessSvc > getGattGenericAccess()
Returns the shared GenericAccess instance, retrieved by getGattServices() or nullptr if not available...
HCIStatusCode setPairingPINCodeNegative() noexcept
bool removeCharListener(const BTGattCharListenerRef &l) noexcept
Remove the given BTGattCharListener from the listener list.
bool setConnSecurity(const BTSecurityLevel sec_level, const SMPIOCapability io_cap=SMPIOCapability::UNSET) noexcept
Sets the given BTSecurityLevel and SMPIOCapability used to connect to this device on the upcoming con...
bool isConnSecurityAutoEnabled() const noexcept
Returns true if automatic security negotiation has been enabled via setConnSecurityAuto(),...
SMPLongTermKey getLongTermKey(const bool responder) const noexcept
Returns a copy of the Long Term Key (LTK), valid after connection and SMP pairing has been completed.
bool pingGATT() noexcept
Issues a GATT ping to the device, validating whether it is still reachable.
void remove() noexcept
Disconnects this device via disconnect(..) if getConnected()==true and explicitly removes its shared ...
BTRole getRole() const noexcept
Return the fixed BTRole of this remote BTDevice.
SMPSignatureResolvingKey getSignatureResolvingKey(const bool responder) const noexcept
Returns a copy of the Signature Resolving Key (CSRK), valid after connection and SMP pairing has been...
EInfoReportRef getEIRInd() noexcept
Return the latest advertised EInfoReport AD_IND variant for this remote device.
HCIStatusCode setPairingPasskeyNegative() noexcept
Method replies with a negative passkey response, i.e.
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...
bool setSMPKeyBin(const SMPKeyBin &bin) noexcept
Copy all keys from the given SMPKeyBin into this BTDevice.
HCIStatusCode connectBREDR(const uint16_t pkt_type=HCI_DM1|HCI_DM3|HCI_DM5|HCI_DH1|HCI_DH3|HCI_DH5, const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01) noexcept
Establish a HCI BDADDR_BREDR connection to this device.
HCIStatusCode unpair() noexcept
Unpair this device from the adapter while staying connected.
bool removeStatusListener(const AdapterStatusListenerRef &l) noexcept
Remove the given listener from the list.
SMPPairingState getPairingState() const noexcept
Returns the current SMPPairingState.
SMPIdentityResolvingKey getIdentityResolvingKey(const bool responder) const noexcept
Returns a copy of the Identity Resolving Key (IRK), valid after connection and SMP pairing has been c...
std::shared_ptr< ConnectionInfo > getConnectionInfo() noexcept
Retrieves the current connection info for this device and returns the ConnectionInfo reference if suc...
bool setConnSecurityAuto(const SMPIOCapability iocap_auto) noexcept
Set automatic security negotiation of BTSecurityLevel and SMPIOCapability pairing mode.
HCIStatusCode connectLE(const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint16_t conn_interval_min=8, const uint16_t conn_interval_max=12, const uint16_t conn_latency=0, const uint16_t conn_supervision_timeout=getHCIConnSupervisorTimeout(0, 15)) noexcept
Establish a HCI BDADDR_LE_PUBLIC or BDADDR_LE_RANDOM connection to this device.
PairingMode getPairingMode() const noexcept
Returns the current PairingMode used by the device.
HCIStatusCode setConnectedLE_PHY(const LE_PHYs Tx, const LE_PHYs Rx) noexcept
Sets preference of used LE_PHYs for the given connection.
std::string const getName() const noexcept
Returns the remote device name.
EInfoReportRef getEIR() noexcept
Return the merged advertised EInfoReport for this remote device.
HCIStatusCode getConnectedLE_PHY(LE_PHYs &resTx, LE_PHYs &resRx) noexcept
Request and return LE_PHYs bit for the given connection.
void setSignatureResolvingKey(const SMPSignatureResolvingKey &csrk) noexcept
Sets the Signature Resolving Key (CSRK) of this device for pre-paired encryption.
size_type removeAllAssociatedCharListener(const BTGattCharRef &associatedCharacteristic) noexcept
Remove all BTGattCharListener from the list, which are associated to the given BTGattChar.
EInfoReportRef getEIRScanRsp() noexcept
Return the latest advertised EInfoReport AD_SCAN_RSP for this remote device.
std::shared_ptr< BTDevice > getSharedInstance() const noexcept
Returns the shared pointer of this instance managed by the adapter.
bool sendIndication(const uint16_t char_value_handle, const jau::TROOctets &value) noexcept
Send an indication event consisting out of the given value representing the given characteristic valu...
BTSecurityLevel getConnSecurityLevel() const noexcept
Return the BTSecurityLevel, determined when the connection is established.
SMPKeyType getAvailableSMPKeys(const bool responder) const noexcept
Returns the available SMPKeyType mask for the responder (LL slave) or initiator (LL master).
GattServiceList_t getGattServices() noexcept
Returns a complete list of shared BTGattService available on this device, initially retrieved via GAT...
void setIdentityResolvingKey(const SMPIdentityResolvingKey &irk) noexcept
Sets the Identity Resolving Key (IRK) of this device for pre-paired encryption.
void setLinkKey(const SMPLinkKey &lk) noexcept
Sets the Link Key (LK) of this device for pre-paired encryption.
~BTDevice() noexcept override
Releases this instance after calling remove().
HCIStatusCode connectDefault() noexcept
Establish a default HCI connection to this device, using certain default parameter.
std::uint32_t getResponderSMPPassKey() const noexcept
Returns the responder SMP passkey, ranging from [0..999999].
std::shared_ptr< BTGattHandler > getGattHandler() noexcept
Returns the connected GATTHandler or nullptr, see connectGATT(), getGattServices() and disconnect().
BTGattServiceRef findGattService(const jau::uuid_t &service_uuid) noexcept
Find a BTGattService by its service_uuid.
HCIStatusCode disconnect(const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION) noexcept
Disconnect the LE or BREDR peer's GATT and HCI connection.
bool matches_irk(const BDAddressAndType &rpa) noexcept
Returns true if this remote device's IRK matches the given random private address (rpa)
SMPIOCapability getConnIOCapability() const noexcept
Return the set SMPIOCapability value, determined when the connection is established.
SMPLinkKey getLinkKey(const bool responder) const noexcept
Returns a copy of the Link Key (LK), valid after connection and SMP pairing has been completed.
BTGattCharRef findGattChar(const jau::uuid_t &service_uuid, const jau::uuid_t &char_uuid) noexcept
Find a BTGattChar by its service_uuid and char_uuid.
bool addCharListener(const BTGattCharListenerRef &l) noexcept
Add the given BTGattCharListener to the listener list if not already present.
HCIStatusCode setPairingNumericComparison(const bool equal) noexcept
Method sets the numeric comparison result, see PairingMode::NUMERIC_COMPARE_ini.
bool addStatusListener(const AdapterStatusListenerRef &l) noexcept
Add the given AdapterStatusListener to the list if not already present, intended to listen only for e...
HCIStatusCode uploadKeys() noexcept
Upload all set keys to the adapter for pre-pairing.
bool getConnected() noexcept
Return true if the device has been successfully connected, otherwise false.
GATTRole getLocalGATTRole() const noexcept
Return the local GATTRole operating for the remote BTDevice.
void setLongTermKey(const SMPLongTermKey <k) noexcept
Sets the Long Term Key (LTK) of this device for pre-paired encryption.
std::string toString() const noexcept override
HCIStatusCode setPairingPasskey(const uint32_t passkey) noexcept
Method sets the given passkey entry, see PairingMode::PASSKEY_ENTRY_ini.
bool sendNotification(const uint16_t char_value_handle, const jau::TROOctets &value) noexcept
Send a notification event consisting out of the given value representing the given characteristic val...
size_type removeAllCharListener() noexcept
Remove all BTGattCharListener from the list.
HCIStatusCode setPairingPINCode(const std::string &pinCode) noexcept
Representing a Gatt Characteristic object from the GATTRole::Client perspective.
Collection of 'Extended Advertising Data' (EAD), 'Advertising Data' (AD) or 'Extended Inquiry Respons...
std::string toString(const bool includeServices=true) const noexcept
bool isSet(EIRDataType bit) const noexcept
@ AD_SCAN_RSP
(Extended) Advertising Data (AD or EAD) Scan Response, i.e.
@ AD_IND
(Extended) Advertising Data (AD or EAD) Indication Variant, i.e.
Generic Access Service is a mandatory GATT service all peripherals are required to implement.
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 isOpen() const noexcept
Returns true if this mgmt instance is open, connected and hence valid, otherwise false.
HCIStatusCode create_conn(const EUI48 &bdaddr, const uint16_t pkt_type=HCI_DM1|HCI_DM3|HCI_DM5|HCI_DH1|HCI_DH3|HCI_DH5, const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01) noexcept
Establish a connection to the given BREDR (non LE).
HCIStatusCode le_set_phy(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType, const LE_PHYs Tx, const LE_PHYs Rx) noexcept
Sets preference of used LE_PHYs for the given connection.
HCIStatusCode le_read_phy(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType, LE_PHYs &resTx, LE_PHYs &resRx) noexcept
Request and return LE_PHYs bit for the given connection.
HCIStatusCode le_del_from_resolv_list(const BDAddressAndType &peerIdentityAddressAndType) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.39 LE Remove Device From Resolving List command.
HCIStatusCode le_create_conn(const EUI48 &peer_bdaddr, const HCILEPeerAddressType peer_mac_type=HCILEPeerAddressType::PUBLIC, const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC, const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint16_t conn_interval_min=8, const uint16_t conn_interval_max=12, const uint16_t conn_latency=0, const uint16_t supervision_timeout=getHCIConnSupervisorTimeout(0, 15)) noexcept
Establish a connection to the given LE peer.
HCIStatusCode disconnect(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType, const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION) noexcept
Disconnect an established connection.
L2CAP read/write communication channel to remote device.
uint16_t opcode, uint16_t dev-id, uint16_t param_size
@ HCI_ENC_KEY_REFRESH_COMPLETE
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.7.65.5 LE Long Term Key Request event.
uint8_t store_hint, MgmtLinkKey key
uint8_t store_hint, MgmtLongTermKey key
mgmt_addr_info { EUI48, uint8_t type }, uint32_t passkey uint8_t entered
Vol 3, Part H: 3.6.2 Encryption Information message.
constexpr jau::uint128dp_t getLTK() const noexcept
Returns the 128-bit Long Term Key (16 octets)
static bool IS_SUPPORTED_BY_OS
Linux/BlueZ prohibits access to the existing SMP implementation via L2CAP (socket).
Vol 3, Part H: 3.6.5 Identity Address Information message.
EUI48 getAddress() const noexcept
Returns the device address.
Vol 3, Part H: 3.6.4 Identify Information message.
constexpr jau::uint128dp_t getIRK() const noexcept
Returns the 128-bit Identity Resolving Key (IRK, 16 octets)
Storage for SMP keys including required connection parameter per local adapter and remote device.
Vol 3, Part H: 3.6.3 Master Identification message.
constexpr uint16_t getEDIV() const noexcept
Returns the 16-bit EDIV value (2 octets) being distributed.
constexpr uint64_t getRand() const noexcept
Returns the 64-bit Rand value (8 octets) being distributed.
Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU) encoded messages over L2CA...
virtual std::string toString() const noexcept
Opcode
SMP Command Codes Vol 3, Part H (SM): 3.3.
@ IDENTITY_ADDRESS_INFORMATION
Vol 3, Part H: 3.5.1 Pairing Request message.
constexpr SMPAuthReqs getAuthReqMask() const noexcept
Returns the Authentication Requirements mask.
constexpr SMPKeyType getInitKeyDist() const noexcept
Returns the Initiator Key Distribution field, which defines which keys the initiator shall distribute...
constexpr SMPKeyType getRespKeyDist() const noexcept
Return the Responder Key Distribution field, which defines which keys the responder shall distribute ...
constexpr SMPIOCapability getIOCapability() const noexcept
Returns the IO capability bit field.
constexpr uint8_t getMaxEncryptionKeySize() const noexcept
This value defines the maximum encryption key size in octets that the device can support.
constexpr SMPOOBDataFlag getOOBDataFlag() const noexcept
Returns the OBB authenticate data flag.
Vol 3, Part H: 3.6.6 Signing Information message.
constexpr jau::uint128dp_t getCSRK() const noexcept
Returns the 128-bit Connection Signature Resolving Key (CSRK, 16 octets)
Transient read only and endian aware octet data, i.e.
Implementation of a dynamic linear array storage, aka vector.
constexpr size_type size() const noexcept
Like std::vector::size().
constexpr void push_back(const value_type &x)
Like std::vector::push_back(), copy.
const bool debug
Debug logging enabled or disabled.
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 uint64_t getElapsedMillisecond() noexcept
Returns current elapsed monotonic time in milliseconds since module startup, see startupTimeMilliseco...
constexpr int_type to_ms() const noexcept
Convenient shortcut to to_num_of(1_ms)
std::chrono::duration< Rep, Period > to_duration(const std::chrono::duration< Rep, Period > &dur_ref, bool *overflow_ptr=nullptr) const noexcept
Convert this fraction into std::chrono::duration with given Rep and Period.
This class provides a RAII-style Sequentially Consistent (SC) data race free (DRF) critical block.
static const uint16_t le_scan_interval
static const uint16_t le_scan_window
static jau::sc_atomic_bool sync_data
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
#define WORDY_PRINT(...)
Use for environment-variable environment::VERBOSE conditional verbose messages, prefix '[elapsed_time...
#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: '.
std::string to_string(const alphabet &v) noexcept
constexpr const bool CONSIDER_HCI_CMD_FOR_SMP_STATE
constexpr bool hasSMPPairingFinished(const SMPPairingState state) noexcept
Returns true if the given SMPPairingState indicates a finished pairing process, i....
constexpr const bool SMP_SUPPORTED_BY_OS
constexpr bool hasSMPIOCapabilityFullInput(const SMPIOCapability ioc) noexcept
constexpr bool isSMPPairingAllowingInput(const SMPPairingState state, const SMPPairingState inputSpec) noexcept
Returns true if the given SMPPairingState indicates a pairing process waiting for user input,...
SMPPairingState
SMP Pairing Process state definition.
SMPKeyType
SMP Key Type for Distribution, indicates keys distributed in the Transport Specific Key Distribution ...
constexpr bool hasSMPIOCapabilityAnyIO(const SMPIOCapability ioc) noexcept
std::string toPassKeyString(const std::uint32_t passKey) noexcept
Returns given passKey ranging [0..999999] as a canonical string, e.g.
SMPIOCapability
Vol 3, Part H, 2.3.2 IO capabilities.
PairingMode getPairingMode(const bool use_sc, const SMPAuthReqs authReqs_ini, const SMPIOCapability ioCap_ini, const SMPOOBDataFlag oobFlag_ini, const SMPAuthReqs authReqs_res, const SMPIOCapability ioCap_res, const SMPOOBDataFlag oobFlag_res) noexcept
Returns the PairingMode derived from both devices' sets of SMPAuthReqs, SMPIOCapability and SMPOOBDat...
constexpr const bool USE_LINUX_BT_SECURITY
constexpr bool hasSMPIOCapabilityBinaryInput(const SMPIOCapability ioc) noexcept
@ SECURE_CONNECTIONS
If LE Secure Connections pairing is supported by the device, then the SC field shall be set to 1,...
@ OOB_EXPECTED
Phase 2: Authentication (MITM) OOB data expected now, see PairingMode::OUT_OF_BAND.
@ REQUESTED_BY_RESPONDER
Phase 0: Pairing requested by responding (slave) device via SMPSecurityReqMsg.
@ 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.
@ FEATURE_EXCHANGE_STARTED
Phase 1: Pairing requested by initiating (master) device via SMPPairingMsg.
@ FEATURE_EXCHANGE_COMPLETED
Phase 1: Pairing responded by responding (slave) device via SMPPairingMsg.
@ KEY_DISTRIBUTION
Phase 3: Key & value distribution started after SMPPairConfirmMsg or SMPPairPubKeyMsg (LE Secure Conn...
@ LINK_KEY
SMP on the LE transport: Indicate that the device would like to derive the Link Key from the LTK.
@ SIGN_KEY
Indicates that the device shall distribute CSRK using the Signing Information command.
@ ENC_KEY
LE legacy pairing: Indicates device shall distribute LTK using the Encryption Information command,...
@ ID_KEY
Indicates that the device shall distribute IRK using the Identity Information command followed by its...
@ OOB_AUTH_DATA_NOT_PRESENT
OOB_AUTH_DATA_NOT_PRESENT.
@ UNSET
Denoting unset value, i.e.
@ NO_INPUT_NO_OUTPUT
No input not output, value 3.
std::shared_ptr< BTManager > BTManagerRef
BLERandomAddressType
BT Core Spec v5.2: Vol 6 LE, Part B Link Layer Specification: 1.3 Device Address.
std::shared_ptr< AdapterStatusListener > AdapterStatusListenerRef
LE_Features
HCI Supported Commands.
constexpr void set(EAD_Event_Type &mask, const EAD_Event_Type bit) noexcept
std::string to_string(const DiscoveryPolicy v) noexcept
LE_PHYs
LE Transport PHY bit values.
HCILEPeerAddressType
HCI LE Address-Type is PUBLIC: 0x00, RANDOM: 0x01.
std::shared_ptr< EInfoReport > EInfoReportRef
GATTRole
Bluetooth GATT roles.
BTRole
Bluetooth roles from the perspective of the link layer (connection initiator).
L2CAP_PSM
Protocol Service Multiplexers (PSM) Assigned numbers https://www.bluetooth.com/specifications/assigne...
BTSecurityLevel
Bluetooth Security Level.
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.
@ UNDEFINED
Undefined, e.g.
@ RESOLVABLE_PRIVAT
Resolvable private random device address 0b01.
@ UNRESOLVABLE_PRIVAT
Non-resolvable private random device address 0b00.
@ STATIC_PUBLIC
Static public 'random' device address 0b11.
@ LE_Encryption
LE_Encryption.
@ RANDOM
Random Device Address.
@ PUBLIC
Public Device Address.
@ Client
Local GATT client role to a remote BTDevice BTRole::Slave running a GATTRole::Server.
@ Server
Local GATT server role to a remote BTDevice BTRole::Master running a GATTRole::Client.
@ BDADDR_BREDR
Bluetooth BREDR address.
@ BDADDR_LE_RANDOM
Bluetooth LE random address, see BLERandomAddressType.
@ BDADDR_LE_PUBLIC
Bluetooth LE public address.
@ 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.
@ UNSET
Security Level not set, value 0.
@ ENC_AUTH
Encryption and authentication (MITM).
@ ENC_ONLY
Encryption and no authentication (no MITM).
@ NONE
No encryption and no authentication.
@ ENC_AUTH_FIPS
Authenticated Secure Connections.
@ PRE_PAIRED
Reusing encryption keys from previous pairing.
@ NEGOTIATING
Pairing mode in negotiating, i.e.
@ OUT_OF_BAND
Utilizing a second factor secret to be used as a secret, e.g.
@ PASSKEY_ENTRY_ini
Passkey Entry input by initiator.
@ NUMERIC_COMPARE_ini
Visual comparison of digit sequence (PIN) input by initiator, shown on both devices.
@ NONE
No pairing mode, implying no secure connections, no encryption and no MITM protection.
@ CONNECTION_TERMINATED_BY_LOCAL_HOST
@ REMOTE_USER_TERMINATED_CONNECTION
@ UNACCEPTABLE_CONNECTION_PARAM
@ CONNECTION_ALREADY_EXISTS
std::shared_ptr< BTGattCharListener > BTGattCharListenerRef
std::shared_ptr< BTGattChar > BTGattCharRef
std::shared_ptr< BTGattService > BTGattServiceRef
void sync() noexcept
Synchronizes filesystems, i.e.
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
std::string to_decstring(const value_type &v, const char separator=',', const nsize_t width=0) noexcept
Produce a decimal string representation of an integral integer value.
constexpr const jau::fraction_i64 zero(0l, 1lu)
zero is 0/1
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: '.
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.
Used for MgmtLoadLinkKeyCmd and MgmtEvtNewLinkKey.
SMPLinkKey toSMPLinkKeyInfo(const bool isResponder) const noexcept
Used for MgmtLoadLongTermKeyCmd and MgmtEvtNewLongTermKey.
SMPLongTermKey toSMPLongTermKey(const BTRole adapterRole) const noexcept
SMP Identity Resolving Key, used for platform agnostic persistence.
bool matches(const EUI48 &rpa) noexcept
Returns true if this IRK matches the given random private address (RPA).
Local SMP Link Key, used for platform agnostic persistence, mapping to platform specific MgmtLoadLink...
bool isResponder() const noexcept
constexpr bool isValid() const noexcept
constexpr bool isCombiKey() const noexcept
SMP Long Term Key, used for platform agnostic persistence.
constexpr bool isValid() const noexcept
bool isResponder() const noexcept
@ SC
Secure Connection used.
@ AUTH
Authentication used.
uint8_t enc_size
Encryption Size, zero if key is invalid.
Property properties
SMPLongTermKey::Property bit mask.
jau::uint128dp_t ltk
Long Term Key (LTK)
SMP Signature Resolving Key, used for platform agnostic persistence.
@ AUTH
Authentication used.