Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
HCIComm.hpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #ifndef HCI_COMM_HPP_
27 #define HCI_COMM_HPP_
28 
29 #include <cstring>
30 #include <string>
31 #include <cstdint>
32 #include <memory>
33 #include <mutex>
34 
35 #include "BTTypes0.hpp"
36 #include "BTIoctl.hpp"
37 #include "HCIIoctl.hpp"
38 #include "HCITypes.hpp"
39 
40 /**
41  * - - - - - - - - - - - - - - -
42  *
43  * Module HCIComm:
44  *
45  * - BT Core Spec v5.2: Vol 4, Part E Host Controller Interface (HCI)
46  */
47 namespace direct_bt {
48 
49  /**
50  * Read/Write HCI communication channel.
51  */
52  class HCIComm {
53  public:
54  const uint16_t dev_id;
55  const uint16_t channel;
56 
57  private:
58  static int hci_open_dev(const uint16_t dev_id, const uint16_t channel) noexcept;
59  static int hci_close_dev(int dd) noexcept;
60 
61  std::recursive_mutex mtx_write;
62  std::atomic<int> socket_descriptor; // the hci socket
63  std::atomic<bool> interrupt_flag; // for forced disconnect
64  std::atomic<pthread_t> tid_read;
65 
66  public:
67  /** Constructing a newly opened HCI communication channel instance */
68  HCIComm(const uint16_t dev_id, const uint16_t channel) noexcept;
69 
70  HCIComm(const HCIComm&) = delete;
71  void operator=(const HCIComm&) = delete;
72 
73  /**
74  * Releases this instance after issuing {@link #close()}.
75  */
76  ~HCIComm() noexcept { close(); }
77 
78  /** Closing the HCI channel, locking {@link #mutex_write()}. */
79  void close() noexcept;
80 
81  bool isOpen() const noexcept { return 0 <= socket_descriptor; }
82 
83  /** Return this HCI socket descriptor. */
84  inline int getSocketDescriptor() const noexcept { return socket_descriptor; }
85 
86  /** Return the recursive write mutex for multithreading access. */
87  inline std::recursive_mutex & mutex_write() noexcept { return mtx_write; }
88 
89  /** Generic read w/ own timeoutMS, w/o locking suitable for a unique ringbuffer sink. */
90  jau::snsize_t read(uint8_t* buffer, const jau::nsize_t capacity, const int32_t timeoutMS) noexcept;
91 
92  /** Generic write, locking {@link #mutex_write()}. */
93  jau::snsize_t write(const uint8_t* buffer, const jau::nsize_t size) noexcept;
94 
95  private:
96  static inline void setu32_bit(int nr, void *addr) noexcept
97  {
98  *((uint32_t *) addr + (nr >> 5)) |= (1 << (nr & 31));
99  }
100 
101  static inline void clearu32_bit(int nr, void *addr) noexcept
102  {
103  *((uint32_t *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
104  }
105 
106  static inline int testu32_bit(int nr, void *addr) noexcept
107  {
108  return *((uint32_t *) addr + (nr >> 5)) & (1 << (nr & 31));
109  }
110 
111  public:
112  static inline void filter_clear(hci_ufilter *f) noexcept
113  {
114  bzero(f, sizeof(*f));
115  }
116  static inline void filter_set_ptype(int t, hci_ufilter *f) noexcept
117  {
118  setu32_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask);
119  }
120  static inline void filter_clear_ptype(int t, hci_ufilter *f) noexcept
121  {
122  clearu32_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask);
123  }
124  static inline int filter_test_ptype(int t, hci_ufilter *f) noexcept
125  {
126  return testu32_bit((t == HCI_VENDOR_PKT) ? 0 : (t & HCI_FLT_TYPE_BITS), &f->type_mask);
127  }
128  static inline void filter_all_ptypes(hci_ufilter *f) noexcept
129  {
130  memset((void *) &f->type_mask, 0xff, sizeof(f->type_mask));
131  }
132  static inline void filter_set_event(int e, hci_ufilter *f) noexcept
133  {
134  setu32_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask);
135  }
136  static inline void filter_clear_event(int e, hci_ufilter *f) noexcept
137  {
138  clearu32_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask);
139  }
140  static inline int filter_test_event(int e, hci_ufilter *f) noexcept
141  {
142  return testu32_bit((e & HCI_FLT_EVENT_BITS), &f->event_mask);
143  }
144  static inline void filter_all_events(hci_ufilter *f) noexcept
145  {
146  memset((void *) f->event_mask, 0xff, sizeof(f->event_mask));
147  }
148  static inline void filter_set_opcode(uint16_t opcode, hci_ufilter *f) noexcept
149  {
150  f->opcode = opcode;
151  }
152  static inline void filter_clear_opcode(hci_ufilter *f) noexcept
153  {
154  f->opcode = 0;
155  }
156  static inline int filter_test_opcode(uint16_t opcode, hci_ufilter *f) noexcept
157  {
158  return (f->opcode == opcode);
159  }
160  };
161 
162 } // namespace direct_bt
163 
164 #endif /* HCI_COMM_HPP_ */
direct_bt::HCIComm::HCIComm
HCIComm(const uint16_t dev_id, const uint16_t channel) noexcept
Constructing a newly opened HCI communication channel instance.
Definition: HCIComm.cpp:105
direct_bt::HCIComm::filter_test_opcode
static int filter_test_opcode(uint16_t opcode, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:156
direct_bt::HCIComm::filter_set_event
static void filter_set_event(int e, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:132
direct_bt::HCIComm::~HCIComm
~HCIComm() noexcept
Releases this instance after issuing close().
Definition: HCIComm.hpp:76
direct_bt::HCIComm::operator=
void operator=(const HCIComm &)=delete
direct_bt
Definition: ATTPDUTypes.hpp:171
direct_bt::HCIComm::filter_all_ptypes
static void filter_all_ptypes(hci_ufilter *f) noexcept
Definition: HCIComm.hpp:128
direct_bt::HCIComm::filter_clear_event
static void filter_clear_event(int e, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:136
direct_bt::HCIComm::isOpen
bool isOpen() const noexcept
Definition: HCIComm.hpp:81
direct_bt::HCIComm::filter_clear_ptype
static void filter_clear_ptype(int t, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:120
HCITypes.hpp
direct_bt::HCIComm::filter_test_event
static int filter_test_event(int e, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:140
direct_bt::HCIComm::filter_all_events
static void filter_all_events(hci_ufilter *f) noexcept
Definition: HCIComm.hpp:144
direct_bt::HCIComm::HCIComm
HCIComm(const HCIComm &)=delete
BTTypes0.hpp
direct_bt::HCIComm::mutex_write
std::recursive_mutex & mutex_write() noexcept
Return the recursive write mutex for multithreading access.
Definition: HCIComm.hpp:87
direct_bt::HCIComm::filter_set_ptype
static void filter_set_ptype(int t, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:116
direct_bt::HCIComm
Read/Write HCI communication channel.
Definition: HCIComm.hpp:52
direct_bt::HCIComm::filter_test_ptype
static int filter_test_ptype(int t, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:124
jau::snsize_t
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:56
jau::nsize_t
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:44
direct_bt::HCIComm::filter_clear
static void filter_clear(hci_ufilter *f) noexcept
Definition: HCIComm.hpp:112
direct_bt::HCIComm::filter_clear_opcode
static void filter_clear_opcode(hci_ufilter *f) noexcept
Definition: HCIComm.hpp:152
direct_bt::HCIComm::channel
const uint16_t channel
Definition: HCIComm.hpp:55
direct_bt::HCIComm::getSocketDescriptor
int getSocketDescriptor() const noexcept
Return this HCI socket descriptor.
Definition: HCIComm.hpp:84
direct_bt::HCIComm::close
void close() noexcept
Closing the HCI channel, locking mutex_write().
Definition: HCIComm.cpp:111
direct_bt::HCIComm::filter_set_opcode
static void filter_set_opcode(uint16_t opcode, hci_ufilter *f) noexcept
Definition: HCIComm.hpp:148
direct_bt::HCIComm::write
jau::snsize_t write(const uint8_t *buffer, const jau::nsize_t size) noexcept
Generic write, locking mutex_write().
Definition: HCIComm.cpp:183
direct_bt::HCIComm::dev_id
const uint16_t dev_id
Definition: HCIComm.hpp:54
direct_bt::HCIComm::read
jau::snsize_t read(uint8_t *buffer, const jau::nsize_t capacity, const int32_t timeoutMS) noexcept
Generic read w/ own timeoutMS, w/o locking suitable for a unique ringbuffer sink.
Definition: HCIComm.cpp:141