![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
The input core (components/drivers/input/input.c) is built only when **RT_USING_INPUT** is enabled. That Kconfig option **depends on RT_USING_DM** — there is no legacy non-DM input stack in-tree. Drivers publish Linux-style **EV_*** events through **struct rt_input_device**; consumers attach via **rt_input_add_handler** or POSIX **/dev/inputN** (Input userspace API (UAPI)).
Event reporting API, polling rules, and pitfalls: Input subsystem.
| Topic | Page |
|---|---|
Userspace **open/read/ioctl** | Input userspace API (UAPI) |
**rt_touch_device** bridge | Input touch bridge |
**KEY_POWER / KEY_RESTART** shutdown/reset | Input power keys |
Sources:
| File | Role |
|---|---|
**input.c** | Global device list, **rt_dm_ida** naming (input0…), **rt_input_device_register** |
**input_power.c** | Input power keys |
**input_touch.c** | Input touch bridge |
**input_uapi.c** | Input userspace API (UAPI) |
**keyboard/**, **joystick/**, **touchscreen/**, **misc/** | OFW platform/SPI drivers |
| Option | Role |
|---|---|
**RT_USING_DM** | Parent — input cannot be enabled without DM |
**RT_USING_INPUT** | Core **input.c**; selects **RT_USING_ADT** + bitmap ADT |
**RT_INPUT_POWER** | Input power keys (default y) |
**RT_INPUT_UAPI** | Input userspace API (UAPI) |
**RT_INPUT_KEYBOARD** | **gpio-keys**, **adc-keys** (see sub-options) |
**RT_INPUT_JOYSTICK** | **adc-joystick** |
**RT_INPUT_TOUCHSCREEN** | Input touch bridge |
**RT_INPUT_MISC** | e.g. **ettus,e3x0-button** |
**SOC_DM_INPUT_*_DIR** | BSP adds more platform drivers via **osource** in sub-Kconfig |
**Unlike I2C device model (DM)**, input has no dedicated rt_bus. Each hardware block is a normal **struct rt_platform_driver** (or **struct rt_spi_driver**) that embeds or owns **struct rt_input_device** and calls **rt_input_device_register** from **probe**.
| Layer | Object | Notes |
|---|---|---|
| Input device | **struct rt_input_device** | Embeds **struct rt_device parent**; capabilities in bitmaps |
| DM naming | **input_ida** in **input.c** | **rt_dm_dev_set_name(&idev->parent, "input%u", id)** |
| Platform binding | **RT_PLATFORM_DRIVER_EXPORT** | Probe/remove on **struct rt_platform_device** |
| SPI touch | **RT_SPI_DRIVER_EXPORT** | e.g. ADS7846 — see Input touch bridge |
| Step | Behavior |
|---|---|
| Allocate ID | **rt_dm_ida_alloc(&input_ida)** — failure → **-RT_EFULL** |
| Init lists / lock | Per-device **handler_nodes**, **rt_spinlock** |
| Register char dev | **RT_Device_Class_Char**, flag **RT_DEVICE_FLAG_DEACTIVATE** |
| Post-register | Start poller timer if **idev->poller**; **input_touch_register**; UAPI fops if enabled |
| Unregister | Refcount check; UAPI/touch teardown; **rt_dm_ida_free** |
Driver pattern — embed input at a known offset:
Use **rt_container_of(idev, struct my_input, parent)** in poll/IRQ callbacks.
| Compatible / binding | Driver file | Bus | Summary |
|---|---|---|---|
**gpio-keys** | **keyboard/keys-gpio.c** | platform | Parent node; each child → one **inputN** per key |
**adc-keys** | **keyboard/keys-adc.c** | platform | **io-channels** via IIO device model (DM); polling |
**adc-joystick** | **joystick/js-adc.c** | platform | Per-child **reg**, IIO, **EV_ABS** polling |
**ti,ads7846** … **ti,xpt2046** | **touchscreen/ts-ads7846.c** | SPI | Input touch bridge |
**ettus,e3x0-button** | **misc/button-e3x0.c** | platform | IRQ **press/release** → **KEY_POWER** |
compatible = "gpio-keys"**; subnodes are individual buttons.rt_ofw_get_named_pin**, property matching ***,code$** (e.g. **linux,code**), optional **debounce-interval**.rt_input_device per child (not one device for the whole parent).rt_iio_channel_get_by_name** / **rt_iio_channel_get_by_index** (IIO device model (DM)).poll-interval** 200 ms if property missing.RT_SPI_DRIVER_EXPORT(ads7846_driver)**; regulator, IRQ, worker thread.input_touch_parse** — Input touch bridge.(SPI **reg** / **spi-max-frequency** belong on the child under the SPI controller node per your BSP.)
RT_USING_DM**, **RT_USING_OFW**, **RT_USING_INPUT** (and subsystem menu if you add under **keyboard/** etc.).struct rt_platform_driver** with **ofw_ids[]** matching Linux binding where possible.probe**: allocate driver private struct with **struct rt_input_device** embedded first (or pointer field).rt_input_set_capability** for every **type/code** you will report; for **EV_ABS**, call **rt_input_set_absinfo** (after capability allocates **absinfo**).rt_input_setup_polling** — poller **poll** must not block (Input subsystem).rt_input_report_*** then **rt_input_sync**.rt_input_device_register** only when hardware is ready; store private data in **pdev->parent.user_data** or **rt_ofw_data(np)** for **remove**.remove**: stop IRQ/poller, **rt_input_device_unregister**, free memory.RT_PLATFORM_DRIVER_EXPORT(drv)** (or **RT_SPI_DRIVER_EXPORT** on SPI slaves).| Issue | Mitigation |
|---|---|
Missing rt_input_sync | Consumers see partial frames — always end with **rt_input_sync**. |
| Capability after register | Set capabilities before **rt_input_device_register**. |
**EV_ABS without absinfo** | Call **rt_input_set_capability(EV_ABS, axis)** then **rt_input_set_absinfo**. |
| Unregister with open UAPI fd | Close **/dev/inputN** first — Input userspace API (UAPI) |
| gpio-keys child vs parent | Driver registers per child; do not expect one **input0** for the whole node. |
| IIO channel NULL | Fix DT **io-channels** — IIO device model (DM) |
| Power handler surprise | Input power keys |
components/drivers/include/drivers/input.hcomponents/drivers/input/Kconfig