42#include "L2CAPIoctl.hpp"
48 #include <sys/socket.h>
53 #if defined(__FreeBSD__)
55 #define SOL_BLUETOOTH 274
61L2CAPEnv::L2CAPEnv() noexcept
62: exploding(
jau::environment::getExplodingProperties("
direct_bt.l2cap") ),
63 L2CAP_READER_POLL_TIMEOUT(
jau::environment::getInt32Property("
direct_bt.l2cap.reader.timeout", 10000, 1500 , INT32_MAX ) ),
64 L2CAP_RESTART_COUNT_ON_ERROR(
jau::environment::getInt32Property("
direct_bt.l2cap.restart.count", 5, INT32_MIN , INT32_MAX ) ),
65 DEBUG_DATA(
jau::environment::getBooleanProperty("
direct_bt.debug.l2cap.data", false) )
87 ", errno "+
std::to_string(errno)+
" ("+std::string(strerror(errno))+
")]";
94 ", errno "+
std::to_string(errno)+
" ("+std::string(strerror(errno))+
")]";
101#if defined(__linux__)
103#elif defined(__FreeBSD__)
105 ABORT(
"add implementation for FreeBSD");
107 #warning add implementation
108 ABORT(
"add implementation");
112 fd = ::socket(AF_BLUETOOTH,
113 SOCK_SEQPACKET, BTPROTO_L2CAP);
116 ERR_PRINT(
"L2CAPComm::l2cap_open_dev: socket failed");
122 bzero((
void *)&a,
sizeof(a));
123 a.l2_family=AF_BLUETOOTH;
127 a.l2_bdaddr_type =
::number(adapterAddressAndType.type);
128 if ( ::bind(fd, (
struct sockaddr *) &a,
sizeof(a)) < 0 ) {
129 ERR_PRINT(
"L2CAPComm::l2cap_open_dev: bind failed");
150 localAddressAndType(std::move(localAddressAndType_)),
151 psm(psm_), cid(cid_),
153 is_open_(
false), interrupted_intern(
false), is_interrupted_extern()
158 DBG_PRINT(
"L2CAP::setBTSecurityLevel: sec_level %s not set: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
160 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
162 getStateString().c_str());
167 struct bt_security bt_sec;
170 BTSecurityLevel old_sec_level = getBTSecurityLevelImpl(remoteAddressAndType);
171 if( old_sec_level != sec_level ) {
172 bzero(&bt_sec,
sizeof(bt_sec));
174 result = ::setsockopt(socket_, SOL_BLUETOOTH, BT_SECURITY, &bt_sec,
sizeof(bt_sec));
176 DBG_PRINT(
"L2CAP::setBTSecurityLevel: Success: sec_level %s -> %s: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
178 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
180 getStateString().c_str());
183 ERR_PRINT(
"L2CAP::setBTSecurityLevel: Failed: sec_level %s -> %s: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
185 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
187 getStateString().c_str());
191 DBG_PRINT(
"L2CAP::setBTSecurityLevel: Unchanged: sec_level %s -> %s: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
193 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
195 getStateString().c_str());
199 DBG_PRINT(
"L2CAP::setBTSecurityLevel: Not implemented: sec_level %s: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
201 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
203 getStateString().c_str());
211 struct bt_security bt_sec;
212 socklen_t optlen =
sizeof(bt_sec);
215 bzero(&bt_sec,
sizeof(bt_sec));
216 result = ::getsockopt(socket_, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, &optlen);
218 if( optlen ==
sizeof(bt_sec) ) {
220 DBG_PRINT(
"L2CAP::getBTSecurityLevel: Success: sec_level %s: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
222 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
224 getStateString().c_str());
226 ERR_PRINT(
"L2CAP::getBTSecurityLevel: Failed: sec_level %s, size %zd returned != %zd bt_sec: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
227 to_string(sec_level).c_str(), optlen,
sizeof(bt_sec),
228 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
230 getStateString().c_str());
233 ERR_PRINT(
"L2CAP::getBTSecurityLevel: Failed: sec_level %s, result %d: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
235 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
237 getStateString().c_str());
240 DBG_PRINT(
"L2CAP::getBTSecurityLevel: Not implemented: sec_level %s: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
242 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
244 getStateString().c_str());
254:
L2CAPComm(adev_id_, std::move(adapterAddressAndType_), psm_, cid_),
256 has_ioerror(
false), tid_connect(0), tid_read(0)
261:
L2CAPComm(adev_id_, std::move(adapterAddressAndType_), psm_, cid_),
262 remoteAddressAndType(std::move(remoteAddressAndType_)),
263 has_ioerror(
false), tid_connect(0), tid_read(0)
265 socket_ = client_socket_;
266 is_open_ = 0 <= client_socket_;
271 bool expOpen =
false;
272 if( !is_open_.compare_exchange_strong(expOpen,
true) ) {
273 DBG_PRINT(
"L2CAPClient::open(%s, %s): Already open: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
274 device.getAddressAndType().toString().c_str(),
to_string(sec_level).c_str(),
275 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
277 getStateString().c_str());
280 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
299 remoteAddressAndType = device.getAddressAndType();
304 int to_retry_count=0;
306 DBG_PRINT(
"L2CAPClient::open: Start Connect: dev_id %u, dd %d, %s, psm %s, cid %s, sec_level %s; %s",
307 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
309 getStateString().c_str());
311 socket_ = l2cap_open_dev(localAddressAndType, psm, cid);
319 if( !setBTSecurityLevelImpl(sec_level, remoteAddressAndType) ) {
325 tid_connect = ::pthread_self();
328 bzero((
void *)&req,
sizeof(req));
329 req.l2_family = AF_BLUETOOTH;
333 req.l2_bdaddr_type =
::number(remoteAddressAndType.type);
335 while( !interrupted() ) {
337 res = ::connect(socket_, (
struct sockaddr*)&req,
sizeof(req));
339 DBG_PRINT(
"L2CAPClient::open: Connect Result: %d, errno 0x%X %s, dev_id %u, %s, psm %s, cid %s",
340 res, errno, strerror(errno),
341 adev_id, remoteAddressAndType.toString().c_str(),
348 }
else if( ETIMEDOUT == errno ) {
350 if( to_retry_count <
number(Defaults::L2CAP_CONNECT_MAX_RETRY) ) {
351 WORDY_PRINT(
"L2CAPClient::open: Connect timeout, retry %d: dev_id %u, dd %d, %s, psm %s, cid %s, sec_level %s; %s",
353 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
355 getStateString().c_str());
358 ERR_PRINT(
"L2CAPClient::open: Connect timeout, retried %d: dev_id %u, dd %d, %s, psm %s, cid %s, sec_level %s; %s",
360 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
362 getStateString().c_str());
366 }
else if( !interrupted() ) {
368 ERR_PRINT(
"L2CAPClient::open: Connect failed: dev_id %u, dd %d, %s, psm %s, cid %s, sec_level %s; %s",
369 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
371 getStateString().c_str());
382 if( !setBTSecurityLevelImpl(sec_level, remoteAddressAndType) ) {
391 const int err = errno;
397bool L2CAPClient::close_impl() noexcept {
400 DBG_PRINT(
"L2CAPClient::close: Not connected: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
408 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
410 DBG_PRINT(
"L2CAPClient::close: Start: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
421 ::pthread_t tid_self = ::pthread_self();
422 ::pthread_t _tid_connect = tid_connect;
423 ::pthread_t _tid_read = tid_read;
428 if( 0 != _tid_read && tid_self != _tid_read ) {
430 if( 0 != ( kerr = ::pthread_kill(_tid_read, SIGALRM) ) ) {
431 ERR_PRINT(
"L2CAPClient::close: pthread_kill read %p FAILED: %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
432 (
void*)_tid_read, kerr,
439 if( 0 != _tid_connect && _tid_read != _tid_connect && tid_self != _tid_connect ) {
441 if( 0 != ( kerr = ::pthread_kill(_tid_connect, SIGALRM) ) ) {
442 ERR_PRINT(
"L2CAPClient::close: Start: pthread_kill connect %p FAILED: %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
443 (
void*)_tid_connect, kerr,
455 DBG_PRINT(
"L2CAPClient::close: End: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
464 DBG_PRINT(
"L2CAPClient::setBTSecurityLevel(%s): Not connected: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
466 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
468 getStateString().c_str());
471 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
473 if( setBTSecurityLevelImpl(sec_level, remoteAddressAndType) ) {
486 DBG_PRINT(
"L2CAPClient::getBTSecurityLevel: Not connected: dev_id %u, dd %d, %s, psm %s, cid %s; %s",
492 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
497#define RWEXITCODE_ENUM(X) \
498 X(RWExitCode, SUCCESS) \
499 X(RWExitCode, NOT_OPEN) \
500 X(RWExitCode, INTERRUPTED) \
501 X(RWExitCode, INVALID_SOCKET_DD) \
502 X(RWExitCode, POLL_ERROR) \
503 X(RWExitCode, POLL_TIMEOUT) \
504 X(RWExitCode, READ_ERROR) \
505 X(RWExitCode, READ_TIMEOUT) \
506 X(RWExitCode, WRITE_ERROR)
508#define CASE2_TO_STRING(U,V) case U::V: return #V;
518 return "Unknown ExitCode";
522 const int32_t timeoutMS = env.L2CAP_READER_POLL_TIMEOUT;
527 err_res =
number(RWExitCode::NOT_OPEN);
530 if( interrupted() ) {
531 err_res =
number(RWExitCode::INTERRUPTED);
535 err_res =
number(RWExitCode::INVALID_SOCKET_DD);
538 if( 0 == capacity ) {
542 tid_read = ::pthread_self();
548 p.fd = socket_; p.events = POLLIN;
549 while ( is_open_ && !interrupted() && ( n = ::poll( &p, 1, timeoutMS ) ) < 0 ) {
551 err_res =
number(RWExitCode::NOT_OPEN);
554 if( interrupted() ) {
555 err_res =
number(RWExitCode::INTERRUPTED);
558 if ( errno == EAGAIN || errno == EINTR ) {
562 if( errno == ETIMEDOUT ) {
563 err_res =
number(RWExitCode::POLL_TIMEOUT);
565 err_res =
number(RWExitCode::POLL_ERROR);
570 err_res =
number(RWExitCode::POLL_TIMEOUT);
576 while ( is_open_ && !interrupted() && ( len = ::read(socket_, buffer, capacity) ) < 0 ) {
578 err_res =
number(RWExitCode::NOT_OPEN);
581 if( interrupted() ) {
582 err_res =
number(RWExitCode::INTERRUPTED);
585 if ( errno == EAGAIN || errno == EINTR ) {
589 if( errno == ETIMEDOUT ) {
590 err_res =
number(RWExitCode::READ_TIMEOUT);
592 err_res =
number(RWExitCode::READ_ERROR);
603 if( err_res ==
number(RWExitCode::NOT_OPEN) ) {
604 WORDY_PRINT(
"L2CAPClient::read: Not open res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
605 err_res, getRWExitCodeString(err_res).c_str(), len,
606 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
608 getStateString().c_str());
609 }
else if( err_res ==
number(RWExitCode::INTERRUPTED) ) {
610 WORDY_PRINT(
"L2CAPClient::read: IRQed res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
611 err_res, getRWExitCodeString(err_res).c_str(), len,
612 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
614 getStateString().c_str());
615 }
else if( err_res !=
number(RWExitCode::POLL_TIMEOUT) ) {
617 if( err_res ==
number(RWExitCode::READ_TIMEOUT) ) {
618 DBG_PRINT(
"L2CAPClient::read: Read Timeout res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
619 err_res, getRWExitCodeString(err_res).c_str(), len,
620 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
622 getStateString().c_str());
625 if( env.L2CAP_RESTART_COUNT_ON_ERROR < 0 ) {
626 ABORT(
"L2CAPClient::read: Error res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
627 err_res, getRWExitCodeString(err_res).c_str(), len,
628 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
630 getStateString().c_str());
632 IRQ_PRINT(
"L2CAPClient::read: Error res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
633 err_res, getRWExitCodeString(err_res).c_str(), len,
634 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
636 getStateString().c_str());
644 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
649 err_res =
number(RWExitCode::NOT_OPEN);
652 if( interrupted() ) {
653 err_res =
number(RWExitCode::INTERRUPTED);
657 err_res =
number(RWExitCode::INVALID_SOCKET_DD);
664 while ( is_open_ && !interrupted() && ( len = ::write(socket_, buffer, length) ) < 0 ) {
666 err_res =
number(RWExitCode::NOT_OPEN);
669 if( interrupted() ) {
670 err_res =
number(RWExitCode::INTERRUPTED);
673 if( EAGAIN == errno || EINTR == errno ) {
677 err_res =
number(RWExitCode::WRITE_ERROR);
685 if( err_res ==
number(RWExitCode::NOT_OPEN) || err_res ==
number(RWExitCode::INTERRUPTED) ) {
687 WORDY_PRINT(
"L2CAPClient::write: IRQed res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
688 err_res, getRWExitCodeString(err_res).c_str(), len,
689 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
691 getStateString().c_str());
696 if( env.L2CAP_RESTART_COUNT_ON_ERROR < 0 ) {
697 ABORT(
"L2CAPClient::write: Error res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
698 err_res, getRWExitCodeString(err_res).c_str(), len,
699 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
701 getStateString().c_str());
703 IRQ_PRINT(
"L2CAPClient::write: Error res %d (%s), len %d; dev_id %u, dd %d, %s, psm %s, cid %s; %s",
704 err_res, getRWExitCodeString(err_res).c_str(), len,
705 adev_id, socket_.load(), remoteAddressAndType.toString().c_str(),
707 getStateString().c_str());
718 ", remote "+remoteAddressAndType.
toString()+
727:
L2CAPComm(adev_id_, std::move(localAddressAndType_), psm_, cid_), tid_accept(0)
731 bool expOpen =
false;
733 DBG_PRINT(
"L2CAPServer::open: Already open: dev_id %u, dd %d, psm %s, cid %s, local %s",
738 const std::lock_guard<std::recursive_mutex> lock(
mtx_open);
741 DBG_PRINT(
"L2CAPServer::open: Start: dev_id %u, dd %d, psm %s, cid %s, local %s",
753 DBG_PRINT(
"L2CAPServer::open: End: res %d, dev_id %u, dd %d, psm %s, cid %s, local %s",
764 ERR_PRINT(
"L2CAPServer::open: Failed: dev_id %u, dd %d, psm %s, cid %s, local %s",
767 const int err = errno;
773bool L2CAPServer::close_impl() noexcept {
776 DBG_PRINT(
"L2CAPServer::close: Not connected: dev_id %u, dd %d, psm %s, cid %s, local %s",
782 const std::lock_guard<std::recursive_mutex> lock(
mtx_open);
784 DBG_PRINT(
"L2CAPServer::close: Start: dev_id %u, dd %d, psm %s, cid %s, local %s",
793 ::pthread_t tid_self = ::pthread_self();
794 ::pthread_t _tid_accept = tid_accept;
797 if( 0 != _tid_accept && tid_self != _tid_accept ) {
799 if( 0 != ( kerr = ::pthread_kill(_tid_accept, SIGALRM) ) ) {
800 ERR_PRINT(
"L2CAPServer::close: Start: pthread_kill connect %p FAILED: %d; dev_id %u, dd %d, psm %s, cid %s, local %s",
801 (
void*)_tid_accept, kerr,
812 DBG_PRINT(
"L2CAPServer::close: End: dev_id %u, dd %d, psm %s, cid %s, local %s",
820 int to_retry_count=0;
822 tid_accept = ::pthread_self();
825 ERR_PRINT(
"L2CAPServer::accept: Not open: dev_id %u, dd[s %d], errno 0x%X %s, psm %s, cid %s, local %s",
834 bzero((
void *)&peer,
sizeof(peer));
835 socklen_t addrlen =
sizeof(peer);
836 int client_socket =
::accept(
socket_, (
struct sockaddr*)&peer, &addrlen);
842 if( 0 <= client_socket )
844 DBG_PRINT(
"L2CAPServer::accept: Success: dev_id %u, dd[s %d, c %d], errno 0x%X %s, psm %s -> %s, cid %s -> %s, local %s -> remote %s",
849 remoteAddressAndType.
toString().c_str());
853 }
else if( ETIMEDOUT == errno ) {
856 WORDY_PRINT(
"L2CAPServer::accept: Timeout # %d (retry): dev_id %u, dd[s %d, c %d], errno 0x%X %s, psm %s -> %s, cid %s -> %s, local %s -> remote %s",
861 remoteAddressAndType.
toString().c_str());
864 WORDY_PRINT(
"L2CAPServer::accept: Timeout # %d (done): dev_id %u, dd[s %d, c %d], errno 0x%X %s, psm %s -> %s, cid %s -> %s, local %s -> remote %s",
869 remoteAddressAndType.
toString().c_str());
875 IRQ_PRINT(
"L2CAPServer::accept: Failed: dev_id %u, dd[s %d, c %d], errno 0x%X %s, psm %s -> %s, cid %s -> %s, local %s -> remote %s",
880 remoteAddressAndType.
toString().c_str());
#define CASE2_TO_STRING(U, V)
constexpr const bool SET_BT_SECURITY_POST_CONNECT
Setting BT_SECURITY within open() after bind() and before connect() causes BlueZ/Kernel to immediatel...
#define RWEXITCODE_ENUM(X)
Unique Bluetooth EUI48 address and BDAddressType tuple.
static const BDAddressAndType ANY_BREDR_DEVICE
Using EUI48::ANY_DEVICE and BDAddressType::BDADDR_BREDR to match any BREDR device.
std::string toString() const noexcept
BTDevice represents one remote Bluetooth device.
static std::string getRWExitCodeString(const RWExitCode ec) noexcept
jau::snsize_t read(uint8_t *buffer, const jau::nsize_t capacity) noexcept
Generic read, w/o locking suitable for a unique ringbuffer sink.
std::string getStateString() const noexcept override
BTSecurityLevel getBTSecurityLevel() noexcept
Fetches the current BlueZ's L2CAP socket BT_SECURITY sec_level.
bool setBTSecurityLevel(const BTSecurityLevel sec_level) noexcept
If sec_level > BTSecurityLevel::UNSET, sets the BlueZ's L2CAP socket BT_SECURITY sec_level,...
L2CAPClient(const uint16_t adev_id, BDAddressAndType adapterAddressAndType, const L2CAP_PSM psm, const L2CAP_CID cid) noexcept
Constructing a non connected L2CAP channel instance for the pre-defined PSM and CID.
@ L2CAP_CONNECT_MAX_RETRY
jau::snsize_t write(const uint8_t *buffer, const jau::nsize_t length) noexcept
Generic write, locking mutex_write().
static constexpr int number(const Defaults d) noexcept
std::string toString() const noexcept override
bool open(const BTDevice &device, const BTSecurityLevel sec_level=BTSecurityLevel::NONE) noexcept
Opens and connects the L2CAP channel, locking mutex_write().
RWExitCode
Exit code for read() and write() operations.
L2CAP client/server socket abstract base class to listen for connecting remote devices.
jau::sc_atomic_bool interrupted_intern
L2CAPComm(const uint16_t adev_id, BDAddressAndType localAddressAndType, const L2CAP_PSM psm, const L2CAP_CID cid) noexcept
BTSecurityLevel getBTSecurityLevelImpl(const BDAddressAndType &remoteAddressAndType) noexcept
const BDAddressAndType localAddressAndType
Corresponding BTAdapter local BTAddressAndType.
void set_interrupted_query(get_boolean_callback_t is_interrupted_cb) noexcept
The external is interrupted callback is used until close(), thereafter it is removed.
const L2CAP_CID cid
Corresponding L2CAP_CID for the channel.
jau::relaxed_atomic_int socket_
static int l2cap_close_dev(int dd) noexcept
static int l2cap_open_dev(const BDAddressAndType &adapterAddressAndType, const L2CAP_PSM psm, const L2CAP_CID cid) noexcept
virtual std::string getStateString() const noexcept=0
jau::sc_atomic_bool is_open_
std::recursive_mutex mtx_open
bool interrupted() const noexcept
Returns true if interrupted by internal or external cause, hence shall stop connecting and reading.
const L2CAP_PSM psm
Corresponding L2CAP_PSM for the channel.
const uint16_t adev_id
Corresponding BTAdapter device id.
bool setBTSecurityLevelImpl(const BTSecurityLevel sec_level, const BDAddressAndType &remoteAddressAndType) noexcept
static L2CAPEnv & get() noexcept
L2CAPServer(const uint16_t adev_id, BDAddressAndType localAddressAndType, const L2CAP_PSM psm, const L2CAP_CID cid) noexcept
bool close() noexcept override
Closing the L2CAP socket, see specializations.
std::unique_ptr< L2CAPClient > accept() noexcept
std::string toString() const noexcept override
std::string getStateString() const noexcept override
#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 ABORT(...)
Use for unconditional ::abort() call with given messages, prefix '[elapsed_time] ABORT @ file:line fu...
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
#define IRQ_PRINT(...)
Use for unconditional interruption messages, prefix '[elapsed_time] Interrupted @ FILE:LINE FUNC: '.
constexpr uint16_t le_to_cpu(uint16_t const l) noexcept
constexpr uint16_t cpu_to_le(uint16_t const h) noexcept
std::string to_string(const alphabet &v) noexcept
constexpr const bool USE_LINUX_BT_SECURITY
std::string to_string(const DiscoveryPolicy v) noexcept
BDAddressType
BT Core Spec v5.2: Vol 3, Part C Generic Access Profile (GAP): 15.1.1.1 Public Bluetooth address.
L2CAP_PSM
Protocol Service Multiplexers (PSM) Assigned numbers https://www.bluetooth.com/specifications/assigne...
BTSecurityLevel
Bluetooth Security Level.
constexpr uint8_t number(const DiscoveryPolicy rhs) noexcept
@ UNSET
Security Level not set, value 0.
@ NONE
No encryption and no authentication.
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
CXX_ALWAYS_INLINE _Tp load() const noexcept
CXX_ALWAYS_INLINE bool compare_exchange_strong(_Tp &__e, _Tp __i) noexcept