• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# USB DDK Development
2
3## Overview
4
5The USB Driver Development Kit (DDK) is a toolset that helps you develop USB device drivers at the application layer based on the user mode. It provides a series of device access APIs, for example, opening and closing USB interfaces, and performing non-isochronous transfer, isochronous transfer, control transfer, and interrupt transfer over USB pipes.
6
7The USB DDK can be used to develop device drivers for all devices that use the USB protocol to transfer data over a USB bus. For the peripherals that are not supported by standard kernel drivers, you can use the peripheral driver application developed based on the USB DDK to implement unique device capabilities.
8
9### Basic Concepts
10
11Before developing the USB DDK, you must understand the following basic concepts:
12
13- **USB**
14
15  Universal Serial Bus (USB) is a widely used interface technology that connects a computer to various external devices, such as a keyboard, mouse, printer, storage device, and smartphone. The USB is designed to provide a standardized, efficient, and easy-to-use connection mode that replaces the traditional serial and parallel interface communication.
16
17- **DDK**
18
19  DDK is a tool package provided by OpenHarmony for developing drivers for non-standard USB serial port devices based on the peripheral framework.
20
21### Implementation Principles
22
23A non-standard peripheral application obtains the USB device ID by using the peripheral management service, and delivers the ID and the action to the USB driver application through RPC. The USB driver application can obtain or set the device descriptor and initiate a control transfer or interrupt transfer request by calling the USB DDK API. Then, the DDK API uses the HDI service to deliver instructions to the kernel driver, and the kernel driver uses instructions to communicate with the device.
24
25**Figure 1** Principles of invoking the USB DDK
26
27![USB_DDK schematic diagram](figures/ddk-schematic-diagram.png)
28
29## Constraints
30
31- The open APIs of USB DDK can be used to develop drivers of non-standard USB peripherals.
32
33- The open APIs of USB DDK can be used only within the lifecycle of **DriverExtensionAbility**.
34
35- To use the open APIs of the USB DDK, you need to declare the matching ACL permissions in **module.json5**, for example, **ohos.permission.ACCESS_DDK_USB**.
36
37## Environment Setup
38
39Before you get started, make necessary preparations by following instructions in [Environment Preparation](environmental-preparation.md).
40
41## How to Develop
42
43### Available APIs
44
45| Name| Description|
46| -------- | -------- |
47| OH_Usb_Init(void) | Initializes the USB DDK.|
48| OH_Usb_Release(void) | Releases the USB DDK.|
49| OH_Usb_GetDeviceDescriptor(uint64_t deviceId, struct UsbDeviceDescriptor *desc) | Obtains the device descriptor of a USB device.|
50| OH_Usb_GetConfigDescriptor(uint64_t deviceId, uint8_t configIndex, struct UsbDdkConfigDescriptor **const config) | Obtains a USB configuration descriptor. To avoid memory leakage, use **OH_Usb_FreeConfigDescriptor()** to release a descriptor after use.|
51| OH_Usb_FreeConfigDescriptor(const struct UsbDdkConfigDescriptor *const config) | Releases a configuration descriptor. To avoid memory leakage, release a descriptor in time after use.|
52| OH_Usb_ClaimInterface(uint64_t deviceId, uint8_t interfaceIndex, uint64_t *interfaceHandle) | Declares a USB interface.|
53| OH_Usb_SelectInterfaceSetting(uint64_t interfaceHandle, uint8_t settingIndex) | Activates the alternate setting of a USB interface.|
54| OH_Usb_GetCurrentInterfaceSetting(uint64_t interfaceHandle, uint8_t \*settingIndex) | Obtains the alternate setting of a USB interface.|
55| OH_Usb_SendControlReadRequest(uint64_t interfaceHandle, const struct UsbControlRequestSetup \*setup, uint32_t timeout, uint8_t \*data, uint32_t \*dataLen) | Sends a control read transfer request. This API returns the result synchronously.|
56| OH_Usb_SendControlWriteRequest(uint64_t interfaceHandle, const struct UsbControlRequestSetup \*setup, uint32_t, const uint8_t \*data, uint32_t dataLen) | Sends a control write transfer request. This API returns the result synchronously.|
57| OH_Usb_ReleaseInterface(uint64_t interfaceHandle) | Releases a USB interface.|
58| OH_Usb_SendPipeRequest(const struct UsbRequestPipe *pipe, UsbDeviceMemMap *devMmap) | Sends a pipe request. This API returns the result synchronously. It applies to interrupt transfer and bulk transfer.|
59| OH_Usb_CreateDeviceMemMap(uint64_t deviceId, size_t size, UsbDeviceMemMap **devMmap) | Create a buffer. To avoid resource leakage, use **OH_Usb_DestroyDeviceMemMap()** to destroy a buffer after use.|
60| OH_Usb_DestroyDeviceMemMap(UsbDeviceMemMap *devMmap) | Destroy a buffer. To avoid resource leakage, destroy a buffer in time after use.|
61| OH_Usb_GetDevices(struct Usb_DeviceArray *devices) | Obtains the USB device ID list. Ensure that the input pointer is valid and the number of devices does not exceed 128. To prevent resource leakage, release the member memory after usage. Besides, make sure that the obtained USB device ID has been filtered by **vid** in the driver configuration information.|
62
63For details about the APIs, see [USB DDK](../../reference/apis-driverdevelopment-kit/_usb_ddk.md).
64
65### How to Develop
66
67To develop a USB driver using the USB DDK, perform the following steps:
68
69**Adding Dynamic Link Libraries**
70
71Add the following libraries to **CMakeLists.txt**.
72```txt
73libusb_ndk.z.so
74```
75
76**Including Header Files**
77```c++
78#include <usb/usb_ddk_api.h>
79#include <usb/usb_ddk_types.h>
80```
81
821. Obtain the device descriptor of a USB device.
83
84    Call **OH_Usb_Init** of **usb_ddk_api.h** to initialize the USB DDK, and call **OH_Usb_GetDeviceDescriptor** to obtain the device descriptor.
85
86    ```c++
87    // Initialize the USB DDK.
88    OH_Usb_Init();
89    struct UsbDeviceDescriptor devDesc;
90    uint64_t deviceId = 0;
91    // Obtain the device descriptor.
92    OH_Usb_GetDeviceDescriptor(deviceId, &devDesc);
93    ```
94
952. Obtain a configuration descriptor, and declare the USB interface.
96
97    Call **OH_Usb_GetConfigDescriptor** of **usb_ddk_api.h** to obtain the configuration descriptor **config**, and call **OH_Usb_ClaimInterface** to declare claiming of the USB interface.
98
99    ```c++
100    struct UsbDdkConfigDescriptor *config = nullptr;
101    // Obtain the configuration descriptor.
102    OH_Usb_GetConfigDescriptor(deviceId, 1, &config);
103    // Obtain the index of the target USB interface based on the configuration descriptor.
104    uint8_t interfaceIndex = 0;
105    // Declare the USB interface.
106    uint64_t interfaceHandle = 0;
107    OH_Usb_ClaimInterface(deviceId, interfaceIndex, &interfaceHandle);
108    // Release the configuration descriptor.
109    OH_Usb_FreeConfigDescriptor(config);
110    ```
1113. Obtain the activated alternate setting of a USB interface.
112
113    Call **OH_Usb_GetCurrentInterfaceSetting** of **usb_ddk_api.h** to obtain the alternate setting, and call **OH_Usb_SelectInterfaceSetting** to activate it.
114
115    ```c++
116    uint8_t settingIndex = 0;
117    // Obtain the alternate setting.
118    OH_Usb_GetCurrentInterfaceSetting(interfaceHandle, &settingIndex);
119
120    // Activate the alternate setting.
121    OH_Usb_SelectInterfaceSetting(interfaceHandle, &settingIndex);
122    ```
1234. Send control read requests and control write requests.
124
125    Call **OH_Usb_SendControlReadRequest** of **usb_ddk_api.h** to send a control read request, or call **OH_Usb_SendControlWriteRequest** to send a control write request.
126
127    ```c++
128        // Timeout interval. Set it to 1s.
129    uint32_t timeout = 1000;
130
131    struct UsbControlRequestSetup setupRead;
132    setupRead.bmRequestType	= 0x80;
133    setupRead.bRequest = 0x08;
134    setupRead.wValue = 0;
135    setupRead.wIndex = 0;
136    setupRead.wLength = 0x01;
137    uint8_t dataRead[256] = {0};
138    uint32_t dataReadLen = 256;
139    // Send a control read request.
140    OH_Usb_SendControlReadRequest(interfaceHandle, &setupRead, timeout, dataRead, &dataReadLen);
141
142    struct UsbControlRequestSetup setupWrite;
143    setupWrite.bmRequestType = 0;
144    setupWrite.bRequest = 0x09;
145    setupWrite.wValue = 1;
146    setupWrite.wIndex = 0;
147    setupWrite.wLength = 0;
148    uint8_t dataWrite[256] = {0};
149    uint32_t dataWriteLen = 256;
150    // Send a control write request.
151    OH_Usb_SendControlWriteRequest(interfaceHandle, &setupWrite, timeout, dataWrite, &dataWriteLen);
152    ```
153
1545. Create a buffer, and send a request.
155
156    Call **OH_Usb_CreateDeviceMemMap** of **usb_ddk_api.h** to create the buffer **devMmap**, and call **OH_Usb_SendPipeRequest** to send a request.
157
158    ```c++
159    struct UsbDeviceMemMap *devMmap = nullptr;
160    // Create a buffer for storing data.
161    size_t bufferLen = 10;
162    OH_Usb_CreateDeviceMemMap(deviceId, bufferLen, &devMmap);
163    struct UsbRequestPipe pipe;
164    pipe.interfaceHandle = interfaceHandle;
165    // Obtain the target endpoint based on the configuration descriptor.
166    pipe.endpoint = 128;
167    pipe.timeout = UINT32_MAX;
168    // Send a request.
169    OH_Usb_SendPipeRequest(&pipe, devMmap);
170    ```
171
1726. Release resources.
173
174    After all requests are processed and before the application exits, call **OH_Usb_DestroyDeviceMemMap** of **usb_ddk_api.h** to destroy the buffer, call **OH_Usb_ReleaseInterface** to release the USB interface, , and call **OH_Usb_Release** to release the USB DDK.
175
176    ```c++
177    // Destroy the buffer.
178    OH_Usb_DestroyDeviceMemMap(devMmap);
179    // Release the USB interface.
180    OH_Usb_ReleaseInterface(interfaceHandle);
181    // Release the USB DDK.
182    OH_Usb_Release();
183    ```
1847. (Optional) Obtain the USB device ID list.
185
186    After the driver is started, call **OH_Usb_GetDevices** to obtain the device ID that matches the VID in the driver configuration for subsequent application development. (VID is the ID of the device vendor and is configured in the driver application to indicate the applicable devices. The queried device IDs need to be filtered by VID.)
187
188    ```c++
189    OH_Usb_Init();
190    constexpr size_t MAX_USB_DEVICE_NUM = 128;
191    struct Usb_DeviceArray deviceArray;
192    deviceArray.deviceIds = new uint64_t[MAX_USB_DEVICE_NUM];
193    // Obtain the USB device list.
194    OH_Usb_GetDevices(&deviceArray);
195    ```
196