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