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