1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gatt_client_profile.h"
17 #include "att.h"
18 #include "bt_def.h"
19 #include "gatt_connection_manager.h"
20 #include "gatt_profile_defines.h"
21 #include "gatt_service_base.h"
22 #include "log.h"
23 #include "securec.h"
24
25 namespace OHOS {
26 namespace bluetooth {
27 struct GattClientProfile::impl {
28 class GattConnectionObserverImplement;
29 GattClientProfileCallback *pClientCallBack_ = nullptr;
30 int connectionObserverId_ = 0;
31 utility::Dispatcher *dispatcher_;
32 std::map<uint16_t, GattCache> cacheMap_ = {};
33 std::map<uint16_t, MtuInfo> mtuInfo_ = {};
34 std::list<std::pair<uint16_t, GattRequestInfo>> requestList_ = {};
35 std::list<std::pair<uint16_t, GattRequestInfo>> responseList_ = {};
36 std::list<std::pair<uint16_t, ReadValCache>> readValCache_ = {};
37 std::unique_ptr<GattConnectionObserverImplement> connectionCallBack_ = {};
38 GattClientProfile *profile_ = nullptr;
implOHOS::bluetooth::GattClientProfile::impl39 impl(GattClientProfileCallback *pClientCallbackFunc, utility::Dispatcher *dispatcher, GattClientProfile &profile)
40 : pClientCallBack_(pClientCallbackFunc),
41 dispatcher_(dispatcher),
42 connectionCallBack_(std::make_unique<GattConnectionObserverImplement>(profile))
43 {}
44 BT_DISALLOW_COPY_AND_ASSIGN(impl);
45
46 static void ReceiveData(uint16_t connectHandle, uint16_t event, void *eventData, Buffer *buffer, void *context);
47 static void ReceiveRequestResult(uint16_t connectHandle, int result, void *context);
48 void RegisterCallbackToATT();
49 static void DeregisterCallbackToATT();
50 void RegisterCallbackToConnectManager();
51 void DeregisterCallbackToConnectManager();
52 void ReceiveRequestResultProcess(uint16_t connectHandle);
53 void IndicateRequestRetToService(int reqId, uint16_t connectHandle, ResponesType reqType, uint8_t errorCode);
54 void ReceiveDataProcess(uint16_t connectHandle, uint16_t event, AttEventData *data, Buffer *buffer,
55 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator attResp);
56 void SetMtuInformation(uint16_t connectHandle, bool isExchanged, uint16_t mtu);
57 MtuInfo GetMtuInformation(uint16_t connectHandle);
58 void AddResponseList(void);
59 void RemoveRequestList(std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
60 void ErrorResponseParsing(
61 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
62 void ErrorResponseParsing(uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
63 void ExchangeMtuParsing(
64 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
65 void DiscoverAllPrimaryServiceParsing(int reqId, uint16_t connectHandle, AttEventData *data);
66 void DiscoverPrimaryServiceByUuidParsing(
67 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
68 void FindIncludeServicesParsing(
69 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
70 void FindIncludeServicesParsing(uint16_t connectHandle, uint16_t handle, Buffer *buffer);
71 void DiscoverAllCharacteristicOfServiceParsing(uint16_t connectHandle, AttEventData *data, bool isByUuid,
72 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
73 void SendDiscoverAllCharacteristicRequest(uint16_t connectHandle, uint16_t startHandle, uint16_t valueHandle,
74 Uuid uuid, bool isByUuid, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
75 void DiscoverCharacteristicByUUIDParsing(
76 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
77 void DiscoverAllCharacteristicDescriptorsParsing(
78 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
79 void ReadCharacteristicValueParsing(
80 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
81 void ReadLongCharacteristicValueParsing(
82 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
83 void ReadUsingCharacteristicByUuidParsing(
84 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
85 void ReadMultipleCharacteristicParsing(
86 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
87 void ReadCharacteristicDescriptorsParsing(
88 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
89 void ReadLongCharacteristicDescriptorsParsing(
90 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
91 void WriteCharacteristicValueParsing(
92 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
93 void WriteCharacteristicDescriptorsParsing(
94 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
95 void WriteLongCharacteristicValueParsing(uint16_t connectHandle, uint16_t handle, uint16_t offset, Buffer *buffer,
96 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
97 void ExecuteWriteParsing(uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
98 void NotificationParsing(uint16_t connectHandle, AttEventData *data, Buffer *buffer);
99 void IndicationParsing(uint16_t connectHandle, const AttEventData *data, Buffer *buffer);
100 void GattRequestTimeoutParsing(int reqId, uint16_t connectHandle, ResponesType respType);
101 static int ConvertResponseErrorCode(uint8_t errorCode);
102 void SplitReadByTypeRsp(
103 uint16_t connectHandle, AttEventData *data, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
104 void SplitReadRsp(
105 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
106 void SplitReadBlobRsp(
107 uint16_t connectHandle, Buffer *buffer, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
108 void SplitWriteRsp(uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
109 void SplitPrepareWriteRsp(uint16_t connectHandle, AttEventData *data, Buffer *buffer,
110 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
111 void SplitReadByTypeReqErrorParsing(
112 uint16_t connectHandle, std::list<std::pair<uint16_t, GattRequestInfo>>::iterator iter);
113 void SplitReadReqErrorParsing(
114 int reqId, uint16_t connectHandle, ResponesType respType, uint16_t handle, int result);
115 void SplitWriteReqErrorParsing(
116 int reqId, uint16_t connectHandle, ResponesType respType, uint16_t handle, int result);
117 static uint16_t SplitDataPackageToUint16(uint8_t *src, uint8_t *offset);
118 static uint8_t SplitDataPackageToUint8(const uint8_t *src, uint8_t *offset);
119 static void SplitDataPackage(uint8_t *dest, uint8_t destMax, uint8_t *offset, uint8_t *src, uint8_t size);
120 static Uuid SplitUuidPackage(const uint8_t *value, uint8_t len);
121 void AddReadValueCache(uint16_t connectHandle, uint16_t handle, uint16_t offset, Buffer *data);
122 uint8_t *GetReadValueCache(uint16_t connectHandle, uint16_t handle);
123 void CreateCache(uint16_t connectHandle, const GattDevice device);
124 void DeleteCache(uint16_t connectHandle, const GattDevice device);
125 void DeleteList(uint16_t connectHandle);
126 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByRequestInfor(uint16_t connectHandle);
127 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByRespones(
128 ResponesType reqType, int reqId);
129 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByResponesInfor(
130 uint16_t handle, uint16_t respType);
131 std::list<std::pair<uint16_t, GattRequestInfo>>::iterator FindIteratorByResponesInfor(
132 uint16_t handle, ResponesType respType);
133 };
134 /**
135 * @brief A constructor used to create <pClientCallbackFunc> and <dispatcher> instance..
136 *
137 * @since 6.0
138
139 */
GattClientProfile(GattClientProfileCallback * pClientCallbackFunc,utility::Dispatcher * dispatcher)140 GattClientProfile::GattClientProfile(GattClientProfileCallback *pClientCallbackFunc, utility::Dispatcher *dispatcher)
141 : pimpl(new (std::nothrow)GattClientProfile::impl(pClientCallbackFunc, dispatcher, *this))
142 {
143 if (pimpl == nullptr) {
144 LOG_ERROR("GattClientProfile get pimpl nullptr.");
145 return;
146 }
147 pimpl->RegisterCallbackToConnectManager();
148 }
149 /**
150 * @brief A destructor used to delete the <pClientCallbackFunc> and <dispatcher> instance.
151 *
152 * @since 6.0
153 */
~GattClientProfile()154 GattClientProfile::~GattClientProfile()
155 {
156 pimpl->DeregisterCallbackToConnectManager();
157 }
158 /**
159 * @brief Enable gatt client profile.
160 *
161 * @since 6.0
162 */
Enable() const163 void GattClientProfile::Enable() const
164 {
165 pimpl->cacheMap_.clear();
166 pimpl->requestList_.clear();
167 pimpl->responseList_.clear();
168 pimpl->mtuInfo_.clear();
169 pimpl->RegisterCallbackToATT();
170 }
171 /**
172 * @brief Disable gatt client profile.
173 *
174 * @since 6.0
175 */
Disable() const176 void GattClientProfile::Disable() const
177 {
178 pimpl->DeregisterCallbackToATT();
179 }
180 /**
181 * @brief Register callback function to ATT.
182 *
183 * @since 6.0
184 */
RegisterCallbackToATT()185 void GattClientProfile::impl::RegisterCallbackToATT()
186 {
187 LOG_INFO("%{public}s", __FUNCTION__);
188 attCallback attDataCallback = GattClientProfile::impl::ReceiveData;
189 attSendDataCallback attReqCallback = GattClientProfile::impl::ReceiveRequestResult;
190
191 ATT_ClientDataRegister(attDataCallback, this);
192 ATT_ClientSendDataRegister(attReqCallback, this);
193 }
194 /**
195 * @brief Unregister callback function to att.
196 *
197 * @since 6.0
198 */
DeregisterCallbackToATT()199 void GattClientProfile::impl::DeregisterCallbackToATT()
200 {
201 LOG_INFO("%{public}s", __FUNCTION__);
202 ATT_ClientDataDeregister();
203 ATT_ClientSendDataDeRegister();
204 }
205 /**
206 * @brief This sub-procedure is used by the client to set the ATT_MTU to the maximum possible value.
207 *
208 * @param reqId Indicates request id.
209 * @param connectHandle Indicates identify a connection.
210 * @param mtu Indicates att bearer transmission unit.
211 * @since 6.0
212 */
ExchangeMtu(int reqId,uint16_t connectHandle,uint16_t mtu) const213 void bluetooth::GattClientProfile::ExchangeMtu(int reqId, uint16_t connectHandle, uint16_t mtu) const
214 {
215 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
216 if (GattConnectionManager::GetInstance().GetDeviceTransport(connectHandle) == GATT_TRANSPORT_TYPE_CLASSIC) {
217 pimpl->pClientCallBack_->OnExchangeMtuEvent(reqId, connectHandle, DEFAULT_CLASSIC_CONNECTION_MTU, false);
218 } else if (!pimpl->GetMtuInformation(connectHandle).isExchanged_) {
219 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(EXCHANGE_MTU, mtu, reqId));
220 LOG_DEBUG("%{public}s: Add requestList_: EXCHANGE_MTU", __FUNCTION__);
221 ATT_ExchangeMTURequest(connectHandle, mtu);
222 } else {
223 pimpl->pClientCallBack_->OnExchangeMtuEvent(
224 reqId, connectHandle, pimpl->GetMtuInformation(connectHandle).mtu_, false);
225 }
226 }
227 /**
228 * @brief This sub-procedure is used by a client to discover all the primary services on a server.
229 *
230 * @param reqId Indicates request id.
231 * @param connectHandle Indicates identify a connection.
232 * @param startHandle Indicates starting handle of the specified service.
233 * @param endHandle Indicates ending handle of the specified service.n.
234 * @since 6.0
235 */
DiscoverAllPrimaryServices(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const236 void bluetooth::GattClientProfile::DiscoverAllPrimaryServices(
237 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
238 {
239 LOG_INFO("%{public}s: connectHandle is %hu, Add requestList_: DISCOVER_ALL_PRIMARY_SERVICE.",
240 __FUNCTION__, connectHandle);
241 BtUuid primarySvcUuid = {BT_UUID_16, {UUID_PRIMARY_SERVICE}};
242 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(DISCOVER_ALL_PRIMARY_SERVICE, reqId));
243 ATT_ReadByGroupTypeRequest(connectHandle, startHandle, endHandle, &primarySvcUuid);
244 }
245
246 /**
247 * @brief This sub-procedure is used by a client to discover all the primary services on a server.
248 *
249 * @param reqId Indicates request id.
250 * @param connectHandle Indicates identify a connection.
251 * @param startHandle Indicates starting handle of the specified service.
252 * @param endHandle Indicates ending handle of the specified service.n.
253 * @since 6.0
254 */
DiscoverAllPrimaryServicesInter(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const255 void bluetooth::GattClientProfile::DiscoverAllPrimaryServicesInter(
256 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
257 {
258 LOG_INFO("%{public}s: connectHandle is %{public}hu, Add requestList_: DISCOVER_ALL_PRIMARY_SERVICE.",
259 __FUNCTION__, connectHandle);
260 auto iter = pimpl->FindIteratorByRespones(DISCOVER_ALL_PRIMARY_SERVICE, reqId);
261 if (iter == pimpl->responseList_.end()) {
262 LOG_INFO("%{public}s: not find connectionHandle(%{public}hu) in response list", __FUNCTION__, connectHandle);
263 return;
264 }
265 pimpl->responseList_.erase(iter);
266
267 BtUuid primarySvcUuid = {BT_UUID_16, {UUID_PRIMARY_SERVICE}};
268 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(DISCOVER_ALL_PRIMARY_SERVICE, reqId));
269 ATT_ReadByGroupTypeRequest(connectHandle, startHandle, endHandle, &primarySvcUuid);
270 }
271
272 /**
273 * @brief This sub-procedure is used by a client to discover a specific primary service on a server when only
274 * the Service UUID is known.
275 *
276 * @param reqId Indicates request id.
277 * @param connectHandle Indicates identify a connection.
278 * @param uuid Indicates service uuid.
279 * @since 6.0
280 */
DiscoverPrimaryServicesByServiceUuid(int reqId,uint16_t connectHandle,const Uuid & uuid) const281 void GattClientProfile::DiscoverPrimaryServicesByServiceUuid(int reqId, uint16_t connectHandle, const Uuid &uuid) const
282 {
283 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
284 uint8_t uuid128[UUID_128BIT_LEN] = {0};
285 Buffer *serviceUuid = BufferMalloc(uuid.GetUuidType());
286 AttFindByTypeValueReq parameter;
287 parameter.attType = UUID_PRIMARY_SERVICE;
288 parameter.handleRange.startHandle = MIN_ATTRIBUTE_HANDLE;
289 parameter.handleRange.endHandle = MAX_ATTRIBUTE_HANDLE;
290
291 if (uuid.GetUuidType() == UUID_16BIT_LEN) {
292 uint16_t uuid16 = uuid.ConvertTo16Bits();
293 (void)memcpy_s(BufferPtr(serviceUuid), UUID_16BIT_LEN, &(uuid16), UUID_16BIT_LEN);
294 pimpl->requestList_.emplace_back(
295 std::make_pair(connectHandle, GattRequestInfo(uuid, DISCOVER_SERVICE_BY_UUID, reqId)));
296 } else if (uuid.GetUuidType() == UUID_32BIT_LEN) {
297 uint32_t uuid32 = uuid.ConvertTo32Bits();
298 (void)memcpy_s(BufferPtr(serviceUuid), UUID_32BIT_LEN, &(uuid32), UUID_32BIT_LEN);
299 pimpl->requestList_.emplace_back(
300 std::make_pair(connectHandle, GattRequestInfo(uuid, DISCOVER_SERVICE_BY_UUID, reqId)));
301 } else if (uuid.GetUuidType() == UUID_128BIT_LEN) {
302 uuid.ConvertToBytesLE(uuid128, UUID_128BIT_LEN);
303 (void)memcpy_s(BufferPtr(serviceUuid), UUID_128BIT_LEN, uuid128, UUID_128BIT_LEN);
304 pimpl->requestList_.emplace_back(
305 std::make_pair(connectHandle, GattRequestInfo(uuid, DISCOVER_SERVICE_BY_UUID, reqId)));
306 } else {
307 BufferFree(serviceUuid);
308 LOG_ERROR("%{public}s: Service UUID length is failed", __FUNCTION__);
309 return;
310 }
311 ATT_FindByTypeValueRequest(connectHandle, ¶meter, serviceUuid);
312 BufferFree(serviceUuid);
313 }
314 /**
315 * @brief This sub-procedure is used by a client to find include service declarations within a service definition
316 * on a server.
317 *
318 * @param reqId Indicates request id.
319 * @param connectHandle Indicates identify a connection.
320 * @param startHandle Indicates starting handle of the specified service.
321 * @param endHandle Indicates ending handle of the specified service.
322 * @since 6.0
323 */
FindIncludedServices(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const324 void GattClientProfile::FindIncludedServices(
325 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
326 {
327 LOG_INFO("%{public}s Parameter startHandle is %hu, endHandle is %hu", __FUNCTION__, startHandle, endHandle);
328 BtUuid includeSvcUuid = {BT_UUID_16, {UUID_INCLUDE_SERVICE}};
329
330 auto iter = pimpl->cacheMap_.find(connectHandle)->second.GetIncludeServices(startHandle);
331 if (iter != nullptr) {
332 iter->clear();
333 }
334 pimpl->requestList_.emplace_back(
335 connectHandle, GattRequestInfo(FIND_INCLUDE_SERVICE, startHandle, endHandle, reqId));
336 LOG_DEBUG("%{public}s: Add requestList_: FIND_INCLUDE_SERVICE", __FUNCTION__);
337 ATT_ReadByTypeRequest(connectHandle, startHandle, endHandle, &includeSvcUuid);
338 }
339 /**
340 * @brief This sub-procedure is used by a client to find all the characteristic declarations within a service
341 * definition on a server.
342 *
343 * @param reqId Indicates request id.
344 * @param connectHandle Indicates identify a connection.
345 * @param startHandle Indicates starting handle of the specified service.
346 * @param endHandle Indicates ending handle of the specified service.
347 * @since 6.0
348 */
DiscoverAllCharacteristicOfService(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const349 void GattClientProfile::DiscoverAllCharacteristicOfService(
350 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
351 {
352 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
353 Uuid tempUuid;
354 BtUuid characteristicUuid = {BT_UUID_16, {UUID_CHARACTERISTIC}};
355
356 auto iter = pimpl->cacheMap_.find(connectHandle)->second.GetCharacteristics(startHandle);
357 if (iter != nullptr) {
358 iter->clear();
359 }
360
361 pimpl->requestList_.emplace_back(connectHandle,
362 GattRequestInfo(DISCOVER_ALL_CHARACTERISTIC,
363 startHandle,
364 endHandle,
365 tempUuid.ConvertFrom16Bits(UUID_CHARACTERISTIC),
366 reqId));
367 LOG_DEBUG("%{public}s: Add requestList_: DISCOVER_ALL_CHARACTERISTIC", __FUNCTION__);
368 ATT_ReadByTypeRequest(connectHandle, startHandle, endHandle, &characteristicUuid);
369 }
370 /**
371 * @brief This sub-procedure is used by a client to discover service characteristics on a server when only the
372 * service handle ranges are known and the characteristic UUID is known.
373 *
374 * @param reqId Indicates request id.
375 * @param connectHandle Indicates identify a connection.
376 * @param startHandle Indicates starting handle of the specified service.
377 * @param endHandle Indicates ending handle of the specified service.
378 * @param uuid Indicates characteristic uuid.
379 * @since 6.0
380 */
DiscoverCharacteristicByUuid(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle,const Uuid & uuid) const381 void GattClientProfile::DiscoverCharacteristicByUuid(
382 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle, const Uuid &uuid) const
383 {
384 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
385 BtUuid tempUuid;
386 uint8_t uuid128[UUID_128BIT_LEN] = {0};
387
388 auto iter = pimpl->cacheMap_.find(connectHandle)->second.GetCharacteristics(startHandle);
389 if (iter != nullptr) {
390 iter->clear();
391 }
392
393 if (uuid.GetUuidType() == UUID_16BIT_LEN) {
394 tempUuid = {BT_UUID_16, {uuid.ConvertTo16Bits()}};
395 pimpl->requestList_.emplace_back(connectHandle,
396 GattRequestInfo(DISCOVER_CHARACTERISTIC_BY_UUID,
397 startHandle,
398 endHandle,
399 uuid.ConvertFrom16Bits(tempUuid.uuid16),
400 reqId));
401 } else if (uuid.GetUuidType() == UUID_32BIT_LEN) {
402 tempUuid = {.type = BT_UUID_32, .uuid32 = uuid.ConvertTo32Bits()};
403 pimpl->requestList_.emplace_back(connectHandle,
404 GattRequestInfo(DISCOVER_CHARACTERISTIC_BY_UUID,
405 startHandle,
406 endHandle,
407 uuid.ConvertFrom32Bits(tempUuid.uuid32),
408 reqId));
409 } else if (uuid.GetUuidType() == UUID_128BIT_LEN) {
410 uuid.ConvertToBytesLE(uuid128, UUID_128BIT_LEN);
411 tempUuid.type = BT_UUID_128;
412 (void)memcpy_s(tempUuid.uuid128, UUID_128BIT_LEN, uuid128, UUID_128BIT_LEN);
413 pimpl->requestList_.emplace_back(connectHandle,
414 GattRequestInfo(DISCOVER_CHARACTERISTIC_BY_UUID,
415 startHandle,
416 endHandle,
417 uuid.ConvertFromBytesLE(tempUuid.uuid128, UUID_128BIT_LEN),
418 reqId));
419 } else {
420 LOG_ERROR("%{public}s: Call - ATT_ReadByTypeRequest - Fail!", __FUNCTION__);
421 return;
422 }
423 ATT_ReadByTypeRequest(connectHandle, startHandle, endHandle, &tempUuid);
424 }
425 /**
426 * @brief This sub-procedure is used by a client to find all the characteristic descriptor’s
427 * Attribute Handles and Attribute Types.
428 *
429 * @param reqId Indicates request id.
430 * @param connectHandle Indicates identify a connection.
431 * @param startHandle Indicates starting handle of the specified service.
432 * @param endHandle Indicates ending handle of the specified service.
433 * @since 6.0
434 */
DiscoverAllCharacteristicDescriptors(int reqId,uint16_t connectHandle,uint16_t startHandle,uint16_t endHandle) const435 void GattClientProfile::DiscoverAllCharacteristicDescriptors(
436 int reqId, uint16_t connectHandle, uint16_t startHandle, uint16_t endHandle) const
437 {
438 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
439 // startHandle is handle of characteristic declaration
440 if (startHandle != INVALID_ATTRIBUTE_HANDLE && startHandle <= endHandle - sizeof(startHandle) &&
441 startHandle <= MAX_ATTRIBUTE_HANDLE - sizeof(startHandle)) {
442 pimpl->requestList_.emplace_back(
443 connectHandle, GattRequestInfo(DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR, startHandle, endHandle, reqId));
444 LOG_DEBUG("%{public}s: Add requestList_: DISCOVER_ALL_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
445 ATT_FindInformationRequest(connectHandle, startHandle + sizeof(startHandle), endHandle);
446 } else {
447 LOG_DEBUG("%{public}s: No descriptor value in the characteristic", __FUNCTION__);
448 uint16_t serviceHandle = pimpl->cacheMap_.find(connectHandle)->second.GetDescriptors(startHandle).second;
449 pimpl->pClientCallBack_->OnDiscoverAllCharacteristicDescriptorsEvent(reqId,
450 GATT_SUCCESS,
451 serviceHandle,
452 startHandle,
453 *pimpl->cacheMap_.find(connectHandle)->second.GetDescriptors(startHandle).first);
454 }
455 }
456 /**
457 * @brief This sub-procedure is used to read a Characteristic Value from a server.
458 *
459 * @param reqId Indicates request id.
460 * @param connectHandle Indicates identify a connection.
461 * @param handle Indicates attribute handle.
462 * @since 6.0
463 */
ReadCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle) const464 void bluetooth::GattClientProfile::ReadCharacteristicValue(int reqId, uint16_t connectHandle, uint16_t handle) const
465 {
466 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
467 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(READ_CHARACTERISTIC_VALUE, handle, reqId));
468 LOG_DEBUG("%{public}s: Add requestList_: READ_CHARACTERISTIC_VALUE", __FUNCTION__);
469 ATT_ReadRequest(connectHandle, handle);
470 }
471 /**
472 * @brief This sub-procedure is used to read a Characteristic Value by uuid from a server.
473 *
474 * @param reqId Indicates request id.
475 * @param connectHandle Indicates identify a connection.
476 * @param uuid Indicates characteristic uuid.
477 * @since 6.0
478 */
ReadUsingCharacteristicByUuid(int reqId,uint16_t connectHandle,const Uuid & uuid) const479 void GattClientProfile::ReadUsingCharacteristicByUuid(int reqId, uint16_t connectHandle, const Uuid &uuid) const
480 {
481 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
482 BtUuid tempUuid;
483 uint8_t uuid128[UUID_128BIT_LEN] = {0};
484
485 if (uuid.GetUuidType() == UUID_16BIT_LEN) {
486 tempUuid = {BT_UUID_16, {uuid.ConvertTo16Bits()}};
487 pimpl->requestList_.emplace_back(connectHandle,
488 GattRequestInfo(READ_USING_CHARACTERISTIC_UUID,
489 MIN_ATTRIBUTE_HANDLE,
490 MAX_ATTRIBUTE_HANDLE,
491 uuid.ConvertFrom16Bits(tempUuid.uuid16),
492 reqId));
493 LOG_DEBUG("%{public}s: Add requestList_: READ_USING_CHARACTERISTIC_UUID", __FUNCTION__);
494 } else if (uuid.GetUuidType() == UUID_128BIT_LEN) {
495 uuid.ConvertToBytesLE(uuid128, UUID_128BIT_LEN);
496 tempUuid.type = BT_UUID_128;
497 (void)memcpy_s(tempUuid.uuid128, UUID_128BIT_LEN, uuid128, UUID_128BIT_LEN);
498 pimpl->requestList_.emplace_back(connectHandle,
499 GattRequestInfo(READ_USING_CHARACTERISTIC_UUID,
500 MIN_ATTRIBUTE_HANDLE,
501 MAX_ATTRIBUTE_HANDLE,
502 uuid.ConvertFromBytesLE(tempUuid.uuid128, UUID_128BIT_LEN),
503 reqId));
504 LOG_DEBUG("%{public}s: Add requestList_: READ_USING_CHARACTERISTIC_UUID", __FUNCTION__);
505 } else {
506 LOG_ERROR("%{public}s: Call - ATT_ReadByTypeRequest - Fail!", __FUNCTION__);
507 return;
508 }
509 ATT_ReadByTypeRequest(connectHandle, MIN_ATTRIBUTE_HANDLE, MAX_ATTRIBUTE_HANDLE, &tempUuid);
510 }
511 /**
512 * @brief This sub-procedure is used to read a long characteristic values from a server.
513 *
514 * @param reqId Indicates request id.
515 * @param connectHandle Indicates identify a connection.
516 * @param handle Indicates attribute handle.
517 * @since 6.0
518 */
ReadLongCharacteristicValue(int reqId,uint16_t connectHandle,uint16_t handle) const519 void GattClientProfile::ReadLongCharacteristicValue(int reqId, uint16_t connectHandle, uint16_t handle) const
520 {
521 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
522 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(READ_LONG_CHARACTERISTIC_VALUE, handle, reqId));
523 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_VALUE", __FUNCTION__);
524 ATT_ReadRequest(connectHandle, handle);
525 }
526 /**
527 * @brief This sub-procedure is used to read multiple characteristic values.
528 *
529 * @param reqId Indicates request id.
530 * @param connectHandle Indicates identify a connection.
531 * @param value Indicates attribute handle list.
532 * @param len Indicates size of value.
533 * @since 6.0
534 */
ReadMultipleCharacteristicValue(int reqId,uint16_t connectHandle,const GattValue & value,size_t len) const535 void GattClientProfile::ReadMultipleCharacteristicValue(
536 int reqId, uint16_t connectHandle, const GattValue &value, size_t len) const
537 {
538 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
539 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
540 if (buffer != nullptr) {
541 pimpl->requestList_.emplace_back(
542 connectHandle, GattRequestInfo(READ_MULTIPLE_CHARACTERISTIC, MIN_ATTRIBUTE_HANDLE, reqId));
543 LOG_DEBUG("%{public}s: Add requestList_: READ_MULTIPLE_CHARACTERISTIC", __FUNCTION__);
544 ATT_ReadMultipleRequest(connectHandle, buffer);
545 BufferFree(buffer);
546 }
547 }
548 /**
549 * @brief This sub-procedure is used to read a characteristic descriptor from a server.
550 *
551 * @param reqId Indicates request id.
552 * @param connectHandle Indicates identify a connection.
553 * @param handle Indicates attribute handle.
554 * @since 6.0
555 */
ReadDescriptorValue(int reqId,uint16_t connectHandle,uint16_t handle) const556 void GattClientProfile::ReadDescriptorValue(int reqId, uint16_t connectHandle, uint16_t handle) const
557 {
558 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
559 pimpl->requestList_.emplace_back(connectHandle, GattRequestInfo(READ_CHARACTERISTIC_DESCRIPTOR, handle, reqId));
560 LOG_DEBUG("%{public}s: Add requestList_: READ_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
561 ATT_ReadRequest(connectHandle, handle);
562 }
563 /**
564 * @brief This sub-procedure is used to read a characteristic descriptor from a server and the length of the
565 * characteristic descriptor declaration is longer than can be sent in a single Read Response Attribute
566 * Protocol message..
567 *
568 * @param reqId Indicates request id.
569 * @param connectHandle Indicates identify a connection.
570 * @param handle Indicates attribute handle.
571 * @since 6.0
572 */
ReadLongCharacteristicDescriptor(int reqId,uint16_t connectHandle,uint16_t handle) const573 void GattClientProfile::ReadLongCharacteristicDescriptor(int reqId, uint16_t connectHandle, uint16_t handle) const
574 {
575 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
576 pimpl->requestList_.emplace_back(
577 connectHandle, GattRequestInfo(READ_LONG_CHARACTERISTIC_DESCRIPTOR, handle, reqId));
578 LOG_DEBUG("%{public}s: Add requestList_: READ_LONG_CHARACTERISTIC_DESCRIPTOR", __FUNCTION__);
579 ATT_ReadRequest(connectHandle, handle);
580 }
581 /**
582 * @brief This sub-procedure is used to write a Characteristic Value to a server when the client knows the
583 * Characteristic Value Handle and the client does not need an acknowledgment that the write was successfully
584 * performed.
585 *
586 * @param reqId Indicates request id.
587 * @param connectHandle Indicates identify a connection.
588 * @param handle Indicates attribute handle.
589 * @param value Indicates value of the schedule settings.
590 * @param len Indicates size of value.
591 * @since 6.0
592 */
WriteWithoutResponse(int reqId,uint16_t connectHandle,uint16_t handle,const GattValue & value,size_t len) const593 void GattClientProfile::WriteWithoutResponse(
594 int reqId, uint16_t connectHandle, uint16_t handle, const GattValue &value, size_t len) const
595 {
596 LOG_INFO("%{public}s: connectHandle is %hu.", __FUNCTION__, connectHandle);
597 Buffer *buffer = GattServiceBase::BuildBuffer(value->get(), len);
598 if (buffer != nullptr) {
599 ATT_WriteCommand(connectHandle, handle, buffer);
600 BufferFree(buffer);
601 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, ¶meter, 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