blob: 9b6fe3c9cacfaf7852fcb97f9ce5b40208c450e5 [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")]
Andrew Walbran37994222023-08-03 12:16:28 +000034#[allow(unsafe_op_in_unsafe_fn)]
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000035mod ffi {
36 #[namespace = "android"]
37 unsafe extern "C++" {
38 include!("ffi/FromRustToCpp.h");
39 fn shouldLog(tag: &str) -> bool;
40 }
41
42 #[namespace = "android::input::verifier"]
43 extern "Rust" {
44 /// Used to validate the incoming motion stream.
45 /// This class is not thread-safe.
46 /// State is stored in the "InputVerifier" object
47 /// that can be created via the 'create' method.
48 /// Usage:
49 ///
50 /// ```ignore
51 /// Box<InputVerifier> verifier = create("inputChannel name");
52 /// result = process_movement(verifier, ...);
53 /// if (result) {
54 /// crash(result.error_message());
55 /// }
56 /// ```
57 type InputVerifier;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000058 #[cxx_name = create]
59 fn create_input_verifier(name: String) -> Box<InputVerifier>;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000060 fn process_movement(
61 verifier: &mut InputVerifier,
62 device_id: i32,
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -070063 source: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000064 action: u32,
65 pointer_properties: &[RustPointerProperties],
Siarhei Vishniakou227a7f82023-07-18 18:30:32 -070066 flags: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000067 ) -> String;
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -070068 fn reset_device(verifier: &mut InputVerifier, device_id: i32);
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000069 }
70
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000071 #[namespace = "android::input::keyboardClassifier"]
72 extern "Rust" {
73 /// Used to classify a keyboard into alphabetic and non-alphabetic
74 type KeyboardClassifier;
75 #[cxx_name = create]
76 fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
77 #[cxx_name = notifyKeyboardChanged]
78 fn notify_keyboard_changed(
79 classifier: &mut KeyboardClassifier,
80 device_id: i32,
81 identifier: RustInputDeviceIdentifier,
82 device_classes: u32,
83 );
84 #[cxx_name = getKeyboardType]
85 fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
86 #[cxx_name = isFinalized]
87 fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
88 #[cxx_name = processKey]
89 fn process_key(
90 classifier: &mut KeyboardClassifier,
91 device_id: i32,
92 evdev_code: i32,
93 modifier_state: u32,
94 );
95 }
96
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000097 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
98 pub struct RustPointerProperties {
99 pub id: i32,
100 }
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000101
102 #[derive(Debug)]
103 pub struct RustInputDeviceIdentifier {
104 pub name: String,
105 pub location: String,
106 pub unique_id: String,
107 pub bus: u16,
108 pub vendor: u16,
109 pub product: u16,
110 pub version: u16,
111 pub descriptor: String,
112 }
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000113}
114
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000115use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000116
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000117fn create_input_verifier(name: String) -> Box<InputVerifier> {
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -0700118 Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
119}
120
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000121fn process_movement(
122 verifier: &mut InputVerifier,
123 device_id: i32,
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700124 source: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000125 action: u32,
126 pointer_properties: &[RustPointerProperties],
Siarhei Vishniakou227a7f82023-07-18 18:30:32 -0700127 flags: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000128) -> String {
Linnan Li13ccabe2024-04-19 17:14:43 +0000129 let motion_flags = MotionFlags::from_bits(flags);
130 if motion_flags.is_none() {
131 panic!(
132 "The conversion of flags 0x{:08x} failed, please check if some flags have not been \
133 added to MotionFlags.",
134 flags
135 );
136 }
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000137 let result = verifier.process_movement(
138 DeviceId(device_id),
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700139 Source::from_bits(source).unwrap(),
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000140 action,
141 pointer_properties,
Linnan Li13ccabe2024-04-19 17:14:43 +0000142 motion_flags.unwrap(),
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000143 );
144 match result {
145 Ok(()) => "".to_string(),
146 Err(e) => e,
147 }
148}
149
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -0700150fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
151 verifier.reset_device(DeviceId(device_id));
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000152}
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000153
154fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
Vaibhav Devmurari099fb592024-06-26 14:26:30 +0000155 // Future design: Make this data store singleton by passing it to C++ side and making it global
156 // and pass by reference to components that need to store persistent data.
157 //
158 // Currently only used by rust keyboard classifier so keeping it here.
159 let data_store = DataStore::new(Box::new(DefaultFileReaderWriter::new(
160 "/data/system/inputflinger-data.json".to_string(),
161 )));
162 Box::new(KeyboardClassifier::new(data_store))
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000163}
164
165fn notify_keyboard_changed(
166 classifier: &mut KeyboardClassifier,
167 device_id: i32,
168 identifier: RustInputDeviceIdentifier,
169 device_classes: u32,
170) {
171 let classes = DeviceClass::from_bits(device_classes);
172 if classes.is_none() {
173 panic!(
174 "The conversion of device class 0x{:08x} failed, please check if some device classes
175 have not been added to DeviceClass.",
176 device_classes
177 );
178 }
179 classifier.notify_keyboard_changed(InputDevice {
180 device_id: DeviceId(device_id),
181 identifier,
182 classes: classes.unwrap(),
183 });
184}
185
186fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
187 classifier.get_keyboard_type(DeviceId(device_id)) as u32
188}
189
190fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
191 classifier.is_finalized(DeviceId(device_id))
192}
193
194fn process_key(
195 classifier: &mut KeyboardClassifier,
196 device_id: i32,
197 evdev_code: i32,
198 meta_state: u32,
199) {
200 let modifier_state = ModifierState::from_bits(meta_state);
201 if modifier_state.is_none() {
202 panic!(
203 "The conversion of meta state 0x{:08x} failed, please check if some meta state
204 have not been added to ModifierState.",
205 meta_state
206 );
207 }
208 classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
209}