1 //
2 //  Copyright (C) 2015 Google, Inc.
3 //
4 //  Licensed under the Apache License, Version 2.0 (the "License");
5 //  you may not use this file except in compliance with the License.
6 //  You may obtain a copy of the License at:
7 //
8 //  http://www.apache.org/licenses/LICENSE-2.0
9 //
10 //  Unless required by applicable law or agreed to in writing, software
11 //  distributed under the License is distributed on an "AS IS" BASIS,
12 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 //  See the License for the specific language governing permissions and
14 //  limitations under the License.
15 //
16 
17 #pragma once
18 
19 #include <memory>
20 #include <string>
21 
22 #include <bluetooth/uuid.h>
23 
24 namespace bluetooth {
25 
26 // Used to uniquely identify a GATT object/attribute
27 // (service/characteristic/descriptor/include entry) after it has been
28 // registered with the stack. Each registered object will be assigned a GATT
29 // identifier that the callers may use in future callbacks.
30 //
31 // For local services, the uniqueness of each identifier is guaranteed only
32 // within the registered GATT server that they exist in.
33 class GattIdentifier final {
34  public:
35   // Static initialization methods. These return NULL if invalid parameters are
36   // given.
37   static std::unique_ptr<GattIdentifier> CreateServiceId(
38       const std::string& device_address,
39       int id,
40       const UUID& uuid,
41       bool is_primary);
42   static std::unique_ptr<GattIdentifier> CreateCharacteristicId(
43       int id, const UUID& uuid,
44       const GattIdentifier& service_id);
45   static std::unique_ptr<GattIdentifier> CreateDescriptorId(
46       int id, const UUID& uuid,
47       const GattIdentifier& characteristic_id);
48 
49   // Constructors and assignment operator.
50   GattIdentifier();
51   GattIdentifier(
52       const std::string& device_address,
53       bool is_primary,
54       const UUID& service_uuid,
55       const UUID& characteristic_uuid,
56       const UUID& descriptor_uuid,
57       int service_instance_id,
58       int characteristic_instance_id,
59       int descriptor_instance_id);
60   ~GattIdentifier() = default;
61   GattIdentifier(const GattIdentifier& other);
62   GattIdentifier& operator=(const GattIdentifier& other);
63 
64 
65   // Comparison function and operator.
66   bool Equals(const GattIdentifier& other) const;
67   bool operator==(const GattIdentifier& rhs) const;
68   bool operator!=(const GattIdentifier& rhs) const;
69 
70   // Functions to verify the type of attribute represented by this identifier.
71   bool IsService() const;
72   bool IsCharacteristic() const;
73   bool IsDescriptor() const;
74 
75   // For characteristics and descriptors, this returns the identifier of the
76   // owning service. For services, this returns NULL.
77   std::unique_ptr<GattIdentifier> GetOwningServiceId() const;
78 
79   // For descriptors, this returns the identifier of the owning characteristic.
80   // For services and characteristics, this returns NULL.
81   std::unique_ptr<GattIdentifier> GetOwningCharacteristicId() const;
82 
83   // Getters for internal fields.
device_address()84   const std::string& device_address() const { return device_address_; }
is_primary()85   bool is_primary() const { return is_primary_; }
service_uuid()86   const UUID& service_uuid() const { return service_uuid_; }
characteristic_uuid()87   const UUID& characteristic_uuid() const { return char_uuid_; }
descriptor_uuid()88   const UUID& descriptor_uuid() const { return desc_uuid_; }
service_instance_id()89   int service_instance_id() const { return service_instance_id_; }
characteristic_instance_id()90   int characteristic_instance_id() const { return char_instance_id_; }
descriptor_instance_id()91   int descriptor_instance_id() const { return desc_instance_id_; }
92 
93  private:
94   friend struct std::hash<bluetooth::GattIdentifier>;
95 
96   // NOTE: Don't forget to update the std::hash specialization below if you
97   // update any of the instance variables in this class.
98 
99   // The BD_ADDR of the device associated with the attribute.
100   std::string device_address_;
101 
102   // An instance ID value of -1 means that it is unitialized. For example, a
103   // service ID would have -1 for characteristic and descriptor instance IDs.
104   bool is_primary_;
105   UUID service_uuid_;
106   UUID char_uuid_;
107   UUID desc_uuid_;
108   int service_instance_id_;
109   int char_instance_id_;
110   int desc_instance_id_;
111 };
112 
113 }  // namespace bluetooth
114 
115 // Custom std::hash specialization so that bluetooth::GattIdentifier can be used
116 // as a key in std::unordered_map.
117 namespace std {
118 
119 template<>
120 struct hash<bluetooth::GattIdentifier> {
121   std::size_t operator()(const bluetooth::GattIdentifier& key) const {
122     std::size_t seed = 0;
123 
124     hash_combine(seed, key.device_address_);
125     hash_combine(seed, key.is_primary_);
126     hash_combine(seed, key.service_uuid_);
127     hash_combine(seed, key.char_uuid_);
128     hash_combine(seed, key.desc_uuid_);
129     hash_combine(seed, key.service_instance_id_);
130     hash_combine(seed, key.char_instance_id_);
131     hash_combine(seed, key.desc_instance_id_);
132 
133     return seed;
134   }
135 
136  private:
137   template<typename T>
138   inline void hash_combine(std::size_t& seed, const T& v) const {
139     std::hash<T> hasher;
140     seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
141   }
142 };
143 
144 }  // namespace std
145