Direct-BT
2.3.1
Direct-BT - Direct Bluetooth Programming.
|
Go to the documentation of this file.
26 #ifndef HCI_HANDLER_HPP_
27 #define HCI_HANDLER_HPP_
43 #include "BTIoctl.hpp"
139 const int32_t HCI_READ_PACKET_MAX_RETRY;
182 class HCIConnection {
188 HCIConnection(
const BDAddressAndType& addressAndType_,
const uint16_t handle_)
189 : addressAndType(addressAndType_), handle(handle_) {}
191 HCIConnection(
const HCIConnection &o) =
default;
192 HCIConnection(HCIConnection &&o) =
default;
193 HCIConnection&
operator=(
const HCIConnection &o) =
default;
194 HCIConnection&
operator=(HCIConnection &&o) =
default;
196 const BDAddressAndType & getAddressAndType()
const {
return addressAndType; }
197 uint16_t getHandle()
const {
return handle; }
199 void setHandle(uint16_t newHandle) { handle = newHandle; }
202 {
return addressAndType == other; }
204 bool operator==(
const HCIConnection& rhs)
const {
208 return addressAndType == rhs.addressAndType;
211 bool operator!=(
const HCIConnection& rhs)
const
212 {
return !(*
this == rhs); }
214 std::size_t hash_code()
const noexcept {
220 ", address "+addressAndType.
toString()+
"]";
223 typedef std::shared_ptr<HCIConnection> HCIConnectionRef;
227 const uint16_t dev_id;
230 hci_ufilter filter_mask;
231 std::atomic<uint32_t> metaev_filter_mask;
232 std::atomic<uint64_t> opcbit_filter_mask;
235 inline void filter_put_metaevs(
const uint32_t mask) noexcept { metaev_filter_mask=mask; }
237 constexpr
static void filter_clear_metaevs(uint32_t &mask) noexcept { mask=0; }
238 constexpr
static void filter_all_metaevs(uint32_t &mask) noexcept { mask=0xffffffffU; }
242 inline void filter_put_opcbit(
const uint64_t mask) noexcept { opcbit_filter_mask=mask; }
244 constexpr
static void filter_clear_opcbit(uint64_t &mask) noexcept { mask=0; }
245 constexpr
static void filter_all_opcbit(uint64_t &mask) noexcept { mask=0xffffffffffffffffUL; }
251 std::mutex mtx_hciReaderLifecycle;
252 std::condition_variable cv_hciReaderInit;
253 pthread_t hciReaderThreadId;
256 std::recursive_mutex mtx_sendReply;
265 uint8_t sup_commands[64];
269 std::atomic<BTMode> btMode;
271 std::atomic<ScanType> currentScanType;
275 std::recursive_mutex mtx_connectionList;
278 std::mutex mtx_connect_cmd;
280 void zeroSupCommands() noexcept;
281 bool initSupCommands() noexcept;
295 HCIConnectionRef addOrUpdateHCIConnection(
jau::darray<HCIConnectionRef> &list,
296 const BDAddressAndType& addressAndType, const uint16_t handle) noexcept;
297 HCIConnectionRef addOrUpdateTrackerConnection(const BDAddressAndType& addressAndType, const uint16_t handle) noexcept {
298 return addOrUpdateHCIConnection(connectionList, addressAndType, handle);
300 HCIConnectionRef addOrUpdateDisconnectCmd(
const BDAddressAndType& addressAndType,
const uint16_t handle) noexcept {
301 return addOrUpdateHCIConnection(disconnectCmdList, addressAndType, handle);
305 HCIConnectionRef findTrackerConnection(
const BDAddressAndType& addressAndType) noexcept {
306 return findHCIConnection(connectionList, addressAndType);
308 HCIConnectionRef findDisconnectCmd(
const BDAddressAndType& addressAndType) noexcept {
309 return findHCIConnection(disconnectCmdList, addressAndType);
312 HCIConnectionRef findTrackerConnection(
const uint16_t handle) noexcept;
313 HCIConnectionRef removeTrackerConnection(
const HCIConnectionRef conn) noexcept;
314 int countPendingTrackerConnections() noexcept;
316 HCIConnectionRef removeHCIConnection(
jau::darray<HCIConnectionRef> &list, const uint16_t handle) noexcept;
317 HCIConnectionRef removeTrackerConnection(const uint16_t handle) noexcept {
318 return removeHCIConnection(connectionList, handle);
320 HCIConnectionRef removeDisconnectCmd(
const uint16_t handle) noexcept {
321 return removeHCIConnection(disconnectCmdList, handle);
326 inline bool isValidMgmtEventCallbackListsIndex(
const MgmtEvent::Opcode opc)
const noexcept {
327 return static_cast<uint16_t
>(opc) < mgmtEventCallbackLists.size();
332 std::unique_ptr<MgmtEvent> translate(HCIEvent& ev) noexcept;
334 std::unique_ptr<const SMPPDUMsg> getSMPPDUMsg(
const HCIACLData::l2cap_frame & l2cap,
const uint8_t * l2cap_data)
const noexcept;
335 void hciReaderThreadImpl() noexcept;
337 bool sendCommand(HCICommand &req) noexcept;
338 std::unique_ptr<HCIEvent> getNextReply(HCICommand &req, int32_t & retryCount, const int32_t replyTimeoutMS) noexcept;
339 std::unique_ptr<HCIEvent> getNextCmdCompleteReply(HCICommand &req, HCICommandCompleteEvent **res) noexcept;
341 std::unique_ptr<HCIEvent> processCommandStatus(HCICommand &req,
HCIStatusCode *status) noexcept;
343 template<typename hci_cmd_event_struct>
344 std::unique_ptr<HCIEvent> processCommandComplete(HCICommand &req,
345 const hci_cmd_event_struct **res,
HCIStatusCode *status) noexcept;
346 template<typename hci_cmd_event_struct>
347 std::unique_ptr<HCIEvent> receiveCommandComplete(HCICommand &req,
348 const hci_cmd_event_struct **res,
HCIStatusCode *status) noexcept;
350 template<typename hci_cmd_event_struct>
353 template<typename hci_cmd_event_struct>
367 void close() noexcept;
375 return true == allowClose.
load() && comm.
isOpen();
380 return 0 != ( sup_commands[37] & ( 1 << 5 ) ) &&
381 0 != ( sup_commands[37] & ( 1 << 6 ) );
386 return 0 != ( sup_commands[37] & ( 1 << 7 ) );
392 std::string
toString() const noexcept;
570 const uint16_t conn_interval_min=12, const uint16_t conn_interval_max=12,
594 const uint16_t pkt_type=HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5,
595 const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01) noexcept;
659 template<>
struct hash<
direct_bt::HCIHandler::HCIConnection> {
660 std::size_t operator()(direct_bt::HCIHandler::HCIConnection
const& a)
const noexcept {
661 return a.hash_code();
HCIStatusCode resetAdapter()
Reset the adapter.
const int32_t HCI_EVT_RING_CAPACITY
Small ringbuffer capacity for synchronized commands, defaults to 64 messages.
HCI Singleton runtime environment properties.
static const uint16_t le_scan_interval
Representing ACL Datas' L2CAP Frame.
std::size_t hash_code() const noexcept
Implementation uses a lock-free volatile cache.
Base jau environment class, merely to tag all environment settings by inheritance and hence documenta...
HCIStatusCode stopAdapter()
Bring down this adapter into a non-POWERED non-functional state.
bool use_ext_conn() const noexcept
Use extended connection if HCI_LE_Extended_Create_Connection is supported (Bluetooth 5....
HCIStatusCode create_conn(const EUI48 &bdaddr, const uint16_t pkt_type=HCI_DM1|HCI_DM3|HCI_DM5|HCI_DH1|HCI_DH3|HCI_DH5, const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01) noexcept
Establish a connection to the given BREDR (non LE).
void setCurrentScanType(const ScanType v) noexcept
bool operator==(const EUI48Sub &lhs, const EUI48Sub &rhs) noexcept
void set_bit_uint64(const uint8_t nr, uint64_t &mask)
void clearAllCallbacks() noexcept
Removes all MgmtEventCallbacks from all MgmtEvent::Opcode lists and all SMPSecurityReqCallbacks.
std::string toString() const noexcept
void clearMgmtEventCallbacks(const MgmtEvent::Opcode opc) noexcept
Removes all MgmtEventCallbacks from the to the named MgmtEvent::Opcode list.
HCIStatusCode disconnect(const uint16_t conn_handle, const BDAddressAndType &addressAndType, const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION) noexcept
Disconnect an established connection.
std::string toString() const noexcept
ScanType getCurrentScanType() const noexcept
HCIStatusCode le_start_scan(const bool filter_dup=true, const bool le_scan_active=false, const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC, const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint8_t filter_policy=0x00) noexcept
Start LE scanning, i.e.
ScanType
Meta ScanType as derived from BTMode, with defined value mask consisting of BDAddressType bits.
HCIStatusCode startAdapter()
Bring up this adapter into a POWERED functional state.
HCIHandler(const uint16_t dev_id, const BTMode btMode=BTMode::NONE) noexcept
A thread safe singleton handler of the HCI control channel to one controller (BT adapter)
jau::cow_darray< HCISMPMsgCallback > HCISMPMsgCallbackList
bool isOpen() const noexcept
uint16_t opcode, uint16_t dev-id, uint16_t param_size
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
HCIMetaEventType
BT Core Spec v5.2: Vol 4, Part E HCI: 7.7.65 LE Meta event.
LE_Features
HCI Supported Commands.
static const uint16_t le_scan_window
HCIStatusCode le_read_phy(const uint16_t conn_handle, const BDAddressAndType &addressAndType, LE_PHYs &resRx, LE_PHYs &resTx) noexcept
Request and return LE_PHYs bit for the given connection.
HCIStatusCode le_set_scan_param(const bool le_scan_active=false, const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC, const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint8_t filter_policy=0x00) noexcept
Sets LE scanning parameters.
HCIStatusCode reset() noexcept
HCI Reset Command.
int removeMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
Returns count of removed given MgmtEventCallback from the named MgmtEvent::Opcode list.
int removeSMPMsgCallback(const HCISMPMsgCallback &l)
bool use_ext_scan() const noexcept
Use extended scanning if HCI_LE_Set_Extended_Scan_Parameters and HCI_LE_Set_Extended_Scan_Enable is s...
CXX_ALWAYS_INLINE _Tp load() const noexcept
void set_bit_uint32(const uint8_t nr, uint32_t &mask)
constexpr uint8_t number(const BDAddressType rhs) noexcept
Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU) encoded messages over L2CA...
@ PACKET_MAX_SIZE
Total packet size, guaranteed to be handled by adapter.
HCIEventType
BT Core Spec v5.2: Vol 4, Part E HCI: 7.7 Events.
Ring buffer implementation, a.k.a circular buffer, exposing lock-free get*(..) and put*(....
HCIStatusCode le_create_conn(const EUI48 &peer_bdaddr, const HCILEPeerAddressType peer_mac_type=HCILEPeerAddressType::PUBLIC, const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC, const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24, const uint16_t conn_interval_min=12, const uint16_t conn_interval_max=12, const uint16_t conn_latency=0, const uint16_t supervision_timeout=getHCIConnSupervisorTimeout(0, 15)) noexcept
Establish a connection to the given LE peer.
jau::FunctionDef< bool, const BDAddressAndType &, const SMPPDUMsg &, const HCIACLData::l2cap_frame & > HCISMPMsgCallback
static bool le_scan_active
Read/Write HCI communication channel.
bool addMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
MgmtEventCallback handling
HCIStatusCode getLocalVersion(HCILocalVersion &version) noexcept
void sendMgmtEvent(const MgmtEvent &event) noexcept
Manually send a MgmtEvent to all of its listeners.
static HCIEnv & get() noexcept
bool isOpen() const noexcept
Returns true if this mgmt instance is open, connected and hence valid, otherwise false.
constexpr int32_t getHCIConnSupervisorTimeout(const uint16_t conn_latency, const uint16_t conn_interval_max_ms, const uint16_t min_result_ms=number(HCIConstInt::LE_CONN_MIN_TIMEOUT_MS), const uint16_t multiplier=10) noexcept
Defining the supervising timeout for LE connections to be a multiple of the maximum connection interv...
const bool DEBUG_EVENT
Debug all HCI event communication.
void resetAllStates(const bool powered_on) noexcept
Reset all internal states, i.e.
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
const bool DEBUG_SCAN_AD_EIR
Debug all scanned HCI 'Advertising Data' (AD) 'Extended Inquiry Response' (EIR) packages.
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
void operator=(const HCIHandler &)=delete
const int32_t HCI_READER_THREAD_POLL_TIMEOUT
Poll timeout for HCI reader thread, defaults to 10s.
void addSMPMsgCallback(const HCISMPMsgCallback &l)
uint32_t test_bit_uint32(const uint8_t nr, const uint32_t mask)
BTMode getBTMode() const noexcept
void setBTMode(const BTMode mode) noexcept
const int32_t HCI_COMMAND_POLL_PERIOD
Poll period for certain HCI commands actively waiting for clearance, defaults to 125ms.
static const uint8_t filter_policy
const int32_t HCI_COMMAND_STATUS_REPLY_TIMEOUT
Timeout for HCI command status replies, excluding command complete, defaults to 3s.
Persistent octet data, i.e.
bool operator!=(const EUI48Sub &lhs, const EUI48Sub &rhs) noexcept
HCILEPeerAddressType
HCI LE Address-Type is PUBLIC: 0x00, RANDOM: 0x01.
HCIStatusCode le_enable_scan(const bool enable, const bool filter_dup=true) noexcept
Starts or stops LE scanning.
LE_PHYs
LE Transport PHY bit values.
Unique Bluetooth EUI48 address and BDAddressType tuple.
static const pid_t pidSelf
const int32_t HCI_COMMAND_COMPLETE_REPLY_TIMEOUT
Timeout for HCI command complete replies, defaults to 10s.
BTMode
Bluetooth adapter operating mode.
HCIStatusCode le_read_local_features(LE_Features &res) noexcept
Request and return LE_Features for the controller.
uint64_t test_bit_uint64(const uint8_t nr, const uint64_t mask)