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 #ifndef LOG_TAG
16 #define LOG_TAG "bt_napi_hid_host"
17 #endif
18
19 #include "bluetooth_hid_host.h"
20
21 #include "bluetooth_log.h"
22 #include "bluetooth_utils.h"
23 #include "napi_async_work.h"
24 #include "napi_bluetooth_hid_host_observer.h"
25 #include "napi_bluetooth_error.h"
26 #include "napi_bluetooth_utils.h"
27 #include "napi_bluetooth_profile.h"
28 #include "napi_bluetooth_hid_host.h"
29 #include "hitrace_meter.h"
30
31 namespace OHOS {
32 namespace Bluetooth {
33 using namespace std;
34 std::shared_ptr<NapiBluetoothHidHostObserver> NapiBluetoothHidHost::observer_ =
35 std::make_shared<NapiBluetoothHidHostObserver>();
36 thread_local napi_ref NapiBluetoothHidHost::consRef_ = nullptr;
37
DefineHidHostJSClass(napi_env env,napi_value exports)38 void NapiBluetoothHidHost::DefineHidHostJSClass(napi_env env, napi_value exports)
39 {
40 napi_value constructor;
41 napi_property_descriptor properties[] = {
42 DECLARE_NAPI_FUNCTION("on", On),
43 DECLARE_NAPI_FUNCTION("off", Off),
44 #ifdef BLUETOOTH_API_SINCE_10
45 DECLARE_NAPI_FUNCTION("getConnectedDevices", GetConnectionDevices),
46 DECLARE_NAPI_FUNCTION("getConnectionState", GetDeviceState),
47 #else
48 DECLARE_NAPI_FUNCTION("getConnectionDevices", GetConnectionDevices),
49 DECLARE_NAPI_FUNCTION("getDeviceState", GetDeviceState),
50 #endif
51 DECLARE_NAPI_FUNCTION("connect", Connect),
52 DECLARE_NAPI_FUNCTION("disconnect", Disconnect),
53 DECLARE_NAPI_FUNCTION("setConnectionStrategy", SetConnectionStrategy),
54 DECLARE_NAPI_FUNCTION("getConnectionStrategy", GetConnectionStrategy),
55 };
56
57 napi_define_class(env, "NapiBluetoothHidHost", NAPI_AUTO_LENGTH, HidHostConstructor, nullptr,
58 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
59 #ifdef BLUETOOTH_API_SINCE_10
60 DefineCreateProfile(env, exports);
61 napi_create_reference(env, constructor, 1, &consRef_);
62 #else
63 napi_value napiProfile;
64 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
65 NapiProfile::SetProfile(env, ProfileId::PROFILE_HID_HOST, napiProfile);
66 HidHost *profile = HidHost::GetProfile();
67 profile->RegisterObserver(observer_);
68 #endif
69 }
70
DefineCreateProfile(napi_env env,napi_value exports)71 napi_value NapiBluetoothHidHost::DefineCreateProfile(napi_env env, napi_value exports)
72 {
73 napi_property_descriptor properties[] = {
74 DECLARE_NAPI_FUNCTION("createHidHostProfile", CreateHidHostProfile),
75 };
76 HITRACE_METER_NAME(HITRACE_TAG_OHOS, "hid:napi_define_properties");
77 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
78 return exports;
79 }
80
CreateHidHostProfile(napi_env env,napi_callback_info info)81 napi_value NapiBluetoothHidHost::CreateHidHostProfile(napi_env env, napi_callback_info info)
82 {
83 HILOGI("enter");
84 napi_value napiProfile;
85 napi_value constructor = nullptr;
86 napi_get_reference_value(env, consRef_, &constructor);
87 napi_new_instance(env, constructor, 0, nullptr, &napiProfile);
88 NapiProfile::SetProfile(env, ProfileId::PROFILE_HID_HOST, napiProfile);
89
90 HidHost *profile = HidHost::GetProfile();
91 profile->RegisterObserver(observer_);
92
93 return napiProfile;
94 }
95
96
HidHostConstructor(napi_env env,napi_callback_info info)97 napi_value NapiBluetoothHidHost::HidHostConstructor(napi_env env, napi_callback_info info)
98 {
99 napi_value thisVar = nullptr;
100 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
101 return thisVar;
102 }
103
On(napi_env env,napi_callback_info info)104 napi_value NapiBluetoothHidHost::On(napi_env env, napi_callback_info info)
105 {
106 if (observer_) {
107 auto status = observer_->eventSubscribe_.Register(env, info);
108 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
109 }
110 return NapiGetUndefinedRet(env);
111 }
112
Off(napi_env env,napi_callback_info info)113 napi_value NapiBluetoothHidHost::Off(napi_env env, napi_callback_info info)
114 {
115 if (observer_) {
116 auto status = observer_->eventSubscribe_.Deregister(env, info);
117 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
118 }
119 return NapiGetUndefinedRet(env);
120 }
121
GetConnectionDevices(napi_env env,napi_callback_info info)122 napi_value NapiBluetoothHidHost::GetConnectionDevices(napi_env env, napi_callback_info info)
123 {
124 HILOGI("enter");
125
126 napi_value ret = nullptr;
127 if (napi_create_array(env, &ret) != napi_ok) {
128 HILOGE("napi_create_array failed.");
129 }
130 napi_status checkRet = CheckEmptyParam(env, info);
131 NAPI_BT_ASSERT_RETURN(env, checkRet == napi_ok, BT_ERR_INVALID_PARAM, ret);
132
133 HidHost *profile = HidHost::GetProfile();
134 vector<int> states = { static_cast<int>(BTConnectState::CONNECTED) };
135 vector<BluetoothRemoteDevice> devices;
136 int errorCode = profile->GetDevicesByStates(states, devices);
137 HILOGI("errorCode:%{public}s, devices size:%{public}zu", GetErrorCode(errorCode).c_str(), devices.size());
138 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, ret);
139
140 vector<string> deviceVector;
141 for (auto &device: devices) {
142 deviceVector.push_back(device.GetDeviceAddr());
143 }
144 ConvertStringVectorToJS(env, ret, deviceVector);
145 return ret;
146 }
147
GetDeviceState(napi_env env,napi_callback_info info)148 napi_value NapiBluetoothHidHost::GetDeviceState(napi_env env, napi_callback_info info)
149 {
150 napi_value result = nullptr;
151 int32_t profileState = ProfileConnectionState::STATE_DISCONNECTED;
152 if (napi_create_int32(env, profileState, &result) != napi_ok) {
153 HILOGE("napi_create_int32 failed.");
154 }
155
156 std::string remoteAddr {};
157 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
158 NAPI_BT_ASSERT_RETURN(env, checkRet, BT_ERR_INVALID_PARAM, result);
159
160 HidHost *profile = HidHost::GetProfile();
161 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
162 int32_t state = static_cast<int32_t>(BTConnectState::DISCONNECTED);
163 int32_t errorCode = profile->GetDeviceState(device, state);
164 NAPI_BT_ASSERT_RETURN(env, errorCode == BT_NO_ERROR, errorCode, result);
165
166 profileState = GetProfileConnectionState(state);
167 if (napi_create_int32(env, profileState, &result) != napi_ok) {
168 HILOGE("napi_create_int32 failed.");
169 }
170 return result;
171 }
172
Connect(napi_env env,napi_callback_info info)173 napi_value NapiBluetoothHidHost::Connect(napi_env env, napi_callback_info info)
174 {
175 HILOGI("enter");
176 std::string remoteAddr {};
177 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
178 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
179
180 HidHost *profile = HidHost::GetProfile();
181 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
182 int32_t errorCode = profile->Connect(device);
183 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
184 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
185 return NapiGetBooleanTrue(env);
186 }
187
Disconnect(napi_env env,napi_callback_info info)188 napi_value NapiBluetoothHidHost::Disconnect(napi_env env, napi_callback_info info)
189 {
190 HILOGI("Disconnect called");
191 std::string remoteAddr {};
192 bool checkRet = CheckDeivceIdParam(env, info, remoteAddr);
193 NAPI_BT_ASSERT_RETURN_FALSE(env, checkRet, BT_ERR_INVALID_PARAM);
194
195 HidHost *profile = HidHost::GetProfile();
196 BluetoothRemoteDevice device(remoteAddr, BT_TRANSPORT_BREDR);
197 int32_t errorCode = profile->Disconnect(device);
198 HILOGI("errorCode:%{public}s", GetErrorCode(errorCode).c_str());
199 NAPI_BT_ASSERT_RETURN_FALSE(env, errorCode == BT_NO_ERROR, errorCode);
200 return NapiGetBooleanTrue(env);
201 }
202
SetConnectionStrategy(napi_env env,napi_callback_info info)203 napi_value NapiBluetoothHidHost::SetConnectionStrategy(napi_env env, napi_callback_info info)
204 {
205 HILOGD("start");
206 std::string remoteAddr {};
207 int32_t strategy = 0;
208 auto status = CheckSetConnectStrategyParam(env, info, remoteAddr, strategy);
209 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
210
211 auto func = [remoteAddr, strategy]() {
212 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
213 HidHost *profile = HidHost::GetProfile();
214 int32_t err = profile->SetConnectStrategy(remoteDevice, strategy);
215 HILOGI("err: %{public}d", err);
216 return NapiAsyncWorkRet(err);
217 };
218 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
219 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
220 asyncWork->Run();
221 return asyncWork->GetRet();
222 }
223
GetConnectionStrategy(napi_env env,napi_callback_info info)224 napi_value NapiBluetoothHidHost::GetConnectionStrategy(napi_env env, napi_callback_info info)
225 {
226 HILOGD("start");
227 std::string remoteAddr {};
228 auto status = CheckDeviceAddressParam(env, info, remoteAddr);
229 NAPI_BT_ASSERT_RETURN_UNDEF(env, status == napi_ok, BT_ERR_INVALID_PARAM);
230
231 auto func = [remoteAddr]() {
232 int strategy = 0;
233 BluetoothRemoteDevice remoteDevice(remoteAddr, BT_TRANSPORT_BREDR);
234 HidHost *profile = HidHost::GetProfile();
235 int32_t err = profile->GetConnectStrategy(remoteDevice, strategy);
236 HILOGI("err: %{public}d, deviceName: %{public}d", err, strategy);
237 auto object = std::make_shared<NapiNativeInt>(strategy);
238 return NapiAsyncWorkRet(err, object);
239 };
240 auto asyncWork = NapiAsyncWorkFactory::CreateAsyncWork(env, info, func, ASYNC_WORK_NO_NEED_CALLBACK);
241 NAPI_BT_ASSERT_RETURN_UNDEF(env, asyncWork, BT_ERR_INTERNAL_ERROR);
242 asyncWork->Run();
243 return asyncWork->GetRet();
244 }
245 } // namespace Bluetooth
246 } // namespace OHOS