1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 //!
17 use hilog_rust::{error, hilog, info, HiLogLabel, LogType};
18 use std::ffi::{c_char, CString};
19 use std::sync::Once;
20
21 const LOG_LABEL: HiLogLabel = HiLogLabel {
22 log_type: LogType::LogCore,
23 domain: 0xd002800,
24 tag: "MMIRustLib",
25 };
26
27 static DOUBLE_ZERO: f64 = 1e-6;
28 static RET_OK: i32 = 0;
29 static RET_ERR: i32 = -1;
30
31 struct CurveItem {
32 pub speeds: Vec<i32>,
33 pub slopes: Vec<f64>,
34 pub diff_nums: Vec<f64>,
35 }
36 struct AccelerateCurves {
37 data: Vec<CurveItem>,
38 }
39 impl AccelerateCurves {
get_curve_by_speed(&self, speed: usize) -> &CurveItem40 fn get_curve_by_speed(&self, speed: usize) -> &CurveItem {
41 &self.data[speed - 1]
42 }
43 }
44 impl AccelerateCurves {
get_instance() -> &'static AccelerateCurves45 fn get_instance() -> &'static AccelerateCurves {
46 static mut GLOBAL_CURVES: Option<AccelerateCurves> = None;
47 static ONCE: Once = Once::new();
48
49 ONCE.call_once(|| unsafe {
50 GLOBAL_CURVES = Some(AccelerateCurves {
51 data: vec![
52 CurveItem {
53 speeds: vec![8, 32, 128],
54 slopes: vec![0.16, 0.30, 0.56],
55 diff_nums: vec![0.0, -1.12, -9.44],
56 },
57 CurveItem {
58 speeds: vec![8, 32, 128],
59 slopes: vec![0.32, 0.60, 1.12],
60 diff_nums: vec![0.0, -2.24, -18.88],
61 },
62 CurveItem {
63 speeds: vec![8, 32, 128],
64 slopes: vec![0.48, 0.90, 1.68],
65 diff_nums: vec![0.0, -3.36, -28.32],
66 },
67 CurveItem {
68 speeds: vec![8, 32, 128],
69 slopes: vec![0.64, 1.20, 2.24],
70 diff_nums: vec![0.0, -4.48, -37.76],
71 },
72 CurveItem {
73 speeds: vec![8, 32, 128],
74 slopes: vec![0.80, 1.50, 2.80],
75 diff_nums: vec![0.0, -5.60, -47.20],
76 },
77 CurveItem {
78 speeds: vec![8, 32, 128],
79 slopes: vec![0.86, 1.95, 3.64],
80 diff_nums: vec![0.0, -8.72, -62.80],
81 },
82 CurveItem {
83 speeds: vec![8, 32, 128],
84 slopes: vec![0.92, 2.40, 4.48],
85 diff_nums: vec![0.0, -11.84, -78.40],
86 },
87 CurveItem {
88 speeds: vec![8, 32, 128],
89 slopes: vec![0.98, 2.85, 5.32],
90 diff_nums: vec![0.0, -14.96, -94.00],
91 },
92 CurveItem {
93 speeds: vec![8, 32, 128],
94 slopes: vec![1.04, 3.30, 6.16],
95 diff_nums: vec![0.0, -18.08, -109.60],
96 },
97 CurveItem {
98 speeds: vec![8, 32, 128],
99 slopes: vec![1.10, 3.75, 7.00],
100 diff_nums: vec![0.0, -21.20, -125.20],
101 },
102 CurveItem {
103 speeds: vec![8, 32, 128],
104 slopes: vec![1.16, 4.20, 7.84],
105 diff_nums: vec![0.0, -24.32, -140.80],
106 },
107 ],
108 });
109 });
110 unsafe { GLOBAL_CURVES.as_ref().unwrap() }
111 }
112 }
113
114 // 这个 extern 代码块链接到 libm 库
115 #[link(name = "m")]
116 extern {
fabs(z: f64) -> f64117 fn fabs(z: f64) -> f64;
ceil(z: f64) -> f64118 fn ceil(z: f64) -> f64;
fmax(a: f64, b: f64) -> f64119 fn fmax(a: f64, b: f64) -> f64;
fmin(a: f64, b: f64) -> f64120 fn fmin(a: f64, b: f64) -> f64;
121 }
122
get_speed_gain(vin: f64, gain: *mut f64, speed: i32) -> bool123 fn get_speed_gain(vin: f64, gain: *mut f64, speed: i32) -> bool {
124 info!(LOG_LABEL, "get_speed_gain enter vin is set to {} speed {} ", @public(vin), @public(speed));
125 unsafe {
126 if fabs(vin) < DOUBLE_ZERO {
127 error!(LOG_LABEL, "{} less that the limit", DOUBLE_ZERO);
128 return false;
129 }
130 }
131 if speed < 1 {
132 error!(LOG_LABEL, "{} The speed value can't be less than 1", @public(speed));
133 return false;
134 }
135 let item = AccelerateCurves::get_instance().get_curve_by_speed(speed as usize);
136 unsafe {
137 let num: i32 = ceil(fabs(vin)) as i32;
138 for i in 0..3 {
139 if num <= item.speeds[i] {
140 *gain = (item.slopes[i] * vin + item.diff_nums[i]) / vin;
141 info!(LOG_LABEL, "gain is set to {}", @public(*gain));
142 return true;
143 }
144 }
145 *gain = (item.slopes[2] * vin + item.diff_nums[2]) / vin;
146 info!(LOG_LABEL, "gain is set to {}", @public(*gain));
147 }
148 info!(LOG_LABEL, "get_speed_gain leave");
149 true
150 }
151
152 /// Offset struct is defined in C++, which give the vlaue
153 /// dx = libinput_event_pointer_get_dx
154 /// dy = libinput_event_pointer_get_dy
155 #[repr(C)]
156 pub struct Offset {
157 dx: f64,
158 dy: f64,
159 }
160
161 /// # Safety
162 /// HandleMotionAccelerate is the origin C++ function name
163 /// C++ will call for rust realization using this name
164 #[no_mangle]
HandleMotionAccelerate( offset: *const Offset, mode: bool, abs_x: *mut f64, abs_y: *mut f64, speed: i32, ) -> i32165 pub unsafe extern "C" fn HandleMotionAccelerate (
166 offset: *const Offset,
167 mode: bool,
168 abs_x: *mut f64,
169 abs_y: *mut f64,
170 speed: i32,
171 ) -> i32 {
172 let mut gain = 0.0;
173 let vin: f64;
174 let dx: f64;
175 let dy: f64;
176 unsafe {
177 dx = (*offset).dx;
178 dy = (*offset).dy;
179 vin = (fmax(fabs(dx), fabs(dy)) + fmin(fabs(dx), fabs(dy))) / 2.0;
180 info!(
181 LOG_LABEL,
182 "output the abs_x {} and abs_y {} captureMode {} dx {} dy {} gain {}",
183 @public(*abs_x),
184 @public(*abs_y),
185 @public(mode),
186 @public(dx),
187 @public(dy),
188 @public(gain)
189 );
190 if !get_speed_gain(vin, &mut gain as *mut f64, speed) {
191 error!(LOG_LABEL, "{} getSpeedGgain failed!", @public(speed));
192 return RET_ERR;
193 }
194 if !mode {
195 *abs_x += dx * gain;
196 *abs_y += dy * gain;
197 }
198 info!(
199 LOG_LABEL,
200 "output the abs_x {} and abs_y {}", @public(*abs_x), @public(*abs_y)
201 );
202 }
203 RET_OK
204 }
205
206 #[test]
test_handle_motion_accelerate_normal()207 fn test_handle_motion_accelerate_normal()
208 {
209 let offset: Offset = Offset{ dx: 0.00002, dy: 1.00004 };
210 let mut abs_x: f64 = 0.0;
211 let mut abs_y: f64 = 0.0;
212 let ret: i32;
213 unsafe {
214 ret = HandleMotionAccelerate(&offset, false, &mut abs_x as *mut f64, &mut abs_y as *mut f64, 2);
215 }
216 assert_eq!(ret, RET_OK);
217 }
218
219 #[test]
test_handle_motion_accelerate_mini_limit()220 fn test_handle_motion_accelerate_mini_limit()
221 {
222 let offset: Offset = Offset{ dx: 0.00000001, dy: 0.00000002 };
223 let mut abs_x: f64 = 0.0;
224 let mut abs_y: f64 = 0.0;
225 let ret: i32;
226 unsafe {
227 ret = HandleMotionAccelerate(&offset, false, &mut abs_x as *mut f64, &mut abs_y as *mut f64, 2);
228 }
229 assert_eq!(ret, RET_ERR);
230 }
231
232 #[test]
test_handle_motion_accelerate_capture_mode_false()233 fn test_handle_motion_accelerate_capture_mode_false()
234 {
235 let offset: Offset = Offset{ dx: 0.00002, dy: 1.00004 };
236 let mut abs_x: f64 = 0.0;
237 let mut abs_y: f64 = 0.0;
238 let ret: i32;
239 unsafe {
240 ret = HandleMotionAccelerate(&offset, true, &mut abs_x as *mut f64, &mut abs_y as *mut f64, 2);
241 }
242 assert_eq!(ret, RET_OK);
243 assert_eq!(abs_x, 0.0);
244 assert_eq!(abs_y, 0.0);
245 }
246