1 /*
2 * Copyright (C) 2023 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 "napi_bluetooth_connection.h"
17
18 #include <set>
19
20 #include "napi_bluetooth_connection_observer.h"
21 #include "napi_bluetooth_remote_device_observer.h"
22 #include "bluetooth_log.h"
23 #include "bluetooth_errorcode.h"
24 #include "napi_bluetooth_error.h"
25 #include "napi_async_work.h"
26 #include "napi_bluetooth_utils.h"
27 #include "parser/napi_parser_utils.h"
28
29 namespace OHOS {
30 namespace Bluetooth {
31 NapiBluetoothConnectionObserver g_connectionObserver;
32 std::shared_ptr<NapiBluetoothRemoteDeviceObserver> g_remoteDeviceObserver;
33 std::mutex deviceMutex;
34 std::vector<std::shared_ptr<BluetoothRemoteDevice>> g_DiscoveryDevices;
35 std::set<std::string> g_supportRegisterFunc = {
36 REGISTER_DEVICE_FIND_TYPE, REGISTER_PIN_REQUEST_TYPE, REGISTER_BOND_STATE_TYPE};
37
38 std::map<std::string, std::function<napi_value(napi_env env)>> g_callbackDefaultValue = {
39 {REGISTER_DEVICE_FIND_TYPE,
__anon23a4181e0102() 40 [](napi_env env) -> napi_value {
41 napi_value result = 0;
42 napi_value value = 0;
43 napi_create_array(env, &result);
44 napi_create_string_utf8(env, INVALID_DEVICE_ID.c_str(), NAPI_AUTO_LENGTH, &value);
45 napi_set_element(env, result, 0, value);
46 return result;
47 }},
48 {REGISTER_PIN_REQUEST_TYPE,
__anon23a4181e0202() 49 [](napi_env env) -> napi_value {
50 napi_value result = 0;
51 napi_value deviceId = nullptr;
52 napi_value pinCode = nullptr;
53 napi_create_object(env, &result);
54 napi_create_string_utf8(env, INVALID_DEVICE_ID.c_str(), NAPI_AUTO_LENGTH, &deviceId);
55 napi_set_named_property(env, result, "deviceId", deviceId);
56 napi_create_string_utf8(env, INVALID_PIN_CODE.c_str(), NAPI_AUTO_LENGTH, &pinCode);
57 napi_set_named_property(env, result, "pinCode", pinCode);
58 return result;
59 }},
__anon23a4181e0302() 60 {REGISTER_BOND_STATE_TYPE, [](napi_env env) -> napi_value {
61 napi_value result = 0;
62 napi_value deviceId = nullptr;
63 napi_value state = nullptr;
64 napi_create_object(env, &result);
65 napi_create_string_utf8(env, INVALID_DEVICE_ID.c_str(), NAPI_AUTO_LENGTH, &deviceId);
66 napi_set_named_property(env, result, "deviceId", deviceId);
67 napi_create_int32(env, static_cast<int32_t>(BondState::BOND_STATE_INVALID), &state);
68 napi_set_named_property(env, result, "state", state);
69 return result;
70 }}};
71
DefineConnectionFunctions(napi_env env,napi_value exports)72 napi_value DefineConnectionFunctions(napi_env env, napi_value exports)
73 {
74 HILOGI("start");
75 RegisterObserverToHost();
76 ConnectionPropertyValueInit(env, exports);
77 napi_property_descriptor desc[] = {
78 DECLARE_NAPI_FUNCTION("getBtConnectionState", GetBtConnectionState),
79 #ifdef BLUETOOTH_API_SINCE_10
80 DECLARE_NAPI_FUNCTION("pairDevice", PairDeviceAsync),
81 DECLARE_NAPI_FUNCTION("cancelPairedDevice", CancelPairedDeviceAsync),
82 #else
83 DECLARE_NAPI_FUNCTION("pairDevice", PairDevice),
84 DECLARE_NAPI_FUNCTION("cancelPairedDevice", CancelPairedDevice),
85 #endif
86 DECLARE_NAPI_FUNCTION("getRemoteDeviceName", GetRemoteDeviceName),
87 DECLARE_NAPI_FUNCTION("getRemoteDeviceClass", GetRemoteDeviceClass),
88 DECLARE_NAPI_FUNCTION("getLocalName", GetLocalName),
89 DECLARE_NAPI_FUNCTION("getPairedDevices", GetPairedDevices),
90 DECLARE_NAPI_FUNCTION("getProfileConnState", GetProfileConnectionState),
91 DECLARE_NAPI_FUNCTION("getProfileConnectionState", GetProfileConnectionState),
92 DECLARE_NAPI_FUNCTION("setDevicePairingConfirmation", SetDevicePairingConfirmation),
93 DECLARE_NAPI_FUNCTION("setLocalName", SetLocalName),
94 DECLARE_NAPI_FUNCTION("setBluetoothScanMode", SetBluetoothScanMode),
95 DECLARE_NAPI_FUNCTION("getBluetoothScanMode", GetBluetoothScanMode),
96 DECLARE_NAPI_FUNCTION("startBluetoothDiscovery", StartBluetoothDiscovery),
97 DECLARE_NAPI_FUNCTION("stopBluetoothDiscovery", StopBluetoothDiscovery),
98 #ifdef BLUETOOTH_API_SINCE_10
99 DECLARE_NAPI_FUNCTION("setDevicePinCode", SetDevicePinCode),
100 DECLARE_NAPI_FUNCTION("cancelPairingDevice", CancelPairingDevice),
101 DECLARE_NAPI_FUNCTION("pairCredibleDevice", PairCredibleDevice),
102 DECLARE_NAPI_FUNCTION("getLocalProfileUuids", GetLocalProfileUuids),
103 DECLARE_NAPI_FUNCTION("getRemoteProfileUuids", GetRemoteProfileUuids),
104 DECLARE_NAPI_FUNCTION("on", RegisterConnectionObserver),
105 DECLARE_NAPI_FUNCTION("off", DeRegisterConnectionObserver),
106 #endif
107 };
108
109 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
110 return exports;
111 }
112
CheckRegisterObserver(napi_env env,napi_callback_info info)113 napi_status CheckRegisterObserver(napi_env env, napi_callback_info info)
114 {
115 size_t argc = ARGS_SIZE_TWO;
116 napi_value argv[ARGS_SIZE_TWO] = {0};
117 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
118 HILOGI("argc: %{public}zu", argc);
119 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO, "Requires 2 arguments.", napi_invalid_arg);
120
121 std::string callbackName;
122 bool ok = ParseString(env, callbackName, argv[PARAM0]);
123 if (!ok) {
124 return napi_invalid_arg;
125 }
126 if (!g_supportRegisterFunc.count(callbackName)) {
127 HILOGE("not support %{public}s.", callbackName.c_str());
128 return napi_invalid_arg;
129 }
130 NAPI_BT_CALL_RETURN(NapiIsFunction(env, argv[PARAM1]));
131
132 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = std::make_shared<BluetoothCallbackInfo>();
133 NAPI_BT_CALL_RETURN(napi_create_reference(env, argv[PARAM1], 1, &callbackInfo->callback_));
134 callbackInfo->env_ = env;
135 if (callbackName == REGISTER_BOND_STATE_TYPE) {
136 g_remoteDeviceObserver->RegisterCallback(callbackName, callbackInfo);
137 } else {
138 g_connectionObserver.RegisterCallback(callbackName, callbackInfo);
139 }
140 return napi_ok;
141 }
142
CheckDeRegisterObserver(napi_env env,napi_callback_info info)143 napi_status CheckDeRegisterObserver(napi_env env, napi_callback_info info)
144 {
145 size_t argc = ARGS_SIZE_TWO;
146 napi_value argv[ARGS_SIZE_TWO] = {0};
147 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
148 NAPI_BT_RETURN_IF(argc < ARGS_SIZE_ONE, "Requires 1 arguments at least.", napi_invalid_arg);
149
150 std::string callbackName;
151 bool ok = ParseString(env, callbackName, argv[PARAM0]);
152 if (!ok) {
153 return napi_invalid_arg;
154 }
155
156 if (!g_supportRegisterFunc.count(callbackName)) {
157 HILOGE("not support %{public}s.", callbackName.c_str());
158 return napi_invalid_arg;
159 }
160
161 if (argc == ARGS_SIZE_ONE) {
162 } else if (argc == ARGS_SIZE_TWO) {
163 NAPI_BT_CALL_RETURN(NapiIsFunction(env, argv[PARAM1]));
164 std::shared_ptr<BluetoothCallbackInfo> callbackInfo = std::make_shared<BluetoothCallbackInfo>();
165 NAPI_BT_CALL_RETURN(napi_create_reference(env, argv[PARAM1], 1, &callbackInfo->callback_));
166 callbackInfo->env_ = env;
167
168 napi_value callback = 0;
169 napi_value undefined = 0;
170 napi_value callResult = 0;
171 napi_get_undefined(callbackInfo->env_, &undefined);
172
173 napi_value result = g_callbackDefaultValue[callbackName](env);
174 napi_get_reference_value(callbackInfo->env_, callbackInfo->callback_, &callback);
175 napi_call_function(callbackInfo->env_, undefined, callback, ARGS_SIZE_ONE, &result, &callResult);
176 } else {
177 return napi_invalid_arg;
178 }
179
180 if (callbackName == REGISTER_BOND_STATE_TYPE) {
181 g_remoteDeviceObserver->DeRegisterCallback(callbackName);
182 } else {
183 g_connectionObserver.DeRegisterCallback(callbackName);
184 }
185 return napi_ok;
186 }
187
RegisterConnectionObserver(napi_env env,napi_callback_info info)188 napi_value RegisterConnectionObserver(napi_env env, napi_callback_info info)
189 {
190 HILOGI("enter");
191 auto status = CheckRegisterObserver(env, info);
192 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
193
194 napi_value ret = nullptr;
195 napi_get_undefined(env, &ret);
196 return ret;
197 }
198
DeRegisterConnectionObserver(napi_env env,napi_callback_info info)199 napi_value DeRegisterConnectionObserver(napi_env env, napi_callback_info info)
200 {
201 HILOGI("enter");
202 auto status = CheckDeRegisterObserver(env, info);
203 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
204
205 napi_value ret = nullptr;
206 napi_get_undefined(env, &ret);
207 return ret;
208 }
209
GetBtConnectionState(napi_env env,napi_callback_info info)210 napi_value GetBtConnectionState(napi_env env, napi_callback_info info)
211 {
212 HILOGI("start");
213 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
214 int state = static_cast<int>(BTConnectState::DISCONNECTED);
215 int32_t err = host->GetBtConnectionState(state);
216 HILOGI("start state %{public}d", state);
217 napi_value result = nullptr;
218 napi_create_int32(env, GetProfileConnectionState(state), &result);
219 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
220 HILOGI("end");
221 return result;
222 }
223
PairDevice(napi_env env,napi_callback_info info)224 napi_value PairDevice(napi_env env, napi_callback_info info)
225 {
226 HILOGI("start");
227 std::string remoteAddr = INVALID_MAC_ADDRESS;
228 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
229 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
230
231 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
232 int deviceType = remoteDevice.GetDeviceType();
233 if (deviceType == INVALID_TYPE) {
234 HILOGE("device is not discovery or scan, just quick BLE pair");
235 remoteDevice = BluetoothRemoteDevice(remoteAddr, BT_TRANSPORT_BLE);
236 }
237 if (deviceType == DEVICE_TYPE_LE) {
238 remoteDevice = BluetoothRemoteDevice(remoteAddr, BT_TRANSPORT_BLE);
239 }
240 int32_t ret = remoteDevice.StartPair();
241 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
242 return NapiGetBooleanTrue(env);
243 }
244
CancelPairedDevice(napi_env env,napi_callback_info info)245 napi_value CancelPairedDevice(napi_env env, napi_callback_info info)
246 {
247 HILOGI("start");
248 std::string remoteAddr{};
249 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
250 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
251
252 int transport = GetDeviceTransport(remoteAddr);
253 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
254 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
255 int32_t ret = host->RemovePair(remoteDevice);
256 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
257
258 return NapiGetBooleanTrue(env);
259 }
260
GetRemoteDeviceName(napi_env env,napi_callback_info info)261 napi_value GetRemoteDeviceName(napi_env env, napi_callback_info info)
262 {
263 HILOGD("start");
264 std::string remoteAddr = INVALID_MAC_ADDRESS;
265 std::string name = INVALID_NAME;
266 napi_value result = nullptr;
267 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
268 napi_create_string_utf8(env, name.c_str(), name.size(), &result);
269 NAPI_BT_ASSERT_RETURN(env, checkRet == true, BT_ERR_INVALID_PARAM, result);
270
271 int transport = GetDeviceTransport(remoteAddr);
272 int32_t err = BluetoothHost::GetDefaultHost().GetRemoteDevice(remoteAddr, transport).GetDeviceName(name);
273 napi_create_string_utf8(env, name.c_str(), name.size(), &result);
274 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
275 return result;
276 }
277
GetRemoteDeviceClass(napi_env env,napi_callback_info info)278 napi_value GetRemoteDeviceClass(napi_env env, napi_callback_info info)
279 {
280 HILOGD("start");
281 std::string remoteAddr = INVALID_MAC_ADDRESS;
282 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
283 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
284
285 int transport = GetDeviceTransport(remoteAddr);
286 int deviceCod = 0;
287 int32_t err = BluetoothHost::GetDefaultHost().GetRemoteDevice(remoteAddr, transport).GetDeviceClass(deviceCod);
288 BluetoothDeviceClass deviceClass = BluetoothDeviceClass(deviceCod);
289 int tmpCod = deviceClass.GetClassOfDevice();
290 int tmpMajorClass = deviceClass.GetMajorClass();
291 int tmpMajorMinorClass = deviceClass.GetMajorMinorClass();
292 if (tmpCod == 0) {
293 HILOGI("cod = %{public}d", tmpCod);
294 tmpCod = MajorClass::MAJOR_UNCATEGORIZED;
295 tmpMajorClass = MajorClass::MAJOR_UNCATEGORIZED;
296 tmpMajorMinorClass = MajorClass::MAJOR_UNCATEGORIZED;
297 }
298 HILOGD("cod = %{public}d, majorClass = %{public}d, majorMinorClass = %{public}d",
299 tmpCod,
300 tmpMajorClass,
301 tmpMajorMinorClass);
302 napi_value result = nullptr;
303 napi_create_object(env, &result);
304 napi_value majorClass = 0;
305 napi_create_int32(env, tmpMajorClass, &majorClass);
306 napi_set_named_property(env, result, "majorClass", majorClass);
307 napi_value majorMinorClass = 0;
308 napi_create_int32(env, tmpMajorMinorClass, &majorMinorClass);
309 napi_set_named_property(env, result, "majorMinorClass", majorMinorClass);
310 napi_value cod = 0;
311 napi_create_int32(env, tmpCod, &cod);
312 napi_set_named_property(env, result, "classOfDevice", cod);
313 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
314 return result;
315 }
316
GetLocalName(napi_env env,napi_callback_info info)317 napi_value GetLocalName(napi_env env, napi_callback_info info)
318 {
319 napi_value result = nullptr;
320 HILOGI("start");
321 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
322 std::string localName = INVALID_NAME;
323 int32_t err = host->GetLocalName(localName);
324 napi_create_string_utf8(env, localName.c_str(), localName.size(), &result);
325 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
326 HILOGI("end");
327 return result;
328 }
329
GetPairedDevices(napi_env env,napi_callback_info info)330 napi_value GetPairedDevices(napi_env env, napi_callback_info info)
331 {
332 HILOGI("start");
333 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
334 std::vector<BluetoothRemoteDevice> remoteDeviceLists;
335 int32_t ret = host->GetPairedDevices(BT_TRANSPORT_BREDR, remoteDeviceLists);
336 napi_value result = nullptr;
337 int count = 0;
338 napi_create_array(env, &result);
339 for (auto vec : remoteDeviceLists) {
340 napi_value remoteDeviceResult;
341 napi_create_string_utf8(env, vec.GetDeviceAddr().c_str(), vec.GetDeviceAddr().size(), &remoteDeviceResult);
342 napi_set_element(env, result, count, remoteDeviceResult);
343 count++;
344 }
345 NAPI_BT_ASSERT_RETURN(env, ret == BT_NO_ERROR, ret, result);
346 std::vector<BluetoothRemoteDevice> bleDeviceLists;
347 ret = host->GetPairedDevices(BT_TRANSPORT_BLE, bleDeviceLists);
348 for (auto vec : bleDeviceLists) {
349 napi_value remoteDeviceResult;
350 napi_create_string_utf8(env, vec.GetDeviceAddr().c_str(), vec.GetDeviceAddr().size(), &remoteDeviceResult);
351 napi_set_element(env, result, count, remoteDeviceResult);
352 count++;
353 }
354 NAPI_BT_ASSERT_RETURN(env, ret == BT_NO_ERROR, ret, result);
355 HILOGI("end");
356 return result;
357 }
358
GetProfileConnectionState(napi_env env,napi_callback_info info)359 napi_value GetProfileConnectionState(napi_env env, napi_callback_info info)
360 {
361 HILOGI("enter");
362 int profileId = 0;
363 bool checkRet = CheckProfileIdParam(env, info, profileId);
364 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet, BT_ERR_INVALID_PARAM);
365
366 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
367 int state = static_cast<int>(BTConnectState::DISCONNECTED);
368 int32_t err = host->GetBtProfileConnState(GetProfileId(profileId), state);
369 int status = GetProfileConnectionState(state);
370 napi_value ret = nullptr;
371 napi_create_int32(env, status, &ret);
372 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, ret);
373 HILOGI("status: %{public}d", status);
374 return ret;
375 }
376
SetDevicePairingConfirmation(napi_env env,napi_callback_info info)377 napi_value SetDevicePairingConfirmation(napi_env env, napi_callback_info info)
378 {
379 HILOGI("start");
380 std::string remoteAddr{};
381 bool accept = false;
382 bool checkRet = CheckSetDevicePairingConfirmationParam(env, info, remoteAddr, accept);
383 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
384
385 HILOGI("SetDevicePairingConfirmation::accept = %{public}d", accept);
386 int transport = GetDeviceTransport(remoteAddr);
387 int32_t ret = BT_NO_ERROR;
388 if (accept) {
389 ret =
390 BluetoothHost::GetDefaultHost().GetRemoteDevice(remoteAddr, transport).SetDevicePairingConfirmation(accept);
391 } else {
392 ret = BluetoothHost::GetDefaultHost().GetRemoteDevice(remoteAddr, transport).CancelPairing();
393 }
394 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
395 return NapiGetBooleanTrue(env);
396 }
397
SetLocalName(napi_env env,napi_callback_info info)398 napi_value SetLocalName(napi_env env, napi_callback_info info)
399 {
400 HILOGI("start");
401 std::string localName = INVALID_NAME;
402 bool checkRet = CheckLocalNameParam(env, info, localName);
403 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
404
405 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
406 int32_t ret = host->SetLocalName(localName);
407 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
408 return NapiGetBooleanTrue(env);
409 }
410
SetBluetoothScanMode(napi_env env,napi_callback_info info)411 napi_value SetBluetoothScanMode(napi_env env, napi_callback_info info)
412 {
413 HILOGI("start");
414 int32_t mode = 0;
415 int32_t duration = 0;
416 bool checkRet = CheckSetBluetoothScanModeParam(env, info, mode, duration);
417 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
418 HILOGI("mode = %{public}d,duration = %{public}d", mode, duration);
419
420 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
421 int32_t ret = host->SetBtScanMode(mode, duration);
422 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
423 host->SetBondableMode(BT_TRANSPORT_BREDR, 1);
424 return NapiGetBooleanTrue(env);
425 }
426
GetBluetoothScanMode(napi_env env,napi_callback_info info)427 napi_value GetBluetoothScanMode(napi_env env, napi_callback_info info)
428 {
429 HILOGI("start");
430 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
431 int32_t scanMode = 0;
432 int32_t err = host->GetBtScanMode(scanMode);
433 napi_value result = nullptr;
434 napi_create_uint32(env, scanMode, &result);
435 NAPI_BT_ASSERT_RETURN(env, err == BT_NO_ERROR, err, result);
436 HILOGI("end");
437 return result;
438 }
439
AddDiscoveryDevice(std::shared_ptr<BluetoothRemoteDevice> & device)440 void AddDiscoveryDevice(std::shared_ptr<BluetoothRemoteDevice> &device)
441 {
442 std::lock_guard<std::mutex> lock(deviceMutex);
443 for (auto dev : g_DiscoveryDevices) {
444 if (device->GetDeviceAddr().compare(dev->GetDeviceAddr()) == 0) {
445 return;
446 }
447 }
448 g_DiscoveryDevices.push_back(device);
449 }
450
ClearDiscoveryDevice()451 void ClearDiscoveryDevice()
452 {
453 std::lock_guard<std::mutex> lock(deviceMutex);
454 g_DiscoveryDevices.clear();
455 }
456
StartBluetoothDiscovery(napi_env env,napi_callback_info info)457 napi_value StartBluetoothDiscovery(napi_env env, napi_callback_info info)
458 {
459 HILOGI("start");
460 ClearDiscoveryDevice();
461 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
462 int ret = host->StartBtDiscovery();
463 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
464 return NapiGetBooleanTrue(env);
465 }
466
StopBluetoothDiscovery(napi_env env,napi_callback_info info)467 napi_value StopBluetoothDiscovery(napi_env env, napi_callback_info info)
468 {
469 HILOGI("start");
470 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
471 int ret = host->CancelBtDiscovery();
472 NAPI_BT_ASSERT_RETURN_FALSE(env, ret == BT_NO_ERROR, ret);
473 return NapiGetBooleanTrue(env);
474 }
475
476 #ifdef BLUETOOTH_API_SINCE_10
SetCallback(const napi_env & env,const napi_ref & callbackIn,const int & errorCode,const napi_value & result)477 static void SetCallback(const napi_env &env, const napi_ref &callbackIn, const int &errorCode, const napi_value &result)
478 {
479 HILOGI("errorCode:%{public}d", errorCode);
480 napi_value undefined = nullptr;
481 napi_get_undefined(env, &undefined);
482
483 napi_value callback = nullptr;
484 napi_value resultout = nullptr;
485 napi_get_reference_value(env, callbackIn, &callback);
486 napi_value results[ARGS_SIZE_TWO] = {nullptr};
487 results[PARAM0] = GetCallbackErrorValue(env, errorCode);
488 results[PARAM1] = result;
489 NAPI_CALL_RETURN_VOID(
490 env, napi_call_function(env, undefined, callback, ARGS_SIZE_TWO, &results[PARAM0], &resultout));
491 HILOGI("end");
492 }
493
SetPromise(const napi_env & env,const napi_deferred & deferred,const int32_t & errorCode,const napi_value & result)494 void SetPromise(const napi_env &env, const napi_deferred &deferred, const int32_t &errorCode, const napi_value &result)
495 {
496 if (errorCode == BT_NO_ERROR) {
497 napi_resolve_deferred(env, deferred, result);
498 } else {
499 napi_reject_deferred(env, deferred, GetCallbackErrorValue(env, errorCode));
500 }
501 }
502
PaddingCallbackPromiseInfo(const napi_env & env,const napi_ref & callback,CallbackPromiseInfo & info,napi_value & promise)503 static void PaddingCallbackPromiseInfo(
504 const napi_env &env, const napi_ref &callback, CallbackPromiseInfo &info, napi_value &promise)
505 {
506 HILOGI("enter");
507 if (callback) {
508 info.callback = callback;
509 info.isCallback = true;
510 } else {
511 napi_deferred deferred = nullptr;
512 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
513 info.deferred = deferred;
514 info.isCallback = false;
515 }
516 HILOGI("end");
517 }
518
ReturnCallbackPromise(const napi_env & env,const CallbackPromiseInfo & info,const napi_value & result)519 static void ReturnCallbackPromise(const napi_env &env, const CallbackPromiseInfo &info, const napi_value &result)
520 {
521 HILOGI("enter");
522 if (info.isCallback) {
523 SetCallback(env, info.callback, info.errorCode, result);
524 } else {
525 SetPromise(env, info.deferred, info.errorCode, result);
526 }
527 HILOGI("end");
528 }
529
ParseSetDevicePinCodeParameters(napi_env env,napi_callback_info info,SetDevicePinCodeCallbackInfo * params)530 napi_status ParseSetDevicePinCodeParameters(napi_env env, napi_callback_info info, SetDevicePinCodeCallbackInfo *params)
531 {
532 HILOGI("enter");
533 size_t expectedArgsCount = ARGS_SIZE_THREE;
534 size_t argc = expectedArgsCount;
535 std::string remoteAddr{};
536 std::string pinCode{};
537 napi_value argv[ARGS_SIZE_THREE] = {nullptr};
538 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, NULL));
539 NAPI_BT_RETURN_IF(argc != expectedArgsCount && argc != expectedArgsCount - CALLBACK_SIZE,
540 "Requires 2 or 3 arguments.",
541 napi_invalid_arg);
542 NAPI_BT_RETURN_IF(!ParseString(env, remoteAddr, argv[PARAM0]), "remoteAddr ParseString failed", napi_invalid_arg);
543 NAPI_BT_RETURN_IF(!IsValidAddress(remoteAddr), "Invalid addr", napi_invalid_arg);
544 NAPI_BT_RETURN_IF(!ParseString(env, pinCode, argv[PARAM1]), "pinCode ParseString failed", napi_invalid_arg);
545 params->deviceId = remoteAddr;
546 params->pinCode = pinCode;
547 if (argc == expectedArgsCount) {
548 NAPI_BT_CALL_RETURN(NapiIsFunction(env, argv[PARAM2]));
549 napi_create_reference(env, argv[PARAM2], 1, ¶ms->promise.callback);
550 }
551 HILOGI("end");
552 return napi_ok;
553 }
554
SetDevicePinCode(napi_env env,napi_callback_info info)555 napi_value SetDevicePinCode(napi_env env, napi_callback_info info)
556 {
557 HILOGI("start");
558 SetDevicePinCodeCallbackInfo *asyncCallbackInfo =
559 new (std::nothrow) SetDevicePinCodeCallbackInfo{.env = env, .asyncWork = nullptr};
560 napi_status status = ParseSetDevicePinCodeParameters(env, info, asyncCallbackInfo);
561 if (status != napi_ok) {
562 delete asyncCallbackInfo;
563 asyncCallbackInfo = nullptr;
564 }
565 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
566
567 napi_value promise = nullptr;
568 PaddingCallbackPromiseInfo(env, asyncCallbackInfo->promise.callback, asyncCallbackInfo->promise, promise);
569
570 napi_value resourceName = nullptr;
571 napi_create_string_latin1(env, "setDevicePinCode", NAPI_AUTO_LENGTH, &resourceName);
572 napi_create_async_work(env,
573 nullptr,
574 resourceName,
575 [](napi_env env, void *data) {
576 HILOGI("napi_create_async_work start");
577 SetDevicePinCodeCallbackInfo *callbackInfo = static_cast<SetDevicePinCodeCallbackInfo *>(data);
578 if (callbackInfo) {
579 int transport = GetDeviceTransport(callbackInfo->deviceId);
580 callbackInfo->promise.errorCode = BluetoothHost::GetDefaultHost()
581 .GetRemoteDevice(callbackInfo->deviceId, transport)
582 .SetDevicePin(callbackInfo->pinCode);
583 }
584 },
585 [](napi_env env, napi_status status, void *data) {
586 SetDevicePinCodeCallbackInfo *callbackInfo = static_cast<SetDevicePinCodeCallbackInfo *>(data);
587 if (callbackInfo) {
588 ReturnCallbackPromise(env, callbackInfo->promise, NapiGetNull(env));
589 if (callbackInfo->promise.callback != nullptr) {
590 napi_delete_reference(env, callbackInfo->promise.callback);
591 }
592 napi_delete_async_work(env, callbackInfo->asyncWork);
593 delete callbackInfo;
594 callbackInfo = nullptr;
595 }
596 },
597 static_cast<void *>(asyncCallbackInfo),
598 &asyncCallbackInfo->asyncWork);
599 NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
600 HILOGI("end");
601 if (asyncCallbackInfo->promise.isCallback) {
602 return NapiGetUndefinedRet(env);
603 } else {
604 return promise;
605 }
606 }
607
CheckDeviceAsyncParam(napi_env env,napi_callback_info info,std::string & addr)608 napi_status CheckDeviceAsyncParam(napi_env env, napi_callback_info info, std::string &addr)
609 {
610 size_t argc = ARGS_SIZE_TWO;
611 napi_value argv[ARGS_SIZE_TWO] = {nullptr};
612 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
613 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments", napi_invalid_arg);
614 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
615 return napi_ok;
616 }
617
PairDeviceAsync(napi_env env,napi_callback_info info)618 napi_value PairDeviceAsync(napi_env env, napi_callback_info info)
619 {
620 HILOGI("start");
621 std::string remoteAddr = INVALID_MAC_ADDRESS;
622 auto checkRet = CheckDeviceAsyncParam(env, info, remoteAddr);
623 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM);
624
625 auto func = [remoteAddr]() {
626 int transport = GetDeviceTransport(remoteAddr);
627 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
628 int32_t err = remoteDevice.StartPair();
629 HILOGI("err: %{public}d", err);
630 return NapiAsyncWorkRet(err);
631 };
632 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
633 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
634 asyncWork->Run();
635 return asyncWork->GetRet();
636 }
637
CancelPairedDeviceAsync(napi_env env,napi_callback_info info)638 napi_value CancelPairedDeviceAsync(napi_env env, napi_callback_info info)
639 {
640 HILOGI("start");
641 std::string remoteAddr {};
642 bool checkRet = CheckDeviceAsyncParam(env, info, remoteAddr);
643 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM);
644
645 auto func = [remoteAddr]() {
646 int transport = GetDeviceTransport(remoteAddr);
647 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
648 BluetoothHost *host = &BluetoothHost::GetDefaultHost();
649 int32_t err = host->RemovePair(remoteDevice);
650 HILOGI("err: %{public}d", err);
651 return NapiAsyncWorkRet(err);
652 };
653 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
654 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
655 asyncWork->Run();
656 return asyncWork->GetRet();
657 }
658
CancelPairingDevice(napi_env env,napi_callback_info info)659 napi_value CancelPairingDevice(napi_env env, napi_callback_info info)
660 {
661 HILOGI("start");
662 std::string remoteAddr{};
663 bool checkRet = CheckDeviceAsyncParam(env, info, remoteAddr);
664 NAPI_BT_ASSERT_RETURN_UNDEF(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM);
665
666 auto func = [remoteAddr]() {
667 int transport = GetDeviceTransport(remoteAddr);
668 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
669 int32_t err = remoteDevice.CancelPairing();
670 HILOGI("err: %{public}d", err);
671 return NapiAsyncWorkRet(err);
672 };
673 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
674 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
675 asyncWork->Run();
676 return asyncWork->GetRet();
677 }
678
CheckPairCredibleDeviceParam(napi_env env,napi_callback_info info,std::string & addr,int & transport)679 napi_status CheckPairCredibleDeviceParam(napi_env env, napi_callback_info info, std::string &addr, int &transport)
680 {
681 size_t argc = ARGS_SIZE_THREE;
682 napi_value argv[ARGS_SIZE_THREE] = {nullptr};
683 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
684 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_TWO && argc != ARGS_SIZE_THREE, "Requires 2 or 3 arguments.", napi_invalid_arg);
685 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], addr));
686 NAPI_BT_RETURN_IF(!ParseInt32(env, transport, argv[PARAM1]), "ParseInt32 failed", napi_invalid_arg);
687 NAPI_BT_RETURN_IF(!IsValidTransport(transport), "Invalid transport", napi_invalid_arg);
688 return napi_ok;
689 }
690
PairCredibleDevice(napi_env env,napi_callback_info info)691 napi_value PairCredibleDevice(napi_env env, napi_callback_info info)
692 {
693 HILOGI("start");
694 std::string remoteAddr = INVALID_MAC_ADDRESS;
695 int transport = INVALID_TYPE;
696 auto status = CheckPairCredibleDeviceParam(env, info, remoteAddr, transport);
697 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
698
699 auto func = [remoteAddr, transport]() {
700 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(remoteAddr, transport);
701 int32_t err = remoteDevice.StartPair();
702 HILOGI("err: %{public}d", err);
703 return NapiAsyncWorkRet(err);
704 };
705 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
706 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
707 asyncWork->Run();
708 return asyncWork->GetRet();
709 }
710
CheckGetProfileUuids(napi_env env,napi_callback_info info,std::string & address)711 napi_status CheckGetProfileUuids(napi_env env, napi_callback_info info, std::string &address)
712 {
713 size_t argc = ARGS_SIZE_TWO;
714 napi_value argv[ARGS_SIZE_TWO] = {0};
715 NAPI_BT_CALL_RETURN(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
716 NAPI_BT_RETURN_IF(argc != ARGS_SIZE_ONE && argc != ARGS_SIZE_TWO, "Requires 1 or 2 arguments.", napi_invalid_arg);
717 NAPI_BT_CALL_RETURN(NapiParseBdAddr(env, argv[PARAM0], address));
718 return napi_ok;
719 }
720
GetLocalProfileUuids(napi_env env,napi_callback_info info)721 napi_value GetLocalProfileUuids(napi_env env, napi_callback_info info)
722 {
723 HILOGI("start");
724 auto func = []() {
725 std::vector<std::string> uuids{};
726 int32_t err = BluetoothHost::GetDefaultHost().GetLocalProfileUuids(uuids);
727 HILOGI("err: %{public}d", err);
728 auto object = std::make_shared<NapiNativeUuidsArray>(uuids);
729 return NapiAsyncWorkRet(err, object);
730 };
731 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
732 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
733 asyncWork->Run();
734 return asyncWork->GetRet();
735 }
736
GetRemoteProfileUuids(napi_env env,napi_callback_info info)737 napi_value GetRemoteProfileUuids(napi_env env, napi_callback_info info)
738 {
739 HILOGI("start");
740 std::string address;
741 auto status = CheckGetProfileUuids(env, info, address);
742 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
743 auto func = [address]() {
744 std::vector<std::string> uuids{};
745 BluetoothRemoteDevice remoteDevice = BluetoothRemoteDevice(address, BT_TRANSPORT_BREDR);
746 int32_t err = remoteDevice.GetDeviceUuids(uuids);
747 HILOGI("err: %{public}d", err);
748 auto object = std::make_shared<NapiNativeUuidsArray>(uuids);
749 return NapiAsyncWorkRet(err, object);
750 };
751 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
752 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
753 asyncWork->Run();
754 return asyncWork->GetRet();
755 }
756 #endif
757
ConnectionPropertyValueInit(napi_env env,napi_value exports)758 napi_value ConnectionPropertyValueInit(napi_env env, napi_value exports)
759 {
760 HILOGI("start");
761 napi_value scanModeObj = ScanModeInit(env);
762 napi_value bondStateObj = BondStateInit(env);
763 #ifdef BLUETOOTH_API_SINCE_10
764 napi_value bluetoothTransportObject = BluetoothTransportInit(env);
765 napi_value pinTypeObject = PinTypeInit(env);
766 #endif
767 napi_property_descriptor exportProperties[] = {
768 DECLARE_NAPI_PROPERTY("ScanMode", scanModeObj),
769 DECLARE_NAPI_PROPERTY("BondState", bondStateObj),
770 #ifdef BLUETOOTH_API_SINCE_10
771 DECLARE_NAPI_PROPERTY("BluetoothTransport", bluetoothTransportObject),
772 DECLARE_NAPI_PROPERTY("PinType", pinTypeObject),
773 #endif
774 };
775 napi_define_properties(env, exports, sizeof(exportProperties) / sizeof(*exportProperties), exportProperties);
776 HILOGI("end");
777 return exports;
778 }
779
ScanModeInit(napi_env env)780 napi_value ScanModeInit(napi_env env)
781 {
782 HILOGI("enter");
783 napi_value scanMode = nullptr;
784 napi_create_object(env, &scanMode);
785 SetNamedPropertyByInteger(env, scanMode, static_cast<int>(ScanMode::SCAN_MODE_NONE), "SCAN_MODE_NONE");
786 SetNamedPropertyByInteger(
787 env, scanMode, static_cast<int>(ScanMode::SCAN_MODE_CONNECTABLE), "SCAN_MODE_CONNECTABLE");
788 SetNamedPropertyByInteger(
789 env, scanMode, static_cast<int>(ScanMode::SCAN_MODE_GENERAL_DISCOVERABLE), "SCAN_MODE_GENERAL_DISCOVERABLE");
790 SetNamedPropertyByInteger(
791 env, scanMode, static_cast<int>(ScanMode::SCAN_MODE_LIMITED_DISCOVERABLE), "SCAN_MODE_LIMITED_DISCOVERABLE");
792 SetNamedPropertyByInteger(env,
793 scanMode,
794 static_cast<int>(ScanMode::SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE),
795 "SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE");
796 SetNamedPropertyByInteger(env,
797 scanMode,
798 static_cast<int>(ScanMode::SCAN_MODE_CONNECTABLE_LIMITED_DISCOVERABLE),
799 "SCAN_MODE_CONNECTABLE_LIMITED_DISCOVERABLE");
800 return scanMode;
801 }
802
BondStateInit(napi_env env)803 napi_value BondStateInit(napi_env env)
804 {
805 HILOGI("enter");
806 napi_value bondState = nullptr;
807 napi_create_object(env, &bondState);
808 SetNamedPropertyByInteger(env, bondState, static_cast<int>(BondState::BOND_STATE_INVALID), "BOND_STATE_INVALID");
809 SetNamedPropertyByInteger(env, bondState, static_cast<int>(BondState::BOND_STATE_BONDING), "BOND_STATE_BONDING");
810 SetNamedPropertyByInteger(env, bondState, static_cast<int>(BondState::BOND_STATE_BONDED), "BOND_STATE_BONDED");
811 return bondState;
812 }
813
814 #ifdef BLUETOOTH_API_SINCE_10
BluetoothTransportInit(napi_env env)815 napi_value BluetoothTransportInit(napi_env env)
816 {
817 HILOGI("enter");
818 napi_value bluetoothTransport = nullptr;
819 napi_create_object(env, &bluetoothTransport);
820 SetNamedPropertyByInteger(
821 env, bluetoothTransport, static_cast<int>(BluetoothTransport::TRANSPORT_BR_EDR), "TRANSPORT_BR_EDR");
822 SetNamedPropertyByInteger(
823 env, bluetoothTransport, static_cast<int>(BluetoothTransport::TRANSPORT_LE), "TRANSPORT_LE");
824 return bluetoothTransport;
825 }
826
PinTypeInit(napi_env env)827 napi_value PinTypeInit(napi_env env)
828 {
829 HILOGI("enter");
830 napi_value pinType = nullptr;
831 napi_create_object(env, &pinType);
832 SetNamedPropertyByInteger(
833 env, pinType, static_cast<int>(PinType::PIN_TYPE_ENTER_PIN_CODE), "PIN_TYPE_ENTER_PIN_CODE");
834 SetNamedPropertyByInteger(
835 env, pinType, static_cast<int>(PinType::PIN_TYPE_ENTER_PASSKEY), "PIN_TYPE_ENTER_PASSKEY");
836 SetNamedPropertyByInteger(
837 env, pinType, static_cast<int>(PinType::PIN_TYPE_CONFIRM_PASSKEY), "PIN_TYPE_CONFIRM_PASSKEY");
838 SetNamedPropertyByInteger(
839 env, pinType, static_cast<int>(PinType::PIN_TYPE_NO_PASSKEY_CONSENT), "PIN_TYPE_NO_PASSKEY_CONSENT");
840 SetNamedPropertyByInteger(
841 env, pinType, static_cast<int>(PinType::PIN_TYPE_NOTIFY_PASSKEY), "PIN_TYPE_NOTIFY_PASSKEY");
842 SetNamedPropertyByInteger(
843 env, pinType, static_cast<int>(PinType::PIN_TYPE_DISPLAY_PIN_CODE), "PIN_TYPE_DISPLAY_PIN_CODE");
844 SetNamedPropertyByInteger(env, pinType, static_cast<int>(PinType::PIN_TYPE_OOB_CONSENT), "PIN_TYPE_OOB_CONSENT");
845 SetNamedPropertyByInteger(
846 env, pinType, static_cast<int>(PinType::PIN_TYPE_PIN_16_DIGITS), "PIN_TYPE_PIN_16_DIGITS");
847 return pinType;
848 }
849 #endif
850
RegisterObserverToHost()851 void RegisterObserverToHost()
852 {
853 HILOGI("start");
854 g_remoteDeviceObserver = std::make_shared<NapiBluetoothRemoteDeviceObserver>();
855 BluetoothHost &host = BluetoothHost::GetDefaultHost();
856 host.RegisterObserver(g_connectionObserver);
857 host.RegisterRemoteDeviceObserver(g_remoteDeviceObserver);
858 }
859
GetDeviceTransport(const std::string & device)860 int GetDeviceTransport(const std::string &device)
861 {
862 std::lock_guard<std::mutex> lock(deviceMutex);
863 for (auto dev : g_DiscoveryDevices) {
864 if (device.compare(dev->GetDeviceAddr()) == 0) {
865 return dev->GetTransportType();
866 }
867 }
868 return BT_TRANSPORT_BREDR;
869 }
870 } // namespace Bluetooth
871 } // namespace OHOS