41 #include "BTIoctl.hpp"
43 #include "HCIIoctl.hpp"
54 #include <sys/ioctl.h>
60 HCIEnv::HCIEnv() noexcept
61 : exploding(
jau::environment::getExplodingProperties("
direct_bt.hci") ),
62 HCI_READER_THREAD_POLL_TIMEOUT(
jau::environment::getInt32Property("
direct_bt.hci.reader.timeout", 10000, 1500 , INT32_MAX ) ),
63 HCI_COMMAND_STATUS_REPLY_TIMEOUT(
jau::environment::getInt32Property("
direct_bt.hci.cmd.status.timeout", 3000, 1500 , INT32_MAX ) ),
64 HCI_COMMAND_COMPLETE_REPLY_TIMEOUT(
jau::environment::getInt32Property("
direct_bt.hci.cmd.complete.timeout", 10000, 1500 , INT32_MAX ) ),
65 HCI_COMMAND_POLL_PERIOD(
jau::environment::getInt32Property("
direct_bt.hci.cmd.poll.period", 125, 50 , INT32_MAX ) ),
66 HCI_EVT_RING_CAPACITY(
jau::environment::getInt32Property("
direct_bt.hci.ringsize", 64, 64 , 1024 ) ),
67 DEBUG_EVENT(
jau::environment::getBooleanProperty("
direct_bt.debug.hci.event", false) ),
68 DEBUG_SCAN_AD_EIR(
jau::environment::getBooleanProperty("
direct_bt.debug.hci.scan_ad_eir", false) ),
69 HCI_READ_PACKET_MAX_RETRY( HCI_EVT_RING_CAPACITY )
81 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
83 auto end = list.end();
84 for (
auto it = list.begin(); it != end; ++it) {
85 HCIConnectionRef conn = *it;
86 if ( conn->equals(addressAndType) ) {
88 WORDY_PRINT(
"HCIHandler::addTrackerConnection: address%s, handle %s: reuse entry %s - %s",
90 conn->toString().c_str(), toString().c_str());
93 if( 0 != conn->getHandle() && handle != conn->getHandle() ) {
94 WARN_PRINT(
"HCIHandler::addTrackerConnection: address%s, handle %s: reusing entry %s, overwriting non-zero handle - %s",
96 conn->toString().c_str(), toString().c_str());
98 conn->setHandle( handle );
103 HCIConnectionRef res(
new HCIConnection(addressAndType, handle) );
104 list.push_back( res );
109 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
112 HCIConnectionRef & e = list[i];
113 if( e->equals(addressAndType) ) {
120 HCIHandler::HCIConnectionRef HCIHandler::findTrackerConnection(
const uint16_t handle) noexcept {
121 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
124 HCIConnectionRef & e = connectionList[i];
125 if ( handle == e->getHandle() ) {
132 HCIHandler::HCIConnectionRef HCIHandler::removeTrackerConnection(
const HCIConnectionRef conn) noexcept {
133 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
134 auto end = connectionList.end();
135 for (
auto it = connectionList.begin(); it != end; ++it) {
136 HCIConnectionRef e = *it;
138 connectionList.erase(it);
144 int HCIHandler::countPendingTrackerConnections() noexcept {
145 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
147 for (
auto it = connectionList.
begin(); it != connectionList.
end(); it++) {
148 HCIConnectionRef e = *it;
149 if ( e->getHandle() == 0 ) {
156 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
157 auto end = list.end();
158 for (
auto it = list.begin(); it != end; ++it) {
159 HCIConnectionRef e = *it;
160 if ( e->getHandle() == handle ) {
169 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
170 connectionList.clear();
171 disconnectCmdList.clear();
200 std::unique_ptr<MgmtEvent> HCIHandler::translate(
HCIEvent& ev) noexcept {
208 const hci_ev_le_conn_complete * ev_cc = getMetaReplyStruct<hci_ev_le_conn_complete>(ev, mevt, &status);
209 if(
nullptr == ev_cc ) {
210 ERR_PRINT(
"HCIHandler::translate(reader): LE_CONN_COMPLETE: Null reply-struct: %s - %s",
211 ev.toString().c_str(), toString().c_str());
217 const HCIConnectionRef conn = addOrUpdateTrackerConnection(addressAndType, handle);
219 return std::make_unique<MgmtEvtDeviceConnected>(dev_id, addressAndType, handle);
221 removeTrackerConnection(conn);
222 return std::make_unique<MgmtEvtDeviceConnectFailed>(dev_id, addressAndType, status);
227 const hci_ev_le_enh_conn_complete * ev_cc = getMetaReplyStruct<hci_ev_le_enh_conn_complete>(ev, mevt, &status);
228 if(
nullptr == ev_cc ) {
229 ERR_PRINT(
"HCIHandler::translate(reader): LE_EXT_CONN_COMPLETE: Null reply-struct: %s - %s",
230 ev.toString().c_str(), toString().c_str());
236 const HCIConnectionRef conn = addOrUpdateTrackerConnection(addressAndType, handle);
238 return std::make_unique<MgmtEvtDeviceConnected>(dev_id, addressAndType, handle);
240 removeTrackerConnection(conn);
241 return std::make_unique<MgmtEvtDeviceConnectFailed>(dev_id, addressAndType, status);
246 const hci_ev_le_remote_feat_complete * ev_cc = getMetaReplyStruct<hci_ev_le_remote_feat_complete>(ev, mevt, &status);
247 if(
nullptr == ev_cc ) {
248 ERR_PRINT(
"HCIHandler::translate(reader): LE_REMOTE_FEAT_COMPLETE: Null reply-struct: %s - %s",
249 ev.toString().c_str(), toString().c_str());
254 const HCIConnectionRef conn = findTrackerConnection(handle);
255 if(
nullptr == conn ) {
256 WARN_PRINT(
"HCIHandler::translate(reader): LE_REMOTE_FEAT_COMPLETE: Not tracked conn_handle %s",
261 WARN_PRINT(
"HCIHandler::translate(reader): LE_REMOTE_FEAT_COMPLETE: Failed: Status %s, Handle %s: %s",
265 return std::make_unique<MgmtEvtHCILERemoteUserFeatures>(dev_id, conn->getAddressAndType(), features);
274 const hci_ev_conn_complete * ev_cc = getReplyStruct<hci_ev_conn_complete>(ev, evt, &status);
275 if(
nullptr == ev_cc ) {
276 ERR_PRINT(
"HCIHandler::translate(reader): CONN_COMPLETE: Null reply-struct: %s - %s",
277 ev.toString().c_str(), toString().c_str());
281 HCIConnectionRef conn = addOrUpdateTrackerConnection(addressAndType, ev_cc->handle);
283 return std::make_unique<MgmtEvtDeviceConnected>(dev_id, conn->getAddressAndType(), conn->getHandle());
286 removeTrackerConnection(conn);
292 const hci_ev_disconn_complete * ev_cc = getReplyStruct<hci_ev_disconn_complete>(ev, evt, &status);
293 if(
nullptr == ev_cc ) {
294 ERR_PRINT(
"HCIHandler::translate(reader): DISCONN_COMPLETE: Null reply-struct: %s - %s",
295 ev.toString().c_str(), toString().c_str());
298 removeDisconnectCmd(ev_cc->handle);
299 HCIConnectionRef conn = removeTrackerConnection(ev_cc->handle);
300 if(
nullptr == conn ) {
301 WORDY_PRINT(
"HCIHandler::translate(reader): DISCONN_COMPLETE: Not tracked handle %s: %s - %s",
302 jau::to_hexstring(ev_cc->handle).c_str(), ev.toString().c_str(), toString().c_str());
307 ERR_PRINT(
"HCIHandler::translate(reader): DISCONN_COMPLETE: !SUCCESS[%s, %s], %s: %s - %s",
309 conn->toString().c_str(), ev.toString().c_str(), toString().c_str());
312 return std::make_unique<MgmtEvtDeviceDisconnected>(dev_id, conn->getAddressAndType(), hciRootReason, conn->getHandle());
317 const hci_ev_encrypt_change * ev_cc = getReplyStruct<hci_ev_encrypt_change>(ev, evt, &status);
318 if(
nullptr == ev_cc ) {
319 ERR_PRINT(
"HCIHandler::translate(reader): ENCRYPT_CHANGE: Null reply-struct: %s - %s",
320 ev.toString().c_str(), toString().c_str());
324 const HCIConnectionRef conn = findTrackerConnection(handle);
325 if(
nullptr == conn ) {
326 WARN_PRINT(
"HCIHandler::translate(reader): ENCRYPT_CHANGE: Not tracked conn_handle %s",
330 return std::make_unique<MgmtEvtHCIEncryptionChanged>(dev_id, conn->getAddressAndType(), status, ev_cc->encrypt);
334 const hci_ev_key_refresh_complete * ev_cc = getReplyStruct<hci_ev_key_refresh_complete>(ev, evt, &status);
335 if(
nullptr == ev_cc ) {
336 ERR_PRINT(
"HCIHandler::translate(reader): ENCRYPT_KEY_REFRESH_COMPLETE: Null reply-struct: %s - %s",
337 ev.toString().c_str(), toString().c_str());
341 const HCIConnectionRef conn = findTrackerConnection(handle);
342 if(
nullptr == conn ) {
343 WARN_PRINT(
"HCIHandler::translate(reader): ENCRYPT_KEY_REFRESH_COMPLETE: Not tracked conn_handle %s",
347 return std::make_unique<MgmtEvtHCIEncryptionKeyRefreshComplete>(dev_id, conn->getAddressAndType(), status);
357 std::unique_ptr<const SMPPDUMsg> HCIHandler::getSMPPDUMsg(
const HCIACLData::l2cap_frame & l2cap,
const uint8_t * l2cap_data)
const noexcept {
358 if(
nullptr != l2cap_data && 0 < l2cap.len && l2cap.isSMP() ) {
364 void HCIHandler::hciReaderThreadImpl() noexcept {
366 const std::lock_guard<std::mutex> lock(mtx_hciReaderLifecycle);
367 hciReaderShallStop =
false;
368 hciReaderRunning =
true;
370 cv_hciReaderInit.notify_all();
373 DBG_PRINT(
"HCIHandler::hciReaderThreadCleanup: hciReaderRunning %d -> 0", hciReaderRunning.
load());
374 hciReaderRunning =
false;
377 while( !hciReaderShallStop ) {
382 hciReaderShallStop =
true;
393 if(
nullptr == acldata ) {
396 WARN_PRINT(
"HCIHandler-IO RECV Drop (non-acl-data) %s - %s",
401 const uint8_t* l2cap_data =
nullptr;
403 std::unique_ptr<const SMPPDUMsg> smpPDU = getSMPPDUMsg(l2cap, l2cap_data);
404 if(
nullptr != smpPDU ) {
405 HCIConnectionRef conn = findTrackerConnection(l2cap.
handle);
407 if(
nullptr != conn ) {
409 smpPDU->
toString().c_str(), conn->toString().c_str());
411 cb.
invoke(conn->getAddressAndType(), *smpPDU, l2cap);
414 WARN_PRINT(
"HCIHandler-IO RECV Drop (ACL.SMP): Not tracked conn_handle %s: %s, %s",
418 }
else if( !l2cap.
isGATT() ) {
424 WARN_PRINT(
"HCIHandler-IO RECV Drop (not event, nor acl-data) %s - %s",
431 if(
nullptr == event ) {
433 ERR_PRINT(
"HCIHandler-IO RECV Drop (non-event) %s - %s",
448 if( hciEventRing.isFull() ) {
449 const jau::nsize_t dropCount = hciEventRing.capacity()/4;
450 hciEventRing.drop(dropCount);
451 WARN_PRINT(
"HCIHandler-IO RECV Drop (%u oldest elements of %u capacity, ring full) - %s",
452 dropCount, hciEventRing.capacity(),
toString().c_str());
454 hciEventRing.putBlocking( std::move( event ) );
461 eircount, e.getEIR()->toString().c_str());
470 eircount, e.getEIR()->toString().c_str());
475 std::unique_ptr<MgmtEvent> mevent = translate(*event);
476 if(
nullptr != mevent ) {
483 }
else if( ETIMEDOUT != errno && !hciReaderShallStop ) {
488 const std::lock_guard<std::mutex> lock(mtx_hciReaderLifecycle);
489 WORDY_PRINT(
"HCIHandler::reader: Ended. Ring has %u entries flushed - %s", hciEventRing.getSize(),
toString().c_str());
490 hciEventRing.clear();
491 hciReaderRunning =
false;
492 cv_hciReaderInit.notify_all();
497 MgmtEventCallbackList & mgmtEventCallbackList = mgmtEventCallbackLists[
static_cast<uint16_t
>(
event.getOpcode())];
503 }
catch (std::exception &e) {
504 ERR_PRINT(
"HCIHandler::sendMgmtEvent-CBs %d/%zd: MgmtEventCallback %s : Caught exception %s - %s",
505 invokeCount+1, mgmtEventCallbackList.
size(),
506 cb.
toString().c_str(), e.what(), toString().c_str());
511 COND_PRINT(env.DEBUG_EVENT,
"HCIHandler::sendMgmtEvent: Event %s -> %d/%zd callbacks", event.toString().c_str(), invokeCount, mgmtEventCallbackList.
size());
515 bool HCIHandler::sendCommand(
HCICommand &req) noexcept {
516 COND_PRINT(env.DEBUG_EVENT,
"HCIHandler-IO SENT %s", req.toString().c_str());
520 ERR_PRINT(
"HCIHandler::sendCommand: HCIComm write error, req %s - %s", req.toString().c_str(), toString().c_str());
526 std::unique_ptr<HCIEvent> HCIHandler::getNextReply(
HCICommand &req, int32_t & retryCount,
const int32_t replyTimeoutMS) noexcept
529 while( retryCount < env.HCI_READ_PACKET_MAX_RETRY ) {
530 std::unique_ptr<HCIEvent> ev = hciEventRing.getBlocking(replyTimeoutMS);
531 if(
nullptr == ev ) {
533 ERR_PRINT(
"HCIHandler::getNextReply: nullptr result (timeout %d ms -> abort): req %s - %s",
534 replyTimeoutMS, req.toString().c_str(), toString().c_str());
540 COND_PRINT(env.DEBUG_EVENT,
"HCIHandler-IO RECV getNextReply: res mismatch (drop, retry %d): res %s; req %s",
541 retryCount, ev->
toString().c_str(), req.toString().c_str());
543 COND_PRINT(env.DEBUG_EVENT,
"HCIHandler-IO RECV getNextReply: res %s; req %s", ev->
toString().c_str(), req.toString().c_str());
551 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
555 int32_t retryCount = 0;
556 std::unique_ptr<HCIEvent> ev =
nullptr;
558 while( retryCount < env.HCI_READ_PACKET_MAX_RETRY ) {
559 ev = getNextReply(req, retryCount, env.HCI_COMMAND_COMPLETE_REPLY_TIMEOUT);
560 if(
nullptr == ev ) {
571 WARN_PRINT(
"HCIHandler::getNextCmdCompleteReply: CMD_STATUS 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
573 ev_cs->
toString().c_str(), req.toString().c_str(), toString().c_str());
576 DBG_PRINT(
"HCIHandler::getNextCmdCompleteReply: CMD_STATUS 0x%2.2X (%s, retryCount %d), errno %d %s: res %s, req %s - %s",
577 number(status),
to_string(status).c_str(), retryCount, errno, strerror(errno),
578 ev_cs->
toString().c_str(), req.toString().c_str(), toString().c_str());
584 DBG_PRINT(
"HCIHandler::getNextCmdCompleteReply: !(CMD_COMPLETE, CMD_STATUS) (drop, retry %d): res %s; req %s - %s",
585 retryCount, ev->
toString().c_str(), req.toString().c_str(), toString().c_str());
595 rbuffer(HCI_MAX_MTU),
596 comm(dev_id_, HCI_CHANNEL_RAW),
597 hciEventRing(
nullptr, env.HCI_EVT_RING_CAPACITY), hciReaderShallStop(
false),
598 hciReaderThreadId(0), hciReaderRunning(
false),
599 allowClose( comm.isOpen() ),
605 ERR_PRINT(
"HCIHandler::ctor: Could not open hci control channel %s", toString().c_str());
610 std::unique_lock<std::mutex> lock(mtx_hciReaderLifecycle);
612 std::thread hciReaderThread(&HCIHandler::hciReaderThreadImpl,
this);
613 hciReaderThreadId = hciReaderThread.native_handle();
616 hciReaderThread.detach();
618 while(
false == hciReaderRunning ) {
619 cv_hciReaderInit.wait(lock);
628 if (setsockopt(comm.getSocketDescriptor(), SOL_SOCKET, SO_TIMESTAMP, &opt,
sizeof(opt)) < 0) {
629 ERR_PRINT(
"HCIHandler::ctor: setsockopt SO_TIMESTAMP %s", toString().c_str());
633 if (setsockopt(comm.getSocketDescriptor(), SOL_SOCKET, SO_PASSCRED, &opt,
sizeof(opt)) < 0) {
634 ERR_PRINT(
"HCIHandler::ctor: setsockopt SO_PASSCRED %s", toString().c_str());
640 #define FILTER_ALL_EVENTS 0
650 if (getsockopt(comm.getSocketDescriptor(), SOL_HCI, HCI_FILTER, &of, &olen) < 0) {
651 ERR_PRINT(
"HCIHandler::ctor: getsockopt %s", toString().c_str());
661 #if FILTER_ALL_EVENTS
680 if (setsockopt(comm.getSocketDescriptor(), SOL_HCI, HCI_FILTER, &filter_mask,
sizeof(filter_mask)) < 0) {
681 ERR_PRINT(
"HCIHandler::ctor: setsockopt HCI_FILTER %s", toString().c_str());
688 #if FILTER_ALL_EVENTS
689 filter_all_metaevs(mask);
698 filter_put_metaevs(mask);
703 #if FILTER_ALL_EVENTS
704 filter_all_opcbit(mask);
723 filter_put_opcbit(mask);
726 sup_commands_set =
false;
730 WORDY_PRINT(
"HCIHandler.ctor: End OK - %s", toString().c_str());
736 WORDY_PRINT(
"HCIHandler.ctor: End failure - %s", toString().c_str());
740 void HCIHandler::zeroSupCommands() noexcept {
741 bzero(sup_commands,
sizeof(sup_commands));
742 sup_commands_set =
false;
744 bool HCIHandler::initSupCommands() noexcept {
751 const hci_rp_read_local_commands * ev_cmds;
753 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_cmds, &status);
755 DBG_PRINT(
"HCIHandler::ctor: READ_LOCAL_COMMANDS: 0x%x (%s) - %s",
760 memcpy(sup_commands, ev_cmds->commands,
sizeof(sup_commands));
761 sup_commands_set =
true;
778 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
789 std::unique_lock<std::mutex> lockReader(mtx_hciReaderLifecycle);
790 const pthread_t tid_self = pthread_self();
791 const pthread_t tid_reader = hciReaderThreadId;
792 hciReaderThreadId = 0;
793 const bool is_reader = tid_reader == tid_self;
794 DBG_PRINT(
"HCIHandler::close: hciReader[running %d, shallStop %d, isReader %d, tid %p) - %s",
795 hciReaderRunning.
load(), hciReaderShallStop.
load(), is_reader, (
void*)tid_reader,
toString().c_str());
796 if( hciReaderRunning ) {
797 hciReaderShallStop =
true;
798 if( !is_reader && 0 != tid_reader ) {
800 if( 0 != ( kerr = pthread_kill(tid_reader, SIGALRM) ) ) {
801 ERR_PRINT(
"HCIHandler::close: pthread_kill %p FAILED: %d - %s", (
void*)tid_reader, kerr,
toString().c_str());
805 while(
true == hciReaderRunning ) {
806 cv_hciReaderInit.wait(lockReader);
826 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
830 if (errno != EALREADY) {
831 ERR_PRINT(
"HCIHandler::startAdapter(dev_id %d): FAILED: %d - %s", dev_id, res,
toString().c_str());
838 #warning add implementation
848 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
853 ERR_PRINT(
"HCIHandler::stopAdapter(dev_id %d): FAILED: %d - %s", dev_id, res,
toString().c_str());
859 #warning add implementation
873 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
879 #warning add implementation
889 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
894 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_status, &status);
895 if(
nullptr == ev ) {
906 ERR_PRINT(
"HCIHandler::getLocalVersion: Not connected %s", toString().c_str());
910 const hci_rp_read_local_version * ev_lv;
912 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_lv, &status);
914 ERR_PRINT(
"HCIHandler::getLocalVersion: READ_LOCAL_VERSION: 0x%x (%s) - %s",
916 bzero(&version,
sizeof(version));
918 version.hci_ver = ev_lv->hci_ver;
921 version.lmp_ver = ev_lv->lmp_ver;
929 ERR_PRINT(
"HCIHandler::le_read_local_features: Not connected %s", toString().c_str());
934 const hci_rp_le_read_local_features * ev_lf;
936 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_lf, &status);
938 ERR_PRINT(
"HCIHandler::le_read_local_features: LE_READ_LOCAL_FEATURES: 0x%x (%s) - %s",
951 ERR_PRINT(
"HCIHandler::le_set_scan_param: Not connected %s", toString().c_str());
955 WARN_PRINT(
"HCIHandler::le_set_scan_param: Not allowed: LE Scan Enabled: %s - tried scan [interval %.3f ms, window %.3f ms]",
959 DBG_PRINT(
"HCI Scan Param: scan [active %d, interval %.3f ms, window %.3f ms, filter %d] - %s",
965 if( use_ext_scan() ) {
966 struct le_set_ext_scan_params {
967 __u8 own_address_type;
970 hci_cp_le_scan_phy_params p1;
974 le_set_ext_scan_params * cp = req0.
getWStruct();
975 cp->own_address_type =
static_cast<uint8_t
>(own_mac_type);
985 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_status, &status);
988 hci_cp_le_set_scan_param * cp = req0.
getWStruct();
992 cp->own_address_type =
static_cast<uint8_t
>(own_mac_type);
996 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_status, &status);
1003 ERR_PRINT(
"HCIHandler::le_enable_scan: Not connected %s", toString().c_str());
1006 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
1009 DBG_PRINT(
"HCI Enable Scan: enable %s -> %s, filter_dup %d - %s",
1010 to_string(currentScanType).c_str(),
to_string(nextScanType).c_str(), filter_dup, toString().c_str());
1013 if( currentScanType != nextScanType ) {
1014 if( use_ext_scan() ) {
1016 hci_cp_le_set_ext_scan_enable * cp = req0.
getWStruct();
1017 cp->enable = enable ? LE_SCAN_ENABLE : LE_SCAN_DISABLE;
1018 cp->filter_dup = filter_dup ? LE_SCAN_FILTER_DUP_ENABLE : LE_SCAN_FILTER_DUP_DISABLE;
1022 std::unique_ptr<HCIEvent> evComplete = processCommandComplete(req0, &ev_status, &status);
1025 hci_cp_le_set_scan_enable * cp = req0.
getWStruct();
1026 cp->enable = enable ? LE_SCAN_ENABLE : LE_SCAN_DISABLE;
1027 cp->filter_dup = filter_dup ? LE_SCAN_FILTER_DUP_ENABLE : LE_SCAN_FILTER_DUP_DISABLE;
1029 std::unique_ptr<HCIEvent> evComplete = processCommandComplete(req0, &ev_status, &status);
1033 WARN_PRINT(
"HCI Enable Scan: current %s == next %s, OK, skip command - %s",
1034 to_string(currentScanType).c_str(),
to_string(nextScanType).c_str(), toString().c_str());
1038 currentScanType = nextScanType;
1051 ERR_PRINT(
"HCIHandler::le_start_scan: Not connected %s", toString().c_str());
1054 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
1057 WARN_PRINT(
"HCIHandler::le_start_scan: Not allowed: LE Scan Enabled: %s", toString().c_str());
1062 WARN_PRINT(
"HCIHandler::le_start_scan: le_set_scan_param failed: %s - %s",
1063 to_string(status).c_str(), toString().c_str());
1065 status = le_enable_scan(
true , filter_dup);
1067 WARN_PRINT(
"HCIHandler::le_start_scan: le_enable_scan failed: %s - %s",
1068 to_string(status).c_str(), toString().c_str());
1078 const uint16_t conn_interval_min,
const uint16_t conn_interval_max,
1079 const uint16_t conn_latency,
const uint16_t supervision_timeout) noexcept {
1085 const std::lock_guard<std::mutex> lock(mtx_connect_cmd);
1088 ERR_PRINT(
"HCIHandler::le_create_conn: Not connected %s", toString().c_str());
1092 const uint16_t min_ce_length = 0x0000;
1093 const uint16_t max_ce_length = 0x0000;
1094 const uint8_t initiator_filter = 0x00;
1096 DBG_PRINT(
"HCI Conn Param: scan [interval %.3f ms, window %.3f ms]", 0.625f *
1098 DBG_PRINT(
"HCI Conn Param: conn [interval [%.3f ms - %.3f ms], latency %d, sup_timeout %d ms] - %s",
1099 1.25f * (
float)conn_interval_min, 1.25f * (
float)conn_interval_max,
1100 conn_latency, supervision_timeout*10, toString().c_str());
1102 int pendingConnections = countPendingTrackerConnections();
1103 if( 0 < pendingConnections ) {
1104 DBG_PRINT(
"HCIHandler::le_create_conn: %d connections pending - %s", pendingConnections, toString().c_str());
1106 while( env.HCI_COMMAND_COMPLETE_REPLY_TIMEOUT > td && 0 < pendingConnections ) {
1107 std::this_thread::sleep_for(std::chrono::milliseconds(env.HCI_COMMAND_POLL_PERIOD));
1108 td += env.HCI_COMMAND_POLL_PERIOD;
1109 pendingConnections = countPendingTrackerConnections();
1111 if( 0 < pendingConnections ) {
1112 WARN_PRINT(
"HCIHandler::le_create_conn: %d connections pending after %d ms - %s", pendingConnections, td, toString().c_str());
1114 DBG_PRINT(
"HCIHandler::le_create_conn: pending connections resolved after %d ms - %s", td, toString().c_str());
1118 HCIConnectionRef disconn = findDisconnectCmd(addressAndType);
1119 if(
nullptr != disconn ) {
1120 DBG_PRINT(
"HCIHandler::le_create_conn: disconnect pending %s - %s",
1121 disconn->toString().c_str(), toString().c_str());
1123 while( env.HCI_COMMAND_COMPLETE_REPLY_TIMEOUT > td &&
nullptr != disconn ) {
1124 std::this_thread::sleep_for(std::chrono::milliseconds(env.HCI_COMMAND_POLL_PERIOD));
1125 td += env.HCI_COMMAND_POLL_PERIOD;
1126 disconn = findDisconnectCmd(addressAndType);
1128 if(
nullptr != disconn ) {
1129 WARN_PRINT(
"HCIHandler::le_create_conn: disconnect persisting after %d ms: %s - %s",
1130 td, disconn->toString().c_str(), toString().c_str());
1132 DBG_PRINT(
"HCIHandler::le_create_conn: disconnect resolved after %d ms - %s", td, toString().c_str());
1135 HCIConnectionRef conn = addOrUpdateTrackerConnection(addressAndType, 0);
1138 if( use_ext_conn() ) {
1139 struct le_ext_create_conn {
1141 __u8 own_address_type;
1142 __u8 peer_addr_type;
1145 hci_cp_le_ext_conn_param p1;
1151 cp->filter_policy = initiator_filter;
1152 cp->own_address_type =
static_cast<uint8_t
>(own_mac_type);
1153 cp->peer_addr_type =
static_cast<uint8_t
>(peer_mac_type);
1154 cp->peer_addr = peer_bdaddr;
1162 cp->p1.supervision_timeout =
jau::cpu_to_le(supervision_timeout);
1167 std::unique_ptr<HCIEvent> ev = processCommandStatus(req0, &status);
1173 hci_cp_le_create_conn * cp = req0.
getWStruct();
1176 cp->filter_policy = initiator_filter;
1177 cp->peer_addr_type =
static_cast<uint8_t
>(peer_mac_type);
1178 cp->peer_addr = peer_bdaddr;
1179 cp->own_address_type =
static_cast<uint8_t
>(own_mac_type);
1187 std::unique_ptr<HCIEvent> ev = processCommandStatus(req0, &status);
1192 removeTrackerConnection(conn);
1195 const std::string s0 =
nullptr != disconn ? disconn->toString() :
"null";
1196 WARN_PRINT(
"HCIHandler::le_create_conn: %s: disconnect pending: %s - %s",
1197 to_string(status).c_str(), s0.c_str(), toString().c_str());
1204 const uint16_t pkt_type,
1205 const uint16_t clock_offset,
const uint8_t role_switch) noexcept {
1211 const std::lock_guard<std::mutex> lock(mtx_connect_cmd);
1214 ERR_PRINT(
"HCIHandler::create_conn: Not connected %s", toString().c_str());
1220 cp->bdaddr = bdaddr;
1221 cp->pkt_type =
jau::cpu_to_le((uint16_t)(pkt_type & (uint16_t)ACL_PTYPE_MASK));
1222 cp->pscan_rep_mode = 0x02;
1223 cp->pscan_mode = 0x00;
1225 cp->role_switch = role_switch;
1227 int pendingConnections = countPendingTrackerConnections();
1228 if( 0 < pendingConnections ) {
1229 DBG_PRINT(
"HCIHandler::create_conn: %d connections pending - %s", pendingConnections, toString().c_str());
1231 while( env.HCI_COMMAND_COMPLETE_REPLY_TIMEOUT > td && 0 < pendingConnections ) {
1232 std::this_thread::sleep_for(std::chrono::milliseconds(env.HCI_COMMAND_POLL_PERIOD));
1233 td += env.HCI_COMMAND_POLL_PERIOD;
1234 pendingConnections = countPendingTrackerConnections();
1236 if( 0 < pendingConnections ) {
1237 WARN_PRINT(
"HCIHandler::create_conn: %d connections pending after %d ms - %s", pendingConnections, td, toString().c_str());
1239 DBG_PRINT(
"HCIHandler::create_conn: pending connections resolved after %d ms - %s", td, toString().c_str());
1243 HCIConnectionRef disconn = findDisconnectCmd(addressAndType);
1244 if(
nullptr != disconn ) {
1245 DBG_PRINT(
"HCIHandler::create_conn: disconnect pending %s - %s",
1246 disconn->toString().c_str(), toString().c_str());
1248 while( env.HCI_COMMAND_COMPLETE_REPLY_TIMEOUT > td &&
nullptr != disconn ) {
1249 std::this_thread::sleep_for(std::chrono::milliseconds(env.HCI_COMMAND_POLL_PERIOD));
1250 td += env.HCI_COMMAND_POLL_PERIOD;
1251 disconn = findDisconnectCmd(addressAndType);
1253 if(
nullptr != disconn ) {
1254 WARN_PRINT(
"HCIHandler::create_conn: disconnect persisting after %d ms: %s - %s",
1255 td, disconn->toString().c_str(), toString().c_str());
1257 DBG_PRINT(
"HCIHandler::create_conn: disconnect resolved after %d ms - %s", td, toString().c_str());
1260 HCIConnectionRef conn = addOrUpdateTrackerConnection(addressAndType, 0);
1262 std::unique_ptr<HCIEvent> ev = processCommandStatus(req0, &status);
1264 removeTrackerConnection(conn);
1267 const std::string s0 =
nullptr != disconn ? disconn->toString() :
"null";
1268 WARN_PRINT(
"HCIHandler::create_conn: %s: disconnect pending: %s - %s",
1269 to_string(status).c_str(), s0.c_str(), toString().c_str());
1279 ERR_PRINT(
"HCIHandler::create_conn: Not connected %s", toString().c_str());
1282 if( 0 == conn_handle ) {
1283 ERR_PRINT(
"HCIHandler::disconnect: Null conn_handle given address%s (drop) - %s",
1284 peerAddressAndType.toString().c_str(), toString().c_str());
1288 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
1289 HCIConnectionRef conn = findTrackerConnection(conn_handle);
1290 if(
nullptr == conn ) {
1292 conn = addOrUpdateTrackerConnection(peerAddressAndType, conn_handle);
1293 WORDY_PRINT(
"HCIHandler::disconnect: Not tracked address%s, added %s - %s",
1294 peerAddressAndType.toString().c_str(),
1295 conn->toString().c_str(), toString().c_str());
1296 }
else if( !conn->equals(peerAddressAndType) ) {
1297 ERR_PRINT(
"HCIHandler::disconnect: Mismatch given address%s and tracked %s (drop) - %s",
1298 peerAddressAndType.toString().c_str(),
1299 conn->toString().c_str(), toString().c_str());
1302 DBG_PRINT(
"HCIHandler::disconnect: address%s, handle %s, %s - %s",
1303 peerAddressAndType.toString().c_str(),
1305 conn->toString().c_str(), toString().c_str());
1317 cp->reason =
number(reason);
1319 std::unique_ptr<HCIEvent> ev = processCommandStatus(req0, &status);
1322 addOrUpdateDisconnectCmd(peerAddressAndType, conn_handle);
1333 ERR_PRINT(
"HCIHandler::le_read_phy: Not connected %s", toString().c_str());
1336 if( 0 == conn_handle ) {
1337 ERR_PRINT(
"HCIHandler::le_read_phy: Null conn_handle given address%s (drop) - %s",
1338 peerAddressAndType.toString().c_str(), toString().c_str());
1342 const std::lock_guard<std::recursive_mutex> lock(mtx_connectionList);
1343 HCIConnectionRef conn = findTrackerConnection(conn_handle);
1344 if(
nullptr == conn ) {
1346 ERR_PRINT(
"HCIHandler::le_read_phy: Not tracked handle %s (address%s) (drop) - %s",
1348 peerAddressAndType.toString().c_str(), toString().c_str());
1350 }
else if( !conn->equals(peerAddressAndType) ) {
1351 ERR_PRINT(
"HCIHandler::le_read_phy: Mismatch given address%s and tracked %s (drop) - %s",
1352 peerAddressAndType.toString().c_str(),
1353 conn->toString().c_str(), toString().c_str());
1356 DBG_PRINT(
"HCIHandler::le_read_phy: address%s, handle %s, %s - %s",
1357 peerAddressAndType.toString().c_str(),
1359 conn->toString().c_str(), toString().c_str());
1361 struct hci_cp_le_read_phy {
1364 struct hci_rp_le_read_phy {
1376 const hci_rp_le_read_phy * ev_phy;
1377 std::unique_ptr<HCIEvent> ev = processCommandComplete(req0, &ev_phy, &status);
1380 ERR_PRINT(
"HCIHandler::le_read_phy: LE_READ_PHY: 0x%x (%s) - %s",
1383 const uint16_t conn_handle_rcvd =
jau::le_to_cpu(ev_phy->handle);
1384 if( conn_handle != conn_handle_rcvd ) {
1385 ERR_PRINT(
"HCIHandler::le_read_phy: Mismatch given address%s conn_handle (req) %s != %s (res) (drop) - %s",
1386 peerAddressAndType.toString().c_str(),
1390 switch( ev_phy->tx_phys ) {
1395 switch( ev_phy->rx_phys ) {
1406 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
1410 int32_t retryCount = 0;
1411 std::unique_ptr<HCIEvent> ev =
nullptr;
1413 if( !sendCommand(req) ) {
1417 while( retryCount < env.HCI_READ_PACKET_MAX_RETRY ) {
1418 ev = getNextReply(req, retryCount, env.HCI_COMMAND_STATUS_REPLY_TIMEOUT);
1419 if(
nullptr == ev ) {
1425 DBG_PRINT(
"HCIHandler::processCommandStatus %s -> Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
1428 ev_cs->
toString().c_str(), req.toString().c_str(), toString().c_str());
1432 DBG_PRINT(
"HCIHandler::processCommandStatus: !CMD_STATUS (drop, retry %d): res %s; req %s - %s",
1433 retryCount, ev->
toString().c_str(), req.toString().c_str(), toString().c_str());
1437 if(
nullptr == ev ) {
1439 WARN_PRINT(
"HCIHandler::processCommandStatus %s -> Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
1442 req.toString().c_str(), toString().c_str());
1449 template<
typename hci_cmd_event_struct>
1450 std::unique_ptr<HCIEvent> HCIHandler::processCommandComplete(
HCICommand &req,
1451 const hci_cmd_event_struct **res,
HCIStatusCode *status) noexcept
1453 const std::lock_guard<std::recursive_mutex> lock(mtx_sendReply);
1458 if( !sendCommand(req) ) {
1459 WARN_PRINT(
"HCIHandler::processCommandComplete Send failed: Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
1461 req.toString().c_str(), toString().c_str());
1465 return receiveCommandComplete(req, res, status);
1468 template<
typename hci_cmd_event_struct>
1469 std::unique_ptr<HCIEvent> HCIHandler::receiveCommandComplete(
HCICommand &req,
1470 const hci_cmd_event_struct **res,
HCIStatusCode *status) noexcept
1477 std::unique_ptr<HCIEvent> ev = getNextCmdCompleteReply(req, &ev_cc);
1478 if(
nullptr == ev ) {
1480 WARN_PRINT(
"HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res nullptr, req %s - %s",
1483 req.toString().c_str(), toString().c_str());
1485 }
else if(
nullptr == ev_cc ) {
1486 WARN_PRINT(
"HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
1489 ev->
toString().c_str(), req.toString().c_str(), toString().c_str());
1493 if( returnParamSize <
sizeof(hci_cmd_event_struct) ) {
1494 WARN_PRINT(
"HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s), errno %d %s: res %s, req %s - %s",
1497 ev_cc->
toString().c_str(), req.toString().c_str(), toString().c_str());
1502 DBG_PRINT(
"HCIHandler::processCommandComplete %s -> %s: Status 0x%2.2X (%s): res %s, req %s - %s",
1505 ev_cc->
toString().c_str(), req.toString().c_str(), toString().c_str());
1509 template<
typename hci_cmd_event_struct>
1512 const hci_cmd_event_struct* res =
nullptr;
1516 HCITypeCmdCompleteEvtWrap ev_cc( event );
1517 if( ev_cc.isTypeAndSizeValid(evc) ) {
1518 *status = ev_cc.getStatus();
1519 res = ev_cc.getStruct();
1521 WARN_PRINT(
"HCIHandler::getReplyStruct: %s: Type or size mismatch: Status 0x%2.2X (%s), errno %d %s: res %s - %s",
1524 ev_cc.
toString().c_str(), toString().c_str());
1529 template<
typename hci_cmd_event_struct>
1532 const hci_cmd_event_struct* res =
nullptr;
1536 const HCITypeCmdCompleteMetaEvtWrap ev_cc( *
static_cast<HCIMetaEvent*
>( &event ) );
1537 if( ev_cc.isTypeAndSizeValid(mec) ) {
1538 *status = ev_cc.getStatus();
1539 res = ev_cc.getStruct();
1541 WARN_PRINT(
"HCIHandler::getMetaReplyStruct: %s: Type or size mismatch: Status 0x%2.2X (%s), errno %d %s: res %s - %s",
1544 ev_cc.
toString().c_str(), toString().c_str());
1559 if( !isValidMgmtEventCallbackListsIndex(opc) ) {
1568 if( !isValidMgmtEventCallbackListsIndex(opc) ) {
1576 if( !isValidMgmtEventCallbackListsIndex(opc) ) {
1580 mgmtEventCallbackLists[
static_cast<uint16_t
>(opc)].
clear();
1583 for(
size_t i=0; i<mgmtEventCallbackLists.size(); i++) {
1584 mgmtEventCallbackLists[i].clear();
1586 hciSMPMsgCallbackList.
clear();