1 /*
2 * Copyright (c) 2021 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 #include "softbus_adapter_ble_gatt_server.h"
16
17 #include "securec.h"
18
19 #include "softbus_adapter_timer.h"
20 #include "softbus_def.h"
21 #include "softbus_errcode.h"
22 #include "softbus_log.h"
23 #include "softbus_type_def.h"
24
25 #include "c_header/ohos_bt_def.h"
26 #include "c_header/ohos_bt_gatt_server.h"
27
28 #define WAIT_HAL_REG_TIME 5 // ms
29 #define WAIT_HAL_REG_RETRY 3
30
31 static const char SOFTBUS_APP_UUID[BT_UUID_LEN] = {
32 0x00, 0x00, 0xFE, 0x36, 0x00, 0x00, 0x10, 0x00,
33 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
34 };
35
36 SoftBusGattsCallback *g_gattsCallback = NULL;
37 static BtGattServerCallbacks g_bleGattsHalCallback = {0};
38 static volatile int g_halServerId = -1;
39 static volatile int g_halRegFlag = -1; // -1:not registered or register failed; 0:registerring; 1:registered
40
CheckGattsStatus(void)41 NO_SANITIZE("cfi") int CheckGattsStatus(void)
42 {
43 if (g_gattsCallback == NULL) {
44 return SOFTBUS_ERR;
45 }
46 while (g_halRegFlag == 0) {
47 CLOGE("ble hal registerring");
48 static int tryTimes = WAIT_HAL_REG_RETRY;
49 if (tryTimes > 0) {
50 SoftBusSleepMs(WAIT_HAL_REG_TIME);
51 tryTimes--;
52 } else {
53 g_halRegFlag = -1;
54 break;
55 }
56 }
57 if (g_halRegFlag == -1) {
58 return SOFTBUS_ERR;
59 }
60 return SOFTBUS_OK;
61 }
62
SoftBusGattsAddService(SoftBusBtUuid srvcUuid,bool isPrimary,int number)63 NO_SANITIZE("cfi") int SoftBusGattsAddService(SoftBusBtUuid srvcUuid, bool isPrimary, int number)
64 {
65 if ((srvcUuid.uuidLen == 0) || (srvcUuid.uuid == NULL) || (number <= 0)) {
66 return SOFTBUS_ERR;
67 }
68 if (CheckGattsStatus() != SOFTBUS_OK) {
69 return SOFTBUS_ERR;
70 }
71 BtUuid uuid = {
72 .uuid = srvcUuid.uuid,
73 .uuidLen = srvcUuid.uuidLen
74 };
75 if (BleGattsAddService(g_halServerId, uuid, isPrimary, number) != SOFTBUS_OK) {
76 return SOFTBUS_ERR;
77 }
78 return SOFTBUS_OK;
79 }
80
SoftBusGattsAddCharacteristic(int srvcHandle,SoftBusBtUuid characUuid,int properties,int permissions)81 NO_SANITIZE("cfi") int SoftBusGattsAddCharacteristic(int srvcHandle, SoftBusBtUuid characUuid, int properties,
82 int permissions)
83 {
84 if ((characUuid.uuidLen == 0) || (characUuid.uuid == NULL)) {
85 return SOFTBUS_ERR;
86 }
87 if (CheckGattsStatus() != SOFTBUS_OK) {
88 return SOFTBUS_ERR;
89 }
90 BtUuid uuid = {
91 .uuid = characUuid.uuid,
92 .uuidLen = characUuid.uuidLen
93 };
94 if (BleGattsAddCharacteristic(g_halServerId, srvcHandle, uuid, properties, permissions) != SOFTBUS_OK) {
95 return SOFTBUS_ERR;
96 }
97 return SOFTBUS_OK;
98 }
99
SoftBusGattsAddDescriptor(int srvcHandle,SoftBusBtUuid descUuid,int permissions)100 NO_SANITIZE("cfi") int SoftBusGattsAddDescriptor(int srvcHandle, SoftBusBtUuid descUuid, int permissions)
101 {
102 if ((descUuid.uuidLen == 0) || (descUuid.uuid == NULL)) {
103 return SOFTBUS_ERR;
104 }
105 if (CheckGattsStatus() != SOFTBUS_OK) {
106 return SOFTBUS_ERR;
107 }
108 BtUuid uuid = {
109 .uuid = descUuid.uuid,
110 .uuidLen = descUuid.uuidLen
111 };
112 if (BleGattsAddDescriptor(g_halServerId, srvcHandle, uuid, permissions) != SOFTBUS_OK) {
113 return SOFTBUS_ERR;
114 }
115 return SOFTBUS_OK;
116 }
117
SoftBusGattsStartService(int srvcHandle)118 NO_SANITIZE("cfi") int SoftBusGattsStartService(int srvcHandle)
119 {
120 if (CheckGattsStatus() != SOFTBUS_OK) {
121 return SOFTBUS_ERR;
122 }
123 CLOGI("BLEINFOPRTINT:BleGattsStartService(%d, %d)", g_halServerId, srvcHandle);
124 if (BleGattsStartService(g_halServerId, srvcHandle) != SOFTBUS_OK) {
125 return SOFTBUS_ERR;
126 }
127 return SOFTBUS_OK;
128 }
129
SoftBusGattsStopService(int srvcHandle)130 NO_SANITIZE("cfi") int SoftBusGattsStopService(int srvcHandle)
131 {
132 if (CheckGattsStatus() != SOFTBUS_OK) {
133 return SOFTBUS_ERR;
134 }
135 CLOGI("BLEINFOPRTINT:SoftBusGattsStopService(%d, %d)", g_halServerId, srvcHandle);
136 if (BleGattsStopService(g_halServerId, srvcHandle) != SOFTBUS_OK) {
137 return SOFTBUS_ERR;
138 }
139 return SOFTBUS_OK;
140 }
141
SoftBusGattsDeleteService(int srvcHandle)142 NO_SANITIZE("cfi") int SoftBusGattsDeleteService(int srvcHandle)
143 {
144 if (CheckGattsStatus() != SOFTBUS_OK) {
145 return SOFTBUS_ERR;
146 }
147 if (BleGattsDeleteService(g_halServerId, srvcHandle) != SOFTBUS_OK) {
148 return SOFTBUS_ERR;
149 }
150 return SOFTBUS_OK;
151 }
152
SoftBusGattsConnect(int connId)153 int SoftBusGattsConnect(int connId)
154 {
155 CLOGD("SoftBusGattsConnect stub is called, return success");
156 return SOFTBUS_OK;
157 }
158
SoftBusGattsDisconnect(SoftBusBtAddr btAddr,int connId)159 NO_SANITIZE("cfi") int SoftBusGattsDisconnect(SoftBusBtAddr btAddr, int connId)
160 {
161 if (CheckGattsStatus() != SOFTBUS_OK) {
162 return SOFTBUS_ERR;
163 }
164 BdAddr addr;
165 if (memcpy_s(addr.addr, BT_ADDR_LEN, btAddr.addr, BT_ADDR_LEN) != EOK) {
166 CLOGE("SoftBusGattsDisconnect memcpy fail");
167 return SOFTBUS_ERR;
168 }
169 if (BleGattsDisconnect(g_halServerId, addr, connId) != SOFTBUS_OK) {
170 return SOFTBUS_ERR;
171 }
172 return SOFTBUS_OK;
173 }
174
SoftBusGattsSendResponse(SoftBusGattsResponse * param)175 NO_SANITIZE("cfi") int SoftBusGattsSendResponse(SoftBusGattsResponse *param)
176 {
177 if (CheckGattsStatus() != SOFTBUS_OK) {
178 return SOFTBUS_ERR;
179 }
180 GattsSendRspParam response = {
181 .connectId = param->connectId,
182 .status = param->status,
183 .attrHandle = param->transId,
184 .valueLen = param->valueLen,
185 .value = param->value
186 };
187 if (BleGattsSendResponse(g_halServerId, &response) != SOFTBUS_OK) {
188 return SOFTBUS_ERR;
189 }
190 return SOFTBUS_OK;
191 }
192
SoftBusGattsSendNotify(SoftBusGattsNotify * param)193 NO_SANITIZE("cfi") int SoftBusGattsSendNotify(SoftBusGattsNotify *param)
194 {
195 CLOGI("SoftBusGattsSendNotify enter");
196 if (CheckGattsStatus() != SOFTBUS_OK) {
197 return SOFTBUS_ERR;
198 }
199 GattsSendIndParam notify = {
200 .connectId = param->connectId,
201 .attrHandle = param->attrHandle,
202 .confirm = param->confirm,
203 .valueLen = param->valueLen,
204 .value = param->value
205 };
206 CLOGI("SoftBusGattsSendNotify call BleGattsSendIndication halconnId:%d attrHandle:%d confirm:%d",
207 notify.connectId, notify.attrHandle, notify.confirm);
208 if (BleGattsSendIndication(g_halServerId, ¬ify) != SOFTBUS_OK) {
209 CLOGE("SoftBusGattsSendNotify failed");
210 return SOFTBUS_ERR;
211 }
212 return SOFTBUS_OK;
213 }
214
BleRegisterServerCallback(int status,int serverId,BtUuid * appUuid)215 NO_SANITIZE("cfi") static void BleRegisterServerCallback(int status, int serverId, BtUuid *appUuid)
216 {
217 CLOGI("BleRegisterServerCallback status=%d severId=%d", status, serverId);
218 if ((appUuid == NULL) || (appUuid->uuid == NULL)) {
219 CLOGE("BleRegisterServerCallback appUuid is null");
220 return;
221 }
222
223 if (memcmp(appUuid->uuid, SOFTBUS_APP_UUID, appUuid->uuidLen) != 0) {
224 CLOGE("BleRegisterServerCallback unknown uuid");
225 return;
226 }
227
228 if (status != SOFTBUS_OK) {
229 CLOGE("BleRegisterServerCallback failed, status=%d", status);
230 g_halRegFlag = -1;
231 } else {
232 g_halRegFlag = 1;
233 g_halServerId = serverId;
234 CLOGI("BLEINFOPRTINT:BleRegisterServerCallback g_halServerId:%d)", g_halServerId);
235 }
236 }
237
BleConnectServerCallback(int connId,int serverId,const BdAddr * bdAddr)238 NO_SANITIZE("cfi") static void BleConnectServerCallback(int connId, int serverId, const BdAddr *bdAddr)
239 {
240 CLOGI("ConnectServerCallback is coming, connId=%d serverId=%d\n", connId, serverId);
241 if (serverId != g_halServerId) {
242 return;
243 }
244 g_gattsCallback->ConnectServerCallback(connId, (const SoftBusBtAddr*)bdAddr);
245 }
246
BleDisconnectServerCallback(int connId,int serverId,const BdAddr * bdAddr)247 NO_SANITIZE("cfi") static void BleDisconnectServerCallback(int connId, int serverId, const BdAddr *bdAddr)
248 {
249 CLOGI("DisconnectServerCallback is coming, connId=%d severId=%d", connId, serverId);
250 if (serverId != g_halServerId) {
251 return;
252 }
253 g_gattsCallback->DisconnectServerCallback(connId, (const SoftBusBtAddr*)bdAddr);
254 }
255
BleServiceAddCallback(int status,int serverId,BtUuid * uuid,int srvcHandle)256 NO_SANITIZE("cfi") static void BleServiceAddCallback(int status, int serverId, BtUuid *uuid, int srvcHandle)
257 {
258 (void)serverId;
259 CLOGI("ServiceAddCallback srvcHandle=%d\n", srvcHandle);
260 if (serverId != g_halServerId) {
261 return;
262 }
263 CLOGI("BLEINFOPRTINT:BleServiceAddCallback srvcHandle:%d)", srvcHandle);
264 g_gattsCallback->ServiceAddCallback(status, (SoftBusBtUuid *)uuid, srvcHandle);
265 }
266
BleIncludeServiceAddCallback(int status,int serverId,int srvcHandle,int includeSrvcHandle)267 NO_SANITIZE("cfi") static void BleIncludeServiceAddCallback(int status, int serverId, int srvcHandle,
268 int includeSrvcHandle)
269 {
270 (void)serverId;
271 (void)srvcHandle;
272 CLOGI("IncludeServiceAddCallback srvcHandle=%d,includeSrvcHandle=%d\n", srvcHandle, includeSrvcHandle);
273 }
274
BleCharacteristicAddCallback(int status,int serverId,BtUuid * uuid,int srvcHandle,int characteristicHandle)275 NO_SANITIZE("cfi") static void BleCharacteristicAddCallback(int status, int serverId, BtUuid *uuid, int srvcHandle,
276 int characteristicHandle)
277 {
278 CLOGI("CharacteristicAddCallback srvcHandle=%d,charHandle=%d\n", srvcHandle, characteristicHandle);
279 if (serverId != g_halServerId) {
280 CLOGE("bad server id");
281 return;
282 }
283 CLOGI("BLEINFOPRTINT:BleCharacteristicAddCallback characteristicHandle:%d)", characteristicHandle);
284 g_gattsCallback->CharacteristicAddCallback(status, (SoftBusBtUuid *)uuid, srvcHandle, characteristicHandle);
285 }
286
BleDescriptorAddCallback(int status,int serverId,BtUuid * uuid,int srvcHandle,int descriptorHandle)287 NO_SANITIZE("cfi") static void BleDescriptorAddCallback(int status, int serverId, BtUuid *uuid,
288 int srvcHandle, int descriptorHandle)
289 {
290 CLOGI("DescriptorAddCallback srvcHandle=%d,descriptorHandle=%d", srvcHandle, descriptorHandle);
291 if (serverId != g_halServerId) {
292 return;
293 }
294 CLOGI("BLEINFOPRTINT:BleDescriptorAddCallback descriptorHandle:%d)", descriptorHandle);
295 g_gattsCallback->DescriptorAddCallback(status, (SoftBusBtUuid *)uuid, srvcHandle, descriptorHandle);
296 }
297
BleServiceStartCallback(int status,int serverId,int srvcHandle)298 NO_SANITIZE("cfi") static void BleServiceStartCallback(int status, int serverId, int srvcHandle)
299 {
300 CLOGI("ServiceStartCallback serverId=%d,srvcHandle=%d\n", serverId, srvcHandle);
301 if (serverId != g_halServerId) {
302 return;
303 }
304 CLOGI("BLEINFOPRTINT:BleServiceStartCallback srvcHandle:%d)", srvcHandle);
305 g_gattsCallback->ServiceStartCallback(status, srvcHandle);
306 }
307
BleServiceStopCallback(int status,int serverId,int srvcHandle)308 NO_SANITIZE("cfi") static void BleServiceStopCallback(int status, int serverId, int srvcHandle)
309 {
310 CLOGI("ServiceStopCallback serverId=%d,srvcHandle=%d\n", serverId, srvcHandle);
311 if (serverId != g_halServerId) {
312 return;
313 }
314 g_gattsCallback->ServiceStopCallback(status, srvcHandle);
315 }
316
BleServiceDeleteCallback(int status,int serverId,int srvcHandle)317 NO_SANITIZE("cfi") static void BleServiceDeleteCallback(int status, int serverId, int srvcHandle)
318 {
319 CLOGI("ServiceDeleteCallback serverId=%d,srvcHandle=%d\n", serverId, srvcHandle);
320 if (serverId != g_halServerId) {
321 return;
322 }
323 g_gattsCallback->ServiceDeleteCallback(status, srvcHandle);
324 }
325
BleRequestReadCallback(BtReqReadCbPara readCbPara)326 NO_SANITIZE("cfi") static void BleRequestReadCallback(BtReqReadCbPara readCbPara)
327 {
328 CLOGI("RequestReadCallback transId=%d, attrHandle=%d\n", readCbPara.transId, readCbPara.attrHandle);
329 SoftBusGattReadRequest req = {
330 .connId = readCbPara.connId,
331 .transId = readCbPara.transId,
332 .btAddr = (SoftBusBtAddr *)readCbPara.bdAddr,
333 .attrHandle = readCbPara.attrHandle,
334 .offset = readCbPara.offset,
335 .isLong = readCbPara.isLong
336 };
337 g_gattsCallback->RequestReadCallback(req);
338 }
339
BleRequestWriteCallback(BtReqWriteCbPara writeCbPara)340 NO_SANITIZE("cfi") static void BleRequestWriteCallback(BtReqWriteCbPara writeCbPara)
341 {
342 CLOGI("RequestWriteCallback transId=%d, attrHandle=%d\n", writeCbPara.transId, writeCbPara.attrHandle);
343 SoftBusGattWriteRequest req = {
344 .connId = writeCbPara.connId,
345 .transId = writeCbPara.transId,
346 .btAddr = (SoftBusBtAddr *)writeCbPara.bdAddr,
347 .attrHandle = writeCbPara.attrHandle,
348 .offset = writeCbPara.offset,
349 .length = writeCbPara.length,
350 .needRsp = writeCbPara.needRsp,
351 .isPrep = writeCbPara.isPrep,
352 .value = writeCbPara.value
353 };
354 g_gattsCallback->RequestWriteCallback(req);
355 }
356
BleResponseConfirmationCallback(int status,int handle)357 NO_SANITIZE("cfi") static void BleResponseConfirmationCallback(int status, int handle)
358 {
359 CLOGI("ResponseConfirmationCallback status=%d, handle=%d\n", status, handle);
360 g_gattsCallback->ResponseConfirmationCallback(status, handle);
361 }
362
BleIndicationSentCallback(int connId,int status)363 NO_SANITIZE("cfi") static void BleIndicationSentCallback(int connId, int status)
364 {
365 CLOGI("IndicationSentCallback status=%d, connId=%d\n", status, connId);
366 g_gattsCallback->NotifySentCallback(connId, status);
367 }
368
BleMtuChangeCallback(int connId,int mtu)369 NO_SANITIZE("cfi") static void BleMtuChangeCallback(int connId, int mtu)
370 {
371 CLOGI("MtuChangeCallback connId=%d, mtu=%d\n", connId, mtu);
372 g_gattsCallback->MtuChangeCallback(connId, mtu);
373 }
374
GattsRegisterHalCallback(void)375 static int GattsRegisterHalCallback(void)
376 {
377 g_bleGattsHalCallback.registerServerCb = BleRegisterServerCallback;
378 g_bleGattsHalCallback.connectServerCb = BleConnectServerCallback;
379 g_bleGattsHalCallback.disconnectServerCb = BleDisconnectServerCallback;
380 g_bleGattsHalCallback.serviceAddCb = BleServiceAddCallback;
381 g_bleGattsHalCallback.includeServiceAddCb = BleIncludeServiceAddCallback;
382 g_bleGattsHalCallback.characteristicAddCb = BleCharacteristicAddCallback;
383 g_bleGattsHalCallback.descriptorAddCb = BleDescriptorAddCallback;
384 g_bleGattsHalCallback.serviceStartCb = BleServiceStartCallback;
385 g_bleGattsHalCallback.serviceStopCb = BleServiceStopCallback;
386 g_bleGattsHalCallback.serviceDeleteCb = BleServiceDeleteCallback;
387 g_bleGattsHalCallback.requestReadCb = BleRequestReadCallback;
388 g_bleGattsHalCallback.requestWriteCb = BleRequestWriteCallback;
389 g_bleGattsHalCallback.responseConfirmationCb = BleResponseConfirmationCallback;
390 g_bleGattsHalCallback.indicationSentCb = BleIndicationSentCallback;
391 g_bleGattsHalCallback.mtuChangeCb = BleMtuChangeCallback;
392 return BleGattsRegisterCallbacks(&g_bleGattsHalCallback);
393 }
394
SoftBusRegisterGattsCallbacks(SoftBusGattsCallback * callback)395 NO_SANITIZE("cfi") int SoftBusRegisterGattsCallbacks(SoftBusGattsCallback *callback)
396 {
397 if (callback == NULL) {
398 CLOGE("SoftBusRegisterGattsCallbacks fail:nullptr");
399 return SOFTBUS_BLECONNECTION_REG_GATTS_CALLBACK_FAIL;
400 }
401 if (g_gattsCallback != NULL) {
402 CLOGW("SoftBusRegisterGattsCallbacks register again");
403 } else {
404 g_gattsCallback = callback;
405 }
406 int ret = GattsRegisterHalCallback();
407 if (ret != SOFTBUS_OK) {
408 CLOGE("SoftBusRegisterGattsCallbacks GattsRegisterCallbacks failed:%d", ret);
409 return SOFTBUS_BLECONNECTION_REG_GATTS_CALLBACK_FAIL;
410 }
411 if (g_halRegFlag == -1) {
412 BtUuid uuid;
413 uuid.uuid = (char *)SOFTBUS_APP_UUID;
414 uuid.uuidLen = sizeof(SOFTBUS_APP_UUID);
415 g_halRegFlag = 0;
416 ret = BleGattsRegister(uuid);
417 if (ret != SOFTBUS_OK) {
418 g_halRegFlag = -1;
419 CLOGE("BleGattsRegister failed%d", ret);
420 return SOFTBUS_BLECONNECTION_REG_GATTS_CALLBACK_FAIL;
421 }
422 }
423 return SOFTBUS_OK;
424 }
425
SoftBusUnRegisterGattsCallbacks(void)426 NO_SANITIZE("cfi") void SoftBusUnRegisterGattsCallbacks(void)
427 {
428 if (g_gattsCallback == NULL) {
429 CLOGI("no need to unregist gatts callback.");
430 return;
431 }
432 if (g_halRegFlag == -1) {
433 CLOGI("no need to unregist gatt server.");
434 return;
435 }
436 if (BleGattsUnRegister(g_halServerId) != SOFTBUS_OK) {
437 CLOGE("BleGattsUnRegister error.");
438 return;
439 }
440 g_halServerId = -1;
441 g_halRegFlag = -1;
442 }
443