summaryrefslogtreecommitdiff
path: root/documentation/6.components/device-driver/input/power.md
blob: 870b559552420a23df15a21c0c6c0ce22a0bdca6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
@page page_device_input_power Input power keys

# Power / restart key handlers (`RT_INPUT_POWER`)

**`input_power.c`** installs global **`rt_input_handler`** instances that map **`KEY_POWER`** and **`KEY_RESTART`** release events to **`rt_hw_cpu_shutdown()`** and **`rt_hw_cpu_reset()`**. Any input device that advertises these keys in its capability bitmap can trigger system power actions without a dedicated PMIC driver hook.

DM and keyboard drivers: @ref page_device_input_dm. Handler API: @ref page_device_input.

Source: **`components/drivers/input/input_power.c`**.

---

## Kconfig

| Option | Default | Role |
| --- | --- | --- |
| **`RT_INPUT_POWER`** | **y** | Build **`input_power.c`**, run **`input_event_power_init`** at env init |

Depends on **`RT_USING_INPUT`**. Disable on boards where **`KEY_POWER`** must only be handled by application code.

---

## Architecture

```
  INIT_ENV_EXPORT(input_event_power_init)
        |
        +-- power_handler_install(KEY_POWER)
        +-- power_handler_install(KEY_RESTART)
                |
                |  (1) tmp_handler: identify=test, callback=power_input_callback
                |      rt_input_add_handler → scans all idevs, counts matches
                v
        (2) For each matching input device index:
                alloc rt_input_handler[N]
                identify=power_input_identify (binds to Nth device with key)
                callback=power_input_callback
                rt_input_add_handler
        |
        v
  Any idev reports KEY_POWER/KEY_RESTART release (value==0)
        → rt_input_event → handler → shutdown/reset
```

| Phase | Behavior |
| --- | --- |
| **Probe pass** | Temporary handler increments **`cap.value`** for each **`rt_input_device`** with **`key_map[code]`** set |
| **Install pass** | One persistent handler per matching device; **`identify`** matches the **`current`**-th device |
| **Runtime** | **`power_input_callback`**: on **`value == 0`** (key release), call BSP hook |

Handlers return **`RT_TRUE`** from **`callback`** to stop further handler dispatch for that event.

---

## Key actions

| Linux code | Event | Action |
| --- | --- | --- |
| **`KEY_POWER`** (116) | **`EV_KEY`**, **`value == 0`** (release) | **`rt_hw_cpu_shutdown()`** |
| **`KEY_RESTART`** | **`EV_KEY`**, **`value == 0`** | **`rt_hw_cpu_reset()`** |

Press (**`value == 1`**) does nothing in **`input_power.c`** — only release triggers power ops.

BSP must implement **`rt_hw_cpu_shutdown`** / **`rt_hw_cpu_reset`** (weak symbols or SoC-specific).

---

## Interaction with drivers

- **`gpio-keys`** child with **`linux,code = <116>`** registers an **`inputN`** with **`KEY_POWER`** in **`key_map`** — power handler attaches automatically when **`RT_INPUT_POWER`** is on.
- **`ettus,e3x0-button`** reports **`KEY_POWER`** on IRQ — same path.
- Does **not** require a dedicated compatible string; only the **advertised key code** matters.

If multiple devices expose **`KEY_POWER`**, each gets its own handler instance; any of them can shut down the system on release.

---

## Disabling or overriding

| Goal | Approach |
| --- | --- |
| **No automatic shutdown** | Set **`RT_INPUT_POWER=n`** in Kconfig |
| **Custom policy** | Disable **`RT_INPUT_POWER`** and use **`rt_input_add_handler`** with higher priority logic, or handle **`KEY_POWER`** only in userspace via @ref page_device_input_uapi |
| **Hold-to-power-off** | Not implemented here — implement in driver (long-press timer) before reporting release |

---

## Pitfalls

| Issue | Mitigation |
| --- | --- |
| **Unexpected shutdown** | Any stray **`KEY_POWER`** release shuts down — verify DT **`linux,code`** and test harnesses |
| **Missing capability** | Driver must **`rt_input_set_capability(idev, EV_KEY, KEY_POWER)`** before register |
| **Press-only testing** | Release is required — press alone does not call shutdown |
| **No matching devices** | **`power_handler_install`** exits early if count is zero (no handlers allocated) |

---

## See also

- @ref page_device_input_dm — **`gpio-keys`** DT example with **`KEY_POWER`**
- @ref page_device_input
- `dt-bindings/input/linux-event-codes.h` (or **`event-codes.h`**)