1 /*
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
19 mod input;
20 mod input_verifier;
21 mod keyboard_classifier;
22
23 pub use input::{
24 DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source,
25 };
26 pub use input_verifier::InputVerifier;
27 pub use keyboard_classifier::KeyboardClassifier;
28
29 #[cxx::bridge(namespace = "android::input")]
30 #[allow(unsafe_op_in_unsafe_fn)]
31 mod ffi {
32 #[namespace = "android"]
33 unsafe extern "C++" {
34 include!("ffi/FromRustToCpp.h");
shouldLog(tag: &str) -> bool35 fn shouldLog(tag: &str) -> bool;
36 }
37
38 #[namespace = "android::input::verifier"]
39 extern "Rust" {
40 /// Used to validate the incoming motion stream.
41 /// This class is not thread-safe.
42 /// State is stored in the "InputVerifier" object
43 /// that can be created via the 'create' method.
44 /// Usage:
45 ///
46 /// ```ignore
47 /// Box<InputVerifier> verifier = create("inputChannel name");
48 /// result = process_movement(verifier, ...);
49 /// if (result) {
50 /// crash(result.error_message());
51 /// }
52 /// ```
53 type InputVerifier;
54 #[cxx_name = create]
create_input_verifier(name: String) -> Box<InputVerifier>55 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, ) -> String56 fn process_movement(
57 verifier: &mut InputVerifier,
58 device_id: i32,
59 source: u32,
60 action: u32,
61 pointer_properties: &[RustPointerProperties],
62 flags: u32,
63 ) -> String;
reset_device(verifier: &mut InputVerifier, device_id: i32)64 fn reset_device(verifier: &mut InputVerifier, device_id: i32);
65 }
66
67 #[namespace = "android::input::keyboardClassifier"]
68 extern "Rust" {
69 /// Used to classify a keyboard into alphabetic and non-alphabetic
70 type KeyboardClassifier;
71 #[cxx_name = create]
create_keyboard_classifier() -> Box<KeyboardClassifier>72 fn create_keyboard_classifier() -> Box<KeyboardClassifier>;
73 #[cxx_name = notifyKeyboardChanged]
notify_keyboard_changed( classifier: &mut KeyboardClassifier, device_id: i32, identifier: RustInputDeviceIdentifier, device_classes: u32, )74 fn notify_keyboard_changed(
75 classifier: &mut KeyboardClassifier,
76 device_id: i32,
77 identifier: RustInputDeviceIdentifier,
78 device_classes: u32,
79 );
80 #[cxx_name = getKeyboardType]
get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u3281 fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32;
82 #[cxx_name = isFinalized]
is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool83 fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool;
84 #[cxx_name = processKey]
process_key( classifier: &mut KeyboardClassifier, device_id: i32, evdev_code: i32, modifier_state: u32, )85 fn process_key(
86 classifier: &mut KeyboardClassifier,
87 device_id: i32,
88 evdev_code: i32,
89 modifier_state: u32,
90 );
91 }
92
93 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
94 pub struct RustPointerProperties {
95 pub id: i32,
96 }
97
98 #[derive(Debug)]
99 pub struct RustInputDeviceIdentifier {
100 pub name: String,
101 pub location: String,
102 pub unique_id: String,
103 pub bus: u16,
104 pub vendor: u16,
105 pub product: u16,
106 pub version: u16,
107 pub descriptor: String,
108 }
109 }
110
111 use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
112
create_input_verifier(name: String) -> Box<InputVerifier>113 fn create_input_verifier(name: String) -> Box<InputVerifier> {
114 Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
115 }
116
process_movement( verifier: &mut InputVerifier, device_id: i32, source: u32, action: u32, pointer_properties: &[RustPointerProperties], flags: u32, ) -> String117 fn process_movement(
118 verifier: &mut InputVerifier,
119 device_id: i32,
120 source: u32,
121 action: u32,
122 pointer_properties: &[RustPointerProperties],
123 flags: u32,
124 ) -> String {
125 let motion_flags = MotionFlags::from_bits(flags);
126 if motion_flags.is_none() {
127 panic!(
128 "The conversion of flags 0x{:08x} failed, please check if some flags have not been \
129 added to MotionFlags.",
130 flags
131 );
132 }
133 let result = verifier.process_movement(
134 DeviceId(device_id),
135 Source::from_bits(source).unwrap(),
136 action,
137 pointer_properties,
138 motion_flags.unwrap(),
139 );
140 match result {
141 Ok(()) => "".to_string(),
142 Err(e) => e,
143 }
144 }
145
reset_device(verifier: &mut InputVerifier, device_id: i32)146 fn reset_device(verifier: &mut InputVerifier, device_id: i32) {
147 verifier.reset_device(DeviceId(device_id));
148 }
149
create_keyboard_classifier() -> Box<KeyboardClassifier>150 fn create_keyboard_classifier() -> Box<KeyboardClassifier> {
151 Box::new(KeyboardClassifier::new())
152 }
153
notify_keyboard_changed( classifier: &mut KeyboardClassifier, device_id: i32, identifier: RustInputDeviceIdentifier, device_classes: u32, )154 fn notify_keyboard_changed(
155 classifier: &mut KeyboardClassifier,
156 device_id: i32,
157 identifier: RustInputDeviceIdentifier,
158 device_classes: u32,
159 ) {
160 let classes = DeviceClass::from_bits(device_classes);
161 if classes.is_none() {
162 panic!(
163 "The conversion of device class 0x{:08x} failed, please check if some device classes
164 have not been added to DeviceClass.",
165 device_classes
166 );
167 }
168 classifier.notify_keyboard_changed(InputDevice {
169 device_id: DeviceId(device_id),
170 identifier,
171 classes: classes.unwrap(),
172 });
173 }
174
get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32175 fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 {
176 classifier.get_keyboard_type(DeviceId(device_id)) as u32
177 }
178
is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool179 fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool {
180 classifier.is_finalized(DeviceId(device_id))
181 }
182
process_key( classifier: &mut KeyboardClassifier, device_id: i32, evdev_code: i32, meta_state: u32, )183 fn process_key(
184 classifier: &mut KeyboardClassifier,
185 device_id: i32,
186 evdev_code: i32,
187 meta_state: u32,
188 ) {
189 let modifier_state = ModifierState::from_bits(meta_state);
190 if modifier_state.is_none() {
191 panic!(
192 "The conversion of meta state 0x{:08x} failed, please check if some meta state
193 have not been added to ModifierState.",
194 meta_state
195 );
196 }
197 classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
198 }
199