diff --git a/cmds/uinput/README.md b/cmds/uinput/README.md index 47e1dad9ccd65..1ce8f9f33a9c5 100644 --- a/cmds/uinput/README.md +++ b/cmds/uinput/README.md @@ -1,87 +1,96 @@ # Usage -## Two options to use the uinput command: -### 1. Interactive through stdin: -type `uinput -` into the terminal, then type/paste commands to send to the binary. -Use Ctrl+D to signal end of stream to the binary (EOF). -This mode can be also used from an app to send uinput events. -For an example, see the cts test case at: [InputTestCase.java][2] +There are two ways to use the `uinput` command: -When using another program to control uinput in interactive mode, registering a -new input device (for example, a bluetooth joystick) should be the first step. -After the device is added, you need to wait for the _onInputDeviceAdded_ -(see [InputDeviceListener][1]) notification before issuing commands -to the device. -Failure to do so will cause missed events and inconsistent behavior. +* **Recommended:** `uinput -` reads commands from standard input until End-of-File (Ctrl+D) is sent. + This mode can be used interactively from a terminal or used to control uinput from another program + or app (such as the CTS tests via [`UinputDevice`][UinputDevice]). +* `uinput ` reads commands from a file instead of standard input. -### 2. Using a file as an input: -type `uinput `, and the file will be used an an input to the binary. -You must add a sufficient delay after a "register" command to ensure device -is ready. The interactive mode is the recommended method of communicating -with the uinput binary. +[UinputDevice]: https://cs.android.com/android/platform/superproject/main/+/main:cts/libs/input/src/com/android/cts/input/UinputDevice.java -All of the input commands should be in pseudo-JSON format as documented below. -See examples [here][3]. +## Command format -The file can have multiple commands one after the other (which is not strictly -legal JSON format, as this would imply multiple root elements). +Input commands should be in JSON format, though the parser is in [lenient mode] to allow comments, +and integers can be specified in hexadecimal (e.g. `0xABCD`). The input file (or standard input) can +contain multiple commands, which will be executed in sequence. Simply add multiple JSON objects to +the file, one after the other without separators: -## Command description +```json5 +{ + "id": 1, + "command": "register", + // ... +} +{ + "id": 1, + "command": "delay", + // ... +} +``` + +Many examples of command files can be found [in the CTS tests][cts-example-jsons]. + +[lenient mode]: https://developer.android.com/reference/android/util/JsonReader#setLenient(boolean) +[cts-example-jsons]: https://cs.android.com/android/platform/superproject/main/+/main:cts/tests/tests/hardware/res/raw/ + +## Command reference + +### `register` -1. `register` Register a new uinput device -| Field | Type | Description | +| Field | Type | Description | +|:----------------:|:--------------:|:-------------------------- | +| `id` | integer | Device ID | +| `command` | string | Must be set to "register" | +| `name` | string | Device name | +| `vid` | 16-bit integer | Vendor ID | +| `pid` | 16-bit integer | Product ID | +| `bus` | string | Bus that device should use | +| `configuration` | object array | uinput device configuration| +| `ff_effects_max` | integer | `ff_effects_max` value | +| `abs_info` | array | Absolute axes information | + +`id` is used for matching the subsequent commands to a specific device to avoid ambiguity when +multiple devices are registered. + +`bus` is used to determine how the uinput device is connected to the host. The options are `"usb"` +and `"bluetooth"`. + +Device configuration is used to configure the uinput device. The `type` field provides a `UI_SET_*` +control code, and data is a vector of control values to be sent to the uinput device, which depends +on the control code. + +| Field | Type | Description | |:-------------:|:-------------:|:-------------------------- | -| id | integer | Device id | -| command | string | Must be set to "register" | -| name | string | Device name | -| vid | 16-bit integer| Vendor id | -| pid | 16-bit integer| Product id | -| bus | string | Bus that device should use | -| configuration | int array | uinput device configuration| -| ff_effects_max| integer | ff_effects_max value | -| abs_info | array | ABS axes information | +| `type` | integer | `UI_SET_` control type | +| `data` | integer array | control values | -Device ID is used for matching the subsequent commands to a specific device -to avoid ambiguity when multiple devices are registered. +`ff_effects_max` must be provided if `UI_SET_FFBIT` is used in `configuration`. -Device bus is used to determine how the uinput device is connected to the host. -The options are "usb" and "bluetooth". - -Device configuration is used to configure uinput device. "type" field provides the UI_SET_* -control code, and data is a vector of control values to be sent to uinput device, depends on -the control code. +`abs_info` fields are provided to set the device axes information. It is an array of below objects: | Field | Type | Description | |:-------------:|:-------------:|:-------------------------- | -| type | integer | UI_SET_ control type | -| data | int array | control values | +| `code` | integer | Axis code | +| `info` | object | Axis information object | -Device ff_effects_max must be provided if FFBIT is set. +The axis information object is defined as below, with the fields having the same meaning as those +Linux's [`struct input_absinfo`][struct input_absinfo]: -Device abs_info fields are provided to set the device axes information. It is an array of below -objects: | Field | Type | Description | |:-------------:|:-------------:|:-------------------------- | -| code | integer | Axis code | -| info | object | ABS information object | - -ABS information object is defined as below: -| Field | Type | Description | -|:-------------:|:-------------:|:-------------------------- | -| value | integer | Latest reported value | -| minimum | integer | Minimum value for the axis | -| maximum | integer | Maximum value for the axis | -| fuzz | integer | fuzz value for noise filter| -| flat | integer | values to be discarded | -| resolution | integer | resolution of axis | - -See [struct input_absinfo][4]) definitions. +| `value` | integer | Latest reported value | +| `minimum` | integer | Minimum value for the axis | +| `maximum` | integer | Maximum value for the axis | +| `fuzz` | integer | fuzz value for noise filter| +| `flat` | integer | values to be discarded | +| `resolution` | integer | resolution of axis | Example: -```json +```json5 { "id": 1, "command": "register", @@ -90,9 +99,9 @@ Example: "pid": 0x2c42, "bus": "usb", "configuration":[ - {"type":100, "data":[1, 21]}, // UI_SET_EVBIT : EV_KEY and EV_FF + {"type":100, "data":[1, 21]}, // UI_SET_EVBIT : EV_KEY and EV_FF {"type":101, "data":[11, 2, 3, 4]}, // UI_SET_KEYBIT : KEY_0 KEY_1 KEY_2 KEY_3 - {"type":107, "data":[80]} // UI_SET_FFBIT : FF_RUMBLE + {"type":107, "data":[80]} // UI_SET_FFBIT : FF_RUMBLE ], "ff_effects_max" : 1, "abs_info": [ @@ -104,19 +113,39 @@ Example: } ] } - ``` -2. `delay` + +[struct input_absinfo]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/kernel/uapi/linux/input.h?q=%22struct%20input_absinfo%22 + +#### Waiting for registration + +After the command is sent, there will be a delay before the device is set up by the Android input +stack, and `uinput` does not wait for that process to finish. Any commands sent to the device during +that time will be dropped. If you are controlling `uinput` by sending commands through standard +input from an app, you need to wait for [`onInputDeviceAdded`][onInputDeviceAdded] to be called on +an `InputDeviceListener` before issuing commands to the device. If you are passing a file to +`uinput`, add a `delay` after the `register` command to let registration complete. + +[onInputDeviceAdded]: https://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html + +#### Unregistering the device + +As soon as EOF is reached (either in interactive mode, or in file mode), the device that was created +will be unregistered. There is no explicit command for unregistering a device. + +### `delay` + Add a delay to command processing | Field | Type | Description | |:-------------:|:-------------:|:-------------------------- | -| id | integer | Device id | -| command | string | Must be set to "delay" | -| duration | integer | Delay in milliseconds | +| `id` | integer | Device ID | +| `command` | string | Must be set to "delay" | +| `duration` | integer | Delay in milliseconds | Example: -```json + +```json5 { "id": 1, "command": "delay", @@ -124,20 +153,21 @@ Example: } ``` -3. `inject` -Send an array of uinput event packets [type, code, value] to the uinput device +### `inject` + +Send an array of uinput event packets to the uinput device | Field | Type | Description | |:-------------:|:-------------:|:-------------------------- | -| id | integer | Device id | -| command | string | Must be set to "inject" | -| events | integer array | events to inject | +| `id` | integer | Device ID | +| `command` | string | Must be set to "inject" | +| `events` | integer array | events to inject | -The "events" parameter is an array of integers, encapsulates evdev input_event type, code and value, -see the example below. +The `events` parameter is an array of integers in sets of three: a type, an axis code, and an axis +value, like you'd find in Linux's `struct input_event`. For example, sending presses of the 0 and 1 +keys would look like this: -Example: -```json +```json5 { "id": 1, "command": "inject", @@ -153,14 +183,6 @@ Example: } ``` -### Notes -1. As soon as EOF is reached (either in interactive mode, or in file mode), -the device that was created will be unregistered. There is no -explicit command for unregistering a device. -2. The `getevent` utility can used to print out the key events -for debugging purposes. +## Notes -[1]: https://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html -[2]: ../../../../cts/tests/tests/hardware/src/android/hardware/input/cts/tests/InputTestCase.java -[3]: ../../../../cts/tests/tests/hardware/res/raw/ -[4]: ../../../../bionic/libc/kernel/uapi/linux/input.h +The `getevent` utility can used to print out the key events for debugging purposes.