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