1 /*
2 * Copyright (c) 2023-2025 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 <unistd.h>
17 #include <cinttypes>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <optional>
21 #include <string>
22 #include <map>
23 #include <vector>
24 #include <uv.h>
25
26 #include "napi_remote_object.h"
27 #include "device_manager_middle.h"
28 #include "edm_errors.h"
29
30 namespace OHOS {
31 namespace ExternalDeviceManager {
32 constexpr int32_t PARAM_COUNT_0 = 0;
33 constexpr int32_t PARAM_COUNT_1 = 1;
34 constexpr int32_t PARAM_COUNT_2 = 2;
35 constexpr int32_t PARAM_COUNT_3 = 3;
36 constexpr uint64_t MAX_JS_NUMBER = 9007199254740991;
37
38 static const std::map<int32_t, std::string> ERROR_MESSAGES = {
39 {SERVICE_EXCEPTION, "ExternalDeviceManager service exception."},
40 {PERMISSION_DENIED, "Permission denied."},
41 {PERMISSION_NOT_SYSTEM_APP, "Permission denied. A non-system application cannot call a system API."},
42 {PARAMETER_ERROR, "The parameter check failed."},
43 {SERVICE_EXCEPTION_NEW, "ExternalDeviceManager service exception."},
44 {SERVICE_NOT_ALLOW_ACCESS, "Driver does not allow application access."},
45 {SERVICE_NOT_BOUND, "There is no binding relationship between the application and the driver."}
46 };
47
48 static std::mutex mapMutex;
49 static std::map<uint64_t, sptr<AsyncData>> g_callbackMap = {};
50 static DriverExtMgrClient &g_edmClient = DriverExtMgrClient::GetInstance();
51 static sptr<DeviceManagerCallback> g_edmCallback = new (std::nothrow) DeviceManagerCallback;
52
53 static napi_value ConvertToBusinessError(const napi_env &env, const ErrMsg &errMsg);
54 static napi_value ConvertToJsDeviceId(const napi_env &env, uint64_t deviceId);
55 static napi_value GetCallbackResult(const napi_env &env, uint64_t deviceId, const sptr<IRemoteObject> &drvExtObj);
56
DeleteNapiRef()57 void AsyncData::DeleteNapiRef()
58 {
59 if (env == nullptr) {
60 return;
61 }
62 auto task = [this]() {
63 EDM_LOGE(MODULE_DEV_MGR, "DeleteNapiRef async task is run.");
64 if (bindCallback != nullptr) {
65 napi_delete_reference(env, bindCallback);
66 }
67 if (onDisconnect != nullptr) {
68 napi_delete_reference(env, onDisconnect);
69 }
70 if (unbindCallback != nullptr) {
71 napi_delete_reference(env, unbindCallback);
72 }
73 };
74 if (napi_status::napi_ok != napi_send_event(env, task, napi_eprio_immediate)) {
75 EDM_LOGE(MODULE_DEV_MGR, "delete napi ref send event failed.");
76 }
77 }
78
OnConnect(uint64_t deviceId,const sptr<IRemoteObject> & drvExtObj,const ErrMsg & errMsg)79 ErrCode DeviceManagerCallback::OnConnect(uint64_t deviceId, const sptr<IRemoteObject> &drvExtObj, const ErrMsg &errMsg)
80 {
81 EDM_LOGE(MODULE_DEV_MGR, "bind device callback: %{public}016" PRIX64, deviceId);
82 std::lock_guard<std::mutex> mapLock(mapMutex);
83 if (g_callbackMap.count(deviceId) == 0) {
84 EDM_LOGE(MODULE_DEV_MGR, "device OnConnect is null");
85 return EDM_NOK;
86 }
87
88 auto data = g_callbackMap[deviceId];
89 if (!errMsg.IsOk()) {
90 g_callbackMap.erase(deviceId);
91 }
92 auto task = [data, drvExtObj, errMsg]() {
93 EDM_LOGE(MODULE_DEV_MGR, "OnConnect async task is run.");
94 napi_handle_scope scope = nullptr;
95 napi_open_handle_scope(data->env, &scope);
96 napi_value result = GetCallbackResult(data->env, data->deviceId, drvExtObj);
97 napi_value err = ConvertToBusinessError(data->env, errMsg);
98 if (data->bindCallback != nullptr) {
99 napi_value callback;
100 napi_get_reference_value(data->env, data->bindCallback, &callback);
101 napi_value argv[PARAM_COUNT_2] = {err, result};
102 napi_value callResult;
103 napi_call_function(data->env, nullptr, callback, PARAM_COUNT_2, argv, &callResult);
104 EDM_LOGI(MODULE_DEV_MGR, "bind device callback finish.");
105 } else if (data->bindDeferred != nullptr) {
106 if (errMsg.IsOk()) {
107 napi_resolve_deferred(data->env, data->bindDeferred, result);
108 } else {
109 napi_reject_deferred(data->env, data->bindDeferred, err);
110 }
111 EDM_LOGI(MODULE_DEV_MGR, "bind device promise finish.");
112 }
113 napi_close_handle_scope(data->env, scope);
114 };
115 if (napi_status::napi_ok != napi_send_event(data->env, task, napi_eprio_immediate)) {
116 EDM_LOGE(MODULE_DEV_MGR, "OnConnect send event failed.");
117 return EDM_NOK;
118 }
119 return EDM_OK;
120 }
121
OnDisconnect(uint64_t deviceId,const ErrMsg & errMsg)122 ErrCode DeviceManagerCallback::OnDisconnect(uint64_t deviceId, const ErrMsg &errMsg)
123 {
124 EDM_LOGE(MODULE_DEV_MGR, "device onDisconnect: %{public}016" PRIX64, deviceId);
125 std::lock_guard<std::mutex> mapLock(mapMutex);
126 if (g_callbackMap.count(deviceId) == 0) {
127 EDM_LOGE(MODULE_DEV_MGR, "device callback map is null");
128 return EDM_NOK;
129 }
130
131 auto data = g_callbackMap[deviceId];
132 g_callbackMap.erase(deviceId);
133 if (data->onDisconnect == nullptr && data->unbindCallback == nullptr && data->unbindDeferred == nullptr) {
134 EDM_LOGE(MODULE_DEV_MGR, "device callback is null");
135 return EDM_NOK;
136 }
137 data->IncStrongRef(nullptr);
138 auto task = [data, errMsg]() {
139 EDM_LOGE(MODULE_DEV_MGR, "OnDisconnect async task is run.");
140 data->DecStrongRef(nullptr);
141 napi_handle_scope scope = nullptr;
142 napi_open_handle_scope(data->env, &scope);
143 napi_value disConnCallback;
144 napi_value result = ConvertToJsDeviceId(data->env, data->deviceId);
145 if (napi_get_reference_value(data->env, data->onDisconnect, &disConnCallback) == napi_ok) {
146 napi_value err = ConvertToBusinessError(data->env, errMsg);
147 napi_value argv[PARAM_COUNT_2] = {err, result};
148 napi_value callResult;
149 napi_call_function(data->env, nullptr, disConnCallback, PARAM_COUNT_2, argv, &callResult);
150 EDM_LOGI(MODULE_DEV_MGR, "onDisconnect callback finish.");
151 }
152
153 napi_value err = ConvertToBusinessError(data->env, data->unBindErrMsg);
154 if (data->unbindCallback != nullptr) {
155 napi_value callback;
156 NAPI_CALL_RETURN_VOID(data->env, napi_get_reference_value(data->env, data->unbindCallback, &callback));
157 napi_value argv[PARAM_COUNT_2] = {err, result};
158 napi_value callResult;
159 napi_call_function(data->env, nullptr, callback, PARAM_COUNT_2, argv, &callResult);
160 EDM_LOGI(MODULE_DEV_MGR, "unbind device callback finish.");
161 } else if (data->unbindDeferred != nullptr) {
162 data->unBindErrMsg.IsOk() ? napi_resolve_deferred(data->env, data->unbindDeferred, result) :
163 napi_reject_deferred(data->env, data->unbindDeferred, err);
164 EDM_LOGI(MODULE_DEV_MGR, "unbind device promise finish.");
165 }
166 napi_close_handle_scope(data->env, scope);
167 };
168 if (napi_status::napi_ok != napi_send_event(data->env, task, napi_eprio_immediate)) {
169 EDM_LOGE(MODULE_DEV_MGR, "OnDisconnect send event failed.");
170 data->DecStrongRef(nullptr);
171 return EDM_NOK;
172 }
173 return EDM_OK;
174 }
175
OnUnBind(uint64_t deviceId,const ErrMsg & errMsg)176 ErrCode DeviceManagerCallback::OnUnBind(uint64_t deviceId, const ErrMsg &errMsg)
177 {
178 EDM_LOGI(MODULE_DEV_MGR, "unbind device callback: %{public}016" PRIX64, deviceId);
179 std::lock_guard<std::mutex> mapLock(mapMutex);
180 if (g_callbackMap.count(deviceId) == 0) {
181 EDM_LOGE(MODULE_DEV_MGR, "device unbind map is null");
182 return EDM_NOK;
183 }
184
185 auto asyncData = g_callbackMap[deviceId];
186 if (asyncData == nullptr || (asyncData->unbindCallback == nullptr && asyncData->unbindDeferred == nullptr)) {
187 EDM_LOGE(MODULE_DEV_MGR, "device unbind is null");
188 return EDM_NOK;
189 }
190 asyncData->unBindErrMsg = errMsg;
191 return EDM_OK;
192 }
193
IsMatchType(const napi_env & env,const napi_value & value,const napi_valuetype & type)194 static bool IsMatchType(const napi_env &env, const napi_value &value, const napi_valuetype &type)
195 {
196 napi_valuetype paramType = napi_undefined;
197 napi_typeof(env, value, ¶mType);
198 return paramType == type;
199 }
200
GetCallbackResult(const napi_env & env,uint64_t deviceId,const sptr<IRemoteObject> & drvExtObj)201 static napi_value GetCallbackResult(const napi_env &env, uint64_t deviceId, const sptr<IRemoteObject> &drvExtObj)
202 {
203 napi_value id = ConvertToJsDeviceId(env, deviceId);
204
205 napi_value remoteObj;
206 if (drvExtObj == nullptr) {
207 napi_get_undefined(env, &remoteObj);
208 EDM_LOGE(MODULE_DEV_MGR, "Remote obj is null.");
209 } else {
210 EDM_LOGI(MODULE_DEV_MGR, "Remote obj create.");
211 remoteObj = NAPI_ohos_rpc_CreateJsRemoteObject(env, drvExtObj);
212 }
213
214 napi_value result;
215 napi_create_object(env, &result);
216 napi_set_named_property(env, result, "deviceId", id);
217 napi_set_named_property(env, result, "remote", remoteObj);
218
219 return result;
220 }
221
GetNapiError(int32_t errorCode)222 static std::optional<std::string> GetNapiError(int32_t errorCode)
223 {
224 auto iter = ERROR_MESSAGES.find(errorCode);
225 if (iter != ERROR_MESSAGES.end()) {
226 return iter->second;
227 }
228 return std::nullopt;
229 }
230
CreateBusinessError(const napi_env & env,const int32_t errCode,const std::string & errMessage)231 static napi_value CreateBusinessError(const napi_env &env, const int32_t errCode, const std::string &errMessage)
232 {
233 napi_value businessError = nullptr;
234 napi_value code = nullptr;
235 napi_value msg = nullptr;
236 NAPI_CALL(env, napi_create_int32(env, errCode, &code));
237 NAPI_CALL(env, napi_create_string_utf8(env, errMessage.c_str(), NAPI_AUTO_LENGTH, &msg));
238 napi_create_error(env, nullptr, msg, &businessError);
239 napi_set_named_property(env, businessError, "code", code);
240 napi_set_named_property(env, businessError, "message", msg);
241 return businessError;
242 }
243
ConvertToBusinessError(const napi_env & env,const ErrMsg & errMsg)244 static napi_value ConvertToBusinessError(const napi_env &env, const ErrMsg &errMsg)
245 {
246 napi_value businessError = nullptr;
247 if (errMsg.IsOk()) {
248 napi_get_undefined(env, &businessError);
249 return businessError;
250 }
251
252 auto msgString = GetNapiError(SERVICE_EXCEPTION);
253 if (!msgString) {
254 napi_get_undefined(env, &businessError);
255 return businessError;
256 }
257
258 napi_value code = nullptr;
259 napi_value msg = nullptr;
260 NAPI_CALL(env, napi_create_int32(env, SERVICE_EXCEPTION, &code));
261 NAPI_CALL(env, napi_create_string_utf8(env, msgString.value().c_str(), NAPI_AUTO_LENGTH, &msg));
262 napi_create_error(env, nullptr, msg, &businessError);
263 napi_set_named_property(env, businessError, "code", code);
264 napi_set_named_property(env, businessError, "message", msg);
265 return businessError;
266 }
267
ConvertToJsDeviceId(const napi_env & env,uint64_t deviceId)268 static napi_value ConvertToJsDeviceId(const napi_env &env, uint64_t deviceId)
269 {
270 napi_value result;
271 if (deviceId > MAX_JS_NUMBER) {
272 NAPI_CALL(env, napi_create_bigint_uint64(env, deviceId, &result));
273 } else {
274 NAPI_CALL(env, napi_create_int64(env, deviceId, &result));
275 }
276 return result;
277 }
278
ThrowErr(const napi_env & env,const int32_t errCode,const std::string & printMsg)279 void ThrowErr(const napi_env &env, const int32_t errCode, const std::string &printMsg)
280 {
281 EDM_LOGE(MODULE_DEV_MGR, "message: %{public}s, code: %{public}d", printMsg.c_str(), errCode);
282 auto msg = GetNapiError(errCode);
283 if (!msg) {
284 EDM_LOGE(MODULE_DEV_MGR, "errCode: %{public}d is invalid", errCode);
285 return;
286 }
287 napi_handle_scope scope = nullptr;
288 napi_open_handle_scope(env, &scope);
289 napi_value error = CreateBusinessError(env, errCode, msg.value());
290 napi_throw(env, error);
291 napi_close_handle_scope(env, scope);
292 }
293
ConvertDeviceToJsDevice(napi_env & env,std::shared_ptr<DeviceData> device)294 static napi_value ConvertDeviceToJsDevice(napi_env& env, std::shared_ptr<DeviceData> device)
295 {
296 napi_value object;
297 napi_value value;
298 NAPI_CALL(env, napi_create_object(env, &object));
299 NAPI_CALL(env, napi_create_int32(env, device->busType, &value));
300 NAPI_CALL(env, napi_set_named_property(env, object, "busType", value));
301 value = ConvertToJsDeviceId(env, device->deviceId);
302 NAPI_CALL(env, napi_set_named_property(env, object, "deviceId", value));
303 NAPI_CALL(env, napi_create_string_utf8(env, device->descripton.c_str(), device->descripton.size(), &value));
304 NAPI_CALL(env, napi_set_named_property(env, object, "description", value));
305 if (device->busType == BusType::BUS_TYPE_USB) {
306 std::shared_ptr<USBDevice> usb = std::static_pointer_cast<USBDevice>(device);
307 NAPI_CALL(env, napi_create_uint32(env, usb->vendorId, &value));
308 NAPI_CALL(env, napi_set_named_property(env, object, "vendorId", value));
309 NAPI_CALL(env, napi_create_uint32(env, usb->productId, &value));
310 NAPI_CALL(env, napi_set_named_property(env, object, "productId", value));
311 }
312
313 return object;
314 }
315
ConvertToJsUSBInterfaceDesc(napi_env & env,std::shared_ptr<USBInterfaceDesc> desc)316 static napi_value ConvertToJsUSBInterfaceDesc(napi_env& env, std::shared_ptr<USBInterfaceDesc> desc)
317 {
318 if (desc == nullptr) {
319 return nullptr;
320 }
321 napi_value object;
322 napi_value value;
323 NAPI_CALL(env, napi_create_object(env, &object));
324 NAPI_CALL(env, napi_create_uint32(env, desc->bInterfaceNumber, &value));
325 NAPI_CALL(env, napi_set_named_property(env, object, "bInterfaceNumber", value));
326 NAPI_CALL(env, napi_create_uint32(env, desc->bClass, &value));
327 NAPI_CALL(env, napi_set_named_property(env, object, "bClass", value));
328 NAPI_CALL(env, napi_create_uint32(env, desc->bSubClass, &value));
329 NAPI_CALL(env, napi_set_named_property(env, object, "bSubClass", value));
330 NAPI_CALL(env, napi_create_uint32(env, desc->bProtocol, &value));
331 NAPI_CALL(env, napi_set_named_property(env, object, "bProtocol", value));
332 return object;
333 }
334
ConvertToJsDeviceInfo(napi_env & env,std::shared_ptr<DeviceInfoData> deviceInfo)335 static napi_value ConvertToJsDeviceInfo(napi_env& env, std::shared_ptr<DeviceInfoData> deviceInfo)
336 {
337 EDM_LOGD(MODULE_DEV_MGR, "ConvertToJsDeviceInfo start");
338 if (deviceInfo == nullptr) {
339 return nullptr;
340 }
341 napi_value object;
342 napi_value value;
343 NAPI_CALL(env, napi_create_object(env, &object));
344 value = ConvertToJsDeviceId(env, deviceInfo->deviceId);
345 NAPI_CALL(env, napi_set_named_property(env, object, "deviceId", value));
346 NAPI_CALL(env, napi_get_boolean(env, deviceInfo->isDriverMatched, &value));
347 NAPI_CALL(env, napi_set_named_property(env, object, "isDriverMatched", value));
348 if (deviceInfo->isDriverMatched) {
349 NAPI_CALL(env, napi_create_string_utf8(env, deviceInfo->driverUid.c_str(),
350 deviceInfo->driverUid.size(), &value));
351 NAPI_CALL(env, napi_set_named_property(env, object, "driverUid", value));
352 }
353 BusType busType = DeviceInfoData::GetBusTypeByDeviceId(deviceInfo->deviceId);
354 if (busType == BusType::BUS_TYPE_USB) {
355 std::shared_ptr<USBDeviceInfoData> usbDeviceInfo = std::static_pointer_cast<USBDeviceInfoData>(deviceInfo);
356 NAPI_CALL(env, napi_create_uint32(env, usbDeviceInfo->vendorId, &value));
357 NAPI_CALL(env, napi_set_named_property(env, object, "vendorId", value));
358 NAPI_CALL(env, napi_create_uint32(env, usbDeviceInfo->productId, &value));
359 NAPI_CALL(env, napi_set_named_property(env, object, "productId", value));
360
361 napi_value interfaceDescList;
362 NAPI_CALL(env, napi_create_array(env, &interfaceDescList));
363 EDM_LOGD(MODULE_DEV_MGR, "interfaceDescList size = %{public}zu", usbDeviceInfo->interfaceDescList.size());
364 for (size_t i = 0; i < usbDeviceInfo->interfaceDescList.size(); i++) {
365 napi_value element = ConvertToJsUSBInterfaceDesc(env, usbDeviceInfo->interfaceDescList[i]);
366 NAPI_CALL(env, napi_set_element(env, interfaceDescList, i, element));
367 }
368 NAPI_CALL(env, napi_set_named_property(env, object, "interfaceDescList", interfaceDescList));
369 }
370 EDM_LOGD(MODULE_DEV_MGR, "ConvertToJsDeviceInfo end");
371 return object;
372 }
373
ConvertToJsDriverInfo(napi_env & env,std::shared_ptr<DriverInfoData> driverInfo)374 static napi_value ConvertToJsDriverInfo(napi_env& env, std::shared_ptr<DriverInfoData> driverInfo)
375 {
376 if (driverInfo == nullptr) {
377 return nullptr;
378 }
379 napi_value object;
380 napi_value value;
381 NAPI_CALL(env, napi_create_object(env, &object));
382 NAPI_CALL(env, napi_create_int32(env, driverInfo->busType, &value));
383 NAPI_CALL(env, napi_set_named_property(env, object, "busType", value));
384 NAPI_CALL(env, napi_create_string_utf8(env, driverInfo->driverUid.c_str(), driverInfo->driverUid.size(), &value));
385 NAPI_CALL(env, napi_set_named_property(env, object, "driverUid", value));
386 NAPI_CALL(env, napi_create_string_utf8(env, driverInfo->driverName.c_str(), driverInfo->driverName.size(), &value));
387 NAPI_CALL(env, napi_set_named_property(env, object, "driverName", value));
388 NAPI_CALL(env, napi_create_string_utf8(env, driverInfo->bundleSize.c_str(), driverInfo->bundleSize.size(), &value));
389 NAPI_CALL(env, napi_set_named_property(env, object, "driverSize", value));
390 NAPI_CALL(env, napi_create_string_utf8(env, driverInfo->version.c_str(), driverInfo->version.size(), &value));
391 NAPI_CALL(env, napi_set_named_property(env, object, "driverVersion", value));
392 NAPI_CALL(env, napi_create_string_utf8(env, driverInfo->description.c_str(),
393 driverInfo->description.size(), &value));
394 NAPI_CALL(env, napi_set_named_property(env, object, "description", value));
395 if (driverInfo->busType == BusType::BUS_TYPE_USB) {
396 std::shared_ptr<USBDriverInfoData> usbDriverInfo = std::static_pointer_cast<USBDriverInfoData>(driverInfo);
397 napi_value pids;
398 NAPI_CALL(env, napi_create_array(env, &pids));
399 for (size_t i = 0; i < usbDriverInfo->pids.size(); i++) {
400 NAPI_CALL(env, napi_create_uint32(env, usbDriverInfo->pids[i], &value));
401 NAPI_CALL(env, napi_set_element(env, pids, i, value));
402 }
403 NAPI_CALL(env, napi_set_named_property(env, object, "productIdList", pids));
404 napi_value vids;
405 NAPI_CALL(env, napi_create_array(env, &vids));
406 for (size_t i = 0; i < usbDriverInfo->vids.size(); i++) {
407 NAPI_CALL(env, napi_create_uint32(env, usbDriverInfo->vids[i], &value));
408 NAPI_CALL(env, napi_set_element(env, vids, i, value));
409 }
410 NAPI_CALL(env, napi_set_named_property(env, object, "vendorIdList", vids));
411 }
412 return object;
413 }
414
QueryDevices(napi_env env,napi_callback_info info)415 static napi_value QueryDevices(napi_env env, napi_callback_info info)
416 {
417 EDM_LOGI(MODULE_DEV_MGR, "queryDevices start");
418 size_t argc = PARAM_COUNT_1;
419 napi_value argv[PARAM_COUNT_1] = {nullptr};
420 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
421
422 int32_t busType = BusType::BUS_TYPE_USB;
423 if (argc > 0 && IsMatchType(env, argv[0], napi_number)) {
424 NAPI_CALL(env, napi_get_value_int32(env, argv[0], &busType));
425 EDM_LOGI(MODULE_DEV_MGR, "bus type is %{public}d", busType);
426 }
427
428 std::vector<std::shared_ptr<DeviceData>> devices;
429 UsbErrCode retCode = g_edmClient.QueryDevice(busType, devices);
430 if (retCode != UsbErrCode::EDM_OK) {
431 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
432 ThrowErr(env, PERMISSION_DENIED, "queryDevice: no permission");
433 } else {
434 ThrowErr(env, SERVICE_EXCEPTION, "Query device service fail");
435 }
436 return nullptr;
437 }
438
439 napi_value resultArray;
440 NAPI_CALL(env, napi_create_array(env, &resultArray));
441 for (size_t index = 0; index < devices.size(); index++) {
442 napi_value element = ConvertDeviceToJsDevice(env, devices[index]);
443 NAPI_CALL(env, napi_set_element(env, resultArray, index, element));
444 }
445 EDM_LOGI(MODULE_DEV_MGR, "query device finish");
446
447 return resultArray;
448 }
449
ParseDeviceId(const napi_env & env,const napi_value & value,uint64_t * deviceId)450 static bool ParseDeviceId(const napi_env& env, const napi_value& value, uint64_t* deviceId)
451 {
452 napi_valuetype type;
453 NAPI_CALL_BASE(env, napi_typeof(env, value, &type), false);
454 if (type == napi_bigint) {
455 bool lossless;
456 NAPI_CALL_BASE(env, napi_get_value_bigint_uint64(env, value, deviceId, &lossless), false);
457 } else if (type == napi_number) {
458 int64_t temp;
459 NAPI_CALL_BASE(env, napi_get_value_int64(env, value, &temp), false);
460 *deviceId = static_cast<uint64_t>(temp);
461 } else {
462 return false;
463 }
464 return true;
465 }
466
BindDevice(napi_env env,napi_callback_info info)467 static napi_value BindDevice(napi_env env, napi_callback_info info)
468 {
469 size_t argc = PARAM_COUNT_3;
470 napi_value argv[PARAM_COUNT_3] = {nullptr};
471 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
472 if (argc < PARAM_COUNT_2) {
473 ThrowErr(env, PARAMETER_ERROR, "bindDevice parameter count not match");
474 return nullptr;
475 }
476
477 uint64_t deviceId;
478 if (!ParseDeviceId(env, argv[0], &deviceId)) {
479 ThrowErr(env, PARAMETER_ERROR, "deviceid type error");
480 return nullptr;
481 }
482 EDM_LOGI(MODULE_DEV_MGR, "Enter bindDevice:%{public}016" PRIX64, deviceId);
483
484 if (!IsMatchType(env, argv[1], napi_function)) {
485 ThrowErr(env, PARAMETER_ERROR, "onDisconnect param is error");
486 return nullptr;
487 }
488
489 std::lock_guard<std::mutex> mapLock(mapMutex);
490 UsbErrCode retCode = g_edmClient.BindDevice(deviceId, g_edmCallback);
491 if (retCode != UsbErrCode::EDM_OK) {
492 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
493 ThrowErr(env, PERMISSION_DENIED, "bindDevice: no permission");
494 } else {
495 ThrowErr(env, SERVICE_EXCEPTION, "bindDevice service failed");
496 }
497 return nullptr;
498 }
499
500 sptr<AsyncData> data = new (std::nothrow) AsyncData {};
501 if (data == nullptr) {
502 ThrowErr(env, PARAMETER_ERROR, "malloc callback data fail");
503 return nullptr;
504 }
505 data->env = env;
506 data->deviceId = deviceId;
507 NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &data->onDisconnect));
508 napi_value promise = nullptr;
509 if (argc > PARAM_COUNT_2 && IsMatchType(env, argv[PARAM_COUNT_2], napi_function)) {
510 NAPI_CALL(env, napi_create_reference(env, argv[PARAM_COUNT_2], 1, &data->bindCallback));
511 } else {
512 NAPI_CALL(env, napi_create_promise(env, &data->bindDeferred, &promise));
513 }
514 g_callbackMap[data->deviceId] = data;
515
516 return promise;
517 }
518
UnbindDevice(napi_env env,napi_callback_info info)519 static napi_value UnbindDevice(napi_env env, napi_callback_info info)
520 {
521 size_t argc = PARAM_COUNT_2;
522 napi_value argv[PARAM_COUNT_2] = {nullptr};
523 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
524 if (argc < PARAM_COUNT_1) {
525 ThrowErr(env, PARAMETER_ERROR, "Param count error");
526 return nullptr;
527 }
528
529 uint64_t deviceId;
530 if (!ParseDeviceId(env, argv[0], &deviceId)) {
531 ThrowErr(env, PARAMETER_ERROR, "deviceid type error");
532 return nullptr;
533 }
534 EDM_LOGI(MODULE_DEV_MGR, "Enter unbindDevice:%{public}016" PRIX64, deviceId);
535
536 UsbErrCode retCode = g_edmClient.UnBindDevice(deviceId);
537 if (retCode != UsbErrCode::EDM_OK) {
538 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
539 ThrowErr(env, PERMISSION_DENIED, "unbindDevice: no permission");
540 } else {
541 ThrowErr(env, SERVICE_EXCEPTION, "unbindDevice service failed");
542 }
543 return nullptr;
544 }
545
546 std::lock_guard<std::mutex> mapLock(mapMutex);
547 if (g_callbackMap.find(deviceId) == g_callbackMap.end()) {
548 ThrowErr(env, SERVICE_EXCEPTION, "Unbind callback does not exist");
549 return nullptr;
550 }
551 auto data = g_callbackMap[deviceId];
552 napi_value promise = nullptr;
553 if (argc > PARAM_COUNT_1 && IsMatchType(env, argv[1], napi_function)) {
554 NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &data->unbindCallback));
555 } else {
556 NAPI_CALL(env, napi_create_promise(env, &data->unbindDeferred, &promise));
557 }
558
559 return promise;
560 }
561
BindDriverWithDeviceId(napi_env env,napi_callback_info info)562 static napi_value BindDriverWithDeviceId(napi_env env, napi_callback_info info)
563 {
564 size_t argc = PARAM_COUNT_3;
565 napi_value argv[PARAM_COUNT_3] = {nullptr};
566 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
567 if (argc < PARAM_COUNT_2) {
568 ThrowErr(env, PARAMETER_ERROR, "bindDriver parameter count not match");
569 return nullptr;
570 }
571
572 uint64_t deviceId;
573 if (!ParseDeviceId(env, argv[0], &deviceId)) {
574 ThrowErr(env, PARAMETER_ERROR, "deviceid type error");
575 return nullptr;
576 }
577 EDM_LOGI(MODULE_DEV_MGR, "Enter bindDriver:%{public}016" PRIX64, deviceId);
578
579 if (!IsMatchType(env, argv[1], napi_function)) {
580 ThrowErr(env, PARAMETER_ERROR, "onDisconnect param is error");
581 return nullptr;
582 }
583
584 std::lock_guard<std::mutex> mapLock(mapMutex);
585 UsbErrCode retCode = g_edmClient.BindDriverWithDeviceId(deviceId, g_edmCallback);
586 if (retCode != UsbErrCode::EDM_OK) {
587 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
588 ThrowErr(env, PERMISSION_DENIED, "bindDriver: no permission");
589 } else if (retCode == UsbErrCode::EDM_ERR_SERVICE_NOT_ALLOW_ACCESS) {
590 ThrowErr(env, SERVICE_NOT_ALLOW_ACCESS,
591 "bindDriver: The driver service does not allow any client to bind.");
592 } else {
593 ThrowErr(env, SERVICE_EXCEPTION_NEW, "bindDriver service failed");
594 }
595 return nullptr;
596 }
597
598 sptr<AsyncData> data = new (std::nothrow) AsyncData {};
599 if (data == nullptr) {
600 ThrowErr(env, PARAMETER_ERROR, "malloc callback data fail");
601 return nullptr;
602 }
603 data->env = env;
604 data->deviceId = deviceId;
605 NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &data->onDisconnect));
606 napi_value promise = nullptr;
607 if (argc > PARAM_COUNT_2 && IsMatchType(env, argv[PARAM_COUNT_2], napi_function)) {
608 NAPI_CALL(env, napi_create_reference(env, argv[PARAM_COUNT_2], 1, &data->bindCallback));
609 } else {
610 NAPI_CALL(env, napi_create_promise(env, &data->bindDeferred, &promise));
611 }
612 g_callbackMap[data->deviceId] = data;
613
614 return promise;
615 }
616
UnbindDriverWithDeviceId(napi_env env,napi_callback_info info)617 static napi_value UnbindDriverWithDeviceId(napi_env env, napi_callback_info info)
618 {
619 size_t argc = PARAM_COUNT_2;
620 napi_value argv[PARAM_COUNT_2] = {nullptr};
621 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
622 if (argc < PARAM_COUNT_1) {
623 ThrowErr(env, PARAMETER_ERROR, "Param count error");
624 return nullptr;
625 }
626
627 uint64_t deviceId;
628 if (!ParseDeviceId(env, argv[0], &deviceId)) {
629 ThrowErr(env, PARAMETER_ERROR, "deviceid type error");
630 return nullptr;
631 }
632 EDM_LOGI(MODULE_DEV_MGR, "Enter unbindDriver:%{public}016" PRIX64, deviceId);
633
634 UsbErrCode retCode = g_edmClient.UnbindDriverWithDeviceId(deviceId);
635 if (retCode != UsbErrCode::EDM_OK) {
636 if (retCode == UsbErrCode::EDM_ERR_NO_PERM) {
637 ThrowErr(env, PERMISSION_DENIED, "unbindDriver: no permission");
638 } else if (retCode == UsbErrCode::EDM_ERR_SERVICE_NOT_BOUND) {
639 ThrowErr(env, SERVICE_NOT_BOUND, "unbindDriver: there is no binding relationship");
640 } else {
641 ThrowErr(env, SERVICE_EXCEPTION_NEW, "unbindDriver service failed");
642 }
643 return nullptr;
644 }
645
646 std::lock_guard<std::mutex> mapLock(mapMutex);
647 if (g_callbackMap.find(deviceId) == g_callbackMap.end()) {
648 ThrowErr(env, SERVICE_EXCEPTION, "Unbind callback does not exist");
649 return nullptr;
650 }
651 auto data = g_callbackMap[deviceId];
652 napi_value promise = nullptr;
653 if (argc > PARAM_COUNT_1 && IsMatchType(env, argv[1], napi_function)) {
654 NAPI_CALL(env, napi_create_reference(env, argv[1], 1, &data->unbindCallback));
655 } else {
656 NAPI_CALL(env, napi_create_promise(env, &data->unbindDeferred, &promise));
657 }
658
659 return promise;
660 }
661
QueryDeviceInfo(napi_env env,napi_callback_info info)662 static napi_value QueryDeviceInfo(napi_env env, napi_callback_info info)
663 {
664 size_t argc = PARAM_COUNT_1;
665 napi_value argv[PARAM_COUNT_1] = {nullptr};
666 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
667
668 uint64_t deviceId = 0;
669 if (argc > PARAM_COUNT_0 && !ParseDeviceId(env, argv[0], &deviceId)) {
670 ThrowErr(env, PARAMETER_ERROR, "deviceId type error");
671 return nullptr;
672 }
673 std::vector<std::shared_ptr<DeviceInfoData>> deviceInfos;
674 int32_t ret;
675 if (argc > PARAM_COUNT_0) {
676 ret = g_edmClient.QueryDeviceInfo(deviceId, deviceInfos);
677 } else {
678 ret = g_edmClient.QueryDeviceInfo(deviceInfos);
679 }
680 if (ret != UsbErrCode::EDM_OK) {
681 if (ret == UsbErrCode::EDM_ERR_NOT_SYSTEM_APP) {
682 ThrowErr(env, PERMISSION_NOT_SYSTEM_APP, "queryDeviceInfo: none system app");
683 } else if (ret == UsbErrCode::EDM_ERR_NO_PERM) {
684 ThrowErr(env, PERMISSION_DENIED, "queryDeviceInfo: no permission");
685 } else {
686 ThrowErr(env, SERVICE_EXCEPTION_NEW, "Query device info service fail");
687 }
688 return nullptr;
689 }
690
691 napi_value resultArray;
692 NAPI_CALL(env, napi_create_array(env, &resultArray));
693 for (size_t i = 0; i < deviceInfos.size(); i++) {
694 napi_value element = ConvertToJsDeviceInfo(env, deviceInfos[i]);
695 NAPI_CALL(env, napi_set_element(env, resultArray, i, element));
696 }
697
698 return resultArray;
699 }
700
QueryDriverInfo(napi_env env,napi_callback_info info)701 static napi_value QueryDriverInfo(napi_env env, napi_callback_info info)
702 {
703 size_t argc = PARAM_COUNT_1;
704 napi_value argv[PARAM_COUNT_1] = {nullptr};
705 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
706 if (argc > PARAM_COUNT_0 && !IsMatchType(env, argv[0], napi_string)) {
707 ThrowErr(env, PARAMETER_ERROR, "driverUid type is invalid");
708 return nullptr;
709 }
710
711 std::vector<std::shared_ptr<DriverInfoData>> driverInfos;
712 int32_t ret;
713 if (argc > PARAM_COUNT_0) {
714 size_t len;
715 NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len));
716 std::string driverUid;
717 driverUid.reserve(len + 1);
718 driverUid.resize(len);
719 NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], &driverUid[0], len + 1, &len));
720 ret = g_edmClient.QueryDriverInfo(driverUid, driverInfos);
721 } else {
722 ret = g_edmClient.QueryDriverInfo(driverInfos);
723 }
724
725 if (ret != UsbErrCode::EDM_OK) {
726 if (ret == UsbErrCode::EDM_ERR_NOT_SYSTEM_APP) {
727 ThrowErr(env, PERMISSION_NOT_SYSTEM_APP, "queryDriverInfo: none system app");
728 } else if (ret == UsbErrCode::EDM_ERR_NO_PERM) {
729 ThrowErr(env, PERMISSION_DENIED, "queryDriverInfo: no permission");
730 } else {
731 ThrowErr(env, SERVICE_EXCEPTION_NEW, "Query driver info service fail");
732 }
733 return nullptr;
734 }
735
736 napi_value resultArray;
737 NAPI_CALL(env, napi_create_array(env, &resultArray));
738 for (size_t index = 0; index < driverInfos.size(); index++) {
739 napi_value element = ConvertToJsDriverInfo(env, driverInfos[index]);
740 NAPI_CALL(env, napi_set_element(env, resultArray, index, element));
741 }
742
743 return resultArray;
744 }
745
EnumBusTypeConstructor(napi_env env,napi_callback_info info)746 static napi_value EnumBusTypeConstructor(napi_env env, napi_callback_info info)
747 {
748 napi_value thisArg = nullptr;
749 void* data = nullptr;
750
751 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data));
752 return thisArg;
753 }
754
CreateEnumBusType(napi_env env,napi_value exports)755 static void CreateEnumBusType(napi_env env, napi_value exports)
756 {
757 napi_value usb = nullptr;
758 napi_create_int32(env, 1, &usb);
759
760 napi_property_descriptor desc[] = {
761 DECLARE_NAPI_STATIC_PROPERTY("USB", usb),
762 };
763
764 napi_value result = nullptr;
765 napi_define_class(env, "BusType", NAPI_AUTO_LENGTH, EnumBusTypeConstructor, nullptr,
766 sizeof(desc) / sizeof(*desc), desc, &result);
767 napi_set_named_property(env, exports, "BusType", result);
768 }
769
770 EXTERN_C_START
771 /*
772 * function for module exports
773 */
ExtDeviceManagerInit(napi_env env,napi_value exports)774 static napi_value ExtDeviceManagerInit(napi_env env, napi_value exports)
775 {
776 napi_property_descriptor desc[] = {
777 DECLARE_NAPI_FUNCTION("queryDevices", QueryDevices),
778 DECLARE_NAPI_FUNCTION("bindDevice", BindDevice),
779 DECLARE_NAPI_FUNCTION("bindDeviceDriver", BindDevice),
780 DECLARE_NAPI_FUNCTION("unbindDevice", UnbindDevice),
781 DECLARE_NAPI_FUNCTION("bindDriverWithDeviceId", BindDriverWithDeviceId),
782 DECLARE_NAPI_FUNCTION("unbindDriverWithDeviceId", UnbindDriverWithDeviceId),
783 DECLARE_NAPI_FUNCTION("queryDeviceInfo", QueryDeviceInfo),
784 DECLARE_NAPI_FUNCTION("queryDriverInfo", QueryDriverInfo),
785 };
786 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
787
788 CreateEnumBusType(env, exports);
789
790 return exports;
791 }
792 EXTERN_C_END
793
794 /*
795 * Module definition
796 */
797 static napi_module g_moduleManager = {
798 .nm_version = 1,
799 .nm_flags = 0,
800 .nm_filename = nullptr,
801 .nm_register_func = ExtDeviceManagerInit,
802 .nm_modname = "driver.deviceManager",
803 .nm_priv = nullptr,
804 .reserved = {nullptr}
805 };
806
807 /*
808 * Module registration
809 */
RegisterModule(void)810 extern "C" __attribute__((constructor)) void RegisterModule(void)
811 {
812 napi_module_register(&g_moduleManager);
813 }
814 }
815 }
816