1# Peripheral Driver Client Development
2
3## When to Use
4
5Peripheral devices (or simply peripherals) are auxiliary devices connected to a device through physical ports, such as handwriting tablets, printers, and scanners. Applications can query and bind peripherals via peripheral management, so that the peripherals can use the customized capabilities provided by the peripheral drivers, such as the printer software.
6
7Peripheral management applies to all devices that can be ported to the OpenHarmony.
8
9## Environment Setup
10
11### Development Tool and Configuration
12
13DevEco Studio, as the driver development tool, allows you to develop, debug, and package drivers.
14
15Download and install DevEco Studio and verify basic operations to ensure that it can function properly. For details, see [Creating and Running a Project](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/ide-create-new-project-V13) in [DevEco Studio User Guide](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/ide-tools-overview-V13).
16
17### SDK Version Configuration
18
19The ArkTs APIs for peripheral management can be used only when the SDK is of API version 10 or later.
20
21### HDC Configuration
22
23HarmonyOS Device Connector (HDC) is a command-line tool for debugging. It can be used to interact with real devices or emulators on Windows, Linux, and Mac. For details, see [HDC Configuration](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/hdc-V5).
24
25**NOTE**<br>Configuration of the environment variable **hdc_server_port** and global environment variables is mandatory.
26
27### Development Device
28
29* Currently, RK3568 is used as the device for development, debugging, and verification. For details about how to compile and burn the RK3568, see [Quick Start](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-pkg-3568-burn.md).
30* During client and driver development, you need to connect an external USB device for debugging. **Currently, only an external USB device is supported.**
31* The product ID and vendor ID of the USB device are required for defining drivers and implementing IPC.
32
33## Available APIs
34
35The following table describes the basic peripheral management capabilities. For details, see [API Reference](../../reference/apis-driverdevelopment-kit/js-apis-driver-deviceManager.md).
36
37**Table 1** APIs for basic peripheral management
38
39| Name                                                                                                                                                      | Description                                                                                   |
40| -----------------------------------------------------------------------------------------------------------------------------------------------------------  | --------------------------------------------------------------------------------------- |
41| queryDevices(busType?: number): Array&lt;Readonly&lt;Device&gt;&gt;                                                                                          | Queries the peripheral list.                                                                      |
42| bindDevice(deviceId: number, onDisconnect: AsyncCallback&lt;number&gt;, callback: AsyncCallback&lt;{deviceId: number; remote: rpc.IRemoteObject;}&gt;): void | Binds a peripheral device. This API uses an asynchronous callback to return the result. If the peripheral device is bound, the **IRemoteObject** of the device driver is returned for subsequent interaction with the device driver.|
43| bindDevice(deviceId: number, onDisconnect: AsyncCallback&lt;number&gt;): Promise&lt;{deviceId: number; remote: rpc.IRemoteObject;}&gt;                       | Binds a peripheral. This API uses a promise to return the result.                                                                 |
44| bindDeviceDriver(deviceId: number, onDisconnect: AsyncCallback&lt;number&gt;, callback: AsyncCallback&gt;RemoteDeviceDriver&gt;): void;                                  | Binds a peripheral. This API uses an asynchronous callback to return the result. It is supported since API version 11.                                                                |
45| bindDeviceDriver(deviceId: number, onDisconnect: AsyncCallback&lt;number&gt;): Promise&lt;RemoteDeviceDriver&gt;;                                                        | Binds a peripheral. This API uses a promise to return the result. It is supported since API version 11.
46| unbindDevice(deviceId: number, callback: AsyncCallback&lt;number&gt;): void                                                                                  | Unbinds a peripheral device. This API uses an asynchronous callback to return the result.                                                                             |
47| unbindDevice(deviceId: number): Promise&lt;number&gt;                                                                                                        | Unbinds a peripheral device. This API uses a promise to return the result.                                                                             |
48
49<!--Del-->
50The following table lists the APIs for extended peripheral management. For details, see [deviceManager API Reference](../../reference/apis-driverdevelopment-kit/js-apis-driver-deviceManager-sys.md).
51
52**Table 2** APIs for extended peripheral management
53
54| Name                                                                         | Description             |
55|------------------------------------------------------------------------------|-----------------|
56| queryDeviceInfo(deviceId?: number): Array&lt;Readonly&lt;DeviceInfo&gt;&gt;  | Obtains the list of detailed information about peripherals.  |
57| queryDriverInfo(driverUid?: string): Array&lt;Readonly&lt;DriverInfo&gt;&gt; | Obtains the list of detailed information about peripheral drivers.|
58<!--DelEnd-->
59
60## How to Develop
61
62You can use the APIs to query and bind peripheral devices so as to use the customized driver capabilities of the peripherals.
63
64The following sample code is a demo that illustrates how to develop both the client and server and implement IPC.
65
661. Create an OpenHarmony project. For details, see [Creating a Project](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/ide-create-new-project-V13).
67
68    **NOTE**
69
70    > To develop a driver client, select the **Empty Ability** template.
71    >
72    > To develop the driver server, select the **Native C++** template.
73    >
74    >To develop both the driver client and server, select the **Native C++** template.
75
76
772. Import the related kit, and declare the product ID, vendor ID, and code of the USB device to be bound.
78
79    **NOTE**
80
81    > Write following sample code in the **entry/src/main/ets/pages/Index.ets** file.
82
83    ```ts
84    import { hilog } from '@kit.PerformanceAnalysisKit';
85    import { deviceManager } from '@kit.DriverDevelopmentKit';
86    import { BusinessError } from '@kit.BasicServicesKit';
87    import { rpc } from '@kit.IPCKit';
88
89    const REQUEST_CODE: number = 99; // Custom communication code, which is for reference only.
90    const productId: number = 4258; // Declare the product ID of the connected USB device.
91    const vendorId: number = 4817; // Declare the vendor ID of the connected USB device.
92    ```
93
943. Define the **message** variable and remote object variable for communication with the driver.
95
96    **NOTE**
97
98    > The following APIs are defined in **struct Index{}**.
99
100    ```ts
101    @State message: string = 'Hello';
102    private remote: rpc.IRemoteObject | null = null;
103    ```
104
1054. Define the **queryDevices** API, and use it to obtain the device ID of the peripheral.
106
107    ```ts
108    private async queryTargetDeviceId(): Promise<number> {
109    try {
110      const devices: Array<deviceManager.Device> = deviceManager.queryDevices(deviceManager.BusType.USB);
111      const index = devices.findIndex((item: deviceManager.Device) => {
112        let usbDevice = item as deviceManager.USBDevice;
113        // If the product ID and vendor ID of the peripheral are unknown, you can view the information about the connected USB device in the log.
114        hilog.info(0, 'testTag', `usbDevice.productId = ${usbDevice.productId}, usbDevice.vendorId = ${usbDevice.vendorId}`);
115        return usbDevice.productId === productId && usbDevice.vendorId === vendorId;
116      });
117      if (index < 0) {
118        hilog.error(0, 'testTag', 'can not find device');
119        return -1;
120      }
121      return devices[index].deviceId;
122    } catch (error) {
123      hilog.error(0, 'testTag', `queryDevice failed, err: ${JSON.stringify(error)}`);
124    }
125    return -1;
126    }
127    ```
128
1295. Define the **bindDeviceDriver** API, and use it to obtain the remote driver object.
130
131    ```ts
132    private async getDriverRemote(deviceId: number): Promise<rpc.IRemoteObject | null> {
133    try {
134      let remoteDeviceDriver: deviceManager.RemoteDeviceDriver = await deviceManager.bindDeviceDriver(deviceId,
135        (err: BusinessError, id: number) => {
136        hilog.info(0, 'testTag', `device[${id}] id disconnect, err: ${JSON.stringify(err)}}`);
137      });
138      return remoteDeviceDriver.remote;
139    } catch (error) {
140      hilog.error(0, 'testTag', `bindDeviceDriver failed, err: ${JSON.stringify(error)}`);
141    }
142      return null;
143    }
144    ```
145
1466. Define the **sendMessageRequest** API, and use it to perform IPC with the remote driver object.
147
148    ```ts
149    private async communicateWithRemote(): Promise<void> {
150      const deviceId: number = await this.queryTargetDeviceId();
151      if (deviceId < 0) {
152        hilog.error(0, 'testTag', 'can not find target device');
153        return;
154      }
155      this.remote = await this.getDriverRemote(deviceId);
156      if (this.remote === null) {
157        hilog.error(0, 'testTag', `getDriverRemote failed`);
158        return;
159      }
160
161      let option = new rpc.MessageOption();
162      let data = new rpc.MessageSequence();
163      let reply = new rpc.MessageSequence();
164
165      // Send "Hello" to the driver.
166      data.writeString(this.message);
167
168      try {
169        await this.remote.sendMessageRequest(REQUEST_CODE, data, reply, option);
170        // Obtain the "Hello world" information returned by the driver.
171        this.message = reply.readString();
172        hilog.info(0, 'testTag', `sendMessageRequest, message: ${this.message}}`);
173      } catch (error) {
174        hilog.error(0, 'testTag', `sendMessageRequest failed, err: ${JSON.stringify(error)}`);
175      }
176    }
177    ```
178
1797. Render the UI. For details about UI development, see [UI Development](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/arkts-ui-development-V5).
180
181    ```ts
182    build() {
183      Row() {
184        Column() {
185          Text (this.message) // "Hello" is displayed.
186            .fontSize(60)
187            .fontWeight(FontWeight.Bold)
188            .onClick (() => { // Click Hello to communicate with the remote driver object. The message "Hello World" is displayed.
189              this.communicateWithRemote();
190            })
191        }
192        .width('100%')
193      }
194      .height('100%')
195    }
196    ```
197
1988. Develop the driver code. For details, see [Peripheral Driver Development](driverextensionability.md).
199
200<!--Del-->
201System applications can query detailed information about peripherals and drivers to implement management. The development procedure is as follows:
202
2031. Import the related kit.
204
205    ```ts
206     import { deviceManager } from '@kit.DriverDevelopmentKit';
207     import { BusinessError } from '@kit.BasicServicesKit';
208    ```
209
2102. Obtain the list of detailed information about peripherals.
211
212    ```ts
213    try {
214       // For example, deviceId is 12345678. You can use queryDevices() to obtain the deviceId.
215       let deviceInfos : Array<deviceManager.DeviceInfo> = deviceManager.queryDeviceInfo(12345678);
216       for (let item of deviceInfos) {
217          console.info(`Device id is ${item.deviceId}`)
218       }
219     } catch (error) {
220       let err: BusinessError = error as BusinessError;
221       console.error(`Failed to query device info. Code is ${err.code}, message is ${err.message}`);
222     }
223    ```
224
2253. Obtains the list of detailed information about peripheral drivers.
226
227    ```ts
228    try {
229       // In this example, driver-12345 is the driver UID. During application development, you can use queryDeviceInfo to query the driver UID and use it as the input parameter.
230       let driverInfos : Array<deviceManager.DriverInfo> = deviceManager.queryDriverInfo("driver-12345");
231       for (let item of driverInfos) {
232          console.info(`driver name is ${item.driverName}`)
233       }
234    } catch (error) {
235       let err: BusinessError = error as BusinessError;
236       console.error(`Failed to query driver info. Code is ${err.code}, message is ${err.message}`);
237    }
238    ```
239<!--DelEnd-->
240
241## Application Signing
242
243**NOTE**<br>Configure the permission before enabling automatic signing.
244
245You need to configure a signature file for your application to run on a device. Besides, to develop a peripheral driver client, you need to declare the **ohos.permission.ACCESS_EXTENSIONAL_DEVICE_DRIVER** permission for the peripheral.
246
247Automatic signing: [Signing Your App/Service Automatically](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/ide-signing-V13#section18815157237)
248
249Permission configuration: [Requesting ACL Permissions and Signing Your App/Service](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/ide-signing-V13#section157591551175916).
250