blob: 4f4ea8568b84f8722a1d1021857e80c3bfd88b7f [file] [log] [blame]
Prabir Pradhan0762b1f2023-06-22 23:08:18 +00001/*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! The rust component of libinput.
18
Vaibhav Devmurari099fb592024-06-26 14:26:30 +000019mod data_store;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000020mod input;
21mod input_verifier;
Vaibhav Devmuraria8359fc2024-06-10 20:01:25 +000022mod keyboard_classification_config;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000023mod keyboard_classifier;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000024
Vaibhav Devmurari099fb592024-06-26 14:26:30 +000025pub use data_store::{DataStore, DefaultFileReaderWriter};
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000026pub use input::{
Vaibhav Devmurari983e76b2024-08-30 15:16:38 +000027 DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
28 Source,
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000029};
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000030pub use input_verifier::InputVerifier;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000031pub use keyboard_classifier::KeyboardClassifier;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000032
33#[cxx::bridge(namespace = "android::input")]
Chris Wailesc98800e2024-09-05 13:31:13 -070034#[allow(clippy::needless_maybe_sized)]
Andrew Walbran37994222023-08-03 12:16:28 +000035#[allow(unsafe_op_in_unsafe_fn)]
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000036mod ffi {
37 #[namespace = "android"]
38 unsafe extern "C++" {
39 include!("ffi/FromRustToCpp.h");
40 fn shouldLog(tag: &str) -> bool;
41 }
42
43 #[namespace = "android::input::verifier"]
44 extern "Rust" {
45 /// Used to validate the incoming motion stream.
46 /// This class is not thread-safe.
47 /// State is stored in the "InputVerifier" object
48 /// that can be created via the 'create' method.
49 /// Usage:
50 ///
51 /// ```ignore
52 /// Box<InputVerifier> verifier = create("inputChannel name");
53 /// result = process_movement(verifier, ...);
54 /// if (result) {
55 /// crash(result.error_message());
56 /// }
57 /// ```
58 type InputVerifier;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000059 #[cxx_name = create]
60 fn create_input_verifier(name: String) -> Box<InputVerifier>;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000061 fn process_movement(
62 verifier: &mut InputVerifier,
63 device_id: i32,
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -070064 source: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000065 action: u32,
66 pointer_properties: &[RustPointerProperties],
Siarhei Vishniakou227a7f82023-07-18 18:30:32 -070067 flags: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000068 ) -> String;
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -070069 fn reset_device(verifier: &mut InputVerifier, device_id: i32);
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000070 }
71
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000072 #[namespace = "android::input::keyboardClassifier"]
73 extern "Rust" {
74 /// Used to classify a keyboard into alphabetic and non-alphabetic
75 type KeyboardClassifier;
76 #[cxx_name = create]
77 fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
78 #[cxx_name = notifyKeyboardChanged]
79 fn notify_keyboard_changed(
80 classifier: &mut KeyboardClassifier,
81 device_id: i32,
82 identifier: RustInputDeviceIdentifier,
83 device_classes: u32,
84 );
85 #[cxx_name = getKeyboardType]
86 fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
87 #[cxx_name = isFinalized]
88 fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
89 #[cxx_name = processKey]
90 fn process_key(
91 classifier: &mut KeyboardClassifier,
92 device_id: i32,
93 evdev_code: i32,
94 modifier_state: u32,
95 );
96 }
97
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000098 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
99 pub struct RustPointerProperties {
100 pub id: i32,
101 }
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000102
103 #[derive(Debug)]
104 pub struct RustInputDeviceIdentifier {
105 pub name: String,
106 pub location: String,
107 pub unique_id: String,
108 pub bus: u16,
109 pub vendor: u16,
110 pub product: u16,
111 pub version: u16,
112 pub descriptor: String,
113 }
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000114}
115
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000116use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000117
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000118fn create_input_verifier(name: String) -> Box<InputVerifier> {
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -0700119 Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
120}
121
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000122fn process_movement(
123 verifier: &mut InputVerifier,
124 device_id: i32,
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700125 source: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000126 action: u32,
127 pointer_properties: &[RustPointerProperties],
Siarhei Vishniakou227a7f82023-07-18 18:30:32 -0700128 flags: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000129) -> String {
Linnan Li13ccabe2024-04-19 17:14:43 +0000130 let motion_flags = MotionFlags::from_bits(flags);
131 if motion_flags.is_none() {
132 panic!(
133 "The conversion of flags 0x{:08x} failed, please check if some flags have not been \
134 added to MotionFlags.",
135 flags
136 );
137 }
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000138 let result = verifier.process_movement(
139 DeviceId(device_id),
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700140 Source::from_bits(source).unwrap(),
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000141 action,
142 pointer_properties,
Linnan Li13ccabe2024-04-19 17:14:43 +0000143 motion_flags.unwrap(),
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000144 );
145 match result {
146 Ok(()) => "".to_string(),
147 Err(e) => e,
148 }
149}
150
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -0700151fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
152 verifier.reset_device(DeviceId(device_id));
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000153}
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000154
155fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
Vaibhav Devmurari099fb592024-06-26 14:26:30 +0000156 // Future design: Make this data store singleton by passing it to C++ side and making it global
157 // and pass by reference to components that need to store persistent data.
158 //
159 // Currently only used by rust keyboard classifier so keeping it here.
160 let data_store = DataStore::new(Box::new(DefaultFileReaderWriter::new(
161 "/data/system/inputflinger-data.json".to_string(),
162 )));
163 Box::new(KeyboardClassifier::new(data_store))
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000164}
165
166fn notify_keyboard_changed(
167 classifier: &mut KeyboardClassifier,
168 device_id: i32,
169 identifier: RustInputDeviceIdentifier,
170 device_classes: u32,
171) {
172 let classes = DeviceClass::from_bits(device_classes);
173 if classes.is_none() {
174 panic!(
175 "The conversion of device class 0x{:08x} failed, please check if some device classes
176 have not been added to DeviceClass.",
177 device_classes
178 );
179 }
180 classifier.notify_keyboard_changed(InputDevice {
181 device_id: DeviceId(device_id),
182 identifier,
183 classes: classes.unwrap(),
184 });
185}
186
187fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
188 classifier.get_keyboard_type(DeviceId(device_id)) as u32
189}
190
191fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
192 classifier.is_finalized(DeviceId(device_id))
193}
194
195fn process_key(
196 classifier: &mut KeyboardClassifier,
197 device_id: i32,
198 evdev_code: i32,
199 meta_state: u32,
200) {
201 let modifier_state = ModifierState::from_bits(meta_state);
202 if modifier_state.is_none() {
203 panic!(
204 "The conversion of meta state 0x{:08x} failed, please check if some meta state
205 have not been added to ModifierState.",
206 meta_state
207 );
208 }
209 classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
210}