• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramType);
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