Skip to main content

starnix_modules_input_event_conversion/
button_fuchsia_to_linux.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fidl_fuchsia_ui_input::{MediaButtonsEvent, TouchButton, TouchButtonsEvent};
6use starnix_types::time::timeval_from_time;
7use starnix_uapi::uapi;
8
9pub struct LinuxButtonEventBatch {
10    pub events: Vec<uapi::input_event>,
11
12    // Because FIDL button events do not carry a timestamp, we perform a direct
13    // clock read during conversion and assign this value as the timestamp for
14    // all generated Linux button events in a single batch.
15    pub event_time: zx::MonotonicInstant,
16    pub power_is_pressed: bool,
17    pub function_is_pressed: bool,
18    pub palm_is_pressed: bool,
19}
20
21impl LinuxButtonEventBatch {
22    pub fn new() -> Self {
23        Self {
24            events: vec![],
25            event_time: zx::MonotonicInstant::get(),
26            power_is_pressed: false,
27            function_is_pressed: false,
28            palm_is_pressed: false,
29        }
30    }
31}
32
33pub fn parse_fidl_media_button_event(
34    fidl_event: &MediaButtonsEvent,
35    power_was_pressed: bool,
36    function_was_pressed: bool,
37) -> LinuxButtonEventBatch {
38    let mut batch = LinuxButtonEventBatch::new();
39    let time = timeval_from_time(batch.event_time);
40    let sync_event = uapi::input_event {
41        // See https://www.kernel.org/doc/Documentation/input/event-codes.rst.
42        time,
43        type_: uapi::EV_SYN as u16,
44        code: uapi::SYN_REPORT as u16,
45        value: 0,
46    };
47
48    batch.power_is_pressed = fidl_event.power.unwrap_or(false);
49    batch.function_is_pressed = fidl_event.function.unwrap_or(false);
50    for (then, now, key_code) in [
51        (power_was_pressed, batch.power_is_pressed, uapi::KEY_POWER),
52        (function_was_pressed, batch.function_is_pressed, uapi::KEY_VOLUMEDOWN),
53    ] {
54        // Button state changed. Send an event.
55        if then != now {
56            batch.events.push(uapi::input_event {
57                time,
58                type_: uapi::EV_KEY as u16,
59                code: key_code as u16,
60                value: now as i32,
61            });
62            batch.events.push(sync_event);
63        }
64    }
65
66    batch
67}
68
69pub fn parse_fidl_touch_button_event(
70    fidl_event: &TouchButtonsEvent,
71    palm_was_pressed: bool,
72) -> LinuxButtonEventBatch {
73    let mut batch = LinuxButtonEventBatch::new();
74    let time = timeval_from_time(batch.event_time);
75    let sync_event = uapi::input_event {
76        // See https://www.kernel.org/doc/Documentation/input/event-codes.rst.
77        time,
78        type_: uapi::EV_SYN as u16,
79        code: uapi::SYN_REPORT as u16,
80        value: 0,
81    };
82
83    if let Some(buttons) = &fidl_event.pressed_buttons {
84        batch.palm_is_pressed = buttons.contains(&TouchButton::Palm)
85    };
86
87    let (then, now, key_code) = (palm_was_pressed, batch.palm_is_pressed, uapi::KEY_SLEEP);
88    // Button state changed. Send an event.
89    if then != now {
90        batch.events.push(uapi::input_event {
91            time,
92            type_: uapi::EV_KEY as u16,
93            code: key_code as u16,
94            value: now as i32,
95        });
96        batch.events.push(sync_event);
97    }
98
99    batch
100}