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 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