• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gatt_cache.h"
17 #include "bt_def.h"
18 #include "gatt_defines.h"
19 
20 namespace bluetooth {
21 using Descriptors = std::pair<std::map<uint16_t, GattCache::Descriptor> *, uint16_t>;
22 
AddService(const Service & service)23 void GattCache::AddService(const Service &service)
24 {
25     auto it = services_.emplace(service.handle_, service);
26     if (!it.second) {
27         it.first->second.endHandle_ = service.endHandle_;
28         it.first->second.uuid_ = service.uuid_;
29     }
30 }
31 
Clear()32 void GattCache::Clear()
33 {
34     services_.clear();
35 }
36 
AddIncludeService(uint16_t serviceHandle,const IncludeService & includeService)37 int GattCache::AddIncludeService(uint16_t serviceHandle, const IncludeService &includeService)
38 {
39     auto it = services_.find(serviceHandle);
40     if (it != services_.end()) {
41         it->second.includeServices_.push_back(includeService);
42 
43         return GattStatus::GATT_SUCCESS;
44     }
45 
46     return GattStatus::INVALID_PARAMETER;
47 }
48 
AddCharacteristic(uint16_t serviceHandle,const Characteristic & characteristic)49 int GattCache::AddCharacteristic(uint16_t serviceHandle, const Characteristic &characteristic)
50 {
51     auto it = services_.find(serviceHandle);
52     if (it != services_.end()) {
53         auto result = it->second.characteristics_.emplace(characteristic.handle_, characteristic);
54         if (result.second) {
55             valueHandleMap_.emplace(characteristic.valueHandle_, std::make_pair(serviceHandle, characteristic.handle_));
56         } else {
57             result.first->second.properties_ = characteristic.properties_;
58             result.first->second.uuid_ = characteristic.uuid_;
59         }
60         return GattStatus::GATT_SUCCESS;
61     }
62     return GattStatus::INVALID_PARAMETER;
63 }
64 
AddDescriptor(uint16_t cccHandle,const Descriptor & descriptor)65 int GattCache::AddDescriptor(uint16_t cccHandle, const Descriptor &descriptor)
66 {
67     for (auto &sIt : services_) {
68         auto cIt = sIt.second.characteristics_.find(cccHandle);
69         if (cIt != sIt.second.characteristics_.end()) {
70             cIt->second.descriptors_.emplace(descriptor.handle_, descriptor);
71             valueHandleMap_.emplace(descriptor.handle_, std::make_pair(sIt.second.handle_, cIt->second.handle_));
72             return GattStatus::GATT_SUCCESS;
73         }
74     }
75 
76     return GattStatus::INVALID_PARAMETER;
77 }
78 
GetCharacteristic(int16_t valueHandle)79 const GattCache::Characteristic *GattCache::GetCharacteristic(int16_t valueHandle)
80 {
81     auto it = valueHandleMap_.find(valueHandle);
82     if (it != valueHandleMap_.end()) {
83         auto svc = services_.find(it->second.first);
84         if (svc != services_.end()) {
85             auto ccc = svc->second.characteristics_.find(it->second.second);
86             if (ccc != svc->second.characteristics_.end()) {
87                 return &ccc->second;
88             }
89         }
90     }
91     return nullptr;
92 }
93 
GetDescriptor(int16_t valueHandle)94 const GattCache::Descriptor *GattCache::GetDescriptor(int16_t valueHandle)
95 {
96     auto it = valueHandleMap_.find(valueHandle);
97     if (it == valueHandleMap_.end()) {
98         return nullptr;
99     }
100     auto svc = services_.find(it->second.first);
101     if (svc == services_.end()) {
102         return nullptr;
103     }
104     auto ccc = svc->second.characteristics_.find(it->second.second);
105     if (ccc == svc->second.characteristics_.end()) {
106         return nullptr;
107     }
108     auto descriptor = ccc->second.descriptors_.find(valueHandle);
109     if (descriptor != ccc->second.descriptors_.end()) {
110         return nullptr;
111     }
112     return &descriptor->second;
113 }
114 
GetCharacteristicEndHandle(uint16_t serviceHandle,uint16_t cccHandle) const115 uint16_t GattCache::GetCharacteristicEndHandle(uint16_t serviceHandle, uint16_t cccHandle) const
116 {
117     auto svc = services_.find(serviceHandle);
118     if (svc == services_.end()) {
119         return INVALID_ATTRIBUTE_HANDLE;
120     }
121 
122     auto ccc = svc->second.characteristics_.find(cccHandle);
123     if (ccc == svc->second.characteristics_.end()) {
124         return INVALID_ATTRIBUTE_HANDLE;
125     }
126 
127     if (++ccc != svc->second.characteristics_.end()) {
128         return ccc->second.handle_ - MIN_ATTRIBUTE_HANDLE;
129     }
130 
131     return svc->second.endHandle_;
132 }
133 
GetServices()134 std::map<uint16_t, GattCache::Service> &GattCache::GetServices()
135 {
136     return services_;
137 }
138 
GetIncludeServices(uint16_t serviceHandle)139 std::vector<GattCache::IncludeService> *GattCache::GetIncludeServices(uint16_t serviceHandle)
140 {
141     auto service = services_.find(serviceHandle);
142     if (service != services_.end()) {
143         return &service->second.includeServices_;
144     }
145     return nullptr;
146 }
147 
GetCharacteristics(uint16_t serviceHandle)148 std::map<uint16_t, GattCache::Characteristic> *GattCache::GetCharacteristics(uint16_t serviceHandle)
149 {
150     auto service = services_.find(serviceHandle);
151     if (service != services_.end()) {
152         return &service->second.characteristics_;
153     }
154     return nullptr;
155 }
156 
GetDescriptors(uint16_t cccHandle)157 Descriptors GattCache::GetDescriptors(uint16_t cccHandle)
158 {
159     for (auto &service : services_) {
160         auto it = service.second.characteristics_.find(cccHandle);
161         if (it != service.second.characteristics_.end()) {
162             return std::make_pair(&it->second.descriptors_, service.second.handle_);
163         }
164     }
165     return std::make_pair(nullptr, 0);
166 }
167 
168 const std::string GattCache::GATT_STORAGE_PRIFIX = "gatt_storage_cache_";
169 
StoredToFile(const GattDevice & address) const170 int GattCache::StoredToFile(const GattDevice& address) const
171 {
172     std::vector<StorageBlob> storage;
173 
174     for (auto &svc : services_) {
175         StorageBlob svcBlob = {};
176         svcBlob.handle_ = svc.second.handle_;
177         svcBlob.type_ = (svc.second.isPrimary_ ? Uuid::ConvertFrom16Bits(UUID_PRIMARY_SERVICE)
178                                                : Uuid::ConvertFrom16Bits(UUID_SECONDARY_SERVICE));
179         svcBlob.value_.service_.uuid_ = svc.second.uuid_;
180         svcBlob.value_.service_.endHandle_ = svc.second.endHandle_;
181         storage.push_back(svcBlob);
182 
183         for (auto &isvc : svc.second.includeServices_) {
184             StorageBlob isvcBlob = {};
185             isvcBlob.handle_ = isvc.handle_;
186             isvcBlob.type_ = Uuid::ConvertFrom16Bits(UUID_INCLUDE_SERVICE);
187             isvcBlob.value_.includeService_.handle_ = isvc.startHandle_;
188             isvcBlob.value_.includeService_.endHandle_ = isvc.endHandle_;
189             isvcBlob.value_.includeService_.uuid_ = isvc.uuid_;
190             storage.push_back(isvcBlob);
191         }
192 
193         for (auto &ccc : svc.second.characteristics_) {
194             StorageBlob cccBlob = {};
195             cccBlob.handle_ = ccc.second.handle_;
196             cccBlob.type_ = Uuid::ConvertFrom16Bits(UUID_CHARACTERISTIC);
197             cccBlob.value_.characteristic_.properties_ = ccc.second.properties_;
198             cccBlob.value_.characteristic_.valueHandle_ = ccc.second.valueHandle_;
199             cccBlob.value_.characteristic_.uuid_ = ccc.second.uuid_;
200             storage.push_back(cccBlob);
201 
202             for (auto &desc : ccc.second.descriptors_) {
203                 StorageBlob descBlob = {};
204                 descBlob.handle_ = desc.second.handle_;
205                 descBlob.type_ = desc.second.uuid_;
206                 storage.push_back(descBlob);
207             }
208         }
209     }
210 
211     return WriteStorageBlobToFile(address, storage);
212 }
213 
LoadFromFile(const GattDevice & address)214 int GattCache::LoadFromFile(const GattDevice& address)
215 {
216     std::vector<StorageBlob> storage = ReadStorageBlobFromFile(address);
217 
218     uint16_t currentSvcHandle = 0;
219     uint16_t currentCccHandle = 0;
220     for (auto &item : storage) {
221         if (item.type_ == Uuid::ConvertFrom16Bits(UUID_PRIMARY_SERVICE) ||
222             item.type_ == Uuid::ConvertFrom16Bits(UUID_SECONDARY_SERVICE)) {
223             AddService(
224                 GattCache::Service((item.type_ == Uuid::ConvertFrom16Bits(UUID_PRIMARY_SERVICE)) ? true : false,
225                     item.handle_,
226                     item.value_.service_.endHandle_,
227                     item.value_.service_.uuid_));
228             currentSvcHandle = item.handle_;
229         } else if (item.type_ == Uuid::ConvertFrom16Bits(UUID_INCLUDE_SERVICE)) {
230             AddIncludeService(currentSvcHandle,
231                 GattCache::IncludeService(item.handle_,
232                     item.value_.includeService_.handle_,
233                     item.value_.includeService_.endHandle_,
234                     item.value_.includeService_.uuid_));
235         } else if (item.type_ == Uuid::ConvertFrom16Bits(UUID_CHARACTERISTIC)) {
236             AddCharacteristic(currentSvcHandle,
237                 GattCache::Characteristic(item.handle_,
238                     item.value_.characteristic_.properties_,
239                     item.value_.characteristic_.valueHandle_,
240                     item.value_.characteristic_.uuid_));
241             currentCccHandle = item.handle_;
242         } else {
243             AddDescriptor(currentCccHandle, GattCache::Descriptor(item.handle_, item.type_));
244         }
245     }
246 
247     return GattStatus::GATT_SUCCESS;
248 }
249 
GenerateGattCacheFileName(const GattDevice & address)250 std::string GattCache::GenerateGattCacheFileName(const GattDevice &address)
251 {
252     return (GATT_STORAGE_PRIFIX + address.addr_.GetAddress() + "_" +
253            ((address.transport_ == GATT_TRANSPORT_TYPE_CLASSIC) ? "CLASSIC" : "LE"));
254 }
255 
WriteStorageBlobToFile(const GattDevice & address,std::vector<StorageBlob> & blob) const256 int GattCache::WriteStorageBlobToFile(const GattDevice& address, std::vector<StorageBlob> &blob) const
257 {
258     FILE* fd = fopen(GenerateGattCacheFileName(address).c_str(), "wb");
259     if (fd == nullptr) {
260         return GattStatus::REQUEST_NOT_SUPPORT;
261     }
262 
263     uint16_t blobSize = blob.size();
264     if (fwrite(&blobSize, sizeof(uint16_t), 1, fd) != 1) {
265         fclose(fd);
266         return GattStatus::INTERNAL_ERROR;
267     }
268 
269     if (fwrite(blob.data(), sizeof(StorageBlob), blobSize, fd) != blobSize) {
270         fclose(fd);
271         return GattStatus::INTERNAL_ERROR;
272     }
273 
274     fclose(fd);
275 
276     return GattStatus::GATT_SUCCESS;
277 }
278 
ReadStorageBlobFromFile(const GattDevice & address) const279 std::vector<GattCache::StorageBlob> GattCache::ReadStorageBlobFromFile(const GattDevice &address) const
280 {
281     FILE* fd = fopen(GenerateGattCacheFileName(address).c_str(), "rb");
282     if (fd == nullptr) {
283         return std::vector<StorageBlob>();
284     }
285 
286     uint16_t blobSize = 0;
287     if (fread(&blobSize, sizeof(uint16_t), 1, fd) != 1) {
288         fclose(fd);
289         return std::vector<StorageBlob>();
290     }
291 
292     std::vector<StorageBlob> blob(blobSize, {0, {}, {}});
293     if (fread(blob.data(), sizeof(StorageBlob), blobSize, fd) != blobSize) {
294         fclose(fd);
295         return std::vector<StorageBlob>();
296     }
297 
298     fclose(fd);
299     return blob;
300 }
301 }  // namespace bluetooth