blob: 008f6754856377e1a467ecca34aea9563dfc6f70 [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::{
27 DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source,
28};
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000029pub use input_verifier::InputVerifier;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000030pub use keyboard_classifier::KeyboardClassifier;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000031
32#[cxx::bridge(namespace = "android::input")]
Andrew Walbran37994222023-08-03 12:16:28 +000033#[allow(unsafe_op_in_unsafe_fn)]
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000034mod ffi {
35 #[namespace = "android"]
36 unsafe extern "C++" {
37 include!("ffi/FromRustToCpp.h");
38 fn shouldLog(tag: &str) -> bool;
39 }
40
41 #[namespace = "android::input::verifier"]
42 extern "Rust" {
43 /// Used to validate the incoming motion stream.
44 /// This class is not thread-safe.
45 /// State is stored in the "InputVerifier" object
46 /// that can be created via the 'create' method.
47 /// Usage:
48 ///
49 /// ```ignore
50 /// Box<InputVerifier> verifier = create("inputChannel name");
51 /// result = process_movement(verifier, ...);
52 /// if (result) {
53 /// crash(result.error_message());
54 /// }
55 /// ```
56 type InputVerifier;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000057 #[cxx_name = create]
58 fn create_input_verifier(name: String) -> Box<InputVerifier>;
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000059 fn process_movement(
60 verifier: &mut InputVerifier,
61 device_id: i32,
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -070062 source: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000063 action: u32,
64 pointer_properties: &[RustPointerProperties],
Siarhei Vishniakou227a7f82023-07-18 18:30:32 -070065 flags: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000066 ) -> String;
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -070067 fn reset_device(verifier: &mut InputVerifier, device_id: i32);
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000068 }
69
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +000070 #[namespace = "android::input::keyboardClassifier"]
71 extern "Rust" {
72 /// Used to classify a keyboard into alphabetic and non-alphabetic
73 type KeyboardClassifier;
74 #[cxx_name = create]
75 fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
76 #[cxx_name = notifyKeyboardChanged]
77 fn notify_keyboard_changed(
78 classifier: &mut KeyboardClassifier,
79 device_id: i32,
80 identifier: RustInputDeviceIdentifier,
81 device_classes: u32,
82 );
83 #[cxx_name = getKeyboardType]
84 fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
85 #[cxx_name = isFinalized]
86 fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
87 #[cxx_name = processKey]
88 fn process_key(
89 classifier: &mut KeyboardClassifier,
90 device_id: i32,
91 evdev_code: i32,
92 modifier_state: u32,
93 );
94 }
95
Prabir Pradhan0762b1f2023-06-22 23:08:18 +000096 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
97 pub struct RustPointerProperties {
98 pub id: i32,
99 }
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000100
101 #[derive(Debug)]
102 pub struct RustInputDeviceIdentifier {
103 pub name: String,
104 pub location: String,
105 pub unique_id: String,
106 pub bus: u16,
107 pub vendor: u16,
108 pub product: u16,
109 pub version: u16,
110 pub descriptor: String,
111 }
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000112}
113
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000114use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000115
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000116fn create_input_verifier(name: String) -> Box<InputVerifier> {
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -0700117 Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
118}
119
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000120fn process_movement(
121 verifier: &mut InputVerifier,
122 device_id: i32,
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700123 source: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000124 action: u32,
125 pointer_properties: &[RustPointerProperties],
Siarhei Vishniakou227a7f82023-07-18 18:30:32 -0700126 flags: u32,
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000127) -> String {
Linnan Li13ccabe2024-04-19 17:14:43 +0000128 let motion_flags = MotionFlags::from_bits(flags);
129 if motion_flags.is_none() {
130 panic!(
131 "The conversion of flags 0x{:08x} failed, please check if some flags have not been \
132 added to MotionFlags.",
133 flags
134 );
135 }
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000136 let result = verifier.process_movement(
137 DeviceId(device_id),
Siarhei Vishniakou2d151ac2023-09-19 13:30:24 -0700138 Source::from_bits(source).unwrap(),
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000139 action,
140 pointer_properties,
Linnan Li13ccabe2024-04-19 17:14:43 +0000141 motion_flags.unwrap(),
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000142 );
143 match result {
144 Ok(()) => "".to_string(),
145 Err(e) => e,
146 }
147}
148
Siarhei Vishniakou1160ecd2023-06-28 15:57:47 -0700149fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
150 verifier.reset_device(DeviceId(device_id));
Prabir Pradhan0762b1f2023-06-22 23:08:18 +0000151}
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000152
153fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
Vaibhav Devmurari099fb592024-06-26 14:26:30 +0000154 // Future design: Make this data store singleton by passing it to C++ side and making it global
155 // and pass by reference to components that need to store persistent data.
156 //
157 // Currently only used by rust keyboard classifier so keeping it here.
158 let data_store = DataStore::new(Box::new(DefaultFileReaderWriter::new(
159 "/data/system/inputflinger-data.json".to_string(),
160 )));
161 Box::new(KeyboardClassifier::new(data_store))
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000162}
163
164fn notify_keyboard_changed(
165 classifier: &mut KeyboardClassifier,
166 device_id: i32,
167 identifier: RustInputDeviceIdentifier,
168 device_classes: u32,
169) {
170 let classes = DeviceClass::from_bits(device_classes);
171 if classes.is_none() {
172 panic!(
173 "The conversion of device class 0x{:08x} failed, please check if some device classes
174 have not been added to DeviceClass.",
175 device_classes
176 );
177 }
178 classifier.notify_keyboard_changed(InputDevice {
179 device_id: DeviceId(device_id),
180 identifier,
181 classes: classes.unwrap(),
182 });
183}
184
185fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
186 classifier.get_keyboard_type(DeviceId(device_id)) as u32
187}
188
189fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
190 classifier.is_finalized(DeviceId(device_id))
191}
192
193fn process_key(
194 classifier: &mut KeyboardClassifier,
195 device_id: i32,
196 evdev_code: i32,
197 meta_state: u32,
198) {
199 let modifier_state = ModifierState::from_bits(meta_state);
200 if modifier_state.is_none() {
201 panic!(
202 "The conversion of meta state 0x{:08x} failed, please check if some meta state
203 have not been added to ModifierState.",
204 meta_state
205 );
206 }
207 classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
208}