• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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