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