1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2023 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker //! The rust component of libinput.
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker mod data_store;
20*38e8c45fSAndroid Build Coastguard Worker mod input;
21*38e8c45fSAndroid Build Coastguard Worker mod input_verifier;
22*38e8c45fSAndroid Build Coastguard Worker mod keyboard_classification_config;
23*38e8c45fSAndroid Build Coastguard Worker mod keyboard_classifier;
24*38e8c45fSAndroid Build Coastguard Worker
25*38e8c45fSAndroid Build Coastguard Worker pub use data_store::{DataStore, DefaultFileReaderWriter};
26*38e8c45fSAndroid Build Coastguard Worker pub use input::{
27*38e8c45fSAndroid Build Coastguard Worker DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
28*38e8c45fSAndroid Build Coastguard Worker Source,
29*38e8c45fSAndroid Build Coastguard Worker };
30*38e8c45fSAndroid Build Coastguard Worker pub use input_verifier::InputVerifier;
31*38e8c45fSAndroid Build Coastguard Worker pub use keyboard_classifier::KeyboardClassifier;
32*38e8c45fSAndroid Build Coastguard Worker
33*38e8c45fSAndroid Build Coastguard Worker #[cxx::bridge(namespace = "android::input")]
34*38e8c45fSAndroid Build Coastguard Worker #[allow(clippy::needless_maybe_sized)]
35*38e8c45fSAndroid Build Coastguard Worker #[allow(unsafe_op_in_unsafe_fn)]
36*38e8c45fSAndroid Build Coastguard Worker mod ffi {
37*38e8c45fSAndroid Build Coastguard Worker #[namespace = "android"]
38*38e8c45fSAndroid Build Coastguard Worker unsafe extern "C++" {
39*38e8c45fSAndroid Build Coastguard Worker include!("ffi/FromRustToCpp.h");
shouldLog(tag: &str) -> bool40*38e8c45fSAndroid Build Coastguard Worker fn shouldLog(tag: &str) -> bool;
41*38e8c45fSAndroid Build Coastguard Worker }
42*38e8c45fSAndroid Build Coastguard Worker
43*38e8c45fSAndroid Build Coastguard Worker #[namespace = "android::input::verifier"]
44*38e8c45fSAndroid Build Coastguard Worker extern "Rust" {
45*38e8c45fSAndroid Build Coastguard Worker /// Used to validate the incoming motion stream.
46*38e8c45fSAndroid Build Coastguard Worker /// This class is not thread-safe.
47*38e8c45fSAndroid Build Coastguard Worker /// State is stored in the "InputVerifier" object
48*38e8c45fSAndroid Build Coastguard Worker /// that can be created via the 'create' method.
49*38e8c45fSAndroid Build Coastguard Worker /// Usage:
50*38e8c45fSAndroid Build Coastguard Worker ///
51*38e8c45fSAndroid Build Coastguard Worker /// ```ignore
52*38e8c45fSAndroid Build Coastguard Worker /// Box<InputVerifier> verifier = create("inputChannel name");
53*38e8c45fSAndroid Build Coastguard Worker /// result = process_movement(verifier, ...);
54*38e8c45fSAndroid Build Coastguard Worker /// if (result) {
55*38e8c45fSAndroid Build Coastguard Worker /// crash(result.error_message());
56*38e8c45fSAndroid Build Coastguard Worker /// }
57*38e8c45fSAndroid Build Coastguard Worker /// ```
58*38e8c45fSAndroid Build Coastguard Worker type InputVerifier;
59*38e8c45fSAndroid Build Coastguard Worker #[cxx_name = create]
create_input_verifier(name: String) -> Box<InputVerifier>60*38e8c45fSAndroid Build Coastguard Worker fn create_input_verifier(name: String) -> Box<InputVerifier>;
process_movement( verifier: &mut InputVerifier, device_id: i32, source: u32, action: u32, pointer_properties: &[RustPointerProperties], flags: u32, ) -> String61*38e8c45fSAndroid Build Coastguard Worker fn process_movement(
62*38e8c45fSAndroid Build Coastguard Worker verifier: &mut InputVerifier,
63*38e8c45fSAndroid Build Coastguard Worker device_id: i32,
64*38e8c45fSAndroid Build Coastguard Worker source: u32,
65*38e8c45fSAndroid Build Coastguard Worker action: u32,
66*38e8c45fSAndroid Build Coastguard Worker pointer_properties: &[RustPointerProperties],
67*38e8c45fSAndroid Build Coastguard Worker flags: u32,
68*38e8c45fSAndroid Build Coastguard Worker ) -> String;
reset_device(verifier: &mut InputVerifier, device_id: i32)69*38e8c45fSAndroid Build Coastguard Worker fn reset_device(verifier: &mut InputVerifier, device_id: i32);
70*38e8c45fSAndroid Build Coastguard Worker }
71*38e8c45fSAndroid Build Coastguard Worker
72*38e8c45fSAndroid Build Coastguard Worker #[namespace = "android::input::keyboardClassifier"]
73*38e8c45fSAndroid Build Coastguard Worker extern "Rust" {
74*38e8c45fSAndroid Build Coastguard Worker /// Used to classify a keyboard into alphabetic and non-alphabetic
75*38e8c45fSAndroid Build Coastguard Worker type KeyboardClassifier;
76*38e8c45fSAndroid Build Coastguard Worker #[cxx_name = create]
create_keyboard_classifier() -> Box<KeyboardClassifier>77*38e8c45fSAndroid Build Coastguard Worker fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
78*38e8c45fSAndroid Build Coastguard Worker #[cxx_name = notifyKeyboardChanged]
notify_keyboard_changed( classifier: &mut KeyboardClassifier, device_id: i32, identifier: RustInputDeviceIdentifier, device_classes: u32, )79*38e8c45fSAndroid Build Coastguard Worker fn notify_keyboard_changed(
80*38e8c45fSAndroid Build Coastguard Worker classifier: &mut KeyboardClassifier,
81*38e8c45fSAndroid Build Coastguard Worker device_id: i32,
82*38e8c45fSAndroid Build Coastguard Worker identifier: RustInputDeviceIdentifier,
83*38e8c45fSAndroid Build Coastguard Worker device_classes: u32,
84*38e8c45fSAndroid Build Coastguard Worker );
85*38e8c45fSAndroid Build Coastguard Worker #[cxx_name = getKeyboardType]
get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u3286*38e8c45fSAndroid Build Coastguard Worker fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
87*38e8c45fSAndroid Build Coastguard Worker #[cxx_name = isFinalized]
is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool88*38e8c45fSAndroid Build Coastguard Worker fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
89*38e8c45fSAndroid Build Coastguard Worker #[cxx_name = processKey]
process_key( classifier: &mut KeyboardClassifier, device_id: i32, evdev_code: i32, modifier_state: u32, )90*38e8c45fSAndroid Build Coastguard Worker fn process_key(
91*38e8c45fSAndroid Build Coastguard Worker classifier: &mut KeyboardClassifier,
92*38e8c45fSAndroid Build Coastguard Worker device_id: i32,
93*38e8c45fSAndroid Build Coastguard Worker evdev_code: i32,
94*38e8c45fSAndroid Build Coastguard Worker modifier_state: u32,
95*38e8c45fSAndroid Build Coastguard Worker );
96*38e8c45fSAndroid Build Coastguard Worker }
97*38e8c45fSAndroid Build Coastguard Worker
98*38e8c45fSAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
99*38e8c45fSAndroid Build Coastguard Worker pub struct RustPointerProperties {
100*38e8c45fSAndroid Build Coastguard Worker pub id: i32,
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker
103*38e8c45fSAndroid Build Coastguard Worker #[derive(Debug)]
104*38e8c45fSAndroid Build Coastguard Worker pub struct RustInputDeviceIdentifier {
105*38e8c45fSAndroid Build Coastguard Worker pub name: String,
106*38e8c45fSAndroid Build Coastguard Worker pub location: String,
107*38e8c45fSAndroid Build Coastguard Worker pub unique_id: String,
108*38e8c45fSAndroid Build Coastguard Worker pub bus: u16,
109*38e8c45fSAndroid Build Coastguard Worker pub vendor: u16,
110*38e8c45fSAndroid Build Coastguard Worker pub product: u16,
111*38e8c45fSAndroid Build Coastguard Worker pub version: u16,
112*38e8c45fSAndroid Build Coastguard Worker pub descriptor: String,
113*38e8c45fSAndroid Build Coastguard Worker }
114*38e8c45fSAndroid Build Coastguard Worker }
115*38e8c45fSAndroid Build Coastguard Worker
116*38e8c45fSAndroid Build Coastguard Worker use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
117*38e8c45fSAndroid Build Coastguard Worker
create_input_verifier(name: String) -> Box<InputVerifier>118*38e8c45fSAndroid Build Coastguard Worker fn create_input_verifier(name: String) -> Box<InputVerifier> {
119*38e8c45fSAndroid Build Coastguard Worker Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
120*38e8c45fSAndroid Build Coastguard Worker }
121*38e8c45fSAndroid Build Coastguard Worker
process_movement( verifier: &mut InputVerifier, device_id: i32, source: u32, action: u32, pointer_properties: &[RustPointerProperties], flags: u32, ) -> String122*38e8c45fSAndroid Build Coastguard Worker fn process_movement(
123*38e8c45fSAndroid Build Coastguard Worker verifier: &mut InputVerifier,
124*38e8c45fSAndroid Build Coastguard Worker device_id: i32,
125*38e8c45fSAndroid Build Coastguard Worker source: u32,
126*38e8c45fSAndroid Build Coastguard Worker action: u32,
127*38e8c45fSAndroid Build Coastguard Worker pointer_properties: &[RustPointerProperties],
128*38e8c45fSAndroid Build Coastguard Worker flags: u32,
129*38e8c45fSAndroid Build Coastguard Worker ) -> String {
130*38e8c45fSAndroid Build Coastguard Worker let motion_flags = MotionFlags::from_bits(flags);
131*38e8c45fSAndroid Build Coastguard Worker if motion_flags.is_none() {
132*38e8c45fSAndroid Build Coastguard Worker panic!(
133*38e8c45fSAndroid Build Coastguard Worker "The conversion of flags 0x{:08x} failed, please check if some flags have not been \
134*38e8c45fSAndroid Build Coastguard Worker added to MotionFlags.",
135*38e8c45fSAndroid Build Coastguard Worker flags
136*38e8c45fSAndroid Build Coastguard Worker );
137*38e8c45fSAndroid Build Coastguard Worker }
138*38e8c45fSAndroid Build Coastguard Worker let result = verifier.process_movement(
139*38e8c45fSAndroid Build Coastguard Worker DeviceId(device_id),
140*38e8c45fSAndroid Build Coastguard Worker Source::from_bits(source).unwrap(),
141*38e8c45fSAndroid Build Coastguard Worker action,
142*38e8c45fSAndroid Build Coastguard Worker pointer_properties,
143*38e8c45fSAndroid Build Coastguard Worker motion_flags.unwrap(),
144*38e8c45fSAndroid Build Coastguard Worker );
145*38e8c45fSAndroid Build Coastguard Worker match result {
146*38e8c45fSAndroid Build Coastguard Worker Ok(()) => "".to_string(),
147*38e8c45fSAndroid Build Coastguard Worker Err(e) => e,
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker }
150*38e8c45fSAndroid Build Coastguard Worker
reset_device(verifier: &mut InputVerifier, device_id: i32)151*38e8c45fSAndroid Build Coastguard Worker fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
152*38e8c45fSAndroid Build Coastguard Worker verifier.reset_device(DeviceId(device_id));
153*38e8c45fSAndroid Build Coastguard Worker }
154*38e8c45fSAndroid Build Coastguard Worker
create_keyboard_classifier() -> Box<KeyboardClassifier>155*38e8c45fSAndroid Build Coastguard Worker fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
156*38e8c45fSAndroid Build Coastguard Worker // Future design: Make this data store singleton by passing it to C++ side and making it global
157*38e8c45fSAndroid Build Coastguard Worker // and pass by reference to components that need to store persistent data.
158*38e8c45fSAndroid Build Coastguard Worker //
159*38e8c45fSAndroid Build Coastguard Worker // Currently only used by rust keyboard classifier so keeping it here.
160*38e8c45fSAndroid Build Coastguard Worker let data_store = DataStore::new(Box::new(DefaultFileReaderWriter::new(
161*38e8c45fSAndroid Build Coastguard Worker "/data/system/inputflinger-data.json".to_string(),
162*38e8c45fSAndroid Build Coastguard Worker )));
163*38e8c45fSAndroid Build Coastguard Worker Box::new(KeyboardClassifier::new(data_store))
164*38e8c45fSAndroid Build Coastguard Worker }
165*38e8c45fSAndroid Build Coastguard Worker
notify_keyboard_changed( classifier: &mut KeyboardClassifier, device_id: i32, identifier: RustInputDeviceIdentifier, device_classes: u32, )166*38e8c45fSAndroid Build Coastguard Worker fn notify_keyboard_changed(
167*38e8c45fSAndroid Build Coastguard Worker classifier: &mut KeyboardClassifier,
168*38e8c45fSAndroid Build Coastguard Worker device_id: i32,
169*38e8c45fSAndroid Build Coastguard Worker identifier: RustInputDeviceIdentifier,
170*38e8c45fSAndroid Build Coastguard Worker device_classes: u32,
171*38e8c45fSAndroid Build Coastguard Worker ) {
172*38e8c45fSAndroid Build Coastguard Worker let classes = DeviceClass::from_bits(device_classes);
173*38e8c45fSAndroid Build Coastguard Worker if classes.is_none() {
174*38e8c45fSAndroid Build Coastguard Worker panic!(
175*38e8c45fSAndroid Build Coastguard Worker "The conversion of device class 0x{:08x} failed, please check if some device classes
176*38e8c45fSAndroid Build Coastguard Worker have not been added to DeviceClass.",
177*38e8c45fSAndroid Build Coastguard Worker device_classes
178*38e8c45fSAndroid Build Coastguard Worker );
179*38e8c45fSAndroid Build Coastguard Worker }
180*38e8c45fSAndroid Build Coastguard Worker classifier.notify_keyboard_changed(InputDevice {
181*38e8c45fSAndroid Build Coastguard Worker device_id: DeviceId(device_id),
182*38e8c45fSAndroid Build Coastguard Worker identifier,
183*38e8c45fSAndroid Build Coastguard Worker classes: classes.unwrap(),
184*38e8c45fSAndroid Build Coastguard Worker });
185*38e8c45fSAndroid Build Coastguard Worker }
186*38e8c45fSAndroid Build Coastguard Worker
get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32187*38e8c45fSAndroid Build Coastguard Worker fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
188*38e8c45fSAndroid Build Coastguard Worker classifier.get_keyboard_type(DeviceId(device_id)) as u32
189*38e8c45fSAndroid Build Coastguard Worker }
190*38e8c45fSAndroid Build Coastguard Worker
is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool191*38e8c45fSAndroid Build Coastguard Worker fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
192*38e8c45fSAndroid Build Coastguard Worker classifier.is_finalized(DeviceId(device_id))
193*38e8c45fSAndroid Build Coastguard Worker }
194*38e8c45fSAndroid Build Coastguard Worker
process_key( classifier: &mut KeyboardClassifier, device_id: i32, evdev_code: i32, meta_state: u32, )195*38e8c45fSAndroid Build Coastguard Worker fn process_key(
196*38e8c45fSAndroid Build Coastguard Worker classifier: &mut KeyboardClassifier,
197*38e8c45fSAndroid Build Coastguard Worker device_id: i32,
198*38e8c45fSAndroid Build Coastguard Worker evdev_code: i32,
199*38e8c45fSAndroid Build Coastguard Worker meta_state: u32,
200*38e8c45fSAndroid Build Coastguard Worker ) {
201*38e8c45fSAndroid Build Coastguard Worker let modifier_state = ModifierState::from_bits(meta_state);
202*38e8c45fSAndroid Build Coastguard Worker if modifier_state.is_none() {
203*38e8c45fSAndroid Build Coastguard Worker panic!(
204*38e8c45fSAndroid Build Coastguard Worker "The conversion of meta state 0x{:08x} failed, please check if some meta state
205*38e8c45fSAndroid Build Coastguard Worker have not been added to ModifierState.",
206*38e8c45fSAndroid Build Coastguard Worker meta_state
207*38e8c45fSAndroid Build Coastguard Worker );
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
210*38e8c45fSAndroid Build Coastguard Worker }
211