Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
DBGattServer.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2021 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 DB_GATT_SERVER_HPP_
27#define DB_GATT_SERVER_HPP_
28
29#include <cstring>
30#include <string>
31#include <memory>
32#include <cstdint>
33#include <mutex>
34#include <atomic>
35#include <initializer_list>
36
37#include <jau/java_uplink.hpp>
38#include <jau/octets.hpp>
39#include <jau/darray.hpp>
40#include <jau/cow_darray.hpp>
41#include <jau/uuid.hpp>
43
44#include "BTTypes0.hpp"
45#include "ATTPDUTypes.hpp"
46
47#include "BTTypes1.hpp"
48
49// #include "BTGattDesc.hpp"
50#include "BTGattChar.hpp"
51#include "jau/int_types.hpp"
52// #include "BTGattService.hpp"
53
54// #define JAU_TRACE_DBGATT 1
55#ifdef JAU_TRACE_DBGATT
56 #define JAU_TRACE_DBGATT_PRINT(...) { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); fflush(stderr); }
57#else
58 #define JAU_TRACE_DBGATT_PRINT(...)
59#endif
60
61/**
62 * - - - - - - - - - - - - - - -
63 *
64 * Module DBGattServer covering the GattServer elements:
65 *
66 * - BT Core Spec v5.2: Vol 3, Part G Generic Attribute Protocol (GATT)
67 * - BT Core Spec v5.2: Vol 3, Part G GATT: 2.6 GATT Profile Hierarchy
68 */
69namespace direct_bt {
70
71 class BTDevice; // forward
72 typedef std::shared_ptr<BTDevice> BTDeviceRef;
73
74 /** @defgroup DBTUserServerAPI Direct-BT Peripheral-Server User Level API
75 * User level Direct-BT API types and functionality addressing the peripheral-server ::GATTRole::Server perspective,
76 * , [see Direct-BT Overview](namespacedirect__bt.html#details).
77 *
78 * @{
79 */
80
81 class DBGattService; // fwd
82
83 /**
84 * Representing a Gatt Characteristic Descriptor object from the ::GATTRole::Server perspective.
85 *
86 * A list of shared DBGattDesc instances are passed at DBGattChar construction
87 * and are retrievable via DBGattChar::getDescriptors().
88 *
89 * See [Direct-BT Overview](namespacedirect__bt.html#details).
90 *
91 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3 Characteristic Descriptor
92 *
93 * @since 2.4.0
94 */
96 private:
97 friend DBGattService;
98
99 uint16_t handle;
100
101 std::shared_ptr<const jau::uuid_t> type;
102
103 jau::POctets value;
104
105 bool variable_length;
106
107 public:
108 /**
109 * Characteristic Descriptor Handle
110 * <p>
111 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
112 * </p>
113 */
114 uint16_t getHandle() const noexcept { return handle; }
115
116 /** Type of descriptor */
117 std::shared_ptr<const jau::uuid_t>& getType() noexcept { return type; }
118
119 /** Type of descriptor */
120 std::shared_ptr<const jau::uuid_t> getType() const noexcept { return type; }
121
122 /**
123 * True if value is of variable length, otherwise fixed length.
124 */
125 bool hasVariableLength() const noexcept { return variable_length; }
126
127 /**
128 * Get reference of this characteristic descriptor's value.
129 *
130 * Its capacity defines the maximum writable variable length
131 * and its size defines the maximum writable fixed length.
132 */
133 jau::POctets& getValue() noexcept { return value; }
134
135 /**
136 * Set this characteristic descriptor's value.
137 *
138 * Methods won't exceed the value's capacity if it is of hasVariableLength()
139 * or the value's size otherwise.
140 *
141 * @param source data to be written to this value
142 * @param source_len length of the source data to be written
143 * @param dest_pos position where the source data shall be written to the value
144 * @return true if successful, otherwise false for exceeding the value's limits.
145 */
146 bool setValue(const uint8_t* source, const jau::nsize_t source_len, const jau::nsize_t dest_pos) noexcept;
147
148 static std::string java_class() noexcept {
149 return std::string(JAVA_MAIN_PACKAGE "DBGattDesc");
150 }
151
152 std::string get_java_class() const noexcept override {
153 return java_class();
154 }
155
156 ~DBGattDesc() noexcept override {
157 JAU_TRACE_DBGATT_PRINT("DBGattDesc dtor0: %p", this);
158 }
159
160 /**
161 *
162 * @param type_
163 * @param value_ the data, which length defines the maximum writable fixed length if variable_length is false.
164 * If variable length is true, its capacity limits the maximum writable length.
165 * Forced to false if isExtendedProperties() or isClientCharConfig().
166 * @param variable_length_ defaults to false.
167 */
168 DBGattDesc(std::shared_ptr<const jau::uuid_t> type_,
169 jau::POctets && value_, bool variable_length_=false) noexcept
170 : handle(0), type(std::move(type_)), value( std::move( value_ ) ), variable_length(variable_length_)
171 {
172 if( variable_length && ( isExtendedProperties() || isClientCharConfig() ) ) {
173 variable_length = false;
174 }
175 JAU_TRACE_DBGATT_PRINT("DBGattDesc ctor0, value-move: %p", this);
176 }
177
178 /**
179 * Copy constructor preserving the capacity of the value
180 * @param o
181 */
183 : jau::jni::JavaUplink(o),
184 handle(o.handle), type(o.type),
185 value(o.value, o.value.capacity()),
186 variable_length(o.variable_length)
187 {
188 JAU_TRACE_DBGATT_PRINT("DBGattDesc ctor-cpy0: %p -> %p", &o, this);
189 }
190
191 /**
192 * Move constructor
193 * @param o POctet source to be taken over
194 */
195 DBGattDesc(DBGattDesc &&o) noexcept
196 : handle(o.handle), type(std::move(o.type)),
197 value(std::move(o.value)),
198 variable_length(o.variable_length)
199 {
200 JAU_TRACE_DBGATT_PRINT("DBGattDesc ctor-move0: %p -> %p", &o, this);
201 }
202
203 /**
204 * Return a newly constructed Client Characteristic Configuration
205 * with a zero uint16_t value of fixed length.
206 * @see isClientCharConfig()
207 */
208 static std::shared_ptr<DBGattDesc> createClientCharConfig() {
210 p.put_uint16_nc(0, 0);
211 return std::make_shared<DBGattDesc>( BTGattDesc::TYPE_CCC_DESC, std::move(p), false /* variable_length */ );
212 }
213
214 /** Fill value with zero bytes. */
215 void bzero() noexcept {
216 value.bzero();
217 }
218
219 /** Value is uint16_t bitfield */
220 bool isExtendedProperties() const noexcept { return *BTGattDesc::TYPE_EXT_PROP == *type; }
221
222 /* BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration (Characteristic Descriptor, optional, single, uint16_t bitfield) */
223 bool isClientCharConfig() const noexcept{ return *BTGattDesc::TYPE_CCC_DESC == *type; }
224
225 /* BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.2 Characteristic User Description */
226 bool isUserDescription() const noexcept{ return *BTGattDesc::TYPE_USER_DESC == *type; }
227
228 std::string toString() const noexcept override {
229 const std::string len = variable_length ? "var" : "fixed";
230 return "Desc[type 0x"+type->toString()+", handle "+jau::to_hexstring(handle)+
231 ", value[len "+len+
232 ", "+value.toString()+
233 " '" + jau::dfa_utf8_decode( value.get_ptr(), value.size() ) + "'"+
234 "], "+javaObjectToString()+"]";
235 }
236 };
237 inline bool operator==(const DBGattDesc& lhs, const DBGattDesc& rhs) noexcept
238 { return lhs.getHandle() == rhs.getHandle(); /** unique attribute handles */ }
239
240 inline bool operator!=(const DBGattDesc& lhs, const DBGattDesc& rhs) noexcept
241 { return !(lhs == rhs); }
242
243 typedef std::shared_ptr<DBGattDesc> DBGattDescRef;
244
245 /**
246 * Representing a Gatt Characteristic object from the ::GATTRole::Server perspective.
247 *
248 * A list of shared DBGattChar instances are passed at DBGattService construction
249 * and are retrievable via DBGattService::getCharacteristics().
250 *
251 * See [Direct-BT Overview](namespacedirect__bt.html#details).
252 *
253 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3 Characteristic Definition
254 *
255 * handle -> CDAV value
256 *
257 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.6.1 Discover All Characteristics of a Service
258 *
259 * The handle represents a service's characteristics-declaration
260 * and the value the Characteristics Property, Characteristics Value Handle _and_ Characteristics UUID.
261 *
262 * @since 2.4.0
263 */
265 private:
266 friend DBGattService;
267
268 bool enabledNotifyState = false;
269 bool enabledIndicateState = false;
270
271 uint16_t handle;
272
273 uint16_t end_handle;
274
275 uint16_t value_handle;
276
277 std::shared_ptr<const jau::uuid_t> value_type;
278
280
281 jau::darray<DBGattDescRef> descriptors;
282
283 jau::POctets value;
284
285 bool variable_length;
286
287 int clientCharConfigIndex;
288
289 int userDescriptionIndex;
290
291 public:
292 /**
293 * Characteristic Handle of this instance.
294 * <p>
295 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
296 * </p>
297 */
298 uint16_t getHandle() const noexcept { return handle; }
299
300 /**
301 * Characteristic end handle, inclusive.
302 * <p>
303 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
304 * </p>
305 */
306 uint16_t getEndHandle() const noexcept { return end_handle; }
307
308 /**
309 * Characteristics Value Handle.
310 * <p>
311 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
312 * </p>
313 */
314 uint16_t getValueHandle() const noexcept { return value_handle; }
315
316 /* Characteristics Value Type UUID */
317 std::shared_ptr<const jau::uuid_t>& getValueType() noexcept { return value_type; }
318
319 /* Characteristics Value Type UUID */
320 std::shared_ptr<const jau::uuid_t> getValueType() const noexcept { return value_type; }
321
322 /* Characteristics Property */
323 BTGattChar::PropertyBitVal getProperties() const noexcept { return properties; }
324
325 /** List of Characteristic Descriptions. */
326 jau::darray<DBGattDescRef>& getDescriptors() noexcept { return descriptors; }
327
328 /**
329 * True if value is of variable length, otherwise fixed length.
330 */
331 bool hasVariableLength() const noexcept { return variable_length; }
332
333 /**
334 * Get reference of this characteristics's value.
335 *
336 * Its capacity defines the maximum writable variable length
337 * and its size defines the maximum writable fixed length.
338 */
339 jau::POctets& getValue() noexcept { return value; }
340
341 /**
342 * Set this characteristics's value.
343 *
344 * Methods won't exceed the value's capacity if it is of hasVariableLength()
345 * or the value's size otherwise.
346 *
347 * @param source data to be written to this value
348 * @param source_len length of the source data to be written
349 * @param dest_pos position where the source data shall be written to the value
350 * @return true if successful, otherwise false for exceeding the value's limits.
351 */
352 bool setValue(const uint8_t* source, const jau::nsize_t source_len, const jau::nsize_t dest_pos) noexcept;
353
354 /* Optional Client Characteristic Configuration index within descriptorList */
355 int getClientCharConfigIndex() const noexcept { return clientCharConfigIndex; }
356
357 /* Optional Characteristic User Description index within descriptorList */
358 int getUserDescriptionIndex() const noexcept { return userDescriptionIndex; }
359
360 static std::string java_class() noexcept {
361 return std::string(JAVA_MAIN_PACKAGE "DBGattChar");
362 }
363
364 std::string get_java_class() const noexcept override {
365 return java_class();
366 }
367
368 ~DBGattChar() noexcept override {
369 JAU_TRACE_DBGATT_PRINT("DBGattChar dtor0: %p", this);
370 }
371
372 /**
373 *
374 * @param value_type_
375 * @param properties_
376 * @param descriptors_
377 * @param value_ the data, which length defines the maximum writable fixed length if variable_length is false.
378 * If variable length is true, its capacity limits the maximum writable length.
379 * @param variable_length_ defaults to false.
380 *
381 */
382 DBGattChar(std::shared_ptr<const jau::uuid_t> value_type_,
383 const BTGattChar::PropertyBitVal properties_,
384 jau::darray<DBGattDescRef> && descriptors_,
385 jau::POctets && value_, bool variable_length_=false) noexcept
386 : handle(0), end_handle(0), value_handle(0),
387 value_type(std::move(value_type_)),
388 properties(properties_),
389 descriptors( std::move( descriptors_ ) ),
390 value( std::move( value_ ) ), variable_length(variable_length_),
391 clientCharConfigIndex(-1),
392 userDescriptionIndex(-1)
393 {
394 int i=0;
395 // C++11: Range-based for loop: [begin, end[
396 for(const DBGattDescRef& d : descriptors) {
397 if( 0 > clientCharConfigIndex && d->isClientCharConfig() ) {
398 clientCharConfigIndex=i;
399 } else if( 0 > userDescriptionIndex && d->isUserDescription() ) {
400 userDescriptionIndex=i;
401 }
402 ++i;
403 }
404 JAU_TRACE_DBGATT_PRINT("DBGattChar: ctor0, descr-move: %p", this);
405 }
406
407 /**
408 * Copy constructor preserving the capacity of the value
409 * @param o
410 */
412 : jau::jni::JavaUplink(o),
413 handle(o.handle), end_handle(o.end_handle),
414 value_handle(o.value_handle), value_type(o.value_type),
415 properties(o.properties),
416 descriptors(o.descriptors),
417 value(o.value, o.value.capacity()),
418 variable_length(o.variable_length),
419 clientCharConfigIndex(o.clientCharConfigIndex),
420 userDescriptionIndex(o.userDescriptionIndex)
421 {
422 JAU_TRACE_DBGATT_PRINT("DBGattChar: ctor-copy0: %p -> %p", &o, this);
423 }
424
425 /**
426 * Move constructor
427 * @param o POctet source to be taken over
428 */
429 DBGattChar(DBGattChar &&o) noexcept
430 : handle(o.handle), end_handle(o.end_handle),
431 value_handle(o.value_handle), value_type(std::move(o.value_type)),
432 properties(o.properties),
433 descriptors(std::move(o.descriptors)),
434 value(std::move(o.value)),
435 variable_length(o.variable_length),
436 clientCharConfigIndex(o.clientCharConfigIndex),
437 userDescriptionIndex(o.userDescriptionIndex)
438 {
439 JAU_TRACE_DBGATT_PRINT("DBGattChar: ctor-move0: %p -> %p", &o, this);
440 }
441
442 bool hasProperties(const BTGattChar::PropertyBitVal v) const noexcept { return v == ( properties & v ); }
443
444 /** Fill value with zero bytes. */
445 void bzero() noexcept {
446 value.bzero();
447 }
448
449 const DBGattDescRef getClientCharConfig() const noexcept {
450 if( 0 > clientCharConfigIndex ) {
451 return nullptr;
452 }
453 return descriptors.at(static_cast<size_t>(clientCharConfigIndex)); // abort if out of bounds
454 }
455
456 const DBGattDescRef getUserDescription() const noexcept {
457 if( 0 > userDescriptionIndex ) {
458 return nullptr;
459 }
460 return descriptors.at(static_cast<size_t>(userDescriptionIndex)); // abort if out of bounds
461 }
463 if( 0 > clientCharConfigIndex ) {
464 return nullptr;
465 }
466 return descriptors.at(static_cast<size_t>(clientCharConfigIndex)); // abort if out of bounds
467 }
468
470 if( 0 > userDescriptionIndex ) {
471 return nullptr;
472 }
473 return descriptors.at(static_cast<size_t>(userDescriptionIndex)); // abort if out of bounds
474 }
475
476 std::string toString() const noexcept override {
477 std::string char_name, notify_str;
478 {
480 if( nullptr != ud ) {
481 char_name = ", '" + jau::dfa_utf8_decode( ud->getValue().get_ptr(), ud->getValue().size() ) + "'";
482 }
483 }
485 notify_str = ", enabled[notify "+std::to_string(enabledNotifyState)+", indicate "+std::to_string(enabledIndicateState)+"]";
486 }
487 const std::string len = variable_length ? "var" : "fixed";
488 return "Char[handle ["+jau::to_hexstring(handle)+".."+jau::to_hexstring(end_handle)+
489 "], props "+jau::to_hexstring(properties)+" "+to_string(properties)+
490 char_name+", value[type 0x"+value_type->toString()+", handle "+jau::to_hexstring(value_handle)+", len "+len+
491 ", "+value.toString()+
492 " '" + jau::dfa_utf8_decode( value.get_ptr(), value.size() ) + "'"+
493 "], ccd-idx "+std::to_string(clientCharConfigIndex)+notify_str+
494 ", "+javaObjectToString()+"]";
495 }
496 };
497 inline bool operator==(const DBGattChar& lhs, const DBGattChar& rhs) noexcept
498 { return lhs.getHandle() == rhs.getHandle() && lhs.getEndHandle() == rhs.getEndHandle(); /** unique attribute handles */ }
499
500 inline bool operator!=(const DBGattChar& lhs, const DBGattChar& rhs) noexcept
501 { return !(lhs == rhs); }
502
503 typedef std::shared_ptr<DBGattChar> DBGattCharRef;
504
505 /** Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values. */
506 inline jau::POctets make_gvalue(const char* name) {
507 return jau::POctets( (const uint8_t*)name, (jau::nsize_t)strlen(name), jau::lb_endian_t::little );
508 }
509
510 /** Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values. */
511 inline jau::POctets make_gvalue(const char* name, const jau::nsize_t capacity) {
512 const jau::nsize_t name_len = (jau::nsize_t)strlen(name);
513 jau::POctets p( std::max<jau::nsize_t>(capacity, name_len), name_len, jau::lb_endian_t::little );
514 p.bzero();
515 p.put_bytes_nc(0, reinterpret_cast<const uint8_t*>(name), name_len);
516 return p;
517 }
518
519 /** Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values. */
520 inline jau::POctets make_gvalue(const uint16_t v) {
522 p.put_uint16_nc(0, v);
523 return p;
524 }
525
526 /** Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values. */
527 inline jau::POctets make_gvalue(const jau::nsize_t capacity, const jau::nsize_t size) {
528 jau::POctets p(capacity, size, jau::lb_endian_t::little);
529 p.bzero();
530 return p;
531 }
532
533 /** Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values. */
534 inline jau::POctets make_gvalue(std::initializer_list<uint8_t> sourcelist) {
535 return jau::POctets(sourcelist, jau::lb_endian_t::little);
536 }
537
538 /** Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values. */
539 inline jau::POctets make_gvalue(const jau::nsize_t capacity, const jau::nsize_t size, std::initializer_list<uint8_t> sourcelist) {
540 jau::POctets p(capacity, size, jau::lb_endian_t::little);
541 p.bzero();
542 const jau::nsize_t max_size = std::min(size, sourcelist.size());
543 if( 0 < max_size ) {
544 std::memcpy(p.get_wptr(), sourcelist.begin(), max_size);
545 }
546 return p;
547 }
548
549 /**
550 * Representing a Gatt Service object from the ::GATTRole::Server perspective.
551 *
552 * A list of shared DBGattService instances are passed at DBGattServer construction
553 * and are retrievable via DBGattServer::getServices().
554 *
555 * See [Direct-BT Overview](namespacedirect__bt.html#details).
556 *
557 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.1 Service Definition
558 *
559 * Includes a complete [Primary] Service Declaration
560 * including its list of Characteristic Declarations,
561 * which also may include its client config if available.
562 *
563 * @since 2.4.0
564 */
566 private:
567 bool primary;
568
569 uint16_t handle;
570
571 uint16_t end_handle;
572
573 std::shared_ptr<const jau::uuid_t> type;
574
575 jau::darray<DBGattCharRef> characteristics;
576
577 public:
578 /**
579 * Indicate whether this service is a primary service.
580 */
581 bool isPrimary() const noexcept { return primary; }
582
583 /**
584 * Service start handle
585 * <p>
586 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
587 * </p>
588 */
589 uint16_t getHandle() const noexcept { return handle; }
590
591 /**
592 * Service end handle, inclusive.
593 * <p>
594 * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
595 * </p>
596 */
597 uint16_t getEndHandle() const noexcept { return end_handle; }
598
599 /** Service type UUID */
600 std::shared_ptr<const jau::uuid_t>& getType() noexcept { return type; }
601
602 /** Service type UUID */
603 std::shared_ptr<const jau::uuid_t> getType() const noexcept { return type; }
604
605 /** List of Characteristic Declarations. */
606 jau::darray<DBGattCharRef>& getCharacteristics() noexcept { return characteristics; }
607
608 static std::string java_class() noexcept {
609 return std::string(JAVA_MAIN_PACKAGE "DBGattService");
610 }
611
612 std::string get_java_class() const noexcept override {
613 return java_class();
614 }
615
616 ~DBGattService() noexcept override {
617 JAU_TRACE_DBGATT_PRINT("DBGattService dtor0: %p", this);
618 }
619
620 DBGattService(const bool primary_,
621 std::shared_ptr<const jau::uuid_t> type_,
622 jau::darray<DBGattCharRef> && characteristics_)
623 : primary(primary_), handle(0), end_handle(0),
624 type(std::move(type_)),
625 characteristics( std::move( characteristics_ ) )
626 { }
627
628 DBGattService(const DBGattService &o) = default;
629 DBGattService(DBGattService &&o) noexcept = default;
630
631 DBGattCharRef findGattChar(const jau::uuid_t& char_uuid) noexcept {
632 for(DBGattCharRef& c : characteristics) {
633 if( char_uuid.equivalent( *c->value_type ) ) {
634 return c;
635 }
636 }
637 return nullptr;
638 }
639 DBGattCharRef findGattCharByValueHandle(const uint16_t char_value_handle) noexcept {
640 for(DBGattCharRef& c : characteristics) {
641 if( char_value_handle == c->value_handle ) {
642 return c;
643 }
644 }
645 return nullptr;
646 }
647
648 /**
649 * Sets all handles of this service instance and all its owned childs,
650 * i.e. DBGattChars elements and its DBGattDesc elements.
651 *
652 * @param start_handle a valid and unique start handle number > 0
653 * @return number of set handles, i.e. `( end_handle - handle ) + 1`
654 */
655 int setHandles(const uint16_t start_handle) {
656 if( 0 == start_handle ) {
657 handle = 0;
658 end_handle = 0;
659 return 0;
660 }
661 uint16_t h = start_handle;
662 handle = h++;
663 for(DBGattCharRef& c : characteristics) {
664 c->handle = h++;
665 c->value_handle = h++;
666 for(DBGattDescRef& d : c->descriptors) {
667 d->handle = h++;
668 }
669 c->end_handle = h-1;
670 }
671 end_handle = h-1;
672 return ( end_handle - handle ) + 1;
673 }
674
675 std::string toString() const noexcept override {
676 return "Srvc[type 0x"+type->toString()+", handle ["+jau::to_hexstring(handle)+".."+jau::to_hexstring(end_handle)+"], "+
677 std::to_string(characteristics.size())+" chars, "+javaObjectToString()+"]";
678
679 }
680 };
681 inline bool operator==(const DBGattService& lhs, const DBGattService& rhs) noexcept
682 { return lhs.getHandle() == rhs.getHandle() && lhs.getEndHandle() == rhs.getEndHandle(); /** unique attribute handles */ }
683
684 inline bool operator!=(const DBGattService& lhs, const DBGattService& rhs) noexcept
685 { return !(lhs == rhs); }
686
687 typedef std::shared_ptr<DBGattService> DBGattServiceRef;
688
689 /**
690 * Representing a complete list of Gatt Service objects from the ::GATTRole::Server perspective,
691 * i.e. the Gatt Server database.
692 *
693 * One instance shall be attached to BTAdapter when advertising via BTAdapter::startAdvertising(),
694 * changing its operating mode to Gatt Server mode, i.e. ::GATTRole::Server.
695 *
696 * The instance can also be retrieved via BTAdapter::getGATTServerData().
697 *
698 * See [Direct-BT Overview](namespacedirect__bt.html#details).
699 *
700 * This class is not thread safe and only intended to be prepared
701 * by the user at startup and processed by the Gatt Server facility.
702 *
703 * @since 2.4.0
704 */
706 public:
707 /**
708 * Operating mode of a DBGattServer instance.
709 */
710 enum class Mode : uint8_t {
711 /** No operation mode, i.e. w/o any DBGattService. */
712 NOP = 0,
713
714 /** Database mode, the default operating on given list of DBGattService. */
715 DB = 1,
716
717 /** Forward mode, acting as a proxy forwarding all requests to a 3rd remote GATT server BTDevice. */
718 FWD = 2
719 };
720 static std::string toModeString(const Mode m) noexcept;
721
722 /**
723 * Listener to remote master device's operations on the local GATT-Server.
724 *
725 * All methods shall return as soon as possible to not block GATT event processing.
726 */
727 class Listener {
728 public:
729 virtual ~Listener() = default;
730
731 /**
732 * Notification that device got connected.
733 *
734 * Convenient user entry, allowing to setup resources.
735 *
736 * @param device the connected device
737 * @param initialMTU initial used minimum MTU until negotiated.
738 */
739 virtual void connected(const BTDeviceRef& device, const uint16_t initialMTU) = 0;
740
741 /**
742 * Notification that device got disconnected.
743 *
744 * Convenient user entry, allowing to clean up resources.
745 *
746 * @param device the disconnected device.
747 */
748 virtual void disconnected(const BTDeviceRef& device) = 0;
749
750 /**
751 * Notification that the MTU has changed.
752 *
753 * @param device the device for which the MTU has changed
754 * @param mtu the new negotiated MTU
755 */
756 virtual void mtuChanged(const BTDeviceRef& device, const uint16_t mtu) = 0;
757
758 /**
759 * Signals attempt to read a value.
760 *
761 * Callee shall accept the read request by returning true, otherwise false.
762 *
763 * @param device
764 * @param s
765 * @param c
766 * @return true if master read has been accepted by GATT-Server listener, otherwise false. Only if all listener return true, the read action will be allowed.
767 */
768 virtual bool readCharValue(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c) = 0;
769
770 /**
771 * Signals attempt to read a value.
772 *
773 * Callee shall accept the read request by returning true, otherwise false.
774 *
775 * @param device
776 * @param s
777 * @param c
778 * @param d
779 * @return true if master read has been accepted by GATT-Server listener, otherwise false. Only if all listener return true, the read action will be allowed.
780 */
781 virtual bool readDescValue(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c, const DBGattDescRef& d) = 0;
782
783 /**
784 * Signals attempt to write a single or bulk (prepare) value.
785 *
786 * Callee shall accept the write request by returning true, otherwise false.
787 *
788 * @param device
789 * @param s
790 * @param c
791 * @param value
792 * @param value_offset
793 * @return true if master write has been accepted by GATT-Server listener, otherwise false. Only if all listener return true, the write action will be allowed.
794 * @see writeCharValueDone()
795 */
796 virtual bool writeCharValue(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c,
797 const jau::TROOctets & value, const uint16_t value_offset) = 0;
798
799 /**
800 * Notifies completion of single or bulk writeCharValue() after having accepted and performed all write requests.
801 *
802 * @param device
803 * @param s
804 * @param c
805 * @see writeCharValue()
806 */
807 virtual void writeCharValueDone(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c) = 0;
808
809 /**
810 * Signals attempt to write a single or bulk (prepare) value.
811 *
812 * Callee shall accept the write request by returning true, otherwise false.
813 *
814 * @param device
815 * @param s
816 * @param c
817 * @param d
818 * @param value
819 * @param value_offset
820 * @return true if master write has been accepted by GATT-Server listener, otherwise false. Only if all listener return true, the write action will be allowed.
821 * @see writeDescValueDone()
822 */
823 virtual bool writeDescValue(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c, const DBGattDescRef& d,
824 const jau::TROOctets & value, const uint16_t value_offset) = 0;
825
826 /**
827 * Notifies completion of single or bulk writeCharValue() after having accepted and performed all write requests.
828 *
829 * @param device
830 * @param s
831 * @param c
832 * @param d
833 * @see writeDescValue()
834 */
835 virtual void writeDescValueDone(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c, const DBGattDescRef& d) = 0;
836
837 /**
838 * Notifies a change of the Client Characteristic Configuration Descriptor (CCCD) value.
839 *
840 * @param device
841 * @param s
842 * @param c
843 * @param d
844 * @param notificationEnabled
845 * @param indicationEnabled
846 */
847 virtual void clientCharConfigChanged(const BTDeviceRef& device, const DBGattServiceRef& s, const DBGattCharRef& c, const DBGattDescRef& d,
848 const bool notificationEnabled, const bool indicationEnabled) = 0;
849
850 /**
851 * Default comparison operator, merely testing for same memory reference.
852 * <p>
853 * Specializations may override.
854 * </p>
855 */
856 virtual bool operator==(const Listener& rhs) const
857 { return this == &rhs; }
858
859 bool operator!=(const Listener& rhs) const
860 { return !(*this == rhs); }
861 };
862 typedef std::shared_ptr<Listener> ListenerRef;
863
867
868 private:
869 ListenerList_t listenerList;
870
871 uint16_t max_att_mtu;
872
873 GattServiceList_t services;
874
875 BTDeviceRef fwdServer; // FWD mode
876
877 Mode mode;
878
879 public:
880 /** Used maximum server Rx ATT_MTU, defaults to 512+1. */
881 uint16_t getMaxAttMTU() const noexcept { return max_att_mtu; }
882
883 /**
884 * Set maximum server Rx ATT_MTU, defaults to 512+1 limit.
885 *
886 * Method can only be issued before passing instance to BTAdapter::startAdvertising()
887 * @see BTAdapter::startAdvertising()
888 */
889 void setMaxAttMTU(const uint16_t v) noexcept { max_att_mtu = std::min<uint16_t>(512+1, v); }
890
891 /** List of Services */
892 jau::darray<DBGattServiceRef>& getServices() noexcept { return services; }
893
894 Mode getMode() const noexcept { return mode; }
895
896 BTDeviceRef getFwdServer() noexcept { return fwdServer; }
897
898 static std::string java_class() noexcept {
899 return std::string(JAVA_MAIN_PACKAGE "DBGattServer");
900 }
901
902 std::string get_java_class() const noexcept override {
903 return java_class();
904 }
905
906 ~DBGattServer() noexcept override { // NOLINT(modernize-use-equals-default)
907 #ifdef JAU_TRACE_DBGATT
908 JAU_TRACE_DBGATT_PRINT("DBGattServer dtor0: %p", this);
910 #endif
911 }
912
913 /**
914 * DBGattServer in Mode::NOP mode.
915 */
917 : max_att_mtu(512+1),
918 services( ),
919 fwdServer( nullptr ),
920 mode(Mode::NOP)
921 { }
922
923 /**
924 * DBGattServer in Mode::DB mode if given services_ are not empty, otherwise in Mode::NOP mode.
925 * @param max_att_mtu_
926 * @param services_
927 */
928 DBGattServer(uint16_t max_att_mtu_, jau::darray<DBGattServiceRef> && services_)
929 : max_att_mtu(std::min<uint16_t>(512+1, max_att_mtu_)),
930 services( std::move( services_ ) ),
931 fwdServer( nullptr ),
932 mode( services.size() > 0 ? Mode::DB : Mode::NOP )
933 { }
934
935 /**
936 * DBGattServer in Mode::DB mode if given services_ are not empty, otherwise in Mode::NOP mode.
937 *
938 * Ctor using default maximum ATT_MTU of 512+1
939 * @param services_
940 */
942 : max_att_mtu(512+1),
943 services( std::move( services_ ) ),
944 fwdServer( nullptr ),
945 mode( services.size() > 0 ? Mode::DB : Mode::NOP )
946 { }
947
948 /**
949 * DBGattServer in Mode::FWD to the given forward BTDevice.
950 *
951 * @param fwdServer_
952 */
954 : max_att_mtu(512+1),
955 services( ),
956 fwdServer(std::move( fwdServer_ )),
957 mode( Mode::FWD )
958 { }
959
961 for(DBGattServiceRef& s : services) {
962 if( type.equivalent( *s->getType() ) ) {
963 return s;
964 }
965 }
966 return nullptr;
967 }
968 DBGattCharRef findGattChar(const jau::uuid_t& service_uuid, const jau::uuid_t& char_uuid) noexcept {
969 DBGattServiceRef service = findGattService(service_uuid);
970 if( nullptr == service ) {
971 return nullptr;
972 }
973 return service->findGattChar(char_uuid);
974 }
975 DBGattDescRef findGattClientCharConfig(const jau::uuid_t& service_uuid, const jau::uuid_t& char_uuid) noexcept {
976 DBGattCharRef c = findGattChar(service_uuid, char_uuid);
977 if( nullptr == c ) {
978 return nullptr;
979 }
980 return c->getClientCharConfig();
981 }
982 bool resetGattClientCharConfig(const jau::uuid_t& service_uuid, const jau::uuid_t& char_uuid) noexcept {
983 DBGattDescRef d = findGattClientCharConfig(service_uuid, char_uuid);
984 if( nullptr == d ) {
985 return false;
986 }
987 d->bzero();
988 return true;
989 }
990
991 DBGattCharRef findGattCharByValueHandle(const uint16_t char_value_handle) noexcept {
992 for(DBGattServiceRef& s : services) {
993 DBGattCharRef r = s->findGattCharByValueHandle(char_value_handle);
994 if( nullptr != r ) {
995 return r;
996 }
997 }
998 return nullptr;
999 }
1000
1001 /**
1002 * Sets all handles of all service instances and all its owned childs,
1003 * i.e. DBGattChars elements and its DBGattDesc elements.
1004 *
1005 * Start handle is `1`.
1006 *
1007 * Method is being called by BTAdapter when advertising is enabled
1008 * via BTAdapter::startAdvertising().
1009 *
1010 * @return number of set handles, i.e. `( end_handle - handle ) + 1`
1011 * @see BTAdapter::startAdvertising()
1012 */
1014 size_type c = 0;
1015 uint16_t h = 1;
1016 for(DBGattServiceRef& s : services) {
1017 int l = s->setHandles(h);
1018 c += l;
1019 h += l; // end + 1 for next service
1020 }
1021 return c;
1022 }
1023
1024 bool addListener(const ListenerRef& l);
1025 bool removeListener(const ListenerRef& l);
1026 ListenerList_t& listener() { return listenerList; }
1027
1028 std::string toFullString() {
1029 std::string res = toString()+"\n";
1030 for(DBGattServiceRef& s : services) {
1031 res.append(" ").append(s->toString()).append("\n");
1032 for(DBGattCharRef& c : s->getCharacteristics()) {
1033 res.append(" ").append(c->toString()).append("\n");
1034 for(DBGattDescRef& d : c->getDescriptors()) {
1035 res.append(" ").append(d->toString()).append("\n");
1036 }
1037 }
1038 }
1039 return res;
1040 }
1041
1042 std::string toString() const noexcept override;
1043 };
1044 typedef std::shared_ptr<DBGattServer> DBGattServerRef;
1045
1046 std::string to_string(const DBGattServer::Mode m) noexcept;
1047
1048 /**@}*/
1049
1050} // namespace direct_bt
1051
1052#endif /* DB_GATT_SERVER_HPP_ */
#define JAVA_MAIN_PACKAGE
Definition: BTTypes0.hpp:44
#define JAU_TRACE_DBGATT_PRINT(...)
PropertyBitVal
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1.1 Characteristic Properties.
Definition: BTGattChar.hpp:105
static const std::shared_ptr< jau::uuid_t > TYPE_CCC_DESC
Definition: BTGattDesc.hpp:84
static const std::shared_ptr< jau::uuid_t > TYPE_USER_DESC
Definition: BTGattDesc.hpp:83
static const std::shared_ptr< jau::uuid_t > TYPE_EXT_PROP
Definition: BTGattDesc.hpp:82
Representing a Gatt Characteristic object from the GATTRole::Server perspective.
static std::string java_class() noexcept
const DBGattDescRef getClientCharConfig() const noexcept
std::shared_ptr< const jau::uuid_t > & getValueType() noexcept
int getUserDescriptionIndex() const noexcept
std::string toString() const noexcept override
bool hasProperties(const BTGattChar::PropertyBitVal v) const noexcept
uint16_t getHandle() const noexcept
Characteristic Handle of this instance.
bool hasVariableLength() const noexcept
True if value is of variable length, otherwise fixed length.
bool setValue(const uint8_t *source, const jau::nsize_t source_len, const jau::nsize_t dest_pos) noexcept
Set this characteristics's value.
~DBGattChar() noexcept override
DBGattChar(std::shared_ptr< const jau::uuid_t > value_type_, const BTGattChar::PropertyBitVal properties_, jau::darray< DBGattDescRef > &&descriptors_, jau::POctets &&value_, bool variable_length_=false) noexcept
DBGattDescRef getClientCharConfig() noexcept
jau::POctets & getValue() noexcept
Get reference of this characteristics's value.
DBGattChar(DBGattChar &&o) noexcept
Move constructor.
int getClientCharConfigIndex() const noexcept
DBGattDescRef getUserDescription() noexcept
jau::darray< DBGattDescRef > & getDescriptors() noexcept
List of Characteristic Descriptions.
DBGattChar(const DBGattChar &o)
Copy constructor preserving the capacity of the value.
const DBGattDescRef getUserDescription() const noexcept
BTGattChar::PropertyBitVal getProperties() const noexcept
uint16_t getEndHandle() const noexcept
Characteristic end handle, inclusive.
std::string get_java_class() const noexcept override
uint16_t getValueHandle() const noexcept
Characteristics Value Handle.
std::shared_ptr< const jau::uuid_t > getValueType() const noexcept
void bzero() noexcept
Fill value with zero bytes.
Representing a Gatt Characteristic Descriptor object from the GATTRole::Server perspective.
std::shared_ptr< const jau::uuid_t > getType() const noexcept
Type of descriptor.
std::shared_ptr< const jau::uuid_t > & getType() noexcept
Type of descriptor.
std::string get_java_class() const noexcept override
DBGattDesc(DBGattDesc &&o) noexcept
Move constructor.
std::string toString() const noexcept override
bool hasVariableLength() const noexcept
True if value is of variable length, otherwise fixed length.
bool setValue(const uint8_t *source, const jau::nsize_t source_len, const jau::nsize_t dest_pos) noexcept
Set this characteristic descriptor's value.
bool isUserDescription() const noexcept
bool isExtendedProperties() const noexcept
Value is uint16_t bitfield.
DBGattDesc(std::shared_ptr< const jau::uuid_t > type_, jau::POctets &&value_, bool variable_length_=false) noexcept
jau::POctets & getValue() noexcept
Get reference of this characteristic descriptor's value.
uint16_t getHandle() const noexcept
Characteristic Descriptor Handle.
bool isClientCharConfig() const noexcept
void bzero() noexcept
Fill value with zero bytes.
static std::string java_class() noexcept
static std::shared_ptr< DBGattDesc > createClientCharConfig()
Return a newly constructed Client Characteristic Configuration with a zero uint16_t value of fixed le...
DBGattDesc(const DBGattDesc &o)
Copy constructor preserving the capacity of the value.
~DBGattDesc() noexcept override
Listener to remote master device's operations on the local GATT-Server.
virtual bool operator==(const Listener &rhs) const
Default comparison operator, merely testing for same memory reference.
virtual bool writeCharValue(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c, const jau::TROOctets &value, const uint16_t value_offset)=0
Signals attempt to write a single or bulk (prepare) value.
virtual bool readCharValue(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c)=0
Signals attempt to read a value.
virtual bool readDescValue(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c, const DBGattDescRef &d)=0
Signals attempt to read a value.
virtual bool writeDescValue(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c, const DBGattDescRef &d, const jau::TROOctets &value, const uint16_t value_offset)=0
Signals attempt to write a single or bulk (prepare) value.
virtual void clientCharConfigChanged(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c, const DBGattDescRef &d, const bool notificationEnabled, const bool indicationEnabled)=0
Notifies a change of the Client Characteristic Configuration Descriptor (CCCD) value.
virtual void connected(const BTDeviceRef &device, const uint16_t initialMTU)=0
Notification that device got connected.
bool operator!=(const Listener &rhs) const
virtual void mtuChanged(const BTDeviceRef &device, const uint16_t mtu)=0
Notification that the MTU has changed.
virtual void disconnected(const BTDeviceRef &device)=0
Notification that device got disconnected.
virtual void writeDescValueDone(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c, const DBGattDescRef &d)=0
Notifies completion of single or bulk writeCharValue() after having accepted and performed all write ...
virtual void writeCharValueDone(const BTDeviceRef &device, const DBGattServiceRef &s, const DBGattCharRef &c)=0
Notifies completion of single or bulk writeCharValue() after having accepted and performed all write ...
Representing a complete list of Gatt Service objects from the GATTRole::Server perspective,...
BTDeviceRef getFwdServer() noexcept
DBGattServer(jau::darray< DBGattServiceRef > &&services_)
DBGattServer in Mode::DB mode if given services_ are not empty, otherwise in Mode::NOP mode.
jau::darray< DBGattServiceRef, size_type > GattServiceList_t
DBGattServiceRef findGattService(const jau::uuid_t &type) noexcept
std::shared_ptr< Listener > ListenerRef
DBGattServer(BTDeviceRef fwdServer_)
DBGattServer in Mode::FWD to the given forward BTDevice.
bool resetGattClientCharConfig(const jau::uuid_t &service_uuid, const jau::uuid_t &char_uuid) noexcept
size_type setServicesHandles()
Sets all handles of all service instances and all its owned childs, i.e.
Mode
Operating mode of a DBGattServer instance.
DBGattServer()
DBGattServer in Mode::NOP mode.
bool addListener(const ListenerRef &l)
static std::string toModeString(const Mode m) noexcept
DBGattCharRef findGattChar(const jau::uuid_t &service_uuid, const jau::uuid_t &char_uuid) noexcept
jau::darray< DBGattServiceRef > & getServices() noexcept
List of Services.
DBGattServer(uint16_t max_att_mtu_, jau::darray< DBGattServiceRef > &&services_)
DBGattServer in Mode::DB mode if given services_ are not empty, otherwise in Mode::NOP mode.
bool removeListener(const ListenerRef &l)
uint16_t getMaxAttMTU() const noexcept
Used maximum server Rx ATT_MTU, defaults to 512+1.
jau::cow_darray< ListenerRef, size_type > ListenerList_t
void setMaxAttMTU(const uint16_t v) noexcept
Set maximum server Rx ATT_MTU, defaults to 512+1 limit.
~DBGattServer() noexcept override
DBGattCharRef findGattCharByValueHandle(const uint16_t char_value_handle) noexcept
std::string get_java_class() const noexcept override
std::string toString() const noexcept override
Mode getMode() const noexcept
static std::string java_class() noexcept
ListenerList_t & listener()
DBGattDescRef findGattClientCharConfig(const jau::uuid_t &service_uuid, const jau::uuid_t &char_uuid) noexcept
Representing a Gatt Service object from the GATTRole::Server perspective.
std::string get_java_class() const noexcept override
std::string toString() const noexcept override
DBGattService(DBGattService &&o) noexcept=default
bool isPrimary() const noexcept
Indicate whether this service is a primary service.
uint16_t getEndHandle() const noexcept
Service end handle, inclusive.
~DBGattService() noexcept override
std::shared_ptr< const jau::uuid_t > & getType() noexcept
Service type UUID.
std::shared_ptr< const jau::uuid_t > getType() const noexcept
Service type UUID.
uint16_t getHandle() const noexcept
Service start handle.
DBGattService(const bool primary_, std::shared_ptr< const jau::uuid_t > type_, jau::darray< DBGattCharRef > &&characteristics_)
DBGattCharRef findGattChar(const jau::uuid_t &char_uuid) noexcept
DBGattService(const DBGattService &o)=default
int setHandles(const uint16_t start_handle)
Sets all handles of this service instance and all its owned childs, i.e.
jau::darray< DBGattCharRef > & getCharacteristics() noexcept
List of Characteristic Declarations.
static std::string java_class() noexcept
DBGattCharRef findGattCharByValueHandle(const uint16_t char_value_handle) noexcept
Persistent endian aware octet data, i.e.
Definition: octets.hpp:560
std::string toString() const
Definition: octets.hpp:932
void put_bytes_nc(const nsize_t i, const uint8_t *source, const nsize_t byte_count) noexcept
Definition: octets.hpp:416
void bzero(const nsize_t i, const nsize_t byte_count)
Definition: octets.hpp:435
constexpr void put_uint16_nc(const nsize_t i, const uint16_t v) noexcept
Definition: octets.hpp:343
uint8_t * get_wptr() noexcept
Definition: octets.hpp:474
Transient read only and endian aware octet data, i.e.
Definition: octets.hpp:67
constexpr nsize_t size() const noexcept
Returns the used memory size for read and write operations, may be zero.
Definition: octets.hpp:162
constexpr uint8_t const * get_ptr() const noexcept
Definition: octets.hpp:272
constexpr size_type size() const noexcept
Like std::vector::size().
Definition: darray.hpp:763
const_reference at(size_type i) const
Like std::vector::at(size_type), immutable reference.
Definition: darray.hpp:814
uint32_t dfa_utf8_decode(uint32_t &state, uint32_t &codep, const uint32_t byte_value)
@ little
Identifier for little endian, equivalent to endian::little.
bool operator==(const BTAdapter &lhs, const BTAdapter &rhs) noexcept
Definition: BTAdapter.hpp:1348
std::shared_ptr< BTDevice > BTDeviceRef
Definition: BTDevice.hpp:1347
std::string to_string(const DiscoveryPolicy v) noexcept
Definition: BTAdapter.cpp:58
bool operator!=(const BTAdapter &lhs, const BTAdapter &rhs) noexcept
Definition: BTAdapter.hpp:1351
std::shared_ptr< DBGattDesc > DBGattDescRef
jau::POctets make_gvalue(const char *name)
Convenience jau::POctets ctor function to create DBGattChar or DBGattDesc values.
std::shared_ptr< DBGattService > DBGattServiceRef
std::shared_ptr< DBGattServer > DBGattServerRef
std::string to_string(const DBGattServer::Mode m) noexcept
std::shared_ptr< DBGattChar > DBGattCharRef
constexpr T min(const T x, const T y) noexcept
Returns the minimum of two integrals (w/ branching) in O(1)
Definition: base_math.hpp:177
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
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
void print_backtrace(const bool skip_anon_frames, const jau::snsize_t max_frames=-1, const jau::snsize_t skip_frames=2) noexcept
Prints the de-mangled backtrace string separated by newline excluding this function to stderr,...
Definition: debug.cpp:173
STL namespace.
@ Notify
@ Indicate