* Copyright (c) 2026 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 "usb_cli_serialization.h"
#include "cJSON.h"
#include "usb_config.h"
#include "usb_endpoint.h"
#include "usb_errors.h"
#include "usb_interface.h"
#define ARG_ONE 1
#define ARG_TWO 2
#define JSON_ERR_STR "{\"type\":\"result\",\"status\":\"failed\",\"errCode\":\"\",\"errMsg\":\"\",\"suggestion\":\"\"}"
namespace OHOS {
namespace USB {
static cJSON* SerializeEndpoint(USBEndpoint &endpoint)
{
cJSON *json = cJSON_CreateObject();
if (!json) {
return nullptr;
}
cJSON_AddNumberToObject(json, "address", static_cast<double>(endpoint.GetAddress()));
cJSON_AddNumberToObject(json, "attributes", static_cast<double>(endpoint.GetAttributes()));
cJSON_AddNumberToObject(json, "interval", static_cast<double>(endpoint.GetInterval()));
cJSON_AddNumberToObject(json, "maxPacketSize", static_cast<double>(endpoint.GetMaxPacketSize()));
cJSON_AddNumberToObject(json, "direction", static_cast<double>(endpoint.GetDirection()));
cJSON_AddNumberToObject(json, "number", static_cast<double>(endpoint.GetEndpointNumber()));
cJSON_AddNumberToObject(json, "type", static_cast<double>(endpoint.GetType()));
cJSON_AddNumberToObject(json, "interfaceId", static_cast<double>(endpoint.GetInterfaceId()));
return json;
}
static cJSON* SerializeInterface(UsbInterface &iface)
{
cJSON *json = cJSON_CreateObject();
if (!json) {
return nullptr;
}
cJSON_AddNumberToObject(json, "id", static_cast<double>(iface.GetId()));
cJSON_AddNumberToObject(json, "protocol", static_cast<double>(iface.GetProtocol()));
cJSON_AddNumberToObject(json, "clazz", static_cast<double>(iface.GetClass()));
cJSON_AddNumberToObject(json, "subClass", static_cast<double>(iface.GetSubClass()));
cJSON_AddNumberToObject(json, "alternateSetting", static_cast<double>(iface.GetAlternateSetting()));
cJSON_AddStringToObject(json, "name", iface.GetName().c_str());
cJSON *endpoints = cJSON_CreateArray();
if (!endpoints) {
cJSON_Delete(json);
return nullptr;
}
auto &eps = iface.GetEndpoints();
for (size_t i = 0; i < eps.size(); ++i) {
cJSON *ep = SerializeEndpoint(eps[i]);
if (ep) {
if (!cJSON_AddItemToArray(endpoints, ep)) {
cJSON_Delete(ep);
}
}
}
if (!cJSON_AddItemToObject(json, "endpoints", endpoints)) {
cJSON_Delete(endpoints);
cJSON_Delete(json);
return nullptr;
}
return json;
}
static cJSON* SerializeConfig(USBConfig &config)
{
cJSON *json = cJSON_CreateObject();
if (!json) {
return nullptr;
}
cJSON_AddNumberToObject(json, "id", static_cast<double>(config.GetId()));
cJSON_AddNumberToObject(json, "attributes", static_cast<double>(config.GetAttributes()));
cJSON_AddNumberToObject(json, "maxPower", static_cast<double>(config.GetMaxPower()));
cJSON_AddStringToObject(json, "name", config.GetName().c_str());
cJSON_AddBoolToObject(json, "isRemoteWakeup", config.IsRemoteWakeup());
cJSON_AddBoolToObject(json, "isSelfPowered", config.IsSelfPowered());
cJSON *interfaces = cJSON_CreateArray();
if (!interfaces) {
cJSON_Delete(json);
return nullptr;
}
for (uint32_t i = 0; i < config.GetInterfaceCount(); ++i) {
UsbInterface iface;
if (config.GetInterface(i, iface)) {
cJSON *intf = SerializeInterface(iface);
if (intf) {
cJSON_AddItemToArray(interfaces, intf);
}
}
}
cJSON_AddItemToObject(json, "interfaces", interfaces);
return json;
}
cJSON* SerializeDevice(UsbDevice &device)
{
cJSON *json = cJSON_CreateObject();
if (!json) {
return nullptr;
}
cJSON_AddNumberToObject(json, "busNum", static_cast<double>(device.GetBusNum()));
cJSON_AddNumberToObject(json, "devAddress", static_cast<double>(device.GetDevAddr()));
cJSON_AddStringToObject(json, "serial", "");
cJSON_AddStringToObject(json, "name", device.GetName().c_str());
cJSON_AddStringToObject(json, "manufacturerName", device.GetManufacturerName().c_str());
cJSON_AddStringToObject(json, "productName", device.GetProductName().c_str());
cJSON_AddStringToObject(json, "version", device.GetVersion().c_str());
cJSON_AddNumberToObject(json, "vendorId", static_cast<double>(device.GetVendorId()));
cJSON_AddNumberToObject(json, "productId", static_cast<double>(device.GetProductId()));
cJSON_AddNumberToObject(json, "clazz", static_cast<double>(device.GetClass()));
cJSON_AddNumberToObject(json, "subClass", static_cast<double>(device.GetSubclass()));
cJSON_AddNumberToObject(json, "protocol", static_cast<double>(device.GetProtocol()));
cJSON *configs = cJSON_CreateArray();
if (!configs) {
cJSON_Delete(json);
return nullptr;
}
auto &cfgs = device.GetConfigs();
for (size_t i = 0; i < cfgs.size(); ++i) {
cJSON *cfg = SerializeConfig(cfgs[i]);
if (cfg) {
cJSON_AddItemToArray(configs, cfg);
}
}
cJSON_AddItemToObject(json, "configs", configs);
return json;
}
cJSON* SerializeAccessory(const USBAccessory &accessory)
{
cJSON *json = cJSON_CreateObject();
if (!json) {
return nullptr;
}
cJSON_AddStringToObject(json, "manufacturer", accessory.GetManufacturer().c_str());
cJSON_AddStringToObject(json, "product", accessory.GetProduct().c_str());
cJSON_AddStringToObject(json, "description", accessory.GetDescription().c_str());
cJSON_AddStringToObject(json, "version", accessory.GetVersion().c_str());
cJSON_AddStringToObject(json, "serialNumber", "");
return json;
}
cJSON* SerializeSerialPort(const UsbSerialPort &port)
{
cJSON *json = cJSON_CreateObject();
if (!json) {
return nullptr;
}
cJSON_AddNumberToObject(json, "portId", static_cast<double>(port.portId_));
std::string deviceName = std::to_string(port.busNum_) + "-" + std::to_string(port.devAddr_);
cJSON_AddStringToObject(json, "deviceName", deviceName.c_str());
return json;
}
std::string FormatSuccess(const std::vector<cJSON*> &items)
{
cJSON *root = cJSON_CreateObject();
if (!root) {
for (auto *item : items) {
cJSON_Delete(item);
}
return JSON_ERR_STR;
}
cJSON_AddStringToObject(root, "type", "result");
cJSON_AddStringToObject(root, "status", "success");
cJSON *data = cJSON_CreateObject();
if (!data) {
for (auto *item : items) {
cJSON_Delete(item);
}
cJSON_Delete(root);
return JSON_ERR_STR;
}
cJSON *list = cJSON_CreateArray();
if (!list) {
for (auto *item : items) {
cJSON_Delete(item);
}
cJSON_Delete(data);
cJSON_Delete(root);
return JSON_ERR_STR;
}
for (auto *item : items) {
if (item) {
cJSON_AddItemToArray(list, item);
}
}
cJSON_AddNumberToObject(data, "number", static_cast<double>(cJSON_GetArraySize(list)));
cJSON_AddItemToObject(data, "list", list);
cJSON_AddItemToObject(root, "data", data);
char *output = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
if (!output) {
return JSON_ERR_STR;
}
std::string result(output);
cJSON_free(output);
return result;
}
static std::string GetErrorCodeString(int32_t code)
{
if (code == ARG_ONE) {
return "MISSING_SUBCOMMAND";
}
if (code == ARG_TWO) {
return "UNKNOWN_SUBCOMMAND";
}
if (code == UEC_INTERFACE_NO_INIT || code == UEC_SERVICE_NO_INIT) {
return "USB_SERVICE_UNAVAILABLE";
}
if (code == UEC_INTERFACE_PERMISSION_DENIED || code == UEC_SERVICE_PERMISSION_DENIED) {
return "PERMISSION_DENIED";
}
if (code == UEC_SERIAL_PORT_NOT_EXIST) {
return "SERIAL_PORT_NOT_FOUND";
}
return "QUERY_FAILED";
}
static std::string GetErrorSuggestion(int32_t code)
{
if (code == 1) {
return "Run './ohos-usbManager --help' for available commands.";
}
return "Please check if the device is connected and the connection is normal.";
}
std::string FormatError(int32_t code, const std::string &message)
{
cJSON *root = cJSON_CreateObject();
if (!root) {
return JSON_ERR_STR;
}
cJSON_AddStringToObject(root, "type", "result");
cJSON_AddStringToObject(root, "status", "failed");
cJSON_AddStringToObject(root, "errCode", GetErrorCodeString(code).c_str());
cJSON_AddStringToObject(root, "errMsg", message.c_str());
cJSON_AddStringToObject(root, "suggestion", GetErrorSuggestion(code).c_str());
char *output = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
if (!output) {
return JSON_ERR_STR;
}
std::string result(output);
cJSON_free(output);
return result;
}
}
}