• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/backend/usb_manager.cxx b/backend/usb_manager.cxx
2new file mode 100644
3index 0000000..baf329a
4--- /dev/null
5+++ b/backend/usb_manager.cxx
6@@ -0,0 +1,683 @@
7+/*
8+ * Copyright (c) 2024 Huawei Device Co., Ltd.
9+ * Licensed under the Apache License, Version 2.0 (the "License");
10+ * you may not use this file except in compliance with the License.
11+ * You may obtain a copy of the License at
12+ *
13+ *     http://www.apache.org/licenses/LICENSE-2.0
14+ *
15+ * Unless required by applicable law or agreed to in writing, software
16+ * distributed under the License is distributed on an "AS IS" BASIS,
17+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+ * See the License for the specific language governing permissions and
19+ * limitations under the License.
20+ */
21+
22+/*
23+ * OH USB interface code for CUPS.
24+ */
25+
26+/*
27+ * Include necessary headers.
28+ */
29+
30+#include "usb_manager.h"
31+#include "usb_srv_client.h"
32+#include "v1_0/iusb_interface.h"
33+
34+#include <map>
35+#include <regex>
36+#include <string>
37+#include <thread>
38+#include <securec.h>
39+
40+using namespace std;
41+using namespace OHOS;
42+using namespace OHOS::USB;
43+
44+#define SAFE_DELETE(ptr)    \
45+    if ((ptr) != nullptr) { \
46+        delete (ptr);       \
47+        (ptr) = nullptr;    \
48+    }
49+
50+#define SAFE_DELETE_ARRAY(ptr) \
51+    if ((ptr) != nullptr) {    \
52+        delete[] (ptr);        \
53+        (ptr) = nullptr;       \
54+    }
55+
56+int32_t BulkTransferWriteData(
57+    USBDevicePipe &usbDevicePipe, USBEndpoint &endpoint, const std::string &sendDataStr, int32_t timeout);
58+int32_t ParseDeviceDescriptor(UsbDevice &usbDevice, ohusb_device_descriptor *devDesc);
59+int32_t ParseConfigDescriptor(USBConfig &usbConfig, ohusb_config_descriptor *confDesc);
60+int32_t ParseInterface(std::vector<UsbInterface> &usbIfaces, ohusb_interface *usbInterface, int32_t ifaceIndex);
61+int32_t ParseInterfaceDescriptor(UsbInterface &usbInterface, ohusb_interface_descriptor *ifaceDesc);
62+int32_t ParseEndpointDescriptor(USBEndpoint &usbEndpoint, ohusb_endpoint_descriptor *epDesc);
63+void ReleaseDeviceDescriptor(ohusb_device_descriptor *devDesc);
64+void ReleaseConfigDescriptor(ohusb_config_descriptor *confDesc);
65+void ReleaseInterface(ohusb_interface *iface);
66+void ReleaseInterfaceDescriptor(ohusb_interface_descriptor *ifaceDesc);
67+void DumpDeviceDescriptor(ohusb_device_descriptor *devdesc);
68+void DumpConfigDescriptor(ohusb_config_descriptor *confDesc);
69+void DumpInterfaceDescriptor(ohusb_interface_descriptor *ifaceDesc);
70+void DumpEndpointDescriptor(ohusb_endpoint_descriptor *eptDesc);
71+char *CopyString(const std::string &source);
72+
73+int32_t OH_GetDevices(ohusb_device_descriptor** list, ssize_t *numdevs)
74+{
75+    fprintf(stderr, "DEBUG: OH_GetDevices enter\n");
76+    vector<UsbDevice> devlist;
77+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
78+    auto getDevRet = usbSrvClient.GetDevices(devlist);
79+    fprintf(stderr, "DEBUG: OH_GetDevices getDevRet = %d\n", getDevRet);
80+    if (getDevRet != OHOS::ERR_OK) {
81+        return OHUSB_ERROR_IO;
82+    }
83+    if (devlist.empty()) {
84+        return OHUSB_SUCCESS;
85+    }
86+    ssize_t devCount = devlist.size();
87+    *numdevs = 0;
88+    fprintf(stderr, "DEBUG: OH_GetDevices device nums = %zd\n", devCount);
89+
90+    *list = (ohusb_device_descriptor *)calloc((size_t)devCount, sizeof(ohusb_device_descriptor));
91+    if (*list == nullptr) {
92+        fprintf(stderr, "DEBUG: OH_GetDevices list is nullptr\n");
93+        return OHUSB_ERROR_NO_MEM;
94+    }
95+    for (ssize_t i = 0; i < devCount; i++) {
96+        fprintf(stderr, "DEBUG: OH_GetDevices devlist[%zd] devAddr = %d, busNum = %d\n",
97+            i, devlist[i].GetDevAddr(), devlist[i].GetBusNum());
98+        if (ParseDeviceDescriptor(devlist[i], *list + i) != OHUSB_SUCCESS) {
99+            return OHUSB_ERROR_IO;
100+        }
101+        (*numdevs)++;
102+    }
103+    return OHUSB_SUCCESS;
104+}
105+
106+int32_t OH_OpenDevice(ohusb_device_descriptor *devDesc, ohusb_pipe **pipe)
107+{
108+    fprintf(stderr, "DEBUG: OH_OpenDevice enter\n");
109+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
110+    UsbDevice usbDevice;
111+    usbDevice.SetBusNum(devDesc->busNum);
112+    usbDevice.SetDevAddr(devDesc->devAddr);
113+    USBDevicePipe usbDevicePipe;
114+    auto openDevRet = usbSrvClient.OpenDevice(usbDevice, usbDevicePipe);
115+    fprintf(stderr, "DEBUG: OH_OpenDevice getDevRet = %d\n", openDevRet);
116+    if (openDevRet != OHOS::ERR_OK) {
117+        return OHUSB_ERROR_IO;
118+    }
119+    *pipe = (ohusb_pipe *)calloc(1, sizeof(ohusb_pipe));
120+    if (*pipe == nullptr) {
121+        fprintf(stderr, "DEBUG: OH_OpenDevice pipe is nullptr\n");
122+        return OHUSB_ERROR_NO_MEM;
123+    }
124+    (*pipe)->busNum = usbDevicePipe.GetBusNum();
125+    (*pipe)->devAddr = usbDevicePipe.GetDevAddr();
126+    fprintf(stderr, "DEBUG: OH_OpenDevice busNum=%d, devAddr=%d\n", (*pipe)->busNum, (*pipe)->devAddr);
127+    fprintf(stderr, "DEBUG: OH_OpenDevice out\n");
128+    return OHUSB_SUCCESS;
129+}
130+
131+int32_t OH_CloseDevice(ohusb_pipe *pipe)
132+{
133+    fprintf(stderr, "DEBUG: OH_CloseDevice enter\n");
134+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
135+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
136+    int32_t ret = usbSrvClient.Close(usbDevicePipe);
137+    if (ret != ERR_OK) {
138+        fprintf(stderr, "DEBUG: OH_CloseDevice fail with ret = %d\n", ret);
139+        return OHUSB_ERROR_BUSY;
140+    }
141+    fprintf(stderr, "DEBUG: OH_CloseDevice out\n");
142+    return OHUSB_SUCCESS;
143+}
144+
145+int32_t OH_ClaimInterface(ohusb_pipe *pipe, int interfaceId, bool force)
146+{
147+    fprintf(stderr, "DEBUG: OH_ClaimInterface enter\n");
148+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
149+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
150+    UsbInterface usbInterface;
151+    usbInterface.SetId(interfaceId);
152+    int32_t ret = usbSrvClient.ClaimInterface(usbDevicePipe, usbInterface, force);
153+    if (ret != ERR_OK) {
154+        fprintf(stderr, "DEBUG: OH_ClaimInterface fail with ret = %d\n", ret);
155+        return OHUSB_ERROR_BUSY;
156+    }
157+    fprintf(stderr, "DEBUG: OH_ClaimInterface out\n");
158+    return OHUSB_SUCCESS;
159+}
160+
161+int32_t OH_ReleaseInterface(ohusb_pipe *pipe, int interfaceId)
162+{
163+    fprintf(stderr, "DEBUG: OH_ReleaseInterface enter\n");
164+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
165+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
166+    UsbInterface usbInterface;
167+    usbInterface.SetId(interfaceId);
168+    int32_t ret = usbSrvClient.ReleaseInterface(usbDevicePipe, usbInterface);
169+    if (ret != ERR_OK) {
170+        fprintf(stderr, "DEBUG: OH_ReleaseInterface fail with ret = %d\n", ret);
171+        return OHUSB_ERROR_BUSY;
172+    }
173+    fprintf(stderr, "DEBUG: OH_ReleaseInterface out\n");
174+    return OHUSB_SUCCESS;
175+}
176+
177+int32_t OH_BulkTransferRead(
178+    ohusb_pipe *pipe, ohusb_transfer_pipe *tpipe, unsigned char *data, int length, int *transferred)
179+{
180+    fprintf(stderr, "DEBUG: OH_BulkTransferRead enter\n");
181+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
182+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
183+    USBEndpoint endpoint;
184+    endpoint.SetInterfaceId(tpipe->bInterfaceId);
185+    endpoint.SetAddr(tpipe->bEndpointAddress);
186+    std::vector<uint8_t> readTempBuffer;
187+    size_t readSize = 0;
188+    int32_t ret = usbSrvClient.BulkTransfer(usbDevicePipe, endpoint, readTempBuffer, OHUSB_BULKTRANSFER_READ_TIMEOUT);
189+    fprintf(stderr, "DEBUG: OH_BulkTransferRead ret = %d\n", ret);
190+    if (ret == HDF_DEV_ERR_NO_DEVICE) {
191+        fprintf(stderr, "DEBUG: OH_BulkTransferRead HDF_DEV_ERR_NO_DEVICE, The device module has no device\n");
192+        return OHUSB_ERROR_NO_DEVICE;
193+    }
194+    readSize = readTempBuffer.size();
195+    fprintf(stderr, "DEBUG: OH_BulkTransferRead readSize = %zu\n", readSize);
196+    if (ret == OHUSB_SUCCESS) {
197+        if (readSize < 512) {
198+            std::copy(readTempBuffer.begin(), readTempBuffer.begin() + readSize, data);
199+            *transferred = readSize;
200+        }
201+        return OHUSB_SUCCESS;
202+    }
203+
204+    fprintf(stderr, "DEBUG: OH_BulkTransferRead read data time out\n");
205+    return OHUSB_ERROR_TIMEOUT;
206+}
207+
208+int32_t OH_BulkTransferWrite(
209+    ohusb_pipe *pipe, ohusb_transfer_pipe *tpipe, unsigned char *data, int length, int *transferred, int32_t timeout)
210+{
211+    fprintf(stderr, "DEBUG: OH_BulkTransferRead enter\n");
212+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
213+    USBEndpoint endpoint;
214+    endpoint.SetInterfaceId(tpipe->bInterfaceId);
215+    endpoint.SetAddr(tpipe->bEndpointAddress);
216+    int32_t ret = 0;
217+    int leftDataLen = length;
218+    while (leftDataLen > 0) {
219+        fprintf(stderr, "DEBUG: OH_BulkTransferWrite leftDataLen waiting for transfer = %d\n", leftDataLen);
220+        size_t len = leftDataLen > OHUSB_ENDPOINT_MAX_LENGTH ? OHUSB_ENDPOINT_MAX_LENGTH : leftDataLen;
221+        std::string sendDataStr(reinterpret_cast<char *>(data), len);
222+        ret = BulkTransferWriteData(usbDevicePipe, endpoint, sendDataStr, timeout);
223+        if (ret == OHUSB_ERROR_IO) {
224+            fprintf(stderr, "DEBUG: OH_BulkTransferWrite OHUSB_ERROR_IO\n");
225+            int32_t claimRet = OH_ClaimInterface(pipe, tpipe->bClaimedInterfaceId, true);
226+            if (claimRet >= 0) {
227+                fprintf(stderr, "DEBUG: OH_BulkTransferWrite OH_ClaimInterface success ret = %d\n", claimRet);
228+                continue;
229+            }
230+        }
231+        if (ret != 0) {
232+            return ret;
233+        }
234+        fprintf(stderr, "DEBUG: OH_BulkTransferWrite transferred data len = %zu\n", len);
235+        leftDataLen -= len;
236+        data += len;
237+    }
238+    *transferred = length - leftDataLen;
239+    fprintf(stderr, "DEBUG: transferred data len = %d\n", *transferred);
240+    fprintf(stderr, "DEBUG: OH_BulkTransferWrite out\n");
241+    return OHUSB_SUCCESS;
242+}
243+
244+int32_t BulkTransferWriteData(
245+    USBDevicePipe &usbDevicePipe, USBEndpoint &endpoint, const std::string &sendDataStr, int32_t timeout)
246+{
247+    std::vector<uint8_t> vectorRequestBuffer;
248+    vectorRequestBuffer.assign(sendDataStr.begin(), sendDataStr.end());
249+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
250+    uint32_t retryNum = 0;
251+    int32_t ret = 0;
252+    do {
253+        fprintf(stderr, "DEBUG: BulkTransferWriteData write data retryCout: %d\n", retryNum);
254+        ret = usbSrvClient.BulkTransfer(usbDevicePipe, endpoint, vectorRequestBuffer, timeout);
255+        fprintf(stderr, "DEBUG: BulkTransferWrite ret: %d\n", ret);
256+        if (ret == HDF_DEV_ERR_NO_DEVICE) {
257+            fprintf(stderr, "DEBUG: BulkTransferWriteData no device\n");
258+            return OHUSB_ERROR_NO_DEVICE;
259+        }
260+        if (ret == OHUSB_ERROR_IO) {
261+            fprintf(stderr, "DEBUG: BulkTransferWriteData OHUSB_ERROR_IO\n");
262+            return OHUSB_ERROR_IO;
263+        }
264+        if (ret == OHUSB_ERROR_TIMEOUT) {
265+            std::this_thread::sleep_for(std::chrono::milliseconds(OHUSB_BULKTRANSFER_WRITE_SLEEP));
266+        }
267+        retryNum++;
268+    } while (ret != OHUSB_SUCCESS && retryNum < OHUSB_WRITE_RETRY_MAX_TIMES);
269+    if (ret != 0) {
270+        fprintf(stderr, "DEBUG: Write data fail\n");
271+        return ret;
272+    }
273+    return ret;
274+}
275+
276+int32_t OH_ControlTransferRead(
277+    ohusb_pipe *pipe, ohusb_control_transfer_parameter *ctrlParam, unsigned char *data, uint16_t length)
278+{
279+    fprintf(stderr, "DEBUG: OH_ControlTransferRead enter\n");
280+    if (pipe == nullptr || ctrlParam == nullptr) {
281+        fprintf(stderr, "DEBUG: pipe or ctrlParam is nullptr\n");
282+        return OHUSB_ERROR_IO;
283+    }
284+    fprintf(stderr, "DEBUG: OH_ControlTransferRead busNum=%d, devAddr=%d\n", pipe->busNum, pipe->devAddr);
285+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
286+    int32_t requestType = ctrlParam->requestType;
287+    int32_t request = ctrlParam->request;
288+    int32_t value = ctrlParam->value;
289+    int32_t index = ctrlParam->index;
290+    int32_t timeOut = ctrlParam->timeout;
291+    const HDI::Usb::V1_0::UsbCtrlTransfer tctrl = {requestType, request, value, index, timeOut};
292+    std::vector<uint8_t> bufferData(length, 0);
293+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
294+    uint32_t retryNum = 0;
295+    int32_t ret = OHUSB_SUCCESS;
296+    do {
297+        ret = usbSrvClient.ControlTransfer(usbDevicePipe, tctrl, bufferData);
298+        retryNum++;
299+    } while ((ret != OHUSB_SUCCESS || bufferData.size() == 0) && retryNum < OHUSB_CONTROLTRANSFER_READ_RETRY_MAX_TIMES);
300+    fprintf(stderr, "DEBUG: OH_ControlTransferRead ret = %d, retryCount: %d\n", ret, retryNum);
301+    if (ret != 0) {
302+        fprintf(stderr, "DEBUG: OH_ControlTransferRead fail\n");
303+        return OHUSB_ERROR_IO;
304+    }
305+    fprintf(stderr, "DEBUG: OH_ControlTransferRead bufferData size = %zu\n", bufferData.size());
306+
307+    if (bufferData.size() == 0) {
308+        return 0;
309+    }
310+
311+    if ((value >> 8) == OHUSB_DT_STRING) {
312+        int bufferLen = bufferData.size();
313+        uint16_t *wbuf = new (std::nothrow) uint16_t[bufferLen + 1]();
314+        if (wbuf == nullptr) {
315+            fprintf(stderr, "DEBUG: OH_ControlTransferRead wbuf is nullptr.\n");
316+            return OHUSB_ERROR_NO_MEM;
317+        }
318+        for (uint32_t i = 0; i < bufferLen - 2; ++i) {
319+            wbuf[i] = bufferData[i + 2];
320+        }
321+        std::wstring wstr(reinterpret_cast<wchar_t *>(wbuf), (bufferLen - 2) / 2);
322+        std::string buffer(wstr.begin(), wstr.end());
323+        fprintf(stderr, "DEBUG: OH_ControlTransferRead buffer = %s\n", buffer.c_str());
324+        if (memcpy_s(data, length, buffer.c_str(), buffer.length()) != 0) {
325+            fprintf(stderr, "DEBUG: OH_ControlTransferRead memcpy_s fail.\n");
326+            return OHUSB_ERROR_NO_MEM;
327+        }
328+    } else if (memcpy_s(data, length, bufferData.data(), bufferData.size()) != 0) {
329+        fprintf(stderr, "DEBUG: OH_ControlTransferRead memcpy_s fail.\n");
330+        return OHUSB_ERROR_NO_MEM;
331+    }
332+
333+    fprintf(stderr, "DEBUG: OH_ControlTransferRead out\n");
334+    return bufferData.size();
335+}
336+
337+int32_t OH_ControlTransferWrite(
338+    ohusb_pipe *pipe, ohusb_control_transfer_parameter *ctrlParam, unsigned char *data, uint16_t length)
339+{
340+    fprintf(stderr, "DEBUG: OH_ControlTransferWrite enter\n");
341+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
342+    int32_t requestType = ctrlParam->requestType;
343+    int32_t request = ctrlParam->request;
344+    int32_t value = ctrlParam->value;
345+    int32_t index = ctrlParam->index;
346+    int32_t timeOut = ctrlParam->timeout;
347+    const HDI::Usb::V1_0::UsbCtrlTransfer tctrl = {requestType, request, value, index, timeOut};
348+    std::vector<uint8_t> bufferData(length, 0);
349+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
350+    int32_t ret = usbSrvClient.ControlTransfer(usbDevicePipe, tctrl, bufferData);
351+    if (ret != 0) {
352+        fprintf(stderr, "DEBUG: OH_ControlTransferWrite fail with ret = %d\n", ret);
353+        return OHUSB_ERROR_IO;
354+    }
355+
356+    fprintf(stderr, "DEBUG: OH_ControlTransferWrite out\n");
357+    return length;
358+}
359+
360+int32_t OH_GetStringDescriptor(ohusb_pipe *pipe, int descId, unsigned char *descriptor, int length)
361+{
362+    fprintf(stderr, "DEBUG: OH_GetStringDescriptor enter\n");
363+    if (descId == 0) {
364+		return OHUSB_ERROR_INVALID_PARAM;
365+    }
366+    ohusb_control_transfer_parameter ctrlParam = {
367+        OHUSB_ENDPOINT_IN,
368+        OHUSB_REQUEST_GET_DESCRIPTOR,
369+        (uint16_t)((OHUSB_DT_STRING << 8) | descId),
370+        OHUSB_LANGUAGE_ID_ENGLISH,
371+        OHUSB_GET_STRING_DESCRIPTOR_TIMEOUT
372+    };
373+    auto ret = OH_ControlTransferRead(pipe, &ctrlParam, descriptor, length);
374+    if (ret <= 0) {
375+        fprintf(stderr, "DEBUG: OH_GetStringDescriptor OH_ControlTransferRead failed\n");
376+        return ret;
377+    }
378+
379+    fprintf(stderr, "DEBUG: OH_GetStringDescriptor out\n");
380+    return ret;
381+}
382+
383+int32_t ParseDeviceDescriptor(UsbDevice &usbDevice, ohusb_device_descriptor *devDesc)
384+{
385+    fprintf(stderr, "DEBUG: ParseDeviceDescriptor enter\n");
386+    if (devDesc == nullptr) {
387+        fprintf(stderr, "DEBUG: ParseDeviceDescriptor devDesc is nullptr\n");
388+        return OHUSB_ERROR_NO_MEM;
389+    }
390+
391+    devDesc->devAddr = usbDevice.GetDevAddr();
392+    devDesc->busNum = usbDevice.GetBusNum();
393+    devDesc->bcdUSB = usbDevice.GetbcdUSB();
394+    devDesc->bDeviceClass = usbDevice.GetClass();
395+    devDesc->bDeviceSubClass = usbDevice.GetSubclass();
396+    devDesc->bDeviceProtocol = usbDevice.GetProtocol();
397+    devDesc->bMaxPacketSize0 = usbDevice.GetbMaxPacketSize0();
398+    devDesc->idVendor = usbDevice.GetVendorId();
399+    devDesc->idProduct = usbDevice.GetProductId();
400+    devDesc->iManufacturer = usbDevice.GetiManufacturer();
401+    devDesc->iProduct = usbDevice.GetiProduct();
402+    devDesc->iSerialNumber = usbDevice.GetiSerialNumber();
403+    devDesc->bNumConfigurations = 0;
404+    ohusb_config_descriptor *config =
405+        (ohusb_config_descriptor *)calloc((size_t)usbDevice.GetConfigCount(), sizeof(ohusb_config_descriptor));
406+    if (config == nullptr) {
407+        fprintf(stderr, "DEBUG: ParseDeviceDescriptor config is null.\n");
408+        return OHUSB_ERROR_NO_MEM;
409+    }
410+    devDesc->config = config;
411+
412+    for (int i = 0; i < usbDevice.GetConfigCount(); i++) {
413+        USBConfig usbConfig;
414+        usbDevice.GetConfig(i, usbConfig);
415+        if (ParseConfigDescriptor(usbConfig, config + i) != OHUSB_SUCCESS) {
416+            return OHUSB_ERROR_IO;
417+        }
418+        (devDesc->bNumConfigurations)++;
419+    }
420+    DumpDeviceDescriptor(devDesc);
421+    fprintf(stderr, "DEBUG: ParseDeviceDescriptor out\n");
422+    return OHUSB_SUCCESS;
423+}
424+
425+int32_t ParseConfigDescriptor(USBConfig &usbConfig, ohusb_config_descriptor *confDesc)
426+{
427+    fprintf(stderr, "DEBUG: ParseConfigDescriptor enter\n");
428+    if (confDesc == nullptr) {
429+        fprintf(stderr, "DEBUG: ParseConfigDescriptor confDesc is nullptr\n");
430+        return OHUSB_ERROR_NO_MEM;
431+    }
432+    confDesc->iConfiguration = usbConfig.GetId();
433+    confDesc->bmAttributes = usbConfig.GetAttributes();
434+    confDesc->MaxPower = usbConfig.GetMaxPower();
435+
436+    std::vector<UsbInterface> usbIfaces = usbConfig.GetInterfaces();
437+    int32_t ifaceCount = usbIfaces.size() > 0 ? usbIfaces[usbIfaces.size() - 1].GetId() + 1 : 0;
438+
439+    confDesc->bNumInterfaces = 0;
440+    ohusb_interface *usbInterface =
441+        (ohusb_interface *)calloc((size_t)ifaceCount, sizeof(ohusb_interface));
442+    if (usbInterface == nullptr) {
443+        fprintf(stderr, "DEBUG: ParseConfigDescriptor usbInterface is nullptr\n");
444+        return OHUSB_ERROR_NO_MEM;
445+    }
446+    confDesc->interface = usbInterface;
447+    for (int32_t ifaceIndex = 0; ifaceIndex < ifaceCount; ifaceIndex++) {
448+        if (ParseInterface(usbIfaces, usbInterface + ifaceIndex, ifaceIndex) != OHUSB_SUCCESS) {
449+            return OHUSB_ERROR_IO;
450+        }
451+        (confDesc->bNumInterfaces)++;
452+    }
453+    DumpConfigDescriptor(confDesc);
454+    fprintf(stderr, "DEBUG: ParseConfigDescriptor out\n");
455+    return OHUSB_SUCCESS;
456+}
457+
458+int32_t ParseInterface(std::vector<UsbInterface> &usbIfaces, ohusb_interface *usbInterface, int32_t ifaceIndex)
459+{
460+    fprintf(stderr, "DEBUG: ParseInterface ifaceIndex=%d\n", ifaceIndex);
461+    for (int32_t usbIfacesIndex = 0; usbIfacesIndex < usbIfaces.size(); usbIfacesIndex++) {
462+        if (usbIfaces[usbIfacesIndex].GetId() == ifaceIndex) {
463+            ohusb_interface_descriptor *altsetting;
464+            altsetting = (ohusb_interface_descriptor *)
465+                calloc((size_t)(usbInterface->num_altsetting + 1), sizeof(*altsetting));
466+            if (altsetting == nullptr) {
467+                fprintf(stderr, "DEBUG: ParseInterface altsetting is nullptr\n");
468+                return OHUSB_ERROR_NO_MEM;
469+            }
470+            if (usbInterface->num_altsetting != 0 &&
471+                memcpy_s(altsetting, sizeof(*altsetting) * (size_t)(usbInterface->num_altsetting),
472+                usbInterface->altsetting, sizeof(*altsetting) * (size_t)(usbInterface->num_altsetting)) != 0) {
473+                fprintf(stderr, "DEBUG: ParseInterface memcpy_s fail.\n");
474+                return OHUSB_ERROR_NO_MEM;
475+            }
476+            usbInterface->altsetting = altsetting;
477+            if (ParseInterfaceDescriptor(usbIfaces[usbIfacesIndex], altsetting + (usbInterface->num_altsetting))
478+                != OHUSB_SUCCESS) {
479+                return OHUSB_ERROR_IO;
480+            }
481+            usbInterface->num_altsetting++;
482+        }
483+    }
484+    fprintf(stderr, "DEBUG: ParseInterface num_altsetting=%d\n", usbInterface->num_altsetting);
485+    return OHUSB_SUCCESS;
486+}
487+
488+int32_t ParseInterfaceDescriptor(UsbInterface &usbInterface, ohusb_interface_descriptor *ifaceDesc)
489+{
490+    fprintf(stderr, "DEBUG: ParseInterfaceDescriptor enter\n");
491+    if (ifaceDesc == nullptr) {
492+        fprintf(stderr, "DEBUG: ParseInterfaceDescriptor ifaceDesc is nullptr\n");
493+        return OHUSB_ERROR_NO_MEM;
494+    }
495+    ifaceDesc->bInterfaceNumber = usbInterface.GetId();
496+    ifaceDesc->bAlternateSetting = usbInterface.GetAlternateSetting();
497+    ifaceDesc->bInterfaceClass = usbInterface.GetClass();
498+    ifaceDesc->bInterfaceSubClass = usbInterface.GetSubClass();
499+    ifaceDesc->bInterfaceProtocol = usbInterface.GetProtocol();
500+    ifaceDesc->bNumEndpoints = 0;
501+    fprintf(stderr, "DEBUG: ParseInterfaceDescriptor class=%x, subclass=%x, protocol=%x.\n",
502+        usbInterface.GetClass(), usbInterface.GetSubClass(), usbInterface.GetProtocol());
503+	ohusb_endpoint_descriptor *endpoint;
504+    endpoint = (ohusb_endpoint_descriptor *)
505+        calloc((size_t)usbInterface.GetEndpointCount(), sizeof(ohusb_endpoint_descriptor));
506+    if (endpoint == nullptr) {
507+        fprintf(stderr, "DEBUG: endpoint is null.\n");
508+        return OHUSB_ERROR_NO_MEM;
509+    }
510+    ifaceDesc->endpoint = endpoint;
511+    std::vector<USBEndpoint> endpoints = usbInterface.GetEndpoints();
512+    for (int i = 0; i < usbInterface.GetEndpointCount(); i++) {
513+        if (ParseEndpointDescriptor(endpoints[i], endpoint + i) != OHUSB_SUCCESS) {
514+            return OHUSB_ERROR_IO;
515+        }
516+        (ifaceDesc->bNumEndpoints)++;
517+    }
518+    DumpInterfaceDescriptor(ifaceDesc);
519+    fprintf(stderr, "DEBUG: ParseInterfaceDescriptor out\n");
520+	return OHUSB_SUCCESS;
521+}
522+
523+int32_t ParseEndpointDescriptor(USBEndpoint &usbEndpoint, ohusb_endpoint_descriptor *epDesc)
524+{
525+    fprintf(stderr, "DEBUG: ParseEndpointDescriptor enter\n");
526+    if (epDesc == nullptr) {
527+        fprintf(stderr, "DEBUG: ParseEndpointDescriptor epDesc is nullptr\n");
528+        return OHUSB_ERROR_NO_MEM;
529+    }
530+    epDesc->bDescriptorType = usbEndpoint.GetType();
531+    epDesc->bEndpointAddress = usbEndpoint.GetAddress();
532+    epDesc->bmAttributes = usbEndpoint.GetAttributes();
533+    epDesc->wMaxPacketSize = usbEndpoint.GetMaxPacketSize();
534+    epDesc->bInterval = usbEndpoint.GetInterval();
535+    epDesc->bInterfaceId = usbEndpoint.GetInterfaceId();
536+    epDesc->direction = usbEndpoint.GetDirection();
537+    DumpEndpointDescriptor(epDesc);
538+    fprintf(stderr, "DEBUG: ParseEndpointDescriptor out\n");
539+	return OHUSB_SUCCESS;
540+}
541+
542+int32_t OH_SetConfiguration(ohusb_pipe *pipe, int configIndex)
543+{
544+    fprintf(stderr, "DEBUG: OH_SetConfiguration enter\n");
545+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
546+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
547+    USBConfig usbConfig;
548+    usbConfig.SetId(configIndex);
549+    int32_t ret = usbSrvClient.SetConfiguration(usbDevicePipe, usbConfig);
550+    if (ret != ERR_OK) {
551+        fprintf(stderr, "DEBUG: OH_SetConfiguration fail with ret = %d\n", ret);
552+        return OHUSB_ERROR_BUSY;
553+    }
554+    fprintf(stderr, "DEBUG: OH_SetConfiguration out\n");
555+    return OHUSB_SUCCESS;
556+}
557+
558+int32_t OH_SetInterface(ohusb_pipe *pipe, int interfaceId, int altIndex)
559+{
560+    fprintf(stderr, "DEBUG: OH_SetInterface enter\n");
561+    auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
562+    USBDevicePipe usbDevicePipe = {pipe->busNum, pipe->devAddr};
563+    UsbInterface usbInterface;
564+    usbInterface.SetId(interfaceId);
565+    usbInterface.SetAlternateSetting(altIndex);
566+    int32_t ret = usbSrvClient.SetInterface(usbDevicePipe, usbInterface);
567+    if (ret != ERR_OK) {
568+        fprintf(stderr, "DEBUG: OH_SetInterface fail with ret = %d\n", ret);
569+        return OHUSB_ERROR_BUSY;
570+    }
571+    fprintf(stderr, "DEBUG: OH_SetInterface out\n");
572+    return OHUSB_SUCCESS;
573+}
574+
575+void ReleaseInterfaceDescriptor(ohusb_interface_descriptor *ifaceDesc)
576+{
577+    if (ifaceDesc != nullptr) {
578+        SAFE_DELETE_ARRAY(ifaceDesc->endpoint);
579+        ifaceDesc->bNumEndpoints = 0;
580+        SAFE_DELETE_ARRAY(ifaceDesc);
581+    }
582+}
583+
584+void ReleaseInterface(ohusb_interface *iface)
585+{
586+    if (iface != nullptr) {
587+        for (uint8_t i = 0; i < iface->num_altsetting; i++) {
588+            ReleaseInterfaceDescriptor((iface->altsetting) + i);
589+        }
590+        iface->num_altsetting = 0;
591+        SAFE_DELETE_ARRAY(iface);
592+    }
593+}
594+
595+void ReleaseConfigDescriptor(ohusb_config_descriptor *confDesc)
596+{
597+    if (confDesc != nullptr) {
598+        for (uint8_t i = 0; i < confDesc->bNumInterfaces; i++) {
599+            ReleaseInterface((confDesc->interface) + i);
600+        }
601+        confDesc->bNumInterfaces = 0;
602+        SAFE_DELETE_ARRAY(confDesc);
603+    }
604+}
605+
606+void ReleaseDeviceDescriptor(ohusb_device_descriptor *devDesc)
607+{
608+    if (devDesc != nullptr) {
609+        for (uint8_t i = 0; i < devDesc->bNumConfigurations; i++) {
610+            ReleaseConfigDescriptor((devDesc->config) + i);
611+        }
612+        devDesc->bNumConfigurations = 0;
613+        SAFE_DELETE_ARRAY(devDesc);
614+    }
615+}
616+
617+void DumpDeviceDescriptor(ohusb_device_descriptor *devDesc)
618+{
619+    fprintf(stderr, "DEBUG: ------------------begin DeviceDescriptor------------------\n");
620+    fprintf(stderr, "DEBUG: busNum = %x\n", devDesc->busNum);
621+    fprintf(stderr, "DEBUG: devAddr = %x\n", devDesc->devAddr);
622+    fprintf(stderr, "DEBUG: bcdUSB = %d\n", devDesc->bcdUSB);
623+    fprintf(stderr, "DEBUG: bDeviceClass = %x\n", devDesc->bDeviceClass);
624+    fprintf(stderr, "DEBUG: bDeviceSubClass = %x\n", devDesc->bDeviceSubClass);
625+    fprintf(stderr, "DEBUG: bDeviceProtocol = %x\n", devDesc->bDeviceProtocol);
626+    fprintf(stderr, "DEBUG: bMaxPacketSize0 = %x\n", devDesc->bMaxPacketSize0);
627+    fprintf(stderr, "DEBUG: idVendor = %d\n", devDesc->idVendor);
628+    fprintf(stderr, "DEBUG: idProduct = %d\n", devDesc->idProduct);
629+    fprintf(stderr, "DEBUG: bcdDevice = %d\n", devDesc->bcdDevice);
630+    fprintf(stderr, "DEBUG: iManufacturer = %x\n", devDesc->iManufacturer);
631+    fprintf(stderr, "DEBUG: iProduct = %x\n", devDesc->iProduct);
632+    fprintf(stderr, "DEBUG: iSerialNumber = %x\n", devDesc->iSerialNumber);
633+    fprintf(stderr, "DEBUG: bNumConfigurations = %x\n", devDesc->bNumConfigurations);
634+    fprintf(stderr, "DEBUG: ------------------end DeviceDescriptor------------------\n");
635+    return;
636+}
637+
638+void DumpConfigDescriptor(ohusb_config_descriptor *confDesc)
639+{
640+    fprintf(stderr, "DEBUG: ------------------begin ConfigDescriptor------------------\n");
641+    fprintf(stderr, "DEBUG: iConfiguration = %x\n", confDesc->iConfiguration);
642+    fprintf(stderr, "DEBUG: bmAttributes = %x\n", confDesc->bmAttributes);
643+    fprintf(stderr, "DEBUG: MaxPower = %x\n", confDesc->MaxPower);
644+    fprintf(stderr, "DEBUG: bNumInterfaces = %x\n", confDesc->bNumInterfaces);
645+    fprintf(stderr, "DEBUG: ------------------end ConfigDescriptor------------------\n");
646+    return;
647+}
648+
649+void DumpInterfaceDescriptor(ohusb_interface_descriptor *ifaceDesc)
650+{
651+    fprintf(stderr, "DEBUG: ------------------begin InterfaceDescriptor------------------\n");
652+    fprintf(stderr, "DEBUG: bInterfaceNumber = %x\n", ifaceDesc->bInterfaceNumber);
653+    fprintf(stderr, "DEBUG: bAlternateSetting = %x\n", ifaceDesc->bAlternateSetting);
654+    fprintf(stderr, "DEBUG: bInterfaceClass = %x\n", ifaceDesc->bInterfaceClass);
655+    fprintf(stderr, "DEBUG: bInterfaceSubClass = %x\n", ifaceDesc->bInterfaceSubClass);
656+    fprintf(stderr, "DEBUG: bInterfaceProtocol = %x\n", ifaceDesc->bInterfaceProtocol);
657+    fprintf(stderr, "DEBUG: bNumEndpoints = %x\n", ifaceDesc->bNumEndpoints);
658+    fprintf(stderr, "DEBUG: ------------------end InterfaceDescriptor------------------\n");
659+    return;
660+}
661+
662+void DumpEndpointDescriptor(ohusb_endpoint_descriptor *eptDesc)
663+{
664+    fprintf(stderr, "DEBUG: ------------------begin EndpointDescriptor------------------\n");
665+    fprintf(stderr, "DEBUG: bDescriptorType = %x\n", eptDesc->bDescriptorType);
666+    fprintf(stderr, "DEBUG: bEndpointAddress = %x\n", eptDesc->bEndpointAddress);
667+    fprintf(stderr, "DEBUG: bmAttributes = %x\n", eptDesc->bmAttributes);
668+    fprintf(stderr, "DEBUG: wMaxPacketSize = %d\n", eptDesc->wMaxPacketSize);
669+    fprintf(stderr, "DEBUG: bInterval = %x\n", eptDesc->bInterval);
670+    fprintf(stderr, "DEBUG: bInterfaceId = %x\n", eptDesc->bInterfaceId);
671+    fprintf(stderr, "DEBUG: direction = %d\n", eptDesc->direction);
672+    fprintf(stderr, "DEBUG: ------------------end EndpointDescriptor------------------\n");
673+    return;
674+}
675+
676+char *CopyString(const std::string &source)
677+{
678+    auto len = source.length();
679+    char *dest = new (std::nothrow) char[len + 1];
680+    if (dest == nullptr) {
681+        fprintf(stderr, "DEBUG: CopyString allocate failed\n");
682+        return nullptr;
683+    }
684+    if (strcpy_s(dest, len + 1, source.c_str()) != 0) {
685+        fprintf(stderr, "DEBUG: CopyString strcpy_s failed\n");
686+    }
687+    dest[len] = '\0';
688+    return dest;
689+}
690diff --git a/backend/usb_manager.h b/backend/usb_manager.h
691new file mode 100644
692index 0000000..e5e39fc
693--- /dev/null
694+++ b/backend/usb_manager.h
695@@ -0,0 +1,468 @@
696+/*
697+ * Copyright (c) 2024 Huawei Device Co., Ltd.
698+ * Licensed under the Apache License, Version 2.0 (the "License");
699+ * you may not use this file except in compliance with the License.
700+ * You may obtain a copy of the License at
701+ *
702+ *     http://www.apache.org/licenses/LICENSE-2.0
703+ *
704+ * Unless required by applicable law or agreed to in writing, software
705+ * distributed under the License is distributed on an "AS IS" BASIS,
706+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
707+ * See the License for the specific language governing permissions and
708+ * limitations under the License.
709+ */
710+
711+#ifndef USB_MANAGER_H
712+#define USB_MANAGER_H
713+
714+#include <cups/string-private.h>
715+
716+#ifdef __cplusplus
717+extern "C" {
718+#endif
719+
720+#include <stdbool.h>
721+
722+#define OHUSB_TRANSFER_TYPE_MASK        0x03    /* in bmAttributes */
723+#define OHUSB_ENDPOINT_DIR_MASK		    0x80
724+
725+const int OHUSB_CLASS_PRINTER = 7;
726+const uint16_t OHUSB_LANGUAGE_ID_ENGLISH = 0x409;
727+const int32_t OHUSB_GET_STRING_DESCRIPTOR_TIMEOUT = 1000;
728+const int32_t OHUSB_STRING_DESCRIPTOR_LENGTH_INDEX = 0;
729+
730+const int32_t OHUSB_ENDPOINT_MAX_LENGTH = 512;
731+const int32_t OHUSB_CONTROLTRANSFER_READ_SLEEP = 100;
732+const int32_t OHUSB_CONTROLTRANSFER_READ_RETRY_MAX_TIMES = 20;
733+const int32_t OHUSB_BULKTRANSFER_WRITE_SLEEP = 1000;
734+const int32_t OHUSB_WRITE_RETRY_MAX_TIMES = 60;
735+const int32_t OHUSB_BULKTRANSFER_READ_TIMEOUT = 5000;
736+
737+/*
738+ * Transfer type
739+ */
740+typedef enum {
741+	/** Control transfer */
742+    OHUSB_TRANSFER_TYPE_CONTROL = 0U,
743+
744+    /** Isochronous transfer */
745+    OHUSB_TRANSFER_TYPE_ISOCHRONOUS = 1U,
746+
747+    /** Bulk transfer */
748+    OHUSB_TRANSFER_TYPE_BULK = 2U,
749+
750+    /** Interrupt transfer */
751+    OHUSB_TRANSFER_TYPE_INTERRUPT = 3U,
752+
753+    /** Bulk stream transfer */
754+    OHUSB_TRANSFER_TYPE_BULK_STREAM = 4U
755+} ohusb_transfer_type;
756+
757+/*
758+ * Request type bits.
759+ */
760+typedef enum {
761+	/** Standard */
762+    OHUSB_REQUEST_TYPE_STANDARD = (0x00 << 5),
763+
764+    /** Class */
765+    OHUSB_REQUEST_TYPE_CLASS = (0x01 << 5),
766+
767+    /** Vendor */
768+    OHUSB_REQUEST_TYPE_VENDOR = (0x02 << 5),
769+
770+    /** Reserved */
771+    OHUSB_REQUEST_TYPE_RESERVED = (0x03 << 5)
772+} ohusb_request_type;
773+
774+/*
775+ * Endpoint direction.
776+ */
777+typedef enum {
778+	/** Out: host-to-device */
779+    OHUSB_ENDPOINT_OUT = 0x00,
780+
781+    /** In: device-to-host */
782+    OHUSB_ENDPOINT_IN = 0x80
783+} ohusb_endpoint_direction;
784+
785+/*
786+ * Recipient bits of the requestType.
787+ */
788+typedef enum {
789+	/** Device */
790+    OHUSB_RECIPIENT_DEVICE = 0x00,
791+
792+    /** Interface */
793+    OHUSB_RECIPIENT_INTERFACE = 0x01,
794+
795+    /** Endpoint */
796+    OHUSB_RECIPIENT_ENDPOINT = 0x02,
797+
798+    /** Other */
799+    OHUSB_RECIPIENT_OTHER = 0x03
800+} ohusb_request_recipient;
801+
802+/*
803+ * Standard requests
804+ */
805+typedef enum {
806+	/** Request status of the specific recipient */
807+    OHUSB_REQUEST_GET_STATUS = 0x00,
808+
809+    /** Clear or disable a specific feature */
810+    OHUSB_REQUEST_CLEAR_FEATURE = 0x01,
811+
812+    /* 0x02 is reserved */
813+
814+    /** Set or enable a specific feature */
815+    OHUSB_REQUEST_SET_FEATURE = 0x03,
816+
817+    /* 0x04 is reserved */
818+
819+    /** Set device address for all future accesses */
820+    OHUSB_REQUEST_SET_ADDRESS = 0x05,
821+
822+    /** Get the specified descriptor */
823+    OHUSB_REQUEST_GET_DESCRIPTOR = 0x06,
824+
825+    /** Used to update existing descriptors or add new descriptors */
826+    OHUSB_REQUEST_SET_DESCRIPTOR = 0x07,
827+
828+    /** Get the current device configuration value */
829+    OHUSB_REQUEST_GET_CONFIGURATION = 0x08,
830+
831+    /** Set device configuration */
832+    OHUSB_REQUEST_SET_CONFIGURATION = 0x09,
833+
834+    /** Return the selected alternate setting for the specified interface */
835+    OHUSB_REQUEST_GET_INTERFACE = 0x0a,
836+
837+    /** Select an alternate interface for the specified interface */
838+    OHUSB_REQUEST_SET_INTERFACE = 0x0b,
839+
840+    /** Set then report an endpoint's synchronization frame */
841+    OHUSB_REQUEST_SYNCH_FRAME = 0x0c,
842+
843+    /** Sets both the U1 and U2 Exit Latency */
844+    OHUSB_REQUEST_SET_SEL = 0x30,
845+
846+    /** Delay from the time a host transmits a packet to the time it is
847+      * received by the device. */
848+    OHUSB_SET_ISOCH_DELAY = 0x31
849+} ohusb_standard_request;
850+
851+/*
852+ * Descriptor types as defined by the USB specification.
853+ */
854+typedef enum {
855+	/** Device descriptor */
856+	OHUSB_DT_DEVICE = 0x01,
857+
858+	/** Configuration descriptor */
859+	OHUSB_DT_CONFIG = 0x02,
860+
861+	/** String descriptor */
862+    OHUSB_DT_STRING = 0x03,
863+
864+    /** Interface descriptor */
865+    OHUSB_DT_INTERFACE = 0x04,
866+
867+    /** Endpoint descriptor */
868+    OHUSB_DT_ENDPOINT = 0x05,
869+
870+    /** Interface Association Descriptor */
871+    OHUSB_DT_INTERFACE_ASSOCIATION = 0x0b,
872+
873+    /** BOS descriptor */
874+    OHUSB_DT_BOS = 0x0f,
875+
876+    /** Device Capability descriptor */
877+    OHUSB_DT_DEVICE_CAPABILITY = 0x10,
878+
879+    /** HID descriptor */
880+    OHUSB_DT_HID = 0x21,
881+
882+    /** HID report descriptor */
883+    OHUSB_DT_REPORT = 0x22,
884+
885+    /** Physical descriptor */
886+    OHUSB_DT_PHYSICAL = 0x23,
887+
888+    /** Hub descriptor */
889+    OHUSB_DT_HUB = 0x29,
890+
891+    /** SuperSpeed Hub descriptor */
892+    OHUSB_DT_SUPERSPEED_HUB = 0x2a,
893+
894+    /** SuperSpeed Endpoint Companion descriptor */
895+    OHUSB_DT_SS_ENDPOINT_COMPANION = 0x30
896+} ohusb_descriptor_type;
897+
898+/**
899+ * Error codes.
900+ */
901+typedef enum {
902+	/** Success (no error) */
903+	OHUSB_SUCCESS = 0,
904+
905+	/** Input/output error */
906+	OHUSB_ERROR_IO = -1,
907+
908+	/** Invalid parameter */
909+	OHUSB_ERROR_INVALID_PARAM = -2,
910+
911+	/** Access denied (insufficient permissions) */
912+	OHUSB_ERROR_ACCESS = -3,
913+
914+	/** No such device (it may have been disconnected) */
915+	OHUSB_ERROR_NO_DEVICE = -4,
916+
917+	/** Entity not found */
918+	OHUSB_ERROR_NOT_FOUND = -5,
919+
920+	/** Resource busy */
921+	OHUSB_ERROR_BUSY = -6,
922+
923+	/** Operation timed out */
924+	OHUSB_ERROR_TIMEOUT = -7,
925+
926+	/** Overflow */
927+	OHUSB_ERROR_OVERFLOW = -8,
928+
929+	/** Pipe error */
930+	OHUSB_ERROR_PIPE = -9,
931+
932+	/** System call interrupted (perhaps due to signal) */
933+	OHUSB_ERROR_INTERRUPTED = -10,
934+
935+	/** Insufficient memory */
936+	OHUSB_ERROR_NO_MEM = -11,
937+
938+	/** Operation not supported or unimplemented on this platform */
939+	OHUSB_ERROR_NOT_SUPPORTED = -12,
940+
941+	/** Other error */
942+	OHUSB_ERROR_OTHER = -99
943+} ohusb_error;
944+
945+/**
946+ * A structure representing the parameter for usb control transfer.
947+ */
948+typedef struct {
949+    /** Request type */
950+    int32_t requestType;
951+
952+    /** Request */
953+    int32_t request;
954+
955+    /** Value. Varies according to request */
956+    int32_t value;
957+
958+    /** Index. Varies according to request, typically used to pass an index
959+	 * or offset */
960+    int32_t index;
961+
962+    /** timeout */
963+    int32_t timeout;
964+} ohusb_control_transfer_parameter;
965+
966+/**
967+ * A structure representing the standard USB endpoint descriptor.
968+ */
969+typedef struct {
970+    /** Descriptor type */
971+    uint8_t  bDescriptorType;
972+
973+    /** The address of the endpoint described by this descriptor. Bits 0:3 are
974+	 * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction. */
975+    uint8_t  bEndpointAddress;
976+
977+    /** Attributes which apply to the endpoint when it is configured using
978+	 * the bConfigurationValue. Bits 0:1 determine the transfer type. Bits 2:3 are
979+     * only used for isochronous endpoints. Bits 4:5 are also only used for
980+     * isochronous endpoints . Bits 6:7 are reserved. */
981+    uint8_t  bmAttributes;
982+
983+    /** Maximum packet size this endpoint is capable of sending/receiving. */
984+    uint16_t wMaxPacketSize;
985+
986+    /** Interval for polling endpoint for data transfers. */
987+    uint8_t  bInterval;
988+
989+    /** The interface id the endpoint belongs to. */
990+    uint8_t  bInterfaceId;
991+
992+    /** The direction of the endpoint. */
993+    uint32_t direction;
994+} ohusb_endpoint_descriptor;
995+
996+/**
997+ * A structure representing the standard USB interface descriptor.
998+ */
999+typedef struct {
1000+    /** Number of this interface */
1001+    uint8_t  bInterfaceNumber;
1002+
1003+    /** Value used to select this alternate setting for this interface */
1004+    uint8_t  bAlternateSetting;
1005+
1006+    /** USB-IF class code for this interface. */
1007+    uint8_t  bInterfaceClass;
1008+
1009+    /** USB-IF subclass code for this interface, qualified by the
1010+	 * bInterfaceClass value */
1011+    uint8_t  bInterfaceSubClass;
1012+
1013+    /** USB-IF protocol code for this interface, qualified by the
1014+	 * bInterfaceClass and bInterfaceSubClass values */
1015+    uint8_t  bInterfaceProtocol;
1016+
1017+    /** Array of endpoint descriptors. This length of this array is determined
1018+	 * by the bNumEndpoints field. */
1019+    ohusb_endpoint_descriptor *endpoint;
1020+
1021+    /** Number of endpoints used by this interface (excluding the control
1022+	 * endpoint). */
1023+    uint8_t  bNumEndpoints;
1024+} ohusb_interface_descriptor;
1025+
1026+/**
1027+ * A collection of alternate settings for a particular USB interface.
1028+ */
1029+typedef struct {
1030+    /** Array of interface descriptors. The length of this array is determined
1031+	 * by the num_altsetting field. */
1032+    ohusb_interface_descriptor *altsetting;
1033+
1034+    /** The number of alternate settings that belong to this interface.
1035+	 * Must be non-negative. */
1036+    int num_altsetting;
1037+} ohusb_interface;
1038+
1039+/**
1040+ * A structure representing the standard USB configuration descriptor.
1041+ */
1042+typedef struct {
1043+    /** Identifier value for this configuration */
1044+    uint8_t iConfiguration;
1045+
1046+    /** Configuration characteristics */
1047+    uint8_t bmAttributes;
1048+
1049+    /** Maximum power consumption of the USB device from this bus in this
1050+	 * configuration when the device is fully operation. Expressed in units
1051+	 * of 2 mA when the device is operating in high-speed mode and in units
1052+	 * of 8 mA when the device is operating in super-speed mode. */
1053+    uint8_t MaxPower;
1054+
1055+    /** Array of interfaces supported by this configuration. The length of
1056+	 * this array is determined by the bNumInterfaces field. */
1057+    ohusb_interface *interface;
1058+
1059+    /** Number of interfaces supported by this configuration */
1060+    uint8_t bNumInterfaces;
1061+} ohusb_config_descriptor;
1062+
1063+/**
1064+ * A structure representing the standard USB device descriptor.
1065+ */
1066+typedef struct {
1067+    /** The bus num of the usb device. */
1068+    uint8_t busNum;
1069+
1070+    /** The device address of the usb device. */
1071+    uint8_t devAddr;
1072+
1073+    /** USB specification release number in binary-coded decimal. A value of
1074+	 * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
1075+    uint16_t bcdUSB;
1076+
1077+    /** USB-IF class code for the device. */
1078+    uint8_t bDeviceClass;
1079+
1080+    /** USB-IF subclass code for the device, qualified by the bDeviceClass
1081+	 * value */
1082+    uint8_t bDeviceSubClass;
1083+
1084+    /** USB-IF protocol code for the device, qualified by the bDeviceClass and
1085+	 * bDeviceSubClass values */
1086+    uint8_t bDeviceProtocol;
1087+
1088+    /** Maximum packet size for endpoint 0 */
1089+    uint8_t bMaxPacketSize0;
1090+
1091+    /** USB-IF vendor ID */
1092+    uint16_t idVendor;
1093+
1094+    /** USB-IF product ID */
1095+    uint16_t idProduct;
1096+
1097+    /** Device release number in binary-coded decimal */
1098+    uint16_t bcdDevice;
1099+
1100+    /** Index of string descriptor describing manufacturer */
1101+    uint8_t iManufacturer;
1102+
1103+    /** Index of string descriptor describing product */
1104+    uint8_t iProduct;
1105+
1106+    /** Index of string descriptor containing device serial number */
1107+    uint8_t iSerialNumber;
1108+
1109+    /** Array of configs supported by this device. The length of
1110+	 * this array is determined by the bNumConfigurations field. */
1111+    ohusb_config_descriptor *config;
1112+
1113+    /** Number of configs supported by this device */
1114+    uint8_t bNumConfigurations;
1115+} ohusb_device_descriptor;
1116+
1117+/**
1118+ * A structure representing the pipe information to transfer data.
1119+ */
1120+typedef struct {
1121+    /** The bus num of the usb device. */
1122+    uint8_t busNum;
1123+
1124+    /** The device address of the usb device. */
1125+    uint8_t devAddr;
1126+} ohusb_pipe;
1127+
1128+/**
1129+ * A structure representing the endpoint information to transfer data.
1130+ */
1131+typedef struct {
1132+    /** The interface id to which the endpoint to transmit data belongs. */
1133+    uint8_t bInterfaceId;
1134+
1135+    /** The endpoint address to transfer data. */
1136+    uint8_t bEndpointAddress;
1137+
1138+    /** The interface id to be claimed. */
1139+    int32_t bClaimedInterfaceId;
1140+} ohusb_transfer_pipe;
1141+
1142+extern int32_t OH_GetDevices(ohusb_device_descriptor** list, ssize_t *numdevs);
1143+extern int32_t OH_OpenDevice(ohusb_device_descriptor *devDesc, ohusb_pipe **pipe);
1144+extern int32_t OH_CloseDevice(ohusb_pipe *pipe);
1145+extern int32_t OH_ClaimInterface(ohusb_pipe *pipe, int interfaceId, bool force);
1146+extern int32_t OH_ReleaseInterface(ohusb_pipe *pipe, int interfaceId);
1147+extern int32_t OH_BulkTransferRead(
1148+    ohusb_pipe *pipe, ohusb_transfer_pipe *tpipe, unsigned char *data, int length, int *transferred);
1149+extern int32_t OH_BulkTransferWrite(
1150+    ohusb_pipe *pipe, ohusb_transfer_pipe *tpipe, unsigned char *data, int length, int *transferred, int32_t timeout);
1151+extern int32_t OH_ControlTransferRead(
1152+    ohusb_pipe *pipe, ohusb_control_transfer_parameter *ctrlParam, unsigned char *data, uint16_t length);
1153+extern int32_t OH_ControlTransferWrite(
1154+    ohusb_pipe *pipe, ohusb_control_transfer_parameter *ctrlParam, unsigned char *data, uint16_t length);
1155+extern int32_t OH_GetStringDescriptor(ohusb_pipe *pipe, int descId, unsigned char *descriptor, int length);
1156+extern int32_t OH_SetConfiguration(ohusb_pipe *pipe, int configIndex);
1157+extern int32_t OH_SetInterface(ohusb_pipe *pipe, int interfaceId, int altIndex);
1158+
1159+#ifdef __cplusplus
1160+} // extern "C"
1161+#endif
1162+
1163+#endif /* USB_MANAGER_H */
1164