1 /*
2  * Copyright (c) 2021-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 
18 #include <sys/time.h>
19 
20 #include <cstdio>
21 #include <cstdlib>
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25 
26 #include "hilog_wrapper.h"
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "napi_common.h"
30 #include "napi_util.h"
31 #include "securec.h"
32 #include "usb_async_context.h"
33 #include "usb_device_pipe.h"
34 #include "usb_endpoint.h"
35 #include "usb_errors.h"
36 #include "usb_napi_errors.h"
37 #include "usb_srv_client.h"
38 
39 using namespace OHOS;
40 using namespace OHOS::USB;
41 using namespace OHOS::HDI::Usb::V1_0;
42 using namespace OHOS::HDI::Usb::V1_1;
43 
44 static constexpr int32_t INDEX_0 = 0;
45 static constexpr int32_t INDEX_1 = 1;
46 static constexpr int32_t INDEX_2 = 2;
47 static constexpr int32_t INDEX_3 = 3;
48 static constexpr int32_t PARAM_COUNT_0 = 0;
49 static constexpr int32_t PARAM_COUNT_1 = 1;
50 static constexpr int32_t PARAM_COUNT_2 = 2;
51 static constexpr int32_t PARAM_COUNT_3 = 3;
52 static constexpr int32_t PARAM_COUNT_4 = 4;
53 static constexpr int32_t STR_DEFAULT_SIZE = 256;
54 static constexpr int32_t DEFAULT_DESCRIPTION_SIZE = 32;
55 
ParseUsbDevicePipe(const napi_env env, const napi_value &obj, USBDevicePipe &pipe)56 static void ParseUsbDevicePipe(const napi_env env, const napi_value &obj, USBDevicePipe &pipe)
57 {
58     napi_valuetype valueType;
59     napi_typeof(env, obj, &valueType);
60     USB_ASSERT_RETURN_VOID(
61         env, valueType == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
62 
63     int32_t busNum = 0;
64     NapiUtil::JsObjectToInt(env, obj, "busNum", busNum);
65     pipe.SetBusNum(static_cast<uint8_t>(busNum));
66     int32_t devAddr = 0;
67     NapiUtil::JsObjectToInt(env, obj, "devAddress", devAddr);
68     pipe.SetDevAddr(static_cast<uint8_t>(devAddr));
69 }
70 
ProcessPromise(const napi_env env, const USBAsyncContext &asyncContext, napi_value &result)71 static void ProcessPromise(const napi_env env, const USBAsyncContext &asyncContext, napi_value &result)
72 {
73     if (asyncContext.deferred) {
74         if (asyncContext.status == napi_ok) {
75             napi_resolve_deferred(env, asyncContext.deferred, result);
76         } else {
77             napi_reject_deferred(env, asyncContext.deferred, result);
78         }
79     }
80 }
81 
CreateUsbDevicePipe(const napi_env env, napi_value &obj, const USBDevicePipe &pipe)82 static void CreateUsbDevicePipe(const napi_env env, napi_value &obj, const USBDevicePipe &pipe)
83 {
84     napi_create_object(env, &obj);
85     NapiUtil::SetValueInt32(env, "busNum", pipe.GetBusNum(), obj);
86     NapiUtil::SetValueInt32(env, "devAddress", pipe.GetDevAddr(), obj);
87 }
88 
CtoJSUsbEndpoint(const napi_env &env, napi_value &obj, const USBEndpoint &usbEndpoint)89 static void CtoJSUsbEndpoint(const napi_env &env, napi_value &obj, const USBEndpoint &usbEndpoint)
90 {
91     napi_create_object(env, &obj);
92     NapiUtil::SetValueUint32(env, "address", usbEndpoint.GetAddress(), obj);
93     NapiUtil::SetValueUint32(env, "attributes", usbEndpoint.GetAttributes(), obj);
94     NapiUtil::SetValueInt32(env, "interval", usbEndpoint.GetInterval(), obj);
95     NapiUtil::SetValueInt32(env, "maxPacketSize", usbEndpoint.GetMaxPacketSize(), obj);
96     NapiUtil::SetValueUint32(env, "direction", usbEndpoint.GetDirection(), obj);
97     NapiUtil::SetValueUint32(env, "number", usbEndpoint.GetEndpointNumber(), obj);
98     NapiUtil::SetValueUint32(env, "type", usbEndpoint.GetType(), obj);
99     NapiUtil::SetValueInt32(env, "interfaceId", usbEndpoint.GetInterfaceId(), obj);
100 }
101 
CtoJSUsbInterface(const napi_env &env, napi_value &obj, const UsbInterface &usbInterface)102 static void CtoJSUsbInterface(const napi_env &env, napi_value &obj, const UsbInterface &usbInterface)
103 {
104     napi_create_object(env, &obj);
105     NapiUtil::SetValueInt32(env, "id", usbInterface.GetId(), obj);
106     NapiUtil::SetValueInt32(env, "protocol", usbInterface.GetProtocol(), obj);
107     NapiUtil::SetValueInt32(env, "clazz", usbInterface.GetClass(), obj);
108     NapiUtil::SetValueInt32(env, "subClass", usbInterface.GetSubClass(), obj);
109     NapiUtil::SetValueInt32(env, "alternateSetting", usbInterface.GetAlternateSetting(), obj);
110     NapiUtil::SetValueUtf8String(env, "name", usbInterface.GetName(), obj);
111 
112     napi_value arr;
113     napi_create_array(env, &arr);
114     for (int32_t i = 0; i < usbInterface.GetEndpointCount(); ++i) {
115         auto usbEndpoint = usbInterface.GetEndpoint(i);
116         if (!usbEndpoint.has_value()) {
117             USB_HILOGE(MODULE_JS_NAPI, "GetEndpoint failed i=%{public}d", i);
118             return;
119         }
120 
121         napi_value objTmp;
122         CtoJSUsbEndpoint(env, objTmp, usbEndpoint.value());
123         napi_set_element(env, arr, i, objTmp);
124     }
125     napi_set_named_property(env, obj, "endpoints", arr);
126 }
127 
CtoJSUsbConfig(const napi_env &env, napi_value &obj, const USBConfig &usbConfig)128 static void CtoJSUsbConfig(const napi_env &env, napi_value &obj, const USBConfig &usbConfig)
129 {
130     napi_create_object(env, &obj);
131     NapiUtil::SetValueInt32(env, "id", usbConfig.GetId(), obj);
132     NapiUtil::SetValueUint32(env, "attributes", usbConfig.GetAttributes(), obj);
133     NapiUtil::SetValueBool(env, "isRemoteWakeup", usbConfig.IsRemoteWakeup(), obj);
134     NapiUtil::SetValueBool(env, "isSelfPowered", usbConfig.IsSelfPowered(), obj);
135     NapiUtil::SetValueInt32(env, "maxPower", usbConfig.GetMaxPower(), obj);
136     NapiUtil::SetValueUtf8String(env, "name", usbConfig.GetName(), obj);
137     napi_value arr;
138     napi_create_array(env, &arr);
139     for (uint32_t i = 0; i < usbConfig.GetInterfaceCount(); ++i) {
140         UsbInterface usbInterface;
141         usbConfig.GetInterface(i, usbInterface);
142         napi_value objTmp;
143         CtoJSUsbInterface(env, objTmp, usbInterface);
144         napi_set_element(env, arr, i, objTmp);
145     }
146     napi_set_named_property(env, obj, "interfaces", arr);
147 }
148 
CtoJSUsbDevice(const napi_env &env, napi_value &obj, const UsbDevice &usbDevice)149 static void CtoJSUsbDevice(const napi_env &env, napi_value &obj, const UsbDevice &usbDevice)
150 {
151     napi_create_object(env, &obj);
152     NapiUtil::SetValueUtf8String(env, "name", usbDevice.GetName(), obj);
153     NapiUtil::SetValueUtf8String(env, "serial", usbDevice.GetmSerial(), obj);
154     NapiUtil::SetValueUtf8String(env, "manufacturerName", usbDevice.GetManufacturerName(), obj);
155     NapiUtil::SetValueUtf8String(env, "productName", usbDevice.GetProductName(), obj);
156     NapiUtil::SetValueUtf8String(env, "version", usbDevice.GetVersion(), obj);
157     NapiUtil::SetValueInt32(env, "vendorId", usbDevice.GetVendorId(), obj);
158     NapiUtil::SetValueInt32(env, "productId", usbDevice.GetProductId(), obj);
159     NapiUtil::SetValueInt32(env, "clazz", usbDevice.GetClass(), obj);
160     NapiUtil::SetValueInt32(env, "subClass", usbDevice.GetSubclass(), obj);
161     NapiUtil::SetValueInt32(env, "protocol", usbDevice.GetProtocol(), obj);
162     NapiUtil::SetValueInt32(env, "devAddress", usbDevice.GetDevAddr(), obj);
163     NapiUtil::SetValueInt32(env, "busNum", usbDevice.GetBusNum(), obj);
164     napi_value arr;
165     napi_create_array(env, &arr);
166     for (int32_t i = 0; i < usbDevice.GetConfigCount(); ++i) {
167         USBConfig usbConfig;
168         usbDevice.GetConfig(i, usbConfig);
169         napi_value objTmp;
170         CtoJSUsbConfig(env, objTmp, usbConfig);
171         napi_set_element(env, arr, i, objTmp);
172     }
173     napi_set_named_property(env, obj, "configs", arr);
174 }
175 
176 static UsbSrvClient &g_usbClient = UsbSrvClient::GetInstance();
177 
178 /* ============================================= Parsers ============================================= */
179 // js to c
ParseEndpointObj(const napi_env env, const napi_value endpointObj, USBEndpoint &ep)180 static void ParseEndpointObj(const napi_env env, const napi_value endpointObj, USBEndpoint &ep)
181 {
182     int32_t address = 0;
183     NapiUtil::JsObjectToInt(env, endpointObj, "address", address);
184     int32_t attributes = 0;
185     NapiUtil::JsObjectToInt(env, endpointObj, "attributes", attributes);
186     int32_t interval = 0;
187     NapiUtil::JsObjectToInt(env, endpointObj, "interval", interval);
188     int32_t maxPacketSize = 0;
189     NapiUtil::JsObjectToInt(env, endpointObj, "maxPacketSize", maxPacketSize);
190     int32_t direction = 0;
191     NapiUtil::JsObjectToInt(env, endpointObj, "direction", direction);
192     USB_ASSERT_RETURN_VOID(env, (direction == USB_ENDPOINT_DIR_IN || direction == USB_ENDPOINT_DIR_OUT),
193         SYSPARAM_INVALID_INPUT, "The interface should have the endpoints property.");
194     int32_t number = 0;
195     NapiUtil::JsObjectToInt(env, endpointObj, "number", number);
196     int32_t type = 0;
197     NapiUtil::JsObjectToInt(env, endpointObj, "type", type);
198     int32_t interfaceId = 0;
199     NapiUtil::JsObjectToInt(env, endpointObj, "interfaceId", interfaceId);
200     ep = USBEndpoint(address, attributes, interval, maxPacketSize);
201     ep.SetInterfaceId(interfaceId);
202 }
203 
ParseEndpointsObjs(const napi_env env, const napi_value interfaceObj, std::vector<USBEndpoint> &eps)204 static bool ParseEndpointsObjs(const napi_env env, const napi_value interfaceObj, std::vector<USBEndpoint> &eps)
205 {
206     napi_value endpointsObjs;
207     bool isGetObjSuccess = NapiUtil::JsObjectGetProperty(env, interfaceObj, "endpoints", endpointsObjs);
208     USB_ASSERT_RETURN_FALSE(
209         env, isGetObjSuccess == true, SYSPARAM_INVALID_INPUT, "The interface should have the endpoints property.");
210 
211     bool result = false;
212     NAPI_CHECK_RETURN_FALSE(napi_is_array(env, endpointsObjs, &result), "Get endpoints type failed");
213     USB_ASSERT_RETURN_FALSE(env, result == true, SYSPARAM_INVALID_INPUT, "The type of endpoints must be array.");
214 
215     uint32_t endpointCount = 0;
216     NAPI_CHECK_RETURN_FALSE(napi_get_array_length(env, endpointsObjs, &endpointCount), "Get array length failed");
217 
218     for (uint32_t k = 0; k < endpointCount; ++k) {
219         napi_value endpointObj;
220         NAPI_CHECK_RETURN_FALSE(napi_get_element(env, endpointsObjs, k, &endpointObj), "Get endpoints element failed");
221         USBEndpoint ep;
222         ParseEndpointObj(env, endpointObj, ep);
223         eps.push_back(ep);
224     }
225 
226     return true;
227 }
228 
229 struct PipeControlParam {
230     int32_t request;
231     int32_t target;
232     uint32_t reqType;
233     int32_t value;
234     int32_t index;
235     uint8_t *data;
236     size_t dataLength;
237 };
238 
ParsePipeControlParam(const napi_env env, const napi_value jsObj, PipeControlParam &controlParam)239 static bool ParsePipeControlParam(const napi_env env, const napi_value jsObj, PipeControlParam &controlParam)
240 {
241     int32_t request = 0;
242     NapiUtil::JsObjectToInt(env, jsObj, "request", request);
243     int32_t target = 0;
244     NapiUtil::JsObjectToInt(env, jsObj, "target", target);
245     uint32_t reqType = 0;
246     NapiUtil::JsObjectToUint(env, jsObj, "reqType", reqType);
247     int32_t value = 0;
248     NapiUtil::JsObjectToInt(env, jsObj, "value", value);
249     int32_t index = 0;
250     NapiUtil::JsObjectToInt(env, jsObj, "index", index);
251 
252     napi_value dataValue;
253     bool hasProperty = NapiUtil::JsObjectGetProperty(env, jsObj, "data", dataValue);
254     USB_ASSERT_RETURN_FALSE(
255         env, hasProperty == true, SYSPARAM_INVALID_INPUT, "The controlParam should have the data property.");
256 
257     uint8_t *data = nullptr;
258     size_t dataLength = 0;
259     size_t offset = 0;
260     NapiUtil::JsUint8ArrayParse(env, dataValue, &data, dataLength, offset);
261     controlParam.request = request;
262     controlParam.target = target;
263     controlParam.reqType = reqType;
264     controlParam.value = value;
265     controlParam.index = index;
266     controlParam.data = data;
267     controlParam.dataLength = dataLength;
268     return true;
269 }
270 
271 struct UsbPipeControlParam {
272     uint32_t reqType;
273     int32_t request;
274     int32_t value;
275     int32_t index;
276     int32_t length;
277     uint8_t *data;
278     size_t dataLength;
279 };
280 
ParseUsbPipeControlParam(const napi_env env, const napi_value jsObj, UsbPipeControlParam &controlParam)281 static void ParseUsbPipeControlParam(const napi_env env, const napi_value jsObj, UsbPipeControlParam &controlParam)
282 {
283     uint32_t reqType = 0;
284     NapiUtil::JsObjectToUint(env, jsObj, "bmRequestType", reqType);
285     int32_t request = 0;
286     NapiUtil::JsObjectToInt(env, jsObj, "bRequest", request);
287     int32_t value = 0;
288     NapiUtil::JsObjectToInt(env, jsObj, "wValue", value);
289     int32_t index = 0;
290     NapiUtil::JsObjectToInt(env, jsObj, "wIndex", index);
291     int32_t length = 0;
292     NapiUtil::JsObjectToInt(env, jsObj, "wLength", length);
293 
294     napi_value dataValue;
295     bool hasProperty = NapiUtil::JsObjectGetProperty(env, jsObj, "data", dataValue);
296     USB_ASSERT_RETURN_VOID(
297         env, hasProperty == true, SYSPARAM_INVALID_INPUT, "The controlParam should have the data property.");
298 
299     uint8_t *data = nullptr;
300     size_t dataLength = 0;
301     size_t offset = 0;
302     NapiUtil::JsUint8ArrayParse(env, dataValue, &data, dataLength, offset);
303     controlParam.reqType = reqType;
304     controlParam.request = request;
305     controlParam.value = value;
306     controlParam.index = index;
307     controlParam.length = length;
308     controlParam.data = data;
309     controlParam.dataLength = dataLength;
310 }
311 
ParseInterfaceObj(const napi_env env, const napi_value interfaceObj, UsbInterface &interface)312 static void ParseInterfaceObj(const napi_env env, const napi_value interfaceObj, UsbInterface &interface)
313 {
314     int32_t id = 0;
315     NapiUtil::JsObjectToInt(env, interfaceObj, "id", id);
316     int32_t protocol = 0;
317     NapiUtil::JsObjectToInt(env, interfaceObj, "protocol", protocol);
318     int32_t clzz = 0;
319     NapiUtil::JsObjectToInt(env, interfaceObj, "clazz", clzz);
320     int32_t subClass = 0;
321     NapiUtil::JsObjectToInt(env, interfaceObj, "subClass", subClass);
322     int32_t alternateSetting = 0;
323     NapiUtil::JsObjectToInt(env, interfaceObj, "alternateSetting", alternateSetting);
324     std::string name;
325     NapiUtil::JsObjectToString(env, interfaceObj, "name", DEFAULT_DESCRIPTION_SIZE, name);
326     std::vector<USBEndpoint> eps;
327 
328     bool ret = ParseEndpointsObjs(env, interfaceObj, eps);
329     if (!ret) {
330         USB_HILOGE(MODULE_JS_NAPI, "Parse endpointers error.");
331         return;
332     }
333 
334     interface = UsbInterface(id, protocol, clzz, subClass, alternateSetting, name, eps);
335 }
336 
ParseInterfacesObjs(const napi_env env, const napi_value configObj, std::vector<UsbInterface> &interfaces)337 static bool ParseInterfacesObjs(const napi_env env, const napi_value configObj, std::vector<UsbInterface> &interfaces)
338 {
339     napi_value interfacesObjs;
340     bool isGetObjSuccess = NapiUtil::JsObjectGetProperty(env, configObj, "interfaces", interfacesObjs);
341     USB_ASSERT_RETURN_FALSE(
342         env, isGetObjSuccess == true, SYSPARAM_INVALID_INPUT, "The config should have the interfaces property.");
343 
344     bool result = false;
345     NAPI_CHECK_RETURN_FALSE(napi_is_array(env, interfacesObjs, &result), "Get interfaces type failed");
346     USB_ASSERT_RETURN_FALSE(env, result == true, SYSPARAM_INVALID_INPUT, "The type of interfaces must be array.");
347 
348     uint32_t interfaceCount = 0;
349     NAPI_CHECK_RETURN_FALSE(napi_get_array_length(env, interfacesObjs, &interfaceCount), "Get array length failed");
350 
351     for (uint32_t i = 0; i < interfaceCount; ++i) {
352         napi_value interfaceObj;
353         NAPI_CHECK_RETURN_FALSE(
354             napi_get_element(env, interfacesObjs, i, &interfaceObj), "Get interfaces element failed");
355 
356         UsbInterface interface;
357         ParseInterfaceObj(env, interfaceObj, interface);
358         interfaces.push_back(interface);
359     }
360 
361     return true;
362 }
363 
ParseConfigObj(const napi_env env, const napi_value configObj, USBConfig &config)364 static void ParseConfigObj(const napi_env env, const napi_value configObj, USBConfig &config)
365 {
366     int32_t id = 0;
367     NapiUtil::JsObjectToInt(env, configObj, "id", id);
368     int32_t attributes = 0;
369     NapiUtil::JsObjectToInt(env, configObj, "attributes", attributes);
370     int32_t maxPower = 0;
371     NapiUtil::JsObjectToInt(env, configObj, "maxPower", maxPower);
372     std::string name;
373     NapiUtil::JsObjectToString(env, configObj, "name", DEFAULT_DESCRIPTION_SIZE, name);
374     bool isRemoteWakeup = false;
375     NapiUtil::JsObjectToBool(env, configObj, "isRemoteWakeup", isRemoteWakeup);
376     bool isSelfPowered = false;
377     NapiUtil::JsObjectToBool(env, configObj, "isSelfPowered", isSelfPowered);
378 
379     std::vector<UsbInterface> interfaces;
380     bool ret = ParseInterfacesObjs(env, configObj, interfaces);
381     if (!ret) {
382         USB_HILOGE(MODULE_JS_NAPI, "Parse interfaces error.");
383         return;
384     }
385 
386     config = USBConfig(id, attributes, name, maxPower, interfaces);
387 }
388 
ParseConfigsObjs(const napi_env env, const napi_value deviceObj, std::vector<USBConfig> &configs)389 static void ParseConfigsObjs(const napi_env env, const napi_value deviceObj, std::vector<USBConfig> &configs)
390 {
391     napi_value configsObj;
392     bool hasProperty = NapiUtil::JsObjectGetProperty(env, deviceObj, "configs", configsObj);
393     USB_ASSERT_RETURN_VOID(
394         env, hasProperty == true, SYSPARAM_INVALID_INPUT, "The device should have the configs property.");
395     napi_valuetype valueType;
396     napi_typeof(env, configsObj, &valueType);
397     USB_ASSERT_RETURN_VOID(
398         env, valueType == napi_object, SYSPARAM_INVALID_INPUT, "The type of configs must be object.");
399 
400     uint32_t configCount = 0;
401     napi_get_array_length(env, configsObj, &configCount);
402     for (uint32_t i = 0; i < configCount; ++i) {
403         napi_value configObj;
404         napi_get_element(env, configsObj, i, &configObj);
405         USBConfig config;
406         ParseConfigObj(env, configObj, config);
407         configs.push_back(config);
408     }
409 }
410 
ParseDeviceObj(const napi_env env, const napi_value deviceObj, UsbDevice &dev)411 static void ParseDeviceObj(const napi_env env, const napi_value deviceObj, UsbDevice &dev)
412 {
413     std::string name;
414     NapiUtil::JsObjectToString(env, deviceObj, "name", DEFAULT_DESCRIPTION_SIZE, name);
415     std::string manufacturerName;
416     NapiUtil::JsObjectToString(env, deviceObj, "manufacturerName", DEFAULT_DESCRIPTION_SIZE, manufacturerName);
417     std::string productName;
418     NapiUtil::JsObjectToString(env, deviceObj, "productName", DEFAULT_DESCRIPTION_SIZE, productName);
419     std::string version;
420     NapiUtil::JsObjectToString(env, deviceObj, "version", DEFAULT_DESCRIPTION_SIZE, version);
421     std::string serial;
422     NapiUtil::JsObjectToString(env, deviceObj, "serial", DEFAULT_DESCRIPTION_SIZE, serial);
423     int32_t devAddr = 0;
424     NapiUtil::JsObjectToInt(env, deviceObj, "devAddress", devAddr);
425     int32_t busNum = 0;
426     NapiUtil::JsObjectToInt(env, deviceObj, "busNum", busNum);
427     int32_t vendorId = 0;
428     NapiUtil::JsObjectToInt(env, deviceObj, "vendorId", vendorId);
429     int32_t productId = 0;
430     NapiUtil::JsObjectToInt(env, deviceObj, "productId", productId);
431     int32_t clazz = 0;
432     NapiUtil::JsObjectToInt(env, deviceObj, "clazz", clazz);
433     int32_t subClass = 0;
434     NapiUtil::JsObjectToInt(env, deviceObj, "subClass", subClass);
435     int32_t protocol = 0;
436     NapiUtil::JsObjectToInt(env, deviceObj, "protocol", protocol);
437     std::vector<USBConfig> configs;
438     ParseConfigsObjs(env, deviceObj, configs);
439     dev = UsbDevice(name, manufacturerName, productName, version, devAddr, busNum, vendorId, productId, clazz, subClass,
440         protocol, configs);
441 }
442 
443 /* ============================================= Usb Core ============================================= */
444 
CoreGetDevices(napi_env env, napi_callback_info info)445 static napi_value CoreGetDevices(napi_env env, napi_callback_info info)
446 {
447     size_t argc = PARAM_COUNT_1;
448     napi_value argv[PARAM_COUNT_1] = {nullptr};
449     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
450     USB_ASSERT(env, (argc == PARAM_COUNT_0), SYSPARAM_INVALID_INPUT, "The function takes no arguments.");
451 
452     std::vector<UsbDevice> deviceList;
453     int32_t ret = g_usbClient.GetDevices(deviceList);
454     napi_value result;
455     if (ret != UEC_OK) {
456         napi_get_undefined(env, &result);
457         USB_HILOGE(MODULE_JS_NAPI, "end call get device failed ret : %{public}d", ret);
458         return result;
459     }
460 
461     napi_create_array(env, &result);
462     int32_t i = 0;
463     for (const auto &ent1 : deviceList) {
464         napi_value element;
465         napi_create_object(env, &element);
466         napi_value device;
467         CtoJSUsbDevice(env, device, ent1);
468         napi_set_element(env, result, i, device);
469         ++i;
470     }
471 
472     return result;
473 }
474 
CoreConnectDevice(napi_env env, napi_callback_info info)475 static napi_value CoreConnectDevice(napi_env env, napi_callback_info info)
476 {
477     size_t argc = PARAM_COUNT_1;
478     napi_value argv[PARAM_COUNT_1] = {nullptr};
479     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
480     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
481 
482     napi_value deviceObj = argv[INDEX_0];
483     napi_valuetype type;
484     NAPI_CHECK(env, napi_typeof(env, deviceObj, &type), "Get deviceObj type failed");
485     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of device must be USBDevice.");
486     UsbDevice dev;
487     ParseDeviceObj(env, deviceObj, dev);
488 
489     USBDevicePipe pipe;
490     int32_t ret = g_usbClient.OpenDevice(dev, pipe);
491     napi_value pipObj = nullptr;
492     if (ret == UEC_OK) {
493         CreateUsbDevicePipe(env, pipObj, pipe);
494     } else if (ret == UEC_SERVICE_PERMISSION_DENIED || ret == UEC_INTERFACE_PERMISSION_DENIED) {
495         ThrowBusinessError(env, USB_DEVICE_PERMISSION_DENIED, "need call requestRight to get the permission");
496     } else {
497         napi_get_undefined(env, &pipObj);
498     }
499 
500     return pipObj;
501 }
502 
DeviceAddRight(napi_env env, napi_callback_info info)503 static napi_value DeviceAddRight(napi_env env, napi_callback_info info)
504 {
505     size_t argc = PARAM_COUNT_2;
506     napi_value argv[PARAM_COUNT_2] = {nullptr};
507     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
508     USB_ASSERT(env, (argc >= PARAM_COUNT_2), SYSPARAM_INVALID_INPUT, "The function at least takes two argument.");
509 
510     napi_valuetype type;
511     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_0], &type), "Get args 1 type failed");
512     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of bundleName must be string.");
513     std::string bundleName;
514     NapiUtil::JsValueToString(env, argv[INDEX_0], STR_DEFAULT_SIZE, bundleName);
515 
516     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_1], &type), "Get args 2 type failed");
517     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of deviceName must be string.");
518     std::string deviceName;
519     NapiUtil::JsValueToString(env, argv[INDEX_1], STR_DEFAULT_SIZE, deviceName);
520 
521     napi_value result;
522     int32_t ret = g_usbClient.AddRight(bundleName, deviceName);
523     USB_HILOGD(MODULE_JS_NAPI, "Device call AddRight ret: %{public}d", ret);
524     if (ret == UEC_OK) {
525         napi_get_boolean(env, true, &result);
526     } else {
527         USB_ASSERT_RETURN_UNDEF(env, (ret != UEC_SERVICE_PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
528         napi_get_boolean(env, false, &result);
529     }
530     return result;
531 }
532 
DeviceAddAccessRight(napi_env env, napi_callback_info info)533 static napi_value DeviceAddAccessRight(napi_env env, napi_callback_info info)
534 {
535     size_t argc = PARAM_COUNT_2;
536     napi_value argv[PARAM_COUNT_2] = {nullptr};
537     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
538     USB_ASSERT(env, (argc >= PARAM_COUNT_2), SYSPARAM_INVALID_INPUT, "The function at least takes two argument.");
539 
540     napi_valuetype type;
541     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_0], &type), "Get args 1 type failed");
542     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of tokenId must be string.");
543     std::string tokenId;
544     NapiUtil::JsValueToString(env, argv[INDEX_0], STR_DEFAULT_SIZE, tokenId);
545 
546     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_1], &type), "Get args 2 type failed");
547     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of deviceName must be string.");
548     std::string deviceName;
549     NapiUtil::JsValueToString(env, argv[INDEX_1], STR_DEFAULT_SIZE, deviceName);
550 
551     napi_value result;
552     int32_t ret = g_usbClient.AddAccessRight(tokenId, deviceName);
553     USB_HILOGD(MODULE_JS_NAPI, "Device call AddRight ret: %{public}d", ret);
554     if (ret == UEC_OK) {
555         napi_get_boolean(env, true, &result);
556     } else {
557         USB_ASSERT_RETURN_UNDEF(env, (ret != UEC_SERVICE_PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
558         napi_get_boolean(env, false, &result);
559     }
560     return result;
561 }
562 
DeviceRemoveRight(napi_env env, napi_callback_info info)563 static napi_value DeviceRemoveRight(napi_env env, napi_callback_info info)
564 {
565     size_t argc = PARAM_COUNT_1;
566     napi_value argv[PARAM_COUNT_1] = {nullptr};
567     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
568     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
569 
570     napi_valuetype type;
571     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_0], &type), "Get args 1 type failed");
572     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of deviceName must be string.");
573     std::string deviceName;
574     NapiUtil::JsValueToString(env, argv[INDEX_0], STR_DEFAULT_SIZE, deviceName);
575 
576     napi_value result;
577     int32_t ret = g_usbClient.RemoveRight(deviceName);
578     USB_HILOGD(MODULE_JS_NAPI, "Device call RemoveRight ret: %{public}d", ret);
579     if (ret == UEC_OK) {
580         napi_get_boolean(env, true, &result);
581     } else {
582         napi_get_boolean(env, false, &result);
583     }
584 
585     return result;
586 }
587 
CoreHasRight(napi_env env, napi_callback_info info)588 static napi_value CoreHasRight(napi_env env, napi_callback_info info)
589 {
590     size_t argc = PARAM_COUNT_1;
591     napi_value args[PARAM_COUNT_1] = {nullptr};
592     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr), "Get call back info failed");
593     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
594 
595     napi_valuetype type;
596     NAPI_CHECK(env, napi_typeof(env, args[INDEX_0], &type), "Get args 1 type failed");
597     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of deviceName must be string");
598     std::string deviceName;
599     NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, deviceName);
600 
601     bool result = g_usbClient.HasRight(deviceName);
602     USB_HILOGD(MODULE_JS_NAPI, "client called result %{public}d", result);
603 
604     napi_value napiValue = nullptr;
605     napi_get_boolean(env, result, &napiValue);
606 
607     return napiValue;
608 }
609 
610 static auto g_requestRightExecute = [](napi_env env, void *data) {
611     USBRightAsyncContext *asyncContext = reinterpret_cast<USBRightAsyncContext *>(data);
612     int32_t ret = g_usbClient.RequestRight(asyncContext->deviceName);
613     if (ret == UEC_OK) {
614         asyncContext->status = napi_ok;
615     } else {
616         asyncContext->status = napi_generic_failure;
617     }
618 };
619 
620 static auto g_requestRightComplete = [](napi_env env, napi_status status, void *data) {
621     USBRightAsyncContext *asyncContext = reinterpret_cast<USBRightAsyncContext *>(data);
622     napi_value queryResult = nullptr;
623     napi_get_boolean(env, asyncContext->status == napi_ok, &queryResult);
624 
625     if (asyncContext->deferred) {
626         napi_resolve_deferred(env, asyncContext->deferred, queryResult);
627     }
628     napi_delete_async_work(env, asyncContext->work);
629     delete asyncContext;
630 };
631 
CoreRequestRight(napi_env env, napi_callback_info info)632 static napi_value CoreRequestRight(napi_env env, napi_callback_info info)
633 {
634     size_t argc = PARAM_COUNT_1;
635     napi_value args[PARAM_COUNT_1] = {nullptr};
636     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr), "Get call back info failed");
637     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
638 
639     napi_valuetype type;
640     NAPI_CHECK(env, napi_typeof(env, args[INDEX_0], &type), "Get args 1 type failed");
641     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of deviceName must be string.");
642     std::string deviceName;
643     NapiUtil::JsValueToString(env, args[INDEX_0], STR_DEFAULT_SIZE, deviceName);
644 
645     auto asyncContext = new (std::nothrow) USBRightAsyncContext();
646     if (asyncContext == nullptr) {
647         USB_HILOGE(MODULE_JS_NAPI, "Create USBRightAsyncContext failed.");
648         return nullptr;
649     }
650 
651     asyncContext->env = env;
652     asyncContext->deviceName = deviceName;
653 
654     napi_value result = nullptr;
655     napi_create_promise(env, &asyncContext->deferred, &result);
656 
657     napi_value resource = nullptr;
658     napi_create_string_utf8(env, "RequestRight", NAPI_AUTO_LENGTH, &resource);
659 
660     napi_create_async_work(env, nullptr, resource, g_requestRightExecute, g_requestRightComplete,
661         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
662     napi_queue_async_work(env, asyncContext->work);
663 
664     return result;
665 }
666 
CoreUsbFunctionsFromString(napi_env env, napi_callback_info info)667 static napi_value CoreUsbFunctionsFromString(napi_env env, napi_callback_info info)
668 {
669     size_t argc = PARAM_COUNT_1;
670     napi_value argv[PARAM_COUNT_1] = {nullptr};
671 
672     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
673     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
674 
675     napi_valuetype type;
676     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_0], &type), "Get args 1 type failed");
677     USB_ASSERT(env, type == napi_string, SYSPARAM_INVALID_INPUT, "The type of funcs must be string.");
678 
679     // get value string argument of napi converted.
680     std::string funcs;
681     NapiUtil::JsValueToString(env, argv[INDEX_0], STR_DEFAULT_SIZE, funcs);
682 
683     int32_t numFuncs = g_usbClient.UsbFunctionsFromString(funcs);
684     USB_HILOGI(MODULE_JS_NAPI, "usb functions from string failed ret = %{public}d", numFuncs);
685     USB_ASSERT_RETURN_UNDEF(env, (numFuncs != UEC_SERVICE_PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
686 
687     napi_value result;
688     napi_create_int32(env, numFuncs, &result);
689 
690     return result;
691 }
692 
CoreUsbFunctionsToString(napi_env env, napi_callback_info info)693 static napi_value CoreUsbFunctionsToString(napi_env env, napi_callback_info info)
694 {
695     size_t argc = PARAM_COUNT_1;
696     napi_value argv[PARAM_COUNT_1] = {nullptr};
697 
698     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
699     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
700 
701     napi_valuetype type;
702     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_0], &type), "Get args 1 type failed");
703     USB_ASSERT(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of funcs must be number.");
704 
705     int32_t funcs;
706     napi_get_value_int32(env, argv[INDEX_0], &funcs);
707     std::string strFuncs = g_usbClient.UsbFunctionsToString(funcs);
708     USB_ASSERT_RETURN_UNDEF(env, (strFuncs != PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
709     napi_value result;
710     napi_create_string_utf8(env, strFuncs.c_str(), NAPI_AUTO_LENGTH, &result);
711 
712     return result;
713 }
714 
715 static auto g_setCurrentFunctionExecute = [](napi_env env, void *data) {
716     USBFunctionAsyncContext *asyncContext = reinterpret_cast<USBFunctionAsyncContext *>(data);
717     int32_t ret = g_usbClient.SetCurrentFunctions(asyncContext->functions);
718     asyncContext->errCode = ret;
719 };
720 
721 static auto g_setCurrentFunctionComplete = [](napi_env env, napi_status status, void *data) {
722     USBFunctionAsyncContext *asyncContext = reinterpret_cast<USBFunctionAsyncContext *>(data);
723     napi_value queryResult = nullptr;
724 
725     if (asyncContext->errCode == UEC_OK) {
726         asyncContext->status = napi_ok;
727         napi_get_boolean(env, true, &queryResult);
728     } else if (asyncContext->errCode == UEC_SERVICE_PERMISSION_DENIED_SYSAPI) {
729         asyncContext->status = napi_generic_failure;
730         queryResult = CreateBusinessError((env), USB_SYSAPI_PERMISSION_DENIED, "");
731     } else if (asyncContext->errCode == UEC_SERVICE_PERMISSION_CHECK_HDC) {
732         asyncContext->status = napi_generic_failure;
733         queryResult = CreateBusinessError((env), USB_HDC_PERMISSION_DENIED, "");
734     } else {
735         asyncContext->status = napi_generic_failure;
736         napi_get_boolean(env, false, &queryResult);
737     }
738     ProcessPromise(env, *asyncContext, queryResult);
739     napi_delete_async_work(env, asyncContext->work);
740     delete asyncContext;
741 };
742 
CoreSetCurrentFunctions(napi_env env, napi_callback_info info)743 static napi_value CoreSetCurrentFunctions(napi_env env, napi_callback_info info)
744 {
745     size_t argc = PARAM_COUNT_1;
746     napi_value argv[PARAM_COUNT_1] = {nullptr};
747 
748     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
749     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
750 
751     napi_valuetype type;
752     NAPI_CHECK(env, napi_typeof(env, argv[INDEX_0], &type), "Get args 1 type failed");
753     USB_ASSERT(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of funcs must be number.");
754 
755     int32_t funcs = 0;
756     napi_get_value_int32(env, argv[INDEX_0], &funcs);
757 
758     auto asyncContext = new (std::nothrow) USBFunctionAsyncContext();
759     if (asyncContext == nullptr) {
760         USB_HILOGE(MODULE_JS_NAPI, "Create USBFunctionAsyncContext failed");
761         return nullptr;
762     }
763 
764     asyncContext->env = env;
765     asyncContext->functions = funcs;
766     napi_value result = nullptr;
767     napi_create_promise(env, &asyncContext->deferred, &result);
768 
769     napi_value resource = nullptr;
770     napi_create_string_utf8(env, "SetCurrentFunctions", NAPI_AUTO_LENGTH, &resource);
771 
772     napi_create_async_work(env, nullptr, resource, g_setCurrentFunctionExecute, g_setCurrentFunctionComplete,
773         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
774     napi_queue_async_work(env, asyncContext->work);
775 
776     return result;
777 }
778 
CoreGetCurrentFunctions(napi_env env, napi_callback_info info)779 static napi_value CoreGetCurrentFunctions(napi_env env, napi_callback_info info)
780 {
781     size_t argc = PARAM_COUNT_1;
782     napi_value argv[PARAM_COUNT_1] = {nullptr};
783     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
784     USB_ASSERT(env, (argc == PARAM_COUNT_0), SYSPARAM_INVALID_INPUT, "The function takes no arguments.");
785 
786     int32_t cfuncs;
787     int32_t ret = g_usbClient.GetCurrentFunctions(cfuncs);
788     napi_value result;
789     USB_HILOGI(MODULE_JS_NAPI, "get current functions failed ret = %{public}d", ret);
790     USB_ASSERT_RETURN_UNDEF(env, (ret != UEC_SERVICE_PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
791 
792     if (ret != UEC_OK) {
793         napi_get_undefined(env, &result);
794         USB_HILOGE(MODULE_JS_NAPI, "end call get ports failed ret : %{public}d", ret);
795         return result;
796     }
797     napi_create_int32(env, cfuncs, &result);
798 
799     return result;
800 }
801 
CoreGetPorts(napi_env env, napi_callback_info info)802 static napi_value CoreGetPorts(napi_env env, napi_callback_info info)
803 {
804     size_t argc = PARAM_COUNT_1;
805     napi_value argv[PARAM_COUNT_1] = {nullptr};
806     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
807     USB_ASSERT(env, (argc == PARAM_COUNT_0), SYSPARAM_INVALID_INPUT, "The function takes no arguments.");
808 
809     std::vector<UsbPort> ports;
810     int32_t ret = g_usbClient.GetPorts(ports);
811     napi_value result;
812     USB_HILOGI(MODULE_JS_NAPI, "get ports failed ret : %{public}d", ret);
813     USB_ASSERT_RETURN_UNDEF(env, (ret != UEC_SERVICE_PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
814 
815     if (ret != UEC_OK) {
816         napi_get_undefined(env, &result);
817         USB_HILOGE(MODULE_JS_NAPI, "end call get ports failed ret : %{public}d", ret);
818         return result;
819     }
820 
821     napi_create_array(env, &result);
822     for (uint32_t i = 0; i < ports.size(); ++i) {
823         napi_value port;
824         napi_create_object(env, &port);
825         NapiUtil::SetValueInt32(env, "id", ports[i].id, port);
826         NapiUtil::SetValueInt32(env, "supportedModes", ports[i].supportedModes, port);
827         napi_value usbPortStatus;
828         napi_create_object(env, &usbPortStatus);
829         NapiUtil::SetValueInt32(env, "currentMode", ports[i].usbPortStatus.currentMode, usbPortStatus);
830         NapiUtil::SetValueInt32(env, "currentPowerRole", ports[i].usbPortStatus.currentPowerRole, usbPortStatus);
831         NapiUtil::SetValueInt32(env, "currentDataRole", ports[i].usbPortStatus.currentDataRole, usbPortStatus);
832         napi_set_named_property(env, port, "status", usbPortStatus);
833         napi_set_element(env, result, i, port);
834     }
835 
836     return result;
837 }
838 
839 /* ============================================= Usb Port ============================================= */
840 
PortGetSupportedModes(napi_env env, napi_callback_info info)841 static napi_value PortGetSupportedModes(napi_env env, napi_callback_info info)
842 {
843     size_t argc = PARAM_COUNT_1;
844     napi_value args[PARAM_COUNT_1] = {nullptr};
845 
846     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr), "Get call back info failed");
847     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
848 
849     napi_valuetype type;
850     NAPI_CHECK(env, napi_typeof(env, args[INDEX_0], &type), "Get args 1 type failed");
851     USB_ASSERT(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of portId must be number.");
852 
853     int32_t id = 0;
854     int32_t result = 0;
855     napi_get_value_int32(env, args[INDEX_0], &id);
856     int32_t ret = g_usbClient.GetSupportedModes(id, result);
857     USB_HILOGI(MODULE_JS_NAPI, "get supported modes failed ret = %{public}d", ret);
858     USB_ASSERT_RETURN_UNDEF(env, (ret != UEC_SERVICE_PERMISSION_DENIED_SYSAPI), USB_SYSAPI_PERMISSION_DENIED, "");
859 
860     if (ret) {
861         USB_HILOGD(MODULE_JS_NAPI, "false ret = %{public}d", ret);
862     }
863     napi_value napiValue = nullptr;
864     NAPI_CHECK(env, napi_create_int32(env, result, &napiValue), "Create int32 failed");
865 
866     return napiValue;
867 }
868 
869 static auto g_setPortRoleExecute = [](napi_env env, void *data) {
870     USBPortRoleAsyncContext *asyncContext = reinterpret_cast<USBPortRoleAsyncContext *>(data);
871     int32_t ret = g_usbClient.SetPortRole(asyncContext->portId, asyncContext->powerRole, asyncContext->dataRole);
872     asyncContext->errCode = ret;
873 };
874 
875 static auto g_setPortRoleComplete = [](napi_env env, napi_status status, void *data) {
876     USBPortRoleAsyncContext *asyncContext = reinterpret_cast<USBPortRoleAsyncContext *>(data);
877     napi_value queryResult = nullptr;
878 
879     if (asyncContext->errCode == UEC_OK) {
880         asyncContext->status = napi_ok;
881         napi_get_boolean(env, true, &queryResult);
882     } else if (asyncContext->errCode == UEC_SERVICE_PERMISSION_DENIED_SYSAPI) {
883         asyncContext->status = napi_generic_failure;
884         queryResult = CreateBusinessError((env), USB_SYSAPI_PERMISSION_DENIED, "");
885     } else if (asyncContext->errCode == UEC_SERVICE_NOT_SUPPORT_SWITCH_PORT) {
886         asyncContext->status = napi_generic_failure;
887         queryResult = CreateBusinessError((env), USB_NOT_SUPPORT_SWITCH_PORT, "");
888     } else {
889         asyncContext->status = napi_generic_failure;
890         napi_get_boolean(env, false, &queryResult);
891     }
892     ProcessPromise(env, *asyncContext, queryResult);
893     napi_delete_async_work(env, asyncContext->work);
894     delete asyncContext;
895 };
896 
PortSetPortRole(napi_env env, napi_callback_info info)897 static napi_value PortSetPortRole(napi_env env, napi_callback_info info)
898 {
899     size_t argc = PARAM_COUNT_3;
900     napi_value args[PARAM_COUNT_3] = {nullptr};
901 
902     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr), "Get call back info failed");
903     USB_ASSERT(env, (argc >= PARAM_COUNT_3), SYSPARAM_INVALID_INPUT, "The function at least takes three arguments.");
904 
905     napi_valuetype type;
906     NAPI_CHECK(env, napi_typeof(env, args[INDEX_0], &type), "Get args 1 type failed");
907     USB_ASSERT(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of portId must be number.");
908     NAPI_CHECK(env, napi_typeof(env, args[INDEX_1], &type), "Get args 2 type failed");
909     USB_ASSERT(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of powerRole must be number.");
910     NAPI_CHECK(env, napi_typeof(env, args[INDEX_2], &type), "Get args 3 type failed");
911     USB_ASSERT(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of dataRole must be number.");
912 
913     int32_t id = 0;
914     napi_get_value_int32(env, args[INDEX_0], &id);
915     int32_t powerRole = 0;
916     napi_get_value_int32(env, args[INDEX_1], &powerRole);
917     int32_t dataRole = 0;
918     napi_get_value_int32(env, args[INDEX_2], &dataRole);
919 
920     auto asyncContext = new (std::nothrow) USBPortRoleAsyncContext();
921     if (asyncContext == nullptr) {
922         USB_HILOGE(MODULE_JS_NAPI, "Create USBPortRoleAsyncContext failed");
923         return nullptr;
924     }
925 
926     asyncContext->env = env;
927     asyncContext->portId = id;
928     asyncContext->dataRole = dataRole;
929     asyncContext->powerRole = powerRole;
930 
931     napi_value result = nullptr;
932     napi_create_promise(env, &asyncContext->deferred, &result);
933 
934     napi_value resource = nullptr;
935     napi_create_string_utf8(env, "PortSetPortRole", NAPI_AUTO_LENGTH, &resource);
936 
937     napi_create_async_work(env, nullptr, resource, g_setPortRoleExecute, g_setPortRoleComplete,
938         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
939     napi_queue_async_work(env, asyncContext->work);
940 
941     return result;
942 }
943 
PipeClaimInterface(napi_env env, napi_callback_info info)944 static napi_value PipeClaimInterface(napi_env env, napi_callback_info info)
945 {
946     size_t argc = PARAM_COUNT_3;
947     napi_value argv[PARAM_COUNT_3] = {nullptr};
948 
949     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
950     USB_ASSERT(env, (argc >= PARAM_COUNT_2), SYSPARAM_INVALID_INPUT,
951         "The function at least takes two arguments.");
952 
953     napi_value obj = argv[INDEX_0];
954     napi_valuetype type;
955     napi_typeof(env, obj, &type);
956     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
957 
958     USBDevicePipe pipe;
959     ParseUsbDevicePipe(env, obj, pipe);
960 
961     UsbInterface interface;
962     napi_value obj2 = argv[INDEX_1];
963     napi_typeof(env, obj2, &type);
964     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of iface must be USBInterface.");
965     ParseInterfaceObj(env, obj2, interface);
966 
967     bool isForce = false;
968     if (argc >= PARAM_COUNT_3) {
969         napi_typeof(env, argv[INDEX_2], &type);
970         if (type == napi_boolean) {
971             napi_get_value_bool(env, argv[INDEX_2], &isForce);
972         } else {
973             USB_HILOGW(MODULE_JS_NAPI, "The type of force must be boolean.");
974         }
975     }
976 
977     int32_t ret = pipe.ClaimInterface(interface, isForce);
978     USB_HILOGD(MODULE_JS_NAPI, "pipe call ClaimInterface ret: %{public}d", ret);
979     napi_value result;
980     napi_create_int32(env, ret, &result);
981 
982     return result;
983 }
984 
PipeReleaseInterface(napi_env env, napi_callback_info info)985 static napi_value PipeReleaseInterface(napi_env env, napi_callback_info info)
986 {
987     size_t argc = PARAM_COUNT_2;
988     napi_value argv[PARAM_COUNT_2] = {nullptr};
989 
990     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
991     USB_ASSERT(env, (argc >= PARAM_COUNT_2), SYSPARAM_INVALID_INPUT, "The function at least takes two arguments.");
992 
993     napi_value obj = argv[INDEX_0];
994     napi_valuetype type;
995     napi_typeof(env, obj, &type);
996     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
997 
998     USBDevicePipe pipe;
999     ParseUsbDevicePipe(env, obj, pipe);
1000 
1001     UsbInterface interface;
1002     napi_value obj2 = argv[INDEX_1];
1003     napi_typeof(env, obj2, &type);
1004     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of iface must be USBInterface.");
1005     ParseInterfaceObj(env, obj2, interface);
1006     int32_t ret = pipe.ReleaseInterface(interface);
1007     USB_HILOGD(MODULE_JS_NAPI, "pipe call PipeReleaseInterface ret: %{public}d", ret);
1008     napi_value result;
1009     napi_create_int32(env, ret, &result);
1010 
1011     return result;
1012 }
1013 
PipeSetInterface(napi_env env, napi_callback_info info)1014 static napi_value PipeSetInterface(napi_env env, napi_callback_info info)
1015 {
1016     size_t argc = PARAM_COUNT_2;
1017     napi_value argv[PARAM_COUNT_2] = {nullptr};
1018     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
1019     USB_ASSERT(env, (argc >= PARAM_COUNT_2), SYSPARAM_INVALID_INPUT, "The function at least takes two arguments.");
1020 
1021     napi_value pipeObj = argv[INDEX_0];
1022     napi_valuetype type;
1023     napi_typeof(env, pipeObj, &type);
1024     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1025 
1026     USBDevicePipe pipe;
1027     ParseUsbDevicePipe(env, pipeObj, pipe);
1028 
1029     napi_value interfaceObj = argv[INDEX_1];
1030     napi_typeof(env, interfaceObj, &type);
1031     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of iface must be USBInterface.");
1032 
1033     UsbInterface interface;
1034     ParseInterfaceObj(env, interfaceObj, interface);
1035     int32_t ret = g_usbClient.SetInterface(pipe, interface);
1036     napi_value result;
1037     napi_create_int32(env, ret, &result);
1038 
1039     return result;
1040 }
1041 
PipeSetConfiguration(napi_env env, napi_callback_info info)1042 static napi_value PipeSetConfiguration(napi_env env, napi_callback_info info)
1043 {
1044     size_t argc = PARAM_COUNT_2;
1045     napi_value argv[PARAM_COUNT_2] = {nullptr};
1046     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
1047     USB_ASSERT(env, (argc >= PARAM_COUNT_2), SYSPARAM_INVALID_INPUT, "The function at least takes two arguments.");
1048 
1049     napi_valuetype type;
1050     napi_value pipeObj = argv[INDEX_0];
1051 
1052     napi_typeof(env, pipeObj, &type);
1053     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1054     USBDevicePipe pipe;
1055     ParseUsbDevicePipe(env, pipeObj, pipe);
1056 
1057     napi_value configObj = argv[INDEX_1];
1058     napi_typeof(env, configObj, &type);
1059     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of config must be USBConfig.");
1060     USBConfig config;
1061     ParseConfigObj(env, configObj, config);
1062 
1063     int32_t ret = g_usbClient.SetConfiguration(pipe, config);
1064     napi_value result;
1065     napi_create_int32(env, ret, &result);
1066 
1067     return result;
1068 }
1069 
PipeGetRawDescriptors(napi_env env, napi_callback_info info)1070 static napi_value PipeGetRawDescriptors(napi_env env, napi_callback_info info)
1071 {
1072     size_t argc = PARAM_COUNT_1;
1073     napi_value argv[PARAM_COUNT_1] = {nullptr};
1074 
1075     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
1076     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
1077     napi_value obj = argv[INDEX_0];
1078     napi_valuetype type;
1079     napi_typeof(env, obj, &type);
1080     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1081 
1082     USBDevicePipe pipe;
1083     ParseUsbDevicePipe(env, obj, pipe);
1084 
1085     napi_value result;
1086     std::vector<uint8_t> bufferData;
1087     int32_t ret = g_usbClient.GetRawDescriptors(pipe, bufferData);
1088     if (ret == UEC_OK) {
1089         NapiUtil::Uint8ArrayToJsValue(env, bufferData, bufferData.size(), result);
1090     } else {
1091         napi_get_undefined(env, &result);
1092     }
1093 
1094     return result;
1095 }
1096 
PipeGetFileDescriptor(napi_env env, napi_callback_info info)1097 static napi_value PipeGetFileDescriptor(napi_env env, napi_callback_info info)
1098 {
1099     size_t argc = PARAM_COUNT_1;
1100     napi_value argv[PARAM_COUNT_1] = {nullptr};
1101 
1102     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
1103     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function at least takes one argument.");
1104     napi_value obj = argv[INDEX_0];
1105     napi_valuetype type;
1106     napi_typeof(env, obj, &type);
1107     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1108 
1109     USBDevicePipe pipe;
1110     ParseUsbDevicePipe(env, obj, pipe);
1111 
1112     int32_t fd = -1;
1113     napi_value result;
1114     g_usbClient.GetFileDescriptor(pipe, fd);
1115     napi_create_int32(env, fd, &result);
1116 
1117     return result;
1118 }
1119 
1120 static auto g_controlTransferExecute = [](napi_env env, void *data) {
1121     USBControlTransferAsyncContext *asyncContext = (USBControlTransferAsyncContext *)data;
1122     std::vector<uint8_t> bufferData(asyncContext->buffer, asyncContext->buffer + asyncContext->bufferLength);
1123     if ((asyncContext->reqType & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_OUT) {
1124         delete[] asyncContext->buffer;
1125         asyncContext->buffer = nullptr;
1126     }
1127 
1128     const UsbCtrlTransfer tctrl = {
1129         asyncContext->reqType, asyncContext->request, asyncContext->value, asyncContext->index, asyncContext->timeOut};
1130     int32_t ret;
1131     do {
1132         ret = asyncContext->pipe.ControlTransfer(tctrl, bufferData);
1133         if (ret != UEC_OK) {
1134             USB_HILOGE(MODULE_JS_NAPI, "ControlTransferExecute failed");
1135             break;
1136         }
1137 
1138         if ((asyncContext->reqType & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_IN) {
1139             ret = memcpy_s(asyncContext->buffer, asyncContext->bufferLength, bufferData.data(), bufferData.size());
1140         }
1141     } while (0);
1142 
1143     if (ret == UEC_OK) {
1144         asyncContext->status = napi_ok;
1145         asyncContext->dataSize = bufferData.size();
1146     } else {
1147         asyncContext->status = napi_generic_failure;
1148         asyncContext->dataSize = 0;
1149     }
1150 };
1151 
1152 static auto g_controlTransferComplete = [](napi_env env, napi_status status, void *data) {
1153     USBControlTransferAsyncContext *asyncContext = reinterpret_cast<USBControlTransferAsyncContext *>(data);
1154     napi_value queryResult = nullptr;
1155 
1156     if (asyncContext->status == napi_ok) {
1157         napi_create_int32(env, asyncContext->dataSize, &queryResult);
1158     } else {
1159         USB_HILOGD(MODULE_JS_NAPI, "ControlTransfer failed");
1160         napi_create_int32(env, -1, &queryResult);
1161     }
1162     if (asyncContext->deferred) {
1163         napi_resolve_deferred(env, asyncContext->deferred, queryResult);
1164     }
1165     napi_delete_async_work(env, asyncContext->work);
1166     delete asyncContext;
1167 };
1168 
GetControlTransferParam( napi_env env, napi_callback_info info)1169 static std::tuple<bool, USBDevicePipe, PipeControlParam, int32_t> GetControlTransferParam(
1170     napi_env env, napi_callback_info info)
1171 {
1172     size_t argc = PARAM_COUNT_3;
1173     napi_value argv[PARAM_COUNT_3] = {nullptr};
1174     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1175     if (status != napi_ok) {
1176         USB_HILOGE(MODULE_JS_NAPI, "ControlTransfer failed to get cb info");
1177         return {false, {}, {}, {}};
1178     }
1179 
1180     if (argc < PARAM_COUNT_2) {
1181         USB_HILOGE(MODULE_JS_NAPI, "The function at least takes two arguments.");
1182         ThrowBusinessError(env, SYSPARAM_INVALID_INPUT, "The function at least takes two arguments.");
1183         return {false, {}, {}, {}};
1184     }
1185 
1186     // pipe param
1187     napi_valuetype type;
1188     napi_typeof(env, argv[INDEX_0], &type);
1189     if (type != napi_object) {
1190         USB_HILOGE(MODULE_JS_NAPI, "index 0 wrong argument type, object expected.");
1191         ThrowBusinessError(env, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1192         return {false, {}, {}, {}};
1193     }
1194 
1195     USBDevicePipe pipe;
1196     ParseUsbDevicePipe(env, argv[INDEX_0], pipe);
1197 
1198     // control params
1199     PipeControlParam controlParam = {0};
1200     bool ret = ParsePipeControlParam(env, argv[INDEX_1], controlParam);
1201     if (!ret) {
1202         USB_HILOGE(MODULE_JS_NAPI, "index 1 wrong argument type, object expected.");
1203         return {false, {}, {}, {}};
1204     }
1205 
1206     // timeOut param
1207     int32_t timeOut = 0;
1208     if (argc > PARAM_COUNT_2) {
1209         napi_typeof(env, argv[INDEX_2], &type);
1210         if (type == napi_number) {
1211             napi_get_value_int32(env, argv[INDEX_2], &timeOut);
1212         } else {
1213             USB_HILOGW(MODULE_JS_NAPI, "index 2 wrong argument type, number expected.");
1214         }
1215     }
1216 
1217     return {true, pipe, controlParam, timeOut};
1218 }
1219 
PipeControlTransfer(napi_env env, napi_callback_info info)1220 static napi_value PipeControlTransfer(napi_env env, napi_callback_info info)
1221 {
1222     auto [res, pipe, controlParam, timeOut] = GetControlTransferParam(env, info);
1223     if (!res) {
1224         USB_HILOGE(MODULE_JS_NAPI, "GetControlTransferParam failed.");
1225         return nullptr;
1226     }
1227 
1228     auto asyncContext = new (std::nothrow) USBControlTransferAsyncContext();
1229     if (asyncContext == nullptr) {
1230         USB_HILOGE(MODULE_JS_NAPI, "New USBControlTransferAsyncContext failed.");
1231         return nullptr;
1232     }
1233 
1234     asyncContext->env = env;
1235     asyncContext->pipe = pipe;
1236     asyncContext->request = controlParam.request;
1237     asyncContext->target = controlParam.target;
1238     asyncContext->reqType = controlParam.reqType;
1239     asyncContext->value = controlParam.value;
1240     asyncContext->index = controlParam.index;
1241 
1242     if ((asyncContext->reqType & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_OUT) {
1243         uint8_t *nativeArrayBuffer = new (std::nothrow) uint8_t[controlParam.dataLength];
1244         if (nativeArrayBuffer == nullptr) {
1245             USB_HILOGE(MODULE_JS_NAPI, "new failed");
1246             delete asyncContext;
1247             return nullptr;
1248         }
1249 
1250         errno_t ret = memcpy_s(nativeArrayBuffer, controlParam.dataLength, controlParam.data, controlParam.dataLength);
1251         if (ret != EOK) {
1252             USB_HILOGE(MODULE_JS_NAPI, "memcpy_s failed");
1253             delete asyncContext;
1254             delete[] nativeArrayBuffer;
1255             return nullptr;
1256         }
1257         asyncContext->buffer = nativeArrayBuffer;
1258     } else {
1259         asyncContext->buffer = controlParam.data;
1260     }
1261 
1262     asyncContext->bufferLength = controlParam.dataLength;
1263     asyncContext->timeOut = timeOut;
1264     napi_value result = nullptr;
1265     napi_create_promise(env, &asyncContext->deferred, &result);
1266 
1267     napi_value resource = nullptr;
1268     napi_create_string_utf8(env, "PipeControlTransfer", NAPI_AUTO_LENGTH, &resource);
1269 
1270     napi_create_async_work(env, nullptr, resource, g_controlTransferExecute, g_controlTransferComplete,
1271         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
1272     napi_queue_async_work(env, asyncContext->work);
1273 
1274     return result;
1275 }
1276 
1277 static auto g_usbControlTransferExecute = [](napi_env env, void *data) {
1278     USBDeviceControlTransferAsyncContext *asyncContext = (USBDeviceControlTransferAsyncContext *)data;
1279     std::vector<uint8_t> bufferData(asyncContext->buffer, asyncContext->buffer + asyncContext->bufferLength);
1280     if ((asyncContext->reqType & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_OUT && asyncContext->buffer != nullptr) {
1281         delete[] asyncContext->buffer;
1282         asyncContext->buffer = nullptr;
1283     }
1284 
1285     const UsbCtrlTransferParams tctrl = {asyncContext->reqType, asyncContext->request,
1286         asyncContext->value, asyncContext->index, asyncContext->length, asyncContext->timeOut};
1287     int32_t ret;
1288     do {
1289         ret = asyncContext->pipe.UsbControlTransfer(tctrl, bufferData);
1290         if (ret != UEC_OK) {
1291             USB_HILOGE(MODULE_JS_NAPI, "ControlTransferExecute failed");
1292             break;
1293         }
1294 
1295         if ((asyncContext->reqType & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_IN) {
1296             ret = memcpy_s(asyncContext->buffer, asyncContext->bufferLength, bufferData.data(), bufferData.size());
1297         }
1298     } while (0);
1299 
1300     if (ret == UEC_OK) {
1301         asyncContext->status = napi_ok;
1302         asyncContext->dataSize = bufferData.size();
1303     } else {
1304         asyncContext->status = napi_generic_failure;
1305         asyncContext->dataSize = 0;
1306     }
1307 };
1308 
1309 static auto g_usbControlTransferComplete = [](napi_env env, napi_status status, void *data) {
1310     USBDeviceControlTransferAsyncContext *asyncContext = reinterpret_cast<USBDeviceControlTransferAsyncContext *>(data);
1311     napi_value queryResult = nullptr;
1312 
1313     if (asyncContext->status == napi_ok) {
1314         napi_create_int32(env, asyncContext->dataSize, &queryResult);
1315     } else {
1316         USB_HILOGD(MODULE_JS_NAPI, "usbControlTransfer failed");
1317         napi_create_int32(env, -1, &queryResult);
1318     }
1319     if (asyncContext->deferred) {
1320         napi_resolve_deferred(env, asyncContext->deferred, queryResult);
1321     }
1322     napi_delete_async_work(env, asyncContext->work);
1323     delete asyncContext;
1324 };
1325 
GetUsbControlTransferParam( napi_env env, napi_callback_info info)1326 static std::tuple<bool, USBDevicePipe, UsbPipeControlParam, int32_t> GetUsbControlTransferParam(
1327     napi_env env, napi_callback_info info)
1328 {
1329     size_t argc = PARAM_COUNT_3;
1330     napi_value argv[PARAM_COUNT_3] = {nullptr};
1331     napi_status status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1332     if (status != napi_ok) {
1333         USB_HILOGE(MODULE_JS_NAPI, "ControlTransfer failed to get cb info");
1334         return {false, {}, {}, {}};
1335     }
1336 
1337     if (argc < PARAM_COUNT_2) {
1338         USB_HILOGE(MODULE_JS_NAPI, "The function at least takes two arguments.");
1339         ThrowBusinessError(env, SYSPARAM_INVALID_INPUT, "The function at least takes two arguments.");
1340         return {false, {}, {}, {}};
1341     }
1342 
1343     // pipe param
1344     napi_valuetype type;
1345     napi_typeof(env, argv[INDEX_0], &type);
1346     if (type != napi_object) {
1347         USB_HILOGE(MODULE_JS_NAPI, "index 0 wrong argument type, object expected.");
1348         ThrowBusinessError(env, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1349         return {false, {}, {}, {}};
1350     }
1351 
1352     USBDevicePipe pipe;
1353     ParseUsbDevicePipe(env, argv[INDEX_0], pipe);
1354 
1355     // control params
1356     napi_typeof(env, argv[INDEX_1], &type);
1357     if (type != napi_object) {
1358         USB_HILOGE(MODULE_JS_NAPI, "index 1 wrong argument type, object expected.");
1359         ThrowBusinessError(env, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDeviceRequestParams.");
1360         return {false, {}, {}, {}};
1361     }
1362 
1363     UsbPipeControlParam controlParam = {0};
1364     ParseUsbPipeControlParam(env, argv[INDEX_1], controlParam);
1365 
1366     // timeOut param
1367     int32_t timeOut = 0;
1368     if (argc > PARAM_COUNT_2) {
1369         napi_typeof(env, argv[INDEX_2], &type);
1370         if (type == napi_number) {
1371             napi_get_value_int32(env, argv[INDEX_2], &timeOut);
1372         } else {
1373             USB_HILOGW(MODULE_JS_NAPI, "index 2 wrong argument type, number expected.");
1374         }
1375     }
1376 
1377     return {true, pipe, controlParam, timeOut};
1378 }
1379 
PipeUsbControlTransfer(napi_env env, napi_callback_info info)1380 static napi_value PipeUsbControlTransfer(napi_env env, napi_callback_info info)
1381 {
1382     auto [res, pipe, controlParam, timeOut] = GetUsbControlTransferParam(env, info);
1383     if (!res) {
1384         USB_HILOGE(MODULE_JS_NAPI, "GetUsbControlTransferParam failed.");
1385         return nullptr;
1386     }
1387 
1388     auto asyncContext = new (std::nothrow) USBDeviceControlTransferAsyncContext();
1389     if (asyncContext == nullptr) {
1390         USB_HILOGE(MODULE_JS_NAPI, "New USBDeviceControlTransferAsyncContext failed.");
1391         return nullptr;
1392     }
1393 
1394     asyncContext->env = env;
1395     asyncContext->pipe = pipe;
1396     asyncContext->reqType = controlParam.reqType;
1397     asyncContext->request = controlParam.request;
1398     asyncContext->value = controlParam.value;
1399     asyncContext->index = controlParam.index;
1400     asyncContext->length = controlParam.length;
1401 
1402     if ((asyncContext->reqType & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_DIR_OUT) {
1403         uint8_t *nativeArrayBuffer = new (std::nothrow) uint8_t[controlParam.dataLength];
1404         if (nativeArrayBuffer == nullptr) {
1405             USB_HILOGE(MODULE_JS_NAPI, "new failed");
1406             delete asyncContext;
1407             return nullptr;
1408         }
1409 
1410         errno_t ret = memcpy_s(nativeArrayBuffer, controlParam.dataLength, controlParam.data, controlParam.dataLength);
1411         if (ret != EOK) {
1412             USB_HILOGE(MODULE_JS_NAPI, "memcpy_s failed");
1413             delete asyncContext;
1414             delete[] nativeArrayBuffer;
1415             return nullptr;
1416         }
1417         asyncContext->buffer = nativeArrayBuffer;
1418     } else {
1419         asyncContext->buffer = controlParam.data;
1420     }
1421 
1422     asyncContext->bufferLength = controlParam.dataLength;
1423     asyncContext->timeOut = timeOut;
1424     napi_value result = nullptr;
1425     napi_create_promise(env, &asyncContext->deferred, &result);
1426 
1427     napi_value resource = nullptr;
1428     napi_create_string_utf8(env, "PipeUsbControlTransfer", NAPI_AUTO_LENGTH, &resource);
1429 
1430     napi_create_async_work(env, nullptr, resource, g_usbControlTransferExecute, g_usbControlTransferComplete,
1431         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
1432     napi_queue_async_work(env, asyncContext->work);
1433 
1434     return result;
1435 }
1436 
1437 static auto g_bulkTransferExecute = [](napi_env env, void *data) {
1438     USBBulkTransferAsyncContext *asyncContext = reinterpret_cast<USBBulkTransferAsyncContext *>(data);
1439     std::vector<uint8_t> bufferData(asyncContext->buffer, asyncContext->buffer + asyncContext->bufferLength);
1440     if (asyncContext->endpoint.GetDirection() == USB_ENDPOINT_DIR_OUT) {
1441         delete[] asyncContext->buffer;
1442         asyncContext->buffer = nullptr;
1443     }
1444 
1445     int32_t ret;
1446     do {
1447         ret = asyncContext->pipe.BulkTransfer(asyncContext->endpoint, bufferData, asyncContext->timeOut);
1448         if (ret != UEC_OK) {
1449             USB_HILOGE(MODULE_JS_NAPI, "ControlTransferExecute failed");
1450             break;
1451         }
1452 
1453         if (asyncContext->endpoint.GetDirection() == USB_ENDPOINT_DIR_IN) {
1454             ret = memcpy_s(asyncContext->buffer, asyncContext->bufferLength, bufferData.data(), bufferData.size());
1455         }
1456     } while (0);
1457 
1458     USB_HILOGD(MODULE_JS_NAPI, "call pipe result %{public}d", ret);
1459     if (ret == UEC_OK) {
1460         asyncContext->status = napi_ok;
1461         asyncContext->dataSize = bufferData.size();
1462     } else {
1463         asyncContext->status = napi_generic_failure;
1464         asyncContext->dataSize = 0;
1465     }
1466 };
1467 
1468 static auto g_bulkTransferComplete = [](napi_env env, napi_status status, void *data) {
1469     USBBulkTransferAsyncContext *asyncContext = reinterpret_cast<USBBulkTransferAsyncContext *>(data);
1470     napi_value queryResult = nullptr;
1471     if (asyncContext->status == napi_ok) {
1472         napi_create_int32(env, asyncContext->dataSize, &queryResult);
1473     } else {
1474         USB_HILOGE(MODULE_JS_NAPI, "BulkTransfer failed");
1475         napi_create_int32(env, -1, &queryResult);
1476     }
1477     if (asyncContext->deferred) {
1478         napi_resolve_deferred(env, asyncContext->deferred, queryResult);
1479     }
1480     napi_delete_async_work(env, asyncContext->work);
1481     delete asyncContext;
1482 };
1483 
GetDescriptorOnBulkTransferParam(napi_env env, napi_value data, USBBulkTransferAsyncContext &asyncContext, const USBEndpoint &ep)1484 static bool GetDescriptorOnBulkTransferParam(napi_env env, napi_value data,
1485     USBBulkTransferAsyncContext &asyncContext, const USBEndpoint &ep)
1486 {
1487     uint8_t *buffer = nullptr;
1488     size_t offset = 0;
1489     size_t bufferSize = 0;
1490     bool hasBuffer = NapiUtil::JsUint8ArrayParse(env, data, &buffer, bufferSize, offset);
1491     if (!hasBuffer) {
1492         USB_HILOGE(MODULE_JS_NAPI, "BulkTransfer wrong argument, buffer is null");
1493         return false;
1494     }
1495     asyncContext.env = env;
1496     asyncContext.endpoint = ep;
1497 
1498     if (ep.GetDirection() == USB_ENDPOINT_DIR_OUT) {
1499         uint8_t *nativeArrayBuffer = new (std::nothrow) uint8_t[bufferSize];
1500         RETURN_IF_WITH_RET(nativeArrayBuffer == nullptr, false);
1501 
1502         errno_t ret = memcpy_s(nativeArrayBuffer, bufferSize, buffer, bufferSize);
1503         if (ret != EOK) {
1504             USB_HILOGE(MODULE_JS_NAPI, "memcpy_s failed");
1505             delete[] nativeArrayBuffer;
1506             return false;
1507         }
1508 
1509         asyncContext.buffer = nativeArrayBuffer;
1510     } else {
1511         asyncContext.buffer = buffer;
1512     }
1513     asyncContext.bufferLength = bufferSize;
1514     return true;
1515 }
1516 
GetBulkTransferParams(napi_env env, napi_callback_info info, USBBulkTransferAsyncContext &asyncContext)1517 static bool GetBulkTransferParams(napi_env env, napi_callback_info info, USBBulkTransferAsyncContext &asyncContext)
1518 {
1519     size_t argc = PARAM_COUNT_4;
1520     napi_value argv[PARAM_COUNT_4] = {nullptr};
1521     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
1522     USB_ASSERT_RETURN_FALSE(
1523         env, (argc >= PARAM_COUNT_3), SYSPARAM_INVALID_INPUT,
1524         "The function at least takes three arguments.");
1525 
1526     napi_valuetype type;
1527     USBDevicePipe pipe;
1528     napi_typeof(env, argv[INDEX_0], &type);
1529     USB_ASSERT_RETURN_FALSE(
1530         env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1531     ParseUsbDevicePipe(env, argv[INDEX_0], pipe);
1532     asyncContext.pipe = pipe;
1533 
1534     USBEndpoint ep;
1535     napi_typeof(env, argv[INDEX_1], &type);
1536     USB_ASSERT_RETURN_FALSE(
1537         env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of endpoint must be USBEndpoint.");
1538     ParseEndpointObj(env, argv[INDEX_1], ep);
1539 
1540     int32_t timeOut = 0;
1541     if (argc > PARAM_COUNT_3) {
1542         napi_typeof(env, argv[INDEX_3], &type);
1543         if (type == napi_number) {
1544             napi_get_value_int32(env, argv[INDEX_3], &timeOut);
1545         } else {
1546             USB_HILOGW(MODULE_JS_NAPI, "The type of timeOut must be number.");
1547         }
1548     }
1549 
1550     if (!GetDescriptorOnBulkTransferParam(env, argv[INDEX_2], asyncContext, ep)) {
1551         USB_HILOGE(MODULE_JS_NAPI, "get asyncContext failed.");
1552         return false;
1553     }
1554     asyncContext.timeOut = timeOut;
1555     return true;
1556 }
1557 
PipeBulkTransfer(napi_env env, napi_callback_info info)1558 static napi_value PipeBulkTransfer(napi_env env, napi_callback_info info)
1559 {
1560     auto asyncContext = new (std::nothrow) USBBulkTransferAsyncContext();
1561     if (asyncContext == nullptr) {
1562         USB_HILOGE(MODULE_JS_NAPI, "Create USBBulkTransferAsyncContext failed.");
1563         return nullptr;
1564     }
1565 
1566     napi_value result = nullptr;
1567     napi_create_promise(env, &asyncContext->deferred, &result);
1568     if (!GetBulkTransferParams(env, info, *asyncContext)) {
1569         USB_HILOGE(MODULE_JS_NAPI, "end call invalid arg");
1570         asyncContext->status = napi_invalid_arg;
1571         napi_value queryResult = nullptr;
1572         napi_create_int32(env, -1, &queryResult);
1573         if (asyncContext->deferred) {
1574             napi_resolve_deferred(env, asyncContext->deferred, queryResult);
1575         }
1576         delete asyncContext;
1577         return result;
1578     }
1579 
1580     napi_value resource = nullptr;
1581     napi_create_string_utf8(env, "PipeBulkTransfer", NAPI_AUTO_LENGTH, &resource);
1582 
1583     napi_status status = napi_create_async_work(env, nullptr, resource, g_bulkTransferExecute, g_bulkTransferComplete,
1584         reinterpret_cast<void *>(asyncContext), &asyncContext->work);
1585     if (status != napi_ok) {
1586         USB_HILOGE(MODULE_JS_NAPI, "create async work failed");
1587         return result;
1588     }
1589     napi_queue_async_work(env, asyncContext->work);
1590 
1591     return result;
1592 }
1593 
PipeClose(napi_env env, napi_callback_info info)1594 static napi_value PipeClose(napi_env env, napi_callback_info info)
1595 {
1596     size_t argc = PARAM_COUNT_1;
1597     napi_value argv[PARAM_COUNT_1] = {nullptr};
1598 
1599     NAPI_CHECK(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), "Get call back info failed");
1600     USB_ASSERT(env, (argc >= PARAM_COUNT_1), SYSPARAM_INVALID_INPUT, "The function takes one argument.");
1601 
1602     napi_value obj = argv[INDEX_0];
1603     napi_valuetype type;
1604     napi_typeof(env, obj, &type);
1605     USB_ASSERT(env, type == napi_object, SYSPARAM_INVALID_INPUT, "The type of pipe must be USBDevicePipe.");
1606 
1607     USBDevicePipe pipe;
1608     ParseUsbDevicePipe(env, obj, pipe);
1609     int32_t ret = pipe.Close();
1610     napi_value result;
1611     napi_create_int32(env, ret, &result);
1612 
1613     return result;
1614 }
1615 
GetVersion(napi_env env, napi_callback_info info)1616 static napi_value GetVersion(napi_env env, napi_callback_info info)
1617 {
1618     auto version = g_usbClient.GetVersion();
1619     USB_HILOGD(MODULE_JS_NAPI, "version is %{public}s", version.c_str());
1620     napi_value result;
1621     napi_create_string_utf8(env, version.c_str(), NAPI_AUTO_LENGTH, &result);
1622     return result;
1623 }
1624 
ToInt32Value(napi_env env, int32_t value)1625 static napi_value ToInt32Value(napi_env env, int32_t value)
1626 {
1627     napi_value staticValue = nullptr;
1628     napi_create_int32(env, value, &staticValue);
1629     return staticValue;
1630 }
1631 
DeclareEnum(napi_env env, napi_value exports)1632 static napi_value DeclareEnum(napi_env env, napi_value exports)
1633 {
1634     napi_property_descriptor desc[] = {
1635         /* Declare Enum PowerRoleType */
1636         DECLARE_NAPI_STATIC_PROPERTY("NONE", ToInt32Value(env, NONE)),
1637         DECLARE_NAPI_STATIC_PROPERTY("SOURCE", ToInt32Value(env, SOURCE)),
1638         DECLARE_NAPI_STATIC_PROPERTY("SINK", ToInt32Value(env, SINK)),
1639 
1640         /* Declare Enum DataRoleType */
1641         DECLARE_NAPI_STATIC_PROPERTY("HOST", ToInt32Value(env, HOST)),
1642         DECLARE_NAPI_STATIC_PROPERTY("DEVICE", ToInt32Value(env, DEVICE)),
1643 
1644         /* Declare Enum PortModeType */
1645         DECLARE_NAPI_STATIC_PROPERTY("UFP", ToInt32Value(env, UFP)),
1646         DECLARE_NAPI_STATIC_PROPERTY("DFP", ToInt32Value(env, DFP)),
1647         DECLARE_NAPI_STATIC_PROPERTY("DRP", ToInt32Value(env, DRP)),
1648         DECLARE_NAPI_STATIC_PROPERTY("NUM_MODES", ToInt32Value(env, NUM_MODES)),
1649 
1650         /* Declare Enum USBRequestTargetType */
1651         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TARGET_DEVICE", ToInt32Value(env, USB_REQUEST_TARGET_DEVICE)),
1652         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TARGET_INTERFACE", ToInt32Value(env, USB_REQUEST_TARGET_INTERFACE)),
1653         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TARGET_ENDPOINT", ToInt32Value(env, USB_REQUEST_TARGET_ENDPOINT)),
1654         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TARGET_OTHER", ToInt32Value(env, USB_REQUEST_TARGET_OTHER)),
1655 
1656         /* Declare Enum USBControlRequestType */
1657         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TYPE_STANDARD", ToInt32Value(env, USB_REQUEST_TYPE_STANDARD)),
1658         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TYPE_CLASS", ToInt32Value(env, USB_REQUEST_TYPE_CLASS)),
1659         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_TYPE_VENDOR", ToInt32Value(env, USB_REQUEST_TYPE_VENDOR)),
1660 
1661         /* Declare Enum USBRequestDirection */
1662         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_DIR_TO_DEVICE", ToInt32Value(env, USB_REQUEST_DIR_TO_DEVICE)),
1663         DECLARE_NAPI_STATIC_PROPERTY("USB_REQUEST_DIR_FROM_DEVICE", ToInt32Value(env, USB_REQUEST_DIR_FROM_DEVICE)),
1664 
1665         /* Declare Enum FunctionType */
1666         DECLARE_NAPI_STATIC_PROPERTY("ACM", ToInt32Value(env, ACM)),
1667         DECLARE_NAPI_STATIC_PROPERTY("ECM", ToInt32Value(env, ECM)),
1668         DECLARE_NAPI_STATIC_PROPERTY("HDC", ToInt32Value(env, HDC)),
1669         DECLARE_NAPI_STATIC_PROPERTY("MTP", ToInt32Value(env, MTP)),
1670         DECLARE_NAPI_STATIC_PROPERTY("PTP", ToInt32Value(env, PTP)),
1671         DECLARE_NAPI_STATIC_PROPERTY("RNDIS", ToInt32Value(env, RNDIS)),
1672         DECLARE_NAPI_STATIC_PROPERTY("MIDI", ToInt32Value(env, MIDI)),
1673         DECLARE_NAPI_STATIC_PROPERTY("AUDIO_SOURCE", ToInt32Value(env, AUDIO_SOURCE)),
1674         DECLARE_NAPI_STATIC_PROPERTY("NCM", ToInt32Value(env, NCM)),
1675         DECLARE_NAPI_STATIC_PROPERTY("STORAGE", ToInt32Value(env, STORAGE)),
1676     };
1677     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1678     return exports;
1679 }
1680 
1681 EXTERN_C_START
1682 /*
1683  * function for module exports
1684  */
UsbInit(napi_env env, napi_value exports)1685 napi_value UsbInit(napi_env env, napi_value exports)
1686 {
1687     USB_HILOGD(MODULE_JS_NAPI, "enter");
1688 
1689     napi_property_descriptor desc[] = {
1690         /* usb core */
1691         DECLARE_NAPI_FUNCTION("getDevices", CoreGetDevices),
1692         DECLARE_NAPI_FUNCTION("connectDevice", CoreConnectDevice),
1693         DECLARE_NAPI_FUNCTION("hasRight", CoreHasRight),
1694         DECLARE_NAPI_FUNCTION("requestRight", CoreRequestRight),
1695         DECLARE_NAPI_FUNCTION("usbFunctionsFromString", CoreUsbFunctionsFromString),
1696         DECLARE_NAPI_FUNCTION("getFunctionsFromString", CoreUsbFunctionsFromString),
1697         DECLARE_NAPI_FUNCTION("usbFunctionsToString", CoreUsbFunctionsToString),
1698         DECLARE_NAPI_FUNCTION("getStringFromFunctions", CoreUsbFunctionsToString),
1699         DECLARE_NAPI_FUNCTION("setCurrentFunctions", CoreSetCurrentFunctions),
1700         DECLARE_NAPI_FUNCTION("setDeviceFunctions", CoreSetCurrentFunctions),
1701         DECLARE_NAPI_FUNCTION("getCurrentFunctions", CoreGetCurrentFunctions),
1702         DECLARE_NAPI_FUNCTION("getDeviceFunctions", CoreGetCurrentFunctions),
1703         DECLARE_NAPI_FUNCTION("getPorts", CoreGetPorts),
1704         DECLARE_NAPI_FUNCTION("getPortList", CoreGetPorts),
1705 
1706         /* usb port */
1707         DECLARE_NAPI_FUNCTION("getSupportedModes", PortGetSupportedModes),
1708         DECLARE_NAPI_FUNCTION("getPortSupportModes", PortGetSupportedModes),
1709         DECLARE_NAPI_FUNCTION("setPortRoles", PortSetPortRole),
1710         DECLARE_NAPI_FUNCTION("setPortRoleTypes", PortSetPortRole),
1711 
1712         /* usb device pipe */
1713         DECLARE_NAPI_FUNCTION("claimInterface", PipeClaimInterface),
1714         DECLARE_NAPI_FUNCTION("releaseInterface", PipeReleaseInterface),
1715         DECLARE_NAPI_FUNCTION("bulkTransfer", PipeBulkTransfer),
1716         DECLARE_NAPI_FUNCTION("controlTransfer", PipeControlTransfer),
1717         DECLARE_NAPI_FUNCTION("usbControlTransfer", PipeUsbControlTransfer),
1718         DECLARE_NAPI_FUNCTION("setInterface", PipeSetInterface),
1719         DECLARE_NAPI_FUNCTION("setConfiguration", PipeSetConfiguration),
1720         DECLARE_NAPI_FUNCTION("getRawDescriptor", PipeGetRawDescriptors),
1721         DECLARE_NAPI_FUNCTION("getFileDescriptor", PipeGetFileDescriptor),
1722         DECLARE_NAPI_FUNCTION("closePipe", PipeClose),
1723 
1724         /* fort test get usb service version */
1725         DECLARE_NAPI_FUNCTION("getVersion", GetVersion),
1726         DECLARE_NAPI_FUNCTION("addRight", DeviceAddRight),
1727         DECLARE_NAPI_FUNCTION("addDeviceAccessRight", DeviceAddAccessRight),
1728         DECLARE_NAPI_FUNCTION("removeRight", DeviceRemoveRight),
1729     };
1730     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1731 
1732     DeclareEnum(env, exports);
1733 
1734     USB_HILOGD(MODULE_JS_NAPI, "return");
1735 
1736     return exports;
1737 }
1738 EXTERN_C_END
1739