• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# HID DDK Development
2
3## Overview
4
5The Human Interface Device (HID) Driver Development Kit (DDK) is a toolset that helps you develop HID drivers at the application layer based on the user mode. It provides APIs for accessing HID devices on a host, including creating a HID device, sending events to a device, destroying a device, opening or closing a device, reading and writing a report, and obtaining device information.
6
7The HID DDK can be used to develop drivers for devices that use HID protocol to transfer data over a USB bus, or for devices that use peripheral drivers to create virtual devices to exchange information with non-standard devices.
8
9### Basic Concepts
10
11Before developing the HID DDK, you must understand the following basic concepts:
12
13- **HID**
14
15  HID is a type of hardware device that implements interaction between a person and a computer or another electronic device. The primary function of HID is to convert user input (such as a key, a click, or a movement) into a data signal, and send the signal to a host device (such as a computer, tablet, or game console), so that the user can control and operate the device.
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 HID device ID by using the peripheral management service, and delivers the ID and the action to the HID device driver application through RPC. The driver application calls the HID DDK API to create and destroy a HID device, send events to a HID device, or obtain and parse packets sent from a HID device. 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 HID DDK
26
27![HID_DDK schematic diagram](figures/ddk-schematic-diagram.png)
28
29## Constraints
30
31- The APIs provided by the HID DDK can be used to develop drivers of non-standard HID devices.
32
33- The open APIs of HID DDK can be used only within the lifecycle of **DriverExtensionAbility**.
34
35- Before using the open APIs of the HID DDK, you must declare the matching ACL permissions in **module.json5**, for example, **ohos.permission.ACCESS_DDK_HID**.
36
37## Available APIs
38
39| Name| Description|
40| -------- | -------- |
41| OH_Hid_CreateDevice(Hid_Device *hidDevice, Hid_EventProperties *hidEventProperties) | Creates a HID device. When the device is no longer required, call **OH_Hid_DestroyDevice** to destroy it.|
42| OH_Hid_EmitEvent(int32_t deviceId, const Hid_EmitItem items[], uint16_t length) | Sends an event to a HID device.|
43| OH_Hid_DestroyDevice(int32_t deviceId) | Destroys a HID device.|
44| int32_t OH_Hid_Init(void) | Initializes the HID DDK.|
45| int32_t OH_Hid_Release(void) | Releases the HID DDK.|
46| int32_t OH_Hid_Open(uint64_t deviceId, uint8_t interfaceIndex, Hid_DeviceHandle **dev) | Opens the device specified by **deviceId** and **interfaceIndex**.|
47| int32_t OH_Hid_Close(Hid_DeviceHandle **dev) | Closes a HID device.|
48| int32_t OH_Hid_Write(Hid_DeviceHandle *dev, uint8_t *data, uint32_t length, uint32_t *bytesWritten) | Writes a report to a HID device.|
49| int32_t OH_Hid_ReadTimeout(Hid_DeviceHandle *dev, uint8_t *data, uint32_t buffSize, int timeout, uint32_t *bytesRead) | Reads a report from a HID device within the specified time.|
50| int32_t OH_Hid_Read(Hid_DeviceHandle *dev, uint8_t *data, uint32_t buffSize, uint32_t *bytesRead) | Reads a report from a HID device in the specified mode. The blocking mode (that is, blocking remains active until data can be read) is used by default. You can call **OH_Hid_SetNonBlocking** to change the mode.|
51| int32_t OH_Hid_SetNonBlocking(Hid_DeviceHandle *dev, int nonblock) | Sets the device read mode to non-blocking mode.|
52| int32_t OH_Hid_GetRawInfo(Hid_DeviceHandle *dev, Hid_RawDevInfo *rawDevInfo) | Obtains the raw information of a HID device.|
53| int32_t OH_Hid_GetRawName(Hid_DeviceHandle *dev, char *data, uint32_t buffSize) | Obtains the raw name of a HID device.|
54| int32_t OH_Hid_GetPhysicalAddress(Hid_DeviceHandle *dev, char *data, uint32_t buffSize) | Obtains the physical address of a HID device.|
55| int32_t OH_Hid_GetRawUniqueId(Hid_DeviceHandle *dev, uint8_t *data, uint32_t buffSize) | Obtains the raw unique identifier of a HID device.|
56| int32_t OH_Hid_SendReport(Hid_DeviceHandle *dev, Hid_ReportType reportType, const uint8_t *data, uint32_t length) | Sends a report to a HID device.|
57| int32_t OH_Hid_GetReport(Hid_DeviceHandle *dev, Hid_ReportType reportType, uint8_t *data, uint32_t buffSize) | Obtains a report from a HID device.|
58| int32_t OH_Hid_GetReportDescriptor(Hid_DeviceHandle *dev, uint8_t *buf, uint32_t buffSize, uint32_t *bytesRead) | Obtains the report descriptor of a HID device.|
59
60For details about the APIs, see [HID DDK](../../reference/apis-driverdevelopment-kit/capi-hidddk.md).
61
62## How to Develop
63
64### Developing a Basic HID Driver
65
66The following steps you through on how to develop a HID device driver using the HID DDK.
67
68**Adding Dynamic Link Libraries**
69
70Add the following libraries to **CMakeLists.txt**.
71```txt
72libhid.z.so
73```
74
75**Including Header Files**
76```c++
77#include <hid/hid_ddk_api.h>
78#include <hid/hid_ddk_types.h>
79```
80
811. Create a HID device.
82
83    Use **OH_Hid_CreateDevice** of **hid_ddk_api.h** to create a HID device. If the operation is successful, a device ID is returned. If the operation fails, an [error code](../../reference/apis-driverdevelopment-kit/capi-hid-ddk-types-h.md#hid_ddkerrcode) is returned.
84
85    ```c++
86    // Construct HID device properties.
87    std::vector<Hid_DeviceProp> deviceProp = {HID_PROP_DIRECT}; // The vector header file needs to be imported.
88    std::string deviceName = "keyboard";
89    Hid_Device hidDevice = {
90        .deviceName = deviceName.c_str(),
91        .vendorId = 0x6006,
92        .productId = 0x6006,
93        .version = 1,
94        .bustype = 3,
95        .properties = deviceProp.data(),
96        .propLength = (uint16_t)deviceProp.size()
97    };
98    // Construct the event properties related to the HID device.
99    std::vector<Hid_EventType> eventType = {HID_EV_ABS, HID_EV_KEY, HID_EV_SYN, HID_EV_MSC};
100    Hid_EventTypeArray eventTypeArray = {.hidEventType = eventType.data(), .length = (uint16_t)eventType.size()};
101    std::vector<Hid_KeyCode> keyCode = {HID_BTN_TOOL_PEN, HID_BTN_TOOL_RUBBER, HID_BTN_TOUCH, HID_BTN_STYLUS, HID_BTN_RIGHT};
102    Hid_KeyCodeArray keyCodeArray = {.hidKeyCode = keyCode.data(), .length = (uint16_t)keyCode.size()};
103    std::vector<Hid_MscEvent> mscEvent = {HID_MSC_SCAN};
104    Hid_MscEventArray mscEventArray = {.hidMscEvent = mscEvent.data(), .length = (uint16_t)mscEvent.size()};
105    std::vector<Hid_AbsAxes> absAxes = {HID_ABS_X, HID_ABS_Y, HID_ABS_PRESSURE};
106    Hid_AbsAxesArray absAxesArray = {.hidAbsAxes = absAxes.data(), .length = (uint16_t)absAxes.size()};
107    Hid_EventProperties hidEventProp = {
108        .hidEventTypes = eventTypeArray,
109        .hidKeys = keyCodeArray,
110        .hidAbs = absAxesArray,
111        .hidMiscellaneous = mscEventArray
112        };
113        // Create a device. The device ID of the device created is returned.
114        int32_t deviceId = OH_Hid_CreateDevice(&hidDevice, &hidEventProp);
115    ```
116
1172. Send an event to the HID device.
118
119    Call **OH_Hid_EmitEvent** in **hid_ddk_api.h** to send an event to the device with the specified **deviceId**.
120
121    ```c++
122    // Construct the event to be sent.
123    Hid_EmitItem event = {.type = HID_EV_MSC, .code = HID_MSC_SCAN, .value = 0x000d0042};
124    std::vector<Hid_EmitItem> itemVec;
125    itemVec.push_back(event);
126    // Send the event to a HID device.
127    int32_t ret = OH_Hid_EmitEvent(deviceId, itemVec.data(), (uint16_t)itemVec.size());
128    ```
129
1303. Release resources.
131
132    Call **OH_Hid_DestroyDevice** in **hid_ddk_api.h** to destroy the device after all requests are processed and before the application exits.
133
134    ```c++
135    // Destroy a HID device.
136    int32_t ret = OH_Hid_DestroyDevice(deviceId);
137    ```
138
139### Developing a HID Packet Communication Driver
140
141The following steps you through on how to develop a HID packet communication driver using the HID DDK.
142
143**Adding Dynamic Link Libraries**
144
145Add the following libraries to **CMakeLists.txt**.
146```txt
147libhid.z.so
148```
149
150**Including Header Files**
151```c++
152#include <hid/hid_ddk_api.h>
153#include <hid/hid_ddk_types.h>
154```
155
1561. Initialize the HID DDK.
157
158    Call **OH_Hid_Init** in **hid_ddk_api.h** to initialize the HID DDK.
159
160    ```c++
161    // Initialize the HID DDK.
162    OH_Hid_Init();
163    ```
164
1652. Open the device.
166
167    Call **OH_Hid_Open** in **hid_ddk_api.h** to open a HID device.
168
169    ```c++
170    uint64_t deviceId = 0x100000003;
171    uint8_t interfaceIndex1 = 0;
172    uint8_t interfaceIndex2 = 1;
173    Hid_DeviceHandle *dev = NULL;
174    Hid_DeviceHandle *devFeature = NULL;
175    // Open the HID device specified by deviceId and interfaceIndex1. Generally, it is a /dev/hidraw0 file.
176    OH_Hid_Open(deviceId, interfaceIndex1, &dev);
177    // Open the HID device specified by deviceId and interfaceIndex2. Generally, it is a /dev/hidraw1 file.
178    OH_Hid_Open(deviceId, interfaceIndex2, &devFeature);
179    ```
180
1813. Write/Send a report (a data packet exchanged between a HID device and a host) to the HID device.
182    - If the report type is **HID_OUTPUT_REPORT** (output report), you can write/send the report in any of the following ways:
183        - Call **OH_Hid_Write** in **hid_ddk_api.h** to write an output report to the HID device.
184
185            ```c++
186            uint8_t data[] = {0x02, 0x02};
187            uint32_t bytesWritten = 0;
188            // Write a report.
189            int32_t ret = OH_Hid_Write(dev, data, sizeof(data), &bytesWritten);
190            ```
191
192        - Call **OH_Hid_SendReport** in **hid_ddk_api.h** to send an output report to the HID device.
193
194            ```c++
195            uint8_t data1[2] = {0x00};
196            // Specify the report ID.
197            data1[0] = 0x02;
198            // Set the report data.
199            data1[1] = 0x02;
200
201            // Send an output report.
202            int32_t ret = OH_Hid_SendReport(dev, HID_OUTPUT_REPORT, data1, sizeof(data1));
203            ```
204
205    - If the report type is **HID_FEATURE_REPORT** (feature report), call **OH_Hid_SendReport** in **hid_ddk_api.h** to send a feature report to the HID device.
206
207        ```c++
208        uint8_t data2[2] = {0x00};
209        // Specify the report ID.
210        data2[0] = 0x02;
211        // Set the report data.
212        data2[1] = 0x02;
213
214        // Send a feature report.
215        int32_t ret = OH_Hid_SendReport(devFeature, HID_FEATURE_REPORT, data2, sizeof(data2));
216        ```
217
2184. Read a report from the HID device.
219    - If the report type is **HID_INPUT_REPORT** (input report), you can read the report in any of the following ways:
220        - Call **OH_Hid_Read** or **OH_Hid_ReadTimeout** in **hid_ddk_api.h** to read an input report from the HID device in blocking mode.
221
222            ```c++
223            uint8_t data3[9] = {0x00};
224            uint32_t bytesRead = 0;
225            // Read a report from a HID device.
226            int32_t ret = OH_Hid_Read(dev, data3, sizeof(data3), &bytesRead);
227
228            uint8_t data4[9] = {0x00};
229            uint32_t bytesRead = 0;
230            // Read a report from a HID device within the specified time.
231            ret = OH_Hid_ReadTimeout(dev, data4, sizeof(data4), 10000, &bytesRead);
232            ```
233
234        - Call **OH_Hid_SetNonBlocking** and **OH_Hid_Read** in **hid_ddk_api.h** to read an input report from the HID device in non-blocking mode.
235
236            ```c++
237            // 1 means to enable non-blocking, and 0 means to disable non-blocking.
238            int32_t ret = OH_Hid_SetNonBlocking(dev, 1);
239
240            // Wait for user input if no data is input when the code is executed.
241            sleep(1);
242            uint8_t data5[9] = {0};
243            uint32_t bytesRead = 0;
244            // Read a report from a HID device.
245            ret = OH_Hid_Read(dev, data5, sizeof(data5), &bytesRead);
246            ```
247
248        - Call **OH_Hid_GetReport** in **hid_ddk_api.h** to obtain an input report from the HID device.
249
250            ```c++
251            uint8_t data6[9] = {0};
252            // Specify the report ID.
253            data6[0] = 0x00;
254
255            // Obtain an input report.
256            int32_t ret = OH_Hid_GetReport(dev, HID_INPUT_REPORT, data6, sizeof(data6));
257            ```
258
259    - If the report type is **HID_FEATURE_REPORT** (feature report), call **OH_Hid_GetReport** in **hid_ddk_api.h** to obtain a feature report from a HID device.
260
261        ```c++
262        uint8_t data7[8] = {0};
263        // Specify the report ID.
264        data7[0] = 0x07;
265
266        // Obtain a feature report.
267        int32_t ret = OH_Hid_GetReport(devFeature, HID_FEATURE_REPORT, data7, sizeof(data7));
268        ```
269
2705. Obtain the raw device information, raw name, physical address, and raw unique identifier of a HID device.
271
272    Call **OH_Hid_GetRawInfo** in **hid_ddk_api.h** to obtain the raw information about a HID device.<br>Call **OH_Hid_GetRawName** to obtain the raw name of a HID device.<br>Call **OH_Hid_GetPhysicalAddress** to obtain the physical address of a HID device.<br>Call **OH_Hid_GetRawUniqueId** to obtain the raw unique identifier of a HID device. The obtained information can be referenced by applications, for example, displaying device information on the GUI.
273
274    ```c++
275    struct Hid_RawDevInfo rawDevInfo;
276    int32_t ret = OH_Hid_GetRawInfo(dev, &rawDevInfo);
277
278    char rawName[1024] = {0};
279    ret = OH_Hid_GetRawName(dev, rawName, sizeof(rawName));
280
281    char physicalAddress[1024] = {0};
282    ret = OH_Hid_GetPhysicalAddress(dev, physicalAddress, sizeof(physicalAddress));
283
284    uint8_t uniqueIdData[64] = {0};
285    ret = OH_Hid_GetRawUniqueId(dev, uniqueIdData, sizeof(uniqueIdData));
286    ```
287
2886. Obtain the report descriptor.
289
290    Call **OH_Hid_GetReportDescriptor** in **hid_ddk_api.h** to obtain the HID device report descriptor.
291
292    ```c++
293    uint8_t desData[1024] = {0};
294    uint32_t bytesRead = 0;
295    int32_t ret = OH_Hid_GetReportDescriptor(dev, desData, sizeof(desData), &bytesRead);
296    ```
297
2987. Close the HID device.
299
300    Call **OH_Hid_Close** in **hid_ddk_api.h** to close the device.
301
302    ```c++
303    // Close the device.
304    OH_Hid_Close(&dev);
305    OH_Hid_Close(&devFeature);
306    ```
307
3088. Release the HID DDK.
309
310    After the HID device is closed, call **OH_Hid_Release** in **hid_ddk_api.h** to release the HID DDK.
311
312    ```c++
313    // Release the HID DDK.
314    OH_Hid_Release();
315    ```
316