* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <sys/time.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <future>
#include <functional>
#include "hilog_wrapper.h"
#include "securec.h"
#include "napi/native_api.h"
#include "napi/native_node_api.h"
#include "napi_common.h"
#include "napi_util.h"
#include "serial_async_context.h"
#include "serial_napi_errors.h"
#include "usb_api_metrics.h"
#include "usb_errors.h"
#include "usb_srv_client.h"
#include "usb_serial_type.h"
using namespace OHOS;
using namespace OHOS::USB;
const int32_t ARGC_1 = 1;
const int32_t ARGC_2 = 2;
const int32_t ARGC_3 = 3;
static UsbSrvClient &g_usbClient = UsbSrvClient::GetInstance();
static int32_t ErrorCodeConversion(int32_t value)
{
static const std::map<int32_t, int32_t> errorMap = {
{UEC_SERVICE_PERMISSION_DENIED_SYSAPI, SERIAL_SYSAPI_PERMISSION_DENIED},
{UEC_SERVICE_PERMISSION_DENIED, SERIAL_INTERFACE_PERMISSION_DENIED},
{UEC_SERVICE_PERMISSION_DENIED_SYSAPI_FAILED, SERIAL_SYSAPI_NOPERMISSION_CALL},
{UEC_SERIAL_PORT_REPEAT_OPEN, SERIAL_PORT_OCCUPIED},
{UEC_SERIAL_PORT_REPEAT_CLOSE, SERIAL_PORT_OCCUPIED},
{UEC_SERIAL_PORT_OCCUPIED, SERIAL_PORT_OCCUPIED},
{UEC_SERIAL_DEVICENOTOPEN, SERIAL_PORT_NOT_OPEN},
{UEC_SERIAL_PORT_NOT_OPEN, SERIAL_PORT_NOT_OPEN},
{UEC_INTERFACE_TIMED_OUT, SERIAL_TIMED_OUT},
{UEC_SERIAL_IO_EXCEPTION, SERIAL_IO_EXCEPTION},
{UEC_SERIAL_PORT_NOT_EXIST, SERIAL_PORT_NOT_EXIST},
{UEC_SERIAL_DATEBASE_ERROR, UEC_COMMON_RIGHT_DATABASE_ERROR}
};
auto it = errorMap.find(value);
if (it != errorMap.end()) {
return it->second;
}
return SERIAL_SERVICE_ABNORMAL;
}
static napi_value SerialGetPortListNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.GetPortList");
USB_HILOGI(MODULE_USB_NAPI, "SerialGetPortListNapi start");
std::vector<OHOS::USB::UsbSerialPort> portIds;
int32_t ret = g_usbClient.SerialGetPortList(portIds);
napi_value result = nullptr;
napi_create_array(env, &result);
if (ret < 0) {
USB_HILOGE(MODULE_USB_NAPI, "SerialGetPortList failed");
return result;
}
for (uint32_t i = 0; i < portIds.size(); ++i) {
napi_value portObj;
napi_create_object(env, &portObj);
NapiUtil::SetValueInt32(env, "portId", portIds[i].portId_, portObj);
std::string deviceName = std::to_string(portIds[i].busNum_) + "-" +
std::to_string(portIds[i].devAddr_);
NapiUtil::SetValueUtf8String(env, "deviceName", deviceName, portObj);
USB_HILOGI(MODULE_USB_NAPI, "portId: %{public}d", portIds[i].portId_);
USB_HILOGI(MODULE_USB_NAPI, "deviceName: %{public}s", deviceName.c_str());
napi_set_element(env, result, i, portObj);
}
return result;
}
static napi_value SerialGetAttributeNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.GetAttribute");
USB_HILOGI(MODULE_USB_NAPI, "SerialGetAttributeNapi start");
size_t argc = ARGC_1;
napi_value argv[ARGC_1] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of arg0 must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
UsbSerialAttr serialAttribute;
int32_t ret = g_usbClient.SerialGetAttribute(portIdValue, serialAttribute);
if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "Failed to get attribute.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
napi_value result = nullptr;
napi_create_object(env, &result);
NapiUtil::SetValueUint32(env, "baudRate", serialAttribute.baudRate_, result);
NapiUtil::SetValueUint32(env, "dataBits", serialAttribute.dataBits_, result);
NapiUtil::SetValueUint32(env, "parity", serialAttribute.parity_, result);
NapiUtil::SetValueUint32(env, "stopBits", serialAttribute.stopBits_, result);
return result;
}
static bool ParseSetAttributeInterfaceParams(napi_env env, napi_callback_info info,
int32_t& portIdValue, UsbSerialAttr& serialAttribute)
{
USB_HILOGI(MODULE_USB_NAPI, "ParseSetAttributeInterfaceParams start");
size_t argc = ARGC_2;
napi_value argv[ARGC_2] = { nullptr };
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
return false;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_2), SYSPARAM_INVALID_INPUT, "The function takes 2 arguments.")) {
return false;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT, "The type of arg0 must be int32_t.")) {
return false;
}
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
return false;
}
napi_value obj = argv[1];
napi_typeof(env, obj, &type);
if (!CheckAndThrowOnError(env, type == napi_object, SYSPARAM_INVALID_INPUT,
"The type of arg1 must be SerialAttribute.")) {
return false;
}
bool result = NapiUtil::JsObjectToUint32(env, obj, "baudRate", serialAttribute.baudRate_) &&
NapiUtil::JsObjectToUint8(env, obj, "dataBits", serialAttribute.dataBits_) &&
NapiUtil::JsObjectToUint8(env, obj, "parity", serialAttribute.parity_) &&
NapiUtil::JsObjectToUint8(env, obj, "stopBits", serialAttribute.stopBits_);
if (!CheckAndThrowOnError(env, result == true, SYSPARAM_INVALID_INPUT,
"Parse attribute failed.")) {
return false;
}
return true;
}
static napi_value SerialSetAttributeNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.SetAttribute");
USB_HILOGI(MODULE_USB_NAPI, "SerialSetAttributeNapi start");
UsbSerialAttr serialAttribute;
int32_t portIdValue = -1;
if (!ParseSetAttributeInterfaceParams(env, info, portIdValue, serialAttribute)) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
USB_HILOGI(MODULE_USB_NAPI, "SetAttributeNapi portIdValue: %{public}d", portIdValue);
int ret = g_usbClient.SerialSetAttribute(portIdValue, serialAttribute);
if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "Failed to set attribute.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
return nullptr;
}
static bool ParseWriteInterfaceParams(napi_env env, napi_callback_info info,
int32_t& portIdValue, napi_value* buffer, uint32_t& timeoutValue)
{
USB_HILOGI(MODULE_USB_NAPI, "ParseWriteInterfaceParams start");
size_t argc = ARGC_3;
napi_value argv[ARGC_3] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
return false;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_2 || argc == ARGC_3), SYSPARAM_INVALID_INPUT,
"The function takes 2 or 3 arguments.")) {
return false;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
return false;
}
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
return false;
}
*buffer = argv[1];
if (argc == ARGC_3) {
napi_value timeout = argv[2];
napi_typeof(env, timeout, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of timeout must be uint32_t.")) {
return false;
}
napi_get_value_uint32(env, timeout, &timeoutValue);
}
return true;
}
static napi_value SerialWriteSyncNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.WriteSync");
USB_HILOGI(MODULE_USB_NAPI, "SerialWriteSyncNapi start");
int32_t portIdValue = -1;
napi_value buffer;
uint32_t timeoutValue = 0;
if (!ParseWriteInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_typedarray_type arrayType;
size_t bufferLength;
void* bufferValue = nullptr;
napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
"The type of buffer must be an array of uint8_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
std::vector<uint8_t> bufferVector(static_cast<uint8_t*>(bufferValue),
static_cast<uint8_t*>(bufferValue) + bufferLength);
uint32_t actualSize = 0;
int32_t ret = g_usbClient.SerialWrite(portIdValue, bufferVector, bufferLength, actualSize, timeoutValue);
if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "SerialWrite Failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
napi_value result = nullptr;
napi_create_int32(env, actualSize, &result);
return result;
}
static auto g_serialWriteExecute = [](napi_env env, void* data) {
SerialWriteAsyncContext *context = static_cast<SerialWriteAsyncContext *>(data);
context->metrics = new UsbApiMetrics("BasicServicesKit.SerialManager.Write");
if (context->contextErrno) {
USB_HILOGE(MODULE_USB_NAPI, "ExecuteCallback failed, reason: napi_get_reference_value");
return;
}
void* bufferValue = context->pData;
if (context->size == 0) {
USB_HILOGE(MODULE_USB_NAPI, "no valid data to write");
return;
}
std::vector<uint8_t> bufferVector(static_cast<uint8_t*>(bufferValue),
static_cast<uint8_t*>(bufferValue) + context->size);
uint32_t actualSize = 0;
int32_t ret = g_usbClient.SerialWrite(context->portId, bufferVector, context->size, actualSize, context->timeout);
if (ret != 0) {
context->contextErrno = ErrorCodeConversion(ret);
}
context->ret = actualSize;
};
static auto g_serialWriteComplete = [](napi_env env, napi_status status, void *data) {
SerialWriteAsyncContext *context = static_cast<SerialWriteAsyncContext *>(data);
napi_value result = nullptr;
if (context->contextErrno) {
if (context->metrics != nullptr) {
context->metrics->SetErrorCode(context->contextErrno);
}
napi_create_int32(env, context->contextErrno, &result);
napi_reject_deferred(env, context->deferred, result);
} else {
napi_create_int32(env, context->ret, &result);
napi_resolve_deferred(env, context->deferred, result);
}
if (context->metrics != nullptr) {
delete context->metrics;
context->metrics = nullptr;
}
napi_delete_async_work(env, context->work);
if (context->bufferRef) {
napi_delete_reference(env, context->bufferRef);
}
delete context;
};
static napi_value SerialWriteNapi(napi_env env, napi_callback_info info)
{
USB_HILOGI(MODULE_USB_NAPI, "start write Napi");
int32_t portIdValue = -1;
napi_value buffer;
uint32_t timeoutValue = 0;
if (!ParseWriteInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
return nullptr;
}
napi_typedarray_type arrayType;
size_t bufferLength;
void* bufferValue = nullptr;
napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
"The type of buffer must be an array of uint8_t.")) {
return nullptr;
}
SerialWriteAsyncContext *asyncContext = new (std::nothrow) SerialWriteAsyncContext;
if (asyncContext == nullptr) {
USB_HILOGE(MODULE_USB_NAPI, "new SerialWriteAsyncContext failed!");
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "asyncContext is null");
return nullptr;
}
napi_value promise;
if (napi_create_promise(env, &asyncContext->deferred, &promise)) {
USB_HILOGE(MODULE_USB_NAPI, "create promise failed!");
CheckAndThrowOnError(env, false, SERIAL_SERVICE_ABNORMAL, "promise is null");
delete asyncContext;
asyncContext = nullptr;
return nullptr;
}
asyncContext->portId = portIdValue;
asyncContext->timeout = timeoutValue;
asyncContext->contextErrno = 0;
asyncContext->size = bufferLength;
asyncContext->pData = bufferValue;
napi_ref bufferRef = nullptr;
napi_status refStatus = napi_create_reference(env, buffer, 1, &bufferRef);
if (refStatus != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "create buffer reference failed");
delete asyncContext;
return nullptr;
}
asyncContext->bufferRef = bufferRef;
napi_value resourceName;
napi_create_string_utf8(env, "SerialWrite", NAPI_AUTO_LENGTH, &resourceName);
napi_create_async_work(env, nullptr, resourceName, g_serialWriteExecute, g_serialWriteComplete, asyncContext,
&asyncContext->work);
napi_queue_async_work(env, asyncContext->work);
return promise;
}
static bool ParseReadInterfaceParams(napi_env env, napi_callback_info info, int32_t& portIdValue,
napi_value* buffer, uint32_t& timeoutValue)
{
size_t argc = ARGC_3;
napi_value argv[ARGC_3] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
return false;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_2 || argc == ARGC_3), SYSPARAM_INVALID_INPUT,
"The function takes 2 or 3 arguments.")) {
return false;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
return false;
}
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
return false;
}
*buffer = argv[1];
if (argc == ARGC_3) {
napi_value timeout = argv[2];
napi_typeof(env, timeout, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of timeout must be uint32_t.")) {
return false;
}
napi_get_value_uint32(env, timeout, &timeoutValue);
}
return true;
}
static napi_value SerialReadSyncNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.ReadSync");
USB_HILOGI(MODULE_USB_NAPI, "SerialReadSyncNapi start");
int32_t portIdValue = -1;
napi_value buffer;
uint32_t timeoutValue = 0;
if (!ParseReadInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_typedarray_type arrayType;
size_t bufferLength;
void* bufferValue = nullptr;
napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
"The type of buffer must be an array of uint8_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
std::vector<uint8_t> bufferData;
uint32_t actualSize = 0;
int32_t ret = g_usbClient.SerialRead(portIdValue, bufferData, bufferLength,
actualSize, timeoutValue);
if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "SerialReadSync Failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
ret = memcpy_s(bufferValue, bufferLength, bufferData.data(), bufferData.size());
if (ret != UEC_OK) {
USB_HILOGE(MODULE_USB_NAPI,
"serial read sync, memcpy_s failed ret: %{public}d", ret);
}
napi_value result = nullptr;
napi_create_int32(env, actualSize, &result);
return result;
}
static auto g_serialReadExecute = [](napi_env env, void* data) {
SerialReadAsyncContext *context = static_cast<SerialReadAsyncContext *>(data);
context->metrics = new UsbApiMetrics("BasicServicesKit.SerialManager.Read");
uint32_t actualSize = 0;
std::vector<uint8_t> bufferData;
int32_t ret = g_usbClient.SerialRead(context->portId, bufferData,
context->size, actualSize, context->timeout);
if (ret != 0) {
context->contextErrno = ErrorCodeConversion(ret);
}
ret = memcpy_s(context->pData, context->size, bufferData.data(), bufferData.size());
if (ret != UEC_OK) {
USB_HILOGE(MODULE_USB_NAPI, "memcpy_s failed ret: %{public}d", ret);
}
context->ret = actualSize;
};
static auto g_serialReadComplete = [](napi_env env, napi_status status, void* data) {
SerialReadAsyncContext *context = static_cast<SerialReadAsyncContext *>(data);
napi_value result = nullptr;
if (context->contextErrno) {
if (context->metrics != nullptr) {
context->metrics->SetErrorCode(context->contextErrno);
}
napi_create_int32(env, context->contextErrno, &result);
napi_reject_deferred(env, context->deferred, result);
} else {
napi_create_int32(env, context->ret, &result);
napi_resolve_deferred(env, context->deferred, result);
}
if (context->metrics != nullptr) {
delete context->metrics;
context->metrics = nullptr;
}
napi_delete_async_work(env, context->work);
delete context;
};
static napi_value SerialReadNapi(napi_env env, napi_callback_info info)
{
USB_HILOGI(MODULE_USB_NAPI, "SerialReadNapi start");
int32_t portIdValue = -1;
napi_value buffer;
uint32_t timeoutValue = 0;
if (!ParseReadInterfaceParams(env, info, portIdValue, &buffer, timeoutValue)) {
return nullptr;
}
napi_typedarray_type arrayType;
size_t bufferLength;
void* bufferValue = nullptr;
napi_get_typedarray_info(env, buffer, &arrayType, &bufferLength, &bufferValue, nullptr, nullptr);
if (!CheckAndThrowOnError(env, arrayType == napi_uint8_array, SYSPARAM_INVALID_INPUT,
"The type of buffer must be an array of uint8_t.")) {
return nullptr;
}
SerialReadAsyncContext *asyncContext = new (std::nothrow) SerialReadAsyncContext;
if (!CheckAndThrowOnError(env, asyncContext != nullptr, SYSPARAM_INVALID_INPUT, "Failed to create promise.")) {
return nullptr;
}
napi_value promise;
if (napi_create_promise(env, &asyncContext->deferred, &promise)) {
USB_HILOGE(MODULE_USB_NAPI, "create promise failed!");
CheckAndThrowOnError(env, false, SERIAL_SERVICE_ABNORMAL, "promise is null");
delete asyncContext;
asyncContext = nullptr;
return nullptr;
}
asyncContext->portId = portIdValue;
asyncContext->timeout = timeoutValue;
asyncContext->contextErrno = 0;
asyncContext->size = bufferLength;
asyncContext->pData = bufferValue;
napi_value resourceName;
napi_create_string_utf8(env, "SerialRead", NAPI_AUTO_LENGTH, &resourceName);
napi_create_async_work(env, nullptr, resourceName, g_serialReadExecute, g_serialReadComplete, asyncContext,
&asyncContext->work);
napi_queue_async_work(env, asyncContext->work);
return promise;
}
static napi_value SerialOpenNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.Open");
USB_HILOGI(MODULE_USB_NAPI, "serialOpenNapi start");
size_t argc = ARGC_1;
napi_value argv[ARGC_1] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
USB_HILOGE(MODULE_USB_NAPI, "portIdValue: %{public}d", portIdValue);
int ret = g_usbClient.SerialOpen(portIdValue);
if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialOpen failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
return nullptr;
}
static napi_value SerialCloseNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.Close");
USB_HILOGI(MODULE_USB_NAPI, "SerialCloseNapi start");
size_t argc = ARGC_1;
napi_value argv[ARGC_1] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int ret = g_usbClient.SerialClose(portIdValue);
if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialClose failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
return nullptr;
}
static napi_value SerialHasRightNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.HasSerialRight");
USB_HILOGI(MODULE_USB_NAPI, "SerialHasRightNapi start");
size_t argc = ARGC_1;
napi_value argv[ARGC_1] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value result = nullptr;
bool hasRight = false;
int32_t ret = g_usbClient.HasSerialRight(portIdValue, hasRight);
if (!CheckAndThrowOnError(env, (ret == 0), ErrorCodeConversion(ret), "SerialHasRight failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
napi_get_boolean(env, hasRight, &result);
return result;
}
static napi_value CancelSerialRightNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.CancelSerialRight");
USB_HILOGI(MODULE_USB_NAPI, "CancelSerialRightNapi start");
size_t argc = ARGC_1;
napi_value argv[ARGC_1] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "get arguments failed.");
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t ret = g_usbClient.CancelSerialRight(portIdValue);
if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialRemoveRight failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
return nullptr;
}
static napi_value SerialAddRightNapi(napi_env env, napi_callback_info info)
{
UsbApiMetrics metrics("BasicServicesKit.SerialManager.AddSerialRight");
USB_HILOGI(MODULE_USB_NAPI, "SerialAddRightNapi start");
size_t argc = ARGC_2;
napi_value argv[ARGC_2] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "can not get arguments.");
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_2), SYSPARAM_INVALID_INPUT, "The function takes 2 arguments.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value tokenId = argv[0];
napi_valuetype type;
napi_typeof(env, tokenId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of tokenId must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t tokenIdValue = 0;
napi_get_value_int32(env, tokenId, &tokenIdValue);
if (!CheckAndThrowOnError(env, (tokenIdValue != 0), SYSPARAM_INVALID_INPUT, "Failed to get tokenId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
napi_value portId = argv[1];
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
metrics.SetErrorCode(SYSPARAM_INVALID_INPUT);
return nullptr;
}
int32_t ret = g_usbClient.AddSerialRight(tokenIdValue, portIdValue);
if (!CheckAndThrowOnError(env, ret == 0, ErrorCodeConversion(ret), "SerialAddRight failed.")) {
metrics.SetErrorCode(ErrorCodeConversion(ret));
return nullptr;
}
return nullptr;
}
static auto g_serialRequestRightExecute = [](napi_env env, void* data) {
SerialRequestRightAsyncContext *asyncContext = static_cast<SerialRequestRightAsyncContext *>(data);
asyncContext->metrics = new UsbApiMetrics("BasicServicesKit.SerialManager.RequestSerialRight");
int32_t ret = g_usbClient.RequestSerialRight(asyncContext->portIdValue, asyncContext->hasRight);
asyncContext->contextErrno = 0;
if (ret != 0) {
USB_HILOGE(MODULE_USB_NAPI, "request right has error");
asyncContext->contextErrno = ErrorCodeConversion(ret);
}
};
static auto g_serialRequestRightComplete = [](napi_env env, napi_status status, void* data) {
SerialRequestRightAsyncContext *asyncContext = static_cast<SerialRequestRightAsyncContext *>(data);
napi_value result = nullptr;
if (asyncContext->contextErrno) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to request serial right");
if (asyncContext->metrics != nullptr) {
asyncContext->metrics->SetErrorCode(asyncContext->contextErrno);
}
napi_create_int32(env, asyncContext->contextErrno, &result);
napi_reject_deferred(env, asyncContext->deferred, result);
} else {
napi_get_boolean(env, asyncContext->hasRight, &result);
napi_resolve_deferred(env, asyncContext->deferred, result);
}
if (asyncContext->metrics != nullptr) {
delete asyncContext->metrics;
asyncContext->metrics = nullptr;
}
napi_delete_async_work(env, asyncContext->work);
delete asyncContext;
};
static napi_value SerialRequestRightNapi(napi_env env, napi_callback_info info)
{
size_t argc = ARGC_1;
napi_value argv[ARGC_1] = {nullptr};
if (!CheckNapiResult(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr),
"Get call back info failed")) {
CheckAndThrowOnError(env, false, SYSPARAM_INVALID_INPUT, "can not get arguments.");
return nullptr;
}
if (!CheckAndThrowOnError(env, (argc == ARGC_1), SYSPARAM_INVALID_INPUT, "The function takes 1 arguments.")) {
return nullptr;
}
napi_value portId = argv[0];
napi_valuetype type;
napi_typeof(env, portId, &type);
if (!CheckAndThrowOnError(env, type == napi_number, SYSPARAM_INVALID_INPUT,
"The type of portId must be int32_t.")) {
return nullptr;
}
int32_t portIdValue = -1;
napi_get_value_int32(env, portId, &portIdValue);
if (!CheckAndThrowOnError(env, (portIdValue != -1), SYSPARAM_INVALID_INPUT, "Failed to get portId.")) {
return nullptr;
}
SerialRequestRightAsyncContext* asyncContext = new (std::nothrow) SerialRequestRightAsyncContext;
if (!CheckAndThrowOnError(env, asyncContext != nullptr, SYSPARAM_INVALID_INPUT, "Failed to create promise.")) {
return nullptr;
}
asyncContext->portIdValue = portIdValue;
asyncContext->contextErrno = 0;
asyncContext->hasRight = false;
napi_value result = nullptr;
if (napi_create_promise(env, &asyncContext->deferred, &result)) {
USB_HILOGE(MODULE_USB_NAPI, "create promise failed!");
CheckAndThrowOnError(env, false, SERIAL_SERVICE_ABNORMAL, "promise is null");
delete asyncContext;
asyncContext = nullptr;
return nullptr;
}
napi_value resourceName;
napi_create_string_utf8(env, "SerialRequestRight", NAPI_AUTO_LENGTH, &resourceName);
napi_create_async_work(env, nullptr, resourceName, g_serialRequestRightExecute,
g_serialRequestRightComplete, static_cast<void*>(asyncContext), &asyncContext->work);
napi_queue_async_work(env, asyncContext->work);
return result;
}
static void SetEnumProperty(napi_env env, napi_value object, const std::string &name, int32_t value)
{
if (name.empty()) {
USB_HILOGE(MODULE_USB_NAPI, "Property name cannot be an empty string");
return;
}
napi_value tempValue = nullptr;
napi_status status = napi_create_int32(env, value, &tempValue);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to create int32 value for enum %{public}s", name.c_str());
return;
}
status = napi_set_named_property(env, object, name.c_str(), tempValue);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to set property %{public}s", name.c_str());
return;
}
}
static napi_value NapiCreateStopBitsTypeEnum(napi_env env)
{
napi_value object = nullptr;
napi_status status = napi_create_object(env, &object);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to create object");
return nullptr;
}
SetEnumProperty(env, object, "STOPBIT_1", STOPBIT_1);
SetEnumProperty(env, object, "STOPBIT_2", STOPBIT_2);
return object;
}
static napi_value NapiCreateParityTypeEnum(napi_env env)
{
napi_value object = nullptr;
napi_status status = napi_create_object(env, &object);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to create object");
return nullptr;
}
SetEnumProperty(env, object, "PARITY_NONE", PARITY_NONE);
SetEnumProperty(env, object, "PARITY_ODD", PARITY_ODD);
SetEnumProperty(env, object, "PARITY_EVEN", PARITY_EVEN);
SetEnumProperty(env, object, "PARITY_MARK", PARITY_MARK);
SetEnumProperty(env, object, "PARITY_SPACE", PARITY_SPACE);
return object;
}
static napi_value NapiCreateDataBitsTypeEnum(napi_env env)
{
napi_value object = nullptr;
napi_status status = napi_create_object(env, &object);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to create object");
return nullptr;
}
SetEnumProperty(env, object, "DATABIT_8", DATABIT_8);
SetEnumProperty(env, object, "DATABIT_7", DATABIT_7);
SetEnumProperty(env, object, "DATABIT_6", DATABIT_6);
SetEnumProperty(env, object, "DATABIT_5", DATABIT_5);
return object;
}
static napi_value NapiCreateBaudRatesTypeEnum(napi_env env)
{
napi_value object = nullptr;
napi_status status = napi_create_object(env, &object);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "Failed to create object");
return nullptr;
}
SetEnumProperty(env, object, "BAUDRATE_50", BAUDRATE_50);
SetEnumProperty(env, object, "BAUDRATE_75", BAUDRATE_75);
SetEnumProperty(env, object, "BAUDRATE_110", BAUDRATE_110);
SetEnumProperty(env, object, "BAUDRATE_134", BAUDRATE_134);
SetEnumProperty(env, object, "BAUDRATE_150", BAUDRATE_150);
SetEnumProperty(env, object, "BAUDRATE_200", BAUDRATE_200);
SetEnumProperty(env, object, "BAUDRATE_300", BAUDRATE_300);
SetEnumProperty(env, object, "BAUDRATE_600", BAUDRATE_600);
SetEnumProperty(env, object, "BAUDRATE_1200", BAUDRATE_1200);
SetEnumProperty(env, object, "BAUDRATE_1800", BAUDRATE_1800);
SetEnumProperty(env, object, "BAUDRATE_2400", BAUDRATE_2400);
SetEnumProperty(env, object, "BAUDRATE_4800", BAUDRATE_4800);
SetEnumProperty(env, object, "BAUDRATE_9600", BAUDRATE_9600);
SetEnumProperty(env, object, "BAUDRATE_19200", BAUDRATE_19200);
SetEnumProperty(env, object, "BAUDRATE_38400", BAUDRATE_38400);
SetEnumProperty(env, object, "BAUDRATE_57600", BAUDRATE_57600);
SetEnumProperty(env, object, "BAUDRATE_115200", BAUDRATE_115200);
SetEnumProperty(env, object, "BAUDRATE_230400", BAUDRATE_230400);
SetEnumProperty(env, object, "BAUDRATE_460800", BAUDRATE_460800);
SetEnumProperty(env, object, "BAUDRATE_500000", BAUDRATE_500000);
SetEnumProperty(env, object, "BAUDRATE_576000", BAUDRATE_576000);
SetEnumProperty(env, object, "BAUDRATE_921600", BAUDRATE_921600);
SetEnumProperty(env, object, "BAUDRATE_1000000", BAUDRATE_1000000);
SetEnumProperty(env, object, "BAUDRATE_1152000", BAUDRATE_1152000);
SetEnumProperty(env, object, "BAUDRATE_1500000", BAUDRATE_1500000);
SetEnumProperty(env, object, "BAUDRATE_2000000", BAUDRATE_2000000);
SetEnumProperty(env, object, "BAUDRATE_2500000", BAUDRATE_2500000);
SetEnumProperty(env, object, "BAUDRATE_3000000", BAUDRATE_3000000);
SetEnumProperty(env, object, "BAUDRATE_3500000", BAUDRATE_3500000);
SetEnumProperty(env, object, "BAUDRATE_4000000", BAUDRATE_4000000);
return object;
}
static napi_value DeclareEnum(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
DECLARE_NAPI_STATIC_PROPERTY("StopBits", NapiCreateStopBitsTypeEnum(env)),
DECLARE_NAPI_STATIC_PROPERTY("Parity", NapiCreateParityTypeEnum(env)),
DECLARE_NAPI_STATIC_PROPERTY("DataBits", NapiCreateDataBitsTypeEnum(env)),
DECLARE_NAPI_STATIC_PROPERTY("BaudRates", NapiCreateBaudRatesTypeEnum(env)),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
return exports;
}
EXTERN_C_START
* function for module exports
*/
napi_value SerialInit(napi_env env, napi_value exports)
{
USB_HILOGD(MODULE_USB_NAPI, "enter");
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("getPortList", SerialGetPortListNapi),
DECLARE_NAPI_FUNCTION("open", SerialOpenNapi),
DECLARE_NAPI_FUNCTION("close", SerialCloseNapi),
DECLARE_NAPI_FUNCTION("read", SerialReadNapi),
DECLARE_NAPI_FUNCTION("readSync", SerialReadSyncNapi),
DECLARE_NAPI_FUNCTION("write", SerialWriteNapi),
DECLARE_NAPI_FUNCTION("writeSync", SerialWriteSyncNapi),
DECLARE_NAPI_FUNCTION("getAttribute", SerialGetAttributeNapi),
DECLARE_NAPI_FUNCTION("setAttribute", SerialSetAttributeNapi),
DECLARE_NAPI_FUNCTION("hasSerialRight", SerialHasRightNapi),
DECLARE_NAPI_FUNCTION("requestSerialRight", SerialRequestRightNapi),
DECLARE_NAPI_FUNCTION("addSerialRight", SerialAddRightNapi),
DECLARE_NAPI_FUNCTION("cancelSerialRight", CancelSerialRightNapi),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
DeclareEnum(env, exports);
USB_HILOGD(MODULE_USB_NAPI, "return");
return exports;
}
EXTERN_C_END