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, &parameter, 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, &parameter, 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