1 /*
2 * Copyright (C) 2021-2022 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_client_profile.h"
17 #include "att.h"
18 #include "bt_def.h"
19 #include "gatt_connection_manager.h"
20 #include "gatt_profile_defines.h"
21 #include "gatt_service_base.h"
22 #include "log.h"
23 #include "securec.h"
24
25 namespace bluetooth {
26 struct GattClientProfile::impl {
27 class GattConnectionObserverImplement;
28 GattClientProfileCallback *pClientCallBack_ = nullptr;
29 int connectionObserverId_ = 0;
30 utility::Dispatcher *dispatcher_;
31 std::map<uint16_t, GattCache> cacheMap_ = {};
32 std::map<uint16_t, MtuInfo> mtuInfo_ = {};
33 std::list<std::pair<uint16_t, GattRequestInfo>> requestList_ = {};
34 std::list<std::pair<uint16_t, GattRequestInfo>> responseList_ = {};
35 std::list<std::pair<uint16_t, ReadValCache>> readValCache_ = {};
36 std::unique_ptr<GattConnectionObserverImplement> connectionCallBack_ = {};
37 GattClientProfile *profile_ = nullptr;
implbluetooth::GattClientProfile::impl38 impl(GattClientProfileCallback *pClientCallbackFunc, utility::Dispatcher *dispatcher, GattClientProfile &profile)
39 : pClientCallBack_(pClientCallbackFunc),
40 dispatcher_(dispatcher),
41 connectionCallBack_(std::make_unique<GattConnectionObserverImplement>(profile))
42 {}
43 DISALLOW_COPY_AND_ASSIGN(impl);
44
45 static void ReceiveData(uint16_t connectHandle, uint16_t event, void *eventData, Buffer *buffer, void *context);
46 static void ReceiveRequestResult(uint16_t connectHandle, int result, void *context);
47 void RegisterCallbackToATT();
48 static void DeregisterCallbackToATT();
49 void RegisterCallbackToConnectManager();
50 void DeregisterCallbackToConnectManager();
51 void ReceiveRequestResultProcess(uint16_t connectHandle);
52 void IndicateRequestRetToService(int reqId, uint16_t connectHandle, ResponesType reqType, uint8_t errorCode);
53 void ReceiveDataProcess(uint16_t connectHandle, uint16_t event, AttEventData *data, Buffer *buffer,
54 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator attResp);
55 void SetMtuInformation(uint16_t connectHandle, bool isExchanged, uint16_t mtu);
56 MtuInfo GetMtuInformation(uint16_t connectHandle);
57 void AddResponseList(void);
58 void RemoveRequestList(std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
59 void ErrorResponseParsing(
60 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
61 void ErrorResponseParsing(uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
62 void ExchangeMtuParsing(
63 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
64 void DiscoverAllPrimaryServiceParsing(int reqId, uint16_t connectHandle, AttEventData *data);
65 void DiscoverPrimaryServiceByUuidParsing(
66 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
67 void FindIncludeServicesParsing(
68 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
69 void FindIncludeServicesParsing(uint16_t connectHandle, uint16_t handle, Buffer *buffer);
70 void DiscoverAllCharacteristicOfServiceParsing(uint16_t connectHandle, AttEventData *data, bool isByUuid,
71 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
72 void SendDiscoverAllCharacteristicRequest(uint16_t connectHandle, uint16_t startHandle, uint16_t valueHandle,
73 Uuid uuid, bool isByUuid, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
74 void DiscoverCharacteristicByUUIDParsing(
75 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
76 void DiscoverAllCharacteristicDescriptorsParsing(
77 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
78 void ReadCharacteristicValueParsing(
79 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
80 void ReadLongCharacteristicValueParsing(
81 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
82 void ReadUsingCharacteristicByUuidParsing(
83 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
84 void ReadMultipleCharacteristicParsing(
85 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
86 void ReadCharacteristicDescriptorsParsing(
87 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
88 void ReadLongCharacteristicDescriptorsParsing(
89 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
90 void WriteCharacteristicValueParsing(
91 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
92 void WriteCharacteristicDescriptorsParsing(
93 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
94 void WriteLongCharacteristicValueParsing(uint16_t connectHandle, uint16_t handle, uint16_t offset, Buffer *buffer,
95 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
96 void ExecuteWriteParsing(uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
97 void NotificationParsing(uint16_t connectHandle, AttEventData *data, Buffer *buffer);
98 void IndicationParsing(uint16_t connectHandle, const AttEventData *data, Buffer *buffer);
99 void GattRequestTimeoutParsing(int reqId, uint16_t connectHandle, ResponesType respType);
100 static int ConvertResponseErrorCode(uint8_t errorCode);
101 void SplitReadByTypeRsp(
102 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
103 void SplitReadRsp(
104 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
105 void SplitReadBlobRsp(
106 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
107 void SplitWriteRsp(uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
108 void SplitPrepareWriteRsp(uint16_t connectHandle, AttEventData *data, Buffer *buffer,
109 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
110 void SplitReadByTypeReqErrorParsing(
111 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
112 void SplitReadReqErrorParsing(
113 int reqId, uint16_t connectHandle, ResponesType respType, uint16_t handle, int result);
114 void SplitWriteReqErrorParsing(
115 int reqId, uint16_t connectHandle, ResponesType respType, uint16_t handle, int result);
116 static uint16_t SplitDataPackageToUint16(uint8_t *src, uint8_t *offset);
117 static uint8_t SplitDataPackageToUint8(const uint8_t *src, uint8_t *offset);
118 static void SplitDataPackage(uint8_t *dest, uint8_t destMax, uint8_t *offset, uint8_t *src, uint8_t size);
119 static Uuid SplitUuidPackage(const uint8_t *value, uint8_t len);
120 void AddReadValueCache(uint16_t connectHandle, uint16_t handle, uint16_t offset, Buffer *data);
121 uint8_t *GetReadValueCache(uint16_t connectHandle, uint16_t handle);
122 void CreateCache(uint16_t connectHandle, const GattDevice device);
123 void DeleteCache(uint16_t connectHandle, const GattDevice device);
124 void DeleteList(uint16_t connectHandle);
125 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByRequestInfor(uint16_t connectHandle);
126 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByRespones(
127 ResponesType reqType, int reqId);
128 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByResponesInfor(
129 uint16_t handle, uint16_t respType);
130 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByResponesInfor(
131 uint16_t handle, ResponesType respType);
132 };
133 /**
134 * @brief A constructor used to create <pClientCallbackFunc> and <dispatcher> instance..
135 *
136 * @since 6.0
137
138 */
GattClientProfile(GattClientProfileCallback * pClientCallbackFunc,utility::Dispatcher * dispatcher)139 GattClientProfile::GattClientProfile(GattClientProfileCallback *pClientCallbackFunc, utility::Dispatcher *dispatcher)
140 : pimpl(new (std::nothrow)GattClientProfile::impl(pClientCallbackFunc, dispatcher, *this))
141 {
142 pimpl->RegisterCallbackToConnectManager();
143 }
144 /**
145 * @brief A destructor used to delete the <pClientCallbackFunc> and <dispatcher> instance.
146 *
147 * @since 6.0
148 */
~GattClientProfile()149 GattClientProfile::~GattClientProfile()
150 {
151 pimpl->DeregisterCallbackToConnectManager();
152 }
153 /**
154 * @brief Enable gatt client profile.
155 *
156 * @since 6.0
157 */
Enable() const158 void GattClientProfile::Enable() const
159 {
160 pimpl->cacheMap_.clear();
161 pimpl->requestList_.clear();
162 pimpl->responseList_.clear();
163 pimpl->mtuInfo_.clear();
164 pimpl->RegisterCallbackToATT();
165 }
166 /**
167 * @brief Disable gatt client profile.
168 *
169 * @since 6.0
170 */
Disable() const171 void GattClientProfile::Disable() const
172 {
173 pimpl->DeregisterCallbackToATT();
174 }
175 /**
176 * @brief Register callback function to ATT.
177 *
178 * @since 6.0
179 */
RegisterCallbackToATT()180 void GattClientProfile::impl::RegisterCallbackToATT()
181 {
182 LOG_INFO("%{public}s", __FUNCTION__);
183 attCallback attDataCallback = GattClientProfile::impl::ReceiveData;
184 attSendDataCallback attReqCallback = GattClientProfile::impl::ReceiveRequestResult;
185
186 ATT_ClientDataRegister(attDataCallback, this);
187 ATT_ClientSendDataRegister(attReqCallback, this);
188 }
189 /**
190 * @brief Unregister callback function to att.
191 *
192 * @since 6.0
193 */
DeregisterCallbackToATT()194 void GattClientProfile::impl::DeregisterCallbackToATT()
195 {
196 LOG_INFO("%{public}s", __FUNCTION__);
197 ATT_ClientDataDeregister();
198 ATT_ClientSendDataDeRegister();
199 }
200 /**
201 * @brief This sub-procedure is used by the client to set the ATT_MTU to the maximum possible value.
202 *
203 * @param reqId Indicates request id.
204 * @param connectHandle Indicates identify a connection.
205 * @param mtu Indicates att bearer transmission unit.
206 * @since 6.0
207 */
ExchangeMtu(int reqId,uint16_t connectHandle,uint16_t mtu) const208 void bluetooth::GattClientProfile::ExchangeMtu(int reqId, uint16_t connectHandle, uint16_t mtu) const
209 {
210 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
211 if (GattConnectionManager::GetInstance().GetDeviceTransport(connectHandle) == GATT_TRANSPORT_TYPE_CLASSIC) {
212 pimpl->pClientCallBack_->OnExchangeMtuEvent(reqId, connectHandle, DEFAULT_CLASSIC_CONNECTION_MTU, false);
213 } else if (!pimpl->GetMtuInformation(connectHandle).isExchanged_) {
214 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(EXCHANGE_MTU, mtu, reqId));
215 LOG_DEBUG("%{public}s: Add requestList_: EXCHANGE_MTU", __FUNCTION__);
216 ATT_ExchangeMTURequest(connectHandle, mtu);
217 } else {
218 pimpl->pClientCallBack_->OnExchangeMtuEvent(
219 reqId, connectHandle, pimpl->GetMtuInformation(connectHandle).mtu_, false);
220 }
221 }
222 /**
223 * @brief This sub-procedure is used by a client to discover all the primary services on a server.
224 *
225 * @param reqId Indicates request id.
226 * @param connectHandle Indicates identify a connection.
227 * @param startHandle Indicates starting handle of the specified service.
228 * @param endHandle Indicates ending handle of the specified service.n.
229 * @since 6.0
230 */
DiscoverAllPrimaryServices(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const231 void bluetooth::GattClientProfile::DiscoverAllPrimaryServices(
232 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
233 {
234 LOG_INFO("%{public}s: connectHandle is %hu, Add requestList_: DISCOVER_ALL_PRIMARY_SERVICE.", __FUNCTION__, connectHandle);
235 BtUuid primarySvcUuid = {BT_UUID_16, {UUID_PRIMARY_SERVICE}};
236 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(DISCOVER_ALL_PRIMARY_SERVICE, reqId));
237 ATT_ReadByGroupTypeRequest(connectHandle, startHandle, endHandle, &primarySvcUuid);
238 }
239
240 /**
241 * @brief This sub-procedure is used by a client to discover all the primary services on a server.
242 *
243 * @param reqId Indicates request id.
244 * @param connectHandle Indicates identify a connection.
245 * @param startHandle Indicates starting handle of the specified service.
246 * @param endHandle Indicates ending handle of the specified service.n.
247 * @since 6.0
248 */
DiscoverAllPrimaryServicesInter(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const249 void bluetooth::GattClientProfile::DiscoverAllPrimaryServicesInter(
250 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
251 {
252 LOG_INFO("%{public}s: connectHandle is %{public}hu, Add requestList_: DISCOVER_ALL_PRIMARY_SERVICE.",
253 __FUNCTION__, connectHandle);
254 auto iter = pimpl->FindIteratorByRespones(DISCOVER_ALL_PRIMARY_SERVICE, reqId);
255 if (iter == pimpl->responseList_.end()) {
256 LOG_INFO("%{public}s: not find connectionHandle(%{public}hu) in response list", __FUNCTION__, connectHandle);
257 return;
258 }
259 pimpl->responseList_.erase(iter);
260
261 BtUuid primarySvcUuid = {BT_UUID_16, {UUID_PRIMARY_SERVICE}};
262 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(DISCOVER_ALL_PRIMARY_SERVICE, reqId));
263 ATT_ReadByGroupTypeRequest(connectHandle, startHandle, endHandle, &primarySvcUuid);
264 }
265
266 /**
267 * @brief This sub-procedure is used by a client to discover a specific primary service on a server when only
268 * the Service UUID is known.
269 *
270 * @param reqId Indicates request id.
271 * @param connectHandle Indicates identify a connection.
272 * @param uuid Indicates service uuid.
273 * @since 6.0
274 */
DiscoverPrimaryServicesByServiceUuid(int reqId,uint16_t connectHandle,const Uuid & uuid) const275 void GattClientProfile::DiscoverPrimaryServicesByServiceUuid(int reqId, uint16_t connectHandle, const Uuid &uuid) const
276 {
277 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
278 uint8_t uuid128[UUID_128BIT_LEN] = {0};
279 Buffer *serviceUuid = BufferMalloc(uuid.GetUuidType());
280 AttFindByTypeValueReq parameter;
281 parameter.attType = UUID_PRIMARY_SERVICE;
282 parameter.handleRange.startHandle = MIN_ATTRIBUTE_HANDLE;
283 parameter.handleRange.endHandle = MAX_ATTRIBUTE_HANDLE;
284
285 if (uuid.GetUuidType() == UUID_16BIT_LEN) {
286 uint16_t uuid16 = uuid.ConvertTo16Bits();
287 (void)memcpy_s(BufferPtr(serviceUuid), UUID_16BIT_LEN, &(uuid16), UUID_16BIT_LEN);
288 pimpl->requestList_.emplace_back(
289 std::make_pair(connectHandle, GattRequestInfo(uuid, DISCOVER_SERVICE_BY_UUID, reqId)));
290 } else if (uuid.GetUuidType() == UUID_32BIT_LEN) {
291 uint32_t uuid32 = uuid.ConvertTo32Bits();
292 (void)memcpy_s(BufferPtr(serviceUuid), UUID_32BIT_LEN, &(uuid32), UUID_32BIT_LEN);
293 pimpl->requestList_.emplace_back(
294 std::make_pair(connectHandle, GattRequestInfo(uuid, DISCOVER_SERVICE_BY_UUID, reqId)));
295 } else if (uuid.GetUuidType() == UUID_128BIT_LEN) {
296 uuid.ConvertToBytesLE(uuid128, UUID_128BIT_LEN);
297 (void)memcpy_s(BufferPtr(serviceUuid), UUID_128BIT_LEN, uuid128, UUID_128BIT_LEN);
298 pimpl->requestList_.emplace_back(
299 std::make_pair(connectHandle, GattRequestInfo(uuid, DISCOVER_SERVICE_BY_UUID, reqId)));
300 } else {
301 BufferFree(serviceUuid);
302 LOG_ERROR("%{public}s: Service UUID length is failed", __FUNCTION__);
303 return;
304 }
305 ATT_FindByTypeValueRequest(connectHandle, ¶meter, serviceUuid);
306 BufferFree(serviceUuid);
307 }
308 /**
309 * @brief This sub-procedure is used by a client to find include service declarations within a service definition
310 * on a server.
311 *
312 * @param reqId Indicates request id.
313 * @param connectHandle Indicates identify a connection.
314 * @param startHandle Indicates starting handle of the specified service.
315 * @param endHandle Indicates ending handle of the specified service.
316 * @since 6.0
317 */
FindIncludedServices(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const318 void GattClientProfile::FindIncludedServices(
319 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
320 {
321 LOG_INFO("%{public}s Parameter startHandle is %hu, endHandle is %hu", __FUNCTION__, startHandle, endHandle);
322 BtUuid includeSvcUuid = {BT_UUID_16, {UUID_INCLUDE_SERVICE}};
323
324 auto iter = pimpl->cacheMap_.find(connectHandle)->second.GetIncludeServices(startHandle);
325 if (iter != nullptr) {
326 iter->clear();
327 }
328 pimpl->requestList_.emplace_back(
329 connectHandle, GattRequestInfo(FIND_INCLUDE_SERVICE, startHandle, endHandle, reqId));
330 LOG_DEBUG("%{public}s: Add requestList_: FIND_INCLUDE_SERVICE", __FUNCTION__);
331 ATT_ReadByTypeRequest(connectHandle, startHandle, endHandle, &includeSvcUuid);
332 }
333 /**
334 * @brief This sub-procedure is used by a client to find all the characteristic declarations within a service
335 * definition on a server.
336 *
337 * @param reqId Indicates request id.
338 * @param connectHandle Indicates identify a connection.
339 * @param startHandle Indicates starting handle of the specified service.
340 * @param endHandle Indicates ending handle of the specified service.
341 * @since 6.0
342 */
DiscoverAllCharacteristicOfService(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const343 void GattClientProfile::DiscoverAllCharacteristicOfService(
344 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
345 {
346 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
347 Uuid tempUuid;
348 BtUuid characteristicUuid = {BT_UUID_16, {UUID_CHARACTERISTIC}};
349
350 auto iter = pimpl->cacheMap_.find(connectHandle)->second.GetCharacteristics(startHandle);
351 if (iter != nullptr) {
352 iter->clear();
353 }
354
355 pimpl->requestList_.emplace_back(connectHandle,
356 GattRequestInfo(DISCOVER_ALL_CHARACTERISTIC,
357 startHandle,
358 endHandle,
359 tempUuid.ConvertFrom16Bits(UUID_CHARACTERISTIC),
360 reqId));
361 LOG_DEBUG("%{public}s: Add requestList_: DISCOVER_ALL_CHARACTERISTIC", __FUNCTION__);
362 ATT_ReadByTypeRequest(connectHandle, startHandle, endHandle, &characteristicUuid);
363 }
364 /**
365 * @brief This sub-procedure is used by a client to discover service characteristics on a server when only the
366 * service handle ranges are known and the characteristic UUID is known.
367 *
368 * @param reqId Indicates request id.
369 * @param connectHandle Indicates identify a connection.
370 * @param startHandle Indicates starting handle of the specified service.
371 * @param endHandle Indicates ending handle of the specified service.
372 * @param uuid Indicates characteristic uuid.
373 * @since 6.0
374 */
DiscoverCharacteristicByUuid(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle,const Uuid & uuid) const375 void GattClientProfile::DiscoverCharacteristicByUuid(
376 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle, const Uuid &uuid) const
377 {
378 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
379 BtUuid tempUuid;
380 uint8_t uuid128[UUID_128BIT_LEN] = {0};
381
382 auto iter = pimpl->cacheMap_.find(connectHandle)->second.GetCharacteristics(startHandle);
383 if (iter != nullptr) {
384 iter->clear();
385 }
386
387 if (uuid.GetUuidType() == UUID_16BIT_LEN) {
388 tempUuid = {BT_UUID_16, {uuid.ConvertTo16Bits()}};
389 pimpl->requestList_.emplace_back(connectHandle,
390 GattRequestInfo(DISCOVER_CHARACTERISTIC_BY_UUID,
391 startHandle,
392 endHandle,
393 uuid.ConvertFrom16Bits(tempUuid.uuid16),
394 reqId));
395 } else if (uuid.GetUuidType() == UUID_32BIT_LEN) {
396 tempUuid = {.type = BT_UUID_32, .uuid32 = uuid.ConvertTo32Bits()};
397 pimpl->requestList_.emplace_back(connectHandle,
398 GattRequestInfo(DISCOVER_CHARACTERISTIC_BY_UUID,
399 startHandle,
400 endHandle,
401 uuid.ConvertFrom32Bits(tempUuid.uuid32),
402 reqId));
403 } else if (uuid.GetUuidType() == UUID_128BIT_LEN) {
404 uuid.ConvertToBytesLE(uuid128, UUID_128BIT_LEN);
405 tempUuid.type = BT_UUID_128;
406 (void)memcpy_s(tempUuid.uuid128, UUID_128BIT_LEN, uuid128, UUID_128BIT_LEN);
407 pimpl->requestList_.emplace_back(connectHandle,
408 GattRequestInfo(DISCOVER_CHARACTERISTIC_BY_UUID,
409 startHandle,
410 endHandle,
411 uuid.ConvertFromBytesLE(tempUuid.uuid128, UUID_128BIT_LEN),
412 reqId));
413 } else {
414 LOG_ERROR("%{public}s: Call - ATT_ReadByTypeRequest - Fail!", __FUNCTION__);
415 return;
416 }
417 ATT_ReadByTypeRequest(connectHandle, startHandle, endHandle, &tempUuid);
418 }
419 /**
420 * @brief This sub-procedure is used by a client to find all the characteristic descriptor’s
421 * Attribute Handles and Attribute Types.
422 *
423 * @param reqId Indicates request id.
424 * @param connectHandle Indicates identify a connection.
425 * @param startHandle Indicates starting handle of the specified service.
426 * @param endHandle Indicates ending handle of the specified service.
427 * @since 6.0
428 */
DiscoverAllCharacteristicDescriptors(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const429 void GattClientProfile::DiscoverAllCharacteristicDescriptors(
430 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
431 {
432 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
433 // startHandle is handle of characteristic declaration
434 if (startHandle != INVALID_ATTRIBUTE_HANDLE && startHandle <= endHandle - sizeof(startHandle) &&
435 startHandle <= MAX_ATTRIBUTE_HANDLE - sizeof(startHandle)) {
436 pimpl->requestList_.emplace_back(
437 connectHandle, GattRequestInfo(DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR, startHandle, endHandle, reqId));
438 LOG_DEBUG("%{public}s: Add requestList_: DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
439 ATT_FindInformationRequest(connectHandle, startHandle + sizeof(startHandle), endHandle);
440 } else {
441 LOG_DEBUG("%{public}s: No descriptor value in the characteristic", __FUNCTION__);
442 uint16_t serviceHandle = pimpl->cacheMap_.find(connectHandle)->second.GetDescriptors(startHandle).second;
443 pimpl->pClientCallBack_->OnDiscoverAllCharacteristicDescriptorsEvent(reqId,
444 GATT_SUCCESS,
445 serviceHandle,
446 startHandle,
447 *pimpl->cacheMap_.find(connectHandle)->second.GetDescriptors(startHandle).first);
448 }
449 }
450 /**
451 * @brief This sub-procedure is used to read a Characteristic Value from a server.
452 *
453 * @param reqId Indicates request id.
454 * @param connectHandle Indicates identify a connection.
455 * @param handle Indicates attribute handle.
456 * @since 6.0
457 */
ReadCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle) const458 void bluetooth::GattClientProfile::ReadCharacteristicValue(int reqId, uint16_t connectHandle, uint16_t handle) const
459 {
460 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
461 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(READ_CHARACTERISTIC_VALUE, handle, reqId));
462 LOG_DEBUG("%{public}s: Add requestList_: READ_CHARACTERISTIC_VALUE", __FUNCTION__);
463 ATT_ReadRequest(connectHandle, handle);
464 }
465 /**
466 * @brief This sub-procedure is used to read a Characteristic Value by uuid from a server.
467 *
468 * @param reqId Indicates request id.
469 * @param connectHandle Indicates identify a connection.
470 * @param uuid Indicates characteristic uuid.
471 * @since 6.0
472 */
ReadUsingCharacteristicByUuid(int reqId,uint16_t connectHandle,const Uuid & uuid) const473 void GattClientProfile::ReadUsingCharacteristicByUuid(int reqId, uint16_t connectHandle, const Uuid &uuid) const
474 {
475 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
476 BtUuid tempUuid;
477 uint8_t uuid128[UUID_128BIT_LEN] = {0};
478
479 if (uuid.GetUuidType() == UUID_16BIT_LEN) {
480 tempUuid = {BT_UUID_16, {uuid.ConvertTo16Bits()}};
481 pimpl->requestList_.emplace_back(connectHandle,
482 GattRequestInfo(READ_USING_CHARACTERISTIC_UUID,
483 MIN_ATTRIBUTE_HANDLE,
484 MAX_ATTRIBUTE_HANDLE,
485 uuid.ConvertFrom16Bits(tempUuid.uuid16),
486 reqId));
487 LOG_DEBUG("%{public}s: Add requestList_: READ_USING_CHARACTERISTIC_UUID", __FUNCTION__);
488 } else if (uuid.GetUuidType() == UUID_128BIT_LEN) {
489 uuid.ConvertToBytesLE(uuid128, UUID_128BIT_LEN);
490 tempUuid.type = BT_UUID_128;
491 (void)memcpy_s(tempUuid.uuid128, UUID_128BIT_LEN, uuid128, UUID_128BIT_LEN);
492 pimpl->requestList_.emplace_back(connectHandle,
493 GattRequestInfo(READ_USING_CHARACTERISTIC_UUID,
494 MIN_ATTRIBUTE_HANDLE,
495 MAX_ATTRIBUTE_HANDLE,
496 uuid.ConvertFromBytesLE(tempUuid.uuid128, UUID_128BIT_LEN),
497 reqId));
498 LOG_DEBUG("%{public}s: Add requestList_: READ_USING_CHARACTERISTIC_UUID", __FUNCTION__);
499 } else {
500 LOG_ERROR("%{public}s: Call - ATT_ReadByTypeRequest - Fail!", __FUNCTION__);
501 return;
502 }
503 ATT_ReadByTypeRequest(connectHandle, MIN_ATTRIBUTE_HANDLE, MAX_ATTRIBUTE_HANDLE, &tempUuid);
504 }
505 /**
506 * @brief This sub-procedure is used to read a long characteristic values from a server.
507 *
508 * @param reqId Indicates request id.
509 * @param connectHandle Indicates identify a connection.
510 * @param handle Indicates attribute handle.
511 * @since 6.0
512 */
ReadLongCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle) const513 void GattClientProfile::ReadLongCharacteristicValue(int reqId, uint16_t connectHandle, uint16_t handle) const
514 {
515 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
516 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(READ_LONG_CHARACTERISTIC_VALUE, handle, reqId));
517 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_VALUE", __FUNCTION__);
518 ATT_ReadRequest(connectHandle, handle);
519 }
520 /**
521 * @brief This sub-procedure is used to read multiple characteristic values.
522 *
523 * @param reqId Indicates request id.
524 * @param connectHandle Indicates identify a connection.
525 * @param value Indicates attribute handle list.
526 * @param len Indicates size of value.
527 * @since 6.0
528 */
ReadMultipleCharacteristicValue(int reqId,uint16_t connectHandle,const GattValue & value,size_t len) const529 void GattClientProfile::ReadMultipleCharacteristicValue(
530 int reqId, uint16_t connectHandle, const GattValue &value, size_t len) const
531 {
532 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
533 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
534 if (buffer != nullptr) {
535 pimpl->requestList_.emplace_back(
536 connectHandle, GattRequestInfo(READ_MULTIPLE_CHARACTERISTIC, MIN_ATTRIBUTE_HANDLE, reqId));
537 LOG_DEBUG("%{public}s: Add requestList_: READ_MULTIPLE_CHARACTERISTIC", __FUNCTION__);
538 ATT_ReadMultipleRequest(connectHandle, buffer);
539 BufferFree(buffer);
540 }
541 }
542 /**
543 * @brief This sub-procedure is used to read a characteristic descriptor from a server.
544 *
545 * @param reqId Indicates request id.
546 * @param connectHandle Indicates identify a connection.
547 * @param handle Indicates attribute handle.
548 * @since 6.0
549 */
ReadDescriptorValue(int reqId,uint16_t connectHandle,uint16_t handle) const550 void GattClientProfile::ReadDescriptorValue(int reqId, uint16_t connectHandle, uint16_t handle) const
551 {
552 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
553 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(READ_CHARACTERISTIC_DESCRIPTOR, handle, reqId));
554 LOG_DEBUG("%{public}s: Add requestList_: READ_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
555 ATT_ReadRequest(connectHandle, handle);
556 }
557 /**
558 * @brief This sub-procedure is used to read a characteristic descriptor from a server and the length of the
559 * characteristic descriptor declaration is longer than can be sent in a single Read Response Attribute
560 * Protocol message..
561 *
562 * @param reqId Indicates request id.
563 * @param connectHandle Indicates identify a connection.
564 * @param handle Indicates attribute handle.
565 * @since 6.0
566 */
ReadLongCharacteristicDescriptor(int reqId,uint16_t connectHandle,uint16_t handle) const567 void GattClientProfile::ReadLongCharacteristicDescriptor(int reqId, uint16_t connectHandle, uint16_t handle) const
568 {
569 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
570 pimpl->requestList_.emplace_back(
571 connectHandle, GattRequestInfo(READ_LONG_CHARACTERISTIC_DESCRIPTOR, handle, reqId));
572 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
573 ATT_ReadRequest(connectHandle, handle);
574 }
575 /**
576 * @brief This sub-procedure is used to write a Characteristic Value to a server when the client knows the
577 * Characteristic Value Handle and the client does not need an acknowledgment that the write was successfully
578 * performed.
579 *
580 * @param reqId Indicates request id.
581 * @param connectHandle Indicates identify a connection.
582 * @param handle Indicates attribute handle.
583 * @param value Indicates value of the schedule settings.
584 * @param len Indicates size of value.
585 * @since 6.0
586 */
WriteWithoutResponse(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const587 void GattClientProfile::WriteWithoutResponse(
588 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
589 {
590 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
591 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
592 if (buffer != nullptr) {
593 ATT_WriteCommand(connectHandle, handle, buffer);
594 BufferFree(buffer);
595 }
596 }
597 /**
598 * @brief This sub-procedure is used to write a Characteristic Value to a server when the client knows the
599 * Characteristic Value Handle and the ATT Bearer is not encrypted.
600 *
601 * @param reqId Indicates request id.
602 * @param connectHandle Indicates identify a connection.
603 * @param handle Indicates attribute handle.
604 * @param value Indicates value of the schedule settings.
605 * @param len Indicates size of value.
606 * @since 6.0
607 */
SignedWriteWithoutResponse(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const608 void GattClientProfile::SignedWriteWithoutResponse(
609 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
610 {
611 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
612 if (GattConnectionManager::GetInstance().GetEncryptionInfo(connectHandle) != false) {
613 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
614 if (buffer != nullptr) {
615 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(WRITE_WITHOUT_RESPONSE, reqId));
616 LOG_DEBUG("%{public}s: Add requestList_: WRITE_WITHOUT_RESPONSE", __FUNCTION__);
617 ATT_SignedWriteCommand(connectHandle, handle, buffer);
618 BufferFree(buffer);
619 }
620 } else {
621 WriteWithoutResponse(reqId, connectHandle, handle, value, len);
622 }
623 }
624 /**
625 * @brief This sub-procedure is used to write a Characteristic Value to a server when the client knows the
626 * Characteristic Value Handle.
627 *
628 * @param reqId Indicates request id.
629 * @param connectHandle Indicates identify a connection.
630 * @param handle Indicates attribute handle.
631 * @param value Indicates value of the schedule settings.
632 * @param len Indicates size of value.
633 * @since 6.0
634 */
WriteCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const635 void bluetooth::GattClientProfile::WriteCharacteristicValue(
636 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
637 {
638 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
639 uint16_t mtu = pimpl->GetMtuInformation(connectHandle).mtu_;
640 if (len <= static_cast<size_t>(mtu - 0x03)) {
641 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
642 if (buffer != nullptr) {
643 pimpl->requestList_.emplace_back(
644 connectHandle, GattRequestInfo(WRITE_CHARACTERISTIC_VALUE, handle, reqId));
645 LOG_DEBUG("%{public}s: Add requestList_: WRITE_CHARACTERISTIC_VALUE", __FUNCTION__);
646 ATT_WriteRequest(connectHandle, handle, buffer);
647 BufferFree(buffer);
648 }
649 } else {
650 WriteLongCharacteristicValue(reqId, connectHandle, handle, value, len);
651 }
652 }
653 /**
654 * @brief This sub-procedure is used to write a Characteristic Value to a server when the client knows the
655 * Characteristic Value Handle but the length of theCharacteristic Value is longer than can be sent in a
656 * single Write Request Attribute Protocol message.
657 *
658 * @param reqId Indicates request id.
659 * @param connectHandle Indicates identify a connection.
660 * @param handle Indicates attribute handle.
661 * @param value Indicates value of the schedule settings.
662 * @param len Indicates size of value.
663 * @since 6.0
664 */
WriteLongCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const665 void GattClientProfile::WriteLongCharacteristicValue(
666 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
667 {
668 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
669 uint16_t bufSize = pimpl->GetMtuInformation(connectHandle).mtu_ - 0x05;
670 AttReadBlobReqPrepareWriteValue attReadBlobObj = {handle, bufSize};
671 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), 0x00, bufSize);
672 if (buffer != nullptr) {
673 pimpl->requestList_.emplace_back(
674 connectHandle, GattRequestInfo(WRITE_LONG_CHARACTERISTIC_VALUE, handle, bufSize, len, value, reqId));
675 LOG_DEBUG("%{public}s: Add requestList_: WRITE_LONG_CHARACTERISTIC_VALUE", __FUNCTION__);
676 ATT_PrepareWriteRequest(connectHandle, attReadBlobObj, buffer);
677 BufferFree(buffer);
678 }
679 }
680 /**
681 * @brief This sub-procedure is used to write a characteristic descriptor value to a server when the client
682 * knows the characteristic descriptor handle.
683 *
684 * @param reqId Indicates request id.
685 * @param connectHandle Indicates identify a connection.
686 * @param handle Indicates attribute handle.
687 * @param value Indicates value of the schedule settings.
688 * @param len Indicates size of value.
689 * @since 6.0
690 */
WriteDescriptorValue(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const691 void GattClientProfile::WriteDescriptorValue(
692 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
693 {
694 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
695 uint16_t mtu = pimpl->GetMtuInformation(connectHandle).mtu_;
696 if (len <= static_cast<size_t>(mtu - 0x03)) {
697 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
698 if (buffer != nullptr) {
699 pimpl->requestList_.emplace_back(
700 connectHandle, GattRequestInfo(WRITE_CHARACTERISTIC_DESCRIPTOR, handle, reqId));
701 LOG_DEBUG("%{public}s: Add requestList_: WRITE_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
702 ATT_WriteRequest(connectHandle, handle, buffer);
703 BufferFree(buffer);
704 }
705 } else {
706 WriteLongCharacteristicDescriptor(reqId, connectHandle, handle, value, len);
707 }
708 }
709 /**
710 * @brief This sub-procedure is used to write a characteristic descriptor value to a server when the client
711 * knows the characteristic descriptor handle but the length of the characteristic descriptor value is
712 * longer than can be sent in a single write request attribute protocol message.
713 *
714 * @param reqId Indicates request id.
715 * @param connectHandle Indicates identify a connection.
716 * @param handle Indicates attribute handle.
717 * @param value Indicates value of the schedule settings.
718 * @param len Indicates size of value.
719 * @since 6.0
720 */
WriteLongCharacteristicDescriptor(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const721 void GattClientProfile::WriteLongCharacteristicDescriptor(
722 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
723 {
724 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
725 WriteLongCharacteristicValue(reqId, connectHandle, handle, value, len);
726 }
727 /**
728 * @brief This sub-procedure is used to write a Characteristic Value to a server when the
729 * client knows the Characteristic Value Handle, and assurance is required that the
730 * correct Characteristic Value is going to be written by transferring the Characteristic
731 * Value to be written in both directions before the write is performed.
732 *
733 * @param reqId Indicates request id.
734 * @param connectHandle Indicates identify a connection.
735 * @param handle Indicates attribute handle.
736 * @param value Indicates value of the schedule settings.
737 * @param len Indicates size of value.
738 * @since 6.0
739 */
ReliableWriteCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const740 void GattClientProfile::ReliableWriteCharacteristicValue(
741 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
742 {
743 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
744 AttReadBlobReqPrepareWriteValue attReadBlobObj = {handle, 0};
745 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), 0x00, len);
746
747 if (buffer != nullptr) {
748 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(RELIABLE_WRITE_VALUE, reqId));
749 LOG_DEBUG("%{public}s: Add requestList_: RELIABLE_WRITE_VALUE", __FUNCTION__);
750 ATT_PrepareWriteRequest(connectHandle, attReadBlobObj, buffer);
751 BufferFree(buffer);
752 }
753 }
754 /**
755 * @brief The Attribute Flags parameter shall be set to 0x01 to immediately write all
756 * pending prepared values in the order that they were prepared.
757 *
758 * @param reqId Indicates request id.
759 * @param connectHandle Indicates identify a connection.
760 * @param flag Indicates 0x00 – Cancel all prepared writes.
761 * 0x01 – Immediately write all pending prepared values.
762 * @since 6.0
763 */
ExecuteWriteRequest(int reqId,uint16_t connectHandle,uint8_t flag) const764 void GattClientProfile::ExecuteWriteRequest(int reqId, uint16_t connectHandle, uint8_t flag) const
765 {
766 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
767 ATT_ExecuteWriteRequest(connectHandle, flag);
768 }
769
770 /**
771 * @brief This sub-procedure is used when a server is configured to indicate a Characteristic Value to a client
772 * and expects an Attribute Protocollayer acknowledgment that the indication was successfully received.
773 *
774 * @param connectHandle Indicates identify a connection.
775 * @since 6.0
776 */
HandleValueConfirmation(uint16_t connectHandle) const777 void GattClientProfile::HandleValueConfirmation(uint16_t connectHandle) const
778 {
779 ATT_HandleValueConfirmation(connectHandle);
780 }
781
GetServices(uint16_t connectHandle) const782 std::map<uint16_t, GattCache::Service> *GattClientProfile::GetServices(uint16_t connectHandle) const
783 {
784 auto cache = pimpl->cacheMap_.find(connectHandle);
785 if (cache != pimpl->cacheMap_.end()) {
786 return &cache->second.GetServices();
787 }
788 return nullptr;
789 }
790
GetCharacteristicEndHandle(uint16_t connectHandle,uint16_t svcHandle,uint16_t handle) const791 uint16_t GattClientProfile::GetCharacteristicEndHandle(
792 uint16_t connectHandle, uint16_t svcHandle, uint16_t handle) const
793 {
794 auto cache = pimpl->cacheMap_.find(connectHandle);
795 if (cache != pimpl->cacheMap_.end()) {
796 return cache->second.GetCharacteristicEndHandle(svcHandle, handle);
797 }
798 return 0;
799 }
800
801 /**
802 * @brief This sub-procedure is used by the client to obtain services.
803 *
804 * @param connectHandle Indicates identify a connection.
805 * @param handle Indicates attribute handle.
806 * @return Returns service pointer.
807 * @since 6.0
808 */
GetService(uint16_t connectHandle,int16_t handle) const809 const GattCache::Service *GattClientProfile::GetService(uint16_t connectHandle, int16_t handle) const
810 {
811 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
812 auto cache = pimpl->cacheMap_.find(connectHandle);
813 if (cache != pimpl->cacheMap_.end()) {
814 auto sIt = cache->second.GetServices().find(handle);
815 if (sIt != cache->second.GetServices().end()) {
816 return &sIt->second;
817 }
818 }
819 return nullptr;
820 }
821 /**
822 * @brief This sub-procedure is used by the client to obtain characteristics.
823 *
824 * @param connectHandle Indicates identify a connection.
825 * @param valueHandle Indicates attribute handle.
826 * @return Returns characteristics pointer.
827 * @since 6.0
828 */
GetCharacteristic(uint16_t connectHandle,int16_t valueHandle) const829 const GattCache::Characteristic *GattClientProfile::GetCharacteristic(
830 uint16_t connectHandle, int16_t valueHandle) const
831 {
832 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
833 auto cache = pimpl->cacheMap_.find(connectHandle);
834 if (cache != pimpl->cacheMap_.end()) {
835 return cache->second.GetCharacteristic(valueHandle);
836 }
837 return nullptr;
838 }
839 /**
840 * @brief This sub-procedure is used by the client to obtain characteristic descriptors.
841 *
842 * @param connectHandle Indicates identify a connection.
843 * @param valueHandle Indicates attribute handle.
844 * @return Returns descriptors pointer.
845 * @since 6.0
846 */
GetDescriptor(uint16_t connectHandle,int16_t valueHandle) const847 const GattCache::Descriptor *GattClientProfile::GetDescriptor(uint16_t connectHandle, int16_t valueHandle) const
848 {
849 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
850 auto cache = pimpl->cacheMap_.find(connectHandle);
851 if (cache != pimpl->cacheMap_.end()) {
852 return cache->second.GetDescriptor(valueHandle);
853 }
854 return nullptr;
855 }
856 /**
857 * @brief This sub-procedure is used by the client to process received data from att.
858 *
859 * @param connectHandle Indicates identify a connection.
860 * @param event Indicates client callback event id.
861 * @param eventData Indicates att data.
862 * @param buffer Indicates att data.
863 * @param context Indicates client callback function.
864 * @since 6.0
865 */
ReceiveData(uint16_t connectHandle,uint16_t event,void * eventData,Buffer * buffer,void * context)866 void GattClientProfile::impl::ReceiveData(
867 uint16_t connectHandle, uint16_t event, void *eventData, Buffer *buffer, void *context)
868 {
869 LOG_INFO("GattClientProfile::%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
870 AttEventData *data = (AttEventData *)eventData;
871 auto object = static_cast<GattClientProfile::impl *>(context);
872
873 if (event == ATT_HANDLE_VALUE_NOTIFICATION_ID) {
874 object->NotificationParsing(connectHandle, data, buffer);
875 } else if (event == ATT_HANDLE_VALUE_INDICATION_ID) {
876 object->IndicationParsing(connectHandle, data, buffer);
877 } else {
878 auto attResp = object->FindIteratorByResponesInfor(connectHandle, event);
879 if (attResp == object->responseList_.end()) {
880 LOG_INFO("%{public}s: attResp is null", __FUNCTION__);
881 return;
882 }
883 object->ReceiveDataProcess(connectHandle, event, data, buffer, attResp);
884 object->responseList_.erase(attResp);
885 }
886 }
887 /**
888 * @brief This sub-procedure is used by removing request list.
889 *
890 * @param connectHandle Indicates identify a connection.
891 * @param connectHandle Indicates identify a connection.
892 * @param event Indicates client callback event id.
893 * @param data Indicates att data.
894 * @param buffer Indicates att data.
895 * @param attResp Indicates iterator of client request information.
896 * @since 6.0
897 */
ReceiveDataProcess(uint16_t connectHandle,uint16_t event,AttEventData * data,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator attResp)898 void GattClientProfile::impl::ReceiveDataProcess(uint16_t connectHandle, uint16_t event, AttEventData *data,
899 Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator attResp)
900 {
901 switch (event) {
902 case ATT_ERROR_RESPONSE_ID:
903 ErrorResponseParsing(connectHandle, data, attResp);
904 break;
905 case ATT_EXCHANGE_MTU_RESPONSE_ID:
906 ExchangeMtuParsing(connectHandle, data, attResp);
907 break;
908 case ATT_FIND_INFORMATION_RESPONSE_ID:
909 DiscoverAllCharacteristicDescriptorsParsing(connectHandle, data, attResp);
910 break;
911 case ATT_FIND_BY_TYPE_VALUE_RESPONSE_ID:
912 DiscoverPrimaryServiceByUuidParsing(connectHandle, data, attResp);
913 break;
914 case ATT_READ_BY_TYPE_RESPONSE_ID:
915 SplitReadByTypeRsp(connectHandle, data, attResp);
916 break;
917 case ATT_READ_RESPONSE_ID:
918 SplitReadRsp(connectHandle, buffer, attResp);
919 break;
920 case ATT_READ_BLOB_RESPONSE_ID:
921 SplitReadBlobRsp(connectHandle, buffer, attResp);
922 break;
923 case ATT_READ_MULTIPLE_RESPONSE_ID:
924 ReadMultipleCharacteristicParsing(connectHandle, buffer, attResp);
925 break;
926 case ATT_READ_BY_GROUP_TYPE_RESPONSE_ID:
927 DiscoverAllPrimaryServiceParsing(attResp->second.reqId_, connectHandle, data);
928 break;
929 case ATT_WRITE_RESPONSE_ID:
930 SplitWriteRsp(connectHandle, attResp);
931 break;
932 case ATT_PREPARE_WRITE_RESPONSE_ID:
933 SplitPrepareWriteRsp(connectHandle, data, buffer, attResp);
934 break;
935 case ATT_EXECUTE_WRITE_RESPONSE_ID:
936 ExecuteWriteParsing(connectHandle, attResp);
937 break;
938 case ATT_TRANSACTION_TIME_OUT_ID:
939 GattRequestTimeoutParsing(attResp->second.reqId_, connectHandle, attResp->second.reqType_);
940 break;
941 default:
942 LOG_ERROR("GATT client profile: %{public}s. It's invalid opcode.", __FUNCTION__);
943 break;
944 }
945 }
946 /**
947 * @brief This sub-procedure is used by the client to process received att request result.
948 *
949 * @param connectHandle Indicates identify a connection.
950 * @param result Indicates request result.
951 * @param context Indicates client callback function.
952 * @since 6.0
953 */
ReceiveRequestResult(uint16_t connectHandle,int result,void * context)954 void GattClientProfile::impl::ReceiveRequestResult(uint16_t connectHandle, int result, void *context)
955 {
956 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
957 auto object = static_cast<GattClientProfile::impl *>(context);
958
959 if (result == GATT_SUCCESS) {
960 object->AddResponseList();
961 } else {
962 object->dispatcher_->PostTask(std::bind(&impl::ReceiveRequestResultProcess, object, connectHandle));
963 }
964 }
965 /**
966 * @brief This sub-procedure is used by the client to process received att request result.
967 *
968 * @param connectHandle Indicates identify a connection.
969 * @since 6.0
970 */
ReceiveRequestResultProcess(uint16_t connectHandle)971 void GattClientProfile::impl::ReceiveRequestResultProcess(uint16_t connectHandle)
972 {
973 auto iter = FindIteratorByRequestInfor(connectHandle);
974 if (iter != requestList_.end()) {
975 IndicateRequestRetToService(iter->second.reqType_, connectHandle, iter->second.reqType_, ATT_OUT_OF_RANGE);
976 LOG_INFO("%{public}s: RemoveRequestList iter reqType: %{public}d", __FUNCTION__, iter->second.reqType_);
977 RemoveRequestList(iter);
978 } else {
979 LOG_ERROR("%{public}s: requestList_ is null", __FUNCTION__);
980 }
981 }
982 /**
983 * @brief This sub-procedure is used by the client to process indicating request result to service.
984 *
985 * @param connectHandle Indicates identify a connection.
986 * @param reqType Indicates send request type.
987 * @param errorCode Indicates error code.
988 * @since 6.0
989 */
IndicateRequestRetToService(int reqId,uint16_t connectHandle,ResponesType reqType,uint8_t errorCode)990 void GattClientProfile::impl::IndicateRequestRetToService(
991 int reqId, uint16_t connectHandle, ResponesType reqType, uint8_t errorCode)
992 {
993 int ret = ConvertResponseErrorCode(errorCode);
994 auto sharedPtr = GattValue(std::make_shared<std::unique_ptr<uint8_t[]>>(nullptr));
995
996 switch (reqType) {
997 case DISCOVER_ALL_PRIMARY_SERVICE:
998 pClientCallBack_->OnDiscoverAllPrimaryServicesEvent(
999 reqId, ret, connectHandle, std::map<uint16_t, GattCache::Service>());
1000 break;
1001 case DISCOVER_SERVICE_BY_UUID:
1002 pClientCallBack_->OnDiscoverPrimaryServicesByServiceUUIDEvent(
1003 reqId, ret, connectHandle, std::map<uint16_t, GattCache::Service>());
1004 break;
1005 case FIND_INCLUDE_SERVICE:
1006 pClientCallBack_->OnFindIncludedServicesEvent(
1007 reqId, ret, connectHandle, 0, std::vector<GattCache::IncludeService>());
1008 break;
1009 case DISCOVER_ALL_CHARACTERISTIC:
1010 case DISCOVER_CHARACTERISTIC_BY_UUID:
1011 pClientCallBack_->OnDiscoverAllCharacteristicOfServiceEvent(
1012 reqId, ret, connectHandle, 0, std::map<uint16_t, GattCache::Characteristic>());
1013 break;
1014 case DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR:
1015 pClientCallBack_->OnDiscoverAllCharacteristicDescriptorsEvent(
1016 reqId, ret, 0, 0, std::map<uint16_t, GattCache::Descriptor>());
1017 break;
1018 case READ_CHARACTERISTIC_VALUE:
1019 case READ_USING_CHARACTERISTIC_UUID:
1020 case READ_MULTIPLE_CHARACTERISTIC:
1021 pClientCallBack_->OnReadCharacteristicValueEvent(reqId, 0, sharedPtr, 0, ret);
1022 break;
1023 case READ_CHARACTERISTIC_DESCRIPTOR:
1024 case READ_LONG_CHARACTERISTIC_DESCRIPTOR:
1025 pClientCallBack_->OnReadDescriptorValueEvent(reqId, 0, sharedPtr, 0, ret);
1026 break;
1027 case WRITE_CHARACTERISTIC_VALUE:
1028 pClientCallBack_->OnWriteCharacteristicValueEvent(reqId, connectHandle, 0, ret);
1029 break;
1030 case WRITE_CHARACTERISTIC_DESCRIPTOR:
1031 pClientCallBack_->OnWriteDescriptorValueEvent(reqId, connectHandle, 0, ret);
1032 break;
1033 case WRITE_LONG_CHARACTERISTIC_VALUE:
1034 pClientCallBack_->OnWriteLongCharacteristicValueEvent(reqId, connectHandle, 0, ret);
1035 break;
1036 case RELIABLE_WRITE_VALUE:
1037 pClientCallBack_->OnReliableWriteCharacteristicValueEvent(reqId, 0, sharedPtr, 0, ret);
1038 break;
1039 case EXCHANGE_MTU:
1040 pClientCallBack_->OnExchangeMtuEvent(reqId, connectHandle, GATT_DEFAULT_MTU, false);
1041 break;
1042 case WRITE_WITHOUT_RESPONSE:
1043 break;
1044 default:
1045 LOG_ERROR("%{public}s: request type is not find!", __FUNCTION__);
1046 break;
1047 }
1048 }
1049 /**
1050 * @brief This sub-procedure is used by the client to set mtu information.
1051 *
1052 * @param connectHandle Indicates identify a connection.
1053 * @param isExchanged Indicates the flag of MTU has been exchanged.
1054 * @param mtu Indicates mtu size.
1055 * @since 6.0
1056 */
SetMtuInformation(uint16_t connectHandle,bool isExchanged,uint16_t mtu)1057 void GattClientProfile::impl::SetMtuInformation(uint16_t connectHandle, bool isExchanged, uint16_t mtu)
1058 {
1059 auto it = mtuInfo_.find(connectHandle);
1060 if (it == mtuInfo_.end()) {
1061 mtuInfo_.emplace(connectHandle, MtuInfo(isExchanged, mtu));
1062 } else {
1063 it->second.mtu_ = mtu;
1064 it->second.isExchanged_ = isExchanged;
1065 }
1066 }
1067 /**
1068 * @brief This sub-procedure is used by the client to get mtu information.
1069 *
1070 * @param connectHandle Indicates identify a connection.
1071 * @return Returns mtu information.
1072 * @since 6.0
1073 */
GetMtuInformation(uint16_t connectHandle)1074 MtuInfo GattClientProfile::impl::GetMtuInformation(uint16_t connectHandle)
1075 {
1076 MtuInfo mtuRet = {false, GATT_DEFAULT_MTU};
1077 auto it = mtuInfo_.find(connectHandle);
1078 if (it != mtuInfo_.end()) {
1079 mtuRet = it->second;
1080 }
1081
1082 return mtuRet;
1083 }
1084 /**
1085 * @brief Add iter to the response list.
1086 *
1087 * @since 6.0
1088 */
AddResponseList(void)1089 void GattClientProfile::impl::AddResponseList(void)
1090 {
1091 auto iter = requestList_.begin();
1092 if (iter != requestList_.end()) {
1093 responseList_.emplace_back(*iter);
1094 LOG_INFO("%{public}s: responseList size: %{public}zu", __FUNCTION__, responseList_.size());
1095 dispatcher_->PostTask(std::bind(&impl::RemoveRequestList, this, iter));
1096 }
1097 }
1098 /**
1099 * @brief Remove iter from the request list.
1100 *
1101 * @since 6.0
1102 */
RemoveRequestList(std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1103 void GattClientProfile::impl::RemoveRequestList(std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1104 {
1105 requestList_.erase(iter);
1106 }
1107 /**
1108 * @brief This sub-procedure is used by the client to process error respond.
1109 *
1110 * @param connectHandle Indicates identify a connection.
1111 * @param data Indicates att data.
1112 * @param iter Indicates iterator of client request information.
1113 * @since 6.0
1114 */
ErrorResponseParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1115 void GattClientProfile::impl::ErrorResponseParsing(
1116 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1117 {
1118 LOG_INFO("%{public}s: connectHandle: %hu", __FUNCTION__, connectHandle);
1119 uint16_t handle = 0;
1120 int reqId = iter->second.reqId_;
1121 ResponesType type = iter->second.reqType_;
1122 auto sharedPtr = GattValue(std::make_shared<std::unique_ptr<uint8_t[]>>(nullptr));
1123
1124 if (data->attErrorResponse.errorCode != ATT_ATTRIBUTE_NOT_FOUND) {
1125 IndicateRequestRetToService(reqId, connectHandle, type, data->attErrorResponse.errorCode);
1126 } else {
1127 switch (data->attErrorResponse.reqOpcode) {
1128 case READ_BY_GROUP_TYPE_REQUEST:
1129 pClientCallBack_->OnDiscoverAllPrimaryServicesEvent(
1130 reqId, GATT_SUCCESS, connectHandle, cacheMap_.find(connectHandle)->second.GetServices());
1131 break;
1132 case READ_BY_TYPE_REQUEST:
1133 SplitReadByTypeReqErrorParsing(connectHandle, iter);
1134 break;
1135 case FIND_BY_TYPE_VALUE_REQUEST:
1136 pClientCallBack_->OnDiscoverPrimaryServicesByServiceUUIDEvent(
1137 reqId, GATT_SUCCESS, connectHandle, cacheMap_.find(connectHandle)->second.GetServices());
1138 break;
1139 case FIND_INFORMATION_REQUEST:
1140 handle = cacheMap_.find(connectHandle)->second.GetDescriptors(iter->second.startHandle_).second;
1141 pClientCallBack_->OnDiscoverAllCharacteristicDescriptorsEvent(reqId,
1142 GATT_SUCCESS,
1143 handle,
1144 iter->second.startHandle_,
1145 *cacheMap_.find(connectHandle)->second.GetDescriptors(iter->second.startHandle_).first);
1146 break;
1147 case READ_REQUEST:
1148 case READ_BLOB_REQUEST:
1149 SplitReadReqErrorParsing(reqId,
1150 connectHandle,
1151 type,
1152 data->attErrorResponse.attHandleInError,
1153 ConvertResponseErrorCode(data->attErrorResponse.errorCode));
1154 break;
1155 case WRITE_REQUEST:
1156 SplitWriteReqErrorParsing(reqId,
1157 connectHandle,
1158 type,
1159 data->attErrorResponse.attHandleInError,
1160 ConvertResponseErrorCode(data->attErrorResponse.errorCode));
1161 break;
1162 case PREPARE_WRITE_REQUEST:
1163 pClientCallBack_->OnReliableWriteCharacteristicValueEvent(reqId,
1164 data->attErrorResponse.attHandleInError,
1165 sharedPtr,
1166 0,
1167 ConvertResponseErrorCode(data->attErrorResponse.errorCode));
1168 break;
1169 default:
1170 LOG_ERROR("%{public}s: Request opcode of error response is invalid", __FUNCTION__);
1171 break;
1172 }
1173 }
1174 }
1175 /**
1176 * @brief This sub-procedure is used by the client to client to process find include service error respond.
1177 *
1178 * @param connectHandle Indicates identify a connection.
1179 * @param iter Indicates iterator of client request information.
1180 * @since 6.0
1181 */
ErrorResponseParsing(uint16_t connectHandle,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1182 void GattClientProfile::impl::ErrorResponseParsing(
1183 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1184 {
1185 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1186 int reqId = iter->second.reqId_;
1187
1188 pClientCallBack_->OnFindIncludedServicesEvent(reqId,
1189 GATT_SUCCESS,
1190 connectHandle,
1191 iter->second.startHandle_,
1192 *cacheMap_.find(connectHandle)->second.GetIncludeServices(iter->second.startHandle_));
1193 }
1194 /**
1195 * @brief This sub-procedure is used by the client to exchange mtu.
1196 *
1197 * @param connectHandle Indicates identify a connection.
1198 * @param data Indicates att data.
1199 * @param iter Indicates iterator of client request information.
1200 * @since 6.0
1201 */
ExchangeMtuParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1202 void GattClientProfile::impl::ExchangeMtuParsing(
1203 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1204 {
1205 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1206 bool status = true;
1207 int reqId = iter->second.reqId_;
1208 uint16_t mtu = data->attExchangeMtuResponse.mtuSize;
1209
1210 if (mtu < GATT_DEFAULT_MTU) {
1211 status = false;
1212 mtu = GATT_DEFAULT_MTU;
1213 } else if (mtu > iter->second.startHandle_) {
1214 mtu = iter->second.startHandle_;
1215 }
1216 SetMtuInformation(connectHandle, status, mtu);
1217 pClientCallBack_->OnExchangeMtuEvent(reqId, connectHandle, mtu, status);
1218 }
1219 /**
1220 * @brief This sub-procedure is used by the client to process discover all primary services.
1221 *
1222 * @param connectHandle Indicates identify a connection.
1223 * @param data Indicates att data.
1224 * @since 6.0
1225
1226 */
DiscoverAllPrimaryServiceParsing(int reqId,uint16_t connectHandle,AttEventData * data)1227 void GattClientProfile::impl::DiscoverAllPrimaryServiceParsing(int reqId, uint16_t connectHandle, AttEventData *data)
1228 {
1229 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1230 BtUuid primarySvcUuid = {BT_UUID_16, {UUID_PRIMARY_SERVICE}};
1231 auto cache = cacheMap_.find(connectHandle);
1232 uint16_t startHandle = 0;
1233 uint16_t endHandle = 0;
1234 uint16_t num = data->attReadByGroupTypeResponse.readGroupResponse.num;
1235 uint16_t len = data->attReadByGroupTypeResponse.readGroupResponse.length;
1236 uint8_t value[UUID_128BIT_LEN] = {0};
1237 uint8_t uuidLen = len - sizeof(startHandle) - sizeof(endHandle);
1238
1239 for (uint8_t i = 0; i < num; i++) {
1240 uint8_t offset = 0;
1241 startHandle = (data->attReadByGroupTypeResponse.readGroupResponse.attributeData + i)->attHandle;
1242 endHandle = (data->attReadByGroupTypeResponse.readGroupResponse.attributeData + i)->groupEndHandle;
1243 SplitDataPackage(value,
1244 UUID_128BIT_LEN,
1245 &offset,
1246 (data->attReadByGroupTypeResponse.readGroupResponse.attributeData + i)->attributeValue,
1247 uuidLen);
1248 Uuid uuid = SplitUuidPackage(value, uuidLen);
1249 dispatcher_->PostTask(std::bind(
1250 &GattCache::AddService, &cache->second, std::move(GattCache::Service(true, startHandle, endHandle, uuid))));
1251 }
1252 if (endHandle == MAX_ATTRIBUTE_HANDLE) {
1253 pClientCallBack_->OnDiscoverAllPrimaryServicesEvent(
1254 reqId, GATT_SUCCESS, connectHandle, cacheMap_.find(connectHandle)->second.GetServices());
1255 LOG_DEBUG("%{public}s Call OnDiscoverAllPrimaryServicesEvent", __FUNCTION__);
1256 } else {
1257 requestList_.emplace_back(connectHandle, GattRequestInfo(DISCOVER_ALL_PRIMARY_SERVICE, reqId));
1258 ATT_ReadByGroupTypeRequest(
1259 connectHandle, endHandle + MIN_ATTRIBUTE_HANDLE, MAX_ATTRIBUTE_HANDLE, &primarySvcUuid);
1260 }
1261 }
1262 /**
1263 * @brief This sub-procedure is used by the client to process discover all primary services by uuid.
1264 *
1265 * @param connectHandle Indicates identify a connection.
1266 * @param data Indicates att data.
1267 * @param iter Indicates iterator of client request information.
1268 * @since 6.0
1269 */
DiscoverPrimaryServiceByUuidParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1270 void GattClientProfile::impl::DiscoverPrimaryServiceByUuidParsing(
1271 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1272 {
1273 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1274
1275 auto cache = cacheMap_.find(connectHandle);
1276 uint16_t endHandle = 0;
1277 uint16_t num = data->attFindByTypeValueResponse.findByTypeValueResponse.listNum;
1278 int reqId = iter->second.reqId_;
1279 int uuidType = iter->second.uuid_.GetUuidType();
1280 Buffer *serviceUuid = BufferMalloc(uuidType);
1281 AttFindByTypeValueReq parameter;
1282
1283 for (uint16_t i = 0; i < num; i++) {
1284 uint16_t startHandle = (data->attFindByTypeValueResponse.findByTypeValueResponse.handleInfoList + i)->attHandle;
1285 endHandle = (data->attFindByTypeValueResponse.findByTypeValueResponse.handleInfoList + i)->groupEndHandle;
1286 dispatcher_->PostTask(std::bind(&GattCache::AddService,
1287 &cache->second,
1288 std::move(GattCache::Service(true, startHandle, endHandle, iter->second.uuid_))));
1289 }
1290 if (endHandle == MAX_ATTRIBUTE_HANDLE) {
1291 pClientCallBack_->OnDiscoverPrimaryServicesByServiceUUIDEvent(
1292 reqId, GATT_SUCCESS, connectHandle, cacheMap_.find(connectHandle)->second.GetServices());
1293 LOG_DEBUG("%{public}s Call OnDiscoverPrimaryServicesByServiceUUIDEvent", __FUNCTION__);
1294 } else {
1295 parameter.handleRange.startHandle = endHandle + MIN_ATTRIBUTE_HANDLE;
1296 parameter.handleRange.endHandle = MAX_ATTRIBUTE_HANDLE;
1297 parameter.attType = UUID_PRIMARY_SERVICE;
1298 if (memcpy_s(BufferPtr(serviceUuid), uuidType, &(iter->second.uuid_), uuidType) != EOK) {
1299 LOG_ERROR("%{public}s Call memcpy_s fail", __FUNCTION__);
1300 BufferFree(serviceUuid);
1301 return;
1302 }
1303 requestList_.emplace_back(connectHandle, GattRequestInfo(iter->second.uuid_, DISCOVER_SERVICE_BY_UUID, reqId));
1304 ATT_FindByTypeValueRequest(connectHandle, ¶meter, serviceUuid);
1305 }
1306 BufferFree(serviceUuid);
1307 }
1308 /**
1309 * @brief This sub-procedure is used by the client to process find include 16bit uuid services.
1310 *
1311 * @param connectHandle Indicates identify a connection.
1312 * @param data Indicates att data.
1313 * @param iter Indicates iterator of client request information.
1314 * @since 6.0
1315 */
FindIncludeServicesParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1316 void GattClientProfile::impl::FindIncludeServicesParsing(
1317 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1318 {
1319 LOG_INFO("%{public}s: connectHandle is %{public}hu.", __FUNCTION__, connectHandle);
1320 if (data == nullptr || data->attReadByTypeResponse.readHandleListNum.valueNum == 0) {
1321 LOG_ERROR("%{public}s: invalid params.", __FUNCTION__);
1322 return;
1323 }
1324 uint8_t offset = 0;
1325 int reqId = iter->second.reqId_;
1326 uint8_t len = data->attReadByTypeResponse.readHandleListNum.len;
1327 uint16_t isvcHandle = data->attReadByTypeResponse.readHandleListNum.valueList->attHandle.attHandle;
1328 uint16_t startHandle =
1329 SplitDataPackageToUint16(data->attReadByTypeResponse.readHandleListNum.valueList->attributeValue, &offset);
1330 uint16_t endHandle =
1331 SplitDataPackageToUint16(data->attReadByTypeResponse.readHandleListNum.valueList->attributeValue, &offset);
1332 BtUuid uuid = {BT_UUID_16, {UUID_INCLUDE_SERVICE}};
1333 auto cache = cacheMap_.find(connectHandle);
1334
1335 if (len == sizeof(startHandle) + sizeof(endHandle) + sizeof(isvcHandle) + UUID_16BIT_LEN) {
1336 uint16_t uuid16Bit =
1337 SplitDataPackageToUint16(data->attReadByTypeResponse.readHandleListNum.valueList->attributeValue, &offset);
1338 Uuid svcUuid16Bit = Uuid::ConvertFrom16Bits(uuid16Bit);
1339 dispatcher_->PostTask(std::bind(&GattCache::AddIncludeService,
1340 &cache->second,
1341 iter->second.startHandle_,
1342 std::move(GattCache::IncludeService(isvcHandle, startHandle, endHandle, svcUuid16Bit))));
1343 dispatcher_->PostTask(std::bind(&GattCache::AddService,
1344 &cache->second,
1345 std::move(GattCache::Service(false, startHandle, endHandle, svcUuid16Bit))));
1346
1347 requestList_.emplace_back(connectHandle,
1348 GattRequestInfo(
1349 FIND_INCLUDE_SERVICE, iter->second.startHandle_, iter->second.endHandle_, ++isvcHandle, reqId));
1350 ATT_ReadByTypeRequest(connectHandle, isvcHandle, iter->second.endHandle_, &uuid);
1351 } else {
1352 dispatcher_->PostTask(std::bind(&GattCache::AddIncludeService,
1353 &cache->second,
1354 iter->second.startHandle_,
1355 std::move(GattCache::IncludeService(isvcHandle, startHandle, endHandle))));
1356 dispatcher_->PostTask(std::bind(&GattCache::AddService,
1357 &cache->second,
1358 std::move(GattCache::Service(false, startHandle, endHandle, Uuid()))));
1359 Uuid nextHandle = Uuid::ConvertFrom16Bits(startHandle);
1360 requestList_.emplace_back(connectHandle,
1361 GattRequestInfo(FIND_INCLUDE_SERVICE,
1362 iter->second.startHandle_,
1363 iter->second.endHandle_,
1364 ++isvcHandle,
1365 nextHandle,
1366 reqId));
1367 ATT_ReadRequest(connectHandle, startHandle);
1368 }
1369 }
1370 /**
1371 * @brief This sub-procedure is used by the client toprocess find include 128bit uuid services.
1372 *
1373 * @param connectHandle Indicates identify a connection.
1374 * @param handle Indicates attribute handle of include service.
1375 * @param buffer Indicates 128bit uuid.
1376 * @since 6.0
1377 */
FindIncludeServicesParsing(uint16_t connectHandle,uint16_t handle,Buffer * buffer)1378 void GattClientProfile::impl::FindIncludeServicesParsing(uint16_t connectHandle, uint16_t handle, Buffer *buffer)
1379 {
1380 auto cache = cacheMap_.find(connectHandle);
1381 auto isvcs = cache->second.GetIncludeServices(handle);
1382 if (isvcs != nullptr) {
1383 for (auto &isvc : *isvcs) {
1384 if (isvc.handle_ == handle) {
1385 uint8_t uuid128Bit[UUID_128BIT_LEN] = {0};
1386 if (memcpy_s(uuid128Bit, UUID_128BIT_LEN, BufferPtr(buffer), BufferGetSize(buffer)) != EOK) {
1387 LOG_ERROR("%{public}s: memcpy_s fail.", __FUNCTION__);
1388 break;
1389 }
1390 isvc.uuid_.ConvertFromBytesLE(uuid128Bit, UUID_128BIT_LEN);
1391 break;
1392 }
1393 }
1394 }
1395 }
1396 /**
1397 * @brief This sub-procedure is used by the client to process discover all characteristics.
1398 *
1399 * @param connectHandle Indicates identify a connection.
1400 * @param data Indicates att data.
1401 * @param isByUuid Indicates if call DiscoverCharacteristicByUUID, isByUuid set true.
1402 * @param iter Indicates iterator of client request information.
1403 * @since 6.0
1404 */
DiscoverAllCharacteristicOfServiceParsing(uint16_t connectHandle,AttEventData * data,bool isByUuid,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1405 void GattClientProfile::impl::DiscoverAllCharacteristicOfServiceParsing(uint16_t connectHandle, AttEventData *data,
1406 bool isByUuid, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1407 {
1408 LOG_INFO("%{public}s: connectHandle is %{public}hu.", __FUNCTION__, connectHandle);
1409 if (data == nullptr || data->attReadByTypeResponse.readHandleListNum.valueNum == 0) {
1410 LOG_ERROR("%{public}s: invalid params.", __FUNCTION__);
1411 return;
1412 }
1413 Uuid uuid;
1414 uint8_t properties = 0;
1415 uint16_t startHandle = 0;
1416 uint16_t valueHandle = 0;
1417 uint16_t len = data->attReadByTypeResponse.readHandleListNum.len;
1418 uint16_t num = data->attReadByTypeResponse.readHandleListNum.valueNum;
1419 uint8_t value[GATT_VALUE_LEN_MAX] = {0};
1420 uint8_t uuidLen = len - sizeof(startHandle) - sizeof(properties) - sizeof(valueHandle);
1421 auto cache = cacheMap_.find(connectHandle);
1422
1423 for (uint16_t i = 0; i < num; i++) {
1424 uint8_t offset = 0;
1425 startHandle = (data->attReadByTypeResponse.readHandleListNum.valueList + i)->attHandle.attHandle;
1426 properties = SplitDataPackageToUint8(
1427 (data->attReadByTypeResponse.readHandleListNum.valueList + i)->attributeValue, &offset);
1428 valueHandle = SplitDataPackageToUint16(
1429 (data->attReadByTypeResponse.readHandleListNum.valueList + i)->attributeValue, &offset);
1430 SplitDataPackage(value,
1431 GATT_VALUE_LEN_MAX,
1432 &offset,
1433 (data->attReadByTypeResponse.readHandleListNum.valueList + i)->attributeValue,
1434 uuidLen);
1435 uuid = SplitUuidPackage(value, uuidLen);
1436 if (isByUuid) {
1437 if (iter->second.uuid_.operator==(uuid)) {
1438 dispatcher_->PostTask(std::bind(&GattCache::AddCharacteristic,
1439 &cache->second,
1440 iter->second.startHandle_,
1441 std::move(GattCache::Characteristic(startHandle, properties, valueHandle, uuid))));
1442 }
1443 } else {
1444 dispatcher_->PostTask(std::bind(&GattCache::AddCharacteristic,
1445 &cache->second,
1446 iter->second.startHandle_,
1447 std::move(GattCache::Characteristic(startHandle, properties, valueHandle, uuid))));
1448 }
1449 }
1450 SendDiscoverAllCharacteristicRequest(connectHandle, ++startHandle, valueHandle, uuid, isByUuid, iter);
1451 }
1452 /**
1453 * @brief This sub-procedure is used by the client to process send discover all characteristics request.
1454 *
1455 * @param connectHandle Indicates identify a connection.
1456 * @param startHandle Indicates service handle.
1457 * @param valueHandle Indicates characteristic value handle.
1458 * @param uuid Indicates characteristic uuid.
1459 * @param isByUuid Indicates if call DiscoverCharacteristicByUUID, isByUuid set true.
1460 * @param iter Indicates iterator of client request information.
1461 * @since 6.0
1462 */
SendDiscoverAllCharacteristicRequest(uint16_t connectHandle,uint16_t startHandle,uint16_t valueHandle,Uuid uuid,bool isByUuid,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1463 void GattClientProfile::impl::SendDiscoverAllCharacteristicRequest(uint16_t connectHandle, uint16_t startHandle,
1464 uint16_t valueHandle, Uuid uuid, bool isByUuid, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1465 {
1466 LOG_INFO("%{public}s: connectHandle is %hu, startHandle is %hu, valueHandle is %hu.",
1467 __FUNCTION__,
1468 connectHandle,
1469 startHandle,
1470 valueHandle);
1471 int reqId = iter->second.reqId_;
1472 BtUuid characteristicUuid = {BT_UUID_16, {UUID_CHARACTERISTIC}};
1473
1474 if (valueHandle == iter->second.endHandle_) {
1475 pClientCallBack_->OnDiscoverAllCharacteristicOfServiceEvent(reqId,
1476 GATT_SUCCESS,
1477 connectHandle,
1478 iter->second.startHandle_,
1479 *cacheMap_.find(connectHandle)->second.GetCharacteristics(iter->second.startHandle_));
1480 } else {
1481 if (isByUuid) {
1482 requestList_.emplace_back(connectHandle,
1483 GattRequestInfo(
1484 DISCOVER_CHARACTERISTIC_BY_UUID, iter->second.startHandle_, iter->second.endHandle_, uuid, reqId));
1485 } else {
1486 requestList_.emplace_back(connectHandle,
1487 GattRequestInfo(
1488 DISCOVER_ALL_CHARACTERISTIC, iter->second.startHandle_, iter->second.endHandle_, uuid, reqId));
1489 }
1490 ATT_ReadByTypeRequest(connectHandle, startHandle, iter->second.endHandle_, &characteristicUuid);
1491 }
1492 }
1493 /**
1494 * @brief This sub-procedure is used by the client to process discover all characteristics by uuid.
1495 *
1496 * @param connectHandle Indicates identify a connection.
1497 * @param data Indicates att data.
1498 * @param iter Indicates iterator of client request information.
1499 * @since 6.0
1500 */
DiscoverCharacteristicByUUIDParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1501 void GattClientProfile::impl::DiscoverCharacteristicByUUIDParsing(
1502 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1503 {
1504 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1505 DiscoverAllCharacteristicOfServiceParsing(connectHandle, data, true, iter);
1506 }
1507 /**
1508 * @brief This sub-procedure is used by the client to process discover all characteristic descriptors.
1509 *
1510 * @param connectHandle Indicates identify a connection.
1511 * @param data Indicates att data.
1512 * @param iter Indicates iterator of client request information.
1513 * @since 6.0
1514 */
DiscoverAllCharacteristicDescriptorsParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1515 void GattClientProfile::impl::DiscoverAllCharacteristicDescriptorsParsing(
1516 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1517 {
1518 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1519 Uuid uuid;
1520 uint16_t attHandle = 0;
1521 uint16_t num = data->attFindInformationResponse.findInforRsponse.pairNum;
1522 uint8_t format = data->attFindInformationResponse.findInforRsponse.format;
1523 auto cache = cacheMap_.find(connectHandle);
1524 int reqId = iter->second.reqId_;
1525
1526 for (uint16_t i = 0; i < num; i++) {
1527 if (format == UUID_16BIT_FORMAT) {
1528 uuid = Uuid::ConvertFrom16Bits(
1529 data->attFindInformationResponse.findInforRsponse.handleUuidPairs[i].uuid.uuid16);
1530 } else if (format == UUID_128BIT_FORMAT) {
1531 uuid = Uuid::ConvertFromBytesLE(
1532 data->attFindInformationResponse.findInforRsponse.handleUuidPairs[i].uuid.uuid128, UUID_128BIT_LEN);
1533 } else {
1534 LOG_ERROR("%{public}s: FindInformationResponse format is failed. Format = %hhu", __FUNCTION__, format);
1535 return;
1536 }
1537 attHandle = data->attFindInformationResponse.findInforRsponse.handleUuidPairs[i].attHandle;
1538 dispatcher_->PostTask(std::bind(&GattCache::AddDescriptor,
1539 &cache->second,
1540 iter->second.startHandle_,
1541 std::move(GattCache::Descriptor(attHandle, uuid))));
1542 }
1543 if (attHandle == iter->second.endHandle_) {
1544 uint16_t serviceHandle = cacheMap_.find(connectHandle)->second.GetDescriptors(iter->second.startHandle_).second;
1545 pClientCallBack_->OnDiscoverAllCharacteristicDescriptorsEvent(reqId,
1546 GATT_SUCCESS,
1547 serviceHandle,
1548 iter->second.startHandle_,
1549 *cacheMap_.find(connectHandle)->second.GetDescriptors(iter->second.startHandle_).first);
1550 LOG_DEBUG("%{public}s Call OnDiscoverAllCharacteristicDescriptorsEvent", __FUNCTION__);
1551 } else {
1552 requestList_.emplace_back(connectHandle,
1553 GattRequestInfo(
1554 DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR, iter->second.startHandle_, iter->second.endHandle_, reqId));
1555 ATT_FindInformationRequest(connectHandle, ++attHandle, iter->second.endHandle_);
1556 }
1557 }
1558 /**
1559 * @brief This sub-procedure is used by the client to process read characteristic value.
1560 *
1561 * @param connectHandle Indicates identify a connection.
1562 * @param buffer Indicates att data.
1563 * @param iter Indicates iterator of client request information.
1564 * @since 6.0
1565 */
ReadCharacteristicValueParsing(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1566 void GattClientProfile::impl::ReadCharacteristicValueParsing(
1567 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1568 {
1569 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1570 uint16_t bufferSize = GetMtuInformation(connectHandle).mtu_ - sizeof(uint8_t);
1571 int reqId = iter->second.reqId_;
1572
1573 if (bufferSize == BufferGetSize(buffer)) {
1574 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_VALUE", __FUNCTION__);
1575 requestList_.emplace_back(
1576 connectHandle, GattRequestInfo(READ_LONG_CHARACTERISTIC_VALUE, iter->second.startHandle_, 0x01, reqId));
1577 AddReadValueCache(connectHandle, iter->second.startHandle_, bufferSize, buffer);
1578 ATT_ReadBlobRequest(connectHandle, iter->second.startHandle_, bufferSize);
1579 } else {
1580 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(buffer), BufferGetSize(buffer));
1581 pClientCallBack_->OnReadCharacteristicValueEvent(
1582 reqId, iter->second.startHandle_, sharedPtr, BufferGetSize(buffer), GATT_SUCCESS);
1583 }
1584 }
1585 /**
1586 * @brief This sub-procedure is used by the client to process read long characteristic value.
1587 *
1588 * @param connectHandle Indicates identify a connection.
1589 * @param buffer Indicates att data.
1590 * @param iter Indicates iterator of client request information.
1591 * @since 6.0
1592 */
ReadLongCharacteristicValueParsing(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1593 void GattClientProfile::impl::ReadLongCharacteristicValueParsing(
1594 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1595 {
1596 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1597 int reqId = iter->second.reqId_;
1598 uint16_t num = iter->second.endHandle_;
1599 uint16_t bufferSize = GetMtuInformation(connectHandle).mtu_ - sizeof(uint8_t);
1600 uint8_t *data = nullptr;
1601
1602 if (bufferSize == BufferGetSize(buffer)) {
1603 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_VALUE", __FUNCTION__);
1604 requestList_.emplace_back(
1605 connectHandle, GattRequestInfo(READ_LONG_CHARACTERISTIC_VALUE, iter->second.startHandle_, ++num, reqId));
1606 AddReadValueCache(connectHandle, iter->second.startHandle_, num * bufferSize, buffer);
1607 ATT_ReadBlobRequest(connectHandle, iter->second.startHandle_, bufferSize * num);
1608 } else {
1609 uint16_t totalSize = num * bufferSize + BufferGetSize(buffer);
1610 AddReadValueCache(connectHandle, iter->second.startHandle_, BufferGetSize(buffer), buffer);
1611 data = GetReadValueCache(connectHandle, iter->second.startHandle_);
1612 auto sharedPtr = GattServiceBase::BuildGattValue(data, totalSize);
1613 pClientCallBack_->OnReadCharacteristicValueEvent(
1614 reqId, iter->second.startHandle_, sharedPtr, BufferGetSize(buffer), GATT_SUCCESS);
1615 free(data);
1616 }
1617 }
1618 /**
1619 * @brief This sub-procedure is used by the client to process read characteristic value by uuid.
1620 *
1621 * @param connectHandle Indicates identify a connection.
1622 * @param data Indicates att data.
1623 * @param iter Indicates iterator of client request information.
1624 * @since 6.0
1625 */
ReadUsingCharacteristicByUuidParsing(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1626 void GattClientProfile::impl::ReadUsingCharacteristicByUuidParsing(
1627 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1628 {
1629 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1630 int reqId = iter->second.reqId_;
1631 uint16_t len = data->attReadByTypeResponse.readHandleListNum.len;
1632 uint16_t handle = data->attReadByTypeResponse.readHandleListNum.valueList->attHandle.attHandle;
1633
1634 auto sharedPtr = GattServiceBase::BuildGattValue(
1635 data->attReadByTypeResponse.readHandleListNum.valueList->attributeValue, len - sizeof(uint16_t));
1636 pClientCallBack_->OnReadCharacteristicValueEvent(
1637 reqId, handle, sharedPtr, len - sizeof(uint16_t), GATT_SUCCESS);
1638 }
1639 /**
1640 * @brief This sub-procedure is used by the client to process read multiple characteristic value.
1641 *
1642 * @param connectHandle Indicates identify a connection.
1643 * @param buffer Indicates att data.
1644 * @param iter Indicates iterator of client request information.
1645 * @since 6.0
1646 */
ReadMultipleCharacteristicParsing(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1647 void GattClientProfile::impl::ReadMultipleCharacteristicParsing(
1648 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1649 {
1650 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1651 int reqId = iter->second.reqId_;
1652 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(buffer), BufferGetSize(buffer));
1653 pClientCallBack_->OnReadCharacteristicValueEvent(
1654 reqId, iter->second.startHandle_, sharedPtr, BufferGetSize(buffer), GATT_SUCCESS);
1655 }
1656 /**
1657 * @brief This sub-procedure is used by the client to process read characteristic descriptors.
1658 *
1659 * @param connectHandle Indicates identify a connection.
1660 * @param buffer Indicates att data.
1661 * @param iter Indicates iterator of client request information.
1662 * @since 6.0
1663 */
ReadCharacteristicDescriptorsParsing(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1664 void GattClientProfile::impl::ReadCharacteristicDescriptorsParsing(
1665 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1666 {
1667 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1668 uint16_t bufferSize = GetMtuInformation(connectHandle).mtu_ - sizeof(uint8_t);
1669 int reqId = iter->second.reqId_;
1670
1671 if (bufferSize == BufferGetSize(buffer)) {
1672 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
1673 requestList_.emplace_back(connectHandle,
1674 GattRequestInfo(READ_LONG_CHARACTERISTIC_DESCRIPTOR, iter->second.startHandle_, 0x01, reqId));
1675 AddReadValueCache(connectHandle, iter->second.startHandle_, bufferSize, buffer);
1676 ATT_ReadBlobRequest(connectHandle, iter->second.startHandle_, bufferSize);
1677 } else {
1678 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(buffer), BufferGetSize(buffer));
1679 pClientCallBack_->OnReadDescriptorValueEvent(
1680 reqId, iter->second.startHandle_, sharedPtr, BufferGetSize(buffer), GATT_SUCCESS);
1681 }
1682 }
1683 /**
1684 * @brief This sub-procedure is used by the client to process read long characteristic value.
1685 *
1686 * @param connectHandle Indicates identify a connection.
1687 * @param buffer Indicates att data.
1688 * @param iter Indicates iterator of client request information.
1689 * @since 6.0
1690 */
ReadLongCharacteristicDescriptorsParsing(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1691 void GattClientProfile::impl::ReadLongCharacteristicDescriptorsParsing(
1692 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1693 {
1694 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1695 int reqId = iter->second.reqId_;
1696 uint16_t num = iter->second.endHandle_;
1697 uint16_t bufferSize = GetMtuInformation(connectHandle).mtu_ - sizeof(uint8_t);
1698 uint8_t *data = nullptr;
1699
1700 if (bufferSize == BufferGetSize(buffer)) {
1701 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
1702 requestList_.emplace_back(connectHandle,
1703 GattRequestInfo(READ_LONG_CHARACTERISTIC_DESCRIPTOR, iter->second.startHandle_, ++num, reqId));
1704 AddReadValueCache(connectHandle, iter->second.startHandle_, num * bufferSize, buffer);
1705 ATT_ReadBlobRequest(connectHandle, iter->second.startHandle_, bufferSize * num);
1706 } else {
1707 uint16_t totalSize = num * bufferSize + BufferGetSize(buffer);
1708 AddReadValueCache(connectHandle, iter->second.startHandle_, BufferGetSize(buffer), buffer);
1709 data = GetReadValueCache(connectHandle, iter->second.startHandle_);
1710 auto sharedPtr = GattServiceBase::BuildGattValue(data, totalSize);
1711 pClientCallBack_->OnReadDescriptorValueEvent(
1712 reqId, iter->second.startHandle_, sharedPtr, BufferGetSize(buffer), GATT_SUCCESS);
1713 free(data);
1714 }
1715 }
1716 /**
1717 * @brief This sub-procedure is used by the client to process write characteristic value.
1718 *
1719 * @param connectHandle Indicates identify a connection.
1720 * @param iter Indicates iterator of client request information.
1721 * @since 6.0
1722 */
WriteCharacteristicValueParsing(uint16_t connectHandle,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1723 void GattClientProfile::impl::WriteCharacteristicValueParsing(
1724 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1725 {
1726 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1727 pClientCallBack_->OnWriteCharacteristicValueEvent(
1728 iter->second.reqId_, connectHandle, iter->second.startHandle_, GATT_SUCCESS);
1729 }
1730 /**
1731 * @brief This sub-procedure is used by the client to process write characteristic descriptors.
1732 *
1733 * @param connectHandle Indicates identify a connection.
1734 * @param iter Indicates iterator of client request information.
1735 * @since 6.0
1736 */
WriteCharacteristicDescriptorsParsing(uint16_t connectHandle,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1737 void GattClientProfile::impl::WriteCharacteristicDescriptorsParsing(
1738 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1739 {
1740 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1741 pClientCallBack_->OnWriteDescriptorValueEvent(
1742 iter->second.reqId_, connectHandle, iter->second.startHandle_, GATT_SUCCESS);
1743 }
1744 /**
1745 * @brief This sub-procedure is used by the client to split read by type response process.
1746 *
1747 * @param connectHandle Indicates identify a connection.
1748 * @param data Indicates att data.
1749 * @param iter Indicates iterator of client request information.
1750 * @since 6.0
1751 */
SplitReadByTypeRsp(uint16_t connectHandle,AttEventData * data,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1752 void GattClientProfile::impl::SplitReadByTypeRsp(
1753 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1754 {
1755 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, iter->second.reqType_);
1756 switch (iter->second.reqType_) {
1757 case DISCOVER_ALL_CHARACTERISTIC:
1758 DiscoverAllCharacteristicOfServiceParsing(connectHandle, data, false, iter);
1759 break;
1760 case DISCOVER_CHARACTERISTIC_BY_UUID:
1761 DiscoverCharacteristicByUUIDParsing(connectHandle, data, iter);
1762 break;
1763 case FIND_INCLUDE_SERVICE:
1764 FindIncludeServicesParsing(connectHandle, data, iter);
1765 break;
1766 case READ_USING_CHARACTERISTIC_UUID:
1767 ReadUsingCharacteristicByUuidParsing(connectHandle, data, iter);
1768 break;
1769 default:
1770 LOG_ERROR("data len is %{public}d.", data->attReadByTypeResponse.readHandleListNum.len);
1771 break;
1772 }
1773 }
1774 /**
1775 * @brief This sub-procedure is used by the client to split read response process.
1776 *
1777 * @param connectHandle Indicates identify a connection.
1778 * @param buffer Indicates att data.
1779 * @param iter Indicates iterator of client request information.
1780 * @since 6.0
1781 */
SplitReadRsp(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1782 void GattClientProfile::impl::SplitReadRsp(
1783 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1784 {
1785 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, iter->second.reqType_);
1786 if (iter->second.reqType_ == READ_CHARACTERISTIC_VALUE) {
1787 ReadCharacteristicValueParsing(connectHandle, buffer, iter);
1788 } else if (iter->second.reqType_ == READ_CHARACTERISTIC_DESCRIPTOR) {
1789 ReadCharacteristicDescriptorsParsing(connectHandle, buffer, iter);
1790 } else {
1791 BtUuid uuid = {BT_UUID_16, {UUID_INCLUDE_SERVICE}};
1792 FindIncludeServicesParsing(connectHandle, iter->second.startHandle_, buffer);
1793 if (iter->second.valHandle_ <= iter->second.endHandle_) {
1794 requestList_.emplace_back(connectHandle,
1795 GattRequestInfo(FIND_INCLUDE_SERVICE,
1796 iter->second.startHandle_,
1797 iter->second.endHandle_,
1798 iter->second.valHandle_,
1799 iter->second.reqId_));
1800 ATT_ReadByTypeRequest(connectHandle, iter->second.valHandle_, iter->second.endHandle_, &uuid);
1801 } else {
1802 ErrorResponseParsing(connectHandle, iter);
1803 }
1804 }
1805 }
1806 /**
1807 * @brief This sub-procedure is used by the client to split read blob response process.
1808 *
1809 * @param connectHandle Indicates identify a connection.
1810 * @param buffer Indicates att data.
1811 * @param iter Indicates iterator of client request information.
1812 * @since 6.0
1813 */
SplitReadBlobRsp(uint16_t connectHandle,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1814 void GattClientProfile::impl::SplitReadBlobRsp(
1815 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1816 {
1817 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, iter->second.reqType_);
1818 if (iter->second.reqType_ == READ_LONG_CHARACTERISTIC_VALUE) {
1819 ReadLongCharacteristicValueParsing(connectHandle, buffer, iter);
1820 } else if (iter->second.reqType_ == READ_LONG_CHARACTERISTIC_DESCRIPTOR) {
1821 ReadLongCharacteristicDescriptorsParsing(connectHandle, buffer, iter);
1822 }
1823 }
1824 /**
1825 * @brief This sub-procedure is used by the client to split prepare write process.
1826 *
1827 * @param connectHandle Indicates identify a connection.
1828 * @param iter Indicates iterator of client request information.
1829 * @since 6.0
1830 */
SplitWriteRsp(uint16_t connectHandle,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1831 void GattClientProfile::impl::SplitWriteRsp(
1832 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1833 {
1834 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, iter->second.reqType_);
1835 if (iter->second.reqType_ == WRITE_CHARACTERISTIC_VALUE) {
1836 WriteCharacteristicValueParsing(connectHandle, iter);
1837 } else if (iter->second.reqType_ == WRITE_CHARACTERISTIC_DESCRIPTOR) {
1838 WriteCharacteristicDescriptorsParsing(connectHandle, iter);
1839 }
1840 }
1841 /**
1842 * @brief This sub-procedure is used by the client to split prepare write process.
1843 *
1844 * @param connectHandle Indicates identify a connection.
1845 * @param data Indicates att event data.
1846 * @param buffer Indicates att data.
1847 * @param iter Indicates iterator of client request information.
1848 * @since 6.0
1849 */
SplitPrepareWriteRsp(uint16_t connectHandle,AttEventData * data,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1850 void GattClientProfile::impl::SplitPrepareWriteRsp(uint16_t connectHandle, AttEventData *data, Buffer *buffer,
1851 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1852 {
1853 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, iter->second.reqType_);
1854 if (iter->second.reqType_ == WRITE_LONG_CHARACTERISTIC_VALUE) {
1855 WriteLongCharacteristicValueParsing(connectHandle,
1856 data->attWriteResponse.prepareWrite.handleValue.attHandle,
1857 data->attWriteResponse.prepareWrite.offset,
1858 buffer,
1859 iter);
1860 } else if (iter->second.reqType_ == RELIABLE_WRITE_VALUE) {
1861 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(buffer), BufferGetSize(buffer));
1862 pClientCallBack_->OnReliableWriteCharacteristicValueEvent(iter->second.reqId_,
1863 iter->second.startHandle_,
1864 sharedPtr,
1865 BufferGetSize(buffer),
1866 GATT_SUCCESS);
1867 } else {
1868 LOG_ERROR("%{public}s: Response type is %{public}d. It's invalid type.", __FUNCTION__, iter->second.reqType_);
1869 }
1870 }
1871
SplitReadByTypeReqErrorParsing(uint16_t connectHandle,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1872 void GattClientProfile::impl::SplitReadByTypeReqErrorParsing(
1873 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1874 {
1875 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, iter->second.reqType_);
1876 auto sharedPtr = GattValue(std::make_shared<std::unique_ptr<uint8_t[]>>(nullptr));
1877
1878 switch (iter->second.reqType_) {
1879 case DISCOVER_ALL_CHARACTERISTIC:
1880 pClientCallBack_->OnDiscoverAllCharacteristicOfServiceEvent(iter->second.reqId_,
1881 GATT_SUCCESS,
1882 connectHandle,
1883 iter->second.startHandle_,
1884 *cacheMap_.find(connectHandle)->second.GetCharacteristics(iter->second.startHandle_));
1885 break;
1886 case DISCOVER_CHARACTERISTIC_BY_UUID:
1887 pClientCallBack_->OnDiscoverAllCharacteristicOfServiceEvent(iter->second.reqId_,
1888 GATT_SUCCESS,
1889 connectHandle,
1890 iter->second.startHandle_,
1891 *cacheMap_.find(connectHandle)->second.GetCharacteristics(iter->second.startHandle_));
1892 break;
1893 case READ_USING_CHARACTERISTIC_UUID:
1894 pClientCallBack_->OnReadCharacteristicValueEvent(
1895 iter->second.reqId_, iter->second.startHandle_, sharedPtr, 0, GATT_SUCCESS);
1896 break;
1897 case FIND_INCLUDE_SERVICE:
1898 pClientCallBack_->OnFindIncludedServicesEvent(iter->second.reqId_,
1899 GATT_SUCCESS,
1900 connectHandle,
1901 iter->second.startHandle_,
1902 *cacheMap_.find(connectHandle)->second.GetIncludeServices(iter->second.startHandle_));
1903 break;
1904 default:
1905 LOG_ERROR("%{public}s: Response type is %{public}d. It's invalid type.", __FUNCTION__, iter->second.reqType_);
1906 break;
1907 }
1908 }
1909
SplitReadReqErrorParsing(int reqId,uint16_t connectHandle,ResponesType respType,uint16_t handle,int result)1910 void GattClientProfile::impl::SplitReadReqErrorParsing(
1911 int reqId, uint16_t connectHandle, ResponesType respType, uint16_t handle, int result)
1912 {
1913 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, respType);
1914 auto sharedPtr = GattValue(std::make_shared<std::unique_ptr<uint8_t[]>>(nullptr));
1915 switch (respType) {
1916 case READ_CHARACTERISTIC_VALUE:
1917 case READ_LONG_CHARACTERISTIC_VALUE:
1918 pClientCallBack_->OnReadCharacteristicValueEvent(reqId, handle, sharedPtr, 0, result);
1919 break;
1920 case READ_CHARACTERISTIC_DESCRIPTOR:
1921 case READ_LONG_CHARACTERISTIC_DESCRIPTOR:
1922 pClientCallBack_->OnReadDescriptorValueEvent(reqId, handle, sharedPtr, 0, result);
1923 break;
1924 default:
1925 LOG_ERROR("%{public}s: It's invalid type.", __FUNCTION__);
1926 break;
1927 }
1928 }
1929
SplitWriteReqErrorParsing(int reqId,uint16_t connectHandle,ResponesType respType,uint16_t handle,int result)1930 void GattClientProfile::impl::SplitWriteReqErrorParsing(
1931 int reqId, uint16_t connectHandle, ResponesType respType, uint16_t handle, int result)
1932 {
1933 LOG_INFO("%{public}s: connectHandle is %hu, respType is %{public}d.", __FUNCTION__, connectHandle, respType);
1934 switch (respType) {
1935 case WRITE_CHARACTERISTIC_VALUE:
1936 pClientCallBack_->OnWriteCharacteristicValueEvent(reqId, connectHandle, handle, result);
1937 break;
1938 case WRITE_CHARACTERISTIC_DESCRIPTOR:
1939 pClientCallBack_->OnWriteDescriptorValueEvent(reqId, connectHandle, handle, result);
1940 break;
1941 default:
1942 LOG_ERROR("%{public}s: It's invalid type.", __FUNCTION__);
1943 break;
1944 }
1945 }
1946 /**
1947 * @brief This sub-procedure is used by the client to process write long characteristic value.
1948 *
1949 * @param connectHandle Indicates identify a connection.
1950 * @param handle Indicates attribute handle.
1951 * @param offset Indicates data offset.
1952 * @param buffer Indicates att data.
1953 * @param iter Indicates iterator of client request information.
1954 * @since 6.0
1955 */
WriteLongCharacteristicValueParsing(uint16_t connectHandle,uint16_t handle,uint16_t offset,Buffer * buffer,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1956 void GattClientProfile::impl::WriteLongCharacteristicValueParsing(uint16_t connectHandle, uint16_t handle,
1957 uint16_t offset, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
1958 {
1959 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
1960 Buffer *buf = nullptr;
1961 uint16_t len = iter->second.endHandle_ - iter->second.valHandle_;
1962 uint16_t bufSize = GetMtuInformation(connectHandle).mtu_ - 0x05;
1963 AttReadBlobReqPrepareWriteValue attReadBlobObj = {handle, (uint16_t)(BufferGetSize(buffer) + offset)};
1964
1965 if (iter->second.endHandle_ <= iter->second.valHandle_) {
1966 ATT_ExecuteWriteRequest(connectHandle, 0x01);
1967 return;
1968 }
1969 if (len >= bufSize) {
1970 buf = GattServiceBase::BuildBuffer(iter->second.data_->get(), (size_t)iter->second.valHandle_, (size_t)bufSize);
1971 requestList_.emplace_back(connectHandle,
1972 GattRequestInfo(WRITE_LONG_CHARACTERISTIC_VALUE,
1973 handle,
1974 iter->second.valHandle_ + bufSize,
1975 iter->second.endHandle_,
1976 iter->second.data_,
1977 iter->second.reqId_));
1978 } else {
1979 buf = GattServiceBase::BuildBuffer(iter->second.data_->get(), (size_t)iter->second.valHandle_, (size_t)len);
1980 requestList_.emplace_back(connectHandle,
1981 GattRequestInfo(WRITE_LONG_CHARACTERISTIC_VALUE,
1982 handle,
1983 iter->second.valHandle_ + len,
1984 iter->second.endHandle_,
1985 iter->second.data_,
1986 iter->second.reqId_));
1987 }
1988 ATT_PrepareWriteRequest(connectHandle, attReadBlobObj, buf);
1989 BufferFree(buf);
1990 }
1991 /**
1992 * @brief This sub-procedure is used by the client to process execute write.
1993 *
1994 * @param connectHandle Indicates identify a connection.
1995 * @param iter Indicates iterator of client request information.
1996 * @since 6.0
1997 */
ExecuteWriteParsing(uint16_t connectHandle,std::list<std::pair<uint16_t,GattRequestInfo>>::iterator iter)1998 void GattClientProfile::impl::ExecuteWriteParsing(
1999 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter)
2000 {
2001 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
2002 if (iter->second.reqType_ == WRITE_LONG_CHARACTERISTIC_VALUE) {
2003 pClientCallBack_->OnWriteLongCharacteristicValueEvent(
2004 iter->second.reqId_, connectHandle, iter->second.startHandle_, GATT_SUCCESS);
2005 } else {
2006 pClientCallBack_->OnExecuteWriteValueEvent(iter->second.reqId_, connectHandle, GATT_SUCCESS);
2007 }
2008 }
2009 /**
2010 * @brief This sub-procedure is used by the client to process notification.
2011 *
2012 * @param connectHandle Indicates identify a connection.
2013 * @param data Indicates attribute handle.
2014 * @param buffer Indicates att data.
2015 * @since 6.0
2016 */
NotificationParsing(uint16_t connectHandle,AttEventData * data,Buffer * buffer)2017 void GattClientProfile::impl::NotificationParsing(uint16_t connectHandle, AttEventData *data, Buffer *buffer)
2018 {
2019 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
2020 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(buffer), BufferGetSize(buffer));
2021 pClientCallBack_->OnCharacteristicNotifyEvent(
2022 connectHandle, data->attNotification.attHandle, sharedPtr, BufferGetSize(buffer), false);
2023 }
2024 /**
2025 * @brief This sub-procedure is used by the client to process indication.
2026 *
2027 * @param connectHandle Indicates identify a connection.
2028 * @param data Indicates attribute handle.
2029 * @param buffer Indicates att data.
2030 * @since 6.0
2031 */
IndicationParsing(uint16_t connectHandle,const AttEventData * data,Buffer * buffer)2032 void GattClientProfile::impl::IndicationParsing(uint16_t connectHandle, const AttEventData *data, Buffer *buffer)
2033 {
2034 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
2035 auto sharedPtr = GattServiceBase::BuildGattValue((uint8_t *)BufferPtr(buffer), BufferGetSize(buffer));
2036 pClientCallBack_->OnCharacteristicNotifyEvent(
2037 connectHandle, data->attIndication.attHandle, sharedPtr, BufferGetSize(buffer), true);
2038 }
2039 /**
2040 * @brief This sub-procedure is used by processing request timeout.
2041 *
2042 * @param connectHandle Indicates identify a connection.
2043 * @param reqType Indicates send request type.
2044 * @since 6.0
2045 */
GattRequestTimeoutParsing(int reqId,uint16_t connectHandle,ResponesType respType)2046 void GattClientProfile::impl::GattRequestTimeoutParsing(int reqId, uint16_t connectHandle, ResponesType respType)
2047 {
2048 IndicateRequestRetToService(reqId, connectHandle, respType, ATT_OUT_OF_RANGE);
2049 }
2050 /**
2051 * @brief Convert the att error code to the service layer error code.
2052 *
2053 * @param errorCode Indicates att error code.
2054 * @return Returns gatt client service's error code.
2055 * @since 6.0
2056 */
ConvertResponseErrorCode(uint8_t errorCode)2057 int GattClientProfile::impl::ConvertResponseErrorCode(uint8_t errorCode)
2058 {
2059 int ret = 0;
2060 switch (errorCode) {
2061 case ATT_INVALID_HANDLE:
2062 ret = INVALID_HANDLE;
2063 break;
2064 case ATT_READ_NOT_PERMITTED:
2065 ret = READ_NOT_PERMITTED;
2066 break;
2067 case ATT_WRITE_NOT_PERMITTED:
2068 ret = WRITE_NOT_PERMITTED;
2069 break;
2070 case ATT_INSUFFICIENT_AUTHENTICATION:
2071 ret = INSUFFICIENT_AUTHENTICATION;
2072 break;
2073 case ATT_INVALID_OFFSET:
2074 ret = INSUFFICIENT_AUTHORIZATION;
2075 break;
2076 case ATT_ATTRIBUTE_NOT_FOUND:
2077 ret = HANDLE_NOT_FOUND;
2078 break;
2079 case ATT_INSUFFICIENT_ENCRYPTION:
2080 ret = INSUFFICIENT_ENCRYPTION;
2081 break;
2082 default:
2083 ret = GATT_FAILURE;
2084 break;
2085 }
2086 return ret;
2087 }
2088 /**
2089 * @brief Split att data package.
2090 *
2091 * @param dest Indicates destination data.
2092 * @param offset Indicates data offset.
2093 * @param src Indicates source data.
2094 * @since 6.0
2095 */
SplitDataPackageToUint16(uint8_t * src,uint8_t * offset)2096 uint16_t GattClientProfile::impl::SplitDataPackageToUint16(uint8_t *src, uint8_t *offset)
2097 {
2098 uint16_t dest = (*(src + *offset)) | ((*(src + *offset + sizeof(uint8_t))) << BIT_8);
2099 *offset += sizeof(uint16_t);
2100 return dest;
2101 }
2102 /**
2103 * @brief Split att data package.
2104 *
2105 * @param dest Indicates destination data.
2106 * @param offset Indicates data offset.
2107 * @param src Indicates source data.
2108 * @since 6.0
2109 */
SplitDataPackageToUint8(const uint8_t * src,uint8_t * offset)2110 uint8_t GattClientProfile::impl::SplitDataPackageToUint8(const uint8_t *src, uint8_t *offset)
2111 {
2112 uint8_t dest = *src;
2113 *offset += sizeof(uint8_t);
2114 return dest;
2115 }
2116 /**
2117 * @brief Split att data package.
2118 *
2119 * @param dest Indicates destination address.
2120 * @param destMax -The maximum length of destination buffer.
2121 * @param offset Indicates address offset.
2122 * @param src Indicates source address.
2123 * @param size Indicates data size.
2124 * @since 6.0
2125 */
SplitDataPackage(uint8_t * dest,uint8_t destMax,uint8_t * offset,uint8_t * src,uint8_t size)2126 void GattClientProfile::impl::SplitDataPackage(
2127 uint8_t *dest, uint8_t destMax, uint8_t *offset, uint8_t *src, uint8_t size)
2128 {
2129 if (memcpy_s(dest, destMax, (src + *offset), size) != EOK) {
2130 LOG_INFO("%{public}s: memcpy_s fail.", __FUNCTION__);
2131 return;
2132 }
2133 *offset = *offset + size;
2134 }
2135 /**
2136 * @brief Split service uuid package.
2137 *
2138 * @param value Indicates source uuid address.
2139 * @param len Indicates uuid length.
2140 * @return Returns gatt uuid.
2141 * @since 6.0
2142 */
SplitUuidPackage(const uint8_t * value,uint8_t len)2143 Uuid GattClientProfile::impl::SplitUuidPackage(const uint8_t *value, uint8_t len)
2144 {
2145 Uuid uuid;
2146 if (len == UUID_16BIT_LEN) {
2147 uuid = Uuid::ConvertFrom16Bits((value[1] << BIT_8) | value[0]);
2148 } else if (len == UUID_128BIT_LEN) {
2149 uuid = Uuid::ConvertFromBytesLE(value, UUID_128BIT_LEN);
2150 } else {
2151 uuid = Uuid::ConvertFrom16Bits(0);
2152 LOG_ERROR("%{public}s Uuid length is %hhu. It's invalid length", __FUNCTION__, len);
2153 }
2154 return uuid;
2155 }
2156 /**
2157 * @brief Find the order of operations GATT request.
2158 *
2159 * @param handle Indicates connectHandle handle.
2160 * @since 6.0
2161 */
FindIteratorByRequestInfor(uint16_t connectHandle)2162 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator GattClientProfile::impl::FindIteratorByRequestInfor(
2163 uint16_t connectHandle)
2164 {
2165 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter;
2166 for (iter = requestList_.begin(); iter != requestList_.end(); iter++) {
2167 if (connectHandle == iter->first) {
2168 break;
2169 }
2170 }
2171 return iter;
2172 }
2173
FindIteratorByResponesInfor(uint16_t handle,uint16_t respType)2174 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator GattClientProfile::impl::FindIteratorByResponesInfor(
2175 uint16_t handle, uint16_t respType)
2176 {
2177 ResponesType type;
2178 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter;
2179 switch (respType) {
2180 case ATT_EXCHANGE_MTU_RESPONSE_ID:
2181 type = EXCHANGE_MTU;
2182 break;
2183 case FIND_INFORMATION_REQUEST:
2184 case ATT_FIND_INFORMATION_RESPONSE_ID:
2185 type = DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR;
2186 break;
2187 case FIND_BY_TYPE_VALUE_REQUEST:
2188 case ATT_FIND_BY_TYPE_VALUE_RESPONSE_ID:
2189 type = DISCOVER_SERVICE_BY_UUID;
2190 break;
2191 case ATT_READ_MULTIPLE_RESPONSE_ID:
2192 type = READ_CHARACTERISTIC_VALUE;
2193 break;
2194 case READ_BY_GROUP_TYPE_REQUEST:
2195 case ATT_READ_BY_GROUP_TYPE_RESPONSE_ID:
2196 type = DISCOVER_ALL_PRIMARY_SERVICE;
2197 break;
2198 case ATT_READ_BLOB_RESPONSE_ID:
2199 case READ_BY_TYPE_REQUEST:
2200 case ATT_READ_BY_TYPE_RESPONSE_ID:
2201 case READ_REQUEST:
2202 case ATT_READ_RESPONSE_ID:
2203 case WRITE_REQUEST:
2204 case ATT_WRITE_RESPONSE_ID:
2205 case ATT_PREPARE_WRITE_RESPONSE_ID:
2206 case ATT_EXECUTE_WRITE_RESPONSE_ID:
2207 default:
2208 for (iter = responseList_.begin(); iter != responseList_.end(); iter++) {
2209 if (handle == iter->first) {
2210 break;
2211 }
2212 }
2213 return iter;
2214 }
2215 for (iter = responseList_.begin(); iter != responseList_.end(); iter++) {
2216 if (handle == iter->first && type == iter->second.reqType_) {
2217 break;
2218 }
2219 }
2220 return iter;
2221 }
2222
FindIteratorByRespones(ResponesType reqType,int reqId)2223 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator GattClientProfile::impl::FindIteratorByRespones(
2224 ResponesType reqType, int reqId)
2225 {
2226 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter;
2227 for (iter = responseList_.begin(); iter != responseList_.end(); iter++) {
2228 if (reqId == iter->second.reqId_ && reqType == iter->second.reqType_) {
2229 break;
2230 }
2231 }
2232 return iter;
2233 }
FindIteratorByResponesInfor(uint16_t handle,ResponesType respType)2234 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator GattClientProfile::impl::FindIteratorByResponesInfor(
2235 uint16_t handle, ResponesType respType)
2236 {
2237 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter;
2238 for (iter = responseList_.begin(); iter != responseList_.end(); iter++) {
2239 if (handle == iter->first && respType == iter->second.reqType_) {
2240 break;
2241 }
2242 }
2243 return iter;
2244 }
2245 /**
2246 * @brief Create cache when gatt is connected.
2247 *
2248 * @param connectHandle Indicates identify a connection.
2249 * @param device Indicates peer device Information.
2250 * @since 6.0
2251 */
CreateCache(uint16_t connectHandle,const GattDevice device)2252 void GattClientProfile::impl::CreateCache(uint16_t connectHandle, const GattDevice device)
2253 {
2254 auto cache = cacheMap_.emplace(connectHandle, std::move(GattCache()));
2255 if (device.isEncryption_ == true) {
2256 cache.first->second.LoadFromFile(device);
2257 }
2258 }
2259 /**
2260 * @brief Delete cache when gatt is disconnected.
2261 *
2262 * @param connectHandle Indicates identify a connection.
2263 * @param device Indicates peer device Information.
2264 * @since 6.0
2265 */
DeleteCache(uint16_t connectHandle,const GattDevice device)2266 void GattClientProfile::impl::DeleteCache(uint16_t connectHandle, const GattDevice device)
2267 {
2268 auto cache = cacheMap_.find(connectHandle);
2269 if (cache != cacheMap_.end()) {
2270 if (device.isEncryption_ == true) {
2271 cache->second.StoredToFile(device);
2272 }
2273 cacheMap_.erase(cache);
2274 LOG_INFO("%{public}s, Device cache successfully deleted", __FUNCTION__);
2275 } else {
2276 LOG_ERROR("%{public}s: Device cache does not exist", __FUNCTION__);
2277 }
2278 }
2279 /**
2280 * @brief Delete cache when gatt is disconnected.
2281 *
2282 * @param connectHandle Indicates identify a connection.
2283 * @since 6.0
2284 */
ClearCacheMap(uint16_t connectHandle) const2285 void GattClientProfile::ClearCacheMap(uint16_t connectHandle) const
2286 {
2287 auto cache = pimpl->cacheMap_.find(connectHandle);
2288 if (cache != pimpl->cacheMap_.end()) {
2289 cache->second.Clear();
2290 LOG_INFO("%{public}s, Device cache successfully deleted", __FUNCTION__);
2291 } else {
2292 LOG_ERROR("%{public}s: Device cache does not exist", __FUNCTION__);
2293 }
2294 }
2295 /**
2296 * @brief Add data to ReadValueCache.
2297 *
2298 * @param connectHandle Indicates identify a connection.
2299 * @param handle Indicates att handle.
2300 * @param offset Indicates response value.
2301 * @param data Indicates response value.
2302 * @since 6.0
2303 */
AddReadValueCache(uint16_t connectHandle,uint16_t handle,uint16_t offset,Buffer * data)2304 void GattClientProfile::impl::AddReadValueCache(uint16_t connectHandle, uint16_t handle, uint16_t offset, Buffer *data)
2305 {
2306 Packet *packet = nullptr;
2307 std::list<std::pair<uint16_t, ReadValCache>>::iterator iter;
2308 for (iter = readValCache_.begin(); iter != readValCache_.end(); iter++) {
2309 if (connectHandle == iter->first && handle == iter->second.handle_) {
2310 packet = iter->second.data_;
2311 break;
2312 }
2313 }
2314 if (packet == nullptr) {
2315 packet = PacketMalloc(0, 0, 0);
2316 }
2317 PacketPayloadAddLast(packet, data);
2318 if (iter == readValCache_.end()) {
2319 readValCache_.emplace_back(connectHandle, ReadValCache(handle, offset, packet));
2320 }
2321 }
2322 /**
2323 * @brief Get data from ReadValueCache.
2324 *
2325 * @param connectHandle Indicates identify a connection.
2326 * @param handle Indicates att handle.
2327 * @since 6.0
2328 */
GetReadValueCache(uint16_t connectHandle,uint16_t handle)2329 uint8_t *GattClientProfile::impl::GetReadValueCache(uint16_t connectHandle, uint16_t handle)
2330 {
2331 uint8_t *buffer = nullptr;
2332 std::list<std::pair<uint16_t, ReadValCache>>::iterator iter;
2333 for (iter = readValCache_.begin(); iter != readValCache_.end(); iter++) {
2334 if (connectHandle == iter->first && handle == iter->second.handle_) {
2335 buffer = (uint8_t *)malloc(PacketSize(iter->second.data_));
2336 if (buffer == nullptr) {
2337 break;
2338 }
2339 PacketRead(iter->second.data_, buffer, 0, PacketSize(iter->second.data_));
2340 PacketFree(iter->second.data_);
2341 readValCache_.erase(iter);
2342 break;
2343 }
2344 }
2345 return buffer;
2346 }
2347
2348 /* @brief Delete list of request and response when gatt is disconnected.
2349 *
2350 * @param connectHandle Indicates identify a connection.
2351 * @since 6.0
2352 */
DeleteList(uint16_t connectHandle)2353 void GattClientProfile::impl::DeleteList(uint16_t connectHandle)
2354 {
2355 LOG_INFO("%{public}s: connectHandle is %{public}hu.", __FUNCTION__, connectHandle);
2356 auto reqList = requestList_.begin();
2357 while (reqList != requestList_.end()) {
2358 if (connectHandle == reqList->first) {
2359 requestList_.erase(reqList++);
2360 } else {
2361 reqList++;
2362 }
2363 }
2364
2365 auto respList = responseList_.begin();
2366 while (respList != responseList_.end()) {
2367 if (connectHandle == respList->first) {
2368 responseList_.erase(respList++);
2369 } else {
2370 respList++;
2371 }
2372 }
2373 }
2374 /**
2375 * @brief Indicates connect or disconnect.
2376 *
2377 * @since 6.0
2378 */
2379 class GattClientProfile::impl::GattConnectionObserverImplement : public GattConnectionObserver {
2380 public:
OnConnect(const GattDevice & device,uint16_t connectionHandle,uint8_t role,int ret)2381 void OnConnect(const GattDevice &device, uint16_t connectionHandle, uint8_t role, int ret) override
2382 {
2383 LOG_INFO("%{public}s: gatt_client connect role is %{public}d", __FUNCTION__, role);
2384 if (role == 1) {
2385 return;
2386 }
2387 this->clientProfile_.pimpl->CreateCache(connectionHandle, device);
2388 }
2389
OnDisconnect(const GattDevice & device,uint16_t connectionHandle,uint8_t role,int ret)2390 void OnDisconnect(const GattDevice &device, uint16_t connectionHandle, uint8_t role, int ret) override
2391 {
2392 if (role == 1) {
2393 LOG_INFO("%{public}s device role is slave", __FUNCTION__);
2394 return;
2395 }
2396 this->clientProfile_.pimpl->DeleteList(connectionHandle);
2397 this->clientProfile_.pimpl->SetMtuInformation(connectionHandle, false, GATT_DEFAULT_MTU);
2398 this->clientProfile_.pimpl->DeleteCache(connectionHandle, device);
2399 }
2400
OnReconnect(const GattDevice & device,uint16_t connectionHandle,uint8_t role,int ret)2401 void OnReconnect(const GattDevice &device, uint16_t connectionHandle, uint8_t role, int ret) override
2402 {
2403 LOG_INFO("%{public}s gatt client service", __FUNCTION__);
2404 if (role == 1) { // slave role.
2405 return;
2406 }
2407 this->clientProfile_.pimpl->CreateCache(connectionHandle, device);
2408 }
2409
OnDisconnectInter(const GattDevice & device,uint16_t connectionHandle,uint8_t role,int ret)2410 void OnDisconnectInter(const GattDevice &device, uint16_t connectionHandle, uint8_t role, int ret) override
2411 {
2412 if (role == 1) {
2413 LOG_INFO("%{public}s device role is slave", __FUNCTION__);
2414 return;
2415 }
2416 this->clientProfile_.pimpl->DeleteCache(connectionHandle, device);
2417 }
2418
GattConnectionObserverImplement(GattClientProfile & clientProfile)2419 GattConnectionObserverImplement(GattClientProfile &clientProfile) : clientProfile_(clientProfile)
2420 {}
~GattConnectionObserverImplement()2421 ~GattConnectionObserverImplement()
2422 {}
2423
2424 private:
2425 GattClientProfile &clientProfile_;
2426 };
2427 /**
2428 * @brief Register callback to ConnectManager.
2429 *
2430 * @since 6.0
2431 */
RegisterCallbackToConnectManager()2432 void GattClientProfile::impl::RegisterCallbackToConnectManager()
2433 {
2434 LOG_INFO("%{public}s", __FUNCTION__);
2435 connectionObserverId_ = GattConnectionManager::GetInstance().RegisterObserver(*connectionCallBack_);
2436 if (connectionObserverId_ < 0) {
2437 LOG_ERROR("%{public}s: GATT_profile register callback to ConnectManager failed", __FUNCTION__);
2438 }
2439 }
2440 /**
2441 * @brief Unregister callback to ConnectManager.
2442 *
2443 * @since 6.0
2444 */
DeregisterCallbackToConnectManager()2445 void GattClientProfile::impl::DeregisterCallbackToConnectManager()
2446 {
2447 LOG_INFO("%{public}s", __FUNCTION__);
2448 GattConnectionManager::GetInstance().DeregisterObserver(connectionObserverId_);
2449 }
2450 } // namespace bluetooth
2451