1use crate::header::{
2 KRUN_INPUT_CONFIG_FEATURE_QUERY, KRUN_INPUT_EVENT_PROVIDER_FEATURE_QUEUE,
3 krun_input_config_vtable, krun_input_event_provider_vtable,
4};
5use crate::{
6 InputAbsInfo, InputBackendError, InputConfigBackend, InputDeviceIds, InputEvent,
7 InputEventProviderBackend,
8};
9use std::ffi::c_void;
10use std::marker::PhantomData;
11use std::os::fd::{AsRawFd, BorrowedFd};
12use std::ptr;
13use std::ptr::null;
14
15pub trait ObjectNew<T: Sync> {
16 fn new(userdata: Option<&T>) -> Self;
17}
18
19pub trait InputQueryConfig {
20 fn query_device_name(&self, name_buf: &mut [u8]) -> Result<u8, InputBackendError>;
22
23 fn query_serial_name(&self, name_buf: &mut [u8]) -> Result<u8, InputBackendError>;
25
26 fn query_device_ids(&self, ids: &mut InputDeviceIds) -> Result<(), InputBackendError>;
28
29 fn query_event_capabilities(
31 &self,
32 event_type: u8,
33 bitmap_buf: &mut [u8],
34 ) -> Result<u8, InputBackendError>;
35
36 fn query_abs_info(
38 &self,
39 abs_axis: u8,
40 abs_info: &mut InputAbsInfo,
41 ) -> Result<(), InputBackendError>;
42
43 fn query_properties(&self, properties: &mut [u8]) -> Result<u8, InputBackendError>;
45}
46
47pub trait InputEventsImpl {
48 fn get_read_notify_fd(&self) -> Result<BorrowedFd<'_>, InputBackendError>;
50
51 fn next_event(&mut self) -> Result<Option<InputEvent>, InputBackendError>;
53}
54
55pub trait IntoInputConfig<T: Sync> {
56 fn into_input_config(userdata: Option<&T>) -> InputConfigBackend<'_>;
57}
58
59impl<I, UserData: Send + Sync> IntoInputConfig<UserData> for I
60where
61 I: InputQueryConfig + ObjectNew<UserData>,
62{
63 fn into_input_config(userdata: Option<&UserData>) -> InputConfigBackend<'_> {
64 extern "C" fn create_config_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
65 instance: *mut *mut c_void,
66 userdata: *const c_void,
67 _reserved: *const c_void,
68 ) -> i32 {
69 let actual_userdata = if userdata.is_null() {
70 None
71 } else {
72 Some(unsafe { &*(userdata as *const T) })
73 };
74
75 let config_obj = I::new(actual_userdata);
76 let boxed_config = Box::into_raw(Box::new(config_obj));
77 unsafe { *instance = boxed_config as *mut c_void };
78 0
79 }
80
81 extern "C" fn config_destroy_fn<I>(instance: *mut c_void) -> i32 {
82 if instance.is_null() {
83 return 0;
84 }
85 let _ = unsafe { Box::from_raw(instance as *mut I) };
86 0
87 }
88
89 extern "C" fn query_device_name_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
90 instance: *mut c_void,
91 name_buf: *mut u8,
92 name_buf_len: usize,
93 ) -> i32 {
94 let config_obj = unsafe { &*(instance as *const I) };
95 let name_buf_slice = unsafe { std::slice::from_raw_parts_mut(name_buf, name_buf_len) };
96
97 match config_obj.query_device_name(name_buf_slice) {
98 Ok(len) => len as i32,
99 Err(e) => e as i32,
100 }
101 }
102
103 extern "C" fn query_serial_name_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
104 instance: *mut c_void,
105 name_buf: *mut u8,
106 name_buf_len: usize,
107 ) -> i32 {
108 let config_obj = unsafe { &*(instance as *const I) };
109 let name_buf_slice = unsafe { std::slice::from_raw_parts_mut(name_buf, name_buf_len) };
110
111 match config_obj.query_serial_name(name_buf_slice) {
112 Ok(len) => len as i32,
113 Err(e) => e as i32,
114 }
115 }
116
117 extern "C" fn query_device_ids_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
118 instance: *mut c_void,
119 ids: *mut InputDeviceIds,
120 ) -> i32 {
121 let config_obj = unsafe { &*(instance as *const I) };
122 let ids = unsafe { &mut *ids };
123
124 match config_obj.query_device_ids(ids) {
125 Ok(()) => 0,
126 Err(e) => e as i32,
127 }
128 }
129
130 extern "C" fn query_event_capabilities_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
131 instance: *mut c_void,
132 event_type: u8,
133 bitmap_buf: *mut u8,
134 bitmap_buf_len: usize,
135 ) -> i32 {
136 let config_obj = unsafe { &*(instance as *const I) };
137 let bitmap_buf_slice =
138 unsafe { std::slice::from_raw_parts_mut(bitmap_buf, bitmap_buf_len) };
139
140 match config_obj.query_event_capabilities(event_type, bitmap_buf_slice) {
141 Ok(len) => len as i32,
142 Err(e) => e as i32,
143 }
144 }
145
146 extern "C" fn query_abs_info_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
147 instance: *mut c_void,
148 abs_axis: u8,
149 abs_info: *mut InputAbsInfo,
150 ) -> i32 {
151 let config_obj = unsafe { &*(instance as *const I) };
152 let abs_info = unsafe { &mut *abs_info };
153
154 match config_obj.query_abs_info(abs_axis, abs_info) {
155 Ok(()) => 0,
156 Err(e) => e as i32,
157 }
158 }
159
160 extern "C" fn query_properties_fn<T: Sync, I: InputQueryConfig + ObjectNew<T>>(
161 instance: *mut c_void,
162 bitmap_buf: *mut u8,
163 bitmap_buf_len: usize,
164 ) -> i32 {
165 let config_obj = unsafe { &*(instance as *const I) };
166 let bitmap_buf_slice =
167 unsafe { std::slice::from_raw_parts_mut(bitmap_buf, bitmap_buf_len) };
168
169 match config_obj.query_properties(bitmap_buf_slice) {
170 Ok(len) => len as i32,
171 Err(e) => e as i32,
172 }
173 }
174
175 let x = userdata.map_or(null(), |t| ptr::from_ref(t) as *const c_void);
176
177 InputConfigBackend {
178 features: KRUN_INPUT_CONFIG_FEATURE_QUERY as u64,
179 create_userdata: x,
180 create_userdata_lifetime: PhantomData,
181 create_fn: Some(create_config_fn::<UserData, I>),
182 vtable: krun_input_config_vtable {
183 destroy: Some(config_destroy_fn::<I>),
184 query_device_name: Some(query_device_name_fn::<UserData, I>),
185 query_serial_name: Some(query_serial_name_fn::<UserData, I>),
186 query_device_ids: Some(query_device_ids_fn::<UserData, I>),
187 query_event_capabilities: Some(query_event_capabilities_fn::<UserData, I>),
188 query_abs_info: Some(query_abs_info_fn::<UserData, I>),
189 query_properties: Some(query_properties_fn::<UserData, I>),
190 },
191 }
192 }
193}
194
195pub trait IntoInputEvents<T: Sync> {
196 fn into_input_events(userdata: Option<&T>) -> InputEventProviderBackend<'_>;
197}
198
199impl<I, UserData: Send + Sync> IntoInputEvents<UserData> for I
200where
201 I: InputEventsImpl + ObjectNew<UserData>,
202{
203 fn into_input_events(userdata: Option<&UserData>) -> InputEventProviderBackend<'_> {
204 extern "C" fn create_events_fn<T: Sync, I: InputEventsImpl + ObjectNew<T>>(
205 instance: *mut *mut c_void,
206 userdata: *const c_void,
207 _reserved: *const c_void,
208 ) -> i32 {
209 let actual_userdata = if userdata.is_null() {
210 None
211 } else {
212 Some(unsafe { &*(userdata as *const T) })
213 };
214
215 let events_obj = I::new(actual_userdata);
216 let boxed_events = Box::into_raw(Box::new(events_obj));
217 unsafe { *instance = boxed_events as *mut c_void };
218 0
219 }
220
221 extern "C" fn events_destroy_fn<I>(instance: *mut c_void) -> i32 {
222 if instance.is_null() {
223 return 0;
224 }
225 let _ = unsafe { Box::from_raw(instance as *mut I) };
226 0
227 }
228
229 extern "C" fn get_ready_efd_fn<I: InputEventsImpl>(instance: *mut c_void) -> i32 {
230 let events_obj = unsafe { &*(instance as *const I) };
231 match events_obj.get_read_notify_fd() {
232 Ok(fd) => fd.as_raw_fd(),
233 Err(e) => e as i32,
234 }
235 }
236
237 extern "C" fn next_event_fn<I: InputEventsImpl>(
238 instance: *mut c_void,
239 out_event: *mut crate::InputEvent,
240 ) -> i32 {
241 let events_obj = unsafe { &mut *(instance as *mut I) };
242 let out_event = unsafe { &mut *out_event };
243
244 match events_obj.next_event() {
245 Ok(Some(event)) => {
246 *out_event = event;
247 1
248 }
249 Ok(None) => 0,
250 Err(e) => e as i32,
251 }
252 }
253 let x: *const c_void = userdata.map_or(null(), |t| ptr::from_ref(t) as *const c_void);
254 InputEventProviderBackend {
255 features: KRUN_INPUT_EVENT_PROVIDER_FEATURE_QUEUE as u64,
256 create_userdata: x,
257 create_userdata_lifetime: PhantomData,
258 create_fn: Some(create_events_fn::<UserData, I>),
259 vtable: krun_input_event_provider_vtable {
260 destroy: Some(events_destroy_fn::<I>),
261 get_ready_efd: Some(get_ready_efd_fn::<I>),
262 next_event: Some(next_event_fn::<I>),
263 },
264 }
265 }
266}