aboutsummaryrefslogtreecommitdiffstats
path: root/api/direct_bt/DBGattServer.hpp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2021-10-07 03:02:20 +0200
committerSven Gothel <[email protected]>2021-10-07 03:02:20 +0200
commit6dd98bd44cc669917662e0f6c1f1e9e9fddea2c3 (patch)
tree8fd4478db5bb709fbd98d213266becfdbcc5e972 /api/direct_bt/DBGattServer.hpp
parentfa61986c2f1476c8109c5b401395d009dff64a35 (diff)
Gatt-Server: Add DBGattServer.hpp, covering DBGattDesc, DBGattChar and DBGattService
Diffstat (limited to 'api/direct_bt/DBGattServer.hpp')
-rw-r--r--api/direct_bt/DBGattServer.hpp304
1 files changed, 304 insertions, 0 deletions
diff --git a/api/direct_bt/DBGattServer.hpp b/api/direct_bt/DBGattServer.hpp
new file mode 100644
index 00000000..c397925b
--- /dev/null
+++ b/api/direct_bt/DBGattServer.hpp
@@ -0,0 +1,304 @@
+/*
+ * Author: Sven Gothel <[email protected]>
+ * Copyright (c) 2021 Gothel Software e.K.
+ * Copyright (c) 2021 ZAFENA AB
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DB_GATT_SERVER_HPP_
+#define DB_GATT_SERVER_HPP_
+
+#include <cstring>
+#include <string>
+#include <memory>
+#include <cstdint>
+
+#include <mutex>
+#include <atomic>
+
+#include <jau/java_uplink.hpp>
+#include <jau/octets.hpp>
+#include <jau/uuid.hpp>
+
+#include "BTTypes0.hpp"
+#include "ATTPDUTypes.hpp"
+
+#include "BTTypes1.hpp"
+
+// #include "BTGattDesc.hpp"
+#include "BTGattChar.hpp"
+// #include "BTGattService.hpp"
+
+
+/**
+ * - - - - - - - - - - - - - - -
+ *
+ * Module DBGattServer covering the GattServer elements:
+ *
+ * - BT Core Spec v5.2: Vol 3, Part G Generic Attribute Protocol (GATT)
+ * - BT Core Spec v5.2: Vol 3, Part G GATT: 2.6 GATT Profile Hierarchy
+ */
+namespace direct_bt {
+
+ /**
+ * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3 Characteristic Descriptor
+ */
+ class DBGattDesc {
+ public:
+ /**
+ * Characteristic Descriptor Handle
+ * <p>
+ * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
+ * </p>
+ */
+ uint16_t handle;
+
+ /** Type of descriptor */
+ std::shared_ptr<const jau::uuid_t> type;
+
+ /* Characteristics Descriptor's Value */
+ jau::POctets value;
+
+ DBGattDesc(const std::shared_ptr<const jau::uuid_t>& type_,
+ const jau::TROOctets& value_) noexcept
+ : handle(0), type(type_), value(value_) {}
+
+ std::string toString() const noexcept {
+ return "Desc[type 0x"+type->toString()+", handle "+jau::to_hexstring(handle)+", value["+value.toString()+"]]";
+ }
+
+ /** Value is uint16_t bitfield */
+ bool isExtendedProperties() const noexcept { return BTGattDesc::TYPE_EXT_PROP == *type; }
+
+ /* BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration (Characteristic Descriptor, optional, single, uint16_t bitfield) */
+ bool isClientCharConfig() const noexcept{ return BTGattDesc::TYPE_CCC_DESC == *type; }
+ };
+ inline bool operator==(const DBGattDesc& lhs, const DBGattDesc& rhs) noexcept
+ { return lhs.handle == rhs.handle; /** unique attribute handles */ }
+
+ inline bool operator!=(const DBGattDesc& lhs, const DBGattDesc& rhs) noexcept
+ { return !(lhs == rhs); }
+
+ /**
+ * <p>
+ * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1 Characteristic Declaration Attribute Value
+ * </p>
+ * handle -> CDAV value
+ * <p>
+ * BT Core Spec v5.2: Vol 3, Part G GATT: 4.6.1 Discover All Characteristics of a Service
+ *
+ * Here the handle is a service's characteristics-declaration
+ * and the value the Characteristics Property, Characteristics Value Handle _and_ Characteristics UUID.
+ * </p>
+ */
+ class DBGattChar {
+ private:
+ bool enabledNotifyState = false;
+ bool enabledIndicateState = false;
+
+ public:
+ class Listener {
+ public:
+ virtual bool readValue(jau::POctets & res) const noexcept = 0;
+
+ virtual bool writeValue(const jau::TROOctets & value) const noexcept = 0;
+ virtual bool writeValueNoResp(const jau::TROOctets & value) const noexcept = 0;
+
+ virtual ~Listener() noexcept {}
+ };
+
+ /**
+ * Characteristic Handle of this instance.
+ * <p>
+ * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
+ * </p>
+ */
+ uint16_t handle;
+
+ /**
+ * Characteristics Value Handle.
+ * <p>
+ * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
+ * </p>
+ */
+ uint16_t value_handle;
+
+ /* Characteristics Value Type UUID */
+ std::shared_ptr<const jau::uuid_t> value_type;
+
+ /* Characteristics Property */
+ BTGattChar::PropertyBitVal properties;
+
+ /** List of Characteristic Descriptions as shared reference */
+ jau::darray<DBGattDesc> descriptors;
+
+ /* Characteristics Descriptor's Value */
+ jau::POctets value;
+
+ /* Optional Client Characteristic Configuration index within descriptorList */
+ int clientCharConfigIndex;
+
+ DBGattChar(const std::shared_ptr<const jau::uuid_t>& value_type_,
+ const BTGattChar::PropertyBitVal properties_,
+ const jau::darray<DBGattDesc>& descriptors_,
+ const jau::TROOctets & value_) noexcept
+ : handle(0), value_handle(0),
+ value_type(value_type_),
+ properties(properties_),
+ descriptors(descriptors_),
+ value(value_),
+ clientCharConfigIndex(-1)
+ {
+ int i=0;
+ // C++11: Range-based for loop: [begin, end[
+ for(DBGattDesc& d : descriptors) {
+ if( d.isClientCharConfig() ) {
+ clientCharConfigIndex=i;
+ break;
+ }
+ ++i;
+ }
+ }
+
+ bool hasProperties(const BTGattChar::PropertyBitVal v) const noexcept { return v == ( properties & v ); }
+
+ std::string toString() const noexcept {
+ std::string notify_str;
+ if( hasProperties(BTGattChar::PropertyBitVal::Notify) || hasProperties(BTGattChar::PropertyBitVal::Indicate) ) {
+ notify_str = ", enabled[notify "+std::to_string(enabledNotifyState)+", indicate "+std::to_string(enabledIndicateState)+"]";
+ }
+ return "Char[handle "+jau::to_hexstring(handle)+", props "+jau::to_hexstring(properties)+" "+BTGattChar::getPropertiesString(properties)+
+ ", value[handle "+jau::to_hexstring(value_handle)+
+ "], ccd-idx "+std::to_string(clientCharConfigIndex)+notify_str+"]";
+ }
+
+ DBGattDesc* getClientCharConfig() noexcept {
+ if( 0 > clientCharConfigIndex ) {
+ return nullptr;
+ }
+ return &descriptors.at(static_cast<size_t>(clientCharConfigIndex)); // abort if out of bounds
+ }
+ };
+ inline bool operator==(const DBGattChar& lhs, const DBGattChar& rhs) noexcept
+ { return lhs.handle == rhs.handle; /** unique attribute handles */ }
+
+ inline bool operator!=(const DBGattChar& lhs, const DBGattChar& rhs) noexcept
+ { return !(lhs == rhs); }
+
+ /**
+ * Representing a complete [Primary] Service Declaration
+ * including its list of Characteristic Declarations,
+ * which also may include its client config if available.
+ */
+ class DBGattService {
+ public:
+ bool primary;
+
+ /**
+ * Service start handle
+ * <p>
+ * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
+ * </p>
+ */
+ uint16_t handle;
+
+ /**
+ * Service end handle, inclusive.
+ * <p>
+ * Attribute handles are unique for each device (server) (BT Core Spec v5.2: Vol 3, Part F Protocol..: 3.2.2 Attribute Handle).
+ * </p>
+ */
+ uint16_t end_handle;
+
+ /** Service type UUID */
+ std::shared_ptr<const jau::uuid_t> type;
+
+ /** List of Characteristic Declarations as shared reference */
+ jau::darray<DBGattChar> characteristics;
+
+ DBGattService(const bool primary_,
+ const std::shared_ptr<const jau::uuid_t>& type_,
+ const jau::darray<DBGattChar>& characteristics_) noexcept
+ : primary(primary_), handle(0), end_handle(0),
+ type(type_),
+ characteristics(characteristics_)
+ { }
+
+ /**
+ * Sets all handles of this service instance and all its owned childs,
+ * i.e. DBGattChars elements and its DBGattDesc elements.
+ *
+ * @param start_handle a valid and unique start handle number > 0
+ * @return number of set handles, i.e. `( end_handle - handle ) + 1`
+ */
+ int setHandles(const uint16_t start_handle) {
+ if( 0 == start_handle ) {
+ handle = 0;
+ end_handle = 0;
+ return 0;
+ }
+ uint16_t h = start_handle;
+ handle = h++;
+ for(DBGattChar& c : characteristics) {
+ c.handle = h++;
+ c.value_handle = h++;
+ for(DBGattDesc& d : c.descriptors) {
+ d.handle = h++;
+ }
+ }
+ end_handle = h;
+ return ( end_handle - handle ) + 1;
+ }
+ std::string toString() const noexcept {
+ return "Srvc[type 0x"+type->toString()+", handle ["+jau::to_hexstring(handle)+".."+jau::to_hexstring(end_handle)+"], "+
+ std::to_string(characteristics.size())+" chars]";
+
+ }
+ };
+ inline bool operator==(const DBGattService& lhs, const DBGattService& rhs) noexcept
+ { return lhs.handle == rhs.handle && lhs.end_handle == rhs.end_handle; /** unique attribute handles */ }
+
+ inline bool operator!=(const DBGattService& lhs, const DBGattService& rhs) noexcept
+ { return !(lhs == rhs); }
+
+ typedef jau::darray<DBGattService> Services;
+
+ /**
+ * Sets all handles of all service instances and all its owned childs,
+ * i.e. DBGattChars elements and its DBGattDesc elements.
+ *
+ * @param start_handle a valid and unique start handle number > 0
+ * @return number of set handles, i.e. `( end_handle - handle ) + 1`
+ */
+ inline int setServicesHandles(const uint16_t start_handle, Services srvcs) {
+ int c = 0;
+ uint16_t h = start_handle;
+ for(DBGattService s : srvcs) {
+ int l = s.setHandles(h);
+ c += l;
+ h += l; // end + 1 for next service
+ }
+ return c;
+ }
+
+} // namespace direct_bt
+
+#endif /* DB_GATT_SERVER_HPP_ */