46 #include <sys/param.h>
48 #include <sys/types.h>
49 #include <sys/ioctl.h>
50 #include <sys/socket.h>
58int HCIComm::hci_open_dev(
const uint16_t dev_id,
const uint16_t channel)
noexcept
60 static_assert(
sizeof(
struct sockaddr) > sizeof(sockaddr_hci), "Requirement sizeof(struct sockaddr) > sizeof(sockaddr_hci)" );
62 sockaddr_hci * ptr_hci_addr = (sockaddr_hci*)&addr_holder;
67#elif defined(__FreeBSD__)
69 ABORT(
"add implementation for FreeBSD");
71 #warning add implementation
72 ABORT(
"add implementation");
76 fd = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
78 ERR_PRINT(
"HCIComm::hci_open_dev: socket failed");
83 bzero(&addr_holder,
sizeof(addr_holder));
84 ptr_hci_addr->hci_family = AF_BLUETOOTH;
85 ptr_hci_addr->hci_dev = dev_id;
86 ptr_hci_addr->hci_channel = channel;
87 if (::bind(fd, &addr_holder,
sizeof(sockaddr_hci)) < 0) {
102int HCIComm::hci_close_dev(
int dd)
noexcept
112: dev_id( _dev_id ), channel( _channel ),
113 socket_descriptor( hci_open_dev(_dev_id, _channel) ),
114 interrupted_intern(
false), is_interrupted_extern(), tid_read(0)
119 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
120 if( 0 > socket_descriptor ) {
121 DBG_PRINT(
"HCIComm::close: Not opened: dd %d", socket_descriptor.
load());
124 DBG_PRINT(
"HCIComm::close: Start: dd %d", socket_descriptor.
load());
127 interrupted_intern =
true;
129 ::pthread_t _tid_read = tid_read;
131 if( 0 != _tid_read ) {
132 ::pthread_t tid_self = ::pthread_self();
133 if( tid_self != _tid_read ) {
135 if( 0 != ( kerr = ::pthread_kill(_tid_read, SIGALRM) ) ) {
136 ERR_PRINT(
"HCIComm::close: pthread_kill read %p FAILED: %d", (
void*)_tid_read, kerr);
141 hci_close_dev(socket_descriptor);
142 socket_descriptor = -1;
143 interrupted_intern =
false;
145 DBG_PRINT(
"HCIComm::close: End: dd %d", socket_descriptor.
load());
150 if( 0 > socket_descriptor ) {
153 if( 0 == capacity ) {
157 if( !timeout.is_zero() ) {
162 p.fd = socket_descriptor; p.events = POLLIN;
163 while ( !interrupted() && (n = ::poll(&p, 1, timeoutMS)) < 0 ) {
164 if ( !interrupted() && ( errno == EAGAIN || errno == EINTR ) ) {
176 while ((len = ::read(socket_descriptor, buffer, capacity)) < 0) {
177 if (errno == EAGAIN || errno == EINTR ) {
192 const std::lock_guard<std::recursive_mutex> lock(mtx_write);
194 if( 0 > socket_descriptor ) {
201 while( ( len = ::write(socket_descriptor, buffer, size) ) < 0 ) {
202 if( EAGAIN == errno || EINTR == errno ) {
HCIComm(const uint16_t dev_id, const uint16_t channel) noexcept
Constructing a newly opened HCI communication channel instance.
void close() noexcept
Closing the HCI channel, locking mutex_write().
jau::snsize_t read(uint8_t *buffer, const jau::nsize_t capacity, const jau::fraction_i64 &timeout) noexcept
Generic read w/ own timeout, w/o locking suitable for a unique ringbuffer sink.
jau::snsize_t write(const uint8_t *buffer, const jau::nsize_t size) noexcept
Generic write, locking mutex_write().
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
#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...
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
constexpr const jau::fraction_i64 milli(1l, 1 '000lu)
milli is 10^-3
CXX_ALWAYS_INLINE _Tp load() const noexcept