1 /*
2 * Copyright (c) 2024 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 "bluetooth_ble_impl.h"
17
18 #include "bluetooth_ble_central_manager.h"
19 #include "bluetooth_ble_common.h"
20 #include "bluetooth_ble_ffi.h"
21 #include "bluetooth_errorcode.h"
22 #include "bluetooth_log.h"
23 #include "cj_lambda.h"
24 #include "napi_bluetooth_utils.h"
25
26 namespace OHOS {
27 namespace CJSystemapi {
28 namespace CJBluetoothBle {
29 using Bluetooth::BleAdvertiser;
30 using Bluetooth::BleAdvertiserData;
31 using Bluetooth::BleScanFilter;
32 using Bluetooth::BleScanSettings;
33 using Bluetooth::IsValidAddress;
34 using Bluetooth::IsValidUuid;
35 using Bluetooth::ParcelUuid;
36 using OHOS::FFI::FFIData;
37
38 using Bluetooth::NapiAdvManufactureData;
39 using Bluetooth::NapiAdvServiceData;
40
41 using Bluetooth::BT_ERR_BLE_SCAN_ALREADY_STARTED;
42 using Bluetooth::BT_ERR_INTERNAL_ERROR;
43 using Bluetooth::BT_ERR_INVALID_PARAM;
44 using Bluetooth::BT_NO_ERROR;
45
46 namespace {
47 using Bluetooth::BleCentralManager;
48
BleAdvertiserGetInstance(void)49 std::shared_ptr<BleAdvertiser> BleAdvertiserGetInstance(void)
50 {
51 static auto instance = BleAdvertiser::CreateInstance();
52 return instance;
53 }
54
BleCentralManagerGetInstance(void)55 BleCentralManager *BleCentralManagerGetInstance(void)
56 {
57 static BleCentralManager instance(FfiBluetoothBleCentralManagerCallback::GetInstance());
58 return &instance;
59 }
60 } // namespace
61
CreateGattServer(FfiGattServer * & ffiGattServer)62 int32_t BleImpl::CreateGattServer(FfiGattServer *&ffiGattServer)
63 {
64 ffiGattServer = FFIData::Create<FfiGattServer>();
65 if (ffiGattServer == nullptr) {
66 return BT_ERR_INTERNAL_ERROR;
67 }
68 return BT_NO_ERROR;
69 }
70
CreateGattClientDevice(std::string deviceId,FfiClientDevice * & ffiClientDevice)71 int32_t BleImpl::CreateGattClientDevice(std::string deviceId, FfiClientDevice *&ffiClientDevice)
72 {
73 if (!IsValidAddress(deviceId)) {
74 HILOGE("Invalid deviceId: %{public}s", deviceId.c_str());
75 return BT_ERR_INVALID_PARAM;
76 }
77 ffiClientDevice = FFIData::Create<FfiClientDevice>(deviceId);
78 return BT_NO_ERROR;
79 }
80
GetConnectedBleDevices(CArrString & res)81 int32_t BleImpl::GetConnectedBleDevices(CArrString &res)
82 {
83 std::lock_guard<std::mutex> lock(FfiGattServer::deviceListMutex_);
84 std::vector<std::string> devicesList = FfiGattServer::deviceList_;
85 res = Convert2CArrString(devicesList);
86 return BT_NO_ERROR;
87 }
88
ParseScanFilterDeviceIdParameters(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)89 static void ParseScanFilterDeviceIdParameters(int32_t &status, NativeScanFilter &scanFilter,
90 BleScanFilter &bleScanFilter)
91 {
92 if (scanFilter.deviceId != nullptr) {
93 std::string deviceId = std::string(scanFilter.deviceId);
94 if (!IsValidAddress(deviceId)) {
95 HILOGE("Invalid deviceId: %{public}s", deviceId.c_str());
96 status = BT_ERR_INVALID_PARAM;
97 }
98 bleScanFilter.SetDeviceId(deviceId);
99 }
100 }
101
ParseScanFilterLocalNameParameters(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)102 static void ParseScanFilterLocalNameParameters(int32_t &status, NativeScanFilter &scanFilter,
103 BleScanFilter &bleScanFilter)
104 {
105 if (scanFilter.name != nullptr) {
106 std::string name = std::string(scanFilter.name);
107 if (name.empty()) {
108 HILOGE("name is empty");
109 status = BT_ERR_INVALID_PARAM;
110 }
111 bleScanFilter.SetName(name);
112 }
113 }
114
ParseUuidParams(char * name,UUID & outUuid)115 static int32_t ParseUuidParams(char *name, UUID &outUuid)
116 {
117 std::string uuid = std::string(name);
118 if (!IsValidUuid(uuid)) {
119 HILOGE("match the UUID faild.");
120 return BT_ERR_INVALID_PARAM;
121 }
122 outUuid = ParcelUuid::FromString(uuid);
123 return BT_NO_ERROR;
124 }
125
ParseScanFilterServiceUuidParameters(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)126 static void ParseScanFilterServiceUuidParameters(int32_t &status, NativeScanFilter &scanFilter,
127 BleScanFilter &bleScanFilter)
128 {
129 if (scanFilter.serviceUuid != nullptr) {
130 UUID uuid{};
131 status = ParseUuidParams(scanFilter.serviceUuid, uuid);
132 if (status != BT_NO_ERROR) {
133 return;
134 }
135 bleScanFilter.SetServiceUuid(uuid);
136 }
137
138 if (scanFilter.serviceUuidMask != nullptr) {
139 UUID uuidMask{};
140 status = ParseUuidParams(scanFilter.serviceUuidMask, uuidMask);
141 if (status != BT_NO_ERROR) {
142 return;
143 }
144 bleScanFilter.SetServiceUuidMask(uuidMask);
145 }
146 }
147
ParseScanFilterSolicitationUuidParameters(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)148 static void ParseScanFilterSolicitationUuidParameters(int32_t &status, NativeScanFilter &scanFilter,
149 BleScanFilter &bleScanFilter)
150 {
151 if (scanFilter.serviceSolicitationUuid != nullptr) {
152 UUID uuid{};
153 status = ParseUuidParams(scanFilter.serviceSolicitationUuid, uuid);
154 if (status != BT_NO_ERROR) {
155 return;
156 }
157 bleScanFilter.SetServiceSolicitationUuid(uuid);
158 }
159
160 if (scanFilter.serviceSolicitationUuidMask != nullptr) {
161 UUID uuidMask{};
162 status = ParseUuidParams(scanFilter.serviceSolicitationUuidMask, uuidMask);
163 if (status != BT_NO_ERROR) {
164 return;
165 }
166 bleScanFilter.SetServiceSolicitationUuidMask(uuidMask);
167 }
168 }
169
ParseScanFilterServiceDataParameters(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)170 static void ParseScanFilterServiceDataParameters(int32_t &status, NativeScanFilter &scanFilter,
171 BleScanFilter &bleScanFilter)
172 {
173 std::vector<uint8_t> data{};
174 if (scanFilter.serviceData.head != nullptr) {
175 bleScanFilter.SetServiceData(std::move(data));
176 }
177
178 std::vector<uint8_t> dataMask{};
179 if (scanFilter.serviceDataMask.head != nullptr) {
180 bleScanFilter.SetServiceDataMask(std::move(dataMask));
181 }
182 }
183
ParseScanFilterManufactureDataParameters(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)184 static void ParseScanFilterManufactureDataParameters(int32_t &status, NativeScanFilter &scanFilter,
185 BleScanFilter &bleScanFilter)
186 {
187 if (scanFilter.manufactureId != 0) {
188 bleScanFilter.SetManufacturerId(scanFilter.manufactureId);
189 HILOGI("Scan filter manufacturerId is %{public}#x", scanFilter.manufactureId);
190 }
191
192 std::vector<uint8_t> data{};
193 if (scanFilter.manufactureData.head != nullptr) {
194 for (int64_t i = 0; i < scanFilter.manufactureData.size; i++) {
195 data.push_back(scanFilter.manufactureData.head[i]);
196 }
197 bleScanFilter.SetManufactureData(std::move(data));
198 }
199
200 std::vector<uint8_t> dataMask{};
201 if (scanFilter.manufactureDataMask.head != nullptr) {
202 for (int64_t i = 0; i < scanFilter.manufactureDataMask.size; i++) {
203 dataMask.push_back(scanFilter.manufactureDataMask.head[i]);
204 }
205 bleScanFilter.SetManufactureDataMask(std::move(dataMask));
206 }
207 }
208
ParseScanFilter(int32_t & status,NativeScanFilter & scanFilter,BleScanFilter & bleScanFilter)209 static void ParseScanFilter(int32_t &status, NativeScanFilter &scanFilter, BleScanFilter &bleScanFilter)
210 {
211 ParseScanFilterDeviceIdParameters(status, scanFilter, bleScanFilter);
212 ParseScanFilterLocalNameParameters(status, scanFilter, bleScanFilter);
213 ParseScanFilterServiceUuidParameters(status, scanFilter, bleScanFilter);
214 ParseScanFilterSolicitationUuidParameters(status, scanFilter, bleScanFilter);
215 ParseScanFilterServiceDataParameters(status, scanFilter, bleScanFilter);
216 ParseScanFilterManufactureDataParameters(status, scanFilter, bleScanFilter);
217 }
218
CheckBleScanParams(CArrNativeScanFilter filters,NativeScanOptions * scanOptions,std::vector<BleScanFilter> & outScanfilters,BleScanSettings & outSettinngs)219 static int32_t CheckBleScanParams(CArrNativeScanFilter filters, NativeScanOptions *scanOptions,
220 std::vector<BleScanFilter> &outScanfilters, BleScanSettings &outSettinngs)
221 {
222 std::vector<BleScanFilter> scanfilters;
223 uint32_t length = static_cast<uint32_t>(filters.size);
224 int32_t status = BT_NO_ERROR;
225 for (uint32_t i = 0; i < length; i++) {
226 BleScanFilter bleScanFilter;
227 ParseScanFilter(status, filters.head[i], bleScanFilter);
228 scanfilters.push_back(bleScanFilter);
229 }
230 if (status != BT_NO_ERROR) {
231 return status;
232 }
233
234 if (scanOptions != nullptr) {
235 outSettinngs.SetReportDelay(scanOptions->interval);
236 outSettinngs.SetScanMode(scanOptions->dutyMode);
237 outSettinngs.SetPhy(scanOptions->phyType);
238 }
239
240 outScanfilters = std::move(scanfilters);
241 return BT_NO_ERROR;
242 }
243
StartBleScan(CArrNativeScanFilter filters,NativeScanOptions * options)244 int32_t BleImpl::StartBleScan(CArrNativeScanFilter filters, NativeScanOptions *options)
245 {
246 std::vector<BleScanFilter> scanfilters;
247 BleScanSettings settings;
248
249 int status = CheckBleScanParams(filters, options, scanfilters, settings);
250 if (status != BT_NO_ERROR) {
251 return status;
252 }
253
254 int ret = BleCentralManagerGetInstance()->StartScan(settings, scanfilters);
255 if (ret != BT_NO_ERROR && ret != BT_ERR_BLE_SCAN_ALREADY_STARTED) {
256 return ret;
257 }
258 return BT_NO_ERROR;
259 }
260
StopBleScan()261 int32_t BleImpl::StopBleScan()
262 {
263 return BleCentralManagerGetInstance()->StopScan();
264 }
265
ParseAdvertisingSettingsParameters(int32_t * errCode,NativeAdvertiseSetting & setting,BleAdvertiserSettings & outSettings)266 static void ParseAdvertisingSettingsParameters(int32_t *errCode, NativeAdvertiseSetting &setting,
267 BleAdvertiserSettings &outSettings)
268 {
269 uint32_t interval = setting.interval;
270 const uint32_t minInterval = 32;
271 const uint32_t maxInterval = 16384;
272 if (interval < minInterval || interval > maxInterval) {
273 HILOGE("Invalid interval: %{public}d", interval);
274 *errCode = BT_ERR_INVALID_PARAM;
275 return;
276 }
277 HILOGI("interval: %{public}u", interval);
278 outSettings.SetInterval(interval);
279
280 int32_t txPower = setting.txPower;
281 const int32_t minTxPower = -127;
282 const int32_t maxTxPower = 1;
283 if (txPower < minTxPower || txPower > maxTxPower) {
284 HILOGE("Invalid tx power: %{public}d", txPower);
285 *errCode = BT_ERR_INVALID_PARAM;
286 return;
287 }
288 HILOGI("txPower is %{public}d", txPower);
289 outSettings.SetTxPower(txPower);
290
291 bool connectable = setting.connectable;
292 HILOGI("connectable: %{public}d", connectable);
293 outSettings.SetConnectable(connectable);
294
295 return;
296 }
297
ParseServiceUuidParameters(int32_t * errCode,NativeAdvertiseData advData,BleAdvertiserData & outData)298 static void ParseServiceUuidParameters(int32_t *errCode, NativeAdvertiseData advData, BleAdvertiserData &outData)
299 {
300 for (int64_t i = 0; i < advData.serviceUuids.size; ++i) {
301 UUID uuid{};
302 *errCode = ParseUuidParams(advData.serviceUuids.head[i], uuid);
303 if (*errCode != BT_NO_ERROR) {
304 return;
305 }
306 outData.AddServiceUuid(uuid);
307 HILOGI("Service Uuid = %{public}s", uuid.ToString().c_str());
308 }
309 return;
310 }
311
ParseManufactureDataParameters(int32_t * errCode,NativeAdvertiseData advData,BleAdvertiserData & outData)312 static void ParseManufactureDataParameters(int32_t *errCode, NativeAdvertiseData advData, BleAdvertiserData &outData)
313 {
314 CArrNativeManufactureData parameter = advData.manufactureData;
315 for (int64_t i = 0; i < parameter.size; ++i) {
316 NativeManufactureData manufactureData = parameter.head[i];
317 CArrUI8 manufactureValue = manufactureData.manufactureValue;
318 std::string value(reinterpret_cast<char *>(manufactureValue.head), manufactureValue.size);
319 outData.AddManufacturerData(manufactureData.manufactureId, value);
320 }
321 return;
322 }
323
ParseServiceDataParameters(int32_t * errCode,NativeAdvertiseData advData,BleAdvertiserData & outData)324 static void ParseServiceDataParameters(int32_t *errCode, NativeAdvertiseData advData, BleAdvertiserData &outData)
325 {
326 CArrNativeServiceData data = advData.serviceData;
327 for (int64_t i = 0; i < data.size; ++i) {
328 NativeServiceData serviceData = data.head[i];
329 std::string value(reinterpret_cast<char *>(serviceData.serviceValue.head), serviceData.serviceValue.size);
330 outData.AddServiceData(ParcelUuid::FromString(std::string(serviceData.serviceUuid)), value);
331 }
332 return;
333 }
334
ParseAdvertisDataParameters(int32_t * errCode,NativeAdvertiseData advData,BleAdvertiserData & outData)335 static void ParseAdvertisDataParameters(int32_t *errCode, NativeAdvertiseData advData, BleAdvertiserData &outData)
336 {
337 ParseServiceUuidParameters(errCode, advData, outData);
338 ParseManufactureDataParameters(errCode, advData, outData);
339 ParseServiceDataParameters(errCode, advData, outData);
340 bool includeDeviceName = advData.includeDeviceName;
341 HILOGI("includeDeviceName: %{public}d", includeDeviceName);
342 outData.SetIncludeDeviceName(includeDeviceName);
343 return;
344 }
345
StartAdvertising(NativeAdvertiseSetting setting,NativeAdvertiseData advData,NativeAdvertiseData * advResponse)346 int32_t BleImpl::StartAdvertising(NativeAdvertiseSetting setting, NativeAdvertiseData advData,
347 NativeAdvertiseData *advResponse)
348 {
349 std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
350 BleAdvertiserSettings nativeSettings;
351 BleAdvertiserData nativeAdvData;
352 BleAdvertiserData nativeRspData;
353 int32_t errCode = BT_NO_ERROR;
354
355 ParseAdvertisingSettingsParameters(&errCode, setting, nativeSettings);
356 ParseAdvertisDataParameters(&errCode, advData, nativeAdvData);
357 if (advResponse != nullptr) {
358 ParseAdvertisDataParameters(&errCode, *advResponse, nativeRspData);
359 }
360
361 if (errCode != BT_NO_ERROR) {
362 return errCode;
363 }
364 return bleAdvertiser->StartAdvertising(nativeSettings, nativeAdvData, nativeRspData, 0,
365 FfiBluetoothBleAdvertiseCallback::GetInstance());
366 }
367
StopAdvertising()368 int32_t BleImpl::StopAdvertising()
369 {
370 std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
371 if (bleAdvertiser == nullptr) {
372 HILOGE("bleAdvertiser is nullptr");
373 return BT_ERR_INTERNAL_ERROR;
374 }
375 return bleAdvertiser->StopAdvertising(FfiBluetoothBleAdvertiseCallback::GetInstance());
376 }
377
IsValidAdvertiserDuration(uint32_t duration)378 static bool IsValidAdvertiserDuration(uint32_t duration)
379 {
380 const uint32_t MIN_DURATION = 0;
381 const uint32_t MAX_DURATION = 65535;
382 if (duration < MIN_DURATION || duration > MAX_DURATION) {
383 return false;
384 }
385 return true;
386 }
387
StartAdvertising(NativeAdvertisingParams advertisingParams,int32_t & id)388 int32_t BleImpl::StartAdvertising(NativeAdvertisingParams advertisingParams, int32_t &id)
389 {
390 std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
391 BleAdvertiserSettings nativeSettings;
392 BleAdvertiserData nativeAdvData;
393 BleAdvertiserData nativeRspData;
394
395 int32_t errCode = BT_NO_ERROR;
396 ParseAdvertisingSettingsParameters(&errCode, advertisingParams.advertisingSettings, nativeSettings);
397 ParseAdvertisDataParameters(&errCode, advertisingParams.advertisingData, nativeAdvData);
398 ParseAdvertisDataParameters(&errCode, advertisingParams.advertisingResponse, nativeRspData);
399 uint16_t duration = advertisingParams.duration;
400 if (!IsValidAdvertiserDuration(duration)) {
401 HILOGE("Invalid duration: %{public}d", duration);
402 return BT_ERR_INVALID_PARAM;
403 }
404 HILOGI("duration: %{public}u", duration);
405 errCode = bleAdvertiser->StartAdvertising(nativeSettings, nativeAdvData, nativeRspData, duration,
406 FfiBluetoothBleAdvertiseCallback::GetInstance());
407 if (errCode != BT_NO_ERROR) {
408 return errCode;
409 }
410 id = FfiBluetoothBleAdvertiseCallback::GetInstance()->GetAdvHandleEvent();
411 if (id < 0) {
412 return BT_ERR_INTERNAL_ERROR;
413 }
414 return BT_NO_ERROR;
415 }
416
EnableAdvertising(NativeAdvertisingEnableParams advertisingEnableParams)417 int32_t BleImpl::EnableAdvertising(NativeAdvertisingEnableParams advertisingEnableParams)
418 {
419 uint32_t advHandle = advertisingEnableParams.advertisingId;
420 uint16_t duration = advertisingEnableParams.duration;
421
422 std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
423 if (bleAdvertiser == nullptr) {
424 HILOGE("bleAdvertiser is nullptr");
425 return BT_ERR_INTERNAL_ERROR;
426 }
427 return bleAdvertiser->EnableAdvertising(advHandle, duration, FfiBluetoothBleAdvertiseCallback::GetInstance());
428 }
429
DisableAdvertising(NativeAdvertisingDisableParams advertisingDisableParams)430 int32_t BleImpl::DisableAdvertising(NativeAdvertisingDisableParams advertisingDisableParams)
431 {
432 uint32_t advHandle = advertisingDisableParams.advertisingId;
433
434 std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
435 if (bleAdvertiser == nullptr) {
436 HILOGE("bleAdvertiser is nullptr");
437 return BT_ERR_INTERNAL_ERROR;
438 }
439 return bleAdvertiser->DisableAdvertising(advHandle, FfiBluetoothBleAdvertiseCallback::GetInstance());
440 }
441
StopAdvertising(uint32_t advertisingId)442 int32_t BleImpl::StopAdvertising(uint32_t advertisingId)
443 {
444 std::shared_ptr<BleAdvertiser> bleAdvertiser = BleAdvertiserGetInstance();
445 if (bleAdvertiser == nullptr) {
446 HILOGE("bleAdvertiser is nullptr");
447 return BT_ERR_INTERNAL_ERROR;
448 }
449 uint32_t advHandle = advertisingId;
450 if (advHandle != bleAdvertiser->GetAdvHandle(FfiBluetoothBleAdvertiseCallback::GetInstance())) {
451 HILOGE("Invalid advHandle: %{public}d", advHandle);
452 return BT_ERR_INVALID_PARAM;
453 }
454 bleAdvertiser->StopAdvertising(FfiBluetoothBleAdvertiseCallback::GetInstance());
455 return BT_NO_ERROR;
456 }
457
RegisterBleObserver(int32_t callbackType,void (* callback)())458 int32_t BleImpl::RegisterBleObserver(int32_t callbackType, void (*callback)())
459 {
460 if (callbackType == REGISTER_BLE_ADVERTISING_STATE_INFO_TYPE) {
461 auto callbackFunc = CJLambda::Create(reinterpret_cast<void (*)(CAdvertisingStateChangeInfo)>(callback));
462 FfiBluetoothBleAdvertiseCallback::GetInstance()->RegisterAdvertisingStateChangeFunc(callbackFunc);
463 } else if (callbackType == REGISTER_BLE_FIND_DEVICE_TYPE) {
464 auto callbackFunc = CJLambda::Create(reinterpret_cast<void (*)(CArrScanResult)>(callback));
465 FfiBluetoothBleCentralManagerCallback::GetInstance().RegisterBLEDeviceFindFunc(callbackFunc);
466 } else {
467 HILOGE("Unsupported callback type");
468 return BT_ERR_INVALID_PARAM;
469 }
470 return BT_NO_ERROR;
471 }
472 } // namespace CJBluetoothBle
473 } // namespace CJSystemapi
474 } // namespace OHOS