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