• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <unistd.h>
17 
18 #include <sys/time.h>
19 
20 #include <cstdio>
21 #include <cstdlib>
22 #include <iostream>
23 #include <sstream>
24 #include <string>
25 #include <future>
26 #include <functional>
27 
28 #include "hilog_wrapper.h"
29 #include "securec.h"
30 #include "napi/native_api.h"
31 #include "napi/native_node_api.h"
32 #include "napi_common.h"
33 #include "napi_util.h"
34 #include "serial_async_context.h"
35 #include "serial_napi_errors.h"
36 #include "usb_errors.h"
37 
38 #include "usb_srv_client.h"
39 #include "usb_serial_type.h"
40 
41 using namespace OHOS;
42 using namespace OHOS::USB;
43 
44 const int32_t ARGC_1 = 1;
45 const int32_t ARGC_2 = 2;
46 const int32_t ARGC_3 = 3;
47 
48 static UsbSrvClient &g_usbClient = UsbSrvClient::GetInstance();
49 
ErrorCodeConversion(int32_t value)50 static int32_t ErrorCodeConversion(int32_t value)
51 {
52     static const std::map<int32_t, int32_t> errorMap = {
53         {UEC_SERVICE_PERMISSION_DENIED_SYSAPI, SERIAL_SYSAPI_PERMISSION_DENIED},
54         {UEC_SERVICE_PERMISSION_DENIED, SERIAL_INTERFACE_PERMISSION_DENIED},
55         {UEC_SERVICE_PERMISSION_DENIED_SYSAPI_FAILED, SERIAL_SYSAPI_NOPERMISSION_CALL},
56         {UEC_SERIAL_PORT_REPEAT_OPEN, SERIAL_PORT_OCCUPIED},
57         {UEC_SERIAL_PORT_REPEAT_CLOSE, SERIAL_PORT_OCCUPIED},
58         {UEC_SERIAL_PORT_OCCUPIED, SERIAL_PORT_OCCUPIED},
59         {UEC_SERIAL_DEVICENOTOPEN, SERIAL_PORT_NOT_OPEN},
60         {UEC_SERIAL_PORT_NOT_OPEN, SERIAL_PORT_NOT_OPEN},
61         {UEC_INTERFACE_TIMED_OUT, SERIAL_TIMED_OUT},
62         {UEC_SERIAL_IO_EXCEPTION, SERIAL_IO_EXCEPTION},
63         {UEC_SERIAL_PORT_NOT_EXIST, SERIAL_PORT_NOT_EXIST},
64         {UEC_SERIAL_DATEBASE_ERROR, UEC_COMMON_RIGHT_DATABASE_ERROR}
65     };
66     auto it = errorMap.find(value);
67     if (it != errorMap.end()) {
68         return it->second;
69     }
70     return SERIAL_SERVICE_ABNORMAL;
71 }
72 
SerialGetPortListNapi(napi_env env,napi_callback_info info)73 static napi_value SerialGetPortListNapi(napi_env env, napi_callback_info info)
74 {
75     USB_HILOGI(MODULE_JS_NAPI, "SerialGetPortListNapi start");
76     std::vector<OHOS::USB::UsbSerialPort> portIds;
77     int32_t ret = g_usbClient.SerialGetPortList(portIds);
78     napi_value result = nullptr;
79     napi_create_array(env, &result);
80     if (ret < 0) {
81         USB_HILOGE(MODULE_JS_NAPI, "SerialGetPortList failed");
82         return result;
83     }
84     for (uint32_t i = 0; i < portIds.size(); ++i) {
85         napi_value portObj;
86         napi_create_object(env, &portObj);
87         NapiUtil::SetValueInt32(env, "portId", portIds[i].portId_, portObj);
88         std::string deviceName = std::to_string(portIds[i].busNum_) + "-" +
89             std::to_string(portIds[i].devAddr_);
90         NapiUtil::SetValueUtf8String(env, "deviceName", deviceName, portObj);
91         USB_HILOGI(MODULE_JS_NAPI, "portId: %{public}d", portIds[i].portId_);
92         USB_HILOGI(MODULE_JS_NAPI, "deviceName: %{public}s", deviceName.c_str());
93         napi_set_element(env, result, i, portObj);
94     }
95     return result;
96 }
97 
SerialGetAttributeNapi(napi_env env,napi_callback_info info)98 static napi_value SerialGetAttributeNapi(napi_env env, napi_callback_info info)
99 {
100     USB_HILOGI(MODULE_JS_NAPI, "SerialGetAttributeNapi start");
101     size_t argc = ARGC_1;
102     napi_value argv[ARGC_1] = {nullptr};
103     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
104         "Get call back info failed")) {
105         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
106         return nullptr;
107     }
108     if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
109         return nullptr;
110     }
111     napi_value portId = argv[0];
112     napi_valuetype type;
113     napi_typeof(env, portId, &type);
114     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of arg0 must be int32_t.")) {
115         return nullptr;
116     }
117     int32_t portIdValue = -1;
118     napi_get_value_int32(env, portId, &portIdValue);
119     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
120         return nullptr;
121     }
122     UsbSerialAttr serialAttribute;
123     int32_t ret = g_usbClient.SerialGetAttribute(portIdValue, serialAttribute);
124     if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "Failed to get attribute.")) {
125         return nullptr;
126     }
127     napi_value result = nullptr;
128     napi_create_object(env, &result);
129     NapiUtil::SetValueUint32(env, "baudRate", serialAttribute.baudRate_, result);
130     NapiUtil::SetValueUint32(env, "dataBits", serialAttribute.dataBits_, result);
131     NapiUtil::SetValueUint32(env, "parity", serialAttribute.parity_, result);
132     NapiUtil::SetValueUint32(env, "stopBits", serialAttribute.stopBits_, result);
133     return result;
134 }
135 
ParseSetAttributeInterfaceParams(napi_env env,napi_callback_info info,int32_t & portIdValue,UsbSerialAttr & serialAttribute)136 static bool ParseSetAttributeInterfaceParams(napi_env env, napi_callback_info info,
137     int32_t& portIdValue, UsbSerialAttr& serialAttribute)
138 {
139     USB_HILOGI(MODULE_JS_NAPI, "ParseSetAttributeInterfaceParams start");
140     size_t argc = ARGC_2;
141     napi_value argv[ARGC_2] = { nullptr };
142     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
143         "Get call back info failed")) {
144         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
145         return false;
146     }
147     if (!CheckAndThrowOnError(env, (argc == ARGC_2), SYSPARAM_INVALID_INPUT, "The function takes 2 arguments.")) {
148         return false;
149     }
150     napi_value portId = argv[0];
151     napi_valuetype type;
152     napi_typeof(env, portId, &type);
153     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of arg0 must be int32_t.")) {
154         return false;
155     }
156     napi_get_value_int32(env, portId, &portIdValue);
157     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
158         return false;
159     }
160     napi_value obj = argv[1];
161     napi_typeof(env, obj, &type);
162     if (!CheckAndThrowOnError(env, type == napi_object, SYSPARAM_INVALID_INPUT,
163         "The type of arg1 must be SerialAttribute.")) {
164         return false;
165     }
166     bool result = NapiUtil::JsObjectToUint32(env, obj, "baudRate", serialAttribute.baudRate_) &&
167         NapiUtil::JsObjectToUint8(env, obj, "dataBits", serialAttribute.dataBits_) &&
168         NapiUtil::JsObjectToUint8(env, obj, "parity", serialAttribute.parity_) &&
169         NapiUtil::JsObjectToUint8(env, obj, "stopBits", serialAttribute.stopBits_);
170     if (!CheckAndThrowOnError(env, result == true, SYSPARAM_INVALID_INPUT,
171         "Parse attribute failed.")) {
172         return false;
173     }
174     return true;
175 }
176 
SerialSetAttributeNapi(napi_env env,napi_callback_info info)177 static napi_value SerialSetAttributeNapi(napi_env env, napi_callback_info info)
178 {
179     USB_HILOGI(MODULE_JS_NAPI, "SerialSetAttributeNapi start");
180     UsbSerialAttr serialAttribute;
181     int32_t portIdValue = -1;
182     if (!ParseSetAttributeInterfaceParams(env, info, portIdValue, serialAttribute)) {
183         return nullptr;
184     }
185     USB_HILOGI(MODULE_JS_NAPI, "SetAttributeNapi portIdValue: %{public}d", portIdValue);
186     int ret = g_usbClient.SerialSetAttribute(portIdValue, serialAttribute);
187     if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "Failed to set attribute.")) {
188         return nullptr;
189     }
190     return nullptr;
191 }
192 
ParseWriteInterfaceParams(napi_env env,napi_callback_info info,int32_t & portIdValue,napi_value * buffer,uint32_t & timeoutValue)193 static bool ParseWriteInterfaceParams(napi_env env, napi_callback_info info,
194     int32_t& portIdValue, napi_value* buffer, uint32_t& timeoutValue)
195 {
196     USB_HILOGI(MODULE_JS_NAPI, "ParseWriteInterfaceParams start");
197     size_t argc = ARGC_3;
198     napi_value argv[ARGC_3] = {nullptr};
199     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
200         "Get call back info failed")) {
201         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
202         return false;
203     }
204     if (!CheckAndThrowOnError(env, (argc == ARGC_2 || argc == ARGC_3), SYSPARAM_INVALID_INPUT,
205         "The function takes 2 or 3 arguments.")) {
206         return false;
207     }
208     napi_value portId = argv[0];
209     napi_valuetype type;
210     napi_typeof(env, portId, &type);
211     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
212         "The type of portId must be int32_t.")) {
213         return false;
214     }
215     napi_get_value_int32(env, portId, &portIdValue);
216     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
217         return false;
218     }
219     *buffer = argv[1];
220     if (argc == ARGC_3) {
221         napi_value timeout = argv[2];
222         napi_typeof(env, timeout, &type);
223         if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
224             "The type of timeout must be uint32_t.")) {
225             return false;
226         }
227         napi_get_value_uint32(env, timeout, &timeoutValue);
228     }
229     return true;
230 }
231 
SerialWriteSyncNapi(napi_env env,napi_callback_info info)232 static napi_value SerialWriteSyncNapi(napi_env env, napi_callback_info info)
233 {
234     USB_HILOGI(MODULE_JS_NAPI, "SerialWriteSyncNapi start");
235     int32_t portIdValue = -1;
236     napi_value buffer;
237     uint32_t timeoutValue = 0;
238     if (!ParseWriteInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
239         return nullptr;
240     }
241     napi_typedarray_type arrayType;
242     size_t bufferLength;
243     void* bufferValue = nullptr;
244     napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
245     if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
246         "The type of buffer must be an array of uint8_t.")) {
247         return nullptr;
248     }
249     std::vector<uint8_t> bufferVector(static_cast<uint8_t*>(bufferValue),
250         static_cast<uint8_t*>(bufferValue) + bufferLength);
251 
252     uint32_t actualSize = 0;
253     int32_t ret = g_usbClient.SerialWrite(portIdValue, bufferVector, bufferLength, actualSize, timeoutValue);
254     if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "SerialWrite Failed.")) {
255         return nullptr;
256     }
257 
258     napi_value result = nullptr;
259     napi_create_int32(env, actualSize, &result);
260     return result;
261 }
262 
__anonb01b89b40102(napi_env env, void* data) 263 static auto g_serialWriteExecute = [](napi_env env, void* data) {
264     SerialWriteAsyncContext *context = static_cast<SerialWriteAsyncContext *>(data);
265     if (context->contextErrno) {
266         USB_HILOGE(MODULE_JS_NAPI, "ExecuteCallback failed, reason: napi_get_reference_value");
267         return;
268     }
269 
270     void* bufferValue = context->pData;
271     if (context->size == 0) {
272         USB_HILOGE(MODULE_JS_NAPI, "no valid data to write");
273         return;
274     }
275 
276     std::vector<uint8_t> bufferVector(static_cast<uint8_t*>(bufferValue),
277         static_cast<uint8_t*>(bufferValue) + context->size);
278 
279     uint32_t actualSize = 0;
280     int32_t ret = g_usbClient.SerialWrite(context->portId, bufferVector, context->size, actualSize, context->timeout);
281     if (ret != 0) {
282         context->contextErrno = ErrorCodeConversion(ret);
283     }
284 
285     context->ret = actualSize;
286 };
287 
__anonb01b89b40202(napi_env env, napi_status status, void *data) 288 static auto g_serialWriteComplete = [](napi_env env, napi_status status, void *data) {
289     SerialWriteAsyncContext *context = static_cast<SerialWriteAsyncContext *>(data);
290     napi_value result = nullptr;
291     if (context->contextErrno) {
292         napi_create_int32(env, context->contextErrno, &result);
293         napi_reject_deferred(env, context->deferred, result);
294     } else {
295         napi_create_int32(env, context->ret, &result);
296         napi_resolve_deferred(env, context->deferred, result);
297     }
298     napi_delete_async_work(env, context->work);
299     delete context;
300 };
301 
SerialWriteNapi(napi_env env,napi_callback_info info)302 static napi_value SerialWriteNapi(napi_env env, napi_callback_info info)
303 {
304     USB_HILOGI(MODULE_JS_NAPI, "start write Napi");
305     int32_t portIdValue = -1;
306     napi_value buffer;
307     uint32_t timeoutValue = 0;
308     if (!ParseWriteInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
309         return nullptr;
310     }
311     napi_typedarray_type arrayType;
312     size_t bufferLength;
313     void* bufferValue = nullptr;
314     napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
315     if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
316         "The type of buffer must be an array of uint8_t.")) {
317         return nullptr;
318     }
319     SerialWriteAsyncContext *asyncContext = new (std::nothrow) SerialWriteAsyncContext;
320     if (asyncContext == nullptr) {
321         USB_HILOGE(MODULE_JS_NAPI, "new SerialWriteAsyncContext failed!");
322         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "asyncContext is null");
323         return nullptr;
324     }
325     napi_value promise;
326     if (napi_create_promise(env, &asyncContext->deferred, &promise)) {
327         USB_HILOGE(MODULE_JS_NAPI, "create promise failed!");
328         CheckAndThrowOnError(env, false, SERIAL_SERVICE_ABNORMAL, "promise is null");
329         delete asyncContext;
330         asyncContext = nullptr;
331         return nullptr;
332     }
333     asyncContext->portId = portIdValue;
334     asyncContext->timeout = timeoutValue;
335     asyncContext->contextErrno = 0;
336     asyncContext->size = bufferLength;
337     asyncContext->pData = bufferValue;
338     napi_value resourceName;
339     napi_create_string_utf8(env, "SerialWrite", NAPI_AUTO_LENGTH, &resourceName);
340     napi_create_async_work(env, nullptr, resourceName, g_serialWriteExecute, g_serialWriteComplete, asyncContext,
341         &asyncContext->work);
342     napi_queue_async_work(env, asyncContext->work);
343     return promise;
344 }
345 
ParseReadInterfaceParams(napi_env env,napi_callback_info info,int32_t & portIdValue,napi_value * buffer,uint32_t & timeoutValue)346 static bool ParseReadInterfaceParams(napi_env env, napi_callback_info info, int32_t& portIdValue,
347     napi_value* buffer, uint32_t& timeoutValue)
348 {
349     size_t argc = ARGC_3;
350     napi_value argv[ARGC_3] = {nullptr};
351     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
352         "Get call back info failed")) {
353         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
354         return false;
355     }
356     if (!CheckAndThrowOnError(env, (argc == ARGC_2 || argc == ARGC_3), SYSPARAM_INVALID_INPUT,
357         "The function takes 2 or 3 arguments.")) {
358         return false;
359     }
360     napi_value portId = argv[0];
361     napi_valuetype type;
362     napi_typeof(env, portId, &type);
363     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
364         "The type of portId must be int32_t.")) {
365         return false;
366     }
367     napi_get_value_int32(env, portId, &portIdValue);
368     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
369         return false;
370     }
371     *buffer = argv[1];
372     if (argc == ARGC_3) {
373         napi_value timeout = argv[2];
374         napi_typeof(env, timeout, &type);
375         if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
376             "The type of timeout must be uint32_t.")) {
377             return false;
378         }
379         napi_get_value_uint32(env, timeout, &timeoutValue);
380     }
381     return true;
382 }
383 
SerialReadSyncNapi(napi_env env,napi_callback_info info)384 static napi_value SerialReadSyncNapi(napi_env env, napi_callback_info info)
385 {
386     USB_HILOGI(MODULE_JS_NAPI, "SerialReadSyncNapi start");
387     int32_t portIdValue = -1;
388     napi_value buffer;
389     uint32_t timeoutValue = 0;
390     if (!ParseReadInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
391         return nullptr;
392     }
393     napi_typedarray_type arrayType;
394     size_t bufferLength;
395     void* bufferValue = nullptr;
396     napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
397     if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
398         "The type of buffer must be an array of uint8_t.")) {
399         return nullptr;
400     }
401 
402     std::vector<uint8_t> bufferData;
403     uint32_t actualSize = 0;
404     int32_t ret = g_usbClient.SerialRead(portIdValue, bufferData, bufferLength,
405         actualSize, timeoutValue);
406     if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "SerialReadSync Failed.")) {
407         return nullptr;
408     }
409     ret = memcpy_s(bufferValue, bufferLength, bufferData.data(), bufferData.size());
410     if (ret != UEC_OK) {
411         USB_HILOGE(MODULE_JS_NAPI,
412             "serial read sync, memcpy_s failed ret: %{public}d", ret);
413     }
414     napi_value result = nullptr;
415     napi_create_int32(env, actualSize, &result);
416     return result;
417 }
418 
__anonb01b89b40302(napi_env env, void* data) 419 static auto g_serialReadExecute = [](napi_env env, void* data) {
420     SerialReadAsyncContext *context = static_cast<SerialReadAsyncContext *>(data);
421     uint32_t actualSize = 0;
422     std::vector<uint8_t> bufferData;
423     int32_t ret = g_usbClient.SerialRead(context->portId, bufferData,
424         context->size, actualSize, context->timeout);
425     if (ret != 0) {
426         context->contextErrno = ErrorCodeConversion(ret);
427     }
428     ret = memcpy_s(context->pData, context->size, bufferData.data(), bufferData.size());
429     if (ret != UEC_OK) {
430         USB_HILOGE(MODULE_JS_NAPI, "memcpy_s failed ret: %{public}d", ret);
431     }
432     context->ret = actualSize;
433 };
434 
__anonb01b89b40402(napi_env env, napi_status status, void* data) 435 static auto g_serialReadComplete = [](napi_env env, napi_status status, void* data) {
436     SerialReadAsyncContext *context = static_cast<SerialReadAsyncContext *>(data);
437     napi_value result = nullptr;
438     if (context->contextErrno) {
439         napi_create_int32(env, context->contextErrno, &result);
440         napi_reject_deferred(env, context->deferred, result);
441     } else {
442         napi_create_int32(env, context->ret, &result);
443         napi_resolve_deferred(env, context->deferred, result);
444     }
445     napi_delete_async_work(env, context->work);
446     delete context;
447 };
448 
SerialReadNapi(napi_env env,napi_callback_info info)449 static napi_value SerialReadNapi(napi_env env, napi_callback_info info)
450 {
451     USB_HILOGI(MODULE_JS_NAPI, "SerialReadNapi start");
452     int32_t portIdValue = -1;
453     napi_value buffer;
454     uint32_t timeoutValue = 0;
455     if (!ParseReadInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
456         return nullptr;
457     }
458     napi_typedarray_type arrayType;
459     size_t bufferLength;
460     void* bufferValue = nullptr;
461     napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
462     if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
463         "The type of buffer must be an array of uint8_t.")) {
464         return nullptr;
465     }
466     SerialReadAsyncContext *asyncContext = new (std::nothrow) SerialReadAsyncContext;
467     if (!CheckAndThrowOnError(env, asyncContext != nullptr, SYSPARAM_INVALID_INPUT, "Failed to create promise.")) {
468         return nullptr;
469     }
470     napi_value promise;
471     if (napi_create_promise(env, &asyncContext->deferred, &promise)) {
472         USB_HILOGE(MODULE_JS_NAPI, "create promise failed!");
473         CheckAndThrowOnError(env, false, SERIAL_SERVICE_ABNORMAL, "promise is null");
474         delete asyncContext;
475         asyncContext = nullptr;
476         return nullptr;
477     }
478     asyncContext->portId = portIdValue;
479     asyncContext->timeout = timeoutValue;
480     asyncContext->contextErrno = 0;
481     asyncContext->size = bufferLength;
482     asyncContext->pData = bufferValue;
483     napi_value resourceName;
484     napi_create_string_utf8(env, "SerialRead", NAPI_AUTO_LENGTH, &resourceName);
485     napi_create_async_work(env, nullptr, resourceName, g_serialReadExecute, g_serialReadComplete, asyncContext,
486         &asyncContext->work);
487     napi_queue_async_work(env, asyncContext->work);
488     return promise;
489 }
490 
SerialOpenNapi(napi_env env,napi_callback_info info)491 static napi_value SerialOpenNapi(napi_env env, napi_callback_info info)
492 {
493     USB_HILOGI(MODULE_JS_NAPI, "serialOpenNapi start");
494     size_t argc = ARGC_1;
495     napi_value argv[ARGC_1] = {nullptr};
496     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
497         "Get call back info failed")) {
498         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
499         return nullptr;
500     }
501     if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
502         return nullptr;
503     }
504     napi_value portId = argv[0];
505     napi_valuetype type;
506     napi_typeof(env, portId, &type);
507     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
508         "The type of portId must be int32_t.")) {
509         return nullptr;
510     }
511     int32_t portIdValue = -1;
512     napi_get_value_int32(env, portId, &portIdValue);
513     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
514         return nullptr;
515     }
516     USB_HILOGE(MODULE_JS_NAPI, "portIdValue: %{public}d", portIdValue);
517     int ret = g_usbClient.SerialOpen(portIdValue);
518     if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialOpen failed.")) {
519         return nullptr;
520     }
521 
522     return nullptr;
523 }
524 
SerialCloseNapi(napi_env env,napi_callback_info info)525 static napi_value SerialCloseNapi(napi_env env, napi_callback_info info)
526 {
527     USB_HILOGI(MODULE_JS_NAPI, "SerialCloseNapi start");
528     size_t argc = ARGC_1;
529     napi_value argv[ARGC_1] = {nullptr};
530     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
531         "Get call back info failed")) {
532         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
533         return nullptr;
534     }
535     if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
536         return nullptr;
537     }
538     napi_value portId = argv[0];
539     napi_valuetype type;
540     napi_typeof(env, portId, &type);
541     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
542         "The type of portId must be int32_t.")) {
543         return nullptr;
544     }
545     int32_t portIdValue = -1;
546     napi_get_value_int32(env, portId, &portIdValue);
547     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
548         return nullptr;
549     }
550 
551     int ret = g_usbClient.SerialClose(portIdValue);
552     if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialClose failed.")) {
553         return nullptr;
554     }
555     return nullptr;
556 }
557 
SerialHasRightNapi(napi_env env,napi_callback_info info)558 static napi_value SerialHasRightNapi(napi_env env, napi_callback_info info)
559 {
560     USB_HILOGI(MODULE_JS_NAPI, "SerialHasRightNapi start");
561     size_t argc = ARGC_1;
562     napi_value argv[ARGC_1] = {nullptr};
563     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
564         "Get call back info failed")) {
565         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
566         return nullptr;
567     }
568     if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
569         return nullptr;
570     }
571     napi_value portId = argv[0];
572     napi_valuetype type;
573     napi_typeof(env, portId, &type);
574     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
575         "The type of portId must be int32_t.")) {
576         return nullptr;
577     }
578     int32_t portIdValue = -1;
579     napi_get_value_int32(env, portId, &portIdValue);
580     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
581         return nullptr;
582     }
583     napi_value result = nullptr;
584     bool hasRight = false;
585     int32_t ret = g_usbClient.HasSerialRight(portIdValue, hasRight);
586     if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "SerialHasRight failed.")) {
587         return nullptr;
588     }
589     napi_get_boolean(env, hasRight, &result);
590     return result;
591 }
592 
CancelSerialRightNapi(napi_env env,napi_callback_info info)593 static napi_value CancelSerialRightNapi(napi_env env, napi_callback_info info)
594 {
595     USB_HILOGI(MODULE_JS_NAPI, "CancelSerialRightNapi start");
596     size_t argc = ARGC_1;
597     napi_value argv[ARGC_1] = {nullptr};
598     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
599         "Get call back info failed")) {
600         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
601         return nullptr;
602     }
603     if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
604         return nullptr;
605     }
606     napi_value portId = argv[0];
607     napi_valuetype type;
608     napi_typeof(env, portId, &type);
609     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
610         "The type of portId must be int32_t.")) {
611         return nullptr;
612     }
613     int32_t portIdValue = -1;
614     napi_get_value_int32(env, portId, &portIdValue);
615     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
616         return nullptr;
617     }
618     int32_t ret = g_usbClient.CancelSerialRight(portIdValue);
619     if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialRemoveRight failed.")) {
620         return nullptr;
621     }
622     return nullptr;
623 }
624 
SerialAddRightNapi(napi_env env,napi_callback_info info)625 static napi_value SerialAddRightNapi(napi_env env, napi_callback_info info)
626 {
627     USB_HILOGI(MODULE_JS_NAPI, "SerialAddRightNapi start");
628     size_t argc = ARGC_2;
629     napi_value argv[ARGC_2] = {nullptr};
630     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
631         "Get call back info failed")) {
632         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "can not get arguments.");
633         return nullptr;
634     }
635     if (!CheckAndThrowOnError(env, (argc == ARGC_2), SYSPARAM_INVALID_INPUT, "The function takes 2 arguments.")) {
636         return nullptr;
637     }
638     napi_value tokenId = argv[0];
639     napi_valuetype type;
640     napi_typeof(env, tokenId, &type);
641     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
642         "The type of tokenId must be int32_t.")) {
643         return nullptr;
644     }
645     int32_t tokenIdValue = 0;
646     napi_get_value_int32(env, tokenId, &tokenIdValue);
647     if (!CheckAndThrowOnError(env, (tokenIdValue != 0), SYSPARAM_INVALID_INPUT, "Failed to get tokenId.")) {
648         return nullptr;
649     }
650     napi_value portId = argv[1];
651     napi_typeof(env, portId, &type);
652     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
653         "The type of portId must be int32_t.")) {
654         return nullptr;
655     }
656     int32_t portIdValue = -1;
657     napi_get_value_int32(env, portId, &portIdValue);
658     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
659         return nullptr;
660     }
661     int32_t ret = g_usbClient.AddSerialRight(tokenIdValue, portIdValue);
662     if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialAddRight failed.")) {
663         return nullptr;
664     }
665     return nullptr;
666 }
667 
__anonb01b89b40502(napi_env env, void* data) 668 static auto g_serialRequestRightExecute = [](napi_env env, void* data) {
669     SerialRequestRightAsyncContext *asyncContext = static_cast<SerialRequestRightAsyncContext *>(data);
670     int32_t ret = g_usbClient.RequestSerialRight(asyncContext->portIdValue, asyncContext->hasRight);
671     asyncContext->contextErrno = 0;
672     if (ret != 0) {
673         USB_HILOGE(MODULE_JS_NAPI, "request right has error");
674         asyncContext->contextErrno = ErrorCodeConversion(ret);
675     }
676 };
677 
__anonb01b89b40602(napi_env env, napi_status status, void* data) 678 static auto g_serialRequestRightComplete = [](napi_env env, napi_status status, void* data) {
679     SerialRequestRightAsyncContext *asyncContext = static_cast<SerialRequestRightAsyncContext *>(data);
680     napi_value result = nullptr;
681     if (asyncContext->contextErrno) {
682         USB_HILOGE(MODULE_JS_NAPI, "Failed to request serial right");
683         napi_create_int32(env, asyncContext->contextErrno, &result);
684         napi_reject_deferred(env, asyncContext->deferred, result);
685     } else {
686         napi_get_boolean(env, asyncContext->hasRight, &result);
687         napi_resolve_deferred(env, asyncContext->deferred, result);
688     }
689     napi_delete_async_work(env, asyncContext->work);
690     delete asyncContext;
691 };
692 
SerialRequestRightNapi(napi_env env,napi_callback_info info)693 static napi_value SerialRequestRightNapi(napi_env env, napi_callback_info info)
694 {
695     size_t argc = ARGC_1;
696     napi_value argv[ARGC_1] = {nullptr};
697     if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
698         "Get call back info failed")) {
699         CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "can not get arguments.");
700         return nullptr;
701     }
702     if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
703         return nullptr;
704     }
705     napi_value portId = argv[0];
706     napi_valuetype type;
707     napi_typeof(env, portId, &type);
708     if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
709         "The type of portId must be int32_t.")) {
710         return nullptr;
711     }
712     int32_t portIdValue = -1;
713     napi_get_value_int32(env, portId, &portIdValue);
714     if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
715         return nullptr;
716     }
717     SerialRequestRightAsyncContext* asyncContext = new (std::nothrow) SerialRequestRightAsyncContext;
718     if (!CheckAndThrowOnError(env, asyncContext != nullptr, SYSPARAM_INVALID_INPUT, "Failed to create promise.")) {
719         return nullptr;
720     }
721     asyncContext->portIdValue = portIdValue;
722     asyncContext->contextErrno = 0;
723     asyncContext->hasRight = false;
724     napi_value result = nullptr;
725     if (napi_create_promise(env, &asyncContext->deferred, &result)) {
726         USB_HILOGE(MODULE_JS_NAPI, "create promise failed!");
727         CheckAndThrowOnError(env, false, SERIAL_SERVICE_ABNORMAL, "promise is null");
728         delete asyncContext;
729         asyncContext = nullptr;
730         return nullptr;
731     }
732     napi_value resourceName;
733     napi_create_string_utf8(env, "SerialRequestRight", NAPI_AUTO_LENGTH, &resourceName);
734     napi_create_async_work(env, nullptr, resourceName, g_serialRequestRightExecute,
735         g_serialRequestRightComplete, static_cast<void*>(asyncContext), &asyncContext->work);
736     napi_queue_async_work(env, asyncContext->work);
737     return result;
738 }
739 
SetEnumProperty(napi_env env,napi_value object,const std::string & name,int32_t value)740 static void SetEnumProperty(napi_env env, napi_value object, const std::string &name, int32_t value)
741 {
742     if (name.empty()) {
743         USB_HILOGE(MODULE_JS_NAPI, "Property name cannot be an empty string");
744         return;
745     }
746 
747     napi_value tempValue = nullptr;
748     napi_status status = napi_create_int32(env, value, &tempValue);
749     if (status != napi_ok) {
750         USB_HILOGE(MODULE_JS_NAPI, "Failed to create int32 value for enum %{public}s", name.c_str());
751         return;
752     }
753     status = napi_set_named_property(env, object, name.c_str(), tempValue);
754     if (status != napi_ok) {
755         USB_HILOGE(MODULE_JS_NAPI, "Failed to set property %{public}s", name.c_str());
756         return;
757     }
758 }
759 
NapiCreateStopBitsTypeEnum(napi_env env)760 static napi_value NapiCreateStopBitsTypeEnum(napi_env env)
761 {
762     napi_value object = nullptr;
763     napi_status status = napi_create_object(env, &object);
764     if (status != napi_ok) {
765         USB_HILOGE(MODULE_JS_NAPI, "Failed to create object");
766         return nullptr;
767     }
768     SetEnumProperty(env, object, "STOPBIT_1", STOPBIT_1);
769     SetEnumProperty(env, object, "STOPBIT_2", STOPBIT_2);
770     return object;
771 }
772 
NapiCreateParityTypeEnum(napi_env env)773 static napi_value NapiCreateParityTypeEnum(napi_env env)
774 {
775     napi_value object = nullptr;
776     napi_status status = napi_create_object(env, &object);
777     if (status != napi_ok) {
778         USB_HILOGE(MODULE_JS_NAPI, "Failed to create object");
779         return nullptr;
780     }
781     SetEnumProperty(env, object, "PARITY_NONE", PARITY_NONE);
782     SetEnumProperty(env, object, "PARITY_ODD", PARITY_ODD);
783     SetEnumProperty(env, object, "PARITY_EVEN", PARITY_EVEN);
784     SetEnumProperty(env, object, "PARITY_MARK", PARITY_MARK);
785     SetEnumProperty(env, object, "PARITY_SPACE", PARITY_SPACE);
786     return object;
787 }
788 
NapiCreateDataBitsTypeEnum(napi_env env)789 static napi_value NapiCreateDataBitsTypeEnum(napi_env env)
790 {
791     napi_value object = nullptr;
792     napi_status status = napi_create_object(env, &object);
793     if (status != napi_ok) {
794         USB_HILOGE(MODULE_JS_NAPI, "Failed to create object");
795         return nullptr;
796     }
797     SetEnumProperty(env, object, "DATABIT_8", DATABIT_8);
798     SetEnumProperty(env, object, "DATABIT_7", DATABIT_7);
799     SetEnumProperty(env, object, "DATABIT_6", DATABIT_6);
800     SetEnumProperty(env, object, "DATABIT_5", DATABIT_5);
801     return object;
802 }
803 
NapiCreateBaudRatesTypeEnum(napi_env env)804 static napi_value NapiCreateBaudRatesTypeEnum(napi_env env)
805 {
806     napi_value object = nullptr;
807     napi_status status = napi_create_object(env, &object);
808     if (status != napi_ok) {
809         USB_HILOGE(MODULE_JS_NAPI, "Failed to create object");
810         return nullptr;
811     }
812     SetEnumProperty(env, object, "BAUDRATE_50", BAUDRATE_50);
813     SetEnumProperty(env, object, "BAUDRATE_75", BAUDRATE_75);
814     SetEnumProperty(env, object, "BAUDRATE_110", BAUDRATE_110);
815     SetEnumProperty(env, object, "BAUDRATE_134", BAUDRATE_134);
816     SetEnumProperty(env, object, "BAUDRATE_150", BAUDRATE_150);
817     SetEnumProperty(env, object, "BAUDRATE_200", BAUDRATE_200);
818     SetEnumProperty(env, object, "BAUDRATE_300", BAUDRATE_300);
819     SetEnumProperty(env, object, "BAUDRATE_600", BAUDRATE_600);
820     SetEnumProperty(env, object, "BAUDRATE_1200", BAUDRATE_1200);
821     SetEnumProperty(env, object, "BAUDRATE_1800", BAUDRATE_1800);
822     SetEnumProperty(env, object, "BAUDRATE_2400", BAUDRATE_2400);
823     SetEnumProperty(env, object, "BAUDRATE_4800", BAUDRATE_4800);
824     SetEnumProperty(env, object, "BAUDRATE_9600", BAUDRATE_9600);
825     SetEnumProperty(env, object, "BAUDRATE_19200", BAUDRATE_19200);
826     SetEnumProperty(env, object, "BAUDRATE_38400", BAUDRATE_38400);
827     SetEnumProperty(env, object, "BAUDRATE_57600", BAUDRATE_57600);
828     SetEnumProperty(env, object, "BAUDRATE_115200", BAUDRATE_115200);
829     SetEnumProperty(env, object, "BAUDRATE_230400", BAUDRATE_230400);
830     SetEnumProperty(env, object, "BAUDRATE_460800", BAUDRATE_460800);
831     SetEnumProperty(env, object, "BAUDRATE_500000", BAUDRATE_500000);
832     SetEnumProperty(env, object, "BAUDRATE_576000", BAUDRATE_576000);
833     SetEnumProperty(env, object, "BAUDRATE_921600", BAUDRATE_921600);
834     SetEnumProperty(env, object, "BAUDRATE_1000000", BAUDRATE_1000000);
835     SetEnumProperty(env, object, "BAUDRATE_1152000", BAUDRATE_1152000);
836     SetEnumProperty(env, object, "BAUDRATE_1500000", BAUDRATE_1500000);
837     SetEnumProperty(env, object, "BAUDRATE_2000000", BAUDRATE_2000000);
838     SetEnumProperty(env, object, "BAUDRATE_2500000", BAUDRATE_2500000);
839     SetEnumProperty(env, object, "BAUDRATE_3000000", BAUDRATE_3000000);
840     SetEnumProperty(env, object, "BAUDRATE_3500000", BAUDRATE_3500000);
841     SetEnumProperty(env, object, "BAUDRATE_4000000", BAUDRATE_4000000);
842     return object;
843 }
844 
DeclareEnum(napi_env env,napi_value exports)845 static napi_value DeclareEnum(napi_env env, napi_value exports)
846 {
847     napi_property_descriptor desc[] = {
848         DECLARE_NAPI_STATIC_PROPERTY("StopBits", NapiCreateStopBitsTypeEnum(env)),
849         DECLARE_NAPI_STATIC_PROPERTY("Parity", NapiCreateParityTypeEnum(env)),
850         DECLARE_NAPI_STATIC_PROPERTY("DataBits", NapiCreateDataBitsTypeEnum(env)),
851         DECLARE_NAPI_STATIC_PROPERTY("BaudRates", NapiCreateBaudRatesTypeEnum(env)),
852     };
853     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
854     return exports;
855 }
856 
857 EXTERN_C_START
858 /*
859  * function for module exports
860  */
SerialInit(napi_env env,napi_value exports)861 napi_value SerialInit(napi_env env, napi_value exports)
862 {
863     USB_HILOGD(MODULE_JS_NAPI, "enter");
864     napi_property_descriptor desc[] = {
865         DECLARE_NAPI_FUNCTION("getPortList", SerialGetPortListNapi),
866         DECLARE_NAPI_FUNCTION("open", SerialOpenNapi),
867         DECLARE_NAPI_FUNCTION("close", SerialCloseNapi),
868         DECLARE_NAPI_FUNCTION("read", SerialReadNapi),
869         DECLARE_NAPI_FUNCTION("readSync", SerialReadSyncNapi),
870         DECLARE_NAPI_FUNCTION("write", SerialWriteNapi),
871         DECLARE_NAPI_FUNCTION("writeSync", SerialWriteSyncNapi),
872         DECLARE_NAPI_FUNCTION("getAttribute", SerialGetAttributeNapi),
873         DECLARE_NAPI_FUNCTION("setAttribute", SerialSetAttributeNapi),
874         DECLARE_NAPI_FUNCTION("hasSerialRight", SerialHasRightNapi),
875         DECLARE_NAPI_FUNCTION("requestSerialRight", SerialRequestRightNapi),
876         DECLARE_NAPI_FUNCTION("addSerialRight", SerialAddRightNapi),
877         DECLARE_NAPI_FUNCTION("cancelSerialRight", CancelSerialRightNapi),
878     };
879     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
880     DeclareEnum(env, exports);
881     USB_HILOGD(MODULE_JS_NAPI, "return");
882     return exports;
883 }
884 EXTERN_C_END
885