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, ¶mType);
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 }