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