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