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