Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
HCIHandler.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_HANDLER_HPP_
27#define HCI_HANDLER_HPP_
28
29#include <cstring>
30#include <string>
31#include <cstdint>
32#include <array>
33
34#include <mutex>
35#include <atomic>
36#include <thread>
37
38#include <jau/darray.hpp>
39#include <jau/environment.hpp>
40#include <jau/ringbuffer.hpp>
41#include <jau/java_uplink.hpp>
42#include <jau/octets.hpp>
44#include <jau/functional.hpp>
45
46#include "BTTypes0.hpp"
47#include "BTIoctl.hpp"
48#include "HCIComm.hpp"
49#include "HCITypes.hpp"
50#include "MgmtTypes.hpp"
51
52/**
53 * - - - - - - - - - - - - - - -
54 *
55 * Module HCIHandler:
56 *
57 * - BT Core Spec v5.2: Vol 4, Part E Host Controller Interface (HCI)
58 */
59namespace direct_bt {
60
61 /** \addtogroup DBTSystemAPI
62 *
63 * @{
64 */
65
66 class HCIHandler; // forward
67
68 /**
69 * HCI Singleton runtime environment properties
70 * <p>
71 * Also see {@link DBTEnv::getExplodingProperties(const std::string & prefixDomain)}.
72 * </p>
73 */
75 friend class HCIHandler;
76
77 private:
78 HCIEnv() noexcept; // NOLINT(modernize-use-equals-delete)
79
80 const bool exploding; // just to trigger exploding properties
81
82 public:
83 /**
84 * Poll timeout for HCI reader thread, defaults to 10s.
85 * <p>
86 * Environment variable is 'direct_bt.hci.reader.timeout'.
87 * </p>
88 */
90
91 /**
92 * Timeout for HCI command status replies, excluding command complete, defaults to 3s.
93 * <p>
94 * Environment variable is 'direct_bt.hci.cmd.status.timeout'.
95 * </p>
96 */
98
99 /**
100 * Timeout for HCI command complete replies, defaults to 10s.
101 * This timeout is rather longer, as it may include waiting for pending command complete.
102 * <p>
103 * Environment variable is 'direct_bt.hci.cmd.complete.timeout'.
104 * </p>
105 */
107
108 /**
109 * Poll period for certain HCI commands actively waiting for clearance, defaults to 125ms.
110 * <p>
111 * Used for LE_Create_Connection or Create_Connection
112 * when waiting for any pending connection commands or the addressed device's disconnect command to been completed
113 * up to HCI_COMMAND_COMPLETE_REPLY_TIMEOUT.
114 * </p>
115 * <p>
116 * Environment variable is 'direct_bt.hci.cmd.complete.timeout'.
117 * </p>
118 */
120
121 /**
122 * Small ringbuffer capacity for synchronized commands, defaults to 64 messages.
123 * <p>
124 * Environment variable is 'direct_bt.hci.ringsize'.
125 * </p>
126 */
128
129 /**
130 * Debug all HCI event communication
131 * <p>
132 * Environment variable is 'direct_bt.debug.hci.event'.
133 * </p>
134 */
135 const bool DEBUG_EVENT;
136
137 /**
138 * Debug all scanned HCI 'Advertising Data' (AD) 'Extended Inquiry Response' (EIR) packages.
139 * <p>
140 * Environment variable is 'direct_bt.debug.hci.scan_ad_eir'.
141 * </p>
142 */
144
145 private:
146 /** Maximum number of packets to wait for until matching a sequential command. Won't block as timeout will limit. */
147 const int32_t HCI_READ_PACKET_MAX_RETRY;
148
149 public:
150 static HCIEnv& get() noexcept {
151 /**
152 * Thread safe starting with C++11 6.7:
153 *
154 * If control enters the declaration concurrently while the variable is being initialized,
155 * the concurrent execution shall wait for completion of the initialization.
156 *
157 * (Magic Statics)
158 *
159 * Avoiding non-working double checked locking.
160 */
161 static HCIEnv e;
162 return e;
163 }
164 };
165
166 typedef jau::function<void(const BDAddressAndType& /* addressAndType */,
169
170 /**
171 * A thread safe singleton handler of the HCI control channel to one controller (BT adapter)
172 * <p>
173 * Implementation utilizes a lock free ringbuffer receiving data within its separate thread.
174 * </p>
175 * <p>
176 * Controlling Environment variables, see {@link HCIEnv}.
177 * </p>
178 */
180 public:
183 };
184
185 const HCIEnv & env;
186
188
189 private:
190 class HCIConnection {
191 private:
192 BDAddressAndType visibleAddressAndType; // immutable
193 BDAddressAndType addressAndType; // mutable
194 uint16_t handle; // mutable
195
196 public:
197 HCIConnection(const BDAddressAndType& addressAndType_, const uint16_t handle_)
198 : visibleAddressAndType(addressAndType_), addressAndType(addressAndType_), handle(handle_) {}
199
200 HCIConnection(const HCIConnection &o) = default;
201 HCIConnection(HCIConnection &&o) = default;
202 HCIConnection& operator=(const HCIConnection &o) = default;
203 HCIConnection& operator=(HCIConnection &&o) = default;
204
205 const BDAddressAndType & getVisibleAddressAndType() const { return visibleAddressAndType; }
206 const BDAddressAndType & getAddressAndType() const { return addressAndType; }
207 void setResolvAddrAndType(const BDAddressAndType& val) { addressAndType = val; }
208
209 uint16_t getHandle() const { return handle; }
210
211 void setHandle(uint16_t newHandle) { handle = newHandle; }
212
213 bool equals(const BDAddressAndType & other) const
214 { return addressAndType == other || visibleAddressAndType == other; }
215
216 bool operator==(const HCIConnection& rhs) const {
217 if( this == &rhs ) {
218 return true;
219 }
220 return addressAndType == rhs.addressAndType || visibleAddressAndType == rhs.visibleAddressAndType;
221 }
222
223 bool operator!=(const HCIConnection& rhs) const
224 { return !(*this == rhs); }
225
226 std::size_t hash_code() const noexcept {
227 return addressAndType.hash_code();
228 }
229
230 std::string toString() const {
231 std::string resaddr_s = visibleAddressAndType != addressAndType ? ", visible "+visibleAddressAndType.toString() : "";
232 return "HCIConnection[handle "+jau::to_hexstring(handle)+
233 ", address "+addressAndType.toString()+resaddr_s+"]";
234 }
235 };
236 public:
237 typedef std::shared_ptr<HCIConnection> HCIConnectionRef;
239
240 private:
241
242 static MgmtEvent::Opcode translate(HCIEventType evt, HCIMetaEventType met) noexcept;
243
244 const uint16_t dev_id;
245 jau::POctets rbuffer;
246 HCIComm comm;
247 hci_ufilter filter_mask;
248 std::atomic<uint32_t> metaev_filter_mask;
249 std::atomic<uint64_t> opcbit_filter_mask;
250
251 inline bool filter_test_metaev(HCIMetaEventType mec) noexcept { return 0 != jau::test_bit_uint32(number(mec)-1, metaev_filter_mask); }
252 inline void filter_put_metaevs(const uint32_t mask) noexcept { metaev_filter_mask=mask; }
253
254 constexpr static void filter_clear_metaevs(uint32_t &mask) noexcept { mask=0; }
255 constexpr static void filter_all_metaevs(uint32_t &mask) noexcept { mask=0xffffffffU; }
256 inline static void filter_set_metaev(HCIMetaEventType mec, uint32_t &mask) noexcept { jau::set_bit_uint32(number(mec)-1, mask); }
257
258 inline bool filter_test_opcbit(HCIOpcodeBit opcbit) noexcept { return 0 != jau::test_bit_uint64(number(opcbit), opcbit_filter_mask); }
259 inline void filter_put_opcbit(const uint64_t mask) noexcept { opcbit_filter_mask=mask; }
260
261 constexpr static void filter_clear_opcbit(uint64_t &mask) noexcept { mask=0; }
262 constexpr static void filter_all_opcbit(uint64_t &mask) noexcept { mask=0xffffffffffffffffUL; }
263 inline static void filter_set_opcbit(HCIOpcodeBit opcbit, uint64_t &mask) noexcept { jau::set_bit_uint64(number(opcbit), mask); }
264
265 jau::service_runner hci_reader_service;
267
268 std::recursive_mutex mtx_sendReply; // for sendWith*Reply, process*Command, ..; Recurses from many..
269
270 LE_Features le_ll_feats;
271 /**
272 * Cached bitfield of Local Supported Commands, 64 octets
273 * <pre>
274 * BT Core Spec v5.2: Vol 4, Part E, 6.27 (HCI) Supported Commands
275 * BT Core Spec v5.2: Vol 4, Part E, 7.4.2 Read Local Supported Commands command
276 * </pre>
277 */
278 uint8_t sup_commands[64];
279 jau::relaxed_atomic_bool sup_commands_set;
280
281 jau::sc_atomic_bool allowClose;
282 std::atomic<BTMode> btMode;
283
284 std::atomic<ScanType> currentScanType;
285 jau::sc_atomic_bool advertisingEnabled;
286
287 HCIConnectionRefList_t connectionList;
288 HCIConnectionRefList_t disconnectCmdList;
289 std::recursive_mutex mtx_connectionList; // Recurses from disconnect -> findTrackerConnection, addOrUpdateTrackerConnection
290
291 /** Exclusive [le] connection command (status + pending completed) one at a time */
292 std::mutex mtx_connect_cmd;
293
294 HCIConnectionRef setResolvHCIConnectionAddr(jau::darray<HCIConnectionRef> &list,
295 const BDAddressAndType& visibleAddressAndType, const BDAddressAndType& addressAndType) noexcept;
296
297 public:
298 void setResolvHCIConnectionAddr(const BDAddressAndType& visibleAddressAndType, const BDAddressAndType& addressAndType) noexcept {
299 setResolvHCIConnectionAddr(connectionList, visibleAddressAndType, addressAndType);
300 setResolvHCIConnectionAddr(disconnectCmdList, visibleAddressAndType, addressAndType);
301 }
302
303 private:
304 /**
305 * Returns a newly added HCIConnectionRef tracker connection with given parameters, if not existing yet.
306 * <p>
307 * In case the HCIConnectionRef tracker connection already exists,
308 * its handle will be updated (see below) and reference returned.
309 * <p>
310 * Overwrite existing tracked connection handle with given _valid_ handle only, i.e. non zero!
311 * </p>
312 * @param address key to matching connection
313 * @param addrType key to matching connection
314 * @param handle ignored for existing tracker _if_ invalid, i.e. zero.
315 */
316 HCIConnectionRef addOrUpdateHCIConnection(HCIConnectionRefList_t& list,
317 const BDAddressAndType& addressAndType, const uint16_t handle) noexcept;
318 HCIConnectionRef addOrUpdateTrackerConnection(const BDAddressAndType& addressAndType, const uint16_t handle) noexcept {
319 return addOrUpdateHCIConnection(connectionList, addressAndType, handle);
320 }
321 HCIConnectionRef addOrUpdateDisconnectCmd(const BDAddressAndType& addressAndType, const uint16_t handle) noexcept {
322 return addOrUpdateHCIConnection(disconnectCmdList, addressAndType, handle);
323 }
324
325 HCIConnectionRef findHCIConnection(HCIConnectionRefList_t& list, const BDAddressAndType& addressAndType) noexcept;
326 HCIConnectionRef findTrackerConnection(const BDAddressAndType& addressAndType) noexcept {
327 return findHCIConnection(connectionList, addressAndType);
328 }
329 HCIConnectionRef findDisconnectCmd(const BDAddressAndType& addressAndType) noexcept {
330 return findHCIConnection(disconnectCmdList, addressAndType);
331 }
332
333 HCIConnectionRef findTrackerConnection(const uint16_t handle) noexcept;
334 HCIConnectionRef removeTrackerConnection(const HCIConnectionRef& conn) noexcept;
335 size_type countPendingTrackerConnections() noexcept;
336 size_type getTrackerConnectionCount() noexcept;
337
338 HCIConnectionRef removeHCIConnection(HCIConnectionRefList_t& list, const uint16_t handle) noexcept;
339 HCIConnectionRef removeTrackerConnection(const uint16_t handle) noexcept {
340 return removeHCIConnection(connectionList, handle);
341 }
342 HCIConnectionRef removeDisconnectCmd(const uint16_t handle) noexcept {
343 return removeHCIConnection(disconnectCmdList, handle);
344 }
345
346 /** One MgmtAdapterEventCallbackList per event type, allowing multiple callbacks to be invoked for each event */
347 std::array<MgmtEventCallbackList, static_cast<uint16_t>(MgmtEvent::Opcode::MGMT_EVENT_TYPE_COUNT)> mgmtEventCallbackLists;
348 inline bool isValidMgmtEventCallbackListsIndex(const MgmtEvent::Opcode opc) const noexcept {
349 return static_cast<uint16_t>(opc) < mgmtEventCallbackLists.size();
350 }
351
352 HCISMPMsgCallbackList hciSMPMsgCallbackList;
353
354 std::unique_ptr<MgmtEvent> translate(HCIEvent& ev) noexcept;
355 std::unique_ptr<MgmtEvent> translate(HCICommand& ev) noexcept;
356
357 std::unique_ptr<const SMPPDUMsg> getSMPPDUMsg(const HCIACLData::l2cap_frame & l2cap, const uint8_t * l2cap_data) const noexcept;
358 void hciReaderWork(jau::service_runner& sr) noexcept;
359 void hciReaderEndLocked(jau::service_runner& sr) noexcept;
360
361 bool sendCommand(HCICommand &req, const bool quiet=false) noexcept;
362 std::unique_ptr<HCIEvent> getNextReply(HCICommand &req, int32_t & retryCount, const jau::fraction_i64& replyTimeout) noexcept;
363 std::unique_ptr<HCIEvent> getNextCmdCompleteReply(HCICommand &req, HCICommandCompleteEvent **res) noexcept;
364
365 std::unique_ptr<HCIEvent> processCommandStatus(HCICommand &req, HCIStatusCode *status, const bool quiet=false) noexcept;
366
367 template<typename hci_cmd_event_struct>
368 std::unique_ptr<HCIEvent> processCommandComplete(HCICommand &req,
369 const hci_cmd_event_struct **res, HCIStatusCode *status,
370 const bool quiet=false) noexcept;
371 template<typename hci_cmd_event_struct>
372 std::unique_ptr<HCIEvent> receiveCommandComplete(HCICommand &req,
373 const hci_cmd_event_struct **res, HCIStatusCode *status,
374 const bool quiet=false) noexcept;
375
376 template<typename hci_cmd_event_struct>
377 const hci_cmd_event_struct* getReplyStruct(HCIEvent& event, HCIEventType evc, HCIStatusCode *status) noexcept;
378
379 template<typename hci_cmd_event_struct>
380 const hci_cmd_event_struct* getMetaReplyStruct(HCIEvent& event, HCIMetaEventType mec, HCIStatusCode *status) noexcept;
381
382 public:
383 HCIHandler(const uint16_t dev_id, const BTMode btMode=BTMode::NONE) noexcept;
384
385 private:
386 void zeroSupCommands() noexcept;
387 bool initSupCommands() noexcept;
388
389 public:
390 HCIHandler(const HCIHandler&) = delete;
391 void operator=(const HCIHandler&) = delete;
392
393 /**
394 * Releases this instance after issuing {@link #close()}.
395 */
396 ~HCIHandler() noexcept { close(); }
397
398 void close() noexcept;
399
400 inline BTMode getBTMode() const noexcept { return btMode; }
401
402 inline void setBTMode(const BTMode mode) noexcept { btMode = mode; }
403
404 /** Returns true if this mgmt instance is open, connected and hence valid, otherwise false */
405 bool isOpen() const noexcept {
406 return true == allowClose.load() && comm.is_open();
407 }
408
409 /** Use extended scanning if HCI_LE_Set_Extended_Scan_Parameters and HCI_LE_Set_Extended_Scan_Enable is supported (Bluetooth 5.0). */
410 bool use_ext_scan() const noexcept {
411 return 0 != ( sup_commands[37] & ( 1 << 5 ) ) &&
412 0 != ( sup_commands[37] & ( 1 << 6 ) );
413 }
414
415 /** Use extended connection if HCI_LE_Extended_Create_Connection is supported (Bluetooth 5.0). */
416 bool use_ext_conn() const noexcept {
417 return 0 != ( sup_commands[37] & ( 1 << 7 ) );
418 }
419
420 bool use_resolv_add() const noexcept { return 0 != ( sup_commands[34] & ( 1 << 3 ) ); }
421 bool use_resolv_del() const noexcept { return 0 != ( sup_commands[34] & ( 1 << 4 ) ); }
422 bool use_resolv_clear() const noexcept { return 0 != ( sup_commands[34] & ( 1 << 5 ) ); }
423 bool use_resolv_size() const noexcept { return 0 != ( sup_commands[34] & ( 1 << 6 ) ); }
424 bool use_resolv_readPeerRA() const noexcept { return 0 != ( sup_commands[34] & ( 1 << 7 ) ); }
425 bool use_resolv_readLocalRA() const noexcept { return 0 != ( sup_commands[35] & ( 1 << 0 ) ); }
426 bool use_resolv_enable() const noexcept { return 0 != ( sup_commands[35] & ( 1 << 1 ) ); }
427
428 /** Use extended advertising if LE_Features::LE_Ext_Adv is set (Bluetooth 5.0). */
429 bool use_ext_adv() const noexcept {
430 return is_set(le_ll_feats, LE_Features::LE_Ext_Adv);
431 }
432
433 ScanType getCurrentScanType() const noexcept { return currentScanType.load(); }
434 void setCurrentScanType(const ScanType v) noexcept { currentScanType = v; }
435
436 /**
437 * Advertising is enabled via le_start_adv() or le_enable_adv().
438 *
439 * Advertising is active until either disabled via le_enable_adv(false) or a connection has been made.
440 *
441 * @return true if advertising is active, otherwise false.
442 */
443 bool isAdvertising() const noexcept { return advertisingEnabled.load(); }
444
445 std::string toString() const noexcept;
446
447 private:
448 /**
449 * Bring up this adapter into a POWERED functional state.
450 * <p>
451 * Currently used in resetAdapter() only.
452 * </p>
453 * @return HCIStatusCode
454 */
455 HCIStatusCode startAdapter();
456
457 /**
458 * Bring down this adapter into a non-POWERED non-functional state.
459 * <p>
460 * All allocated resources should be freed and the internal state being reset
461 * in compliance to
462 * <pre>
463 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.3.2 Reset command
464 * </pre>
465 * </p>
466 * <p>
467 * Currently used in resetAdapter() only.
468 * </p>
469 * @return HCIStatusCode
470 */
471 HCIStatusCode stopAdapter();
472
473 public:
474 /**
475 * Use post shutdown function, considered to be `noexcept`.
476 *
477 * `HCIStatusCode post_shutdown() noexcept`
478 *
479 * @return HCIStatusCode::SUCCESS to continue the process, otherwise to abort process.
480 */
481 typedef jau::function<HCIStatusCode() /* noexcept */> PostShutdownFunc;
482
483 /**
484 * Complete adapter reset.
485 *
486 * The semantics are specific to the HCI host implementation,
487 * however, it shall comply at least with the HCI Reset command.
488 *
489 * The adapter shall be shutdown into standby first, i.e. POWERED off,
490 * then the adapter should be brought up into a POWERED functional state afterwards.
491 *
492 * <pre>
493 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.3.2 Reset command
494 * </pre>
495 *
496 * @param user_post_shutdown optional custom user function to be executed after successful adapter shutdown.
497 * If function is not null and returns false, the adapter will not be brought up again.
498 *
499 * @return HCIStatusCode
500 */
501 HCIStatusCode resetAdapter(const PostShutdownFunc& user_post_shutdown);
502
503 /**
504 * Reset all internal states, i.e. connection and disconnect lists.
505 * <p>
506 * Must be explicitly called with `powered_on=true` when adapter is powered on!
507 * </p>
508 * @param powered_on indicates whether the adapter is powered on or not
509 * @see initSupCommands()
510 * @see resetAdapter()
511 */
512 bool resetAllStates(const bool powered_on) noexcept;
513
514 private:
515 HCIStatusCode resetHCI() noexcept;
516
517 public:
519
520 /**
521 * Return previously fetched LE_Features for the controller via initSupCommands() via resetAllStates()
522 * <pre>
523 * BT Core Spec v5.2: Vol 6, Part B, 4.6 (LE LL) Feature Support
524 *
525 * BT Core Spec v5.2: Vol 4, Part E, 7.8.3 LE Read Local Supported Features command
526 * </pre>
527 * @param res reference for the resulting LE_Features
528 * @return HCIStatusCode
529 * @see initSupCommands()
530 * @see resetAllStates()
531 */
532 LE_Features le_get_local_features() noexcept { return le_ll_feats; }
533
534 private:
535
536 /**
537 * Return HCIStatusCode::SUCCESS if isOpen() and the conn_handle is tracked
538 * and matching the give peerAddressAndType
539 *
540 * @param caller caller method base-name for DBG_ or ERR_PRINT.
541 * @param conn_handle
542 * @param peerAddressAndType
543 * @param addUntrackedConn true adds connection if not tracked,
544 * otherwise return HCIStatusCode::INVALID_HCI_COMMAND_PARAMETERS (default)
545 * @return HCIStatusCode
546 */
547 HCIStatusCode check_open_connection(const std::string& caller,
548 const uint16_t conn_handle, const BDAddressAndType& peerAddressAndType,
549 const bool addUntrackedConn = false);
550
551 public:
552 /**
553 * Request supported LE_Features from remote device.
554 * <pre>
555 * BT Core Spec v5.2: Vol 6, Part B, 4.6 (LE LL) Feature Support
556 *
557 * BT Core Spec v5.2: Vol 4, Part E, 7.8.21 LE Read Remote Features command
558 * </pre>
559 *
560 * Method returns immediate without result.
561 *
562 * Result is being delivered off-thread via HCIMetaEventType::LE_REMOTE_FEAT_COMPLETE, see
563 * <pre>
564 * BT Core Spec v5.2: Vol 4, Part E, 7.7.65.4 LE Read Remote Features Complete event
565 * </pre>
566 * @return HCIStatusCode
567 */
568 HCIStatusCode le_read_remote_features(const uint16_t conn_handle, const BDAddressAndType& peerAddressAndType) noexcept;
569
570 private:
571 /**
572 * Sets LE scanning parameters.
573 * <pre>
574 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.64 LE Set Extended Scan Parameters command (Bluetooth 5.0)
575 *
576 * if available, otherwise using
577 *
578 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.10 LE Set Scan Parameters command
579 *
580 *
581 * BT Core Spec v5.2: Vol 6 LE, Part B Link Layer: 4.4.3 Scanning State
582 * </pre>
583 * <p>
584 * Scan parameters control advertising (AD) Protocol Data Unit (PDU) delivery behavior.
585 * </p>
586 * <p>
587 * Should not be called while LE scanning is active, otherwise HCIStatusCode::COMMAND_DISALLOWED will be returned.
588 * </p>
589 *
590 * @param le_scan_active true enables delivery of active scanning PDUs, otherwise no scanning PDUs shall be sent (default)
591 * @param own_mac_type HCILEOwnAddressType::PUBLIC (default) or random/private.
592 * @param le_scan_interval in units of 0.625ms, default value 24 for 15ms; Value range [4 .. 0x4000] for [2.5ms .. 10.24s]
593 * @param le_scan_window in units of 0.625ms, default value 24 for 15ms; Value range [4 .. 0x4000] for [2.5ms .. 10.24s]. Shall be <= le_scan_interval
594 * @param filter_policy 0x00 accepts all PDUs (default), 0x01 only of whitelisted, ...
595 */
596 HCIStatusCode le_set_scan_param(const bool le_scan_active=false,
598 const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24,
599 const uint8_t filter_policy=0x00) noexcept;
600
601 public:
602 /**
603 * Starts or stops LE scanning.
604 * <pre>
605 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.65 LE Set Extended Scan Enable command (Bluetooth 5.0)
606 *
607 * if available, otherwise using
608 *
609 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.11 LE Set Scan Enable command
610 * </pre>
611 * @param enable true to enable discovery, otherwise false
612 * @param filter_dup true to filter out duplicate AD PDUs (default), otherwise all will be reported.
613 */
614 HCIStatusCode le_enable_scan(const bool enable, const bool filter_dup=true) noexcept;
615
616 /**
617 * Start LE scanning, i.e. performs le_set_scan_param() and le_enable_scan() in one atomic operation.
618 * <pre>
619 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.64 LE Set Extended Scan Parameters command (Bluetooth 5.0)
620 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.10 LE Set Scan Parameters command
621 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.65 LE Set Extended Scan Enable command (Bluetooth 5.0)
622 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.11 LE Set Scan Enable command
623 * </pre>
624 * <p>
625 * Scan parameters control advertising (AD) Protocol Data Unit (PDU) delivery behavior.
626 * </p>
627 * <p>
628 * Should not be called while LE scanning is active, otherwise HCIStatusCode::COMMAND_DISALLOWED will be returned.
629 * </p>
630 * <p>
631 * Method will report errors.
632 * </p>
633 *
634 * @param filter_dup true to filter out duplicate AD PDUs (default), otherwise all will be reported.
635 * @param le_scan_active true enables delivery of active scanning PDUs like EIR w/ device name (default), otherwise no scanning PDUs shall be sent.
636 * @param own_mac_type HCILEOwnAddressType::PUBLIC (default) or random/private.
637 * @param le_scan_interval in units of 0.625ms, default value 24 for 15ms; Value range [4 .. 0x4000] for [2.5ms .. 10.24s]
638 * @param le_scan_window in units of 0.625ms, default value 24 for 15ms; Value range [4 .. 0x4000] for [2.5ms .. 10.24s]. Shall be <= le_scan_interval
639 * @param filter_policy 0x00 accepts all PDUs (default), 0x01 only of whitelisted, ...
640 * @see le_read_local_features()
641 */
642 HCIStatusCode le_start_scan(const bool filter_dup=true,
643 const bool le_scan_active=true,
644 const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC,
645 const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24,
646 const uint8_t filter_policy=0x00) noexcept;
647
648 /**
649 * Establish a connection to the given LE peer.
650 * <pre>
651 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.66 LE Extended Create Connection command (Bluetooth 5.0)
652 *
653 * if available, otherwise using
654 *
655 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.12 LE Create Connection command
656 * </pre>
657 * <p>
658 * Set window to the same value as the interval, enables continuous scanning.
659 * </p>
660 * <p>
661 * The supervising timeout period is the time it takes before a devices gives up on the link if no packets are received.
662 * Hence this parameter influences the responsiveness on a link loss.
663 * A too small number may render the link too unstable, it should be at least 6 times of the connection interval.
664 * <br>
665 * To detect a link loss one can also send a regular ping to check whether the peripheral is still responding, see BTGattHandler::ping().
666 * </p>
667 * <p>
668 * Implementation tries to mitigate HCIStatusCode::COMMAND_DISALLOWED failure due to any pending connection commands,
669 * waiting actively up to HCIEnv::HCI_COMMAND_COMPLETE_REPLY_TIMEOUT, testing every HCIEnv::HCI_COMMAND_POLL_PERIOD if resolved.<br>
670 * <br>
671 * In case of no resolution, i.e. another HCI_LE_Create_Connection command is pending,
672 * HCIStatusCode::COMMAND_DISALLOWED will be returned by the underlying HCI host implementation.
673 * </p>
674 * <p>
675 * Implementation tries to mitigate HCIStatusCode::CONNECTION_ALREADY_EXISTS failure due to a specific pending disconnect command,
676 * waiting actively up to HCIEnv::HCI_COMMAND_COMPLETE_REPLY_TIMEOUT, testing every HCIEnv::HCI_COMMAND_POLL_PERIOD if resolved.<br>
677 * <br>
678 * In case of no resolution, i.e. the connection persists,
679 * HCIStatusCode::CONNECTION_ALREADY_EXISTS will be returned by the underlying HCI host implementation.
680 * </p>
681 * @param peer_bdaddr
682 * @param peer_mac_type
683 * @param own_mac_type
684 * @param le_scan_interval in units of 0.625ms, default value 24 for 15ms; Value range [4 .. 0x4000] for [2.5ms .. 10.24s]
685 * @param le_scan_window in units of 0.625ms, default value 24 for 15ms; Value range [4 .. 0x4000] for [2.5ms .. 10.24s]. Shall be <= le_scan_interval
686 * @param conn_interval_min in units of 1.25ms, default value 8 for 10ms; Value range [6 .. 3200] for [7.5ms .. 4000ms]
687 * @param conn_interval_max in units of 1.25ms, default value 12 for 15ms; Value range [6 .. 3200] for [7.5ms .. 4000ms]
688 * @param conn_latency slave latency in units of connection events, default value 0; Value range [0 .. 0x01F3]. See Range of [0 - getHCIMaxConnLatency()].
689 * @param supervision_timeout in units of 10ms, default value >= 10 x conn_interval_max; Value range [0xA-0x0C80] for [100ms - 32s]. We use 500ms minimum, i.e. getHCIConnSupervisorTimeout(0, 15, ::HCIConstInt::LE_CONN_MIN_TIMEOUT_MS).
690 * @return
691 */
692 HCIStatusCode le_create_conn(const EUI48 &peer_bdaddr,
693 const HCILEPeerAddressType peer_mac_type=HCILEPeerAddressType::PUBLIC,
694 const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC,
695 const uint16_t le_scan_interval=24, const uint16_t le_scan_window=24,
696 const uint16_t conn_interval_min=8, const uint16_t conn_interval_max=12,
697 const uint16_t conn_latency=0, const uint16_t supervision_timeout=getHCIConnSupervisorTimeout(0, 15)) noexcept;
698
699 /**
700 * Establish a connection to the given BREDR (non LE).
701 * <pre>
702 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.5 Create Connection command
703 * </pre>
704 * <p>
705 * Implementation tries to mitigate HCIStatusCode::COMMAND_DISALLOWED failure due to any pending connection commands,
706 * waiting actively up to HCIEnv::HCI_COMMAND_COMPLETE_REPLY_TIMEOUT, testing every HCIEnv::HCI_COMMAND_POLL_PERIOD if resolved.<br>
707 * <br>
708 * In case of no resolution, i.e. another HCI_Create_Connection command is pending,
709 * HCIStatusCode::COMMAND_DISALLOWED will be returned by the underlying HCI host implementation.
710 * </p>
711 * <p>
712 * Implementation tries to mitigate HCIStatusCode::CONNECTION_ALREADY_EXISTS failure due to a specific pending disconnect command,
713 * waiting actively up to HCIEnv::HCI_COMMAND_COMPLETE_REPLY_TIMEOUT, testing every HCIEnv::HCI_COMMAND_POLL_PERIOD if resolved.<br>
714 * <br>
715 * In case of no resolution, i.e. the connection persists,
716 * HCIStatusCode::CONNECTION_ALREADY_EXISTS will be returned by the underlying HCI host implementation.
717 * </p>
718 */
719 HCIStatusCode create_conn(const EUI48 &bdaddr,
720 const uint16_t pkt_type=HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5,
721 const uint16_t clock_offset=0x0000, const uint8_t role_switch=0x01) noexcept;
722
723 /**
724 * Disconnect an established connection.
725 * <pre>
726 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.1.6 Disconnect command
727 * </pre>
728 */
729 HCIStatusCode disconnect(const uint16_t conn_handle, const BDAddressAndType& peerAddressAndType,
730 const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION) noexcept;
731
732 /**
733 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.38 LE Add Device To Resolving List command
734 */
735 HCIStatusCode le_add_to_resolv_list(const BDAddressAndType& peerIdentityAddressAndType,
736 jau::uint128dp_t& peer_irk, jau::uint128dp_t& local_irk) noexcept;
737 /**
738 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.39 LE Remove Device From Resolving List command
739 */
740 HCIStatusCode le_del_from_resolv_list(const BDAddressAndType& peerIdentityAddressAndType) noexcept;
741 /**
742 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.40 LE Clear Resolving List command
743 */
745 /**
746 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.41 LE Read Resolving List Size command
747 */
748 HCIStatusCode le_read_resolv_list_size(uint32_t& size_res) noexcept;
749 /**
750 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.42 LE Read Peer Resolvable Address command
751 * <p>
752 * FIXME: May not be supported by Linux/BlueZ
753 * </p>
754 */
755 HCIStatusCode le_read_peer_resolv_addr(const BDAddressAndType& peerIdentityAddressAndType,
756 jau::EUI48& peerResolvableAddress) noexcept;
757 /**
758 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.43 LE Read Local Resolvable Address command
759 * <p>
760 * FIXME: May not be supported by Linux/BlueZ
761 * </p>
762 */
763 HCIStatusCode le_read_local_resolv_addr(const BDAddressAndType& peerIdentityAddressAndType,
764 jau::EUI48& localResolvableAddress) noexcept;
765 /**
766 * BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.44 LE Set Address Resolution Enable command
767 */
768 HCIStatusCode le_set_addr_resolv_enable(const bool enable) noexcept;
769
770 /**
771 * Request and return LE_PHYs bit for the given connection.
772 * <pre>
773 * BT Core Spec v5.2: Vol 4, Part E, 7.8.47 LE Read PHY command
774 * </pre>
775 *
776 * Controller shall send a pending HCIMetaEventType::LE_PHY_UPDATE_COMPLETE event with SUCCESS
777 * after issuing this command in all cases (change or unchanged PHYs).
778 *
779 * @param conn_handle
780 * @param addressAndType
781 * @param resTx reference for the resulting transmitter LE_PHYs bit
782 * @param resRx reference for the resulting receiver LE_PHYs bit
783 * @return HCIStatusCode
784 * @since 2.4.0
785 */
786 HCIStatusCode le_read_phy(const uint16_t conn_handle, const BDAddressAndType& peerAddressAndType,
787 LE_PHYs& resTx, LE_PHYs& resRx) noexcept;
788
789
790 /**
791 * Sets default preference of used LE_PHYs for all subsequent LE connections.
792 *
793 * BT Core Spec v5.2: Vol 4, Part E, 7.8.48 LE Set Default PHY command
794 *
795 * @param Tx transmitter LE_PHYs bit mask of preference if not set to LE_PHYs::NONE (ignored).
796 * @param Rx receiver LE_PHYs bit mask of preference if not set to LE_PHYs::NONE (ignored).
797 * @return
798 * @since 2.4.0
799 */
800 HCIStatusCode le_set_default_phy(const LE_PHYs Tx, const LE_PHYs Rx) noexcept;
801
802 /**
803 * Sets preference of used LE_PHYs for the given connection.
804 *
805 * - BT Core Spec v5.2: Vol 4, Part E, 7.8.49 LE Set PHY command
806 * - BT Core Spec v5.2: Vol 4, Part E, 7.7.65.12 LE PHY Update Complete event
807 *
808 * @param conn_handle
809 * @param peerAddressAndType
810 * @param Tx transmitter LE_PHYs bit mask of preference if not set to LE_PHYs::NONE (ignored).
811 * @param Rx receiver LE_PHYs bit mask of preference if not set to LE_PHYs::NONE (ignored).
812 * @return
813 * @since 2.4.0
814 */
815 HCIStatusCode le_set_phy(const uint16_t conn_handle, const BDAddressAndType& peerAddressAndType,
816 const LE_PHYs Tx, const LE_PHYs Rx) noexcept;
817
818 private:
819 /**
820 * Sets LE advertising parameters.
821 * <pre>
822 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.53 LE Set Extended Advertising Parameters command (Bluetooth 5.0)
823 *
824 * if available, otherwise using
825 *
826 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.5 LE Set Advertising Parameters command
827 * </pre>
828 * <p>
829 * Scan parameters control advertising (AD) Protocol Data Unit (PDU) delivery behavior.
830 * </p>
831 * <p>
832 * Should not be called while LE scanning is active, otherwise HCIStatusCode::COMMAND_DISALLOWED will be returned.
833 * </p>
834 *
835 * @param peer_bdaddr EUI48 of directed peer, defaults to EUI48::ANY_DEVICE (zero address)
836 * @param own_mac_type HCILEOwnAddressType::PUBLIC (default) or random/private.
837 * @param peer_mac_type HCILEOwnAddressType::PUBLIC (default) or random/private.
838 * @param adv_interval_min in units of 0.625ms, default value 0x0800 for 1.28s; Value range [0x0020 .. 0x4000] for [20ms .. 10.24s]
839 * @param adv_interval_max in units of 0.625ms, default value 0x0800 for 1.28s; Value range [0x0020 .. 0x4000] for [20ms .. 10.24s]
840 * @param adv_type see AD_PDU_Type, default ::AD_PDU_Type::ADV_IND
841 * @param adv_chan_map bit 0: chan 37, bit 1: chan 38, bit 2: chan 39, default is 0x07 (all 3 channels enabled)
842 * @param filter_policy 0x00 accepts all PDUs (default), 0x01 only of whitelisted, ...
843 */
844 HCIStatusCode le_set_adv_param(const EUI48 &peer_bdaddr=EUI48::ANY_DEVICE,
845 const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC,
846 const HCILEOwnAddressType peer_mac_type=HCILEOwnAddressType::PUBLIC,
847 const uint16_t adv_interval_min=0x0800, const uint16_t adv_interval_max=0x0800,
848 const AD_PDU_Type adv_type=AD_PDU_Type::ADV_IND,
849 const uint8_t adv_chan_map=0x07,
850 const uint8_t filter_policy=0x00) noexcept;
851
852 /**
853 * Sets LE advertising data
854 * <pre>
855 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.54 LE Set Extended Advertising Data command (Bluetooth 5.0)
856 *
857 * if available, otherwise using
858 *
859 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.7 LE Set Advertising Data command (Bluetooth 4.0)
860 * </pre>
861 *
862 * Advertising_Data_Length:
863 * - Bluetooth 4.0: 0 - 31 octets
864 * - Bluetooth 5.0: 0 - 251 octets, i.e. max-param 255 - 4 bytes cp-args
865 *
866 *
867 * @param eir EInfoReport full ADV EIR
868 * @param mask EIRDataType mask for EInfoReport to select advertisement EIR PDU data, defaults to EIRDataType::FLAGS | EIRDataType::NAME | EIRDataType::MANUF_DATA
869 * @return HCIStatusCode::SUCCESS if successful, otherwise the HCIStatusCode error state
870 */
871 HCIStatusCode le_set_adv_data(const EInfoReport &eir,
872 const EIRDataType mask = EIRDataType::FLAGS | EIRDataType::NAME | EIRDataType::MANUF_DATA) noexcept;
873
874 /**
875 * Sets LE scan-response data (active scanning)
876 * <pre>
877 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.55 LE Set Extended Scan Response Data command (Bluetooth 5.0)
878 *
879 * if available, otherwise using
880 *
881 * BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.8 LE Set Scan Response Data command (Bluetooth 4.0)
882 * </pre>
883 *
884 * Advertising_Data_Length:
885 * - Bluetooth 4.0: 0 - 31 octets
886 * - Bluetooth 5.0: 0 - 251 octets, i.e. max-param 255 - 4 bytes cp-args
887 *
888 * @param eir EInfoReport full ADV EIR
889 * @param mask EIRDataType mask for EInfoReport to select scan-response EIR PDU data, defaults to EIRDataType::SERVICE_UUID
890 * @return HCIStatusCode::SUCCESS if successful, otherwise the HCIStatusCode error state
891 */
892 HCIStatusCode le_set_scanrsp_data(const EInfoReport &eir,
893 const EIRDataType mask = EIRDataType::SERVICE_UUID) noexcept;
894
895 public:
896 /**
897 * Enables or disabled advertising.
898 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.56 LE Set Extended Advertising Enable command (Bluetooth 5.0)
899 *
900 * if available, otherwise using
901 *
902 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.9 LE Set Advertising Enable command
903 *
904 * Advertising is active until either disabled via le_enable_adv(false) or a connection has been made,
905 * see isAdvertising().
906 *
907 * @param enable
908 * @return HCIStatusCode::SUCCESS if successful, otherwise the HCIStatusCode error state
909 * @since 2.4.0
910 */
911 HCIStatusCode le_enable_adv(const bool enable) noexcept;
912
913 /**
914 * Starts advertising
915 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.53 LE Set Extended Advertising Parameters command (Bluetooth 5.0)
916 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.54 LE Set Extended Advertising Data command (Bluetooth 5.0)
917 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.55 LE Set Extended Scan Response Data command (Bluetooth 5.0)
918 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.56 LE Set Extended Advertising Enable command (Bluetooth 5.0)
919 *
920 * if available, otherwise using
921 *
922 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.5 LE Set Advertising Parameters command
923 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.7 LE Set Advertising Data command
924 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.8 LE Set Scan Response Data command
925 * - BT Core Spec v5.2: Vol 4 HCI, Part E HCI Functional: 7.8.9 LE Set Advertising Enable command
926 *
927 * Advertising is active until either disabled via le_enable_adv(false) or a connection has been made,
928 * see isAdvertising().
929 *
930 * TODO:
931 * - Random address for privacy if desired!
932 * - Consider SMP (security)
933 *
934 * @param eir Full ADV EIR EInfoReport
935 * @param adv_mask EIRDataType mask for EInfoReport to select advertisement EIR PDU data, defaults to EIRDataType::FLAGS | EIRDataType::SERVICE_UUID
936 * @param scanrsp_mask EIRDataType mask for EInfoReport to select scan-response (active scanning) EIR PDU data, defaults to EIRDataType::NAME | EIRDataType::CONN_IVAL
937 * @param peer_bdaddr EUI48 of directed peer, defaults to EUI48::ANY_DEVICE (zero address)
938 * @param own_mac_type HCILEOwnAddressType::PUBLIC (default) or random/private.
939 * @param peer_mac_type HCILEOwnAddressType::PUBLIC (default) or random/private.
940 * @param adv_interval_min in units of 0.625ms, default value 160 for 100ms; Value range [0x0020 .. 0x4000] for [20ms .. 10.24s]
941 * @param adv_interval_max in units of 0.625ms, default value 480 for 300ms; Value range [0x0020 .. 0x4000] for [20ms .. 10.24s]
942 * @param adv_type see AD_PDU_Type, default ::AD_PDU_Type::ADV_IND
943 * @param adv_chan_map bit 0: chan 37, bit 1: chan 38, bit 2: chan 39, default is 0x07 (all 3 channels enabled)
944 * @param filter_policy 0x00 accepts all PDUs (default), 0x01 only of whitelisted, ...
945 * @return HCIStatusCode::SUCCESS if successful, otherwise the HCIStatusCode error state
946 * @since 2.4.0
947 */
949 const EIRDataType adv_mask = EIRDataType::FLAGS | EIRDataType::SERVICE_UUID,
950 const EIRDataType scanrsp_mask = EIRDataType::NAME | EIRDataType::CONN_IVAL,
951 const EUI48 &peer_bdaddr=EUI48::ANY_DEVICE,
952 const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC,
953 const HCILEOwnAddressType peer_mac_type=HCILEOwnAddressType::PUBLIC,
954 const uint16_t adv_interval_min=160, const uint16_t adv_interval_max=480,
955 const AD_PDU_Type adv_type=AD_PDU_Type::ADV_IND,
956 const uint8_t adv_chan_map=0x07,
957 const uint8_t filter_policy=0x00) noexcept;
958
959 /** MgmtEventCallback handling */
960
961 /**
962 * Appends the given MgmtEventCallback to the named MgmtEvent::Opcode list,
963 * if it is not present already (opcode + callback).
964 * @param opc opcode index for callback list, the callback shall be added to
965 * @param cb the to be added callback
966 * @return true if newly added or already existing, false if given MgmtEvent::Opcode is out of supported range.
967 */
968 bool addMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept;
969 /** Returns count of removed given MgmtEventCallback from the named MgmtEvent::Opcode list. */
970 size_type removeMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept;
971 /** Removes all MgmtEventCallbacks from the to the named MgmtEvent::Opcode list. */
972 void clearMgmtEventCallbacks(const MgmtEvent::Opcode opc) noexcept;
973
974 void addSMPMsgCallback(const HCISMPMsgCallback & l);
976
977 /** Removes all MgmtEventCallbacks from all MgmtEvent::Opcode lists and all SMPSecurityReqCallbacks. */
978 void clearAllCallbacks() noexcept;
979
980 /** Manually send a MgmtEvent to all of its listeners. */
981 void sendMgmtEvent(const MgmtEvent& event) noexcept;
982 };
983
984 /**@}*/
985
986} // namespace direct_bt
987
988#if 0
989// Injecting specialization of std::hash to namespace std of our types above
990// Would need to make direct_bt::HCIHandler::HCIConnection accessible
991namespace std
992{
993 /** \addtogroup DBTSystemAPI
994 *
995 * @{
996 */
997
998 template<> struct hash<direct_bt::HCIHandler::HCIConnection> {
999 std::size_t operator()(direct_bt::HCIHandler::HCIConnection const& a) const noexcept {
1000 return a.hash_code();
1001 }
1002 };
1003
1004 /**@}*/
1005
1006}
1007#endif
1008
1009#endif /* HCI_HANDLER_HPP_ */
1010
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BTAddress.hpp:175
std::size_t hash_code() const noexcept
Implementation uses a lock-free volatile cache.
Definition: BTAddress.hpp:319
std::string toString() const noexcept
Definition: BTTypes0.cpp:186
Collection of 'Extended Advertising Data' (EAD), 'Advertising Data' (AD) or 'Extended Inquiry Respons...
Definition: BTTypes0.hpp:898
Read/Write HCI communication channel.
Definition: HCIComm.hpp:61
bool is_open() const noexcept
Definition: HCIComm.hpp:91
HCI Singleton runtime environment properties.
Definition: HCIHandler.hpp:74
static HCIEnv & get() noexcept
Definition: HCIHandler.hpp:150
const jau::fraction_i64 HCI_COMMAND_STATUS_REPLY_TIMEOUT
Timeout for HCI command status replies, excluding command complete, defaults to 3s.
Definition: HCIHandler.hpp:97
const jau::fraction_i64 HCI_READER_THREAD_POLL_TIMEOUT
Poll timeout for HCI reader thread, defaults to 10s.
Definition: HCIHandler.hpp:89
const int32_t HCI_EVT_RING_CAPACITY
Small ringbuffer capacity for synchronized commands, defaults to 64 messages.
Definition: HCIHandler.hpp:127
const bool DEBUG_EVENT
Debug all HCI event communication.
Definition: HCIHandler.hpp:135
const jau::fraction_i64 HCI_COMMAND_POLL_PERIOD
Poll period for certain HCI commands actively waiting for clearance, defaults to 125ms.
Definition: HCIHandler.hpp:119
const jau::fraction_i64 HCI_COMMAND_COMPLETE_REPLY_TIMEOUT
Timeout for HCI command complete replies, defaults to 10s.
Definition: HCIHandler.hpp:106
const bool DEBUG_SCAN_AD_EIR
Debug all scanned HCI 'Advertising Data' (AD) 'Extended Inquiry Response' (EIR) packages.
Definition: HCIHandler.hpp:143
A thread safe singleton handler of the HCI control channel to one controller (BT adapter)
Definition: HCIHandler.hpp:179
bool use_resolv_del() const noexcept
Definition: HCIHandler.hpp:421
bool use_resolv_readPeerRA() const noexcept
Definition: HCIHandler.hpp:424
bool use_ext_adv() const noexcept
Use extended advertising if LE_Features::LE_Ext_Adv is set (Bluetooth 5.0).
Definition: HCIHandler.hpp:429
void setBTMode(const BTMode mode) noexcept
Definition: HCIHandler.hpp:402
bool use_ext_conn() const noexcept
Use extended connection if HCI_LE_Extended_Create_Connection is supported (Bluetooth 5....
Definition: HCIHandler.hpp:416
bool use_resolv_clear() const noexcept
Definition: HCIHandler.hpp:422
bool isOpen() const noexcept
Returns true if this mgmt instance is open, connected and hence valid, otherwise false.
Definition: HCIHandler.hpp:405
std::shared_ptr< HCIConnection > HCIConnectionRef
Definition: HCIHandler.hpp:237
bool use_resolv_readLocalRA() const noexcept
Definition: HCIHandler.hpp:425
HCIStatusCode le_clear_resolv_list() noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.40 LE Clear Resolving List command.
HCIStatusCode le_read_remote_features(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType) noexcept
Request supported LE_Features from remote device.
Definition: HCIHandler.cpp:932
void close() noexcept
Definition: HCIHandler.cpp:949
bool isAdvertising() const noexcept
Advertising is enabled via le_start_adv() or le_enable_adv().
Definition: HCIHandler.hpp:443
jau::darray< HCIConnectionRef, size_type > HCIConnectionRefList_t
Definition: HCIHandler.hpp:238
HCIStatusCode le_enable_adv(const bool enable) noexcept
Enables or disabled advertising.
bool use_resolv_size() const noexcept
Definition: HCIHandler.hpp:423
HCIStatusCode le_enable_scan(const bool enable, const bool filter_dup=true) noexcept
Starts or stops LE scanning.
BTMode getBTMode() const noexcept
Definition: HCIHandler.hpp:400
bool use_resolv_add() const noexcept
Definition: HCIHandler.hpp:420
HCIStatusCode resetAdapter(const PostShutdownFunc &user_post_shutdown)
Complete adapter reset.
void clearAllCallbacks() noexcept
Removes all MgmtEventCallbacks from all MgmtEvent::Opcode lists and all SMPSecurityReqCallbacks.
bool addMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
MgmtEventCallback handling
HCIStatusCode le_read_resolv_list_size(uint32_t &size_res) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.41 LE Read Resolving List Size command.
void clearMgmtEventCallbacks(const MgmtEvent::Opcode opc) noexcept
Removes all MgmtEventCallbacks from the to the named MgmtEvent::Opcode list.
LE_Features le_get_local_features() noexcept
Return previously fetched LE_Features for the controller via initSupCommands() via resetAllStates()
Definition: HCIHandler.hpp:532
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).
jau::nsize_t size_type
Definition: HCIHandler.hpp:187
HCIStatusCode le_set_phy(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType, const LE_PHYs Tx, const LE_PHYs Rx) noexcept
Sets preference of used LE_PHYs for the given connection.
HCIStatusCode le_start_adv(const EInfoReport &eir, const EIRDataType adv_mask=EIRDataType::FLAGS|EIRDataType::SERVICE_UUID, const EIRDataType scanrsp_mask=EIRDataType::NAME|EIRDataType::CONN_IVAL, const EUI48 &peer_bdaddr=EUI48::ANY_DEVICE, const HCILEOwnAddressType own_mac_type=HCILEOwnAddressType::PUBLIC, const HCILEOwnAddressType peer_mac_type=HCILEOwnAddressType::PUBLIC, const uint16_t adv_interval_min=160, const uint16_t adv_interval_max=480, const AD_PDU_Type adv_type=AD_PDU_Type::ADV_IND, const uint8_t adv_chan_map=0x07, const uint8_t filter_policy=0x00) noexcept
Starts advertising.
HCIStatusCode le_read_phy(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType, LE_PHYs &resTx, LE_PHYs &resRx) noexcept
Request and return LE_PHYs bit for the given connection.
HCIStatusCode le_set_default_phy(const LE_PHYs Tx, const LE_PHYs Rx) noexcept
Sets default preference of used LE_PHYs for all subsequent LE connections.
HCIStatusCode le_start_scan(const bool filter_dup=true, const bool le_scan_active=true, 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.
bool resetAllStates(const bool powered_on) noexcept
Reset all internal states, i.e.
ScanType getCurrentScanType() const noexcept
Definition: HCIHandler.hpp:433
size_type removeMgmtEventCallback(const MgmtEvent::Opcode opc, const MgmtEventCallback &cb) noexcept
Returns count of removed given MgmtEventCallback from the named MgmtEvent::Opcode list.
void sendMgmtEvent(const MgmtEvent &event) noexcept
Manually send a MgmtEvent to all of its listeners.
Definition: HCIHandler.cpp:588
HCIStatusCode le_add_to_resolv_list(const BDAddressAndType &peerIdentityAddressAndType, jau::uint128dp_t &peer_irk, jau::uint128dp_t &local_irk) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.38 LE Add Device To Resolving List command.
HCIStatusCode getLocalVersion(HCILocalVersion &version) noexcept
HCIStatusCode le_set_addr_resolv_enable(const bool enable) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.44 LE Set Address Resolution Enable command.
HCIStatusCode le_read_peer_resolv_addr(const BDAddressAndType &peerIdentityAddressAndType, jau::EUI48 &peerResolvableAddress) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.42 LE Read Peer Resolvable Address command.
void addSMPMsgCallback(const HCISMPMsgCallback &l)
std::string toString() const noexcept
Definition: HCIHandler.cpp:976
void setCurrentScanType(const ScanType v) noexcept
Definition: HCIHandler.hpp:434
HCIStatusCode le_del_from_resolv_list(const BDAddressAndType &peerIdentityAddressAndType) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.39 LE Remove Device From Resolving List command.
const HCIEnv & env
Definition: HCIHandler.hpp:185
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=8, 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.
HCIStatusCode disconnect(const uint16_t conn_handle, const BDAddressAndType &peerAddressAndType, const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION) noexcept
Disconnect an established connection.
HCIStatusCode le_read_local_resolv_addr(const BDAddressAndType &peerIdentityAddressAndType, jau::EUI48 &localResolvableAddress) noexcept
BT Core Spec v5.2: Vol 4, Part E HCI: 7.8.43 LE Read Local Resolvable Address command.
bool use_resolv_enable() const noexcept
Definition: HCIHandler.hpp:426
void operator=(const HCIHandler &)=delete
HCIHandler(const uint16_t dev_id, const BTMode btMode=BTMode::NONE) noexcept
Definition: HCIHandler.cpp:686
size_type 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...
Definition: HCIHandler.hpp:410
void setResolvHCIConnectionAddr(const BDAddressAndType &visibleAddressAndType, const BDAddressAndType &addressAndType) noexcept
Definition: HCIHandler.hpp:298
uint16_t opcode, uint16_t dev-id, uint16_t param_size
Definition: MgmtTypes.hpp:1402
Handles the Security Manager Protocol (SMP) using Protocol Data Unit (PDU) encoded messages over L2CA...
Definition: SMPTypes.hpp:842
Persistent endian aware octet data, i.e.
Definition: octets.hpp:560
Class template jau::function is a general-purpose static-polymorphic function wrapper.
Ring buffer implementation, a.k.a circular buffer, exposing lock-free get*(..) and put*(....
Definition: ringbuffer.hpp:182
Base jau environment class, merely to tag all environment settings by inheritance and hence documenta...
Definition: environment.hpp:57
Service runner, a reusable dedicated thread performing custom user services.
static const uint8_t filter_policy
static const uint16_t le_scan_interval
static const uint16_t le_scan_window
static const bool filter_dup
static bool le_scan_active
static const uint16_t adv_interval_max
static const uint8_t adv_chan_map
static const uint16_t adv_interval_min
static const AD_PDU_Type adv_type
jau::cow_darray< HCISMPMsgCallback > HCISMPMsgCallbackList
Definition: HCIHandler.hpp:168
HCIEventType
BT Core Spec v5.2: Vol 4, Part E HCI: 7.7 Events.
Definition: HCITypes.hpp:308
HCIMetaEventType
BT Core Spec v5.2: Vol 4, Part E HCI: 7.7.65 LE Meta event.
Definition: HCITypes.hpp:350
jau::function< void(const BDAddressAndType &, const SMPPDUMsg &, const HCIACLData::l2cap_frame &)> HCISMPMsgCallback
Definition: HCIHandler.hpp:167
@ PACKET_MAX_SIZE
Total packet size, guaranteed to be handled by adapter.
bool operator==(const BTAdapter &lhs, const BTAdapter &rhs) noexcept
Definition: BTAdapter.hpp:1348
BTMode
Bluetooth adapter operating mode.
Definition: BTTypes0.hpp:112
LE_Features
HCI Supported Commands.
Definition: BTTypes0.hpp:162
LE_PHYs
LE Transport PHY bit values.
Definition: BTTypes0.hpp:231
HCILEPeerAddressType
HCI LE Address-Type is PUBLIC: 0x00, RANDOM: 0x01.
Definition: BTAddress.hpp:135
ScanType
Meta ScanType as derived from BTMode, with defined value mask consisting of BDAddressType bits.
Definition: BTTypes0.hpp:350
AD_PDU_Type
LE Advertising (AD) Protocol Data Unit (PDU) Types.
Definition: BTTypes0.hpp:397
bool operator!=(const BTAdapter &lhs, const BTAdapter &rhs) noexcept
Definition: BTAdapter.hpp:1351
constexpr uint16_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...
Definition: HCITypes.hpp:102
HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Definition: HCITypes.hpp:138
constexpr bool is_set(const LE_Features mask, const LE_Features bit) noexcept
Definition: BTTypes0.hpp:219
constexpr uint8_t number(const DiscoveryPolicy rhs) noexcept
Definition: BTAdapter.hpp:100
EIRDataType
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
Definition: BTTypes0.hpp:838
@ PUBLIC
Public Device Address.
std::enable_if< std::is_floating_point_v< T >, bool >::type constexpr equals(const T &a, const T &b, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if both values are equal, i.e.
Definition: float_math.hpp:394
fraction< int64_t > fraction_i64
fraction using int64_t as integral type
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
void set_bit_uint32(const uint8_t nr, uint32_t &mask)
void set_bit_uint64(const uint8_t nr, uint64_t &mask)
uint64_t test_bit_uint64(const uint8_t nr, const uint64_t mask)
uint32_t test_bit_uint32(const uint8_t nr, const uint32_t mask)
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
STL namespace.
Representing ACL Datas' L2CAP Frame.
Definition: HCITypes.hpp:977
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: eui48.hpp:324
CXX_ALWAYS_INLINE _Tp load() const noexcept