1use crate::device::{UserData, callback::fp_match_cb, fn_pointer};
2use crate::image::FpImage;
3use gio::Cancellable;
4use glib::object::ObjectExt;
5use glib::translate::FromGlibPtrNone;
6use glib::translate::{FromGlibPtrFull, ToGlibPtr};
7use std::sync::Arc;
8
9use crate::print::FpPrint;
10
11use super::FpDevice;
12
13pub type FpEnrollProgress<T> =
15 fn(&FpDevice, i32, Option<FpPrint>, Option<crate::GError>, &Option<T>) -> ();
16pub type FpMatchCb<T> =
18 fn(&FpDevice, Option<FpPrint>, FpPrint, Option<crate::GError>, &Option<T>) -> ();
19
20impl FpDevice {
21 #[cfg(not(doctest))]
22 pub fn open_sync(&self, cancellable: Option<&Cancellable>) -> Result<(), crate::GError> {
34 let raw_cancel = match cancellable {
35 Some(p) => p.to_glib_none().0,
36 None => std::ptr::null_mut(),
37 };
38
39 let mut error = std::ptr::null_mut();
40
41 let res = unsafe {
42 libfprint_sys::fp_device_open_sync(
43 self.to_glib_none().0,
44 raw_cancel.cast(),
45 std::ptr::addr_of_mut!(error),
46 )
47 };
48 if res == glib::ffi::GFALSE {
49 return Err(unsafe { glib::Error::from_glib_full(error.cast()) });
50 }
51 Ok(())
52 }
53 #[cfg(not(doctest))]
54 pub fn close_sync(&self, cancellable: Option<&Cancellable>) -> Result<(), crate::GError> {
67 let raw_cancel = match cancellable {
68 Some(p) => p.to_glib_none().0,
69 None => std::ptr::null_mut(),
70 };
71
72 let mut error = std::ptr::null_mut();
73
74 let res = unsafe {
75 libfprint_sys::fp_device_close_sync(
76 self.to_glib_none().0,
77 raw_cancel.cast(),
78 std::ptr::addr_of_mut!(error),
79 )
80 };
81 if res == glib::ffi::GFALSE {
82 return Err(unsafe { glib::Error::from_glib_full(error.cast()) });
83 }
84 Ok(())
85 }
86
87 #[cfg(not(doctest))]
88 pub fn enroll_sync<T>(
109 &self,
110 template: FpPrint,
111 cancellable: Option<&Cancellable>,
112 progress_cb: Option<FpEnrollProgress<T>>,
113 progress_data: Option<T>,
114 ) -> Result<FpPrint, crate::GError> {
115 let mut error = std::ptr::null_mut();
116
117 let template = self.check_print(template);
118
119 let raw_dev = self.to_glib_none().0;
120 let raw_cancel = match cancellable {
121 Some(p) => p.to_glib_none().0,
122 None => std::ptr::null_mut(),
123 };
124
125 let user_ptr = fn_pointer!(progress_cb, progress_data);
126
127 let raw_template: *mut libfprint_sys::FpPrint = template.to_glib_full();
129
130 let ptr = unsafe {
131 libfprint_sys::fp_device_enroll_sync(
132 raw_dev,
133 raw_template,
134 raw_cancel.cast(),
135 Some(crate::device::callback::fp_enroll_progress::<FpEnrollProgress<T>, T>),
136 user_ptr,
137 std::ptr::addr_of_mut!(error),
138 )
139 };
140
141 if !user_ptr.is_null() {
142 let _: Arc<UserData<FpEnrollProgress<T>, T>> =
143 unsafe { Arc::from_raw(user_ptr.cast()) };
144 }
145
146 if !ptr.is_null() {
147 let fp = unsafe { FpPrint::from_glib_full(ptr) };
148 unsafe {
149 fp.set_data("set", true);
150 }
151 Ok(fp)
152 } else {
153 Err(unsafe { glib::Error::from_glib_full(error.cast()) })
154 }
155 }
156
157 #[cfg(not(doctest))]
158 pub fn verify_sync<T>(
184 &self,
185 enrolled_print: &FpPrint,
186 cancellable: Option<gio::Cancellable>,
187 match_cb: Option<FpMatchCb<T>>,
188 match_data: Option<T>,
189 print: Option<&mut FpPrint>, ) -> Result<bool, crate::GError> {
191 let ptr = fn_pointer!(match_cb, match_data);
192 let mut error = std::ptr::null_mut();
193 let mut matched = glib::ffi::GFALSE;
194
195 let mut new_print: libfprint_sys::FpPrint_autoptr = std::ptr::null_mut();
196 let new_print_ptr = match print {
197 Some(_) => std::ptr::addr_of_mut!(new_print),
198 None => std::ptr::null_mut(),
199 };
200
201 let raw_cancel = match cancellable {
202 Some(p) => p.to_glib_none().0,
203 None => std::ptr::null_mut(),
204 };
205
206 let res = unsafe {
207 libfprint_sys::fp_device_verify_sync(
208 self.to_glib_none().0,
209 enrolled_print.to_glib_none().0,
210 raw_cancel.cast(),
211 Some(fp_match_cb::<FpMatchCb<T>, T>),
212 ptr,
213 &mut matched,
214 new_print_ptr,
215 &mut error,
216 )
217 };
218 if let Some(p) = print
219 && !new_print.is_null()
220 {
221 *p = unsafe { FpPrint::from_glib_full(new_print) };
222 }
223
224 if res == glib::ffi::GFALSE {
227 return Err(unsafe { glib::Error::from_glib_none(error.cast()) });
228 }
229 Ok(matched == glib::ffi::GTRUE)
231 }
232 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
233 pub fn suspend_sync(&self, cancellable: Option<&Cancellable>) -> Result<(), crate::GError> {
235 let raw_cancel = match cancellable {
236 Some(p) => p.to_glib_none().0,
237 None => std::ptr::null_mut(),
238 };
239
240 let mut error = std::ptr::null_mut();
241
242 let res = unsafe {
243 libfprint_sys::fp_device_suspend_sync(
244 self.to_glib_none().0,
245 raw_cancel.cast(),
246 std::ptr::addr_of_mut!(error),
247 )
248 };
249 if res == glib::ffi::GFALSE {
250 return Err(unsafe { glib::Error::from_glib_full(error.cast()) });
251 }
252 Ok(())
253 }
254
255 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
256 pub fn resume_sync(&self, cancellable: Option<&Cancellable>) -> Result<(), crate::GError> {
258 let raw_cancel = match cancellable {
259 Some(p) => p.to_glib_none().0,
260 None => std::ptr::null_mut(),
261 };
262
263 let mut error = std::ptr::null_mut();
264
265 let res = unsafe {
266 libfprint_sys::fp_device_resume_sync(
267 self.to_glib_none().0,
268 raw_cancel.cast(),
269 std::ptr::addr_of_mut!(error),
270 )
271 };
272 if res == glib::ffi::GFALSE {
273 return Err(unsafe { glib::Error::from_glib_full(error.cast()) });
274 }
275 Ok(())
276 }
277 #[cfg(not(doctest))]
278 pub fn identify_sync<T>(
306 &self,
307 prints: &[FpPrint],
308 cancellable: Option<&Cancellable>,
309 match_cb: Option<FpMatchCb<T>>,
310 match_data: Option<T>,
311 print: Option<&mut FpPrint>, ) -> Result<Option<FpPrint>, crate::GError> {
313 use glib::translate::ToGlibContainerFromSlice;
317 let ptr = fn_pointer!(match_cb, match_data);
318
319 let raw_prints: (*mut glib::ffi::GPtrArray, _) =
321 ToGlibContainerFromSlice::to_glib_container_from_slice(prints);
322
323 let raw_cancel = match cancellable {
324 Some(p) => p.to_glib_none().0,
325 None => std::ptr::null_mut(),
326 };
327
328 let mut new_print: libfprint_sys::FpPrint_autoptr = std::ptr::null_mut();
329 let new_print_ptr = match print {
330 Some(_) => std::ptr::addr_of_mut!(new_print),
331 None => std::ptr::null_mut(),
332 };
333
334 let mut print_match = std::ptr::null_mut();
335
336 let mut error = std::ptr::null_mut();
337
338 let res = unsafe {
339 libfprint_sys::fp_device_identify_sync(
340 self.to_glib_none().0,
341 raw_prints.0.cast(),
342 raw_cancel.cast(),
343 Some(fp_match_cb::<FpMatchCb<T>, T>),
344 ptr,
345 new_print_ptr,
346 std::ptr::addr_of_mut!(print_match),
347 std::ptr::addr_of_mut!(error),
348 )
349 };
350 unsafe { libfprint_sys::g_ptr_array_free(raw_prints.0.cast(), 1) };
351
352 if let Some(p) = print
353 && !new_print.is_null()
354 {
355 *p = unsafe { FpPrint::from_glib_full(new_print) };
356 };
357
358 if res == glib::ffi::GFALSE {
359 return Err(unsafe { glib::Error::from_glib_full(error.cast()) });
360 }
361 if print_match.is_null() {
362 Ok(None)
363 } else {
364 Ok(Some(unsafe { FpPrint::from_glib_full(print_match) }))
365 }
366 }
367 #[cfg(not(doctest))]
368 pub fn capture_sync(
379 &self,
380 wait_for_finger: bool,
381 cancellable: Option<&Cancellable>,
382 ) -> Result<FpImage, crate::GError> {
383 let raw_cancel = match cancellable {
384 Some(p) => p.to_glib_none().0,
385 None => std::ptr::null_mut(),
386 };
387
388 let mut raw_error = std::ptr::null_mut();
389
390 let raw_image = unsafe {
391 libfprint_sys::fp_device_capture_sync(
392 self.to_glib_none().0,
393 wait_for_finger as i32,
394 raw_cancel.cast(),
395 std::ptr::addr_of_mut!(raw_error),
396 )
397 };
398 if raw_image.is_null() {
399 return Err(unsafe { glib::Error::from_glib_full(raw_error.cast()) });
400 }
401 Ok(unsafe { FpImage::from_glib_full(raw_image) })
402 }
403
404 pub fn delete_print_sync() {
406 unimplemented!()
407 }
408 pub fn list_prints_sync() {
410 unimplemented!()
411 }
412 pub fn clear_storage_sync() {
414 unimplemented!()
415 }
416
417 fn check_print(&self, template: FpPrint) -> FpPrint {
418 let set: Option<bool> = unsafe { template.steal_data("set") };
420 if set == Some(true) {
421 let empty_template = FpPrint::new(self);
422 if let Some(username) = template.username() {
423 empty_template.set_username(&username);
424 }
425 if let Some(description) = template.description() {
426 empty_template.set_description(&description);
427 }
428 empty_template.set_finger(template.finger());
429 if let Some(date) = template.enroll_date() {
430 empty_template.set_enroll_date(date);
431 }
432 drop(template);
433 empty_template
434 } else {
435 template
436 }
437 }
438}