diff --git a/NEWS b/NEWS index eacd99c9..2e0a2c6a 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,16 @@ This file lists notable changes in each release. For the full history of all changes, see ChangeLog. +2021-11-02: v1.94.3 release + +Highlights: + * Ensure idle mainloop before completing enumeration (fprintd#119) + * It is now possible to extend already enrolled prints + * elanspi: Fix timeout error with some hardware (#438) + * elanspi: Fix cancellation issues + * goodixmoc: Return matching device print; fixes duplicate checking (#444) + * goodixmoc: Support clearing the storage (usually unused) + 2021-11-02: v1.94.2 release Highlights: diff --git a/README b/README.md similarity index 98% rename from README rename to README.md index 29846596..b318be9c 100644 --- a/README +++ b/README.md @@ -1,9 +1,10 @@ -libfprint -========= +# libfprint libfprint is part of the fprint project: https://fprint.freedesktop.org/ +## History + libfprint was originally developed as part of an academic project at the University of Manchester with the aim of hiding differences between different consumer fingerprint scanners and providing a single uniform API to application @@ -15,6 +16,8 @@ from this one, although I try to keep them as similar as possible (I'm not hiding anything in the academic branch, it's just the open source release contains some commits excluded from the academic project). +## License + THE UNIVERSITY OF MANCHESTER DOES NOT ENDORSE THIS THIS SOFTWARE RELEASE AND IS IN NO WAY RESPONSIBLE FOR THE CODE CONTAINED WITHIN, OR ANY DAMAGES CAUSED BY USING OR DISTRIBUTING THE SOFTWARE. Development does not happen on diff --git a/TODO b/TODO deleted file mode 100644 index 5d1034d2..00000000 --- a/TODO +++ /dev/null @@ -1,30 +0,0 @@ -LIBRARY -======= -test suite against NFIQ compliance set -make library optionally asynchronous and maybe thread-safe -nbis cleanups -API function to determine if img device supports uncond. capture -race-free way of saying "save this print but don't overwrite" - -NEW DRIVERS -=========== -Sunplus 895 driver -AES3400/3500 driver -ID Mouse driver -Support for 2nd generation MS devices -Support for 2nd generation UPEK devices - -IMAGING -======= -ignore first frame or two with aes2501 -aes2501: increase threshold "sum" for end-of-image detection -aes2501 gain calibration -aes4000 gain calibration -aes4000 resampling -PPMM parameter to get_minutiae seems to have no effect -nbis minutiae should be stored in endian-independent format - -PORTABILITY -=========== -OpenBSD can't do -Wshadow or visibility -OpenBSD: add compat codes for ENOTSUP ENODATA and EPROTO diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb index cbc6109f..91a14ebd 100644 --- a/data/autosuspend.hwdb +++ b/data/autosuspend.hwdb @@ -181,7 +181,6 @@ usb:v06CBp00DF* usb:v06CBp00F9* usb:v06CBp00FC* usb:v06CBp00C2* -usb:v06CBp00C9* usb:v06CBp0100* usb:v06CBp00F0* usb:v06CBp0103* @@ -268,15 +267,19 @@ usb:v06CBp008A* usb:v06CBp009A* usb:v06CBp009B* usb:v06CBp00A2* +usb:v06CBp00A8* usb:v06CBp00B7* usb:v06CBp00BB* usb:v06CBp00BE* usb:v06CBp00C4* usb:v06CBp00CB* +usb:v06CBp00C9* usb:v06CBp00D8* usb:v06CBp00DA* +usb:v06CBp00DC* usb:v06CBp00E7* usb:v06CBp00E9* +usb:v06CBp00FD* usb:v0A5Cp5801* usb:v0A5Cp5805* usb:v0A5Cp5834* @@ -288,6 +291,7 @@ usb:v0A5Cp5844* usb:v0A5Cp5845* usb:v0BDAp5812* usb:v10A5p0007* +usb:v10A5p9200* usb:v1188p9545* usb:v138Ap0007* usb:v138Ap003A* @@ -305,6 +309,7 @@ usb:v1491p0088* usb:v16D1p1027* usb:v1C7Ap0300* usb:v1C7Ap0575* +usb:v1C7Ap0576* usb:v27C6p5042* usb:v27C6p5110* usb:v27C6p5117* @@ -324,7 +329,9 @@ usb:v27C6p55A2* usb:v27C6p55A4* usb:v27C6p55B4* usb:v27C6p5740* +usb:v27C6p5E0A* usb:v2808p9338* +usb:v298Dp2020* usb:v298Dp2033* usb:v3538p0930* ID_AUTOSUSPEND=1 diff --git a/doc/libfprint-2-sections.txt b/doc/libfprint-2-sections.txt index 91258b62..0fb0cfab 100644 --- a/doc/libfprint-2-sections.txt +++ b/doc/libfprint-2-sections.txt @@ -260,6 +260,7 @@ fpi_ssm_get_device fpi_ssm_get_error fpi_ssm_dup_error fpi_ssm_get_cur_state +fpi_ssm_silence_debug fpi_ssm_spi_transfer_cb fpi_ssm_spi_transfer_with_weak_pointer_cb fpi_ssm_usb_transfer_cb diff --git a/examples/enroll.c b/examples/enroll.c index f133c8b8..10dfa5da 100644 --- a/examples/enroll.c +++ b/examples/enroll.c @@ -35,6 +35,7 @@ typedef struct _EnrollData unsigned int sigint_handler; FpFinger finger; int ret_value; + gboolean update_fingerprint; } EnrollData; static void @@ -84,7 +85,8 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data) /* Even if the device has storage, it may not be able to save all the * metadata that the print contains, so we can always save a local copy * containing the handle to the device print */ - int r = print_data_save (print, enroll_data->finger); + int r = print_data_save (print, enroll_data->finger, + enroll_data->update_fingerprint); if (r < 0) { g_warning ("Data save failed, code %d", r); @@ -124,6 +126,40 @@ on_enroll_progress (FpDevice *device, fp_device_get_nr_enroll_stages (device)); } +static gboolean +should_update_fingerprint (void) +{ + int update_choice; + gboolean update_fingerprint = FALSE; + + printf ("Should an existing fingerprint be updated instead of being replaced (if present)? " + "Enter Y/y or N/n to make a choice.\n"); + update_choice = getchar (); + if (update_choice == EOF) + { + g_warning ("EOF encountered while reading a character"); + return EXIT_FAILURE; + } + + switch (update_choice) + { + case 'y': + case 'Y': + update_fingerprint = TRUE; + break; + + case 'n': + case 'N': + update_fingerprint = FALSE; + break; + + default: + g_warning ("Invalid choice %c, should be Y/y or N/n.", update_choice); + return EXIT_FAILURE; + } + return update_fingerprint; +} + static void on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data) { @@ -139,13 +175,26 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data) return; } - printf ("Opened device. It's now time to enroll your finger.\n\n"); + printf ("Opened device.\n"); + + if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_UPDATE_PRINT)) + { + printf ("The device supports fingerprint updates.\n"); + enroll_data->update_fingerprint = should_update_fingerprint (); + } + else + { + printf ("The device doesn't support fingerprint updates. Old prints will be erased.\n"); + enroll_data->update_fingerprint = FALSE; + } + + printf ("It's now time to enroll your finger.\n\n"); printf ("You will need to successfully scan your %s finger %d times to " "complete the process.\n\n", finger_to_string (enroll_data->finger), fp_device_get_nr_enroll_stages (dev)); printf ("Scan your finger now.\n"); - print_template = print_create_template (dev, enroll_data->finger); + print_template = print_create_template (dev, enroll_data->finger, enroll_data->update_fingerprint); fp_device_enroll (dev, print_template, enroll_data->cancellable, on_enroll_progress, NULL, NULL, (GAsyncReadyCallback) on_enroll_completed, @@ -171,11 +220,9 @@ main (void) FpDevice *dev; FpFinger finger; - g_print ("This program will enroll the selected finger, unconditionally " - "overwriting any print for the same finger that was enrolled " - "previously. If you want to continue, press enter, otherwise hit " - "Ctrl+C\n"); - getchar (); + g_print ("This program will enroll the selected finger overwriting any print for the same" + " finger that was enrolled previously. Fingerprint updates without erasing old data" + " are possible on devices supporting that. Ctrl+C interrupts program execution.\n"); g_print ("Choose the finger to enroll:\n"); finger = finger_chooser (); diff --git a/examples/identify.c b/examples/identify.c index bc2fe00d..dc6a5d5c 100644 --- a/examples/identify.c +++ b/examples/identify.c @@ -143,6 +143,7 @@ on_identify_cb (FpDevice *dev, FpPrint *match, FpPrint *print, if (match) { g_autoptr(FpPrint) matched_print = g_object_ref (match); + const GDate *date; char date_str[128] = {}; identify_data->ret_value = EXIT_SUCCESS; @@ -155,7 +156,8 @@ on_identify_cb (FpDevice *dev, FpPrint *match, FpPrint *print, matched_print = g_steal_pointer (&stored_print); } - if (fp_print_get_enroll_date (matched_print)) + date = fp_print_get_enroll_date (matched_print); + if (date && g_date_valid (date)) g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0", fp_print_get_enroll_date (matched_print)); else diff --git a/examples/manage-prints.c b/examples/manage-prints.c index 4d206cc9..88200a35 100644 --- a/examples/manage-prints.c +++ b/examples/manage-prints.c @@ -161,7 +161,7 @@ on_list_completed (FpDevice *dev, finger_to_string (fp_print_get_finger (print)), fp_print_get_username (print)); - if (date) + if (date && g_date_valid (date)) { g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d\0", date); g_print (", enrolled on %s", buf); diff --git a/examples/storage.c b/examples/storage.c index 6c92dba6..b84c72d5 100644 --- a/examples/storage.c +++ b/examples/storage.c @@ -102,8 +102,23 @@ save_data (GVariant *data) return 0; } +static FpPrint * +load_print_from_data (GVariant *data) +{ + const guchar *stored_data = NULL; + gsize stored_len; + FpPrint *print; + + g_autoptr(GError) error = NULL; + stored_data = (const guchar *) g_variant_get_fixed_array (data, &stored_len, 1); + print = fp_print_deserialize (stored_data, stored_len, &error); + if (error) + g_warning ("Error deserializing data: %s", error->message); + return print; +} + int -print_data_save (FpPrint *print, FpFinger finger) +print_data_save (FpPrint *print, FpFinger finger, gboolean update_fingerprint) { g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger); @@ -137,25 +152,12 @@ print_data_load (FpDevice *dev, FpFinger finger) g_autoptr(GVariant) val = NULL; g_autoptr(GVariantDict) dict = NULL; - const guchar *stored_data = NULL; - gsize stored_len; dict = load_data (); val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); if (val) - { - FpPrint *print; - g_autoptr(GError) error = NULL; - - stored_data = (const guchar *) g_variant_get_fixed_array (val, &stored_len, 1); - print = fp_print_deserialize (stored_data, stored_len, &error); - - if (error) - g_warning ("Error deserializing data: %s", error->message); - - return print; - } + return load_print_from_data (val); return NULL; } @@ -207,16 +209,30 @@ gallery_data_load (FpDevice *dev) } FpPrint * -print_create_template (FpDevice *dev, FpFinger finger) +print_create_template (FpDevice *dev, FpFinger finger, gboolean load_existing) { + g_autoptr(GVariantDict) dict = NULL; g_autoptr(GDateTime) datetime = NULL; g_autoptr(GDate) date = NULL; + g_autoptr(GVariant) existing_val = NULL; + g_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger); FpPrint *template = NULL; gint year, month, day; - template = fp_print_new (dev); - fp_print_set_finger (template, finger); - fp_print_set_username (template, g_get_user_name ()); + if (load_existing) + { + dict = load_data (); + existing_val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); + if (existing_val != NULL) + template = load_print_from_data (existing_val); + } + if (template == NULL) + { + template = fp_print_new (dev); + fp_print_set_finger (template, finger); + fp_print_set_username (template, g_get_user_name ()); + } + datetime = g_date_time_new_now_local (); g_date_time_get_ymd (datetime, &year, &month, &day); date = g_date_new_dmy (day, month, year); diff --git a/examples/storage.h b/examples/storage.h index 81390bd0..0922b902 100644 --- a/examples/storage.h +++ b/examples/storage.h @@ -21,12 +21,14 @@ #pragma once int print_data_save (FpPrint *print, - FpFinger finger); + FpFinger finger, + gboolean update_fingerprint); FpPrint * print_data_load (FpDevice *dev, FpFinger finger); GPtrArray * gallery_data_load (FpDevice *dev); -FpPrint * print_create_template (FpDevice *dev, - FpFinger finger); +FpPrint * print_create_template (FpDevice *dev, + FpFinger finger, + const gboolean load_existing); gboolean print_image_save (FpPrint *print, const char *path); gboolean save_image_to_pgm (FpImage *img, diff --git a/examples/verify.c b/examples/verify.c index 4b16323d..6892ef0e 100644 --- a/examples/verify.c +++ b/examples/verify.c @@ -130,12 +130,14 @@ on_match_cb (FpDevice *dev, FpPrint *match, FpPrint *print, if (match) { - char date_str[128]; + const GDate *date = fp_print_get_enroll_date (match); + char date_str[128] = ""; verify_data->ret_value = EXIT_SUCCESS; - g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0", - fp_print_get_enroll_date (match)); + if (date && g_date_valid (date)) + g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0", + fp_print_get_enroll_date (match)); g_debug ("Match report: device %s matched finger %s successifully " "with print %s, enrolled on date %s by user %s", fp_device_get_name (dev), diff --git a/libfprint/drivers/elanspi.c b/libfprint/drivers/elanspi.c index daea67c3..9338013d 100644 --- a/libfprint/drivers/elanspi.c +++ b/libfprint/drivers/elanspi.c @@ -439,6 +439,12 @@ elanspi_capture_old_line_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpoin } else { + /* check for termination */ + if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_NONE) + { + fpi_ssm_mark_completed (transfer->ssm); + return; + } /* check for cancellation */ if (fpi_device_action_is_cancelled (dev)) { @@ -606,6 +612,7 @@ elanspi_calibrate_old_handler (FpiSsm *ssm, FpDevice *dev) case ELANSPI_CALIBOLD_CHECKFIN_CAPTURE: case ELANSPI_CALIBOLD_DACFINE_CAPTURE: chld = fpi_ssm_new (dev, elanspi_capture_old_handler, ELANSPI_CAPTOLD_NSTATES); + fpi_ssm_silence_debug (chld); fpi_ssm_start_subsm (ssm, chld); return; @@ -860,6 +867,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev) case ELANSPI_CALIBHV_CAPTURE: chld = fpi_ssm_new (dev, elanspi_capture_hv_handler, ELANSPI_CAPTHV_NSTATES); + fpi_ssm_silence_debug (chld); fpi_ssm_start_subsm (ssm, chld); return; @@ -1115,6 +1123,7 @@ do_sw_reset: chld = fpi_ssm_new_full (dev, elanspi_calibrate_hv_handler, ELANSPI_CALIBHV_NSTATES, ELANSPI_CALIBHV_PROTECT, "HV calibrate"); else chld = fpi_ssm_new_full (dev, elanspi_calibrate_old_handler, ELANSPI_CALIBOLD_NSTATES, ELANSPI_CALIBOLD_PROTECT, "old calibrate"); + fpi_ssm_silence_debug (chld); fpi_ssm_start_subsm (ssm, chld); return; @@ -1123,6 +1132,7 @@ do_sw_reset: chld = fpi_ssm_new (dev, elanspi_capture_hv_handler, ELANSPI_CAPTHV_NSTATES); else chld = fpi_ssm_new (dev, elanspi_capture_old_handler, ELANSPI_CAPTOLD_NSTATES); + fpi_ssm_silence_debug (chld); fpi_ssm_start_subsm (ssm, chld); return; @@ -1219,8 +1229,6 @@ elanspi_guess_image (FpiDeviceElanSpi *self, guint16 *raw_image) sq_stddev /= (frame_width * frame_height); - fp_dbg (" stddev=%" G_GUINT64_FORMAT "d, ip=%d, is_fp=%d, is_empty=%d", sq_stddev, invalid_percent, is_fp, is_empty); - if (invalid_percent < ELANSPI_MAX_REAL_INVALID_PERCENT) is_fp += 1; if (invalid_percent > ELANSPI_MIN_EMPTY_INVALID_PERCENT) @@ -1231,6 +1239,8 @@ elanspi_guess_image (FpiDeviceElanSpi *self, guint16 *raw_image) if (sq_stddev < ELANSPI_MAX_EMPTY_STDDEV) is_empty += 1; + fp_dbg (" stddev=%" G_GUINT64_FORMAT "d, ip=%d, is_fp=%d, is_empty=%d", sq_stddev, invalid_percent, is_fp, is_empty); + if (is_fp > is_empty) return ELANSPI_GUESS_FINGERPRINT; else if (is_empty > is_fp) @@ -1482,11 +1492,12 @@ elanspi_fp_capture_ssm_handler (FpiSsm *ssm, FpDevice *dev) if (self->deactivating) { fp_dbg (" got deactivate; exiting"); + + self->deactivating = FALSE; fpi_ssm_mark_completed (ssm); /* mark deactivate done */ fpi_image_device_deactivate_complete (FP_IMAGE_DEVICE (dev), NULL); - self->deactivating = FALSE; return; } @@ -1495,6 +1506,7 @@ elanspi_fp_capture_ssm_handler (FpiSsm *ssm, FpDevice *dev) chld = fpi_ssm_new (dev, elanspi_capture_hv_handler, ELANSPI_CAPTHV_NSTATES); else chld = fpi_ssm_new (dev, elanspi_capture_old_handler, ELANSPI_CAPTOLD_NSTATES); + fpi_ssm_silence_debug (chld); fpi_ssm_start_subsm (ssm, chld); return; diff --git a/libfprint/drivers/elanspi.h b/libfprint/drivers/elanspi.h index c9e17b8c..ffe34160 100644 --- a/libfprint/drivers/elanspi.h +++ b/libfprint/drivers/elanspi.h @@ -97,7 +97,37 @@ static const struct elanspi_reg_entry elanspi_calibration_table_default[] = { {0xff, 0xff} }; -static const struct elanspi_reg_entry elanspi_calibration_table_id567[] = { +static const struct elanspi_reg_entry elanspi_calibration_table_id6[] = { + {0x2A, 0x07}, + {0x1, 0x00}, + {0x2, 0x5f}, + {0x3, 0x00}, + {0x4, 0x5f}, + {0x5, 0x60}, + {0x6, 0xC0}, + {0x7, 0x80}, + {0x8, 0x04}, + {0xA, 0x97}, + {0xB, 0x72}, + {0xC, 0x69}, + {0xF, 0x2A}, + {0x11, 0x2A}, + {0x13, 0x27}, + {0x15, 0x67}, + {0x18, 0x04}, + {0x21, 0x20}, + {0x22, 0x36}, + {0x29, 0x02}, + {0x2A, 0x03}, + {0x2A, 0x5F}, + {0x2B, 0xC0}, + {0x2C, 0x10}, + {0x2E, 0xFF}, + + {0xff, 0xff} +}; + +static const struct elanspi_reg_entry elanspi_calibration_table_id57[] = { {0x2A, 0x07}, {0x5, 0x60}, {0x6, 0xC0}, @@ -143,9 +173,9 @@ static const struct elanspi_regtable elanspi_calibration_table_old = { .other = elanspi_calibration_table_default, .entries = { { .sid = 0x0, .table = elanspi_calibration_table_id0 }, - { .sid = 0x5, .table = elanspi_calibration_table_id567 }, - { .sid = 0x6, .table = elanspi_calibration_table_id567 }, - { .sid = 0x7, .table = elanspi_calibration_table_id567 }, + { .sid = 0x5, .table = elanspi_calibration_table_id57 }, + { .sid = 0x6, .table = elanspi_calibration_table_id6 }, + { .sid = 0x7, .table = elanspi_calibration_table_id57 }, { .sid = 0x0, .table = NULL } } }; diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 15a85323..4eeb7215 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -159,7 +159,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer, { fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, - "Corrupted message received")); + "Corrupted message header received")); return; } @@ -420,12 +420,9 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, gxfp_cmd_response_t *resp, GError *error) { - g_autoptr(GPtrArray) templates = NULL; FpDevice *device = FP_DEVICE (self); - FpPrint *match = NULL; - FpPrint *print = NULL; - gint cnt = 0; - gboolean find = false; + FpPrint *new_scan = NULL; + FpPrint *matching = NULL; if (error) { @@ -434,46 +431,34 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, } if (resp->verify.match) { - match = fp_print_from_template (self, &resp->verify.template); + new_scan = fp_print_from_template (self, &resp->verify.template); if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY) { - templates = g_ptr_array_sized_new (1); - fpi_device_get_verify_data (device, &print); - g_ptr_array_add (templates, print); + fpi_device_get_verify_data (device, &matching); + if (!fp_print_equal (matching, new_scan)) + matching = NULL; } else { + GPtrArray *templates = NULL; fpi_device_get_identify_data (device, &templates); - g_ptr_array_ref (templates); - } - for (cnt = 0; cnt < templates->len; cnt++) - { - print = g_ptr_array_index (templates, cnt); - if (fp_print_equal (print, match)) + for (gint i = 0; i < templates->len; i++) { - find = true; - break; + if (fp_print_equal (g_ptr_array_index (templates, i), new_scan)) + { + matching = g_ptr_array_index (templates, i); + break; + } } - - } - if (find) - { - if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY) - fpi_device_verify_report (device, FPI_MATCH_SUCCESS, match, error); - else - fpi_device_identify_report (device, print, match, error); } } - if (!find) - { - if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY) - fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error); - else - fpi_device_identify_report (device, NULL, NULL, error); - } + if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY) + fpi_device_verify_report (device, matching ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, new_scan, error); + else + fpi_device_identify_report (device, matching, new_scan, error); fpi_ssm_next_state (self->task_ssm); @@ -764,9 +749,14 @@ fp_enroll_check_duplicate_cb (FpiDeviceGoodixMoc *self, } if (resp->check_duplicate_resp.duplicate) { + g_autoptr(FpPrint) print = NULL; + + print = g_object_ref_sink (fp_print_from_template (self, &resp->check_duplicate_resp.template)); + fpi_ssm_mark_failed (self->task_ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_DUPLICATE, - "Finger has already enrolled")); + "Finger was already enrolled as '%s'", + fp_print_get_description (print))); return; } @@ -1170,6 +1160,32 @@ fp_template_delete_cb (FpiDeviceGoodixMoc *self, fp_info ("Successfully deleted enrolled user"); fpi_device_delete_complete (device, NULL); } + +static void +fp_template_delete_all_cb (FpiDeviceGoodixMoc *self, + gxfp_cmd_response_t *resp, + GError *error) +{ + FpDevice *device = FP_DEVICE (self); + + if (error) + { + fpi_device_clear_storage_complete (device, error); + return; + } + if ((resp->result >= GX_FAILED) && (resp->result != GX_ERROR_FINGER_ID_NOEXIST)) + { + fpi_device_clear_storage_complete (FP_DEVICE (self), + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Failed clear storage, result: 0x%x", + resp->result)); + return; + } + + fp_info ("Successfully cleared storage"); + fpi_device_clear_storage_complete (device, NULL); +} + /****************************************************************************** * * fp_template_list Function @@ -1493,6 +1509,19 @@ gx_fp_template_delete (FpDevice *device) } +static void +gx_fp_template_delete_all (FpDevice *device) +{ + FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device); + + goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL, + false, + NULL, + 0, + fp_template_delete_all_cb); + +} + static void fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self) { @@ -1536,6 +1565,7 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass) dev_class->probe = gx_fp_probe; dev_class->enroll = gx_fp_enroll; dev_class->delete = gx_fp_template_delete; + dev_class->clear_storage = gx_fp_template_delete_all; dev_class->list = gx_fp_template_list; dev_class->verify = gx_fp_verify_identify; dev_class->identify = gx_fp_verify_identify; diff --git a/libfprint/drivers/goodixmoc/goodix_proto.c b/libfprint/drivers/goodixmoc/goodix_proto.c index 01044a94..b615dbaa 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.c +++ b/libfprint/drivers/goodixmoc/goodix_proto.c @@ -259,12 +259,9 @@ gx_proto_parse_fingerid ( if (buffer[Offset++] != 67) return -1; - fid_buffer_size--; template->type = buffer[Offset++]; - fid_buffer_size--; template->finger_index = buffer[Offset++]; - fid_buffer_size--; Offset++; memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid)); Offset += sizeof (template->accountid); @@ -273,6 +270,8 @@ gx_proto_parse_fingerid ( template->payload.size = buffer[Offset++]; if (template->payload.size > sizeof (template->payload.data)) return -1; + if (template->payload.size + Offset > fid_buffer_size) + return -1; memset (template->payload.data, 0, template->payload.size); memcpy (template->payload.data, &buffer[Offset], template->payload.size); @@ -365,9 +364,12 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c if (buffer_len < 3) return -1; uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1)); - if ((buffer_len < tid_size + 3) || (buffer_len > sizeof (template_format_t)) + 3) + offset += 3; + + if (buffer_len < tid_size + offset) + return -1; + if (gx_proto_parse_fingerid (buffer + offset, tid_size, &presp->check_duplicate_resp.template) != 0) return -1; - memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size); } break; @@ -380,9 +382,12 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c fingerlist = buffer + 2; for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++) { - uint16_t fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset)); + uint16_t fingerid_length; + if (buffer_len < offset + 2) + return -1; + fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset)); offset += 2; - if (buffer_len < fingerid_length + offset + 2) + if (buffer_len < fingerid_length + offset) return -1; if (gx_proto_parse_fingerid (fingerlist + offset, fingerid_length, @@ -405,7 +410,7 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c presp->verify.match = (buffer[0] == 0) ? true : false; if (presp->verify.match) { - if (buffer_len < sizeof (template_format_t) + 10) + if (buffer_len < 10) return -1; offset += 1; presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset)); @@ -416,6 +421,8 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c offset += 1; fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset)); offset += 2; + if (buffer_len < fingerid_size + offset) + return -1; if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0) { presp->result = GX_FAILED; diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index 98627ed7..7a2c6ebe 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -36,7 +36,6 @@ static const FpIdEntry id_table[] = { { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, }, - { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C9, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, }, diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index 35e2f2b8..82f309e8 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -1189,10 +1189,11 @@ fp_device_resume_finish (FpDevice *device, * fp_device_enroll_finish(). * * The @template_print parameter is a #FpPrint with available metadata filled - * in. The driver may make use of this metadata, when e.g. storing the print on - * device memory. It is undefined whether this print is filled in by the driver - * and returned, or whether the driver will return a newly created print after - * enrollment succeeded. + * in and, optionally, with existing fingerprint data to be updated with newly + * enrolled fingerprints if a device driver supports it. The driver may make use + * of the metadata, when e.g. storing the print on device memory. It is undefined + * whether this print is filled in by the driver and returned, or whether the + * driver will return a newly created print after enrollment succeeded. */ void fp_device_enroll (FpDevice *device, @@ -1229,19 +1230,30 @@ fp_device_enroll (FpDevice *device, if (!FP_IS_PRINT (template_print)) { - g_warning ("User did not pass a print template!"); g_task_return_error (task, - fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID, + "User did not pass a print template!")); return; } g_object_get (template_print, "fpi-type", &print_type, NULL); if (print_type != FPI_PRINT_UNDEFINED) { - g_warning ("Passed print template must be newly created and blank!"); - g_task_return_error (task, - fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); - return; + if (!fp_device_has_feature (device, FP_DEVICE_FEATURE_UPDATE_PRINT)) + { + g_task_return_error (task, + fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID, + "A device does not support print updates!")); + return; + } + if (!fp_print_compatible (template_print, device)) + { + g_task_return_error (task, + fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID, + "The print and device must have a matching driver and device id" + " for a fingerprint update to succeed")); + return; + } } priv->current_action = FPI_DEVICE_ACTION_ENROLL; diff --git a/libfprint/fp-device.h b/libfprint/fp-device.h index 5a9dda0f..1069bc59 100644 --- a/libfprint/fp-device.h +++ b/libfprint/fp-device.h @@ -59,6 +59,7 @@ typedef enum { * @FP_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage * @FP_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection * @FP_DEVICE_FEATURE_ALWAYS_ON: Whether the device can run continuously + * @FP_DEVICE_FEATURE_UPDATE_PRINT: Supports updating an existing print record using new scans */ typedef enum /*< flags >*/ { FP_DEVICE_FEATURE_NONE = 0, @@ -71,6 +72,7 @@ typedef enum /*< flags >*/ { FP_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6, FP_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7, FP_DEVICE_FEATURE_ALWAYS_ON = 1 << 8, + FP_DEVICE_FEATURE_UPDATE_PRINT = 1 << 9, } FpDeviceFeature; /** diff --git a/libfprint/fp-image-device.c b/libfprint/fp-image-device.c index 82e69f99..519ad754 100644 --- a/libfprint/fp-image-device.c +++ b/libfprint/fp-image-device.c @@ -101,6 +101,7 @@ fp_image_device_start_capture_action (FpDevice *device) FpImageDevice *self = FP_IMAGE_DEVICE (device); FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); FpiDeviceAction action; + FpiPrintType print_type; /* There is just one action that we cannot support out * of the box, which is a capture without first waiting @@ -124,7 +125,9 @@ fp_image_device_start_capture_action (FpDevice *device) FpPrint *enroll_print = NULL; fpi_device_get_enroll_data (device, &enroll_print); - fpi_print_set_type (enroll_print, FPI_PRINT_NBIS); + g_object_get (enroll_print, "fpi-type", &print_type, NULL); + if (print_type != FPI_PRINT_NBIS) + fpi_print_set_type (enroll_print, FPI_PRINT_NBIS); } priv->enroll_stage = 0; @@ -221,6 +224,7 @@ fp_image_device_class_init (FpImageDeviceClass *klass) fp_device_class->cancel = fp_image_device_cancel_action; fpi_device_class_auto_initialize_features (fp_device_class); + fp_device_class->features |= FP_DEVICE_FEATURE_UPDATE_PRINT; /* Default implementations */ klass->activate = fp_image_device_default_activate; diff --git a/libfprint/fp-print.c b/libfprint/fp-print.c index c8a1b071..8532b6cc 100644 --- a/libfprint/fp-print.c +++ b/libfprint/fp-print.c @@ -61,6 +61,7 @@ enum { /* Private property*/ PROP_FPI_TYPE, PROP_FPI_DATA, + PROP_FPI_PRINTS, N_PROPS }; @@ -133,6 +134,10 @@ fp_print_get_property (GObject *object, g_value_set_variant (value, self->data); break; + case PROP_FPI_PRINTS: + g_value_set_pointer (value, self->prints); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -188,6 +193,11 @@ fp_print_set_property (GObject *object, self->data = g_value_dup_variant (value); break; + case PROP_FPI_PRINTS: + g_clear_pointer (&self->prints, g_ptr_array_unref); + self->prints = g_value_get_pointer (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -299,6 +309,19 @@ fp_print_class_init (FpPrintClass *klass) NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + /** + * FpPrint::fpi-prints: (skip) + * + * This property is only for internal purposes. + * + * Stability: private + */ + properties[PROP_FPI_PRINTS] = + g_param_spec_pointer ("fpi-prints", + "Prints", + "Prints for internal use only", + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_properties (object_class, N_PROPS, properties); } diff --git a/libfprint/fpi-ssm.c b/libfprint/fpi-ssm.c index 8080f550..fb36fc44 100644 --- a/libfprint/fpi-ssm.c +++ b/libfprint/fpi-ssm.c @@ -81,6 +81,7 @@ struct _FpiSsm int start_cleanup; int cur_state; gboolean completed; + gboolean silence; GSource *timeout; GError *error; FpiSsmCompletedCallback callback; @@ -245,10 +246,11 @@ fpi_ssm_free (FpiSsm *machine) /* Invoke the state handler */ static void -__ssm_call_handler (FpiSsm *machine) +__ssm_call_handler (FpiSsm *machine, gboolean force_msg) { - fp_dbg ("[%s] %s entering state %d", fp_device_get_driver (machine->dev), - machine->name, machine->cur_state); + if (force_msg || !machine->silence) + fp_dbg ("[%s] %s entering state %d", fp_device_get_driver (machine->dev), + machine->name, machine->cur_state); machine->handler (machine, machine->dev); } @@ -275,7 +277,7 @@ fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback) ssm->cur_state = 0; ssm->completed = FALSE; ssm->error = NULL; - __ssm_call_handler (ssm); + __ssm_call_handler (ssm, TRUE); } static void @@ -346,7 +348,7 @@ fpi_ssm_mark_completed (FpiSsm *machine) if (next_state < machine->nr_states) { machine->cur_state = next_state; - __ssm_call_handler (machine); + __ssm_call_handler (machine, TRUE); return; } @@ -460,7 +462,7 @@ fpi_ssm_next_state (FpiSsm *machine) if (machine->cur_state == machine->nr_states) fpi_ssm_mark_completed (machine); else - __ssm_call_handler (machine); + __ssm_call_handler (machine, FALSE); } void @@ -537,7 +539,7 @@ fpi_ssm_jump_to_state (FpiSsm *machine, int state) if (machine->cur_state == machine->nr_states) fpi_ssm_mark_completed (machine); else - __ssm_call_handler (machine); + __ssm_call_handler (machine, FALSE); } typedef struct @@ -642,6 +644,22 @@ fpi_ssm_dup_error (FpiSsm *machine) return NULL; } +/** + * fpi_ssm_silence_debug: + * @machine: an #FpiSsm state machine + * + * Turn off state change debug messages from this SSM. This does not disable + * all messages, as e.g. the initial state, SSM completion and cleanup states + * are still printed out. + * + * Use if the SSM loops and would flood the debug log otherwise. + */ +void +fpi_ssm_silence_debug (FpiSsm *machine) +{ + machine->silence = TRUE; +} + /** * fpi_ssm_usb_transfer_cb: * @transfer: a #FpiUsbTransfer diff --git a/libfprint/fpi-ssm.h b/libfprint/fpi-ssm.h index 235e84ad..d2601c88 100644 --- a/libfprint/fpi-ssm.h +++ b/libfprint/fpi-ssm.h @@ -96,6 +96,8 @@ GError * fpi_ssm_get_error (FpiSsm *machine); GError * fpi_ssm_dup_error (FpiSsm *machine); int fpi_ssm_get_cur_state (FpiSsm *machine); +void fpi_ssm_silence_debug (FpiSsm *machine); + /* Callbacks to be used by the driver instead of implementing their own * logic. */ diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index f5674574..ad9cdd07 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -42,15 +42,19 @@ static const FpIdEntry whitelist_id_table[] = { { .vid = 0x06cb, .pid = 0x009a }, { .vid = 0x06cb, .pid = 0x009b }, { .vid = 0x06cb, .pid = 0x00a2 }, + { .vid = 0x06cb, .pid = 0x00a8 }, { .vid = 0x06cb, .pid = 0x00b7 }, { .vid = 0x06cb, .pid = 0x00bb }, { .vid = 0x06cb, .pid = 0x00be }, { .vid = 0x06cb, .pid = 0x00c4 }, { .vid = 0x06cb, .pid = 0x00cb }, + { .vid = 0x06cb, .pid = 0x00c9 }, { .vid = 0x06cb, .pid = 0x00d8 }, { .vid = 0x06cb, .pid = 0x00da }, + { .vid = 0x06cb, .pid = 0x00dc }, { .vid = 0x06cb, .pid = 0x00e7 }, { .vid = 0x06cb, .pid = 0x00e9 }, + { .vid = 0x06cb, .pid = 0x00fd }, { .vid = 0x0a5c, .pid = 0x5801 }, { .vid = 0x0a5c, .pid = 0x5805 }, { .vid = 0x0a5c, .pid = 0x5834 }, @@ -62,6 +66,7 @@ static const FpIdEntry whitelist_id_table[] = { { .vid = 0x0a5c, .pid = 0x5845 }, { .vid = 0x0bda, .pid = 0x5812 }, { .vid = 0x10a5, .pid = 0x0007 }, + { .vid = 0x10a5, .pid = 0x9200 }, { .vid = 0x1188, .pid = 0x9545 }, { .vid = 0x138a, .pid = 0x0007 }, { .vid = 0x138a, .pid = 0x003a }, @@ -79,6 +84,7 @@ static const FpIdEntry whitelist_id_table[] = { { .vid = 0x16d1, .pid = 0x1027 }, { .vid = 0x1c7a, .pid = 0x0300 }, { .vid = 0x1c7a, .pid = 0x0575 }, + { .vid = 0x1c7a, .pid = 0x0576 }, { .vid = 0x27c6, .pid = 0x5042 }, { .vid = 0x27c6, .pid = 0x5110 }, { .vid = 0x27c6, .pid = 0x5117 }, @@ -98,7 +104,9 @@ static const FpIdEntry whitelist_id_table[] = { { .vid = 0x27c6, .pid = 0x55a4 }, { .vid = 0x27c6, .pid = 0x55b4 }, { .vid = 0x27c6, .pid = 0x5740 }, + { .vid = 0x27c6, .pid = 0x5e0a }, { .vid = 0x2808, .pid = 0x9338 }, + { .vid = 0x298d, .pid = 0x2020 }, { .vid = 0x298d, .pid = 0x2033 }, { .vid = 0x3538, .pid = 0x0930 }, { .vid = 0 }, diff --git a/libfprint/tod/libfprint-tod.ver.in b/libfprint/tod/libfprint-tod.ver.in index 8166f164..496d5252 100644 --- a/libfprint/tod/libfprint-tod.ver.in +++ b/libfprint/tod/libfprint-tod.ver.in @@ -1,10 +1,212 @@ LIBFPRINT_TOD_@tod_soversion@.0.0 { global: - fpi_*; - fpi_ssm_new_full; + fpi_assemble_frames; + fpi_assemble_lines; + fpi_byte_reader_dup_data; + fpi_byte_reader_dup_string_utf16; + fpi_byte_reader_dup_string_utf32; + fpi_byte_reader_dup_string_utf8; + fpi_byte_reader_free; + fpi_byte_reader_get_data; + fpi_byte_reader_get_float32_be; + fpi_byte_reader_get_float32_le; + fpi_byte_reader_get_float64_be; + fpi_byte_reader_get_float64_le; + fpi_byte_reader_get_int16_be; + fpi_byte_reader_get_int16_le; + fpi_byte_reader_get_int24_be; + fpi_byte_reader_get_int24_le; + fpi_byte_reader_get_int32_be; + fpi_byte_reader_get_int32_le; + fpi_byte_reader_get_int64_be; + fpi_byte_reader_get_int64_le; + fpi_byte_reader_get_int8; + fpi_byte_reader_get_pos; + fpi_byte_reader_get_remaining; + fpi_byte_reader_get_size; + fpi_byte_reader_get_string_utf8; + fpi_byte_reader_get_sub_reader; + fpi_byte_reader_get_uint16_be; + fpi_byte_reader_get_uint16_le; + fpi_byte_reader_get_uint24_be; + fpi_byte_reader_get_uint24_le; + fpi_byte_reader_get_uint32_be; + fpi_byte_reader_get_uint32_le; + fpi_byte_reader_get_uint64_be; + fpi_byte_reader_get_uint64_le; + fpi_byte_reader_get_uint8; + fpi_byte_reader_init; + fpi_byte_reader_masked_scan_uint32; + fpi_byte_reader_masked_scan_uint32_peek; + fpi_byte_reader_new; + fpi_byte_reader_peek_data; + fpi_byte_reader_peek_float32_be; + fpi_byte_reader_peek_float32_le; + fpi_byte_reader_peek_float64_be; + fpi_byte_reader_peek_float64_le; + fpi_byte_reader_peek_int16_be; + fpi_byte_reader_peek_int16_le; + fpi_byte_reader_peek_int24_be; + fpi_byte_reader_peek_int24_le; + fpi_byte_reader_peek_int32_be; + fpi_byte_reader_peek_int32_le; + fpi_byte_reader_peek_int64_be; + fpi_byte_reader_peek_int64_le; + fpi_byte_reader_peek_int8; + fpi_byte_reader_peek_string_utf8; + fpi_byte_reader_peek_sub_reader; + fpi_byte_reader_peek_uint16_be; + fpi_byte_reader_peek_uint16_le; + fpi_byte_reader_peek_uint24_be; + fpi_byte_reader_peek_uint24_le; + fpi_byte_reader_peek_uint32_be; + fpi_byte_reader_peek_uint32_le; + fpi_byte_reader_peek_uint64_be; + fpi_byte_reader_peek_uint64_le; + fpi_byte_reader_peek_uint8; + fpi_byte_reader_set_pos; + fpi_byte_reader_skip; + fpi_byte_reader_skip_string_utf16; + fpi_byte_reader_skip_string_utf32; + fpi_byte_reader_skip_string_utf8; + fpi_byte_writer_ensure_free_space; + fpi_byte_writer_fill; + fpi_byte_writer_free; + fpi_byte_writer_free_and_get_data; + fpi_byte_writer_get_remaining; + fpi_byte_writer_init; + fpi_byte_writer_init_with_data; + fpi_byte_writer_init_with_size; + fpi_byte_writer_new; + fpi_byte_writer_new_with_data; + fpi_byte_writer_new_with_size; + fpi_byte_writer_put_data; + fpi_byte_writer_put_float32_be; + fpi_byte_writer_put_float32_le; + fpi_byte_writer_put_float64_be; + fpi_byte_writer_put_float64_le; + fpi_byte_writer_put_int16_be; + fpi_byte_writer_put_int16_le; + fpi_byte_writer_put_int24_be; + fpi_byte_writer_put_int24_le; + fpi_byte_writer_put_int32_be; + fpi_byte_writer_put_int32_le; + fpi_byte_writer_put_int64_be; + fpi_byte_writer_put_int64_le; + fpi_byte_writer_put_int8; + fpi_byte_writer_put_string_utf16; + fpi_byte_writer_put_string_utf32; + fpi_byte_writer_put_string_utf8; + fpi_byte_writer_put_uint16_be; + fpi_byte_writer_put_uint16_le; + fpi_byte_writer_put_uint24_be; + fpi_byte_writer_put_uint24_le; + fpi_byte_writer_put_uint32_be; + fpi_byte_writer_put_uint32_le; + fpi_byte_writer_put_uint64_be; + fpi_byte_writer_put_uint64_le; + fpi_byte_writer_put_uint8; + fpi_byte_writer_reset; + fpi_byte_writer_reset_and_get_data; + fpi_device_action_error; + fpi_device_action_get_type; + fpi_device_action_is_cancelled; + fpi_device_add_timeout; + fpi_device_capture_complete; + fpi_device_close_complete; + fpi_device_configure_wakeup; + fpi_device_delete_complete; + fpi_device_enroll_complete; + fpi_device_enroll_progress; + fpi_device_error_new; + fpi_device_error_new_msg; + fpi_device_get_cancellable; + fpi_device_get_capture_data; + fpi_device_get_current_action; + fpi_device_get_delete_data; + fpi_device_get_driver_data; + fpi_device_get_enroll_data; + fpi_device_get_identify_data; + fpi_device_get_usb_device; + fpi_device_get_verify_data; + fpi_device_get_virtual_env; + fpi_device_identify_complete; + fpi_device_identify_report; + fpi_device_list_complete; + fpi_device_open_complete; + fpi_device_probe_complete; + fpi_device_remove; + fpi_device_report_finger_status; + fpi_device_report_finger_status_changes; + fpi_device_retry_new; + fpi_device_retry_new_msg; + fpi_device_set_nr_enroll_stages; + fpi_device_set_scan_type; + fpi_device_udev_subtype_flags_get_type; + fpi_device_update_temp; + fpi_device_verify_complete; + fpi_device_verify_report; + fpi_do_movement_estimation; + fpi_image_device_activate; + fpi_image_device_activate_complete; + fpi_image_device_close_complete; + fpi_image_device_deactivate; + fpi_image_device_deactivate_complete; + fpi_image_device_image_captured; + fpi_image_device_open_complete; + fpi_image_device_report_finger_status; + fpi_image_device_retry_scan; + fpi_image_device_session_error; + fpi_image_device_set_bz3_threshold; + fpi_image_device_state_get_type; + fpi_image_flags_get_type; + fpi_image_resize; + fpi_match_result_get_type; + fpi_mean_sq_diff_norm; + fpi_print_add_from_image; + fpi_print_add_print; + fpi_print_bz3_match; + fpi_print_fill_from_user_id; + fpi_print_generate_user_id; + fpi_print_set_device_stored; + fpi_print_set_type; + fpi_print_type_get_type; + fpi_ssm_cancel_delayed_state_change; + fpi_ssm_dup_error; + fpi_ssm_free; + fpi_ssm_get_cur_state; + fpi_ssm_get_data; + fpi_ssm_get_error; + fpi_ssm_jump_to_state; fpi_ssm_jump_to_state_delayed; + fpi_ssm_jump_to_state_delayed_1_90; + fpi_ssm_mark_completed; fpi_ssm_mark_completed_delayed; + fpi_ssm_mark_completed_delayed_1_90; + fpi_ssm_mark_failed; + fpi_ssm_new_full; + fpi_ssm_new_full_1_90; + fpi_ssm_next_state; fpi_ssm_next_state_delayed; + fpi_ssm_next_state_delayed_1_90; + fpi_ssm_set_data; + fpi_ssm_start; + fpi_ssm_start_subsm; + fpi_ssm_usb_transfer_cb; + fpi_ssm_usb_transfer_with_weak_pointer_cb; + fpi_std_sq_dev; + fpi_transfer_type_get_type; + fpi_usb_transfer_fill_bulk; + fpi_usb_transfer_fill_bulk_full; + fpi_usb_transfer_fill_control; + fpi_usb_transfer_fill_interrupt; + fpi_usb_transfer_fill_interrupt_full; + fpi_usb_transfer_get_type; + fpi_usb_transfer_new; + fpi_usb_transfer_ref; + fpi_usb_transfer_submit; + fpi_usb_transfer_submit_sync; + fpi_usb_transfer_unref; local: *; }; @@ -15,13 +217,23 @@ global: fpi_device_clear_storage_complete; fpi_device_get_udev_data; fpi_device_update_features; - fpi_spi_*; + fpi_spi_transfer_get_type; + fpi_spi_transfer_new; + fpi_spi_transfer_read; + fpi_spi_transfer_read_full; + fpi_spi_transfer_ref; + fpi_spi_transfer_submit; + fpi_spi_transfer_submit_sync; + fpi_spi_transfer_unref; + fpi_spi_transfer_write; + fpi_spi_transfer_write_full; fpi_ssm_get_device; fpi_ssm_jump_to_state_delayed; fpi_ssm_mark_completed_delayed; fpi_ssm_new_full; fpi_ssm_next_state_delayed; - fpi_ssm_spi_*; + fpi_ssm_spi_transfer_cb; + fpi_ssm_spi_transfer_with_weak_pointer_cb; } LIBFPRINT_TOD_@tod_soversion@.0.0; LIBFPRINT_TOD_@tod_soversion@_1.94 { @@ -30,4 +242,8 @@ global: fpi_device_critical_leave; fpi_device_resume_complete; fpi_device_suspend_complete; + fpi_ssm_silence_debug; + + /* Keep this always in the current development version */ + fpi_*; } LIBFPRINT_TOD_@tod_soversion@_1.92; diff --git a/libfprint/tod/meson.build b/libfprint/tod/meson.build index ba395c16..10c49e4c 100644 --- a/libfprint/tod/meson.build +++ b/libfprint/tod/meson.build @@ -75,6 +75,10 @@ pkgconfig.generate(libfprint_tod, ] ) +tod_local_headers = [ + 'tod-macros.h', +] + tod_headers = [] extra_libfprint_headers = [ 'drivers_api.h', @@ -95,3 +99,7 @@ custom_target('tod_fpi_enums_headers', install_headers(tod_headers, subdir: tod_subpath ) + +install_headers(tod_local_headers, + subdir: tod_subpath / 'tod', +) diff --git a/meson.build b/meson.build index ad105f1f..f7381ca7 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('libfprint', [ 'c', 'cpp' ], - version: '1.94.2+tod1', + version: '1.94.3+tod1', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized', diff --git a/tests/elanspi/capture.ioctl b/tests/elanspi/capture.ioctl index dcd5821e..fc292d36 100644 --- a/tests/elanspi/capture.ioctl +++ b/tests/elanspi/capture.ioctl @@ -24,6 +24,10 @@ TW 8c62 TW 805a TW 04 TW aa07 +TW 8100 +TW 825f +TW 8300 +TW 845f TW 8560 TW 86c0 TW 8780 @@ -38,8 +42,11 @@ TW 9567 TW 9804 TW a120 TW a236 +TW a902 +TW aa03 TW aa5f TW abc0 +TW ac10 TW aeff TW 01 TW 03ff diff --git a/tests/goodixmoc/custom.py b/tests/goodixmoc/custom.py index 2fe6edd9..1fb513a1 100755 --- a/tests/goodixmoc/custom.py +++ b/tests/goodixmoc/custom.py @@ -21,7 +21,7 @@ assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK) assert d.has_feature(FPrint.DeviceFeature.STORAGE) assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST) assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE) -assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR) +assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR) d.open_sync() diff --git a/tests/meson.build b/tests/meson.build index e1eaedc8..48fece68 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -279,7 +279,6 @@ if get_option('tod') ) fp_todv1_enums = gnome.mkenums_simple('fp-todv1-enums', - source_dir: 'tod-drivers', sources: [ 'tod-drivers/base-fp-device.h', 'tod-drivers/base-fp-print.h', @@ -326,6 +325,7 @@ if get_option('tod') 'v1+1.90.3', 'v1+1.90.5', 'v1+1.94.0', + 'v1+1.94.3', ] foreach tod_version: tod_test_versions diff --git a/tests/test-fp-todv1-types.c b/tests/test-fp-todv1-types.c index 830cee75..34582b97 100644 --- a/tests/test-fp-todv1-types.c +++ b/tests/test-fp-todv1-types.c @@ -283,6 +283,7 @@ test_device_public_enums (void) check_type_compatibility (FP_TYPE_DEVICE_ERROR, 1, 94, 0); check_type_compatibility (FP_TYPE_DEVICE_FEATURE, 1, 92, 0); check_type_compatibility (FP_TYPE_DEVICE_FEATURE, 1, 94, 0); + check_type_compatibility (FP_TYPE_DEVICE_FEATURE, 1, 94, 3); check_type_compatibility (FP_TYPE_TEMPERATURE, 1, 94, 0); check_type_compatibility (FPI_TYPE_DEVICE_UDEV_SUBTYPE_FLAGS, 1, 92, 0); } diff --git a/tests/test-fpi-device.c b/tests/test-fpi-device.c index 6e2021c2..a7b2611b 100644 --- a/tests/test-fpi-device.c +++ b/tests/test-fpi-device.c @@ -27,6 +27,7 @@ #include "fpi-compat.h" #include "fpi-log.h" #include "test-device-fake.h" +#include "fp-print-private.h" #ifdef TEST_TOD_DRIVER @@ -146,6 +147,10 @@ tod_check_device_version (FpDevice *device_class, typedef FpDevice FpAutoCloseDevice; +/* gcc 12.0.1 is complaining about dangling pointers in the auto_close* functions */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdangling-pointer" + static FpAutoCloseDevice * auto_close_fake_device_new (void) { @@ -178,6 +183,8 @@ auto_close_fake_device_free (FpAutoCloseDevice *device) } G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpAutoCloseDevice, auto_close_fake_device_free) +#pragma GCC diagnostic pop + typedef FpDeviceClass FpAutoResetClass; static FpAutoResetClass default_fake_dev_class = {0}; @@ -256,6 +263,16 @@ make_fake_print (FpDevice *device, return enrolled_print; } +static FpPrint * +make_fake_nbis_print (FpDevice *device) +{ + FpPrint *enrolled_print = fp_print_new (device); + + fpi_print_set_type (enrolled_print, FPI_PRINT_NBIS); + + return enrolled_print; +} + static FpPrint * make_fake_print_reffed (FpDevice *device, GVariant *print_data) @@ -1193,7 +1210,6 @@ test_driver_enroll_error_no_print (void) out_print = fp_device_enroll_sync (device, fp_print_new (device), NULL, NULL, NULL, &error); - g_test_assert_expected_messages (); g_assert (fake_dev->last_called_function == dev_class->enroll); g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL); g_assert_null (out_print); @@ -1201,6 +1217,111 @@ test_driver_enroll_error_no_print (void) g_clear_error (&error); } +static void +test_driver_enroll_update_nbis (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + g_autoptr(FpAutoCloseDevice) device = NULL; + g_autoptr(FpPrint) template_print = NULL; + FpiDeviceFake *fake_dev = NULL; + FpPrint *out_print = NULL; + + dev_class->features |= FP_DEVICE_FEATURE_UPDATE_PRINT; + device = auto_close_fake_device_new (); + fake_dev = FPI_DEVICE_FAKE (device); + + template_print = make_fake_nbis_print (device); + fake_dev->ret_print = template_print; + + out_print = + fp_device_enroll_sync (device, template_print, NULL, NULL, NULL, &error); + + g_assert (fake_dev->last_called_function == dev_class->enroll); + g_assert (fake_dev->action_data == template_print); + + g_assert_no_error (error); + g_assert (out_print == template_print); +} + +static void +test_driver_enroll_update_nbis_wrong_device (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + g_autoptr(FpAutoCloseDevice) device = NULL; + g_autoptr(FpPrint) template_print = NULL; + FpiDeviceFake *fake_dev = NULL; + FpPrint *out_print = NULL; + + dev_class->features |= FP_DEVICE_FEATURE_UPDATE_PRINT; + + device = auto_close_fake_device_new (); + fake_dev = FPI_DEVICE_FAKE (device); + + template_print = make_fake_nbis_print (device); + template_print->device_id = g_strdup ("wrong_device"); + fake_dev->ret_print = template_print; + + out_print = + fp_device_enroll_sync (device, template_print, NULL, NULL, NULL, &error); + + g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID); + g_assert (out_print == NULL); +} + +static void +test_driver_enroll_update_nbis_wrong_driver (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + g_autoptr(FpAutoCloseDevice) device = NULL; + g_autoptr(FpPrint) template_print = NULL; + FpiDeviceFake *fake_dev = NULL; + FpPrint *out_print = NULL; + + dev_class->features |= FP_DEVICE_FEATURE_UPDATE_PRINT; + + device = auto_close_fake_device_new (); + fake_dev = FPI_DEVICE_FAKE (device); + + template_print = make_fake_nbis_print (device); + template_print->driver = g_strdup ("wrong_driver"); + fake_dev->ret_print = template_print; + + out_print = + fp_device_enroll_sync (device, template_print, NULL, NULL, NULL, &error); + + g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID); + g_assert (out_print == NULL); +} + +static void +test_driver_enroll_update_nbis_missing_feature (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + g_autoptr(FpAutoCloseDevice) device = NULL; + g_autoptr(FpPrint) template_print = NULL; + FpiDeviceFake *fake_dev = NULL; + FpPrint *out_print = NULL; + + device = auto_close_fake_device_new (); + fake_dev = FPI_DEVICE_FAKE (device); + + template_print = make_fake_nbis_print (device); + fake_dev->ret_print = template_print; + + out_print = + fp_device_enroll_sync (device, template_print, NULL, NULL, NULL, &error); + + g_assert (fake_dev->last_called_function == dev_class->open); + g_assert (fake_dev->action_data == NULL); + + g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID); + g_assert (out_print == NULL); +} + typedef struct { gint completed_stages; @@ -3530,6 +3651,13 @@ main (int argc, char *argv[]) g_test_add_func ("/driver/enroll/error", test_driver_enroll_error); g_test_add_func ("/driver/enroll/error/no_print", test_driver_enroll_error_no_print); g_test_add_func ("/driver/enroll/progress", test_driver_enroll_progress); + g_test_add_func ("/driver/enroll/update_nbis", test_driver_enroll_update_nbis); + g_test_add_func ("/driver/enroll/update_nbis_wrong_device", + test_driver_enroll_update_nbis_wrong_device); + g_test_add_func ("/driver/enroll/update_nbis_wrong_driver", + test_driver_enroll_update_nbis_wrong_driver); + g_test_add_func ("/driver/enroll/update_nbis_missing_feature", + test_driver_enroll_update_nbis_missing_feature); g_test_add_func ("/driver/verify", test_driver_verify); g_test_add_func ("/driver/verify/fail", test_driver_verify_fail); g_test_add_func ("/driver/verify/retry", test_driver_verify_retry); diff --git a/tests/tod-drivers/base-fp-device.h b/tests/tod-drivers/base-fp-device.h index 5d3bbc26..ee3d09c4 100644 --- a/tests/tod-drivers/base-fp-device.h +++ b/tests/tod-drivers/base-fp-device.h @@ -86,6 +86,45 @@ typedef enum { FP_DEVICE_ERROR_TODV1_90_4_REMOVED = 0x100, } FpDeviceErrorTODV1_90_4; +typedef enum /*< flags >*/ { + FP_DEVICE_FEATURE_TODV1_92_0_NONE = 0, + FP_DEVICE_FEATURE_TODV1_92_0_CAPTURE = 1 << 0, + FP_DEVICE_FEATURE_TODV1_92_0_IDENTIFY = 1 << 1, + FP_DEVICE_FEATURE_TODV1_92_0_VERIFY = 1 << 2, + FP_DEVICE_FEATURE_TODV1_92_0_STORAGE = 1 << 3, + FP_DEVICE_FEATURE_TODV1_92_0_STORAGE_LIST = 1 << 4, + FP_DEVICE_FEATURE_TODV1_92_0_STORAGE_DELETE = 1 << 5, + FP_DEVICE_FEATURE_TODV1_92_0_STORAGE_CLEAR = 1 << 6, + FP_DEVICE_FEATURE_TODV1_92_0_DUPLICATES_CHECK = 1 << 7, +} FpDeviceFeatureTODV1_92_0; + +typedef enum /*< flags >*/ { + FP_DEVICE_FEATURE_TODV1_94_0_NONE = 0, + FP_DEVICE_FEATURE_TODV1_94_0_CAPTURE = 1 << 0, + FP_DEVICE_FEATURE_TODV1_94_0_IDENTIFY = 1 << 1, + FP_DEVICE_FEATURE_TODV1_94_0_VERIFY = 1 << 2, + FP_DEVICE_FEATURE_TODV1_94_0_STORAGE = 1 << 3, + FP_DEVICE_FEATURE_TODV1_94_0_STORAGE_LIST = 1 << 4, + FP_DEVICE_FEATURE_TODV1_94_0_STORAGE_DELETE = 1 << 5, + FP_DEVICE_FEATURE_TODV1_94_0_STORAGE_CLEAR = 1 << 6, + FP_DEVICE_FEATURE_TODV1_94_0_DUPLICATES_CHECK = 1 << 7, + FP_DEVICE_FEATURE_TODV1_94_0_ALWAYS_ON = 1 << 8, +} FpDeviceFeatureTODV1_94_0; + +typedef enum /*< flags >*/ { + FP_DEVICE_FEATURE_TODV1_94_3_NONE = 0, + FP_DEVICE_FEATURE_TODV1_94_3_CAPTURE = 1 << 0, + FP_DEVICE_FEATURE_TODV1_94_3_IDENTIFY = 1 << 1, + FP_DEVICE_FEATURE_TODV1_94_3_VERIFY = 1 << 2, + FP_DEVICE_FEATURE_TODV1_94_3_STORAGE = 1 << 3, + FP_DEVICE_FEATURE_TODV1_94_3_STORAGE_LIST = 1 << 4, + FP_DEVICE_FEATURE_TODV1_94_3_STORAGE_DELETE = 1 << 5, + FP_DEVICE_FEATURE_TODV1_94_3_STORAGE_CLEAR = 1 << 6, + FP_DEVICE_FEATURE_TODV1_94_3_DUPLICATES_CHECK = 1 << 7, + FP_DEVICE_FEATURE_TODV1_94_3_ALWAYS_ON = 1 << 8, + FP_DEVICE_FEATURE_TODV1_94_3_UPDATE_PRINT = 1 << 9, +} FpDeviceFeatureTODV1_94_3; + typedef enum { FP_DEVICE_ERROR_TODV1_94_0_GENERAL, FP_DEVICE_ERROR_TODV1_94_0_NOT_SUPPORTED, diff --git a/tests/tod-drivers/base-fpi-device.h b/tests/tod-drivers/base-fpi-device.h index 0e847611..222ff088 100644 --- a/tests/tod-drivers/base-fpi-device.h +++ b/tests/tod-drivers/base-fpi-device.h @@ -110,31 +110,6 @@ typedef enum { FPI_DEVICE_ACTION_TODV1_92_0_CLEAR_STORAGE } FpiDeviceActionTODV1_92_0; -typedef enum /*< flags >*/ { - FP_DEVICE_FEATURE_TODV1_92_0_NONE = 0, - FP_DEVICE_FEATURE_TODV1_92_0_CAPTURE = 1 << 0, - FP_DEVICE_FEATURE_TODV1_92_0_IDENTIFY = 1 << 1, - FP_DEVICE_FEATURE_TODV1_92_0_VERIFY = 1 << 2, - FP_DEVICE_FEATURE_TODV1_92_0_STORAGE = 1 << 3, - FP_DEVICE_FEATURE_TODV1_92_0_STORAGE_LIST = 1 << 4, - FP_DEVICE_FEATURE_TODV1_92_0_STORAGE_DELETE = 1 << 5, - FP_DEVICE_FEATURE_TODV1_92_0_STORAGE_CLEAR = 1 << 6, - FP_DEVICE_FEATURE_TODV1_92_0_DUPLICATES_CHECK = 1 << 7, -} FpDeviceFeatureTODV1_92_0; - -typedef enum /*< flags >*/ { - FP_DEVICE_FEATURE_TODV1_94_0_NONE = 0, - FP_DEVICE_FEATURE_TODV1_94_0_CAPTURE = 1 << 0, - FP_DEVICE_FEATURE_TODV1_94_0_IDENTIFY = 1 << 1, - FP_DEVICE_FEATURE_TODV1_94_0_VERIFY = 1 << 2, - FP_DEVICE_FEATURE_TODV1_94_0_STORAGE = 1 << 3, - FP_DEVICE_FEATURE_TODV1_94_0_STORAGE_LIST = 1 << 4, - FP_DEVICE_FEATURE_TODV1_94_0_STORAGE_DELETE = 1 << 5, - FP_DEVICE_FEATURE_TODV1_94_0_STORAGE_CLEAR = 1 << 6, - FP_DEVICE_FEATURE_TODV1_94_0_DUPLICATES_CHECK = 1 << 7, - FP_DEVICE_FEATURE_TODV1_94_0_ALWAYS_ON = 1 << 8, -} FpDeviceFeatureTODV1_94_0; - typedef enum { FPI_DEVICE_UDEV_SUBTYPE_TODV1_92_0_SPIDEV = 1 << 0, FPI_DEVICE_UDEV_SUBTYPE_TODV1_92_0_HIDRAW = 1 << 1, diff --git a/tests/tod-drivers/tod-x86_64-v1+1.94.3/libdevice-fake-tod-ssm-test-v1+1.94.3-x86_64.so b/tests/tod-drivers/tod-x86_64-v1+1.94.3/libdevice-fake-tod-ssm-test-v1+1.94.3-x86_64.so new file mode 100755 index 00000000..b8934d1a Binary files /dev/null and b/tests/tod-drivers/tod-x86_64-v1+1.94.3/libdevice-fake-tod-ssm-test-v1+1.94.3-x86_64.so differ diff --git a/tests/tod-drivers/tod-x86_64-v1+1.94.3/libdevice-fake-tod-test-driver-v1+1.94.3-x86_64.so b/tests/tod-drivers/tod-x86_64-v1+1.94.3/libdevice-fake-tod-test-driver-v1+1.94.3-x86_64.so new file mode 100755 index 00000000..e373a384 Binary files /dev/null and b/tests/tod-drivers/tod-x86_64-v1+1.94.3/libdevice-fake-tod-test-driver-v1+1.94.3-x86_64.so differ diff --git a/tests/virtual-image.py b/tests/virtual-image.py index 7605b583..e4a464eb 100755 --- a/tests/virtual-image.py +++ b/tests/virtual-image.py @@ -136,6 +136,7 @@ class VirtualImage(unittest.TestCase): self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE)) self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY)) self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.UPDATE_PRINT)) self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)) self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE)) self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST)) @@ -144,7 +145,8 @@ class VirtualImage(unittest.TestCase): self.assertEqual(self.dev.get_features(), FPrint.DeviceFeature.CAPTURE | FPrint.DeviceFeature.IDENTIFY | - FPrint.DeviceFeature.VERIFY) + FPrint.DeviceFeature.VERIFY | + FPrint.DeviceFeature.UPDATE_PRINT) def test_capture_prevents_close(self): cancel = Gio.Cancellable() @@ -167,7 +169,7 @@ class VirtualImage(unittest.TestCase): while not self._cancelled: ctx.iteration(True) - def enroll_print(self, image): + def enroll_print(self, image, template=None): self._step = 0 self._enrolled = None @@ -181,14 +183,15 @@ class VirtualImage(unittest.TestCase): self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) self._enrolled = fp - template = FPrint.Print.new(self.dev) - template.props.finger = FPrint.Finger.LEFT_THUMB - template.props.username = "testuser" - template.props.description = "test print" - datetime = GLib.DateTime.new_now_local() - date = GLib.Date() - date.set_dmy(*datetime.get_ymd()[::-1]) - template.props.enroll_date = date + if template is None: + template = FPrint.Print.new(self.dev) + template.props.finger = FPrint.Finger.LEFT_THUMB + template.props.username = "testuser" + template.props.description = "test print" + datetime = GLib.DateTime.new_now_local() + date = GLib.Date() + date.set_dmy(*datetime.get_ymd()[::-1]) + template.props.enroll_date = date self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) self.dev.enroll(template, None, progress_cb, tuple(), done_cb) @@ -264,6 +267,28 @@ class VirtualImage(unittest.TestCase): ctx.iteration(True) assert(not self._verify_match) + # Test fingerprint updates + # Enroll a second print + fp_whorl_tended_arch = self.enroll_print('tented_arch', fp_whorl) + + # Make sure the first print verifies successfully after the update + self._verify_match = None + self._verify_fp = None + self.dev.verify(fp_whorl_tended_arch, callback=verify_cb) + self.send_image('whorl') + while self._verify_match is None: + ctx.iteration(True) + assert(self._verify_match) + + # Make sure the second print verifies successfully after the update + self._verify_match = None + self._verify_fp = None + self.dev.verify(fp_whorl_tended_arch, callback=verify_cb) + self.send_image('tented_arch') + while self._verify_match is None: + ctx.iteration(True) + assert(self._verify_match) + # Test verify error cases self._verify_fp = None self._verify_error = None