From 2d10d864d8bc4b952cf412f6e18e44412dba759a Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 9 Dec 2020 15:46:23 +0100 Subject: [PATCH 001/103] nbis: Disable array-parameter and array-bounds warnings NBIS just does weird things and while the array-parameter warning is easy to fix, the other is not trivial. So disable these warnings so that we can still build using newer GCC versions. --- libfprint/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfprint/meson.build b/libfprint/meson.build index 96cfe9b5..4d1d30cc 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -234,6 +234,8 @@ libnbis = static_library('nbis', '-Wno-error=redundant-decls', '-Wno-redundant-decls', '-Wno-discarded-qualifiers', + '-Wno-array-bounds', + '-Wno-array-parameter', ]), install: false) From ed5339c4f5bbd80ac79b98ef21d8924af61b400d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 14 Dec 2020 18:13:53 +0100 Subject: [PATCH 002/103] vfs5011: Unset the recorded rows list when freeing them Ensure that we unset the rows list when closing the device, so that we won't try to append to invalid rows list new ones again. --- libfprint/drivers/vfs5011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index ffc06803..2d5b0b9f 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -821,7 +821,7 @@ dev_close (FpImageDevice *dev) 0, 0, &error); g_free (self->capture_buffer); - g_slist_free_full (self->rows, g_free); + g_slist_free_full (g_steal_pointer (&self->rows), g_free); fpi_image_device_close_complete (dev, error); } From 3560a0f1e7c8aab6082dc3c20a0e0e33eb814105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 14 Dec 2020 18:16:43 +0100 Subject: [PATCH 003/103] vfs5011: Remove the stray ; --- libfprint/drivers/vfs5011.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index 2d5b0b9f..c1e684c1 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -815,8 +815,6 @@ dev_close (FpImageDevice *dev) GError *error = NULL; FpDeviceVfs5011 *self = FPI_DEVICE_VFS5011 (dev); - ; - g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); From 7e2b89791e36d63dd12e3e5969edc054d48519a2 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 4 Dec 2020 16:26:22 +0100 Subject: [PATCH 004/103] tests: Fix typo in instructions --- tests/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/README.md b/tests/README.md index 8a70ba12..9dc575ed 100644 --- a/tests/README.md +++ b/tests/README.md @@ -27,7 +27,7 @@ A new 'capture' test is created by means of `capture.py` script: - `export LD_PRELOAD=/libfprint/libfprint-2.so` - `export GI_TYPELIB_PATH=/libfprint` - Also, sometimes the driver must be adopted to the emulated environment + Also, sometimes the driver must be adapted to the emulated environment (mainly if it uses random numbers, see `synaptics.c` for an example). Set the following environment variable to enable this adaptation: - `export FP_DEVICE_EMULATION=1` From b1b20f8ab962fb75df8caa4a0a5eda5ce982b5c1 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 4 Dec 2020 16:26:34 +0100 Subject: [PATCH 005/103] tests: Mention permissions in test docs --- tests/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/README.md b/tests/README.md index 9dc575ed..9eac6a4b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -41,6 +41,11 @@ A new 'capture' test is created by means of `capture.py` script: The following USB device is used in the example above: `/dev/bus/usb/001/005`. + For the following commands, it is assumed that the user that's + running the commands has full access to the device node, whether + by running the commands as `root`, or changing the permissions for + that device node. + 4. Record information about this device: `umockdev-record /dev/bus/usb/001/005 > DRIVER/device` From d6ca8ff2b0fff62ebc0b5507f3633f1fe7db75d5 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 17 Dec 2020 13:58:38 +0100 Subject: [PATCH 006/103] tests: Fix typo in comment --- tests/test-fp-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-fp-context.c b/tests/test-fp-context.c index 1dd1f727..156e6d47 100644 --- a/tests/test-fp-context.c +++ b/tests/test-fp-context.c @@ -287,7 +287,7 @@ test_context_remove_device_opening (void) g_assert_true (removed); g_assert_null (tctx->user_data); - /* Running the mainloop now will cause the open to *succeed* dispite removal! */ + /* Running the mainloop now will cause the open to *succeed* despite removal! */ while (!open_done) g_main_context_iteration (NULL, TRUE); From ee928db5b2cdb82f967aff156a8fc01686e6bc58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torstein=20Huseb=C3=B8?= Date: Tue, 18 Aug 2020 17:36:16 +0200 Subject: [PATCH 007/103] treewide: Correct typos --- libfprint/drivers/goodixmoc/goodix.c | 2 +- libfprint/drivers/synaptics/synaptics.c | 2 +- libfprint/fp-device.c | 2 +- libfprint/fpi-device.c | 2 +- libfprint/fpi-ssm.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index bb0368b9..563b379a 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -742,7 +742,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self, fpi_ssm_mark_failed (self->task_ssm, error); return; } - /* if reach max timeout(5sec) finger not up, swtich to finger up again */ + /* if reach max timeout(5sec) finger not up, switch to finger up again */ if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT) { fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_WAIT_FINGER_UP); diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index 934a271e..f4100722 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -121,7 +121,7 @@ cmd_receive_cb (FpiUsbTransfer *transfer, { if (resp.response_id == BMKT_RSP_CANCEL_OP_OK) { - fp_dbg ("Received cancellation success resonse"); + fp_dbg ("Received cancellation success response"); fpi_ssm_mark_failed (transfer->ssm, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index 6db665fa..f752a487 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -792,7 +792,7 @@ fp_device_close_finish (FpDevice *device, * 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 successed. + * enrollment succeeded. */ void fp_device_enroll (FpDevice *device, diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index 0968c0c1..de511920 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -760,7 +760,7 @@ fp_device_task_return_in_idle_cb (gpointer user_data) g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_REMOVED)); /* NOTE: The removed signal will be emitted from the GTask - * notify::completed if that is neccessary. */ + * notify::completed if that is necessary. */ return G_SOURCE_REMOVE; } diff --git a/libfprint/fpi-ssm.c b/libfprint/fpi-ssm.c index 3cc39a7f..25728d18 100644 --- a/libfprint/fpi-ssm.c +++ b/libfprint/fpi-ssm.c @@ -74,7 +74,7 @@ * upon success (or fails). * * Your completion callback should examine the return value of - * fpi_ssm_get_error() in ordater to determine whether the #FpiSsm completed or + * fpi_ssm_get_error() in order to determine whether the #FpiSsm completed or * failed. An error code of zero indicates successful completion. */ From e6712fbcca7b087c4d90f47a86ab94449b5814ea Mon Sep 17 00:00:00 2001 From: fengqiangguo Date: Wed, 16 Dec 2020 20:35:53 +0800 Subject: [PATCH 008/103] goodixmoc: add two new Goodix PID support. Add two new Goodix PID 0x63AC and 0x639C, to support two more Goodix fingerprint devices on Linux platform. --- libfprint/drivers/goodixmoc/goodix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 563b379a..e9f91fef 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -1424,6 +1424,8 @@ static const FpIdEntry id_table[] = { { .vid = 0x27c6, .pid = 0x5840, }, { .vid = 0x27c6, .pid = 0x6496, }, { .vid = 0x27c6, .pid = 0x60A2, }, + { .vid = 0x27c6, .pid = 0x63AC, }, + { .vid = 0x27c6, .pid = 0x639C, }, { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */ }; From 2ee0d1678410b675efd6c32934ab44194e7be376 Mon Sep 17 00:00:00 2001 From: fengqiangguo Date: Thu, 10 Dec 2020 23:12:38 +0800 Subject: [PATCH 009/103] goodixmoc: fetch max_stored_prints from device During updating configuration, device will send back the max_stored_prints back. The number of max_stored_prints is different among different devices. --- libfprint/drivers/goodixmoc/goodix.c | 12 +++++++++++- libfprint/drivers/goodixmoc/goodix_proto.c | 8 +++++++- libfprint/drivers/goodixmoc/goodix_proto.h | 8 +++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index e9f91fef..7c66ba32 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -53,6 +53,7 @@ struct _FpiDeviceGoodixMoc pgxfp_sensor_cfg_t sensorcfg; gint enroll_stage; gint max_enroll_stage; + gint max_stored_prints; GCancellable *cancellable; GPtrArray *list_result; guint8 template_id[TEMPLATE_ID_SIZE]; @@ -560,6 +561,13 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self, resp->result)); return; } + if (resp->finger_list_resp.finger_num >= self->max_stored_prints) + { + fpi_ssm_mark_failed (self->task_ssm, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL)); + return; + } + fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE); } @@ -975,7 +983,7 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self, fpi_ssm_mark_failed (self->task_ssm, error); return; } - + self->max_stored_prints = resp->finger_config.max_stored_prints; fpi_ssm_next_state (self->task_ssm); } @@ -1259,6 +1267,8 @@ gx_fp_init (FpDevice *device) GError *error = NULL; int ret = 0; + self->max_stored_prints = FP_MAX_FINGERNUM; + self->cancellable = g_cancellable_new (); self->sensorcfg = g_new0 (gxfp_sensor_cfg_t, 1); diff --git a/libfprint/drivers/goodixmoc/goodix_proto.c b/libfprint/drivers/goodixmoc/goodix_proto.c index ece8123d..e30d23df 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.c +++ b/libfprint/drivers/goodixmoc/goodix_proto.c @@ -294,6 +294,12 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c break; case MOC_CMD0_UPDATE_CONFIG: + { + presp->finger_config.status = buffer[0]; + presp->finger_config.max_stored_prints = buffer[2]; + } + break; + case MOC_CMD0_COMMITENROLLMENT: case MOC_CMD0_DELETETEMPLATE: break; @@ -411,7 +417,7 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig) memset (pconfig, 0, sizeof (*pconfig)); //NOTICE: Do not change any value! - memcpy (&pconfig->config, sensor_config, 26); + memcpy (&pconfig->config, sensor_config, G_N_ELEMENTS (sensor_config)); pconfig->reserved[0] = 1; gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, (uint8_t *) &crc32_calc); diff --git a/libfprint/drivers/goodixmoc/goodix_proto.h b/libfprint/drivers/goodixmoc/goodix_proto.h index 1611a601..53eea046 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.h +++ b/libfprint/drivers/goodixmoc/goodix_proto.h @@ -25,7 +25,7 @@ #define PACKAGE_CRC_SIZE (4) #define PACKAGE_HEADER_SIZE (8) -#define FP_MAX_FINGERNUM (10) +#define FP_MAX_FINGERNUM (20) #define TEMPLATE_ID_SIZE (32) @@ -167,6 +167,11 @@ typedef struct _fp_finger_status uint8_t status; } fp_finger_status_t, *pfp_finger_status_t; +typedef struct _fp_finger_config +{ + uint8_t status; + uint8_t max_stored_prints; +} fp_finger_config_t, *pfp_finger_config_t; typedef struct _fp_cmd_response { @@ -183,6 +188,7 @@ typedef struct _fp_cmd_response gxfp_enum_fingerlist_t finger_list_resp; gxfp_version_info_t version_info; fp_finger_status_t finger_status; + fp_finger_config_t finger_config; }; } gxfp_cmd_response_t, *pgxfp_cmd_response_t; From 3d5db6a391f9f168c6b6b2c721c5443e59881268 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 9 Dec 2020 15:04:08 +0100 Subject: [PATCH 010/103] synaptics: Improve identify handler and return a new print It is easier (and more correct) to create a new print from the reported data and match that against the prints in the gallery. We continue to return NULL during verify as we cannot provide any additional information in that case. --- libfprint/drivers/synaptics/synaptics.c | 91 +++++++++++++------------ 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index f4100722..61abe84a 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -451,6 +451,37 @@ parse_print_data (GVariant *data, return TRUE; } +static FpPrint * +create_print (FpiDeviceSynaptics *self, + guint8 *user_id, + guint8 finger_id) +{ + FpPrint *print; + g_autofree gchar *user_id_safe; + GVariant *data = NULL; + GVariant *uid = NULL; + + user_id_safe = g_strndup ((char *) user_id, BMKT_MAX_USER_ID_LEN); + + print = fp_print_new (FP_DEVICE (self)); + uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + user_id_safe, + strlen (user_id_safe), + 1); + data = g_variant_new ("(y@ay)", + finger_id, + uid); + + fpi_print_set_type (print, FPI_PRINT_RAW); + fpi_print_set_device_stored (print, TRUE); + g_object_set (print, "fpi-data", data, NULL); + g_object_set (print, "description", user_id_safe, NULL); + + fpi_print_fill_from_user_id (print, user_id_safe); + + return print; +} + static void list_msg_cb (FpiDeviceSynaptics *self, bmkt_response_t *resp, @@ -503,10 +534,7 @@ list_msg_cb (FpiDeviceSynaptics *self, for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++) { - GVariant *data = NULL; - GVariant *uid = NULL; FpPrint *print; - gchar *userid; if (get_enroll_templates_resp->templates[n].user_id_len == 0) continue; @@ -519,23 +547,9 @@ list_msg_cb (FpiDeviceSynaptics *self, get_enroll_templates_resp->templates[n].user_id, get_enroll_templates_resp->templates[n].finger_id); - userid = (gchar *) get_enroll_templates_resp->templates[n].user_id; - - print = fp_print_new (FP_DEVICE (self)); - uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - get_enroll_templates_resp->templates[n].user_id, - get_enroll_templates_resp->templates[n].user_id_len, - 1); - data = g_variant_new ("(y@ay)", - get_enroll_templates_resp->templates[n].finger_id, - uid); - - fpi_print_set_type (print, FPI_PRINT_RAW); - fpi_print_set_device_stored (print, TRUE); - g_object_set (print, "fpi-data", data, NULL); - g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL); - - fpi_print_fill_from_user_id (print, userid); + print = create_print (self, + get_enroll_templates_resp->templates[n].user_id, + get_enroll_templates_resp->templates[n].finger_id); g_ptr_array_add (self->list_result, g_object_ref_sink (print)); } @@ -760,37 +774,28 @@ identify_msg_cb (FpiDeviceSynaptics *self, FpPrint *print = NULL; GPtrArray *prints = NULL; g_autoptr(GVariant) data = NULL; - guint8 finger; - const guint8 *user_id; - gsize user_id_len = 0; - gint cnt = 0; - gboolean find = FALSE; + gboolean found = FALSE; + guint index; + + print = create_print (self, + resp->response.id_resp.user_id, + resp->response.id_resp.finger_id); fpi_device_get_identify_data (device, &prints); - for (cnt = 0; cnt < prints->len; cnt++) + found = g_ptr_array_find_with_equal_func (prints, + print, + (GEqualFunc) fp_print_equal, + &index); + + if (found) { - print = g_ptr_array_index (prints, cnt); - g_object_get (print, "fpi-data", &data, NULL); - g_debug ("data is %p", data); - parse_print_data (data, &finger, &user_id, &user_id_len); - if (user_id) - { - if (memcmp (resp->response.id_resp.user_id, user_id, user_id_len) == 0) - { - find = TRUE; - break; - } - } - } - if(find) - { - fpi_device_identify_report (device, print, print, NULL); + fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL); fpi_device_identify_complete (device, NULL); } else { - fpi_device_identify_report (device, NULL, NULL, NULL); + fpi_device_identify_report (device, NULL, print, NULL); identify_complete_after_finger_removal (self); } } From 35d2d78e672934acc27d19d2bfa23a773b944b3e Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 15 Dec 2020 13:16:19 +0100 Subject: [PATCH 011/103] synaptics: Delay verify operation completion until finger remoal We used to return early in the case where the print matched in order to report the result more quickly. However, with the early reporting mechanism and the fprintd side implementation of it, this is not necessary anymore. As such, only stop the "verify" and "identify" operations when the finger is removed (or the operation is cancelled, which is actually what will happen currently). --- libfprint/drivers/synaptics/synaptics.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index 61abe84a..27021517 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -663,7 +663,7 @@ verify_msg_cb (FpiDeviceSynaptics *self, fp_info ("Verify was successful! for user: %s finger: %d score: %f", verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result); fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, NULL); - fpi_device_verify_complete (device, NULL); + verify_complete_after_finger_removal (self); break; } } @@ -789,15 +789,11 @@ identify_msg_cb (FpiDeviceSynaptics *self, &index); if (found) - { - fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL); - fpi_device_identify_complete (device, NULL); - } + fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL); else - { - fpi_device_identify_report (device, NULL, print, NULL); - identify_complete_after_finger_removal (self); - } + fpi_device_identify_report (device, NULL, print, NULL); + + identify_complete_after_finger_removal (self); } } } From f852d972a5c9948b52589e30bed3f9e30dc29bf9 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 14 Dec 2020 20:34:56 +0100 Subject: [PATCH 012/103] goodix: Add missing return to fp_verify_capture_cb Found by coverity. While quite bad in theory, proper safeguards are in place, so it will only result in a g_return_val_if_fail to be hit rather than causing more severe side effects. --- libfprint/drivers/goodixmoc/goodix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 7c66ba32..d22c44f8 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -342,6 +342,7 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self, { fpi_ssm_mark_failed (self->task_ssm, fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER)); + return; } fpi_ssm_next_state (self->task_ssm); } From 943c64d96f8679b74e6fab8a5b1542b2ec34fae4 Mon Sep 17 00:00:00 2001 From: Vincent Huang Date: Tue, 5 Jan 2021 15:25:46 +0800 Subject: [PATCH 013/103] synaptics: modify the command to only identify the provided print list --- libfprint/drivers/synaptics/synaptics.c | 105 ++++++++++++++++++++---- libfprint/drivers/synaptics/synaptics.h | 1 + 2 files changed, 90 insertions(+), 16 deletions(-) diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index 27021517..be5582e5 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -27,6 +27,9 @@ G_DEFINE_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE) +static void init_identify_msg (FpDevice *device); +static void compose_and_send_identify_msg (FpDevice *device); + static const FpIdEntry id_table[] = { { .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE9, }, @@ -739,6 +742,12 @@ identify_msg_cb (FpiDeviceSynaptics *self, fp_info ("Place Finger on the Sensor!"); break; + case BMKT_RSP_SEND_NEXT_USER_ID: + { + compose_and_send_identify_msg (device); + break; + } + case BMKT_RSP_ID_FAIL: if (resp->result == BMKT_SENSOR_STIMULUS_ERROR) { @@ -800,6 +809,21 @@ identify_msg_cb (FpiDeviceSynaptics *self, static void identify (FpDevice *device) +{ + init_identify_msg (device); + compose_and_send_identify_msg (device); +} + +static void +init_identify_msg (FpDevice *device) +{ + FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); + + self->id_idx = 0; +} + +static void +compose_and_send_identify_msg (FpDevice *device) { FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpPrint *print = NULL; @@ -809,28 +833,77 @@ identify (FpDevice *device) guint8 finger; const guint8 *user_id; gsize user_id_len = 0; - gint cnt = 0; + g_autofree guint8 *payload = NULL; + guint8 payload_len = 0; + guint8 payloadOffset = 0; fpi_device_get_identify_data (device, &prints); - - for (cnt = 0; cnt < prints->len; cnt++) + if (prints->len > UINT8_MAX) { - print = g_ptr_array_index (prints, cnt); - g_object_get (print, "fpi-data", &data, NULL); - g_debug ("data is %p", data); - if (!parse_print_data (data, &finger, &user_id, &user_id_len)) - { - fpi_device_identify_complete (device, - fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); - return; - } + fpi_device_identify_complete (device, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; } - G_DEBUG_HERE (); + if(self->id_idx >= prints->len) + { + fp_warn ("Device asked for more prints than we are providing."); + fpi_device_identify_complete (device, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Unexpected index")); + return; + } + print = g_ptr_array_index (prints, self->id_idx); + g_object_get (print, "fpi-data", &data, NULL); + g_debug ("data is %p", data); + if (!parse_print_data (data, &finger, &user_id, &user_id_len)) + { + fpi_device_identify_complete (device, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + if(self->id_idx == 0) + { + /* + * Construct payload. + * 1st byte is total number of IDs in list. + * 2nd byte is number of IDs in list. + * 1 byte for each ID length, maximum id length is 100. + * user_id_len bytes of each ID + */ + payload_len = 2 + 1 + user_id_len; + payload = g_malloc0 (payload_len); + payload[payloadOffset] = prints->len; + payloadOffset += 1; + payload[payloadOffset] = 1; /* send one id per message */ + payloadOffset += 1; + payload[payloadOffset] = user_id_len; + payloadOffset += 1; + memcpy (&payload[payloadOffset], user_id, user_id_len); + payloadOffset += user_id_len; - synaptics_sensor_cmd (self, 0, BMKT_CMD_ID_USER, NULL, 0, identify_msg_cb); + G_DEBUG_HERE (); + + synaptics_sensor_cmd (self, 0, BMKT_CMD_ID_USER_IN_ORDER, payload, payloadOffset, identify_msg_cb); + } + else + { + /* + * 1st byte is the number of IDs + * 1 byte for each ID length + * id_length bytes for each ID + */ + payload_len = 1 + 1 + user_id_len; + payload = g_malloc0 (payload_len); + payload[payloadOffset] = 1; /* send one id per message */ + payloadOffset += 1; + payload[payloadOffset] = user_id_len; + payloadOffset += 1; + memcpy (&payload[payloadOffset], user_id, user_id_len); + payloadOffset += user_id_len; + synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_ID_NEXT_USER, payload, payloadOffset, NULL); + } + self->id_idx++; } - - static void enroll_msg_cb (FpiDeviceSynaptics *self, bmkt_response_t *resp, diff --git a/libfprint/drivers/synaptics/synaptics.h b/libfprint/drivers/synaptics/synaptics.h index ac50171b..deb3a224 100644 --- a/libfprint/drivers/synaptics/synaptics.h +++ b/libfprint/drivers/synaptics/synaptics.h @@ -110,6 +110,7 @@ struct _FpiDeviceSynaptics FpiSsm *cmd_ssm; FpiUsbTransfer *cmd_pending_transfer; gboolean cmd_complete_on_removal; + guint8 id_idx; bmkt_sensor_version_t mis_version; From 8254b9e99e4ca1b16e0d02ea337e966f58cbf72c Mon Sep 17 00:00:00 2001 From: boger Date: Mon, 4 Jan 2021 15:37:52 +0800 Subject: [PATCH 014/103] goodixmoc: support finger status report there is no specific API for report finger status, finger needed status is set when captrue sample cmd send, once cmd receive correct, finger is pressing on sensor. --- libfprint/drivers/goodixmoc/goodix.c | 17 +++++++++++++++-- tests/goodixmoc/custom.py | 5 +++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index d22c44f8..af64d814 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -331,7 +331,9 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self, fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL)); return; } - + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_PRESENT, + FP_FINGER_STATUS_NONE); if (resp->capture_data_resp.img_quality == 0) { fpi_ssm_mark_failed (self->task_ssm, @@ -435,6 +437,9 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device) switch (fpi_ssm_get_cur_state (ssm)) { case FP_VERIFY_CAPTURE: + fpi_device_report_finger_status_changes (device, + FP_FINGER_STATUS_NEEDED, + FP_FINGER_STATUS_NONE); goodix_sensor_cmd (self, MOC_CMD0_CAPTURE_DATA, MOC_CMD1_DEFAULT, true, (const guint8 *) ¶m, @@ -629,7 +634,9 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self, fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE); return; } - + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_PRESENT, + FP_FINGER_STATUS_NONE); if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) || (resp->capture_data_resp.img_coverage < self->sensorcfg->config[5])) { @@ -764,6 +771,9 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self, "Switch finger mode failed")); return; } + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_NONE, + FP_FINGER_STATUS_PRESENT); if (self->enroll_stage < self->max_enroll_stage) { fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE); @@ -826,6 +836,9 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device) break; case FP_ENROLL_CAPTURE: + fpi_device_report_finger_status_changes (device, + FP_FINGER_STATUS_NEEDED, + FP_FINGER_STATUS_NONE); goodix_sensor_cmd (self, MOC_CMD0_CAPTURE_DATA, MOC_CMD1_DEFAULT, true, (const guint8 *) &dummy, diff --git a/tests/goodixmoc/custom.py b/tests/goodixmoc/custom.py index 57faf6c5..17f35622 100755 --- a/tests/goodixmoc/custom.py +++ b/tests/goodixmoc/custom.py @@ -20,6 +20,7 @@ d.open_sync() template = FPrint.Print.new(d) def enroll_progress(*args): + assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED print('enroll progress: ' + str(args)) def identify_done(dev, res): @@ -31,7 +32,9 @@ def identify_done(dev, res): # List, enroll, list, verify, identify, delete print("enrolling") +assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE p = d.enroll_sync(template, None, enroll_progress, None) +assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE print("enroll done") print("listing") @@ -40,7 +43,9 @@ print("listing done") assert len(stored) == 1 assert stored[0].equal(p) print("verifying") +assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE verify_res, verify_print = d.verify_sync(p) +assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE print("verify done") del p assert verify_res == True From a6c2509ca8c3aacefac8d00232e260f53eeed9f0 Mon Sep 17 00:00:00 2001 From: Aris Lin Date: Fri, 8 Jan 2021 14:48:22 +0800 Subject: [PATCH 015/103] synaptics: check if current firmware supports during device probe Fixes: #239 and #351 --- libfprint/drivers/synaptics/synaptics.c | 73 +++++++++++++------------ tests/synaptics/custom.ioctl | 72 ++++++++++++------------ 2 files changed, 76 insertions(+), 69 deletions(-) diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index be5582e5..b4711faf 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -1133,6 +1133,44 @@ delete_print (FpDevice *device) synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb); } +static void +prob_msg_cb (FpiDeviceSynaptics *self, + bmkt_response_t *resp, + GError *error) +{ + GUsbDevice *usb_dev = NULL; + g_autofree gchar *serial = NULL; + + usb_dev = fpi_device_get_usb_device (FP_DEVICE (self)); + + if (error) + { + g_usb_device_close (usb_dev, NULL); + fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version")); + return; + } + + if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + serial = g_strdup ("emulated-device"); + else + serial = g_usb_device_get_string_descriptor (usb_dev, + g_usb_device_get_serial_number_index (usb_dev), + &error); + + if (resp->result == BMKT_SUCCESS) + { + g_usb_device_close (usb_dev, NULL); + fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, error); + } + else + { + g_warning ("Probe fingerprint sensor failed with %d!", resp->result); + g_usb_device_close (usb_dev, NULL); + fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + } +} + static void dev_probe (FpDevice *device) { @@ -1233,40 +1271,7 @@ dev_probe (FpDevice *device) fp_dbg ("Target: %d", self->mis_version.target); fp_dbg ("Product: %d", self->mis_version.product); - - /* We need at least firmware version 10.1, and for 10.1 build 2989158 */ - if (self->mis_version.version_major < 10 || - self->mis_version.version_minor < 1 || - (self->mis_version.version_major == 10 && - self->mis_version.version_minor == 1 && - self->mis_version.build_num < 2989158)) - { - fp_warn ("Firmware version %d.%d with build number %d is unsupported", - self->mis_version.version_major, - self->mis_version.version_minor, - self->mis_version.build_num); - - error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, - "Unsupported firmware version " - "(%d.%d with build number %d)", - self->mis_version.version_major, - self->mis_version.version_minor, - self->mis_version.build_num); - goto err_close; - } - - /* This is the same as the serial_number from above, hex encoded and somewhat reordered */ - /* Should we add in more, e.g. the chip revision? */ - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) - serial = g_strdup ("emulated-device"); - else - serial = g_usb_device_get_string_descriptor (usb_dev, - g_usb_device_get_serial_number_index (usb_dev), - &error); - - g_usb_device_close (usb_dev, NULL); - - fpi_device_probe_complete (device, serial, NULL, error); + synaptics_sensor_cmd (self, 0, BMKT_CMD_FPS_INIT, NULL, 0, prob_msg_cb); return; diff --git a/tests/synaptics/custom.ioctl b/tests/synaptics/custom.ioctl index 370a8e07..e2ea71f1 100644 --- a/tests/synaptics/custom.ioctl +++ b/tests/synaptics/custom.ioctl @@ -4,14 +4,16 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 01 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 40 38 0 00009C37FE5C669C2D000A01014101C10000D11BB7134A090FA1000000000100000000000003 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE011100 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE01130100 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE025400 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE021100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02130100 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE035400 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 @@ -20,13 +22,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255010C + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355010C USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 @@ -35,19 +37,19 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550119 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550119 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 @@ -56,13 +58,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 @@ -71,13 +73,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550132 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550132 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 @@ -86,13 +88,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 @@ -101,13 +103,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 @@ -116,13 +118,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255014B + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355014B USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 @@ -131,7 +133,7 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 @@ -140,13 +142,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550157 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550157 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 @@ -155,21 +157,21 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550164 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550164 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE02591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE03591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037100 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE03752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037200 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE037600 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE04651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046600 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE04752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047200 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE047600 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE05651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056600 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046000 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056000 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101 @@ -178,9 +180,9 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE04651E4650312D30303030303030302D302 USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100 USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0468214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE05811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE05831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE06A100 - USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE06A200 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0568214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE06811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE06831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE07A100 + USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE07A200 From 7c2a67a9544dd5b7bfa134ad7add566590f9c913 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 13 Jan 2021 13:18:58 +0100 Subject: [PATCH 016/103] Release 1.90.7 --- NEWS | 10 ++++++++++ meson.build | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 335986ed..c7a9c70b 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. +2020-12-01: v1.90.7 release + +Highlights: + * vfs5011: Fix possible use-after-free + * goodixmoc: Add two new PIDs (0x63AC, 0x639C) + * goodixmoc: Support finger status API + * synaptics: Only identify within provided prints + * synaptics: Reject devices with old firmware during probe (#239) + + 2020-12-01: v1.90.6 release This release is primarily a bugfix release for some older issues. diff --git a/meson.build b/meson.build index a2b849b1..139c571c 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('libfprint', [ 'c', 'cpp' ], - version: '1.90.6', + version: '1.90.7', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized', From 6d4b498dae482a3373ff74ffbf90eb1a0170e048 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 13 Jan 2021 14:45:07 +0100 Subject: [PATCH 017/103] tests: Mark umockdev-test.py executable This makes it easier to execute it for out-of-tree tests. --- tests/umockdev-test.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tests/umockdev-test.py diff --git a/tests/umockdev-test.py b/tests/umockdev-test.py old mode 100644 new mode 100755 From 17a8bacfaffe70f6358ee89fac2e9ee5b73bfdeb Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 18 Jan 2021 14:37:53 +0100 Subject: [PATCH 018/103] usb-transfer: Remove incorrect statement from documentation The string was still written without having the _full function in mind. --- libfprint/fpi-usb-transfer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfprint/fpi-usb-transfer.c b/libfprint/fpi-usb-transfer.c index fe491685..784aa59d 100644 --- a/libfprint/fpi-usb-transfer.c +++ b/libfprint/fpi-usb-transfer.c @@ -187,7 +187,7 @@ fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer, * fpi_usb_transfer_fill_bulk_full: * @transfer: The #FpiUsbTransfer * @endpoint: The endpoint to send the transfer to - * @buffer: The data to send. A buffer will be created and managed for you if you pass NULL. + * @buffer: The data to send. * @length: The size of @buffer * @free_func: (destroy buffer): Destroy notify for @buffer * @@ -275,7 +275,7 @@ fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer, * fpi_usb_transfer_fill_interrupt_full: * @transfer: The #FpiUsbTransfer * @endpoint: The endpoint to send the transfer to - * @buffer: The data to send. A buffer will be created and managed for you if you pass NULL. + * @buffer: The data to send. * @length: The size of @buffer * @free_func: (destroy buffer): Destroy notify for @buffer * From 349fbeb834c7b938e91e90d7329e2b502ea47124 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 18 Jan 2021 16:25:25 +0100 Subject: [PATCH 019/103] drivers: Disable reindent and disable uncrustify for large headers There are static data and take a long time to process. Also, the VFS301 fragments were really badly indented, fix that. --- libfprint/drivers/aes1660.h | 2 + libfprint/drivers/aes2660.h | 2 + libfprint/drivers/upektc.h | 2 + libfprint/drivers/vfs301_proto_fragments.h | 384 +++++++++++---------- libfprint/drivers/vfs5011_proto.h | 2 + 5 files changed, 201 insertions(+), 191 deletions(-) diff --git a/libfprint/drivers/aes1660.h b/libfprint/drivers/aes1660.h index 18e4e0c9..452582d1 100644 --- a/libfprint/drivers/aes1660.h +++ b/libfprint/drivers/aes1660.h @@ -22,6 +22,8 @@ #define AES1660_FRAME_SIZE 0x244 +/* *INDENT-OFF* */ + /* First init sequence, 0x07 cmd returns following before INIT1: * { 0x07, 0x05, 0x00, 0x8f, 0x16, 0x25, 0x01, 0x00 } */ diff --git a/libfprint/drivers/aes2660.h b/libfprint/drivers/aes2660.h index 5427c80a..485b5809 100644 --- a/libfprint/drivers/aes2660.h +++ b/libfprint/drivers/aes2660.h @@ -21,6 +21,8 @@ #define AES2660_FRAME_SIZE 0x354 +/* *INDENT-OFF* */ + /* First init sequence, 0x07 cmd returns following before INIT1: * { 0x07, 0x05, 0x00, 0x91, 0x26, 0x21, 0x00, 0x00 } */ diff --git a/libfprint/drivers/upektc.h b/libfprint/drivers/upektc.h index a1f9a231..58c4a0cc 100644 --- a/libfprint/drivers/upektc.h +++ b/libfprint/drivers/upektc.h @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* *INDENT-OFF* */ + #pragma once #define UPEKTC_CMD_LEN 0x40 diff --git a/libfprint/drivers/vfs301_proto_fragments.h b/libfprint/drivers/vfs301_proto_fragments.h index 6decbc79..9691bc8f 100644 --- a/libfprint/drivers/vfs301_proto_fragments.h +++ b/libfprint/drivers/vfs301_proto_fragments.h @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* *INDENT-OFF* */ + /* There are many similar blocks in the data below, also the data are * self-similar (looks like some config blocks? pokes like in vfs101?) */ @@ -1621,56 +1623,56 @@ static const unsigned char vfs301_24[] = { /* 119 B */ #define vfs301_02D0_ALIGNED_BLOB \ PACKET ("0200", "8005", \ "FF830720" "5F820720" "FF830720" \ - "5F820720" "FF830720" "5F820720" "FF830720" \ - "5F820720" "FF830720" "5F820720" "FF8B0720" \ - "608A0720" "FF930720" "61920720" "FF9B0720" \ - "629A0720" "FFA30720" "63A20720" "FFAB0720" \ - "64AA0720" "FFB30720" "65B20720" "FFBB0720" \ - "66BA0720" "FFC30720" "67C20720" "FFCB0720" \ - "68CA0720" "FFD30720" "69D20720" "FFDB0720" \ - "6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \ - "6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \ - "6EFA0720" "FF850720" "6F840720" "FF8D0720" \ - "708C0720" "FF950720" "71940720" "FF9D0720" \ - "729C0720" "FFA50720" "73A40720" "FFAD0720" \ - "74AC0720" "FFB50720" "75B40720" "FFBD0720" \ - "76BC0720" "FFC50720" "77C40720" "FFCD0720" \ - "78CC0720" "FFD50720" "79D40720" "FFDD0720" \ - "7ADC0720" "FFE50720" "7BE40720" "FFED0720" \ - "7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \ - "7EFC0720" "FF870720" "7F860720" "FF8F0720" \ - "808E0720" "FF970720" "81960720" "FF9F0720" \ - "829E0720" "FFA70720" "83A60720" "FFAF0720" \ - "84AE0720" "FFB70720" "85B60720" "FFBF0720" \ - "86BE0720" "FFC70720" "87C60720" "FFCF0720" \ - "88CE0720" "FFD70720" "89D60720" "FFDF0720" \ - "8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \ - "8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \ - "8EFE0720" \ - "FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \ - "FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \ - "FFDF0720" "8ADE0720" "FFD70720" "89D60720" \ - "FFCF0720" "88CE0720" "FFC70720" "87C60720" \ - "FFBF0720" "86BE0720" "FFB70720" "85B60720" \ - "FFAF0720" "84AE0720" "FFA70720" "83A60720" \ - "FF9F0720" "829E0720" "FF970720" "81960720" \ - "FF8F0720" "808E0720" "FF870720" "7F860720" \ - "FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \ - "FFED0720" "7CEC0720" "FFE50720" "7BE40720" \ - "FFDD0720" "7ADC0720" "FFD50720" "79D40720" \ - "FFCD0720" "78CC0720" "FFC50720" "77C40720" \ - "FFBD0720" "76BC0720" "FFB50720" "75B40720" \ - "FFAD0720" "74AC0720" "FFA50720" "73A40720" \ - "FF9D0720" "729C0720" "FF950720" "71940720" \ - "FF8D0720" "708C0720" "FF850720" "6F840720" \ - "FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \ - "FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \ - "FFDB0720" "6ADA0720" "FFD30720" "69D20720" \ - "FFCB0720" "68CA0720" "FFC30720" "67C20720" \ - "FFBB0720" "66BA0720" "FFB30720" "65B20720" \ - "FFAB0720" "64AA0720" "FFA30720" "63A20720" \ - "FF9B0720" "629A0720" "FF930720" "61920720" \ - "FF8B0720" "608A0720" "FF830720" "5F820720" \ + "5F820720" "FF830720" "5F820720" "FF830720" \ + "5F820720" "FF830720" "5F820720" "FF8B0720" \ + "608A0720" "FF930720" "61920720" "FF9B0720" \ + "629A0720" "FFA30720" "63A20720" "FFAB0720" \ + "64AA0720" "FFB30720" "65B20720" "FFBB0720" \ + "66BA0720" "FFC30720" "67C20720" "FFCB0720" \ + "68CA0720" "FFD30720" "69D20720" "FFDB0720" \ + "6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \ + "6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \ + "6EFA0720" "FF850720" "6F840720" "FF8D0720" \ + "708C0720" "FF950720" "71940720" "FF9D0720" \ + "729C0720" "FFA50720" "73A40720" "FFAD0720" \ + "74AC0720" "FFB50720" "75B40720" "FFBD0720" \ + "76BC0720" "FFC50720" "77C40720" "FFCD0720" \ + "78CC0720" "FFD50720" "79D40720" "FFDD0720" \ + "7ADC0720" "FFE50720" "7BE40720" "FFED0720" \ + "7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \ + "7EFC0720" "FF870720" "7F860720" "FF8F0720" \ + "808E0720" "FF970720" "81960720" "FF9F0720" \ + "829E0720" "FFA70720" "83A60720" "FFAF0720" \ + "84AE0720" "FFB70720" "85B60720" "FFBF0720" \ + "86BE0720" "FFC70720" "87C60720" "FFCF0720" \ + "88CE0720" "FFD70720" "89D60720" "FFDF0720" \ + "8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \ + "8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \ + "8EFE0720" \ + "FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \ + "FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \ + "FFDF0720" "8ADE0720" "FFD70720" "89D60720" \ + "FFCF0720" "88CE0720" "FFC70720" "87C60720" \ + "FFBF0720" "86BE0720" "FFB70720" "85B60720" \ + "FFAF0720" "84AE0720" "FFA70720" "83A60720" \ + "FF9F0720" "829E0720" "FF970720" "81960720" \ + "FF8F0720" "808E0720" "FF870720" "7F860720" \ + "FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \ + "FFED0720" "7CEC0720" "FFE50720" "7BE40720" \ + "FFDD0720" "7ADC0720" "FFD50720" "79D40720" \ + "FFCD0720" "78CC0720" "FFC50720" "77C40720" \ + "FFBD0720" "76BC0720" "FFB50720" "75B40720" \ + "FFAD0720" "74AC0720" "FFA50720" "73A40720" \ + "FF9D0720" "729C0720" "FF950720" "71940720" \ + "FF8D0720" "708C0720" "FF850720" "6F840720" \ + "FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \ + "FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \ + "FFDB0720" "6ADA0720" "FFD30720" "69D20720" \ + "FFCB0720" "68CA0720" "FFC30720" "67C20720" \ + "FFBB0720" "66BA0720" "FFB30720" "65B20720" \ + "FFAB0720" "64AA0720" "FFA30720" "63A20720" \ + "FF9B0720" "629A0720" "FF930720" "61920720" \ + "FF8B0720" "608A0720" "FF830720" "5F820720" \ Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ @@ -1871,49 +1873,49 @@ const char *vfs301_0220_01[] = { "A46C0420" "A46C0400" "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () @@ -2268,55 +2270,55 @@ const char *vfs301_02D0_04[] = { * any troubles. */ PACKET ("0200", "8005", "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () @@ -2437,55 +2439,55 @@ const char *vfs301_02D0_05[] = { * any troubles. */ PACKET ("0200", "8005", "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () diff --git a/libfprint/drivers/vfs5011_proto.h b/libfprint/drivers/vfs5011_proto.h index 5b2f8f41..e49cd800 100644 --- a/libfprint/drivers/vfs5011_proto.h +++ b/libfprint/drivers/vfs5011_proto.h @@ -1,5 +1,7 @@ #pragma once +/* *INDENT-OFF* */ + #define VFS5011_LINE_SIZE 240 #define VFS5011_IMAGE_WIDTH 160 From 944e0d03837daa71c9db64b457d0239aa75596bd Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 13:29:17 +0100 Subject: [PATCH 020/103] udev-rules: Print warning if an ID is supported --- libfprint/fprint-list-udev-rules.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-rules.c index d6c884cb..5f80fe19 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-rules.c @@ -110,6 +110,7 @@ static const FpIdEntry blacklist_id_table[] = { static const FpDeviceClass whitelist = { .type = FP_DEVICE_TYPE_USB, .id_table = whitelist_id_table, + .id = "whitelist", .full_name = "Hardcoded whitelist" }; @@ -138,13 +139,15 @@ print_driver (const FpDeviceClass *cls) key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); - if (g_hash_table_lookup (printed, key) != NULL) + if (cls == &whitelist && g_hash_table_lookup (printed, key) != NULL) { + g_warning ("%s implemented by driver %s", + key, (const char *) g_hash_table_lookup (printed, key)); g_free (key); continue; } - g_hash_table_insert (printed, key, GINT_TO_POINTER (1)); + g_hash_table_insert (printed, key, (void *) cls->id); if (num_printed == 0) g_print ("# %s\n", cls->full_name); From 80dbc9c0cb0825c89cdd07c5d4ceda5055cc2d8a Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 13:37:51 +0100 Subject: [PATCH 021/103] udev-rules: Remove supported synaptics devices --- libfprint/fprint-list-udev-rules.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-rules.c index 5f80fe19..e574cac7 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-rules.c @@ -45,12 +45,9 @@ static const FpIdEntry whitelist_id_table[] = { { .vid = 0x06cb, .pid = 0x00b7 }, { .vid = 0x06cb, .pid = 0x00bb }, { .vid = 0x06cb, .pid = 0x00be }, - { .vid = 0x06cb, .pid = 0x00c2 }, - { .vid = 0x06cb, .pid = 0x00c9 }, { .vid = 0x06cb, .pid = 0x00cb }, { .vid = 0x06cb, .pid = 0x00d8 }, { .vid = 0x06cb, .pid = 0x00da }, - { .vid = 0x06cb, .pid = 0x00e7 }, { .vid = 0x0a5c, .pid = 0x5801 }, { .vid = 0x0a5c, .pid = 0x5805 }, { .vid = 0x0a5c, .pid = 0x5834 }, From 16095a21fd0a86a0ecc29ee4e67dfb0e25d78683 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 13:38:08 +0100 Subject: [PATCH 022/103] tests: Add check that no supported device is whitelisted --- tests/meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/meson.build b/tests/meson.build index 12a10959..f9603b89 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -168,6 +168,11 @@ foreach test_name: unit_tests ) endforeach +# Run udev rule generator with fatal warnings +test('udev-rules', + udev_rules, + env: envs) + gdb = find_program('gdb', required: false) if gdb.found() add_test_setup('gdb', From 55a2bb55361ae3f1b46c542167069e85e66b1e74 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:13:03 +0100 Subject: [PATCH 023/103] Generate a hwdb instead of udev rules We only use the rules/hwdb to enable auto-suspend. So, instead of shipping our own rules, we can just use the existing autosuspend rules and ship a hwdb that sets the appropriate flag. Closes: #336 --- ...nt-list-udev-rules.c => fprint-list-udev-hwdb.c} | 13 ++++++++----- libfprint/meson.build | 10 +++++----- meson.build | 6 +++--- meson_options.txt | 4 ++-- tests/meson.build | 4 ++-- 5 files changed, 20 insertions(+), 17 deletions(-) rename libfprint/{fprint-list-udev-rules.c => fprint-list-udev-hwdb.c} (93%) diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-hwdb.c similarity index 93% rename from libfprint/fprint-list-udev-rules.c rename to libfprint/fprint-list-udev-hwdb.c index e574cac7..1553db4d 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -147,17 +147,20 @@ print_driver (const FpDeviceClass *cls) g_hash_table_insert (printed, key, (void *) cls->id); if (num_printed == 0) - g_print ("# %s\n", cls->full_name); + { + if (cls != &whitelist) + g_print ("\n# Supported by libfprint driver %s\n", cls->id); + else + g_print ("\n# Known unsupported devices\n"); + } - g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n", + g_print ("usb:v%04Xp%04X*\n", entry->vid, entry->pid); - g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n", - entry->vid, entry->pid, cls->full_name); num_printed++; } if (num_printed > 0) - g_print ("\n"); + g_print (" ID_AUTOSUSPEND=1\n"); } int diff --git a/libfprint/meson.build b/libfprint/meson.build index 4d1d30cc..e385ce83 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -295,19 +295,19 @@ libfprint_private_dep = declare_dependency( ] ) -udev_rules = executable('fprint-list-udev-rules', - 'fprint-list-udev-rules.c', +udev_hwdb = executable('fprint-list-udev-hwdb', + 'fprint-list-udev-hwdb.c', dependencies: libfprint_private_dep, link_with: libfprint_drivers, install: false) if get_option('udev_rules') custom_target('udev-rules', - output: '60-@0@-autosuspend.rules'.format(versioned_libname), + output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), capture: true, - command: [ udev_rules ], + command: [ udev_hwdb ], install: true, - install_dir: udev_rules_dir) + install_dir: udev_hwdb_dir) endif supported_devices = executable('fprint-list-supported-devices', diff --git a/meson.build b/meson.build index 139c571c..0d4822d3 100644 --- a/meson.build +++ b/meson.build @@ -175,11 +175,11 @@ drivers_type_func += '}' root_inc = include_directories('.') if get_option('udev_rules') - udev_rules_dir = get_option('udev_rules_dir') + udev_hwdb_dir = get_option('udev_hwdb_dir') - if udev_rules_dir == 'auto' + if udev_hwdb_dir == 'auto' udev_dep = dependency('udev') - udev_rules_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/rules.d' + udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d' endif endif diff --git a/meson_options.txt b/meson_options.txt index 746efdc7..414695fd 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,8 +10,8 @@ option('udev_rules', description: 'Whether to create a udev rules file', type: 'boolean', value: true) -option('udev_rules_dir', - description: 'Installation path for udev rules', +option('udev_hwdb_dir', + description: 'Installation path for udev hwdb', type: 'string', value: 'auto') option('gtk-examples', diff --git a/tests/meson.build b/tests/meson.build index f9603b89..537a00a2 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -169,8 +169,8 @@ foreach test_name: unit_tests endforeach # Run udev rule generator with fatal warnings -test('udev-rules', - udev_rules, +test('udev-hwdb', + udev_hwdb, env: envs) gdb = find_program('gdb', required: false) From cbce56c14241c3f64a428ced4558e0b57fa8d18c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:19:10 +0100 Subject: [PATCH 024/103] meson: Always build hwdb file We want systemd to pull our hwdb. In order to ease this, always build the hwdb file, even if it is disabled. Once systemd has merged the rules, downstream should turn off the rules in libfprint. The default in libfprint will also be changed to not build the hwdb (udev_rules option) eventually. --- libfprint/meson.build | 18 ++++++++++-------- meson.build | 2 ++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index e385ce83..3464bf37 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -301,14 +301,16 @@ udev_hwdb = executable('fprint-list-udev-hwdb', link_with: libfprint_drivers, install: false) -if get_option('udev_rules') - custom_target('udev-rules', - output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), - capture: true, - command: [ udev_hwdb ], - install: true, - install_dir: udev_hwdb_dir) -endif +# We always build this file; primarily so that systemd can pull it +# from the artefacts! +custom_target('udev-rules', + output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), + capture: true, + command: [ udev_hwdb ], + install: get_option('udev_rules'), + install_dir: udev_hwdb_dir, + build_by_default: true + ) supported_devices = executable('fprint-list-supported-devices', 'fprint-list-supported-devices.c', diff --git a/meson.build b/meson.build index 0d4822d3..cd0d83d2 100644 --- a/meson.build +++ b/meson.build @@ -181,6 +181,8 @@ if get_option('udev_rules') udev_dep = dependency('udev') udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d' endif +else + udev_hwdb_dir = false endif if get_option('gtk-examples') From f6179d6cc4758276d7eeb825e1de8a1f36c87d2c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:36:45 +0100 Subject: [PATCH 025/103] ci: Export hwdb into artefacts --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f0925b8..bf190b23 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,10 +49,13 @@ build: <<: *build_one_driver <<: *build # <<: *check_abi + after_script: + - cp _build/libfprint/60-autosuspend-libfprint-2.hwdb . artifacts: expose_as: "HTML Documentation" paths: - _build/doc/html/ + - 60-autosuspend-libfprint-2.hwdb expire_in: 1 week test: From 1f2d723485efb4a352a42a085e1dd17315971377 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:42:35 +0100 Subject: [PATCH 026/103] Drop version from libfprint hwdb As we are shipping a hwdb file now, we cannot have a collision with the old libfprint version. Also, we are going to pull these rules into systemd and they will not be installed via libfprint in the future. As such, collisions will not happen again and it makes more sense like this for systemd. --- .gitlab-ci.yml | 4 ++-- libfprint/meson.build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bf190b23..c416c2b0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,12 +50,12 @@ build: <<: *build # <<: *check_abi after_script: - - cp _build/libfprint/60-autosuspend-libfprint-2.hwdb . + - cp _build/libfprint/60-autosuspend-libfprint.hwdb . artifacts: expose_as: "HTML Documentation" paths: - _build/doc/html/ - - 60-autosuspend-libfprint-2.hwdb + - 60-autosuspend-libfprint.hwdb expire_in: 1 week test: diff --git a/libfprint/meson.build b/libfprint/meson.build index 3464bf37..abf2fb92 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -304,7 +304,7 @@ udev_hwdb = executable('fprint-list-udev-hwdb', # We always build this file; primarily so that systemd can pull it # from the artefacts! custom_target('udev-rules', - output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), + output: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), capture: true, command: [ udev_hwdb ], install: get_option('udev_rules'), From 284f6f1ef812f9561c150ca28b06f91a44f7a09c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 15:55:56 +0100 Subject: [PATCH 027/103] ci: Add check that wiki and generator are in sync Add a new test that checks that the unsupported list is not out of date. As the wiki can be edited at any time, add this as a further optional check into the CI pipeline. --- .gitlab-ci.yml | 9 ++++++ tests/hwdb-check-unsupported.py | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100755 tests/hwdb-check-unsupported.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c416c2b0..4f56ec77 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -112,6 +112,15 @@ test_indent: - git diff - "! git status -s | grep -q ." +test_unsupported_list: + stage: check-source + except: + variables: + - $CI_PIPELINE_SOURCE == "schedule" + allow_failure: true + script: + - tests/hwdb-check-unsupported.py + flatpak: stage: flatpak extends: .flatpak diff --git a/tests/hwdb-check-unsupported.py b/tests/hwdb-check-unsupported.py new file mode 100755 index 00000000..650cd099 --- /dev/null +++ b/tests/hwdb-check-unsupported.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import os +import sys +import urllib +import urllib.request +import re + +error = False + +try: + response = urllib.request.urlopen('https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md') +except: + print("Could not download current list of unsupported devices, skipping test.") + sys.exit(77) +data = response.read().decode('utf-8') + +devices = [] +devices_re = re.compile(r'^.*([0-9a-fA-F]{4}):([0-9a-fA-F]{4}).*$', re.MULTILINE) +for m in devices_re.finditer(data): + vid = m.group(1) + pid = m.group(2) + devices.append((vid, pid)) + +generator = open(os.path.join(os.path.dirname(__file__), '..', 'libfprint', 'fprint-list-udev-hwdb.c')).read() + +id_re = re.compile(' { .vid = 0x([a-fA-F0-9]*), .pid = 0x([a-fA-F0-9]*) }') +# Check everything is the same +started = False +for l in generator.split('\n'): + m = id_re.match(l) + if m is None: + # Stop on the first line that does not match anymore + if started: + break + continue + else: + started = True + + vid_pid = (m.group(1), m.group(2)) + try: + devices.remove(vid_pid) + except ValueError: + print("Generator has entry that is not on wiki: {}:{}".format(*vid_pid)) + error = True + +for vid_pid in devices: + print("New entry from wiki is missing: {}:{}".format(*vid_pid)) + error = True + +if error: + sys.exit(1) +else: + sys.exit(0) From 66fc93eeff14d273f06ea9ba9c7ee590e94d56cc Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 20 Jan 2021 18:02:31 +0100 Subject: [PATCH 028/103] udev-hwdb: Prevent devices from being listed twice The change to print a warning (for testing purposes) from commit 944e0d03837 (udev-rules: Print warning if an ID is supported) was incorrect because it prevented duplicated to be suppressed if a device is listed by two independent drivers. --- libfprint/fprint-list-udev-hwdb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index 1553db4d..b6870852 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -136,10 +136,11 @@ print_driver (const FpDeviceClass *cls) key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); - if (cls == &whitelist && g_hash_table_lookup (printed, key) != NULL) + if (g_hash_table_lookup (printed, key) != NULL) { - g_warning ("%s implemented by driver %s", - key, (const char *) g_hash_table_lookup (printed, key)); + if (cls == &whitelist) + g_warning ("%s implemented by driver %s", + key, (const char *) g_hash_table_lookup (printed, key)); g_free (key); continue; } From 99c269b3fe3048d6d7050c9d460cd2ff04090df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 10 Dec 2020 20:22:54 +0100 Subject: [PATCH 029/103] meson: Do not support drivers known to fail in Big Endian archs When building in big endian architectures some device tests will fail, as per this we're pretty sure that most of the drivers are not ready to work in big-endian architectures. Since we're aware of this, better to just stop supporting those drivers instead of having each distribution to handle the problem. So, add a list of supported drivers that is filled depending the architecture type we're building on. Keep continue building those drivers since we want to at least test-build them, but do not expose them as libfprint drivers, so if a device in the system uses any of them will be ignored. At the same time, we keep track of the problem, so that we can fix the drivers. Related to #236 --- meson.build | 20 +++++++++++++++++++- tests/meson.build | 3 ++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index cd0d83d2..ec5d9a6f 100644 --- a/meson.build +++ b/meson.build @@ -89,6 +89,7 @@ cairo_dep = dependency('cairo', required: false) # Drivers drivers = get_option('drivers').split(',') virtual_drivers = [ 'virtual_image' ] + default_drivers = [ 'upektc_img', 'vfs5011', @@ -113,6 +114,13 @@ default_drivers = [ 'goodixmoc', ] +# FIXME: All the drivers should be fixed by adjusting the byte order. +# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236 +endian_independent_drivers = virtual_drivers + [ + 'aes3500', + 'synaptics', +] + all_drivers = default_drivers + virtual_drivers if drivers == [ 'all' ] @@ -150,6 +158,16 @@ foreach driver: drivers endif endforeach +supported_drivers = [] +foreach driver: drivers + if build_machine.endian() == 'little' or driver in endian_independent_drivers + supported_drivers += driver + else + warning('Driver @0@ is not supported by big endian cpu @1@. Please, fix it!'.format( + driver, build_machine.cpu())) + endif +endforeach + # Export the drivers' types to the core code drivers_type_list = [] drivers_type_func = [] @@ -162,7 +180,7 @@ drivers_type_func += '{' drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));' drivers_type_func += ' GType t;' drivers_type_func += '' -foreach driver: drivers +foreach driver: supported_drivers drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);' drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();' drivers_type_func += ' g_array_append_val (drivers, t);' diff --git a/tests/meson.build b/tests/meson.build index 537a00a2..4ebf3b70 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -70,7 +70,8 @@ if get_option('introspection') driver_envs = envs driver_envs.set('FP_DRIVERS_WHITELIST', driver_test) - if driver_test in drivers and gusb_dep.version().version_compare('>= 0.3.0') + if (driver_test in supported_drivers and + gusb_dep.version().version_compare('>= 0.3.0')) test(driver_test, find_program('umockdev-test.py'), args: join_paths(meson.current_source_dir(), driver_test), From 533180a2e639148d2e6657f7ecbfab7c0025da63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 20 Jan 2021 20:02:05 +0100 Subject: [PATCH 030/103] data: Use auto-generated but hardcoded autosuspend hwdb file This solves various problems: 1. It stays the same also if some drivers have been disabled 2. It uses a stable path for being imported by systemd 3. It is still checked for its validity by tests 4. It can be auto-generated using a simple command --- .gitlab-ci.yml | 3 - data/autosuspend.hwdb | 262 ++++++++++++++++++++++++++++++ data/meson.build | 9 + libfprint/fprint-list-udev-hwdb.c | 5 + libfprint/meson.build | 24 ++- meson.build | 12 ++ tests/meson.build | 5 +- tests/test-generated-hwdb.sh | 24 +++ 8 files changed, 332 insertions(+), 12 deletions(-) create mode 100644 data/autosuspend.hwdb create mode 100644 data/meson.build create mode 100755 tests/test-generated-hwdb.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4f56ec77..e6f736cd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,13 +49,10 @@ build: <<: *build_one_driver <<: *build # <<: *check_abi - after_script: - - cp _build/libfprint/60-autosuspend-libfprint.hwdb . artifacts: expose_as: "HTML Documentation" paths: - _build/doc/html/ - - 60-autosuspend-libfprint.hwdb expire_in: 1 week test: diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb new file mode 100644 index 00000000..f22d16a2 --- /dev/null +++ b/data/autosuspend.hwdb @@ -0,0 +1,262 @@ +# This file has been generated using fprint-list-udev-hwdb with all drivers enabled + +# Supported by libfprint driver upektc_img +usb:v147Ep2016* +usb:v147Ep2020* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs5011 +usb:v138Ap0010* +usb:v138Ap0011* +usb:v138Ap0015* +usb:v138Ap0017* +usb:v138Ap0018* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes3500 +usb:v08FFp5731* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes4000 +usb:v5501p08FF* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes1610 +usb:v08FFp1600* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes1660 +usb:v08FFp1660* +usb:v08FFp1680* +usb:v08FFp1681* +usb:v08FFp1682* +usb:v08FFp1683* +usb:v08FFp1684* +usb:v08FFp1685* +usb:v08FFp1686* +usb:v08FFp1687* +usb:v08FFp1688* +usb:v08FFp1689* +usb:v08FFp168A* +usb:v08FFp168B* +usb:v08FFp168C* +usb:v08FFp168D* +usb:v08FFp168E* +usb:v08FFp168F* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2660 +usb:v08FFp2660* +usb:v08FFp2680* +usb:v08FFp2681* +usb:v08FFp2682* +usb:v08FFp2683* +usb:v08FFp2684* +usb:v08FFp2685* +usb:v08FFp2686* +usb:v08FFp2687* +usb:v08FFp2688* +usb:v08FFp2689* +usb:v08FFp268A* +usb:v08FFp268B* +usb:v08FFp268C* +usb:v08FFp268D* +usb:v08FFp268E* +usb:v08FFp268F* +usb:v08FFp2691* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2501 +usb:v08FFp2500* +usb:v08FFp2580* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2550 +usb:v08FFp2550* +usb:v08FFp2810* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs101 +usb:v138Ap0001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs301 +usb:v138Ap0005* +usb:v138Ap0008* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs0050 +usb:v138Ap0050* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver etes603 +usb:v1C7Ap0603* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vcom5s +usb:v061Ap0110* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver synaptics +usb:v06CBp00BD* +usb:v06CBp00E9* +usb:v06CBp00DF* +usb:v06CBp00F9* +usb:v06CBp00FC* +usb:v06CBp00C2* +usb:v06CBp00C9* +usb:v06CBp00E7* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver elan +usb:v04F3p0903* +usb:v04F3p0907* +usb:v04F3p0C01* +usb:v04F3p0C02* +usb:v04F3p0C03* +usb:v04F3p0C04* +usb:v04F3p0C05* +usb:v04F3p0C06* +usb:v04F3p0C07* +usb:v04F3p0C08* +usb:v04F3p0C09* +usb:v04F3p0C0A* +usb:v04F3p0C0B* +usb:v04F3p0C0C* +usb:v04F3p0C0D* +usb:v04F3p0C0E* +usb:v04F3p0C0F* +usb:v04F3p0C10* +usb:v04F3p0C11* +usb:v04F3p0C12* +usb:v04F3p0C13* +usb:v04F3p0C14* +usb:v04F3p0C15* +usb:v04F3p0C16* +usb:v04F3p0C17* +usb:v04F3p0C18* +usb:v04F3p0C19* +usb:v04F3p0C1A* +usb:v04F3p0C1B* +usb:v04F3p0C1C* +usb:v04F3p0C1D* +usb:v04F3p0C1E* +usb:v04F3p0C1F* +usb:v04F3p0C20* +usb:v04F3p0C21* +usb:v04F3p0C22* +usb:v04F3p0C23* +usb:v04F3p0C24* +usb:v04F3p0C25* +usb:v04F3p0C26* +usb:v04F3p0C27* +usb:v04F3p0C28* +usb:v04F3p0C29* +usb:v04F3p0C2A* +usb:v04F3p0C2B* +usb:v04F3p0C2C* +usb:v04F3p0C2D* +usb:v04F3p0C2E* +usb:v04F3p0C2F* +usb:v04F3p0C30* +usb:v04F3p0C31* +usb:v04F3p0C32* +usb:v04F3p0C33* +usb:v04F3p0C42* +usb:v04F3p0C4D* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver uru4000 +usb:v045Ep00BC* +usb:v045Ep00BD* +usb:v045Ep00CA* +usb:v05BAp0007* +usb:v05BAp0008* +usb:v05BAp000A* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upektc +usb:v0483p2015* +usb:v147Ep3001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upeksonly +usb:v147Ep1000* +usb:v147Ep1001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver goodixmoc +usb:v27C6p5840* +usb:v27C6p6496* +usb:v27C6p60A2* +usb:v27C6p63AC* +usb:v27C6p639C* + ID_AUTOSUSPEND=1 + +# Known unsupported devices +usb:v04F3p036B* +usb:v04F3p0C00* +usb:v04F3p0C4B* +usb:v04F3p0C4C* +usb:v04F3p0C4F* +usb:v04F3p0C57* +usb:v04F3p2706* +usb:v06CBp0081* +usb:v06CBp0088* +usb:v06CBp008A* +usb:v06CBp009A* +usb:v06CBp009B* +usb:v06CBp00A2* +usb:v06CBp00B7* +usb:v06CBp00BB* +usb:v06CBp00BE* +usb:v06CBp00CB* +usb:v06CBp00D8* +usb:v06CBp00DA* +usb:v0A5Cp5801* +usb:v0A5Cp5805* +usb:v0A5Cp5834* +usb:v0A5Cp5843* +usb:v10A5p0007* +usb:v1188p9545* +usb:v138Ap0007* +usb:v138Ap003A* +usb:v138Ap003C* +usb:v138Ap003D* +usb:v138Ap003F* +usb:v138Ap0090* +usb:v138Ap0091* +usb:v138Ap0092* +usb:v138Ap0094* +usb:v138Ap0097* +usb:v138Ap009D* +usb:v138Ap00AB* +usb:v147Ep1002* +usb:v1491p0088* +usb:v16D1p1027* +usb:v1C7Ap0300* +usb:v1C7Ap0570* +usb:v1C7Ap0575* +usb:v27C6p5042* +usb:v27C6p5110* +usb:v27C6p5117* +usb:v27C6p5201* +usb:v27C6p521D* +usb:v27C6p5301* +usb:v27C6p530C* +usb:v27C6p532D* +usb:v27C6p533C* +usb:v27C6p5381* +usb:v27C6p5385* +usb:v27C6p538C* +usb:v27C6p538D* +usb:v27C6p5395* +usb:v27C6p5584* +usb:v27C6p55A2* +usb:v27C6p55A4* +usb:v27C6p55B4* +usb:v27C6p5740* +usb:v2808p9338* +usb:v298Dp2033* +usb:v3538p0930* + ID_AUTOSUSPEND=1 diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 00000000..975c1c3f --- /dev/null +++ b/data/meson.build @@ -0,0 +1,9 @@ +if get_option('udev_rules') + # This file has to be updated using + # ninja -C libfprint/sync-udev-hwdb + + install_data('autosuspend.hwdb', + rename: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), + install_dir: udev_hwdb_dir, + ) +endif diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index b6870852..630be0f7 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -168,8 +168,13 @@ int main (int argc, char **argv) { g_autoptr(GArray) drivers = fpi_get_driver_types (); + g_autofree char *program_name = NULL; guint i; + program_name = g_path_get_basename (argv[0]); + g_print ("# This file has been generated using %s with all drivers enabled\n", + program_name); + printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (i = 0; i < drivers->len; i++) diff --git a/libfprint/meson.build b/libfprint/meson.build index abf2fb92..110c4582 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -301,16 +301,24 @@ udev_hwdb = executable('fprint-list-udev-hwdb', link_with: libfprint_drivers, install: false) -# We always build this file; primarily so that systemd can pull it -# from the artefacts! -custom_target('udev-rules', - output: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), +udev_hwdb_generator = custom_target('udev-hwdb', + output: 'autosuspend.hwdb', + depend_files: drivers_sources, capture: true, command: [ udev_hwdb ], - install: get_option('udev_rules'), - install_dir: udev_hwdb_dir, - build_by_default: true - ) + install: false, +) + +custom_target('sync-udev-hwdb', + depends: udev_hwdb_generator, + output: 'sync-udev-hwdb', + install: false, + command: [ + 'cp', '-v', + udev_hwdb_generator.full_path(), + meson.source_root() / 'data' + ] +) supported_devices = executable('fprint-list-supported-devices', 'fprint-list-supported-devices.c', diff --git a/meson.build b/meson.build index ec5d9a6f..8dc852aa 100644 --- a/meson.build +++ b/meson.build @@ -135,6 +135,18 @@ if drivers.length() == 0 or drivers[0] == '' error('Cannot build libfprint without drivers, please specify a valid value for the drivers option') endif +if drivers == all_drivers or drivers == default_drivers + default_drivers_are_enabled = true +else + default_drivers_are_enabled = true + foreach driver: default_drivers + if driver not in drivers + default_drivers_are_enabled = false + break + endif + endforeach +endif + nss_dep = dependency('', required: false) imaging_dep = dependency('', required: false) libfprint_conf.set10('HAVE_PIXMAN', false) diff --git a/tests/meson.build b/tests/meson.build index 4ebf3b70..8e24980b 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -5,6 +5,7 @@ envs.set('G_MESSAGES_DEBUG', 'all') # Setup paths envs.set('MESON_SOURCE_ROOT', meson.source_root()) +envs.set('MESON_BUILD_ROOT', meson.build_root()) envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint')) # Set FP_DEVICE_EMULATION so that drivers can adapt (e.g. to use fixed @@ -170,8 +171,10 @@ foreach test_name: unit_tests endforeach # Run udev rule generator with fatal warnings +envs.set('UDEV_HWDB', udev_hwdb.full_path()) +envs.set('UDEV_HWDB_CHECK_CONTENTS', default_drivers_are_enabled ? '1' : '0') test('udev-hwdb', - udev_hwdb, + find_program('test-generated-hwdb.sh'), env: envs) gdb = find_program('gdb', required: false) diff --git a/tests/test-generated-hwdb.sh b/tests/test-generated-hwdb.sh new file mode 100755 index 00000000..34209cb5 --- /dev/null +++ b/tests/test-generated-hwdb.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e + +[ -x "$UDEV_HWDB" ] || exit 1 + +if [ "$UDEV_HWDB_CHECK_CONTENTS" == 1 ]; then + generated_rules=$(mktemp "${TMPDIR:-/tmp}/libfprint-XXXXXX.hwdb") +else + generated_rules=/dev/null +fi + +$UDEV_HWDB > "$generated_rules" + +if [ "$UDEV_HWDB_CHECK_CONTENTS" != 1 ]; then + exit 77 +fi + +if ! cmp "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then + echo "E: Autosuspend file needs to be re-generated!" + echo " ninja -C $MESON_BUILD_ROOT libfprint/sync-udev-hwdb" + exit 1 +fi + +rm "$generated_rules" From 2f2da87240eb3d65ff7a0d11b29029a3d084115d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 20 Jan 2021 22:02:10 +0100 Subject: [PATCH 031/103] list-udev-hwdb: Add SPDX license to the generated file And update it... --- data/autosuspend.hwdb | 1 + libfprint/fprint-list-udev-hwdb.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb index f22d16a2..7a78068c 100644 --- a/data/autosuspend.hwdb +++ b/data/autosuspend.hwdb @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later # This file has been generated using fprint-list-udev-hwdb with all drivers enabled # Supported by libfprint driver upektc_img diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index 630be0f7..6f533fb6 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -172,6 +172,8 @@ main (int argc, char **argv) guint i; program_name = g_path_get_basename (argv[0]); + + g_print ("# SPDX-License-Identifier: LGPL-2.1-or-later\n"); g_print ("# This file has been generated using %s with all drivers enabled\n", program_name); From 5df14206d8f93ba45044daac463bc1500a2b0065 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 15:57:21 +0100 Subject: [PATCH 032/103] tests: Add support for creating other virtual readers Add support for creating more virtual readers. Co-authored-by: Bastien Nocera --- tests/test-fp-context.c | 14 +++++++------- tests/test-fp-device.c | 30 +++++++++++++++--------------- tests/test-utils.c | 38 +++++++++++++++++++++++++++++--------- tests/test-utils.h | 9 +++++++-- 4 files changed, 58 insertions(+), 33 deletions(-) diff --git a/tests/test-fp-context.c b/tests/test-fp-context.c index 156e6d47..c74548cd 100644 --- a/tests/test-fp-context.c +++ b/tests/test-fp-context.c @@ -50,7 +50,7 @@ test_context_has_virtual_device (void) GPtrArray *devices; unsigned int i; - fpt_setup_virtual_device_environment (); + fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE); context = fp_context_new (); devices = fp_context_get_devices (context); @@ -82,7 +82,7 @@ test_context_enumerates_new_devices (void) context = fp_context_new (); - fpt_setup_virtual_device_environment (); + fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE); fp_context_enumerate (context); devices = fp_context_get_devices (context); @@ -120,7 +120,7 @@ context_device_removed_cb (FpContext *ctx, FpDevice *device, FptContext *tctx) static void test_context_remove_device_closed (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); gboolean removed; tctx->user_data = NULL; @@ -162,7 +162,7 @@ close_done_cb (GObject *device, GAsyncResult *res, gpointer user_data) static void test_context_remove_device_closing (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) close_error = NULL; g_autoptr(GError) error = NULL; gboolean removed; @@ -207,7 +207,7 @@ test_context_remove_device_closing (void) static void test_context_remove_device_open (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) error = NULL; gboolean removed = FALSE; @@ -267,7 +267,7 @@ open_done_cb (GObject *device, GAsyncResult *res, gpointer user_data) static void test_context_remove_device_opening (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) close_error = NULL; gboolean open_done = FALSE; gboolean removed; @@ -327,7 +327,7 @@ enroll_done_cb (GObject *device, GAsyncResult *res, gpointer user_data) static void test_context_remove_device_active (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) error = NULL; g_autoptr(GCancellable) cancellable = NULL; g_autoptr(GError) enroll_error = NULL; diff --git a/tests/test-fp-device.c b/tests/test-fp-device.c index e3eb662e..b8f6f172 100644 --- a/tests/test-fp-device.c +++ b/tests/test-fp-device.c @@ -36,7 +36,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx) static void test_device_open_async (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx); @@ -59,7 +59,7 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, FptContext *tctx) static void test_device_close_async (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx); while (!tctx->user_data) @@ -76,7 +76,7 @@ static void test_device_open_sync (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, &error); g_assert_no_error (error); @@ -97,7 +97,7 @@ static void test_device_open_sync_notify (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx); fp_device_open_sync (tctx->device, NULL, &error); @@ -109,7 +109,7 @@ static void test_device_close_sync (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); fp_device_close_sync (tctx->device, NULL, &error); @@ -131,7 +131,7 @@ static void test_device_close_sync_notify (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); @@ -144,7 +144,7 @@ test_device_close_sync_notify (void) static void test_device_get_driver (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image"); @@ -153,7 +153,7 @@ test_device_get_driver (void) static void test_device_get_device_id (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0"); @@ -162,7 +162,7 @@ test_device_get_device_id (void) static void test_device_get_name (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpstr (fp_device_get_name (tctx->device), ==, @@ -172,7 +172,7 @@ test_device_get_name (void) static void test_device_get_scan_type (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE); @@ -181,7 +181,7 @@ test_device_get_scan_type (void) static void test_device_get_finger_status (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpint (fp_device_get_finger_status (tctx->device), ==, FP_FINGER_STATUS_NONE); @@ -190,7 +190,7 @@ test_device_get_finger_status (void) static void test_device_get_nr_enroll_stages (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5); @@ -199,7 +199,7 @@ test_device_get_nr_enroll_stages (void) static void test_device_supports_identify (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_true (fp_device_supports_identify (tctx->device)); @@ -208,7 +208,7 @@ test_device_supports_identify (void) static void test_device_supports_capture (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_true (fp_device_supports_capture (tctx->device)); @@ -217,7 +217,7 @@ test_device_supports_capture (void) static void test_device_has_storage (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_false (fp_device_has_storage (tctx->device)); diff --git a/tests/test-utils.c b/tests/test-utils.c index 834a90e8..1c1be17f 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -22,16 +22,29 @@ #include "test-utils.h" +struct +{ + const char *envvar; + const char *driver_id; + const char *device_id; +} devtype_vars[FPT_NUM_VIRTUAL_DEVICE_TYPES] = { + { "FP_VIRTUAL_IMAGE", "virtual_image", "virtual_image" }, /* FPT_VIRTUAL_DEVICE_IMAGE */ +}; + +static FptVirtualDeviceType global_devtype; + void fpt_teardown_virtual_device_environment (void) { - const char *path = g_getenv ("FP_VIRTUAL_IMAGE"); + const char *path; + + path = g_getenv (devtype_vars[global_devtype].envvar); if (path) { g_autofree char *temp_dir = g_path_get_dirname (path); - g_unsetenv ("FP_VIRTUAL_IMAGE"); + g_unsetenv (devtype_vars[global_devtype].envvar); g_unlink (path); g_rmdir (temp_dir); } @@ -44,19 +57,23 @@ on_signal_event (int sig) } void -fpt_setup_virtual_device_environment (void) +fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype) { g_autoptr(GError) error = NULL; g_autofree char *temp_dir = NULL; g_autofree char *temp_path = NULL; + g_autofree char *filename = NULL; - g_assert_null (g_getenv ("FP_VIRTUAL_IMAGE")); + g_assert_null (g_getenv (devtype_vars[devtype].envvar)); temp_dir = g_dir_make_tmp ("libfprint-XXXXXX", &error); g_assert_no_error (error); - temp_path = g_build_filename (temp_dir, "virtual-image.socket", NULL); - g_setenv ("FP_VIRTUAL_IMAGE", temp_path, TRUE); + filename = g_strdup_printf ("%s.socket", devtype_vars[devtype].device_id); + temp_path = g_build_filename (temp_dir, filename, NULL); + g_setenv (devtype_vars[devtype].envvar, temp_path, TRUE); + + global_devtype = devtype; signal (SIGKILL, on_signal_event); signal (SIGABRT, on_signal_event); @@ -78,13 +95,16 @@ fpt_context_new (void) } FptContext * -fpt_context_new_with_virtual_imgdev (void) +fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype) { FptContext *tctx; GPtrArray *devices; unsigned int i; - fpt_setup_virtual_device_environment (); + g_assert_true (devtype >= FPT_VIRTUAL_DEVICE_IMAGE && + devtype < FPT_NUM_VIRTUAL_DEVICE_TYPES); + + fpt_setup_virtual_device_environment (devtype); tctx = fpt_context_new (); devices = fp_context_get_devices (tctx->fp_context); @@ -96,7 +116,7 @@ fpt_context_new_with_virtual_imgdev (void) { FpDevice *device = devices->pdata[i]; - if (g_strcmp0 (fp_device_get_driver (device), "virtual_image") == 0) + if (g_strcmp0 (fp_device_get_driver (device), devtype_vars[devtype].driver_id) == 0) { tctx->device = device; break; diff --git a/tests/test-utils.h b/tests/test-utils.h index 4bc1e699..e4e4c30e 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -19,7 +19,12 @@ #include -void fpt_setup_virtual_device_environment (void); +typedef enum { + FPT_VIRTUAL_DEVICE_IMAGE = 0, + FPT_NUM_VIRTUAL_DEVICE_TYPES +} FptVirtualDeviceType; + +void fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype); void fpt_teardown_virtual_device_environment (void); typedef struct _FptContext @@ -30,7 +35,7 @@ typedef struct _FptContext } FptContext; FptContext * fpt_context_new (void); -FptContext * fpt_context_new_with_virtual_imgdev (void); +FptContext * fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype); void fpt_context_free (FptContext *test_context); From 253750ec0864af7831c72120a8efe1263bc0393d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 15:54:12 +0100 Subject: [PATCH 033/103] virtual-device-listener: Add a device socket handler class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of repeating the same code in both the virtual-image and the virtual-device drivers, implement a class to handle the socket listening an data reading. Co-authored-by: Marco Trevisan (Treviño) --- libfprint/drivers/virtual-device-listener.c | 355 ++++++++++++++++++++ libfprint/drivers/virtual-device-private.h | 93 +++++ libfprint/drivers/virtual-image.c | 260 ++++---------- libfprint/meson.build | 3 + 4 files changed, 524 insertions(+), 187 deletions(-) create mode 100644 libfprint/drivers/virtual-device-listener.c create mode 100644 libfprint/drivers/virtual-device-private.h diff --git a/libfprint/drivers/virtual-device-listener.c b/libfprint/drivers/virtual-device-listener.c new file mode 100644 index 00000000..50fe95fa --- /dev/null +++ b/libfprint/drivers/virtual-device-listener.c @@ -0,0 +1,355 @@ +/* + * Socket utilities for "simple" device debugging + * + * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2020 Marco Trevisan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define FP_COMPONENT "virtual_device_connection" + +#include "fpi-log.h" + +#include +#include + +#include "virtual-device-private.h" + +struct _FpDeviceVirtualListener +{ + GSocketListener parent_instance; + + GSocketConnection *connection; + GCancellable *cancellable; + guint cancellable_id; + + FpDeviceVirtualListenerConnectionCb ready_cb; + gpointer ready_cb_data; + + gint socket_fd; + gint client_fd; +}; + +G_DEFINE_TYPE (FpDeviceVirtualListener, fp_device_virtual_listener, G_TYPE_SOCKET_LISTENER) + +static void start_listen (FpDeviceVirtualListener *self); + +FpDeviceVirtualListener * +fp_device_virtual_listener_new (void) +{ + return g_object_new (fp_device_virtual_listener_get_type (), NULL); +} + +static void +fp_device_virtual_listener_dispose (GObject *object) +{ + FpDeviceVirtualListener *self = FP_DEVICE_VIRTUAL_LISTENER (object); + + if (self->cancellable_id) + { + g_cancellable_disconnect (self->cancellable, self->cancellable_id); + self->cancellable_id = 0; + } + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_object (&self->connection); + + self->ready_cb = NULL; + + G_OBJECT_CLASS (fp_device_virtual_listener_parent_class)->dispose (object); +} + +static void +fp_device_virtual_listener_class_init (FpDeviceVirtualListenerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = fp_device_virtual_listener_dispose; +} + +static void +fp_device_virtual_listener_init (FpDeviceVirtualListener *self) +{ +} + +static void +new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDeviceVirtualListener *self = user_data; + GSocketConnection *connection; + + connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object), + res, + NULL, + &error); + if (!connection) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_warning ("Error accepting a new connection: %s", error->message); + start_listen (self); + return; + } + + /* Always allow further connections. + * If we get a new one, we generally just close the old connection. */ + start_listen (self); + if (self->connection) + { + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + g_clear_object (&self->connection); + } + + self->connection = connection; + fp_dbg ("Got a new connection!"); + + self->ready_cb (self, self->ready_cb_data); +} + +static void +start_listen (FpDeviceVirtualListener *self) +{ + g_socket_listener_accept_async (G_SOCKET_LISTENER (self), + self->cancellable, + new_connection_cb, + self); +} + +static void +on_cancelled (GCancellable *cancellable, + FpDeviceVirtualListener *self) +{ + fp_device_virtual_listener_connection_close (self); + g_socket_listener_close (G_SOCKET_LISTENER (self)); + g_clear_object (&self->cancellable); + self->ready_cb = NULL; +} + +gboolean +fp_device_virtual_listener_start (FpDeviceVirtualListener *self, + const char *address, + GCancellable *cancellable, + FpDeviceVirtualListenerConnectionCb cb, + gpointer user_data, + GError **error) +{ + g_autoptr(GSocketAddress) addr = NULL; + G_DEBUG_HERE (); + + g_return_val_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE); + g_return_val_if_fail (cb != NULL, FALSE); + g_return_val_if_fail (self->ready_cb == NULL, FALSE); + + self->client_fd = -1; + + g_socket_listener_set_backlog (G_SOCKET_LISTENER (self), 1); + + /* Remove any left over socket. */ + g_unlink (address); + + addr = g_unix_socket_address_new (address); + + if (!g_socket_listener_add_address (G_SOCKET_LISTENER (self), + addr, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + NULL, + NULL, + error)) + { + g_warning ("Could not listen on unix socket: %s", (*error)->message); + return FALSE; + } + + self->ready_cb = cb; + self->ready_cb_data = user_data; + self->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + if (self->cancellable) + self->cancellable_id = g_cancellable_connect (self->cancellable, + G_CALLBACK (on_cancelled), self, NULL); + + start_listen (self); + + return TRUE; +} + +gboolean +fp_device_virtual_listener_connection_close (FpDeviceVirtualListener *self) +{ + g_return_val_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE); + + if (!self->connection) + return FALSE; + + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + g_clear_object (&self->connection); + + return TRUE; +} + +static void +on_stream_read_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GTask) task = user_data; + FpDeviceVirtualListener *self = g_task_get_source_object (task); + gboolean all; + gboolean success; + gsize bytes; + + all = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "all")); + + if (all) + { + success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error); + } + else + { + gssize sbytes; + + sbytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); + bytes = sbytes; + success = (sbytes >= 0); + } + + if (g_task_return_error_if_cancelled (task)) + return; + + /* If we are cancelled, just return immediately. */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)) + { + g_task_return_int (task, 0); + return; + } + + /* If this error is for an old connection (that should be closed already), + * then just give up immediately with a CLOSED error. + */ + if (self->connection && + g_io_stream_get_input_stream (G_IO_STREAM (self->connection)) != G_INPUT_STREAM (source_object)) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CLOSED, + "Error on old connection, ignoring."); + return; + } + + if (!success || bytes == 0) + { + /* We accept it if someone tries to read twice and just return that error. */ + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) + { + if (self->connection) + { + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + g_clear_object (&self->connection); + } + } + + if (error) + { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + else + { + // g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data"); + return; + } + } + + g_task_return_int (task, bytes); +} + +void +fp_device_virtual_listener_read (FpDeviceVirtualListener *self, + gboolean all, + void *buffer, + gsize count, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + GInputStream *stream; + + g_return_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self)); + + task = g_task_new (self, self->cancellable, callback, user_data); + g_object_set_data (G_OBJECT (task), "all", GINT_TO_POINTER (all)); + + if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection))) + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED, + "Listener not connected to any stream"); + return; + } + + stream = g_io_stream_get_input_stream (G_IO_STREAM (self->connection)); + if (all) + { + g_input_stream_read_all_async (stream, buffer, count, + G_PRIORITY_DEFAULT, + self->cancellable, + on_stream_read_cb, + g_steal_pointer (&task)); + } + else + { + g_input_stream_read_async (stream, buffer, count, + G_PRIORITY_DEFAULT, + self->cancellable, + on_stream_read_cb, + g_steal_pointer (&task)); + } +} + +gsize +fp_device_virtual_listener_read_finish (FpDeviceVirtualListener *self, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, self), 0); + + return g_task_propagate_int (G_TASK (result), error); +} + +gboolean +fp_device_virtual_listener_write_sync (FpDeviceVirtualListener *self, + const char *buffer, + gsize count, + GError **error) +{ + if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection))) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED, + "Listener not connected to any stream"); + return FALSE; + } + + return g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (self->connection)), + buffer, + count, + NULL, + self->cancellable, + error); +} diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h new file mode 100644 index 00000000..6049d66b --- /dev/null +++ b/libfprint/drivers/virtual-device-private.h @@ -0,0 +1,93 @@ +/* + * Virtual driver for "simple" device debugging + * + * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2020 Bastien Nocera + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a virtual driver to debug the non-image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to registered programmatically. + * Using this, it is possible to test libfprint and fprintd. + */ + +#include + +#include "fpi-device.h" + +#define MAX_LINE_LEN 1024 + +G_DECLARE_FINAL_TYPE (FpDeviceVirtualListener, fp_device_virtual_listener, FP, DEVICE_VIRTUAL_LISTENER, GSocketListener) + +typedef void (*FpDeviceVirtualListenerConnectionCb) (FpDeviceVirtualListener *listener, + gpointer user_data); + +FpDeviceVirtualListener * fp_device_virtual_listener_new (void); + +gboolean fp_device_virtual_listener_start (FpDeviceVirtualListener *listener, + const char *address, + GCancellable *cancellable, + FpDeviceVirtualListenerConnectionCb cb, + gpointer user_data, + GError **error); + +gboolean fp_device_virtual_listener_connection_close (FpDeviceVirtualListener *listener); + +void fp_device_virtual_listener_read (FpDeviceVirtualListener *listener, + gboolean all, + void *buffer, + gsize count, + GAsyncReadyCallback callback, + gpointer user_data); +gsize fp_device_virtual_listener_read_finish (FpDeviceVirtualListener *listener, + GAsyncResult *result, + GError **error); + +gboolean fp_device_virtual_listener_write_sync (FpDeviceVirtualListener *self, + const char *buffer, + gsize count, + GError **error); + + +struct _FpDeviceVirtualDevice +{ + FpDevice parent; + + FpDeviceVirtualListener *listener; + GCancellable *cancellable; + + char recv_buf[MAX_LINE_LEN]; + + GPtrArray *pending_commands; + + GHashTable *prints_storage; +}; + +/* Not really final here, but we can do this to share the FpDeviceVirtualDevice + * contents without having to use a shared private struct instead. */ +G_DECLARE_FINAL_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP, DEVICE_VIRTUAL_DEVICE, FpDevice) + +struct _FpDeviceVirtualDeviceStorage +{ + FpDeviceVirtualDevice parent; +}; + +G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, FP, DEVICE_VIRTUAL_DEVICE_STORAGE, FpDeviceVirtualDevice) + + +char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error); diff --git a/libfprint/drivers/virtual-image.c b/libfprint/drivers/virtual-image.c index d4c7cc54..6b0043fe 100644 --- a/libfprint/drivers/virtual-image.c +++ b/libfprint/drivers/virtual-image.c @@ -29,36 +29,27 @@ #include "fpi-log.h" +#include "virtual-device-private.h" + #include "../fpi-image.h" #include "../fpi-image-device.h" -#include -#include -#include - struct _FpDeviceVirtualImage { - FpImageDevice parent; + FpImageDevice parent; - GSocketListener *listener; - GSocketConnection *connection; - GCancellable *listen_cancellable; - GCancellable *cancellable; + FpDeviceVirtualListener *listener; + GCancellable *cancellable; - gint socket_fd; - gint client_fd; - - gboolean automatic_finger; - FpImage *recv_img; - gint recv_img_hdr[2]; + gboolean automatic_finger; + FpImage *recv_img; + gint recv_img_hdr[2]; }; G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVICE_VIRTUAL_IMAGE, FpImageDevice) G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE) -static void start_listen (FpDeviceVirtualImage *dev); -static void recv_image (FpDeviceVirtualImage *dev, - GInputStream *stream); +static void recv_image (FpDeviceVirtualImage *self); static void recv_image_img_recv_cb (GObject *source_object, @@ -66,35 +57,20 @@ recv_image_img_recv_cb (GObject *source_object, gpointer user_data) { g_autoptr(GError) error = NULL; + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object); FpDeviceVirtualImage *self; FpImageDevice *device; - gboolean success; - gsize bytes = 0; + gsize bytes; - success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error); + bytes = fp_device_virtual_listener_read_finish (listener, res, &error); - /* Can't use self if the operation was cancelled. */ - if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (!bytes || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED)) return; self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); device = FP_IMAGE_DEVICE (self); - /* Consider success if we received the right amount of data, otherwise - * an error must have happened. */ - if (bytes < self->recv_img->width * self->recv_img->height) - { - if (!success) - g_warning ("Error receiving image data: %s", error->message); - else - g_warning ("Error receiving image data: end of stream before all data was read"); - - self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); - return; - } - if (self->automatic_finger) fpi_image_device_report_finger_status (device, TRUE); fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img)); @@ -102,7 +78,7 @@ recv_image_img_recv_cb (GObject *source_object, fpi_image_device_report_finger_status (device, FALSE); /* And, listen for more images from the same client. */ - recv_image (self, G_INPUT_STREAM (source_object)); + recv_image (self); } static void @@ -112,37 +88,30 @@ recv_image_hdr_recv_cb (GObject *source_object, { g_autoptr(GError) error = NULL; FpDeviceVirtualImage *self; - gboolean success; + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object); gsize bytes; - success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error); + bytes = fp_device_virtual_listener_read_finish (listener, res, &error); - if (!success || bytes != sizeof (self->recv_img_hdr)) + if (error) { - if (!success) - { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || - g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)) - return; - g_warning ("Error receiving header for image data: %s", error->message); - } - else if (bytes != 0) - { - g_warning ("Received incomplete header before end of stream."); - } + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) + return; - self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); + g_warning ("Error receiving header for image data: %s", error->message); return; } + if (!bytes) + return; + self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000) { g_warning ("Image header suggests an unrealistically large image, disconnecting client."); - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); + fp_device_virtual_listener_connection_close (listener); } if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0) @@ -178,153 +147,80 @@ recv_image_hdr_recv_cb (GObject *source_object, default: /* disconnect client, it didn't play fair */ - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); + fp_device_virtual_listener_connection_close (listener); } /* And, listen for more images from the same client. */ - recv_image (self, G_INPUT_STREAM (source_object)); + recv_image (self); return; } self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]); g_debug ("image data: %p", self->recv_img->data); - g_input_stream_read_all_async (G_INPUT_STREAM (source_object), - (guint8 *) self->recv_img->data, - self->recv_img->width * self->recv_img->height, - G_PRIORITY_DEFAULT, - self->cancellable, - recv_image_img_recv_cb, - self); + fp_device_virtual_listener_read (listener, + TRUE, + (guint8 *) self->recv_img->data, + self->recv_img->width * self->recv_img->height, + recv_image_img_recv_cb, + self); } static void -recv_image (FpDeviceVirtualImage *self, GInputStream *stream) +recv_image (FpDeviceVirtualImage *self) { + fp_device_virtual_listener_read (self->listener, + TRUE, + self->recv_img_hdr, + sizeof (self->recv_img_hdr), + recv_image_hdr_recv_cb, + self); +} + +static void +on_listener_connected (FpDeviceVirtualListener *listener, + gpointer user_data) +{ + FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); FpiImageDeviceState state; - g_object_get (self, "fpi-image-device-state", &state, NULL); + self->automatic_finger = TRUE; - g_debug ("Starting image receive (if active), state is: %i", state); + g_object_get (self, + "fpi-image-device-state", &state, + NULL); + /* Only read if we are in AWAIT_FINGER_* or CAPTURE states */ + if (state <= FPI_IMAGE_DEVICE_STATE_DEACTIVATING) + return; - /* Only register if the state is active. */ - if (state >= FPI_IMAGE_DEVICE_STATE_IDLE) - { - g_input_stream_read_all_async (stream, - self->recv_img_hdr, - sizeof (self->recv_img_hdr), - G_PRIORITY_DEFAULT, - self->cancellable, - recv_image_hdr_recv_cb, - self); - } -} - -static void -new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) -{ - g_autoptr(GError) error = NULL; - GSocketConnection *connection; - GInputStream *stream; - FpDeviceVirtualImage *dev = user_data; - - connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object), - res, - NULL, - &error); - if (!connection) - { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - g_warning ("Error accepting a new connection: %s", error->message); - start_listen (dev); - } - - /* Always accept further connections (but we disconnect them immediately - * if we already have a connection). */ - start_listen (dev); - - if (dev->connection) - { - /* We may not have noticed that the stream was closed, - * if the device is deactivated. - * Cancel any ongoing operation on the old connection. */ - g_cancellable_cancel (dev->cancellable); - g_clear_object (&dev->cancellable); - dev->cancellable = g_cancellable_new (); - - g_clear_object (&dev->connection); - } - - if (dev->connection) - { - g_warning ("Rejecting new connection"); - g_io_stream_close (G_IO_STREAM (connection), NULL, NULL); - g_object_unref (connection); - return; - } - - dev->connection = connection; - dev->automatic_finger = TRUE; - stream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); - - fp_dbg ("Got a new connection!"); - recv_image (dev, stream); -} - -static void -start_listen (FpDeviceVirtualImage *dev) -{ - g_socket_listener_accept_async (dev->listener, - dev->listen_cancellable, - new_connection_cb, - dev); + recv_image (self); } static void dev_init (FpImageDevice *dev) { g_autoptr(GError) error = NULL; - g_autoptr(GSocketListener) listener = NULL; + g_autoptr(FpDeviceVirtualListener) listener = NULL; + g_autoptr(GCancellable) cancellable = NULL; FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); - const char *env; - g_autoptr(GSocketAddress) addr = NULL; G_DEBUG_HERE (); - self->client_fd = -1; + listener = fp_device_virtual_listener_new (); + cancellable = g_cancellable_new (); - env = fpi_device_get_virtual_env (FP_DEVICE (self)); - - listener = g_socket_listener_new (); - g_socket_listener_set_backlog (listener, 1); - - /* Remove any left over socket. */ - g_unlink (env); - - addr = g_unix_socket_address_new (env); - - if (!g_socket_listener_add_address (listener, - addr, - G_SOCKET_TYPE_STREAM, - G_SOCKET_PROTOCOL_DEFAULT, - NULL, - NULL, - &error)) + if (!fp_device_virtual_listener_start (listener, + fpi_device_get_virtual_env (FP_DEVICE (self)), + cancellable, + on_listener_connected, + self, + &error)) { - g_warning ("Could not listen on unix socket: %s", error->message); - - fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), g_steal_pointer (&error)); - + fpi_image_device_open_complete (dev, g_steal_pointer (&error)); return; } self->listener = g_steal_pointer (&listener); - self->cancellable = g_cancellable_new (); - self->listen_cancellable = g_cancellable_new (); - - start_listen (self); + self->cancellable = g_steal_pointer (&cancellable); /* Delay result to open up the possibility of testing race conditions. */ fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_open_complete, NULL, NULL); @@ -338,11 +234,8 @@ dev_deinit (FpImageDevice *dev) G_DEBUG_HERE (); g_cancellable_cancel (self->cancellable); - g_cancellable_cancel (self->listen_cancellable); g_clear_object (&self->cancellable); - g_clear_object (&self->listen_cancellable); g_clear_object (&self->listener); - g_clear_object (&self->connection); /* Delay result to open up the possibility of testing race conditions. */ fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_close_complete, NULL, NULL); @@ -353,23 +246,16 @@ dev_activate (FpImageDevice *dev) { FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); - fpi_image_device_activate_complete (dev, NULL); + /* Start reading (again). */ + recv_image (self); - if (self->connection) - recv_image (self, g_io_stream_get_input_stream (G_IO_STREAM (self->connection))); + fpi_image_device_activate_complete (dev, NULL); } static void dev_deactivate (FpImageDevice *dev) { - FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); - - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - self->cancellable = g_cancellable_new (); - - /* XXX: Need to wait for the operation to be cancelled. */ - fpi_device_add_timeout (FP_DEVICE (dev), 10, (FpTimeoutFunc) fpi_image_device_deactivate_complete, NULL, NULL); + fpi_image_device_deactivate_complete (dev, NULL); } static void diff --git a/libfprint/meson.build b/libfprint/meson.build index 110c4582..5309391a 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -155,6 +155,9 @@ foreach driver: drivers if driver == 'virtual_image' drivers_sources += [ 'drivers/virtual-image.c' ] endif + if driver.startswith('virtual_') + drivers_sources += [ 'drivers/virtual-device-listener.c' ] + endif if driver == 'synaptics' drivers_sources += [ 'drivers/synaptics/synaptics.c', From 3f7a638eed88e24ed221bd3b08def3951a80e651 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 15:59:07 +0100 Subject: [PATCH 034/103] virtual-device: Add non-image mock devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two variants one with storage and identify support and the other without storage. It implements the following commands: * INSERT id * REMOVE id * SCAN id * ERROR error-code * LIST (returns saved print) The INSERT/REMOVE/LIST commands are only available in the storage driver. The SCAN command emulates presenting a finger. These commands can be send ahead of time, and will be queued and processed when appropriate. i.e. for INSERT/REMOVE that is immediately when possible, for SCAN/ERROR processing is delayed. The LIST command is always processed immediately. Note that only a single command can be send per socket connection and the command must be send in a single message. The socket will be closed after the command has been processed. Co-authored-by: Bastien Nocera Co-authored-by: Marco Trevisan (Treviño) --- libfprint/drivers/virtual-device-storage.c | 181 +++++++++++ libfprint/drivers/virtual-device.c | 331 +++++++++++++++++++++ libfprint/meson.build | 6 + meson.build | 6 +- tests/meson.build | 6 +- tests/test-utils.c | 2 + tests/test-utils.h | 2 + 7 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 libfprint/drivers/virtual-device-storage.c create mode 100644 libfprint/drivers/virtual-device.c diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c new file mode 100644 index 00000000..aae0f33e --- /dev/null +++ b/libfprint/drivers/virtual-device-storage.c @@ -0,0 +1,181 @@ +/* + * Virtual driver for "simple" device debugging with storage + * + * Copyright (C) 2020 Bastien Nocera + * Copyright (C) 2020 Marco Trevisan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a virtual driver to debug the non-image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to registered programmatically. + * Using this, it is possible to test libfprint and fprintd. + */ + +#define FP_COMPONENT "virtual_device_storage" + +#include "virtual-device-private.h" +#include "fpi-log.h" + +G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, fpi_device_virtual_device_get_type ()) + +static void +dev_identify (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + GPtrArray *prints; + GError *error = NULL; + g_autofree char *scan_id = NULL; + + fpi_device_get_identify_data (dev, &prints); + + scan_id = process_cmds (self, TRUE, &error); + + if (scan_id) + { + GVariant *data = NULL; + FpPrint *new_scan; + FpPrint *match = NULL; + guint idx; + + new_scan = fp_print_new (dev); + fpi_print_set_type (new_scan, FPI_PRINT_RAW); + if (self->prints_storage) + fpi_print_set_device_stored (new_scan, TRUE); + data = g_variant_new_string (scan_id); + g_object_set (new_scan, "fpi-data", data, NULL); + + if (g_ptr_array_find_with_equal_func (prints, + new_scan, + (GEqualFunc) fp_print_equal, + &idx)) + match = g_ptr_array_index (prints, idx); + + fpi_device_identify_report (dev, + match, + new_scan, + NULL); + } + + fpi_device_identify_complete (dev, error); +} + +struct ListData +{ + FpDevice *dev; + GPtrArray *res; +}; + +static void +dev_list_insert_print (gpointer key, + gpointer value, + gpointer user_data) +{ + struct ListData *data = user_data; + FpPrint *print = fp_print_new (data->dev); + GVariant *var = NULL; + + fpi_print_fill_from_user_id (print, key); + fpi_print_set_type (print, FPI_PRINT_RAW); + var = g_variant_new_string (key); + g_object_set (print, "fpi-data", var, NULL); + g_object_ref_sink (print); + + g_ptr_array_add (data->res, print); +} + +static void +dev_list (FpDevice *dev) +{ + g_autoptr(GPtrArray) prints_list = NULL; + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); + struct ListData data; + + process_cmds (vdev, FALSE, NULL); + + prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), NULL); + data.dev = dev; + data.res = prints_list; + + g_hash_table_foreach (vdev->prints_storage, dev_list_insert_print, &data); + + fpi_device_list_complete (dev, g_steal_pointer (&prints_list), NULL); +} + +static void +dev_delete (FpDevice *dev) +{ + g_autoptr(GVariant) data = NULL; + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); + FpPrint *print = NULL; + const char *id = NULL; + + process_cmds (vdev, FALSE, NULL); + + fpi_device_get_delete_data (dev, &print); + + g_object_get (print, "fpi-data", &data, NULL); + if (data == NULL) + { + fpi_device_delete_complete (dev, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + + id = g_variant_get_string (data, NULL); + + fp_dbg ("Deleting print %s for user %s", + id, + fp_print_get_username (print)); + + if (g_hash_table_remove (vdev->prints_storage, id)) + fpi_device_delete_complete (dev, NULL); + else + fpi_device_delete_complete (dev, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); +} + +static void +fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self) +{ + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (self); + + vdev->prints_storage = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); +} + +static const FpIdEntry driver_ids[] = { + { .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE" }, + { .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT" }, + { .virtual_envvar = NULL } +}; + +static void +fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + + dev_class->id = FP_COMPONENT; + dev_class->full_name = "Virtual device with storage and identification for debugging"; + dev_class->id_table = driver_ids; + + dev_class->identify = dev_identify; + dev_class->list = dev_list; + dev_class->delete = dev_delete; +} diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c new file mode 100644 index 00000000..5c143b19 --- /dev/null +++ b/libfprint/drivers/virtual-device.c @@ -0,0 +1,331 @@ +/* + * Virtual driver for "simple" device debugging + * + * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2020 Bastien Nocera + * Copyright (C) 2020 Marco Trevisan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a virtual driver to debug the non-image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to registered programmatically. + * Using this, it is possible to test libfprint and fprintd. + */ + +#define FP_COMPONENT "virtual_device" + +#include "virtual-device-private.h" +#include "fpi-log.h" + +G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) + +#define INSERT_CMD_PREFIX "INSERT " +#define REMOVE_CMD_PREFIX "REMOVE " +#define SCAN_CMD_PREFIX "SCAN " +#define ERROR_CMD_PREFIX "ERROR " + +#define LIST_CMD "LIST" + +char * +process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error) +{ + while (self->pending_commands->len > 0) + { + gchar *cmd = g_ptr_array_index (self->pending_commands, 0); + + /* These are always processed. */ + if (g_str_has_prefix (cmd, INSERT_CMD_PREFIX)) + { + g_assert (self->prints_storage); + g_hash_table_add (self->prints_storage, + g_strdup (cmd + strlen (INSERT_CMD_PREFIX))); + + g_ptr_array_remove_index (self->pending_commands, 0); + continue; + } + else if (g_str_has_prefix (cmd, REMOVE_CMD_PREFIX)) + { + g_assert (self->prints_storage); + if (!g_hash_table_remove (self->prints_storage, + cmd + strlen (REMOVE_CMD_PREFIX))) + g_warning ("ID %s was not found in storage", cmd + strlen (REMOVE_CMD_PREFIX)); + + g_ptr_array_remove_index (self->pending_commands, 0); + continue; + } + + /* If we are not scanning, then we have to stop here. */ + if (!scan) + break; + + if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX)) + { + char *res = g_strdup (cmd + strlen (SCAN_CMD_PREFIX)); + + g_ptr_array_remove_index (self->pending_commands, 0); + return res; + } + else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX)) + { + g_propagate_error (error, + fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); + + g_ptr_array_remove_index (self->pending_commands, 0); + return NULL; + } + else + { + g_warning ("Could not process command: %s", cmd); + g_ptr_array_remove_index (self->pending_commands, 0); + } + } + + /* No commands left, throw a timeout error. */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands left that can be run!"); + return NULL; +} + +static void +write_key_to_listener (void *key, void *val, void *user_data) +{ + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (user_data); + + if (!fp_device_virtual_listener_write_sync (listener, key, strlen (key), NULL) || + !fp_device_virtual_listener_write_sync (listener, "\n", 1, NULL)) + g_warning ("Error writing reply to LIST command"); +} + +static void +recv_instruction_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object); + gsize bytes; + + bytes = fp_device_virtual_listener_read_finish (listener, res, &error); + fp_dbg ("Got instructions of length %ld\n", bytes); + + if (error) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_warning ("Error receiving instruction data: %s", error->message); + return; + } + + if (bytes > 0) + { + FpDeviceVirtualDevice *self; + g_autofree char *cmd = NULL; + + self = FP_DEVICE_VIRTUAL_DEVICE (user_data); + + cmd = g_strndup (self->recv_buf, bytes); + + if (g_str_has_prefix (cmd, LIST_CMD)) + { + if (self->prints_storage) + g_hash_table_foreach (self->prints_storage, write_key_to_listener, listener); + } + else + { + g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); + } + } + + fp_device_virtual_listener_connection_close (listener); +} + +static void +recv_instruction (FpDeviceVirtualDevice *self) +{ + fp_device_virtual_listener_read (self->listener, + FALSE, + self->recv_buf, + sizeof (self->recv_buf), + recv_instruction_cb, + self); +} + +static void +on_listener_connected (FpDeviceVirtualListener *listener, + gpointer user_data) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (user_data); + + recv_instruction (self); +} + +static void +dev_init (FpDevice *dev) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GCancellable) cancellable = NULL; + g_autoptr(FpDeviceVirtualListener) listener = NULL; + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + + G_DEBUG_HERE (); + + listener = fp_device_virtual_listener_new (); + cancellable = g_cancellable_new (); + + if (!fp_device_virtual_listener_start (listener, + fpi_device_get_virtual_env (FP_DEVICE (self)), + cancellable, + on_listener_connected, + self, + &error)) + { + fpi_device_open_complete (dev, g_steal_pointer (&error)); + return; + } + + self->listener = g_steal_pointer (&listener); + self->cancellable = g_steal_pointer (&cancellable); + + fpi_device_open_complete (dev, NULL); +} + +static void +dev_verify (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + FpPrint *print; + GError *error = NULL; + g_autofree char *scan_id = NULL; + + fpi_device_get_verify_data (dev, &print); + + scan_id = process_cmds (self, TRUE, &error); + + if (scan_id) + { + GVariant *data = NULL; + FpPrint *new_scan; + gboolean success; + + g_debug ("Virtual device scanned print %s", scan_id); + + new_scan = fp_print_new (dev); + fpi_print_set_type (new_scan, FPI_PRINT_RAW); + if (self->prints_storage) + fpi_print_set_device_stored (new_scan, TRUE); + data = g_variant_new_string (scan_id); + g_object_set (new_scan, "fpi-data", data, NULL); + + success = fp_print_equal (print, new_scan); + + fpi_device_verify_report (dev, + success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, + new_scan, + NULL); + } + else + { + g_debug ("Virtual device scann failed with error: %s", error->message); + } + + fpi_device_verify_complete (dev, error); +} + +static void +dev_enroll (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + GError *error = NULL; + FpPrint *print = NULL; + g_autofree char *id = NULL; + + fpi_device_get_enroll_data (dev, &print); + + id = process_cmds (self, TRUE, &error); + + if (id) + { + GVariant *data; + + fpi_print_set_type (print, FPI_PRINT_RAW); + data = g_variant_new_string (id); + g_object_set (print, "fpi-data", data, NULL); + + if (self->prints_storage) + { + g_hash_table_add (self->prints_storage, g_strdup (id)); + fpi_print_set_device_stored (print, TRUE); + } + + fpi_device_enroll_complete (dev, g_object_ref (print), error); + } + else + { + fpi_device_enroll_complete (dev, NULL, error); + } +} + +static void +dev_deinit (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_object (&self->listener); + g_clear_object (&self->listener); + + fpi_device_close_complete (dev, NULL); +} + +static void +fpi_device_virtual_device_finalize (GObject *object) +{ + G_DEBUG_HERE (); +} + +static void +fpi_device_virtual_device_init (FpDeviceVirtualDevice *self) +{ + self->pending_commands = g_ptr_array_new_with_free_func (g_free); +} + +static const FpIdEntry driver_ids[] = { + { .virtual_envvar = "FP_VIRTUAL_DEVICE", }, + { .virtual_envvar = NULL } +}; + +static void +fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = fpi_device_virtual_device_finalize; + + dev_class->id = FP_COMPONENT; + dev_class->full_name = "Virtual device for debugging"; + dev_class->type = FP_DEVICE_TYPE_VIRTUAL; + dev_class->id_table = driver_ids; + dev_class->nr_enroll_stages = 5; + + dev_class->open = dev_init; + dev_class->close = dev_deinit; + dev_class->verify = dev_verify; + dev_class->enroll = dev_enroll; +} diff --git a/libfprint/meson.build b/libfprint/meson.build index 5309391a..0090ece3 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -155,6 +155,12 @@ foreach driver: drivers if driver == 'virtual_image' drivers_sources += [ 'drivers/virtual-image.c' ] endif + if driver == 'virtual_device' + drivers_sources += [ 'drivers/virtual-device.c' ] + endif + if driver == 'virtual_device_storage' + drivers_sources += [ 'drivers/virtual-device-storage.c' ] + endif if driver.startswith('virtual_') drivers_sources += [ 'drivers/virtual-device-listener.c' ] endif diff --git a/meson.build b/meson.build index 8dc852aa..2b6fe846 100644 --- a/meson.build +++ b/meson.build @@ -88,7 +88,11 @@ cairo_dep = dependency('cairo', required: false) # Drivers drivers = get_option('drivers').split(',') -virtual_drivers = [ 'virtual_image' ] +virtual_drivers = [ + 'virtual_image', + 'virtual_device', + 'virtual_device_storage', +] default_drivers = [ 'upektc_img', diff --git a/tests/meson.build b/tests/meson.build index 8e24980b..61decd5d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -13,7 +13,11 @@ envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint')) envs.set('FP_DEVICE_EMULATION', '1') # Set a colon-separated list of native drivers we enable in tests -envs.set('FP_DRIVERS_WHITELIST', 'virtual_image') +envs.set('FP_DRIVERS_WHITELIST', ':'.join([ + 'virtual_image', + 'virtual_device', + 'virtual_device_storage', +])) envs.set('NO_AT_BRIDGE', '1') diff --git a/tests/test-utils.c b/tests/test-utils.c index 1c1be17f..a14d1cae 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -29,6 +29,8 @@ struct const char *device_id; } devtype_vars[FPT_NUM_VIRTUAL_DEVICE_TYPES] = { { "FP_VIRTUAL_IMAGE", "virtual_image", "virtual_image" }, /* FPT_VIRTUAL_DEVICE_IMAGE */ + { "FP_VIRTUAL_DEVICE", "virtual_device", "virtual_device" }, /* FPT_VIRTUAL_DEVICE_NONIMAGE */ + { "FP_VIRTUAL_DEVICE_STORAGE", "virtual_device_storage", "virtual_device_storage" } /* FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE */ }; static FptVirtualDeviceType global_devtype; diff --git a/tests/test-utils.h b/tests/test-utils.h index e4e4c30e..7419a4c7 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -21,6 +21,8 @@ typedef enum { FPT_VIRTUAL_DEVICE_IMAGE = 0, + FPT_VIRTUAL_DEVICE_NONIMAGE, + FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE, FPT_NUM_VIRTUAL_DEVICE_TYPES } FptVirtualDeviceType; From 8ded064e65f7aca1d5910582826519409fbd28ee Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 16:23:18 +0100 Subject: [PATCH 035/103] tests: Add test based on the new virtual devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marco Trevisan (Treviño) --- tests/meson.build | 70 +++++++----- tests/virtual-device.py | 247 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+), 31 deletions(-) create mode 100644 tests/virtual-device.py diff --git a/tests/meson.build b/tests/meson.build index 61decd5d..f15bd8ad 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -33,43 +33,51 @@ drivers_tests = [ if get_option('introspection') envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint')) + virtual_devices_tests = [ + 'virtual-image', + 'virtual-device', + ] - if 'virtual_image' in drivers - python3 = find_program('python3') - unittest_inspector = find_program('unittest_inspector.py') - base_args = files('virtual-image.py') - suite = [] + unittest_inspector = find_program('unittest_inspector.py') - r = run_command(unittest_inspector, files('virtual-image.py')) - unit_tests = r.stdout().strip().split('\n') + foreach vdtest: virtual_devices_tests + driver_name = '_'.join(vdtest.split('-')) + if driver_name in drivers + python3 = find_program('python3') + base_args = files(vdtest + '.py') + suite = ['virtual-driver'] - if r.returncode() == 0 and unit_tests.length() > 0 - suite += 'virtual-image' - else - unit_tests = ['virtual-image'] - endif + r = run_command(unittest_inspector, files(vdtest + '.py')) + unit_tests = r.stdout().strip().split('\n') - foreach ut: unit_tests - ut_suite = suite - ut_args = base_args - if unit_tests.length() > 1 - ut_args += ut - ut_suite += ut.split('.')[0] + if r.returncode() == 0 and unit_tests.length() > 0 + suite += vdtest + else + unit_tests = [vdtest] endif - test(ut, - python3, - args: ut_args, - suite: ut_suite, - depends: libfprint_typelib, - env: envs, + + foreach ut: unit_tests + ut_suite = suite + ut_args = base_args + if unit_tests.length() > 1 + ut_args += ut + ut_suite += ut.split('.')[0] + endif + test(ut, + python3, + args: ut_args, + suite: ut_suite, + depends: libfprint_typelib, + env: envs, + ) + endforeach + else + test(vdtest, + find_program('sh'), + args: ['-c', 'exit 77'] ) - endforeach - else - test('virtual-image', - find_program('sh'), - args: ['-c', 'exit 77'] - ) - endif + endif + endforeach foreach driver_test: drivers_tests driver_envs = envs diff --git a/tests/virtual-device.py b/tests/virtual-device.py new file mode 100644 index 00000000..8d15bfd4 --- /dev/null +++ b/tests/virtual-device.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 + +import sys +try: + import gi + import re + import os + + from gi.repository import GLib, Gio + + import unittest + import socket + import struct + import subprocess + import shutil + import glob + import tempfile +except Exception as e: + print("Missing dependencies: %s" % str(e)) + sys.exit(77) + +FPrint = None + +# Re-run the test with the passed wrapper if set +wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER') +if wrapper: + wrap_cmd = wrapper.split(' ') + [sys.executable, os.path.abspath(__file__)] + \ + sys.argv[1:] + os.unsetenv('LIBFPRINT_TEST_WRAPPER') + sys.exit(subprocess.check_call(wrap_cmd)) + +ctx = GLib.main_context_default() + + +class Connection: + + def __init__(self, addr): + self.addr = addr + + def __enter__(self): + self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.con.connect(self.addr) + return self.con + + def __exit__(self, exc_type, exc_val, exc_tb): + self.con.close() + del self.con + +class VirtualDevice(unittest.TestCase): + + @classmethod + def setUpClass(cls): + unittest.TestCase.setUpClass() + cls.tmpdir = tempfile.mkdtemp(prefix='libfprint-') + + driver_name = cls.driver_name if hasattr(cls, 'driver_name') else None + if not driver_name: + driver_name = re.compile(r'(? Date: Thu, 21 Jan 2021 00:57:43 +0100 Subject: [PATCH 036/103] build: Ensure we process the data dir --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 2b6fe846..0a65754e 100644 --- a/meson.build +++ b/meson.build @@ -240,6 +240,7 @@ if get_option('gtk-examples') subdir('demo') endif +subdir('data') subdir('tests') pkgconfig = import('pkgconfig') From 2f6adce2fa95d95778054ed6f1ce8615e63cc794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 01:17:02 +0100 Subject: [PATCH 037/103] data: Keep using versioned libname for hwdb file --- data/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/meson.build b/data/meson.build index 975c1c3f..99adf5d7 100644 --- a/data/meson.build +++ b/data/meson.build @@ -3,7 +3,7 @@ if get_option('udev_rules') # ninja -C libfprint/sync-udev-hwdb install_data('autosuspend.hwdb', - rename: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), + rename: '60-autosuspend-@0@.hwdb'.format(versioned_libname), install_dir: udev_hwdb_dir, ) endif From 63bfaf4f608e31ae7798fe5cc8a58a1913444b3d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 21 Jan 2021 12:22:08 +0100 Subject: [PATCH 038/103] tests: Add trailing newline to busname/devname sysfs attributes libusb 1.0.24 now expects busnum/devnum to be \n terminated. Update the device descriptions accordingly. https://github.com/martinpitt/umockdev/issues/115 --- tests/aes3500/device | 16 ++++++++-------- tests/elan/device | 12 ++++++------ tests/goodixmoc/device | 8 ++++---- tests/synaptics/device | 4 ++-- tests/vfs0050/device | 4 ++-- tests/vfs301/device | 12 ++++++------ tests/vfs5011/device | 4 ++-- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/aes3500/device b/tests/aes3500/device index 4a2a9037..c662cc8f 100644 --- a/tests/aes3500/device +++ b/tests/aes3500/device @@ -35,11 +35,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0000 A: bmAttributes=80 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000 A: dev=189:259 -A: devnum=4 +A: devnum=4\n A: devpath=1.1.3 L: driver=../../../../../../../../../../bus/usb/drivers/usb A: idProduct=5731 @@ -106,11 +106,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=9100 A: bmAttributes=e0 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C A: dev=189:258 -A: devnum=3 +A: devnum=3\n A: devpath=1.1 L: driver=../../../../../../../../../bus/usb/drivers/usb A: idProduct=0006 @@ -186,11 +186,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=9100 A: bmAttributes=e0 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C A: dev=189:257 -A: devnum=2 +A: devnum=2\n A: devpath=1 L: driver=../../../../../../../../bus/usb/drivers/usb A: idProduct=0006 @@ -270,11 +270,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0415 A: bmAttributes=e0 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C A: dev=189:256 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/elan/device b/tests/elan/device index 7374dc24..6e1e421e 100644 --- a/tests/elan/device +++ b/tests/elan/device @@ -36,11 +36,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0140 A: bmAttributes=80 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001 A: dev=189:93 -A: devnum=94 +A: devnum=94\n A: devpath=4.4 L: driver=../../../../../../bus/usb/drivers/usb A: idProduct=0c26 @@ -107,11 +107,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=5284 A: bmAttributes=e0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=1201100209000140EF17181084520102000109021900010100E0000904000001090000000705810301000C A: dev=189:82 -A: devnum=83 +A: devnum=83\n A: devpath=4 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=1018 @@ -189,11 +189,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0503 A: bmAttributes=e0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12010002090001406B1D020003050302010109021900010100E0000904000001090000000705810304000C A: dev=189:0 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/goodixmoc/device b/tests/goodixmoc/device index 627c9dc0..b008eb2b 100644 --- a/tests/goodixmoc/device +++ b/tests/goodixmoc/device @@ -37,11 +37,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0100 A: bmAttributes=a0 -A: busnum=1 +A: busnum=1\n A: configuration=UIDCBEE4D7B_XXXX_MOC_B0 H: descriptors=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000 A: dev=189:2 -A: devnum=3 +A: devnum=3\n A: devpath=8 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=60a2 @@ -125,11 +125,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0504 A: bmAttributes=e0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C A: dev=189:0 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/synaptics/device b/tests/synaptics/device index 6da3eea7..87c4bed2 100644 --- a/tests/synaptics/device +++ b/tests/synaptics/device @@ -34,11 +34,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0000 A: bmAttributes=a0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004 A: dev=189:69 -A: devnum=70 +A: devnum=70\n A: devpath=1 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=00bd diff --git a/tests/vfs0050/device b/tests/vfs0050/device index 1bea50a0..b66be4ba 100644 --- a/tests/vfs0050/device +++ b/tests/vfs0050/device @@ -38,11 +38,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0060 A: bmAttributes=a0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12011001FF10FF088A13500060000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 A: dev=189:3 -A: devnum=4 +A: devnum=4\n A: devpath=9 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=0050 diff --git a/tests/vfs301/device b/tests/vfs301/device index 635f7951..26d3b57e 100644 --- a/tests/vfs301/device +++ b/tests/vfs301/device @@ -37,11 +37,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0c90 A: bmAttributes=a0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12011001FF10FF088A130500900C0000000109022700010100A0320904000003FF000000070501024000000705810240000007058202400000 A: dev=189:132 -A: devnum=5 +A: devnum=5\n A: devpath=1.3 L: driver=../../../../../../bus/usb/drivers/usb A: idProduct=0005 @@ -120,11 +120,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0000 A: bmAttributes=e0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810302000C A: dev=189:129 -A: devnum=2 +A: devnum=2\n A: devpath=1 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=0020 @@ -204,11 +204,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0504 A: bmAttributes=e0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12010002090000406B1D020004050302010109021900010100E0000904000001090000000705810304000C A: dev=189:128 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/vfs5011/device b/tests/vfs5011/device index 4c75e596..e39a74fa 100644 --- a/tests/vfs5011/device +++ b/tests/vfs5011/device @@ -35,11 +35,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0078 A: bmAttributes=a0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 A: dev=189:144 -A: devnum=17 +A: devnum=17\n A: devpath=6 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=0017 From 170924ee4fc2143ed1569545b39d4bfb4857f378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 15:01:55 +0100 Subject: [PATCH 039/103] test-generated-hwdb: Just use diff to compare for being more informative --- tests/test-generated-hwdb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-generated-hwdb.sh b/tests/test-generated-hwdb.sh index 34209cb5..87c08bbf 100755 --- a/tests/test-generated-hwdb.sh +++ b/tests/test-generated-hwdb.sh @@ -15,7 +15,7 @@ if [ "$UDEV_HWDB_CHECK_CONTENTS" != 1 ]; then exit 77 fi -if ! cmp "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then +if ! diff -u "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then echo "E: Autosuspend file needs to be re-generated!" echo " ninja -C $MESON_BUILD_ROOT libfprint/sync-udev-hwdb" exit 1 From 57f836a0f65fcc7f69c082b71d33afcb6c6fd1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 15:26:31 +0100 Subject: [PATCH 040/103] udev-hwdb: Generate autosuspend list using a sorted list --- data/autosuspend.hwdb | 142 +++++++++++++++--------------- libfprint/fprint-list-udev-hwdb.c | 10 +++ 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb index 7a78068c..63e40cf7 100644 --- a/data/autosuspend.hwdb +++ b/data/autosuspend.hwdb @@ -1,27 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # This file has been generated using fprint-list-udev-hwdb with all drivers enabled -# Supported by libfprint driver upektc_img -usb:v147Ep2016* -usb:v147Ep2020* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs5011 -usb:v138Ap0010* -usb:v138Ap0011* -usb:v138Ap0015* -usb:v138Ap0017* -usb:v138Ap0018* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver aes3500 -usb:v08FFp5731* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver aes4000 -usb:v5501p08FF* - ID_AUTOSUSPEND=1 - # Supported by libfprint driver aes1610 usb:v08FFp1600* ID_AUTOSUSPEND=1 @@ -46,6 +25,16 @@ usb:v08FFp168E* usb:v08FFp168F* ID_AUTOSUSPEND=1 +# Supported by libfprint driver aes2501 +usb:v08FFp2500* +usb:v08FFp2580* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2550 +usb:v08FFp2550* +usb:v08FFp2810* + ID_AUTOSUSPEND=1 + # Supported by libfprint driver aes2660 usb:v08FFp2660* usb:v08FFp2680* @@ -67,46 +56,12 @@ usb:v08FFp268F* usb:v08FFp2691* ID_AUTOSUSPEND=1 -# Supported by libfprint driver aes2501 -usb:v08FFp2500* -usb:v08FFp2580* +# Supported by libfprint driver aes3500 +usb:v08FFp5731* ID_AUTOSUSPEND=1 -# Supported by libfprint driver aes2550 -usb:v08FFp2550* -usb:v08FFp2810* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs101 -usb:v138Ap0001* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs301 -usb:v138Ap0005* -usb:v138Ap0008* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs0050 -usb:v138Ap0050* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver etes603 -usb:v1C7Ap0603* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vcom5s -usb:v061Ap0110* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver synaptics -usb:v06CBp00BD* -usb:v06CBp00E9* -usb:v06CBp00DF* -usb:v06CBp00F9* -usb:v06CBp00FC* -usb:v06CBp00C2* -usb:v06CBp00C9* -usb:v06CBp00E7* +# Supported by libfprint driver aes4000 +usb:v5501p08FF* ID_AUTOSUSPEND=1 # Supported by libfprint driver elan @@ -167,6 +122,44 @@ usb:v04F3p0C42* usb:v04F3p0C4D* ID_AUTOSUSPEND=1 +# Supported by libfprint driver etes603 +usb:v1C7Ap0603* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver goodixmoc +usb:v27C6p5840* +usb:v27C6p6496* +usb:v27C6p60A2* +usb:v27C6p63AC* +usb:v27C6p639C* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver synaptics +usb:v06CBp00BD* +usb:v06CBp00E9* +usb:v06CBp00DF* +usb:v06CBp00F9* +usb:v06CBp00FC* +usb:v06CBp00C2* +usb:v06CBp00C9* +usb:v06CBp00E7* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upeksonly +usb:v147Ep2016* +usb:v147Ep1000* +usb:v147Ep1001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upektc +usb:v0483p2015* +usb:v147Ep3001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upektc_img +usb:v147Ep2020* + ID_AUTOSUSPEND=1 + # Supported by libfprint driver uru4000 usb:v045Ep00BC* usb:v045Ep00BD* @@ -176,22 +169,29 @@ usb:v05BAp0008* usb:v05BAp000A* ID_AUTOSUSPEND=1 -# Supported by libfprint driver upektc -usb:v0483p2015* -usb:v147Ep3001* +# Supported by libfprint driver vcom5s +usb:v061Ap0110* ID_AUTOSUSPEND=1 -# Supported by libfprint driver upeksonly -usb:v147Ep1000* -usb:v147Ep1001* +# Supported by libfprint driver vfs0050 +usb:v138Ap0050* ID_AUTOSUSPEND=1 -# Supported by libfprint driver goodixmoc -usb:v27C6p5840* -usb:v27C6p6496* -usb:v27C6p60A2* -usb:v27C6p63AC* -usb:v27C6p639C* +# Supported by libfprint driver vfs101 +usb:v138Ap0001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs301 +usb:v138Ap0005* +usb:v138Ap0008* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs5011 +usb:v138Ap0010* +usb:v138Ap0011* +usb:v138Ap0015* +usb:v138Ap0017* +usb:v138Ap0018* ID_AUTOSUSPEND=1 # Known unsupported devices diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index 6f533fb6..2a78e81f 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -164,6 +164,15 @@ print_driver (const FpDeviceClass *cls) g_print (" ID_AUTOSUSPEND=1\n"); } +static int +driver_compare (gconstpointer p1, gconstpointer p2) +{ + g_autoptr(FpDeviceClass) cls1 = g_type_class_ref (*(GType *) p1); + g_autoptr(FpDeviceClass) cls2 = g_type_class_ref (*(GType *) p2); + + return g_strcmp0 (cls1->id, cls2->id); +} + int main (int argc, char **argv) { @@ -178,6 +187,7 @@ main (int argc, char **argv) program_name); printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_array_sort (drivers, driver_compare); for (i = 0; i < drivers->len; i++) { From 3b83157e9b9b642dfb7f6ab177ec9e601e6e6a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 15:34:36 +0100 Subject: [PATCH 041/103] build: Skip the hwdb test if not all drivers are really enabled --- meson.build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meson.build b/meson.build index 0a65754e..cbeab4d6 100644 --- a/meson.build +++ b/meson.build @@ -184,6 +184,10 @@ foreach driver: drivers endif endforeach +if default_drivers_are_enabled and supported_drivers != drivers + default_drivers_are_enabled = false +endif + # Export the drivers' types to the core code drivers_type_list = [] drivers_type_func = [] From e0c41c544413ade2e8577bf2c667ed405d8ace6f Mon Sep 17 00:00:00 2001 From: fengqiangguo Date: Wed, 16 Dec 2020 10:31:46 +0800 Subject: [PATCH 042/103] goodixmoc: Fix some big/little endian support issues Goodix driver is not working fine in BigEndian architectures. This commit fixes some of these issues. Related: #236 --- libfprint/drivers/goodixmoc/goodix.c | 2 +- libfprint/drivers/goodixmoc/goodix_proto.c | 85 ++++++++++++++-------- libfprint/drivers/goodixmoc/goodix_proto.h | 4 +- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index af64d814..82913d73 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -127,7 +127,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer, } gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc); - if(crc32_calc != *(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)) + if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len))) { fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, diff --git a/libfprint/drivers/goodixmoc/goodix_proto.c b/libfprint/drivers/goodixmoc/goodix_proto.c index e30d23df..962fd6e7 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.c +++ b/libfprint/drivers/goodixmoc/goodix_proto.c @@ -141,8 +141,11 @@ crc32_update (gf_crc32_context *ctx, const uint8_t *message, uint32_t n_bytes) static void crc32_final (gf_crc32_context *ctx, uint8_t *md) { + uint32_t crc = 0; + ctx->crc = (REFLECT_REMAINDER (ctx->crc) ^ FINAL_XOR_VALUE); - memcpy (md, &ctx->crc, 4); + crc = GUINT32_TO_LE (ctx->crc); + memcpy (md, &crc, 4); } uint8_t @@ -184,7 +187,7 @@ init_pack_header ( pheader->cmd1 = LOBYTE (cmd); pheader->packagenum = packagenum; pheader->reserved = dump_seq++; - pheader->len = len + PACKAGE_CRC_SIZE; + pheader->len = GUINT16_TO_LE (len + PACKAGE_CRC_SIZE); pheader->crc8 = gx_proto_crc8_calc ((uint8_t *) pheader, 6); pheader->rev_crc8 = ~pheader->crc8; } @@ -224,14 +227,14 @@ gx_proto_parse_header ( { if (!buffer || !pheader) return -1; - if (buffer_len < PACKAGE_HEADER_SIZE) + if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE) return -1; memcpy (pheader, buffer, sizeof (pack_header)); - - pheader->len = GUINT16_FROM_LE ( *(uint16_t *) (buffer + 4)); + pheader->len = GUINT16_FROM_LE (pheader->len); + if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE) + return -1; pheader->len -= PACKAGE_CRC_SIZE; - return 0; } @@ -248,7 +251,7 @@ gx_proto_parse_fingerid ( if (!template || !fid_buffer) return -1; - if (fid_buffer_size < 70) + if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t)) return -1; buffer = fid_buffer; @@ -256,28 +259,30 @@ 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], 32); - Offset += 32; - - memcpy (template->tid, &buffer[Offset], 32); - Offset += 32; // Offset == 68 - + memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid)); + Offset += sizeof (template->accountid); + memcpy (template->tid, &buffer[Offset], sizeof (template->tid)); + Offset += sizeof (template->tid); // Offset == 68 template->payload.size = buffer[Offset++]; - memset (template->payload.data, 0, 56); + if (template->payload.size > sizeof (template->payload.data)) + return -1; + memset (template->payload.data, 0, template->payload.size); memcpy (template->payload.data, &buffer[Offset], template->payload.size); return 0; } int -gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_cmd_response_t presp) +gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp) { - uint32_t offset = 0; + uint16_t offset = 0; uint8_t *fingerlist = NULL; if (!buffer || !presp) @@ -289,6 +294,8 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c { case RESPONSE_PACKAGE_CMD: { + if (buffer_len < sizeof (gxfp_parse_msg_t) + 1) + return -1; presp->parse_msg.ack_cmd = buffer[1]; } break; @@ -296,32 +303,46 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c case MOC_CMD0_UPDATE_CONFIG: { presp->finger_config.status = buffer[0]; - presp->finger_config.max_stored_prints = buffer[2]; + if (buffer_len >= 3) + presp->finger_config.max_stored_prints = buffer[2]; + else + /* to compatiable old version firmware */ + presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM; + } break; case MOC_CMD0_COMMITENROLLMENT: case MOC_CMD0_DELETETEMPLATE: + /* just check result */ break; case MOC_CMD0_GET_VERSION: + if (buffer_len < sizeof (gxfp_version_info_t) + 1) + return -1; memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t)); break; case MOC_CMD0_CAPTURE_DATA: if (LOBYTE (cmd) == MOC_CMD1_DEFAULT) { + if (buffer_len < sizeof (gxfp_capturedata_t) + 1) + return -1; presp->capture_data_resp.img_quality = buffer[1]; presp->capture_data_resp.img_coverage = buffer[2]; } break; case MOC_CMD0_ENROLL_INIT: + if (buffer_len < sizeof (gxfp_enroll_init_t) + 1) + return -1; if (presp->result == GX_SUCCESS) memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE); break; case MOC_CMD0_ENROLL: + if (buffer_len < sizeof (gxfp_enroll_update_t)) + return -1; presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true; presp->enroll_update.img_overlay = buffer[1]; presp->enroll_update.img_preoverlay = buffer[2]; @@ -331,7 +352,11 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true; if (presp->check_duplicate_resp.duplicate) { - uint16_t tid_size = GUINT16_FROM_LE (*(buffer + 1)); + 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) + return -1; memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size); } break; @@ -339,18 +364,16 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c case MOC_CMD0_GETFINGERLIST: if (presp->result != GX_SUCCESS) break; + if (buffer_len < 2) + return -1; presp->finger_list_resp.finger_num = buffer[1]; - if (presp->finger_list_resp.finger_num > FP_MAX_FINGERNUM) - { - presp->finger_list_resp.finger_num = 0; - presp->result = GX_ERROR_NO_AVAILABLE_SPACE; - break; - } fingerlist = buffer + 2; for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++) { - uint16_t fingerid_length = GUINT16_FROM_LE (*(fingerlist + offset)); + uint16_t fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset)); offset += 2; + if (buffer_len < fingerid_length + offset + 2) + return -1; if (gx_proto_parse_fingerid (fingerlist + offset, fingerid_length, &presp->finger_list_resp.finger_list[num]) != 0) @@ -372,14 +395,16 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_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) + return -1; offset += 1; - presp->verify.rejectdetail = GUINT16_FROM_LE (*(buffer + offset)); + presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset)); offset += 2; - score = GUINT32_FROM_LE (*(buffer + offset)); + score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset)); offset += 4; - study = GUINT16_FROM_LE (*(buffer + offset)); + study = buffer[offset]; offset += 1; - fingerid_size = GUINT16_FROM_LE (*(buffer + offset)); + fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset)); offset += 2; if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0) { diff --git a/libfprint/drivers/goodixmoc/goodix_proto.h b/libfprint/drivers/goodixmoc/goodix_proto.h index 53eea046..e98e4e44 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.h +++ b/libfprint/drivers/goodixmoc/goodix_proto.h @@ -89,7 +89,7 @@ typedef struct _gxfp_version_info uint8_t interface[GX_VERSION_LEN]; uint8_t protocol[GX_VERSION_LEN]; uint8_t flashVersion[GX_VERSION_LEN]; - uint8_t reserved[62]; + uint8_t reserved[38]; } gxfp_version_info_t, *pgxfp_version_info_t; @@ -225,7 +225,7 @@ int gx_proto_parse_header (uint8_t *buffer, int gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, - uint32_t buffer_len, + uint16_t buffer_len, pgxfp_cmd_response_t presponse); int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig); From 89890dbd1f00289ed8ae2bcff41edc993a33b457 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 21 Jan 2021 17:36:41 +0100 Subject: [PATCH 043/103] build: Explicitly mark libfprint as a shared library While meson suggests to always use 'library' this leads to some unwanted behaviors when it comes to generate pkg-config files for it, as they will include `Libs.Private` / `Required.private` fields that should not be really part of a shared library as libfprint is meant to be used. --- libfprint/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index 0090ece3..66c4c747 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -267,7 +267,7 @@ libfprint_drivers = static_library('fprint-drivers', mapfile = files('libfprint.ver') vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0]) -libfprint = library(versioned_libname.split('lib')[1], +libfprint = shared_library(versioned_libname.split('lib')[1], sources: [ fp_enums, libfprint_sources, From ce9527d2cb86d0243dc42ad2153c8693f95d8d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 01:15:19 +0100 Subject: [PATCH 044/103] virtual-device: Wait for delayed commands to be processed This allows to mimick the image device better, so that we can start an operation and send the commands within some delay. --- libfprint/drivers/virtual-device-private.h | 4 ++ libfprint/drivers/virtual-device-storage.c | 6 +- libfprint/drivers/virtual-device.c | 80 +++++++++++++++++++--- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index 6049d66b..5f2371d8 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -76,6 +76,8 @@ struct _FpDeviceVirtualDevice GPtrArray *pending_commands; GHashTable *prints_storage; + + guint wait_command_id; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice @@ -91,3 +93,5 @@ G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_st char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error); +gboolean should_wait_for_command (FpDeviceVirtualDevice *self, + GError *error); diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index aae0f33e..26d44970 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -36,14 +36,16 @@ G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, static void dev_identify (FpDevice *dev) { + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); GPtrArray *prints; - GError *error = NULL; g_autofree char *scan_id = NULL; fpi_device_get_identify_data (dev, &prints); scan_id = process_cmds (self, TRUE, &error); + if (should_wait_for_command (self, error)) + return; if (scan_id) { @@ -71,7 +73,7 @@ dev_identify (FpDevice *dev) NULL); } - fpi_device_identify_complete (dev, error); + fpi_device_identify_complete (dev, g_steal_pointer (&error)); } struct ListData diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 5c143b19..1c131299 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -41,8 +41,34 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define LIST_CMD "LIST" +static void +maybe_continue_current_action (FpDeviceVirtualDevice *self) +{ + FpDevice *dev = FP_DEVICE (self); + + switch (fpi_device_get_current_action (dev)) + { + case FPI_DEVICE_ACTION_ENROLL: + FP_DEVICE_GET_CLASS (self)->enroll (dev); + break; + + case FPI_DEVICE_ACTION_VERIFY: + FP_DEVICE_GET_CLASS (self)->verify (dev); + break; + + case FPI_DEVICE_ACTION_IDENTIFY: + FP_DEVICE_GET_CLASS (self)->identify (dev); + break; + + default: + break; + } +} + char * -process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error) +process_cmds (FpDeviceVirtualDevice * self, + gboolean scan, + GError * *error) { while (self->pending_commands->len > 0) { @@ -96,7 +122,7 @@ process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error) } /* No commands left, throw a timeout error. */ - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands left that can be run!"); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No commands left that can be run!"); return NULL; } @@ -120,7 +146,7 @@ recv_instruction_cb (GObject *source_object, gsize bytes; bytes = fp_device_virtual_listener_read_finish (listener, res, &error); - fp_dbg ("Got instructions of length %ld\n", bytes); + fp_dbg ("Got instructions of length %ld", bytes); if (error) { @@ -139,6 +165,7 @@ recv_instruction_cb (GObject *source_object, self = FP_DEVICE_VIRTUAL_DEVICE (user_data); cmd = g_strndup (self->recv_buf, bytes); + fp_dbg ("Received command %s", cmd); if (g_str_has_prefix (cmd, LIST_CMD)) { @@ -148,6 +175,9 @@ recv_instruction_cb (GObject *source_object, else { g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); + g_clear_handle_id (&self->wait_command_id, g_source_remove); + + maybe_continue_current_action (self); } } @@ -204,17 +234,46 @@ dev_init (FpDevice *dev) fpi_device_open_complete (dev, NULL); } +static gboolean +wait_for_command_timeout (gpointer data) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data); + GError *error = NULL; + + self->wait_command_id = 0; + error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!"); + fpi_device_action_error (FP_DEVICE (self), error); + + return FALSE; +} + +gboolean +should_wait_for_command (FpDeviceVirtualDevice *self, + GError *error) +{ + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + return FALSE; + + if (self->wait_command_id) + return FALSE; + + self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self); + return TRUE; +} + static void dev_verify (FpDevice *dev) { + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); FpPrint *print; - GError *error = NULL; g_autofree char *scan_id = NULL; fpi_device_get_verify_data (dev, &print); scan_id = process_cmds (self, TRUE, &error); + if (should_wait_for_command (self, error)) + return; if (scan_id) { @@ -240,23 +299,25 @@ dev_verify (FpDevice *dev) } else { - g_debug ("Virtual device scann failed with error: %s", error->message); + g_debug ("Virtual device scan failed with error: %s", error->message); } - fpi_device_verify_complete (dev, error); + fpi_device_verify_complete (dev, g_steal_pointer (&error)); } static void dev_enroll (FpDevice *dev) { + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); - GError *error = NULL; FpPrint *print = NULL; g_autofree char *id = NULL; fpi_device_get_enroll_data (dev, &print); id = process_cmds (self, TRUE, &error); + if (should_wait_for_command (self, error)) + return; if (id) { @@ -272,11 +333,11 @@ dev_enroll (FpDevice *dev) fpi_print_set_device_stored (print, TRUE); } - fpi_device_enroll_complete (dev, g_object_ref (print), error); + fpi_device_enroll_complete (dev, g_object_ref (print), NULL); } else { - fpi_device_enroll_complete (dev, NULL, error); + fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); } } @@ -285,6 +346,7 @@ dev_deinit (FpDevice *dev) { FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + g_clear_handle_id (&self->wait_command_id, g_source_remove); g_cancellable_cancel (self->cancellable); g_clear_object (&self->cancellable); g_clear_object (&self->listener); From 546f35132c74469aaaa5211cdd5b8c5ed26a3eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 16:38:24 +0100 Subject: [PATCH 045/103] tests/virtual-device: Use FPrint.DeviceError values to send errors --- tests/virtual-device.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 8d15bfd4..21da790f 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -131,8 +131,8 @@ class VirtualDevice(unittest.TestCase): if isinstance(scan_nick, str): self.send_command('SCAN', scan_nick) - else: - self.send_command('ERROR', scan_nick) + elif isinstance(scan_nick, FPrint.DeviceError): + self.send_command('ERROR', int(scan_nick)) def verify_cb(dev, res): try: @@ -184,7 +184,7 @@ class VirtualDevice(unittest.TestCase): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) with self.assertRaisesRegex(GLib.Error, r"An unspecified error occurred"): - self.check_verify(matching, 0, match=False) + self.check_verify(matching, FPrint.DeviceError.GENERAL, match=False) class VirtualDeviceStorage(VirtualDevice): From f0443ba2f3e7f4e936dd48e03fe32050e58aeea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 17:16:48 +0100 Subject: [PATCH 046/103] virtual-device: Add support for reporting device Retry "errors" --- libfprint/drivers/virtual-device-storage.c | 4 ++++ libfprint/drivers/virtual-device.c | 17 ++++++++++++++++- tests/virtual-device.py | 8 +++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 26d44970..1a925951 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -72,6 +72,10 @@ dev_identify (FpDevice *dev) new_scan, NULL); } + else if (error && error->domain == FP_DEVICE_RETRY) + { + fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error)); + } fpi_device_identify_complete (dev, g_steal_pointer (&error)); } diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 1c131299..cf397c5a 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -38,6 +38,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define REMOVE_CMD_PREFIX "REMOVE " #define SCAN_CMD_PREFIX "SCAN " #define ERROR_CMD_PREFIX "ERROR " +#define RETRY_CMD_PREFIX "RETRY " #define LIST_CMD "LIST" @@ -111,6 +112,14 @@ process_cmds (FpDeviceVirtualDevice * self, g_propagate_error (error, fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); + g_ptr_array_remove_index (self->pending_commands, 0); + return NULL; + } + else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX)) + { + g_propagate_error (error, + fpi_device_retry_new (g_ascii_strtoull (cmd + strlen (RETRY_CMD_PREFIX), NULL, 10))); + g_ptr_array_remove_index (self->pending_commands, 0); return NULL; } @@ -302,6 +311,9 @@ dev_verify (FpDevice *dev) g_debug ("Virtual device scan failed with error: %s", error->message); } + if (error && error->domain == FP_DEVICE_RETRY) + fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error)); + fpi_device_verify_complete (dev, g_steal_pointer (&error)); } @@ -337,7 +349,10 @@ dev_enroll (FpDevice *dev) } else { - fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); + if (error && error->domain == FP_DEVICE_RETRY) + fpi_device_enroll_progress (dev, 0, NULL, g_steal_pointer (&error)); + else + fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); } } diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 21da790f..3a514f57 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -93,7 +93,7 @@ class VirtualDevice(unittest.TestCase): super().tearDown() def send_command(self, command, *args): - self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR']) + self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -133,6 +133,8 @@ class VirtualDevice(unittest.TestCase): self.send_command('SCAN', scan_nick) elif isinstance(scan_nick, FPrint.DeviceError): self.send_command('ERROR', int(scan_nick)) + elif isinstance(scan_nick, FPrint.DeviceRetry): + self.send_command('RETRY', int(scan_nick)) def verify_cb(dev, res): try: @@ -186,6 +188,10 @@ class VirtualDevice(unittest.TestCase): with self.assertRaisesRegex(GLib.Error, r"An unspecified error occurred"): self.check_verify(matching, FPrint.DeviceError.GENERAL, match=False) + def test_enroll_verify_retry(self): + with self.assertRaisesRegex(GLib.GError, 'too short'): + self.check_verify(FPrint.Print.new(self.dev), + FPrint.DeviceRetry.TOO_SHORT, match=False) class VirtualDeviceStorage(VirtualDevice): From 50f522583e951272fa72b11a85fe235d648abc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 01:28:20 +0100 Subject: [PATCH 047/103] virtual-device: Set needed finger state on enroll and verify --- libfprint/drivers/virtual-device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index cf397c5a..68f5c3d1 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -279,6 +279,7 @@ dev_verify (FpDevice *dev) g_autofree char *scan_id = NULL; fpi_device_get_verify_data (dev, &print); + fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NEEDED); scan_id = process_cmds (self, TRUE, &error); if (should_wait_for_command (self, error)) @@ -325,6 +326,7 @@ dev_enroll (FpDevice *dev) FpPrint *print = NULL; g_autofree char *id = NULL; + fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NEEDED); fpi_device_get_enroll_data (dev, &print); id = process_cmds (self, TRUE, &error); From 43d0dfdd8f352c567f1ef816e0c85bfe329018ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 04:34:50 +0100 Subject: [PATCH 048/103] virtual-device-storage: Set needed finger state on enroll and verify --- libfprint/drivers/virtual-device-storage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 1a925951..355f4953 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -42,6 +42,7 @@ dev_identify (FpDevice *dev) g_autofree char *scan_id = NULL; fpi_device_get_identify_data (dev, &prints); + fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NEEDED); scan_id = process_cmds (self, TRUE, &error); if (should_wait_for_command (self, error)) From 3d6fb15b5c65b38ebea8796fc50afcfd2788fc81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 01:28:38 +0100 Subject: [PATCH 049/103] virtual-device: Add API to change current finger status --- libfprint/drivers/virtual-device.c | 15 ++++++++++ tests/virtual-device.py | 47 ++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 68f5c3d1..cf36d0d3 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -39,6 +39,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define SCAN_CMD_PREFIX "SCAN " #define ERROR_CMD_PREFIX "ERROR " #define RETRY_CMD_PREFIX "RETRY " +#define FINGER_CMD_PREFIX "FINGER " #define LIST_CMD "LIST" @@ -75,6 +76,8 @@ process_cmds (FpDeviceVirtualDevice * self, { gchar *cmd = g_ptr_array_index (self->pending_commands, 0); + g_debug ("Processing command %s", cmd); + /* These are always processed. */ if (g_str_has_prefix (cmd, INSERT_CMD_PREFIX)) { @@ -123,6 +126,18 @@ process_cmds (FpDeviceVirtualDevice * self, g_ptr_array_remove_index (self->pending_commands, 0); return NULL; } + else if (g_str_has_prefix (cmd, FINGER_CMD_PREFIX)) + { + gboolean finger_present; + + finger_present = g_ascii_strtoull (cmd + strlen (FINGER_CMD_PREFIX), NULL, 10) != 0; + fpi_device_report_finger_status_changes (FP_DEVICE (self), + finger_present ? FP_FINGER_STATUS_PRESENT : FP_FINGER_STATUS_NONE, + finger_present ? FP_FINGER_STATUS_NONE : FP_FINGER_STATUS_PRESENT); + + g_ptr_array_remove_index (self->pending_commands, 0); + continue; + } else { g_warning ("Could not process command: %s", cmd); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 3a514f57..570e3bef 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -93,7 +93,8 @@ class VirtualDevice(unittest.TestCase): super().tearDown() def send_command(self, command, *args): - self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY']) + self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', + 'FINGER']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -102,6 +103,16 @@ class VirtualDevice(unittest.TestCase): while ctx.pending(): ctx.iteration(False) + def send_finger_report(self, has_finger, iterate=True): + self.send_command('FINGER', 1 if has_finger else 0) + + if iterate: + expected = (FPrint.FingerStatusFlags.PRESENT if has_finger + else ~FPrint.FingerStatusFlags.PRESENT) + + while not (self.dev.get_finger_status() & expected): + ctx.iteration(True) + def enroll_print(self, nick, finger, username='testuser'): self._enrolled = None @@ -109,6 +120,8 @@ class VirtualDevice(unittest.TestCase): print("Enroll done") self._enrolled = dev.enroll_finish(res) + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + self.send_command('SCAN', nick) template = FPrint.Print.new(self.dev) @@ -119,6 +132,12 @@ class VirtualDevice(unittest.TestCase): while self._enrolled is None: ctx.iteration(False) + if not self._enrolled: + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED) + + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + self.assertEqual(self._enrolled.get_device_stored(), self.dev.has_storage()) @@ -181,7 +200,6 @@ class VirtualDevice(unittest.TestCase): self.check_verify(matching, 'not-testprint', match=False) - def test_enroll_verify_error(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) @@ -193,6 +211,31 @@ class VirtualDevice(unittest.TestCase): self.check_verify(FPrint.Print.new(self.dev), FPrint.DeviceRetry.TOO_SHORT, match=False) + def test_finger_status(self): + cancellable = Gio.Cancellable() + got_cb = False + + def verify_cb(dev, res): + nonlocal got_cb + got_cb = True + + self.dev.verify(FPrint.Print.new(self.dev), callback=verify_cb, cancellable=cancellable) + while not self.dev.get_finger_status() is FPrint.FingerStatusFlags.NEEDED: + ctx.iteration(True) + + self.send_finger_report(True) + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED | FPrint.FingerStatusFlags.PRESENT) + + self.send_finger_report(False) + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED) + + cancellable.cancel() + while not got_cb: + ctx.iteration(True) + + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + class VirtualDeviceStorage(VirtualDevice): def cleanup_device_storage(self): From e8886dbc6b88badfd1311ba8c5105f6ab1917640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 02:02:05 +0100 Subject: [PATCH 050/103] virtual-device: Support all the configured enrolling stages --- libfprint/drivers/virtual-device-private.h | 1 + libfprint/drivers/virtual-device.c | 49 +++++++++++++++++----- tests/virtual-device.py | 12 +++++- 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index 5f2371d8..08d6736b 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -78,6 +78,7 @@ struct _FpDeviceVirtualDevice GHashTable *prints_storage; guint wait_command_id; + guint enroll_stages_passed; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index cf36d0d3..5f193d6b 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -352,24 +352,53 @@ dev_enroll (FpDevice *dev) { GVariant *data; - fpi_print_set_type (print, FPI_PRINT_RAW); - data = g_variant_new_string (id); - g_object_set (print, "fpi-data", data, NULL); - - if (self->prints_storage) + if (self->enroll_stages_passed == 0) { - g_hash_table_add (self->prints_storage, g_strdup (id)); - fpi_print_set_device_stored (print, TRUE); + fpi_print_set_type (print, FPI_PRINT_RAW); + data = g_variant_new_string (id); + g_object_set (print, "fpi-data", data, NULL); + } + else + { + gboolean changed; + + g_object_get (print, "fpi-data", &data, NULL); + changed = !g_str_equal (id, g_variant_get_string (data, NULL)); + g_variant_unref (data); + + if (changed) + { + g_set_error (&error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL, "ID Mismatch"); + fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, error); + return; + } } - fpi_device_enroll_complete (dev, g_object_ref (print), NULL); + self->enroll_stages_passed++; + fpi_device_enroll_progress (dev, self->enroll_stages_passed, print, NULL); + if (self->enroll_stages_passed == FP_DEVICE_GET_CLASS (self)->nr_enroll_stages) + { + if (self->prints_storage) + { + fpi_print_set_device_stored (print, TRUE); + g_hash_table_add (self->prints_storage, g_strdup (id)); + } + + fpi_device_enroll_complete (dev, g_object_ref (print), NULL); + self->enroll_stages_passed = 0; + } } else { if (error && error->domain == FP_DEVICE_RETRY) - fpi_device_enroll_progress (dev, 0, NULL, g_steal_pointer (&error)); + { + fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, g_steal_pointer (&error)); + } else - fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); + { + self->enroll_stages_passed = 0; + fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); + } } } diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 570e3bef..f2399bd5 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -120,6 +120,10 @@ class VirtualDevice(unittest.TestCase): print("Enroll done") self._enrolled = dev.enroll_finish(res) + def progress_cb(dev, stage, pnt, data, error): + self._enroll_stage = stage + self._enroll_progress_error = error + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) self.send_command('SCAN', nick) @@ -128,14 +132,20 @@ class VirtualDevice(unittest.TestCase): template.set_finger(finger) template.set_username(username) - self.dev.enroll(template, None, None, tuple(), done_cb) + stage = 1 + self.dev.enroll(template, callback=done_cb, progress_cb=progress_cb) while self._enrolled is None: ctx.iteration(False) if not self._enrolled: self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED) + self.assertEqual(self._enroll_stage, stage) + self.assertLess(self._enroll_stage, self.dev.get_nr_enroll_stages()) + self.send_command('SCAN', nick) + stage += 1 + self.assertEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) self.assertEqual(self._enrolled.get_device_stored(), From a291d17f26edc9728db021d941138d50a824c971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 02:03:20 +0100 Subject: [PATCH 051/103] virtual-device: Properly cleanup the virtual devices data Ensure we call the parent finalize function and cleanup local data --- libfprint/drivers/virtual-device-storage.c | 13 +++++++++++++ libfprint/drivers/virtual-device.c | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 355f4953..c948a6b4 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -167,6 +167,16 @@ fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self) NULL); } +static void +fpi_device_virtual_device_storage_finalize (GObject *object) +{ + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (object); + + G_DEBUG_HERE (); + g_clear_pointer (&vdev->prints_storage, g_hash_table_destroy); + G_OBJECT_CLASS (fpi_device_virtual_device_storage_parent_class)->finalize (object); +} + static const FpIdEntry driver_ids[] = { { .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE" }, { .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT" }, @@ -177,6 +187,9 @@ static void fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass *klass) { FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = fpi_device_virtual_device_storage_finalize; dev_class->id = FP_COMPONENT; dev_class->full_name = "Virtual device with storage and identification for debugging"; diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 5f193d6b..03453b07 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -419,7 +419,11 @@ dev_deinit (FpDevice *dev) static void fpi_device_virtual_device_finalize (GObject *object) { + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (object); + G_DEBUG_HERE (); + g_clear_pointer (&self->pending_commands, g_ptr_array_unref); + G_OBJECT_CLASS (fpi_device_virtual_device_parent_class)->finalize (object); } static void From 665de7813be6c3e3fc4e52b1f5ae9c0e0b0b2d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 15:38:46 +0100 Subject: [PATCH 052/103] fpi-device: Ensure we're receiving a valid number of enroll stages --- libfprint/fpi-device.c | 1 + tests/test-fpi-device.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index de511920..f59d430d 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -216,6 +216,7 @@ fpi_device_set_nr_enroll_stages (FpDevice *device, FpDevicePrivate *priv = fp_device_get_instance_private (device); g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (enroll_stages > 0); priv->nr_enroll_stages = enroll_stages; g_object_notify (G_OBJECT (device), "nr-enroll-stages"); diff --git a/tests/test-fpi-device.c b/tests/test-fpi-device.c index 57e5cf91..ab5a108c 100644 --- a/tests/test-fpi-device.c +++ b/tests/test-fpi-device.c @@ -433,7 +433,7 @@ test_driver_set_nr_enroll_stages (void) g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_autoptr(GParamSpec) pspec = NULL; FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device); - int expected_stages = g_random_int_range (G_MININT32, G_MAXINT32); + int expected_stages = g_random_int_range (1, G_MAXINT32); g_signal_connect (device, "notify::nr-enroll-stages", G_CALLBACK (on_device_notify), NULL); fpi_device_set_nr_enroll_stages (device, expected_stages); @@ -443,6 +443,18 @@ test_driver_set_nr_enroll_stages (void) pspec = g_steal_pointer (&fake_dev->user_data); g_assert_cmpstr (pspec->name, ==, "nr-enroll-stages"); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*enroll_stages > 0*"); + fpi_device_set_nr_enroll_stages (device, 0); + g_assert_cmpint (fp_device_get_nr_enroll_stages (device), ==, expected_stages); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*enroll_stages > 0*"); + fpi_device_set_nr_enroll_stages (device, -2); + g_assert_cmpint (fp_device_get_nr_enroll_stages (device), ==, expected_stages); + g_test_assert_expected_messages (); } static void From 56bcf1ffdd33ed3381e9b3c87dbdc98633367af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 15:43:49 +0100 Subject: [PATCH 053/103] virtual-device: Add command to change the number of enroll stages As per this don't use the class value anymore at enroll phase, as it may differ. --- libfprint/drivers/virtual-device.c | 10 +++++++- tests/virtual-device.py | 37 +++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 03453b07..8fcff49c 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -40,6 +40,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define ERROR_CMD_PREFIX "ERROR " #define RETRY_CMD_PREFIX "RETRY " #define FINGER_CMD_PREFIX "FINGER " +#define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES " #define LIST_CMD "LIST" @@ -196,6 +197,13 @@ recv_instruction_cb (GObject *source_object, if (self->prints_storage) g_hash_table_foreach (self->prints_storage, write_key_to_listener, listener); } + else if (g_str_has_prefix (cmd, SET_ENROLL_STAGES_PREFIX)) + { + guint stages; + + stages = g_ascii_strtoull (cmd + strlen (SET_ENROLL_STAGES_PREFIX), NULL, 10); + fpi_device_set_nr_enroll_stages (FP_DEVICE (self), stages); + } else { g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); @@ -376,7 +384,7 @@ dev_enroll (FpDevice *dev) self->enroll_stages_passed++; fpi_device_enroll_progress (dev, self->enroll_stages_passed, print, NULL); - if (self->enroll_stages_passed == FP_DEVICE_GET_CLASS (self)->nr_enroll_stages) + if (self->enroll_stages_passed == fp_device_get_nr_enroll_stages (FP_DEVICE (self))) { if (self->prints_storage) { diff --git a/tests/virtual-device.py b/tests/virtual-device.py index f2399bd5..48b54946 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -94,7 +94,7 @@ class VirtualDevice(unittest.TestCase): def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', - 'FINGER']) + 'FINGER', 'SET_ENROLL_STAGES']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -145,6 +145,7 @@ class VirtualDevice(unittest.TestCase): self.send_command('SCAN', nick) stage += 1 + self.assertEqual(self._enroll_stage, stage) self.assertEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) @@ -246,6 +247,40 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + def test_change_enroll_stages(self): + notified_spec = None + def on_stage_changed(dev, spec): + nonlocal notified_spec + notified_spec = spec + + self.dev.connect('notify::nr-enroll-stages', on_stage_changed) + + notified_spec = None + self.send_command('SET_ENROLL_STAGES', 20) + self.assertEqual(self.dev.get_nr_enroll_stages(), 20) + self.assertEqual(notified_spec.name, 'nr-enroll-stages') + + notified_spec = None + self.send_command('SET_ENROLL_STAGES', 1) + self.assertEqual(self.dev.get_nr_enroll_stages(), 1) + self.assertEqual(notified_spec.name, 'nr-enroll-stages') + + GLib.test_expect_message('libfprint-device', + GLib.LogLevelFlags.LEVEL_CRITICAL, '*enroll_stages > 0*') + notified_spec = None + self.send_command('SET_ENROLL_STAGES', 0) + self.assertEqual(self.dev.get_nr_enroll_stages(), 1) + self.assertIsNone(notified_spec) + GLib.test_assert_expected_messages_internal('libfprint-device', + __file__, 0, 'test_change_enroll_stages') + + def test_quick_enroll(self): + self.send_command('SET_ENROLL_STAGES', 1) + self.assertEqual(self.dev.get_nr_enroll_stages(), 1) + matching = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) + self.assertEqual(matching.get_username(), 'testuser') + self.assertEqual(matching.get_finger(), FPrint.Finger.LEFT_LITTLE) + class VirtualDeviceStorage(VirtualDevice): def cleanup_device_storage(self): From be0b4ae2bba45e4977c80beb3df9e76005e10c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 16:33:32 +0100 Subject: [PATCH 054/103] tests/virtual-device: Trigger new scans when we got progress callback --- tests/virtual-device.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 48b54946..709641b9 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -120,10 +120,30 @@ class VirtualDevice(unittest.TestCase): print("Enroll done") self._enrolled = dev.enroll_finish(res) + self._enroll_stage = -1 def progress_cb(dev, stage, pnt, data, error): self._enroll_stage = stage self._enroll_progress_error = error + stage = 1 + def enroll_in_progress(): + if self._enroll_stage < 0 and not self._enrolled: + return True + + nonlocal stage + self.assertLessEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) + self.assertEqual(self._enroll_stage, stage) + + if self._enroll_stage < self.dev.get_nr_enroll_stages(): + self._enroll_stage = -1 + self.assertIsNone(self._enrolled) + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED) + GLib.idle_add(self.send_command, 'SCAN', nick) + stage += 1 + + return not self._enrolled + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) self.send_command('SCAN', nick) @@ -132,19 +152,10 @@ class VirtualDevice(unittest.TestCase): template.set_finger(finger) template.set_username(username) - stage = 1 self.dev.enroll(template, callback=done_cb, progress_cb=progress_cb) - while self._enrolled is None: + while enroll_in_progress(): ctx.iteration(False) - if not self._enrolled: - self.assertEqual(self.dev.get_finger_status(), - FPrint.FingerStatusFlags.NEEDED) - self.assertEqual(self._enroll_stage, stage) - self.assertLess(self._enroll_stage, self.dev.get_nr_enroll_stages()) - self.send_command('SCAN', nick) - stage += 1 - self.assertEqual(self._enroll_stage, stage) self.assertEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) From 81e53c422d987703750f8729469cdd45636834f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 17:35:29 +0100 Subject: [PATCH 055/103] virtual-device: Add support for changing the device scan type --- libfprint/drivers/virtual-device.c | 12 ++++++++++++ tests/virtual-device.py | 25 ++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 8fcff49c..ca8f885c 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -41,6 +41,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define RETRY_CMD_PREFIX "RETRY " #define FINGER_CMD_PREFIX "FINGER " #define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES " +#define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE " #define LIST_CMD "LIST" @@ -204,6 +205,17 @@ recv_instruction_cb (GObject *source_object, stages = g_ascii_strtoull (cmd + strlen (SET_ENROLL_STAGES_PREFIX), NULL, 10); fpi_device_set_nr_enroll_stages (FP_DEVICE (self), stages); } + else if (g_str_has_prefix (cmd, SET_SCAN_TYPE_PREFIX)) + { + const char *scan_type = cmd + strlen (SET_SCAN_TYPE_PREFIX); + g_autoptr(GEnumClass) scan_types = g_type_class_ref (fp_scan_type_get_type ()); + GEnumValue *value = g_enum_get_value_by_nick (scan_types, scan_type); + + if (value) + fpi_device_set_scan_type (FP_DEVICE (self), value->value); + else + g_warning ("Scan type '%s' not found", scan_type); + } else { g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 709641b9..876de661 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -94,7 +94,7 @@ class VirtualDevice(unittest.TestCase): def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', - 'FINGER', 'SET_ENROLL_STAGES']) + 'FINGER', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -292,6 +292,29 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(matching.get_username(), 'testuser') self.assertEqual(matching.get_finger(), FPrint.Finger.LEFT_LITTLE) + def test_change_scan_type(self): + notified_spec = None + def on_scan_type_changed(dev, spec): + nonlocal notified_spec + notified_spec = spec + + self.dev.connect('notify::scan-type', on_scan_type_changed) + + for scan_type in [FPrint.ScanType.PRESS, FPrint.ScanType.SWIPE]: + notified_spec = None + self.send_command('SET_SCAN_TYPE', scan_type.value_nick) + self.assertEqual(self.dev.get_scan_type(), scan_type) + self.assertEqual(notified_spec.name, 'scan-type') + + GLib.test_expect_message('libfprint-virtual_device', + GLib.LogLevelFlags.LEVEL_WARNING, '*Scan type*not found') + notified_spec = None + self.send_command('SET_SCAN_TYPE', 'eye-contact') + self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE) + self.assertIsNone(notified_spec) + GLib.test_assert_expected_messages_internal('libfprint-device', + __file__, 0, 'test_change_scan_type') + class VirtualDeviceStorage(VirtualDevice): def cleanup_device_storage(self): From dfb27222eb166a4d0776a1742940c9cdf803b7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 18:20:20 +0100 Subject: [PATCH 056/103] tests/virtual-device: Add function that figures out the command from type --- tests/virtual-device.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 876de661..b406e1a9 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -113,6 +113,26 @@ class VirtualDevice(unittest.TestCase): while not (self.dev.get_finger_status() & expected): ctx.iteration(True) + def send_error(self, error): + self.assertIsInstance(error, FPrint.DeviceError) + self.send_command('ERROR', int(error)) + + def send_retry(self, retry): + self.assertIsInstance(retry, FPrint.DeviceRetry) + self.send_command('RETRY', int(retry)) + + def send_auto(self, obj): + if isinstance(obj, FPrint.DeviceError): + self.send_error(obj) + elif isinstance(obj, FPrint.DeviceRetry): + self.send_retry(obj) + elif isinstance(obj, FPrint.FingerStatusFlags): + self.send_finger_report(obj & FPrint.FingerStatusFlags.PRESENT, iterate=False) + elif isinstance(obj, FPrint.ScanType): + self.send_command('SET_SCAN_TYPE', obj.value_nick) + else: + raise Exception('No known type found for {}'.format(obj)) + def enroll_print(self, nick, finger, username='testuser'): self._enrolled = None @@ -172,10 +192,8 @@ class VirtualDevice(unittest.TestCase): if isinstance(scan_nick, str): self.send_command('SCAN', scan_nick) - elif isinstance(scan_nick, FPrint.DeviceError): - self.send_command('ERROR', int(scan_nick)) - elif isinstance(scan_nick, FPrint.DeviceRetry): - self.send_command('RETRY', int(scan_nick)) + else: + self.send_auto(scan_nick) def verify_cb(dev, res): try: @@ -302,7 +320,7 @@ class VirtualDevice(unittest.TestCase): for scan_type in [FPrint.ScanType.PRESS, FPrint.ScanType.SWIPE]: notified_spec = None - self.send_command('SET_SCAN_TYPE', scan_type.value_nick) + self.send_auto(scan_type) self.assertEqual(self.dev.get_scan_type(), scan_type) self.assertEqual(notified_spec.name, 'scan-type') From 162a83e48461d372a5f5c31d7e662f82671d58dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 18:21:23 +0100 Subject: [PATCH 057/103] tests/virtual-device: Add ability to enroll with a retry step and test it --- tests/virtual-device.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index b406e1a9..c31de257 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -133,7 +133,7 @@ class VirtualDevice(unittest.TestCase): else: raise Exception('No known type found for {}'.format(obj)) - def enroll_print(self, nick, finger, username='testuser'): + def enroll_print(self, nick, finger, username='testuser', retry_scan=-1): self._enrolled = None def done_cb(dev, res): @@ -145,22 +145,38 @@ class VirtualDevice(unittest.TestCase): self._enroll_stage = stage self._enroll_progress_error = error - stage = 1 + self.assertLessEqual(retry_scan, self.dev.get_nr_enroll_stages()) + + retries = 1 + should_retry = retry_scan > 0 + def enroll_in_progress(): if self._enroll_stage < 0 and not self._enrolled: return True - nonlocal stage + nonlocal retries self.assertLessEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) - self.assertEqual(self._enroll_stage, stage) + if should_retry and retries > retry_scan: + self.assertEqual(self._enroll_stage, retries - 1) + else: + self.assertEqual(self._enroll_stage, retries) + + if retries == retry_scan + 1: + self.assertIsNotNone(self._enroll_progress_error) + self.assertEqual(self._enroll_progress_error.code, FPrint.DeviceRetry.TOO_SHORT) + else: + self.assertIsNone(self._enroll_progress_error) if self._enroll_stage < self.dev.get_nr_enroll_stages(): self._enroll_stage = -1 self.assertIsNone(self._enrolled) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED) - GLib.idle_add(self.send_command, 'SCAN', nick) - stage += 1 + if retry_scan == retries: + GLib.idle_add(self.send_auto, FPrint.DeviceRetry.TOO_SHORT) + else: + GLib.idle_add(self.send_command, 'SCAN', nick) + retries += 1 return not self._enrolled @@ -176,7 +192,7 @@ class VirtualDevice(unittest.TestCase): while enroll_in_progress(): ctx.iteration(False) - self.assertEqual(self._enroll_stage, stage) + self.assertEqual(self._enroll_stage, retries if not should_retry else retries - 1) self.assertEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) @@ -230,6 +246,11 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(matching.get_username(), 'testuser') self.assertEqual(matching.get_finger(), FPrint.Finger.LEFT_LITTLE) + def test_enroll_with_retry(self): + matching = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE, retry_scan=2) + self.assertEqual(matching.get_username(), 'testuser') + self.assertEqual(matching.get_finger(), FPrint.Finger.LEFT_LITTLE) + def test_enroll_verify_match(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_THUMB) From 33ffadf402617e06698665fed67daa357a579af3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 19:54:12 +0100 Subject: [PATCH 058/103] tests/virtual-device: Cleanup device storage on teardown --- tests/virtual-device.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index c31de257..44664d7d 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -356,6 +356,10 @@ class VirtualDevice(unittest.TestCase): class VirtualDeviceStorage(VirtualDevice): + def tearDown(self): + self.cleanup_device_storage() + super().tearDown() + def cleanup_device_storage(self): for print in self.dev.list_prints_sync(): self.assertTrue(self.dev.delete_print_sync(print, None)) @@ -373,17 +377,14 @@ class VirtualDeviceStorage(VirtualDevice): self.assertTrue(self.dev.has_storage()) def test_list_empty(self): - self.cleanup_device_storage() self.assertFalse(self.dev.list_prints_sync()) def test_list_populated(self): - self.cleanup_device_storage() self.send_command('INSERT', 'p1') print2 = self.enroll_print('p2', FPrint.Finger.LEFT_LITTLE) self.assertEqual({'p1', 'p2'}, {p.props.fpi_data.get_string() for p in self.dev.list_prints_sync()}) def test_list_delete(self): - self.cleanup_device_storage() p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB) l = self.dev.list_prints_sync() print(l[0]) @@ -394,7 +395,6 @@ class VirtualDeviceStorage(VirtualDevice): self.assertFalse(self.dev.list_prints_sync()) def test_list_delete_missing(self): - self.cleanup_device_storage() p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB) self.send_command('REMOVE', 'testprint') From 67cb61cc180f2636f63565b575646edd60cd9147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 24 Jan 2021 20:01:53 +0100 Subject: [PATCH 059/103] tests/virtual-device: Add identification tests Reusing most of the logic of the `check_verify` utility function --- libfprint/drivers/virtual-device-storage.c | 2 + tests/virtual-device.py | 50 +++++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index c948a6b4..1fcee3c7 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -62,6 +62,8 @@ dev_identify (FpDevice *dev) data = g_variant_new_string (scan_id); g_object_set (new_scan, "fpi-data", data, NULL); + g_debug ("Trying to identify print '%s' against a gallery of %u prints", scan_id, prints->len); + if (g_ptr_array_find_with_equal_func (prints, new_scan, (GEqualFunc) fp_print_equal, diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 44664d7d..82beaa72 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -201,10 +201,14 @@ class VirtualDevice(unittest.TestCase): return self._enrolled - def check_verify(self, p, scan_nick, match): + def check_verify(self, p, scan_nick, match, identify=False): self._verify_match = None self._verify_fp = None self._verify_error = None + self._verify_completed = False + + if identify: + self.assertTrue(self.dev.supports_identify()) if isinstance(scan_nick, str): self.send_command('SCAN', scan_nick) @@ -213,16 +217,31 @@ class VirtualDevice(unittest.TestCase): def verify_cb(dev, res): try: - self._verify_match, self._verify_fp = dev.verify_finish(res) + self._verify_match, self._verify_fp = ( + dev.identify_finish(res) if identify else dev.verify_finish(res)) except gi.repository.GLib.Error as e: self._verify_error = e - self.dev.verify(p, callback=verify_cb) - while self._verify_match is None and self._verify_error is None: + self._verify_completed = True + + if identify: + self.dev.identify(p if isinstance(p, list) else [p], callback=verify_cb) + else: + self.dev.verify(p, callback=verify_cb) + + while not self._verify_completed: ctx.iteration(True) - if match: - assert self._verify_fp.equal(p) + if identify: + if match: + self.assertIsNotNone(self._verify_match) + else: + self.assertIsNone(self._verify_match) + else: + if self._verify_fp: + self.assertEqual(self._verify_fp.equal(p), match) + else: + self.assertFalse(match) if isinstance(scan_nick, str): self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick) @@ -401,6 +420,25 @@ class VirtualDeviceStorage(VirtualDevice): with self.assertRaisesRegex(GLib.GError, 'Print was not found'): self.dev.delete_print_sync(p) + def test_identify_match(self): + rt = self.enroll_print('right-thumb', FPrint.Finger.RIGHT_THUMB) + lt = self.enroll_print('left-thumb', FPrint.Finger.LEFT_THUMB) + + self.check_verify([rt, lt], 'right-thumb', identify=True, match=True) + self.check_verify([rt, lt], 'left-thumb', identify=True, match=True) + + def test_identify_no_match(self): + rt = self.enroll_print('right-thumb', FPrint.Finger.RIGHT_THUMB) + lt = self.enroll_print('left-thumb', FPrint.Finger.LEFT_THUMB) + + self.check_verify(lt, 'right-thumb', identify=True, match=False) + self.check_verify(rt, 'left-thumb', identify=True, match=False) + + def test_identify_retry(self): + with self.assertRaisesRegex(GLib.GError, 'too short'): + self.check_verify(FPrint.Print.new(self.dev), + FPrint.DeviceRetry.TOO_SHORT, identify=True, match=False) + if __name__ == '__main__': try: From c3ece8621db786adfc4d446f543463056e062d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 14:16:12 +0100 Subject: [PATCH 060/103] virtual-device: Implement UNPLUG operation --- libfprint/drivers/virtual-device.c | 5 ++++ tests/virtual-device.py | 37 ++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index ca8f885c..e462a2bd 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -44,6 +44,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE " #define LIST_CMD "LIST" +#define UNPLUG_CMD "UNPLUG" static void maybe_continue_current_action (FpDeviceVirtualDevice *self) @@ -198,6 +199,10 @@ recv_instruction_cb (GObject *source_object, if (self->prints_storage) g_hash_table_foreach (self->prints_storage, write_key_to_listener, listener); } + else if (g_str_has_prefix (cmd, UNPLUG_CMD)) + { + fpi_device_remove (FP_DEVICE (self)); + } else if (g_str_has_prefix (cmd, SET_ENROLL_STAGES_PREFIX)) { guint stages; diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 82beaa72..cdf56ac5 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -82,19 +82,21 @@ class VirtualDevice(unittest.TestCase): def setUp(self): super().setUp() + self._close_on_teardown = True self.assertFalse(self.dev.is_open()) self.dev.open_sync() self.assertTrue(self.dev.is_open()) def tearDown(self): - self.assertTrue(self.dev.is_open()) - self.dev.close_sync() + if self._close_on_teardown: + self.assertTrue(self.dev.is_open()) + self.dev.close_sync() self.assertFalse(self.dev.is_open()) super().tearDown() def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', - 'FINGER', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) + 'FINGER', 'UNPLUG', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -373,6 +375,30 @@ class VirtualDevice(unittest.TestCase): GLib.test_assert_expected_messages_internal('libfprint-device', __file__, 0, 'test_change_scan_type') + def test_device_unplug(self): + self._close_on_teardown = False + notified_spec = None + def on_removed_notify(dev, spec): + nonlocal notified_spec + notified_spec = spec + + removed = False + def on_removed(dev): + nonlocal removed + removed = True + + self.assertFalse(self.dev.props.removed) + + self.dev.connect('notify::removed', on_removed_notify) + self.dev.connect('removed', on_removed) + self.send_command('UNPLUG') + self.assertEqual(notified_spec.name, 'removed') + self.assertTrue(self.dev.props.removed) + self.assertTrue(removed) + + with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): + self.dev.close_sync() + class VirtualDeviceStorage(VirtualDevice): def tearDown(self): @@ -380,8 +406,9 @@ class VirtualDeviceStorage(VirtualDevice): super().tearDown() def cleanup_device_storage(self): - for print in self.dev.list_prints_sync(): - self.assertTrue(self.dev.delete_print_sync(print, None)) + if self.dev.is_open() and not self.dev.props.removed: + for print in self.dev.list_prints_sync(): + self.assertTrue(self.dev.delete_print_sync(print, None)) def test_device_properties(self): self.assertEqual(self.dev.get_driver(), 'virtual_device_storage') From 8c45c0952e39f510e375c54cc805698ab398838b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 15:06:15 +0100 Subject: [PATCH 061/103] virtual-device: Split verify check function in two parts to be reusable We can so inject further operations in the middle, such as for the finger status check --- tests/virtual-device.py | 56 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index cdf56ac5..d2217d8e 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -203,20 +203,16 @@ class VirtualDevice(unittest.TestCase): return self._enrolled - def check_verify(self, p, scan_nick, match, identify=False): + def start_verify(self, p, identify=False): self._verify_match = None self._verify_fp = None self._verify_error = None self._verify_completed = False + self._cancellable = Gio.Cancellable() if identify: self.assertTrue(self.dev.supports_identify()) - if isinstance(scan_nick, str): - self.send_command('SCAN', scan_nick) - else: - self.send_auto(scan_nick) - def verify_cb(dev, res): try: self._verify_match, self._verify_fp = ( @@ -227,13 +223,36 @@ class VirtualDevice(unittest.TestCase): self._verify_completed = True if identify: - self.dev.identify(p if isinstance(p, list) else [p], callback=verify_cb) + self.dev.identify(p if isinstance(p, list) else [p], + cancellable=self._cancellable, callback=verify_cb) else: - self.dev.verify(p, callback=verify_cb) + self.dev.verify(p, cancellable=self._cancellable, callback=verify_cb) + def cancel_verify(self): + self._cancellable.cancel() while not self._verify_completed: ctx.iteration(True) + self.assertIsNone(self._verify_match) + self.assertIsNotNone(self._verify_error) + self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + + def complete_verify(self): + while not self._verify_completed: + ctx.iteration(True) + + if self._verify_error is not None: + raise self._verify_error + + def check_verify(self, p, scan_nick, match, identify=False): + if isinstance(scan_nick, str): + self.send_command('SCAN', scan_nick) + else: + self.send_auto(scan_nick) + + self.start_verify(p, identify) + self.complete_verify() + if identify: if match: self.assertIsNotNone(self._verify_match) @@ -248,9 +267,6 @@ class VirtualDevice(unittest.TestCase): if isinstance(scan_nick, str): self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick) - if self._verify_error is not None: - raise self._verify_error - def test_device_properties(self): self.assertEqual(self.dev.get_driver(), 'virtual_device') self.assertEqual(self.dev.get_device_id(), '0') @@ -294,16 +310,8 @@ class VirtualDevice(unittest.TestCase): FPrint.DeviceRetry.TOO_SHORT, match=False) def test_finger_status(self): - cancellable = Gio.Cancellable() - got_cb = False - - def verify_cb(dev, res): - nonlocal got_cb - got_cb = True - - self.dev.verify(FPrint.Print.new(self.dev), callback=verify_cb, cancellable=cancellable) - while not self.dev.get_finger_status() is FPrint.FingerStatusFlags.NEEDED: - ctx.iteration(True) + self.start_verify(FPrint.Print.new(self.dev), + identify=self.dev.supports_identify()) self.send_finger_report(True) self.assertEqual(self.dev.get_finger_status(), @@ -312,11 +320,7 @@ class VirtualDevice(unittest.TestCase): self.send_finger_report(False) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED) - cancellable.cancel() - while not got_cb: - ctx.iteration(True) - - self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + self.cancel_verify() def test_change_enroll_stages(self): notified_spec = None From 153b24a95af24fec0da68b5135231016266c1d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 15:07:31 +0100 Subject: [PATCH 062/103] virtual-device: Use identify function for verify tests when possible --- tests/virtual-device.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index d2217d8e..bf48c578 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -291,18 +291,21 @@ class VirtualDevice(unittest.TestCase): def test_enroll_verify_match(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_THUMB) - self.check_verify(matching, 'testprint', match=True) + self.check_verify(matching, 'testprint', match=True, + identify=self.dev.supports_identify()) def test_enroll_verify_no_match(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) - self.check_verify(matching, 'not-testprint', match=False) + self.check_verify(matching, 'not-testprint', match=False, + identify=self.dev.supports_identify()) def test_enroll_verify_error(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) with self.assertRaisesRegex(GLib.Error, r"An unspecified error occurred"): - self.check_verify(matching, FPrint.DeviceError.GENERAL, match=False) + self.check_verify(matching, FPrint.DeviceError.GENERAL, match=False, + identify=self.dev.supports_identify()) def test_enroll_verify_retry(self): with self.assertRaisesRegex(GLib.GError, 'too short'): From 89b4c4ee758e05b6e9236b0288e90f8bc48aae06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 15:14:30 +0100 Subject: [PATCH 063/103] virtual-device: Test unplug operation while we're verifying --- tests/virtual-device.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index bf48c578..919c724c 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -406,6 +406,39 @@ class VirtualDevice(unittest.TestCase): with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): self.dev.close_sync() + def test_device_unplug_during_verify(self): + self._close_on_teardown = False + + notified_spec = None + def on_removed_notify(dev, spec): + nonlocal notified_spec + notified_spec = spec + + removed = False + def on_removed(dev): + nonlocal removed + removed = True + + self.assertFalse(self.dev.props.removed) + self.dev.connect('notify::removed', on_removed_notify) + self.dev.connect('removed', on_removed) + + self.start_verify(FPrint.Print.new(self.dev), + identify=self.dev.supports_identify()) + + self.send_command('UNPLUG') + self.assertEqual(notified_spec.name, 'removed') + self.assertTrue(self.dev.props.removed) + self.assertFalse(removed) + + with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): + self.complete_verify() + + self.assertTrue(removed) + + with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): + self.dev.close_sync() + class VirtualDeviceStorage(VirtualDevice): def tearDown(self): From 18db20d160fe005e6b0bc23031d8c72c91196091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 16:41:55 +0100 Subject: [PATCH 064/103] virtual-device: Add support for sleep command It can be used to delay operations, simulating a busy device. --- libfprint/drivers/virtual-device-private.h | 1 + libfprint/drivers/virtual-device.c | 35 ++++++++++++++++++++-- tests/virtual-device.py | 20 ++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index 08d6736b..d0d8077a 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -78,6 +78,7 @@ struct _FpDeviceVirtualDevice GHashTable *prints_storage; guint wait_command_id; + guint sleep_timeout_id; guint enroll_stages_passed; }; diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index e462a2bd..61e98df7 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -40,6 +40,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define ERROR_CMD_PREFIX "ERROR " #define RETRY_CMD_PREFIX "RETRY " #define FINGER_CMD_PREFIX "FINGER " +#define SLEEP_CMD_PREFIX "SLEEP " #define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES " #define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE " @@ -70,10 +71,26 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self) } } +static gboolean +sleep_timeout_cb (gpointer data) +{ + FpDeviceVirtualDevice *self = data; + + self->sleep_timeout_id = 0; + + if (g_cancellable_is_cancelled (self->cancellable)) + return FALSE; + + g_debug ("Sleeping completed"); + maybe_continue_current_action (self); + + return FALSE; +} + char * process_cmds (FpDeviceVirtualDevice * self, - gboolean scan, - GError * *error) + gboolean scan, + GError **error) { while (self->pending_commands->len > 0) { @@ -101,6 +118,16 @@ process_cmds (FpDeviceVirtualDevice * self, g_ptr_array_remove_index (self->pending_commands, 0); continue; } + else if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX)) + { + guint64 sleep_ms = g_ascii_strtoull (cmd + strlen (SLEEP_CMD_PREFIX), NULL, 10); + + g_debug ("Sleeping %lums", sleep_ms); + self->sleep_timeout_id = g_timeout_add (sleep_ms, sleep_timeout_cb, self); + g_ptr_array_remove_index (self->pending_commands, 0); + + return NULL; + } /* If we are not scanning, then we have to stop here. */ if (!scan) @@ -300,6 +327,9 @@ gboolean should_wait_for_command (FpDeviceVirtualDevice *self, GError *error) { + if (!error && self->sleep_timeout_id) + return TRUE; + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) return FALSE; @@ -433,6 +463,7 @@ dev_deinit (FpDevice *dev) FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); g_clear_handle_id (&self->wait_command_id, g_source_remove); + g_clear_handle_id (&self->sleep_timeout_id, g_source_remove); g_cancellable_cancel (self->cancellable); g_clear_object (&self->cancellable); g_clear_object (&self->listener); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 919c724c..323b23aa 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -96,7 +96,7 @@ class VirtualDevice(unittest.TestCase): def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', - 'FINGER', 'UNPLUG', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) + 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -439,6 +439,24 @@ class VirtualDevice(unittest.TestCase): with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): self.dev.close_sync() + def test_device_sleep(self): + enrolled = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) + + timeout_reached = False + def on_timeout(): + nonlocal timeout_reached + timeout_reached = True + + self.send_command('SLEEP', 1500) + GLib.timeout_add(300, on_timeout) + + self.start_verify(enrolled, identify=self.dev.supports_identify()) + while not timeout_reached: + ctx.iteration(False) + + self.assertFalse(self._verify_completed) + self.cancel_verify() + class VirtualDeviceStorage(VirtualDevice): def tearDown(self): From 993109a7f8d15a20f460d85501dcf549b3fb45ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 16:47:19 +0100 Subject: [PATCH 065/103] virtual-device: Implement cancel vfunc, to stop timeouts --- libfprint/drivers/virtual-device.c | 21 +++++++++++++++++++++ tests/virtual-device.py | 5 ++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 61e98df7..2f9c3a85 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -92,6 +92,15 @@ process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error) { + if (g_cancellable_is_cancelled (self->cancellable) || + (fpi_device_get_current_action (FP_DEVICE (self)) != FPI_DEVICE_ACTION_NONE && + g_cancellable_is_cancelled (fpi_device_get_cancellable (FP_DEVICE (self))))) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, + "Operation was cancelled"); + return NULL; + } + while (self->pending_commands->len > 0) { gchar *cmd = g_ptr_array_index (self->pending_commands, 0); @@ -457,6 +466,17 @@ dev_enroll (FpDevice *dev) } } +static void +dev_cancel (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + + g_debug ("Got cancellation!"); + g_clear_handle_id (&self->sleep_timeout_id, g_source_remove); + + maybe_continue_current_action (self); +} + static void dev_deinit (FpDevice *dev) { @@ -511,4 +531,5 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass) dev_class->close = dev_deinit; dev_class->verify = dev_verify; dev_class->enroll = dev_enroll; + dev_class->cancel = dev_cancel; } diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 323b23aa..fb0f2bba 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -440,8 +440,6 @@ class VirtualDevice(unittest.TestCase): self.dev.close_sync() def test_device_sleep(self): - enrolled = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) - timeout_reached = False def on_timeout(): nonlocal timeout_reached @@ -450,7 +448,8 @@ class VirtualDevice(unittest.TestCase): self.send_command('SLEEP', 1500) GLib.timeout_add(300, on_timeout) - self.start_verify(enrolled, identify=self.dev.supports_identify()) + self.start_verify(FPrint.Print.new(self.dev), + identify=self.dev.supports_identify()) while not timeout_reached: ctx.iteration(False) From 3693c39bc527eba0f2973894acb6beff9e740b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 17:10:00 +0100 Subject: [PATCH 066/103] virtual-device: Make cancellation support toggable We may want to have the device to sleep while releasing an operation, this will allow to do it. --- libfprint/drivers/virtual-device-private.h | 1 + libfprint/drivers/virtual-device.c | 13 +++++++ tests/virtual-device.py | 40 +++++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index d0d8077a..068da002 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -80,6 +80,7 @@ struct _FpDeviceVirtualDevice guint wait_command_id; guint sleep_timeout_id; guint enroll_stages_passed; + gboolean supports_cancellation; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 2f9c3a85..27749ba3 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -43,6 +43,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define SLEEP_CMD_PREFIX "SLEEP " #define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES " #define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE " +#define SET_CANCELLATION_PREFIX "SET_CANCELLATION_ENABLED " #define LIST_CMD "LIST" #define UNPLUG_CMD "UNPLUG" @@ -257,6 +258,14 @@ recv_instruction_cb (GObject *source_object, else g_warning ("Scan type '%s' not found", scan_type); } + else if (g_str_has_prefix (cmd, SET_CANCELLATION_PREFIX)) + { + self->supports_cancellation = g_ascii_strtoull ( + cmd + strlen (SET_CANCELLATION_PREFIX), NULL, 10) != 0; + + g_debug ("Cancellation support toggled: %d", + self->supports_cancellation); + } else { g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); @@ -471,6 +480,9 @@ dev_cancel (FpDevice *dev) { FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + if (!self->supports_cancellation) + return; + g_debug ("Got cancellation!"); g_clear_handle_id (&self->sleep_timeout_id, g_source_remove); @@ -505,6 +517,7 @@ fpi_device_virtual_device_finalize (GObject *object) static void fpi_device_virtual_device_init (FpDeviceVirtualDevice *self) { + self->supports_cancellation = TRUE; self->pending_commands = g_ptr_array_new_with_free_func (g_free); } diff --git a/tests/virtual-device.py b/tests/virtual-device.py index fb0f2bba..41e57287 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -96,7 +96,8 @@ class VirtualDevice(unittest.TestCase): def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', - 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE']) + 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE', + 'SET_CANCELLATION_ENABLED']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -453,6 +454,43 @@ class VirtualDevice(unittest.TestCase): while not timeout_reached: ctx.iteration(False) + self.assertFalse(self._verify_completed) + + timeout_reached = False + self._cancellable.cancel() + GLib.timeout_add(200, on_timeout) + + while not timeout_reached: + ctx.iteration(False) + + self.assertTrue(self._verify_completed) + self.cancel_verify() + + def test_device_sleep_on_cancellation(self): + timeout_reached = False + def on_timeout(): + nonlocal timeout_reached + timeout_reached = True + + self.send_command('SET_CANCELLATION_ENABLED', int(False)) + self.send_command('SLEEP', 1500) + self.send_command('SCAN', 'foo-print') + GLib.timeout_add(300, on_timeout) + + self.start_verify(FPrint.Print.new(self.dev), + identify=self.dev.supports_identify()) + while not timeout_reached: + ctx.iteration(False) + + self.assertFalse(self._verify_completed) + + timeout_reached = False + self._cancellable.cancel() + GLib.timeout_add(300, on_timeout) + + while not timeout_reached: + ctx.iteration(False) + self.assertFalse(self._verify_completed) self.cancel_verify() From 08f4be707c1594e0beabbdf5f2225c93c1b7960e Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 25 Jan 2021 11:26:58 +0100 Subject: [PATCH 067/103] uru4000: Call irq stop handler immediately if the transfer is cancelled The irq handler may already be stopped if stop_irq_handler is called. In that case, we should immediately call the handler rather than just never calling it. This fixes deactivation when the device is unexpectedly unplugged. Closes: #355 --- libfprint/drivers/uru4000.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index 0e67b2dc..f5d5d85b 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -375,6 +375,10 @@ stop_irq_handler (FpImageDevice *dev, irqs_stopped_cb_fn cb) g_cancellable_cancel (self->irq_cancellable); self->irqs_stopped_cb = cb; } + else + { + cb (dev); + } } /***** STATE CHANGING *****/ From 2382506491d86293781bcfbc2b3f616ecf046364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 21:16:36 +0100 Subject: [PATCH 068/103] virtual-device: Add checks for verify reports --- tests/virtual-device.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 41e57287..30d97050 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -208,12 +208,21 @@ class VirtualDevice(unittest.TestCase): self._verify_match = None self._verify_fp = None self._verify_error = None + self._verify_report_match = None + self._verify_report_print = None self._verify_completed = False + self._verify_reported = False self._cancellable = Gio.Cancellable() if identify: self.assertTrue(self.dev.supports_identify()) + def match_cb(dev, match, pnt, data, error): + self._verify_reported = True + self._verify_report_match = match + self._verify_report_print = pnt + self._verify_report_error = error + def verify_cb(dev, res): try: self._verify_match, self._verify_fp = ( @@ -225,9 +234,10 @@ class VirtualDevice(unittest.TestCase): if identify: self.dev.identify(p if isinstance(p, list) else [p], - cancellable=self._cancellable, callback=verify_cb) + cancellable=self._cancellable, match_cb=match_cb, callback=verify_cb) else: - self.dev.verify(p, cancellable=self._cancellable, callback=verify_cb) + self.dev.verify(p, cancellable=self._cancellable, match_cb=match_cb, + callback=verify_cb) def cancel_verify(self): self._cancellable.cancel() @@ -254,14 +264,21 @@ class VirtualDevice(unittest.TestCase): self.start_verify(p, identify) self.complete_verify() + self.assertTrue(self._verify_reported) + + if not match: + self.assertIsNone(self._verify_report_match) + if identify: if match: + self.assertIsNotNone(self._verify_report_match) self.assertIsNotNone(self._verify_match) - else: - self.assertIsNone(self._verify_match) else: if self._verify_fp: self.assertEqual(self._verify_fp.equal(p), match) + if match: + self.assertTrue( + self._verify_fp.equal(self._verify_report_match)) else: self.assertFalse(match) From 3db0858fb0d86fe23335d75284558992651a4009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 21:29:20 +0100 Subject: [PATCH 069/103] tests/virtual-device: Add a class function to wait for a timeout --- tests/virtual-device.py | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 30d97050..1f9d76c6 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -94,6 +94,16 @@ class VirtualDevice(unittest.TestCase): self.assertFalse(self.dev.is_open()) super().tearDown() + def wait_timeout(self, interval): + timeout_reached = False + def on_timeout(): + nonlocal timeout_reached + timeout_reached = True + + GLib.timeout_add(interval, on_timeout) + while not timeout_reached: + ctx.iteration(False) + def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE', @@ -458,55 +468,33 @@ class VirtualDevice(unittest.TestCase): self.dev.close_sync() def test_device_sleep(self): - timeout_reached = False - def on_timeout(): - nonlocal timeout_reached - timeout_reached = True - self.send_command('SLEEP', 1500) - GLib.timeout_add(300, on_timeout) self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) - while not timeout_reached: - ctx.iteration(False) + self.wait_timeout(300) self.assertFalse(self._verify_completed) - timeout_reached = False self._cancellable.cancel() - GLib.timeout_add(200, on_timeout) - - while not timeout_reached: - ctx.iteration(False) + self.wait_timeout(200) self.assertTrue(self._verify_completed) self.cancel_verify() def test_device_sleep_on_cancellation(self): - timeout_reached = False - def on_timeout(): - nonlocal timeout_reached - timeout_reached = True - self.send_command('SET_CANCELLATION_ENABLED', int(False)) self.send_command('SLEEP', 1500) self.send_command('SCAN', 'foo-print') - GLib.timeout_add(300, on_timeout) self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) - while not timeout_reached: - ctx.iteration(False) + self.wait_timeout(300) self.assertFalse(self._verify_completed) - timeout_reached = False self._cancellable.cancel() - GLib.timeout_add(300, on_timeout) - - while not timeout_reached: - ctx.iteration(False) + self.wait_timeout(300) self.assertFalse(self._verify_completed) self.cancel_verify() From 0bb0492025762a995cbd1b4390de335ac81c776a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 22:47:40 +0100 Subject: [PATCH 070/103] virtual-device: Mark finger as needed only after we start scanning In case we sent a sleep event to the device we may want to wait it to emit the finger needed state before the timeout is completed. So add a function to manage this for all the scan cases --- libfprint/drivers/virtual-device-private.h | 2 + libfprint/drivers/virtual-device-storage.c | 9 ++--- libfprint/drivers/virtual-device.c | 47 +++++++++++++++++----- tests/virtual-device.py | 27 +++++++++++++ 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index 068da002..70b178b9 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -96,5 +96,7 @@ G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_st char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error); +char * start_scan_command (FpDeviceVirtualDevice *self, + GError **error); gboolean should_wait_for_command (FpDeviceVirtualDevice *self, GError *error); diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 1fcee3c7..654a1712 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -41,13 +41,12 @@ dev_identify (FpDevice *dev) GPtrArray *prints; g_autofree char *scan_id = NULL; - fpi_device_get_identify_data (dev, &prints); - fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NEEDED); - - scan_id = process_cmds (self, TRUE, &error); - if (should_wait_for_command (self, error)) + scan_id = start_scan_command (self, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) return; + fpi_device_get_identify_data (dev, &prints); + if (scan_id) { GVariant *data = NULL; diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 27749ba3..13654156 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -358,6 +358,35 @@ should_wait_for_command (FpDeviceVirtualDevice *self, return TRUE; } +char * +start_scan_command (FpDeviceVirtualDevice *self, + GError **error) +{ + g_autoptr(GError) local_error = NULL; + g_autofree char *scan_id = NULL; + + scan_id = process_cmds (self, TRUE, &local_error); + + if (!self->sleep_timeout_id) + { + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_NEEDED, + FP_FINGER_STATUS_NONE); + } + + if (should_wait_for_command (self, local_error)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING, + "Still waiting for command"); + return NULL; + } + + if (local_error) + g_propagate_error (error, g_steal_pointer (&local_error)); + + return g_steal_pointer (&scan_id); +} + static void dev_verify (FpDevice *dev) { @@ -366,13 +395,12 @@ dev_verify (FpDevice *dev) FpPrint *print; g_autofree char *scan_id = NULL; - fpi_device_get_verify_data (dev, &print); - fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NEEDED); - - scan_id = process_cmds (self, TRUE, &error); - if (should_wait_for_command (self, error)) + scan_id = start_scan_command (self, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) return; + fpi_device_get_verify_data (dev, &print); + if (scan_id) { GVariant *data = NULL; @@ -414,13 +442,12 @@ dev_enroll (FpDevice *dev) FpPrint *print = NULL; g_autofree char *id = NULL; - fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NEEDED); - fpi_device_get_enroll_data (dev, &print); - - id = process_cmds (self, TRUE, &error); - if (should_wait_for_command (self, error)) + id = start_scan_command (self, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) return; + fpi_device_get_enroll_data (dev, &print); + if (id) { GVariant *data; diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 1f9d76c6..fe50fe49 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -344,6 +344,9 @@ class VirtualDevice(unittest.TestCase): self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED) + self.send_finger_report(True) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED | FPrint.FingerStatusFlags.PRESENT) @@ -353,6 +356,30 @@ class VirtualDevice(unittest.TestCase): self.cancel_verify() + def test_finger_status_after_sleep(self): + self.send_command('SLEEP', 10) + self.start_verify(FPrint.Print.new(self.dev), + identify=self.dev.supports_identify()) + + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NONE) + + while self.dev.get_finger_status() != FPrint.FingerStatusFlags.NEEDED: + ctx.iteration(True) + + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED) + + self.send_finger_report(True) + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED | FPrint.FingerStatusFlags.PRESENT) + + self.send_finger_report(False) + self.assertEqual(self.dev.get_finger_status(), + FPrint.FingerStatusFlags.NEEDED) + + self.cancel_verify() + def test_change_enroll_stages(self): notified_spec = None def on_stage_changed(dev, spec): From 1dae6796f7e7d76cf1837f800ca4ba97bef43097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 25 Jan 2021 23:36:00 +0100 Subject: [PATCH 071/103] virtual-device: Report finger presency when we receive a 'SCAN' event --- libfprint/drivers/virtual-device-storage.c | 4 ++++ libfprint/drivers/virtual-device.c | 23 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 654a1712..ba122538 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -79,6 +79,10 @@ dev_identify (FpDevice *dev) fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error)); } + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_NONE, + FP_FINGER_STATUS_PRESENT); + fpi_device_identify_complete (dev, g_steal_pointer (&error)); } diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 13654156..9105a4b8 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -383,6 +383,10 @@ start_scan_command (FpDeviceVirtualDevice *self, if (local_error) g_propagate_error (error, g_steal_pointer (&local_error)); + else + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_PRESENT, + FP_FINGER_STATUS_NONE); return g_steal_pointer (&scan_id); } @@ -428,6 +432,10 @@ dev_verify (FpDevice *dev) g_debug ("Virtual device scan failed with error: %s", error->message); } + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_NONE, + FP_FINGER_STATUS_PRESENT); + if (error && error->domain == FP_DEVICE_RETRY) fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error)); @@ -451,6 +459,7 @@ dev_enroll (FpDevice *dev) if (id) { GVariant *data; + gboolean completed; if (self->enroll_stages_passed == 0) { @@ -475,8 +484,16 @@ dev_enroll (FpDevice *dev) } self->enroll_stages_passed++; + completed = self->enroll_stages_passed == fp_device_get_nr_enroll_stages (FP_DEVICE (self)); + fpi_device_report_finger_status_changes (FP_DEVICE (self), + completed ? + FP_FINGER_STATUS_NEEDED : + FP_FINGER_STATUS_NONE, + FP_FINGER_STATUS_PRESENT); + fpi_device_enroll_progress (dev, self->enroll_stages_passed, print, NULL); - if (self->enroll_stages_passed == fp_device_get_nr_enroll_stages (FP_DEVICE (self))) + + if (completed) { if (self->prints_storage) { @@ -490,6 +507,10 @@ dev_enroll (FpDevice *dev) } else { + fpi_device_report_finger_status_changes (FP_DEVICE (self), + FP_FINGER_STATUS_NONE, + FP_FINGER_STATUS_PRESENT); + if (error && error->domain == FP_DEVICE_RETRY) { fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, g_steal_pointer (&error)); From 7ffcc2f9e7cbf5897156486cdf0ec14f1d31f3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 26 Jan 2021 03:37:16 +0100 Subject: [PATCH 072/103] virtual-device: Make possible to inject sleep events while verifying/identifying Each command should be separated by SLEEP to be considered as something we want to perform during the current operation, otherwise will be used by next operation consuming it. --- libfprint/drivers/virtual-device-private.h | 5 ++ libfprint/drivers/virtual-device-storage.c | 16 +++-- libfprint/drivers/virtual-device.c | 78 ++++++++++++++++++++-- tests/virtual-device.py | 19 ++++++ 4 files changed, 110 insertions(+), 8 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index 70b178b9..efb1cdf2 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -80,7 +80,9 @@ struct _FpDeviceVirtualDevice guint wait_command_id; guint sleep_timeout_id; guint enroll_stages_passed; + gboolean match_reported; gboolean supports_cancellation; + gboolean injected_synthetic_cmd; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice @@ -100,3 +102,6 @@ char * start_scan_command (FpDeviceVirtualDevice *self, GError **error); gboolean should_wait_for_command (FpDeviceVirtualDevice *self, GError *error); +gboolean should_wait_to_sleep (FpDeviceVirtualDevice *self, + const char *scan_id, + GError *error); diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index ba122538..9db8efec 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -69,10 +69,14 @@ dev_identify (FpDevice *dev) &idx)) match = g_ptr_array_index (prints, idx); - fpi_device_identify_report (dev, - match, - new_scan, - NULL); + if (!self->match_reported) + { + self->match_reported = TRUE; + fpi_device_identify_report (dev, + match, + new_scan, + NULL); + } } else if (error && error->domain == FP_DEVICE_RETRY) { @@ -83,6 +87,10 @@ dev_identify (FpDevice *dev) FP_FINGER_STATUS_NONE, FP_FINGER_STATUS_PRESENT); + if (should_wait_to_sleep (self, scan_id, error)) + return; + + self->match_reported = FALSE; fpi_device_identify_complete (dev, g_steal_pointer (&error)); } diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 9105a4b8..769b91e6 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -53,6 +53,9 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self) { FpDevice *dev = FP_DEVICE (self); + if (self->sleep_timeout_id) + return; + switch (fpi_device_get_current_action (dev)) { case FPI_DEVICE_ACTION_ENROLL: @@ -365,6 +368,9 @@ start_scan_command (FpDeviceVirtualDevice *self, g_autoptr(GError) local_error = NULL; g_autofree char *scan_id = NULL; + if (fp_device_get_finger_status (FP_DEVICE (self)) == FP_FINGER_STATUS_NONE) + self->injected_synthetic_cmd = FALSE; + scan_id = process_cmds (self, TRUE, &local_error); if (!self->sleep_timeout_id) @@ -376,6 +382,8 @@ start_scan_command (FpDeviceVirtualDevice *self, if (should_wait_for_command (self, local_error)) { + g_assert (!scan_id); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING, "Still waiting for command"); return NULL; @@ -391,6 +399,51 @@ start_scan_command (FpDeviceVirtualDevice *self, return g_steal_pointer (&scan_id); } +gboolean +should_wait_to_sleep (FpDeviceVirtualDevice *self, + const char *scan_id, + GError *error) +{ + const gchar *cmd; + + if (self->sleep_timeout_id) + return TRUE; + + if (!self->pending_commands->len) + return FALSE; + + cmd = g_ptr_array_index (self->pending_commands, 0); + + if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX)) + { + g_free (process_cmds (self, FALSE, NULL)); + + g_assert (!self->injected_synthetic_cmd); + g_assert (self->sleep_timeout_id != 0); + + if (!self->pending_commands->len) + { + g_autofree char *injected_cmd = NULL; + + if (scan_id) + injected_cmd = g_strconcat (SCAN_CMD_PREFIX, scan_id, NULL); + else if (error && error->domain == FP_DEVICE_ERROR) + injected_cmd = g_strdup_printf (ERROR_CMD_PREFIX " %d", error->code); + else if (error && error->domain == FP_DEVICE_RETRY) + injected_cmd = g_strdup_printf (RETRY_CMD_PREFIX " %d", error->code); + else + return TRUE; + + g_debug ("Sleeping now, command queued for later: %s", injected_cmd); + + g_ptr_array_insert (self->pending_commands, 0, g_steal_pointer (&injected_cmd)); + self->injected_synthetic_cmd = TRUE; + } + } + + return self->sleep_timeout_id != 0; +} + static void dev_verify (FpDevice *dev) { @@ -422,10 +475,14 @@ dev_verify (FpDevice *dev) success = fp_print_equal (print, new_scan); - fpi_device_verify_report (dev, - success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, - new_scan, - NULL); + if (!self->match_reported) + { + self->match_reported = TRUE; + fpi_device_verify_report (dev, + success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, + new_scan, + NULL); + } } else { @@ -439,6 +496,10 @@ dev_verify (FpDevice *dev) if (error && error->domain == FP_DEVICE_RETRY) fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error)); + if (should_wait_to_sleep (self, scan_id, error)) + return; + + self->match_reported = FALSE; fpi_device_verify_complete (dev, g_steal_pointer (&error)); } @@ -517,6 +578,9 @@ dev_enroll (FpDevice *dev) } else { + if (should_wait_to_sleep (self, id, error)) + return; + self->enroll_stages_passed = 0; fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error)); } @@ -528,6 +592,12 @@ dev_cancel (FpDevice *dev) { FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + if (self->injected_synthetic_cmd) + { + self->injected_synthetic_cmd = FALSE; + g_ptr_array_remove_index (self->pending_commands, 0); + } + if (!self->supports_cancellation) return; diff --git a/tests/virtual-device.py b/tests/virtual-device.py index fe50fe49..e1156566 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -526,6 +526,25 @@ class VirtualDevice(unittest.TestCase): self.assertFalse(self._verify_completed) self.cancel_verify() + def test_device_sleep_before_completing_verify(self): + enrolled = self.enroll_print('foo-print', FPrint.Finger.LEFT_RING) + + self.send_command('SLEEP', 100) + self.start_verify(enrolled, identify=self.dev.supports_identify()) + self.send_command('SCAN', 'bar-print') + self.send_command('SLEEP', 800) + + while not self._verify_reported: + ctx.iteration(False) + + self.assertFalse(self._verify_completed) + self.wait_timeout(10) + self.assertFalse(self._verify_completed) + + self.complete_verify() + self.assertTrue(self._verify_reported) + + class VirtualDeviceStorage(VirtualDevice): def tearDown(self): From 88a38c38aff592bfdf36bbc02f6548fdf6f01aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 26 Jan 2021 01:33:55 +0100 Subject: [PATCH 073/103] virtual-device: Add support for sleeping and sending errors on list and delete --- libfprint/drivers/virtual-device-private.h | 1 + libfprint/drivers/virtual-device-storage.c | 22 ++++++++++-- libfprint/drivers/virtual-device.c | 41 +++++++++++++++++----- tests/virtual-device.py | 41 ++++++++++++++++++++++ 4 files changed, 95 insertions(+), 10 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index efb1cdf2..75ae6589 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -83,6 +83,7 @@ struct _FpDeviceVirtualDevice gboolean match_reported; gboolean supports_cancellation; gboolean injected_synthetic_cmd; + gboolean ignore_wait; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 9db8efec..a4c94252 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -122,10 +122,19 @@ static void dev_list (FpDevice *dev) { g_autoptr(GPtrArray) prints_list = NULL; + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); struct ListData data; - process_cmds (vdev, FALSE, NULL); + process_cmds (vdev, FALSE, &error); + if (should_wait_for_command (vdev, error)) + return; + + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_list_complete (dev, NULL, g_steal_pointer (&error)); + return; + } prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), NULL); data.dev = dev; @@ -140,11 +149,20 @@ static void dev_delete (FpDevice *dev) { g_autoptr(GVariant) data = NULL; + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); FpPrint *print = NULL; const char *id = NULL; - process_cmds (vdev, FALSE, NULL); + process_cmds (vdev, FALSE, &error); + if (should_wait_for_command (vdev, error)) + return; + + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_delete_complete (dev, g_steal_pointer (&error)); + return; + } fpi_device_get_delete_data (dev, &print); diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 769b91e6..b32610c5 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -70,6 +70,14 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self) FP_DEVICE_GET_CLASS (self)->identify (dev); break; + case FPI_DEVICE_ACTION_LIST: + FP_DEVICE_GET_CLASS (self)->list (dev); + break; + + case FPI_DEVICE_ACTION_DELETE: + FP_DEVICE_GET_CLASS (self)->delete (dev); + break; + default: break; } @@ -141,6 +149,14 @@ process_cmds (FpDeviceVirtualDevice * self, return NULL; } + else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX)) + { + g_propagate_error (error, + fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); + + g_ptr_array_remove_index (self->pending_commands, 0); + return NULL; + } /* If we are not scanning, then we have to stop here. */ if (!scan) @@ -153,14 +169,6 @@ process_cmds (FpDeviceVirtualDevice * self, g_ptr_array_remove_index (self->pending_commands, 0); return res; } - else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX)) - { - g_propagate_error (error, - fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); - - g_ptr_array_remove_index (self->pending_commands, 0); - return NULL; - } else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX)) { g_propagate_error (error, @@ -338,6 +346,20 @@ wait_for_command_timeout (gpointer data) GError *error = NULL; self->wait_command_id = 0; + + switch (fpi_device_get_current_action (FP_DEVICE (self))) + { + case FPI_DEVICE_ACTION_LIST: + case FPI_DEVICE_ACTION_DELETE: + self->ignore_wait = TRUE; + maybe_continue_current_action (self); + self->ignore_wait = FALSE; + return FALSE; + + default: + break; + } + error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!"); fpi_device_action_error (FP_DEVICE (self), error); @@ -351,6 +373,9 @@ should_wait_for_command (FpDeviceVirtualDevice *self, if (!error && self->sleep_timeout_id) return TRUE; + if (self->ignore_wait) + return FALSE; + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) return FALSE; diff --git a/tests/virtual-device.py b/tests/virtual-device.py index e1156566..bce202f8 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -586,6 +586,47 @@ class VirtualDeviceStorage(VirtualDevice): self.dev.delete_print_sync(p) self.assertFalse(self.dev.list_prints_sync()) + def test_delete_error(self): + deleted_res = None + def on_deleted(dev, res): + nonlocal deleted_res + try: + deleted_res = dev.delete_print_finish(res) + except GLib.Error as e: + deleted_res = e + + self.send_command('SLEEP', 100) + self.send_error(FPrint.DeviceError.DATA_NOT_FOUND) + self.dev.delete_print(FPrint.Print.new(self.dev), callback=on_deleted) + self.wait_timeout(2) + self.assertIsNone(deleted_res) + + while not deleted_res: + ctx.iteration(True) + + self.assertEqual(deleted_res.code, int(FPrint.DeviceError.DATA_NOT_FOUND)) + + def test_list_error(self): + list_res = None + + def on_listed(dev, res): + nonlocal list_res + try: + list_res = dev.list_prints_finish(res) + except GLib.Error as e: + list_res = e + + self.send_command('SLEEP', 100) + self.send_error(FPrint.DeviceError.BUSY) + self.dev.list_prints(callback=on_listed) + self.wait_timeout(2) + self.assertIsNone(list_res) + + while not list_res: + ctx.iteration(True) + + self.assertEqual(list_res.code, int(FPrint.DeviceError.BUSY)) + def test_list_delete_missing(self): p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB) self.send_command('REMOVE', 'testprint') From cfde050220eff8e07c51573ddf39fe50c28a9da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 26 Jan 2021 02:24:16 +0100 Subject: [PATCH 074/103] virtual-device: Add ability to close a device with delay or with error --- libfprint/drivers/virtual-device.c | 16 ++++++++++++++++ tests/virtual-device.py | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index b32610c5..9da1f778 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -78,6 +78,10 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self) FP_DEVICE_GET_CLASS (self)->delete (dev); break; + case FPI_DEVICE_ACTION_CLOSE: + FP_DEVICE_GET_CLASS (self)->close (dev); + break; + default: break; } @@ -635,8 +639,20 @@ dev_cancel (FpDevice *dev) static void dev_deinit (FpDevice *dev) { + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + process_cmds (self, FALSE, &error); + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_close_complete (dev, g_steal_pointer (&error)); + return; + } + else if (self->sleep_timeout_id) + { + return; + } + g_clear_handle_id (&self->wait_command_id, g_source_remove); g_clear_handle_id (&self->sleep_timeout_id, g_source_remove); g_cancellable_cancel (self->cancellable); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index bce202f8..58eb02e2 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -544,6 +544,27 @@ class VirtualDevice(unittest.TestCase): self.complete_verify() self.assertTrue(self._verify_reported) + def test_close_error(self): + self._close_on_teardown = False + close_res = None + + def on_closed(dev, res): + nonlocal close_res + try: + close_res = dev.close_finish(res) + except GLib.Error as e: + close_res = e + + self.send_command('SLEEP', 100) + self.send_error(FPrint.DeviceError.BUSY) + self.dev.close(callback=on_closed) + self.wait_timeout(2) + self.assertIsNone(close_res) + + while not close_res: + ctx.iteration(True) + + self.assertEqual(close_res.code, int(FPrint.DeviceError.BUSY)) class VirtualDeviceStorage(VirtualDevice): From 549718753f14abb49b918d2601959a40cccbddd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 26 Jan 2021 02:24:41 +0100 Subject: [PATCH 075/103] fpi-device: Fix argument name on report_finger_status() annotation --- libfprint/fpi-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index f59d430d..be5b0e98 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -1530,7 +1530,7 @@ fpi_device_report_finger_status (FpDevice *device, * fpi_device_report_finger_status_changes: * @device: The #FpDevice * @added_status: The #FpFingerStatusFlags to add - * @added_status: The #FpFingerStatusFlags to remove + * @removed_status: The #FpFingerStatusFlags to remove * * Report the finger status for the @device adding the @added_status flags * and removing the @removed_status flags. From 31541edc582173bb11bf43657a6fb5baa9472f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 26 Jan 2021 05:17:48 +0100 Subject: [PATCH 076/103] tests/virtual-device: Use a sleep multiplier when under valgrind --- tests/meson.build | 1 + tests/virtual-device.py | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/meson.build b/tests/meson.build index f15bd8ad..291d8065 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -209,6 +209,7 @@ if valgrind.found() timeout_multiplier: 10, env: [ 'G_SLICE=always-malloc', + 'UNDER_VALGRIND=1', ('LIBFPRINT_TEST_WRAPPER=@0@ --tool=memcheck --leak-check=full ' + '--suppressions=@1@ --suppressions=@2@').format( valgrind.path(), glib_suppressions, python_suppressions) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 58eb02e2..789f3853 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -146,6 +146,11 @@ class VirtualDevice(unittest.TestCase): else: raise Exception('No known type found for {}'.format(obj)) + def send_sleep(self, interval): + self.assertGreater(interval, 0) + multiplier = 5 if 'UNDER_VALGRIND' in os.environ else 1 + self.send_command('SLEEP', interval * multiplier) + def enroll_print(self, nick, finger, username='testuser', retry_scan=-1): self._enrolled = None @@ -357,7 +362,7 @@ class VirtualDevice(unittest.TestCase): self.cancel_verify() def test_finger_status_after_sleep(self): - self.send_command('SLEEP', 10) + self.send_sleep(10) self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) @@ -495,7 +500,7 @@ class VirtualDevice(unittest.TestCase): self.dev.close_sync() def test_device_sleep(self): - self.send_command('SLEEP', 1500) + self.send_sleep(1500) self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) @@ -511,7 +516,7 @@ class VirtualDevice(unittest.TestCase): def test_device_sleep_on_cancellation(self): self.send_command('SET_CANCELLATION_ENABLED', int(False)) - self.send_command('SLEEP', 1500) + self.send_sleep(1500) self.send_command('SCAN', 'foo-print') self.start_verify(FPrint.Print.new(self.dev), @@ -529,10 +534,10 @@ class VirtualDevice(unittest.TestCase): def test_device_sleep_before_completing_verify(self): enrolled = self.enroll_print('foo-print', FPrint.Finger.LEFT_RING) - self.send_command('SLEEP', 100) + self.send_sleep(100) self.start_verify(enrolled, identify=self.dev.supports_identify()) self.send_command('SCAN', 'bar-print') - self.send_command('SLEEP', 800) + self.send_sleep(800) while not self._verify_reported: ctx.iteration(False) @@ -555,7 +560,7 @@ class VirtualDevice(unittest.TestCase): except GLib.Error as e: close_res = e - self.send_command('SLEEP', 100) + self.send_sleep(100) self.send_error(FPrint.DeviceError.BUSY) self.dev.close(callback=on_closed) self.wait_timeout(2) @@ -616,7 +621,7 @@ class VirtualDeviceStorage(VirtualDevice): except GLib.Error as e: deleted_res = e - self.send_command('SLEEP', 100) + self.send_sleep(100) self.send_error(FPrint.DeviceError.DATA_NOT_FOUND) self.dev.delete_print(FPrint.Print.new(self.dev), callback=on_deleted) self.wait_timeout(2) @@ -637,7 +642,7 @@ class VirtualDeviceStorage(VirtualDevice): except GLib.Error as e: list_res = e - self.send_command('SLEEP', 100) + self.send_sleep(100) self.send_error(FPrint.DeviceError.BUSY) self.dev.list_prints(callback=on_listed) self.wait_timeout(2) From c4069065f99b99e66549b30646c896900a7b32a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 26 Jan 2021 05:27:44 +0100 Subject: [PATCH 077/103] virtual-device: Ensure we've an error before dereferencing it --- libfprint/drivers/virtual-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 9da1f778..f7767a61 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -513,7 +513,7 @@ dev_verify (FpDevice *dev) NULL); } } - else + else if (error) { g_debug ("Virtual device scan failed with error: %s", error->message); } From 8d21a9c27c0c8b55db21cb48d0fe59f9773429a0 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 26 Jan 2021 15:10:11 +0100 Subject: [PATCH 078/103] ssm: Catch more errors in FpiSsm without crashing --- libfprint/fpi-ssm.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/libfprint/fpi-ssm.c b/libfprint/fpi-ssm.c index 25728d18..6264d407 100644 --- a/libfprint/fpi-ssm.c +++ b/libfprint/fpi-ssm.c @@ -130,6 +130,7 @@ fpi_ssm_new_full (FpDevice *dev, { FpiSsm *machine; + BUG_ON (dev == NULL); BUG_ON (nr_states < 1); BUG_ON (handler == NULL); @@ -155,6 +156,8 @@ fpi_ssm_set_data (FpiSsm *machine, gpointer ssm_data, GDestroyNotify ssm_data_destroy) { + g_return_if_fail (machine); + if (machine->ssm_data_destroy && machine->ssm_data) machine->ssm_data_destroy (machine->ssm_data); @@ -173,12 +176,16 @@ fpi_ssm_set_data (FpiSsm *machine, void * fpi_ssm_get_data (FpiSsm *machine) { + g_return_val_if_fail (machine, NULL); + return machine->ssm_data; } static void fpi_ssm_clear_delayed_action (FpiSsm *machine) { + g_return_if_fail (machine); + if (machine->cancellable_id) { g_cancellable_disconnect (machine->cancellable, machine->cancellable_id); @@ -235,6 +242,8 @@ fpi_ssm_set_delayed_action_timeout (FpiSsm *machine, gpointer user_data, GDestroyNotify destroy_func) { + g_return_if_fail (machine); + BUG_ON (machine->completed); BUG_ON (machine->timeout != NULL); @@ -302,6 +311,8 @@ __ssm_call_handler (FpiSsm *machine) void fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback) { + g_return_if_fail (ssm != NULL); + BUG_ON (!ssm->completed); ssm->callback = callback; ssm->cur_state = 0; @@ -336,6 +347,9 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) void fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child) { + g_return_if_fail (parent != NULL); + g_return_if_fail (child != NULL); + BUG_ON (parent->timeout); child->parentsm = parent; @@ -355,6 +369,8 @@ fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child) void fpi_ssm_mark_completed (FpiSsm *machine) { + g_return_if_fail (machine != NULL); + BUG_ON (machine->completed); BUG_ON (machine->timeout != NULL); @@ -427,6 +443,7 @@ fpi_ssm_mark_completed_delayed (FpiSsm *machine, void fpi_ssm_mark_failed (FpiSsm *machine, GError *error) { + g_return_if_fail (machine != NULL); g_assert (error); if (machine->error) { @@ -534,6 +551,8 @@ fpi_ssm_next_state_delayed (FpiSsm *machine, void fpi_ssm_jump_to_state (FpiSsm *machine, int state) { + g_return_if_fail (machine != NULL); + BUG_ON (machine->completed); BUG_ON (state < 0 || state >= machine->nr_states); BUG_ON (machine->timeout != NULL); @@ -610,6 +629,8 @@ fpi_ssm_jump_to_state_delayed (FpiSsm *machine, int fpi_ssm_get_cur_state (FpiSsm *machine) { + g_return_val_if_fail (machine != NULL, 0); + return machine->cur_state; } @@ -624,6 +645,8 @@ fpi_ssm_get_cur_state (FpiSsm *machine) GError * fpi_ssm_get_error (FpiSsm *machine) { + g_return_val_if_fail (machine != NULL, NULL); + return machine->error; } @@ -638,6 +661,8 @@ fpi_ssm_get_error (FpiSsm *machine) GError * fpi_ssm_dup_error (FpiSsm *machine) { + g_return_val_if_fail (machine != NULL, NULL); + if (machine->error) return g_error_copy (machine->error); From ec4c7ca5a9870b32b552871fb915e2fb608c9e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 27 Jan 2021 15:17:34 +0100 Subject: [PATCH 079/103] virtual-device-storage: Don't listed prints --- libfprint/drivers/virtual-device-storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index a4c94252..dbda8057 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -136,7 +136,7 @@ dev_list (FpDevice *dev) return; } - prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), NULL); + prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), g_object_unref); data.dev = dev; data.res = prints_list; From 31e34bd4bddba011bc0e00ba07544f5ebe3c9da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 27 Jan 2021 14:49:03 +0100 Subject: [PATCH 080/103] virtual-device: Emit data not found during verify/identify If trying to identify a print not in the storage we emit data not found error, this can be helpful to do further fprintd testing too --- libfprint/drivers/virtual-device-storage.c | 49 ++++++++++++++-------- libfprint/drivers/virtual-device.c | 15 +++++-- tests/virtual-device.py | 42 ++++++++++++++++--- 3 files changed, 80 insertions(+), 26 deletions(-) diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index dbda8057..34e89718 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -33,22 +33,23 @@ G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, fpi_device_virtual_device_get_type ()) +static GPtrArray * get_stored_prints (FpDeviceVirtualDevice * self); + static void dev_identify (FpDevice *dev) { g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); - GPtrArray *prints; g_autofree char *scan_id = NULL; scan_id = start_scan_command (self, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) return; - fpi_device_get_identify_data (dev, &prints); - if (scan_id) { + g_autoptr(GPtrArray) stored = get_stored_prints (self); + GPtrArray *prints; GVariant *data = NULL; FpPrint *new_scan; FpPrint *match = NULL; @@ -56,17 +57,22 @@ dev_identify (FpDevice *dev) new_scan = fp_print_new (dev); fpi_print_set_type (new_scan, FPI_PRINT_RAW); - if (self->prints_storage) - fpi_print_set_device_stored (new_scan, TRUE); + fpi_print_set_device_stored (new_scan, TRUE); data = g_variant_new_string (scan_id); g_object_set (new_scan, "fpi-data", data, NULL); + fpi_device_get_identify_data (dev, &prints); g_debug ("Trying to identify print '%s' against a gallery of %u prints", scan_id, prints->len); - if (g_ptr_array_find_with_equal_func (prints, - new_scan, - (GEqualFunc) fp_print_equal, - &idx)) + if (!g_ptr_array_find_with_equal_func (stored, + new_scan, + (GEqualFunc) fp_print_equal, + NULL)) + error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND); + else if (g_ptr_array_find_with_equal_func (prints, + new_scan, + (GEqualFunc) fp_print_equal, + &idx)) match = g_ptr_array_index (prints, idx); if (!self->match_reported) @@ -118,13 +124,28 @@ dev_list_insert_print (gpointer key, g_ptr_array_add (data->res, print); } +static GPtrArray * +get_stored_prints (FpDeviceVirtualDevice *self) +{ + GPtrArray * prints_list; + struct ListData data; + + prints_list = g_ptr_array_new_full (g_hash_table_size (self->prints_storage), + g_object_unref); + data.dev = FP_DEVICE (self); + data.res = prints_list; + + g_hash_table_foreach (self->prints_storage, dev_list_insert_print, &data); + + return prints_list; +} + static void dev_list (FpDevice *dev) { g_autoptr(GPtrArray) prints_list = NULL; g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); - struct ListData data; process_cmds (vdev, FALSE, &error); if (should_wait_for_command (vdev, error)) @@ -136,13 +157,7 @@ dev_list (FpDevice *dev) return; } - prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), g_object_unref); - data.dev = dev; - data.res = prints_list; - - g_hash_table_foreach (vdev->prints_storage, dev_list_insert_print, &data); - - fpi_device_list_complete (dev, g_steal_pointer (&prints_list), NULL); + fpi_device_list_complete (dev, get_stored_prints (vdev), NULL); } static void diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index f7767a61..ca658dd9 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -478,22 +478,21 @@ dev_verify (FpDevice *dev) { g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); - FpPrint *print; g_autofree char *scan_id = NULL; scan_id = start_scan_command (self, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) return; - fpi_device_get_verify_data (dev, &print); - if (scan_id) { GVariant *data = NULL; FpPrint *new_scan; + FpPrint *print; gboolean success; g_debug ("Virtual device scanned print %s", scan_id); + fpi_device_get_verify_data (dev, &print); new_scan = fp_print_new (dev); fpi_print_set_type (new_scan, FPI_PRINT_RAW); @@ -502,7 +501,15 @@ dev_verify (FpDevice *dev) data = g_variant_new_string (scan_id); g_object_set (new_scan, "fpi-data", data, NULL); - success = fp_print_equal (print, new_scan); + if (self->prints_storage && !g_hash_table_contains (self->prints_storage, scan_id)) + { + error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND); + success = FALSE; + } + else + { + success = fp_print_equal (print, new_scan); + } if (!self->match_reported) { diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 789f3853..dea25ebc 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -273,7 +273,7 @@ class VirtualDevice(unittest.TestCase): def check_verify(self, p, scan_nick, match, identify=False): if isinstance(scan_nick, str): self.send_command('SCAN', scan_nick) - else: + elif scan_nick is not None: self.send_auto(scan_nick) self.start_verify(p, identify) @@ -330,8 +330,15 @@ class VirtualDevice(unittest.TestCase): def test_enroll_verify_no_match(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) - self.check_verify(matching, 'not-testprint', match=False, - identify=self.dev.supports_identify()) + if self.dev.has_storage(): + with self.assertRaises(GLib.Error) as error: + self.check_verify(matching, 'not-testprint', match=False, + identify=self.dev.supports_identify()) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) + else: + self.check_verify(matching, 'not-testprint', match=False, + identify=self.dev.supports_identify()) def test_enroll_verify_error(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) @@ -546,7 +553,13 @@ class VirtualDevice(unittest.TestCase): self.wait_timeout(10) self.assertFalse(self._verify_completed) - self.complete_verify() + if self.dev.has_storage(): + with self.assertRaises(GLib.Error) as error: + self.complete_verify() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) + else: + self.complete_verify() self.assertTrue(self._verify_reported) def test_close_error(self): @@ -657,8 +670,10 @@ class VirtualDeviceStorage(VirtualDevice): p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB) self.send_command('REMOVE', 'testprint') - with self.assertRaisesRegex(GLib.GError, 'Print was not found'): + with self.assertRaises(GLib.Error) as error: self.dev.delete_print_sync(p) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) def test_identify_match(self): rt = self.enroll_print('right-thumb', FPrint.Finger.RIGHT_THUMB) @@ -679,6 +694,23 @@ class VirtualDeviceStorage(VirtualDevice): self.check_verify(FPrint.Print.new(self.dev), FPrint.DeviceRetry.TOO_SHORT, identify=True, match=False) + def test_delete_multiple_times(self): + rt = self.enroll_print('right-thumb', FPrint.Finger.RIGHT_THUMB) + self.dev.delete_print_sync(rt) + + with self.assertRaisesRegex(GLib.Error, 'Print was not found'): + self.dev.delete_print_sync(rt) + + def test_verify_missing_print(self): + with self.assertRaisesRegex(GLib.Error, 'Print was not found'): + self.check_verify(FPrint.Print.new(self.dev), + 'not-existing-print', False, identify=False) + + def test_identify_missing_print(self): + with self.assertRaisesRegex(GLib.Error, 'Print was not found'): + self.check_verify(FPrint.Print.new(self.dev), + 'not-existing-print', False, identify=True) + if __name__ == '__main__': try: From 36304b736bc4538bce84819ea79366fd610ca095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 27 Jan 2021 15:02:17 +0100 Subject: [PATCH 081/103] tests/virtual-device: Properly handle exceptions on enroll callback We need to get them back to the caller function to be caught by the test suite. --- tests/virtual-device.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index dea25ebc..949a6c99 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -156,7 +156,10 @@ class VirtualDevice(unittest.TestCase): def done_cb(dev, res): print("Enroll done") - self._enrolled = dev.enroll_finish(res) + try: + self._enrolled = dev.enroll_finish(res) + except Exception as e: + self._enrolled = e self._enroll_stage = -1 def progress_cb(dev, stage, pnt, data, error): @@ -172,6 +175,9 @@ class VirtualDevice(unittest.TestCase): if self._enroll_stage < 0 and not self._enrolled: return True + if isinstance(self._enrolled, Exception): + raise(self._enrolled) + nonlocal retries self.assertLessEqual(self._enroll_stage, self.dev.get_nr_enroll_stages()) if should_retry and retries > retry_scan: From d90ee96df8c7f224acfc1a77e1ac6438c4c6b180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 27 Jan 2021 15:03:19 +0100 Subject: [PATCH 082/103] virtual-device: Return an duplicated data error if trying to re-enroll a print --- libfprint/drivers/virtual-device.c | 10 ++++++++++ tests/virtual-device.py | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index ca658dd9..6a321f64 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -558,6 +558,16 @@ dev_enroll (FpDevice *dev) GVariant *data; gboolean completed; + if (self->prints_storage && g_hash_table_contains (self->prints_storage, id)) + { + if (should_wait_to_sleep (self, id, error)) + return; + + fpi_device_enroll_complete (dev, NULL, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_DUPLICATE)); + return; + } + if (self->enroll_stages_passed == 0) { fpi_print_set_type (print, FPI_PRINT_RAW); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 949a6c99..a6ae787d 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -613,6 +613,13 @@ class VirtualDeviceStorage(VirtualDevice): self.assertFalse(self.dev.supports_capture()) self.assertTrue(self.dev.has_storage()) + def test_duplicate_enroll(self): + self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) + with self.assertRaises(GLib.Error) as error: + self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_DUPLICATE)) + def test_list_empty(self): self.assertFalse(self.dev.list_prints_sync()) From c495b8200045388806c72270fba29401072b8c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 00:47:24 +0100 Subject: [PATCH 083/103] virtual-device: Use python's with idiom to check GLib expected error messages And we can properly provide a real traceback as well --- tests/virtual-device.py | 44 ++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index a6ae787d..c8cae88e 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -13,6 +13,7 @@ try: import struct import subprocess import shutil + import traceback import glob import tempfile except Exception as e: @@ -46,6 +47,21 @@ class Connection: self.con.close() del self.con + +class GLibErrorMessage: + def __init__(self, component, level, expected_message): + self.level = level + self.component = component + self.expected_message = expected_message + + def __enter__(self): + GLib.test_expect_message(self.component, self.level, self.expected_message) + + def __exit__(self, exc_type, exc_val, exc_tb): + (filename, line, func_name, text) = traceback.extract_stack()[-2] + GLib.test_assert_expected_messages_internal(self.component, + filename, line, func_name) + class VirtualDevice(unittest.TestCase): @classmethod @@ -416,14 +432,12 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(self.dev.get_nr_enroll_stages(), 1) self.assertEqual(notified_spec.name, 'nr-enroll-stages') - GLib.test_expect_message('libfprint-device', - GLib.LogLevelFlags.LEVEL_CRITICAL, '*enroll_stages > 0*') - notified_spec = None - self.send_command('SET_ENROLL_STAGES', 0) - self.assertEqual(self.dev.get_nr_enroll_stages(), 1) - self.assertIsNone(notified_spec) - GLib.test_assert_expected_messages_internal('libfprint-device', - __file__, 0, 'test_change_enroll_stages') + with GLibErrorMessage('libfprint-device', + GLib.LogLevelFlags.LEVEL_CRITICAL, '*enroll_stages > 0*'): + notified_spec = None + self.send_command('SET_ENROLL_STAGES', 0) + self.assertEqual(self.dev.get_nr_enroll_stages(), 1) + self.assertIsNone(notified_spec) def test_quick_enroll(self): self.send_command('SET_ENROLL_STAGES', 1) @@ -446,14 +460,12 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(self.dev.get_scan_type(), scan_type) self.assertEqual(notified_spec.name, 'scan-type') - GLib.test_expect_message('libfprint-virtual_device', - GLib.LogLevelFlags.LEVEL_WARNING, '*Scan type*not found') - notified_spec = None - self.send_command('SET_SCAN_TYPE', 'eye-contact') - self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE) - self.assertIsNone(notified_spec) - GLib.test_assert_expected_messages_internal('libfprint-device', - __file__, 0, 'test_change_scan_type') + with GLibErrorMessage('libfprint-virtual_device', + GLib.LogLevelFlags.LEVEL_WARNING, '*Scan type*not found'): + notified_spec = None + self.send_command('SET_SCAN_TYPE', 'eye-contact') + self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE) + self.assertIsNone(notified_spec) def test_device_unplug(self): self._close_on_teardown = False From e1e3f6955e389d83568b6135e794c720e1c4acef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 00:54:34 +0100 Subject: [PATCH 084/103] virtual-device: Remove messages we can't process from queue when not scanning Commands that are not valid for non-scan operations should be removed from queue, or these may be re-proposed forever. --- libfprint/drivers/virtual-device.c | 6 +++++- tests/virtual-device.py | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 6a321f64..6f83a057 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -164,7 +164,11 @@ process_cmds (FpDeviceVirtualDevice * self, /* If we are not scanning, then we have to stop here. */ if (!scan) - break; + { + g_warning ("Could not process command: %s", cmd); + g_ptr_array_remove_index (self->pending_commands, 0); + break; + } if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX)) { diff --git a/tests/virtual-device.py b/tests/virtual-device.py index c8cae88e..941b30cd 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -556,6 +556,12 @@ class VirtualDevice(unittest.TestCase): self.assertFalse(self._verify_completed) self.cancel_verify() + # Since we don't really cancel here, next command will be passed to release + self._close_on_teardown = False + with GLibErrorMessage('libfprint-virtual_device', + GLib.LogLevelFlags.LEVEL_WARNING, 'Could not process command: SCAN *'): + self.dev.close_sync() + def test_device_sleep_before_completing_verify(self): enrolled = self.enroll_print('foo-print', FPrint.Finger.LEFT_RING) From 51009b48a043f528c2bf661ee2aba7c3baa88f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 01:16:12 +0100 Subject: [PATCH 085/103] virtual-device: Process supported commands on device open When opening the device we can process commands that we left for that after the previous close, to do that we only have to inject an invalid command that will be processed (and ignored) while closing, so that at next device opening we will be able to proceed with the previously sent commands. Add tests to finally check this case! --- libfprint/drivers/virtual-device.c | 20 +++++++++++++++ tests/virtual-device.py | 41 +++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 6f83a057..1acfcfef 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -78,6 +78,10 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self) FP_DEVICE_GET_CLASS (self)->delete (dev); break; + case FPI_DEVICE_ACTION_OPEN: + FP_DEVICE_GET_CLASS (self)->open (dev); + break; + case FPI_DEVICE_ACTION_CLOSE: FP_DEVICE_GET_CLASS (self)->close (dev); break; @@ -327,6 +331,22 @@ dev_init (FpDevice *dev) G_DEBUG_HERE (); + process_cmds (self, FALSE, &error); + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_open_complete (dev, g_steal_pointer (&error)); + return; + } + else if (self->sleep_timeout_id) + { + return; + } + else if (self->listener) + { + fpi_device_open_complete (dev, NULL); + return; + } + listener = fp_device_virtual_listener_new (); cancellable = g_cancellable_new (); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 941b30cd..1b98abef 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -123,7 +123,7 @@ class VirtualDevice(unittest.TestCase): def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE', - 'SET_CANCELLATION_ENABLED']) + 'SET_CANCELLATION_ENABLED', 'IGNORED_COMMAND']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -333,6 +333,45 @@ class VirtualDevice(unittest.TestCase): self.assertFalse(self.dev.supports_capture()) self.assertFalse(self.dev.has_storage()) + def test_open_error(self): + self._close_on_teardown = False + self.send_command('IGNORED_COMMAND') # This will be consumed by close + self.send_error(FPrint.DeviceError.PROTO) # This will be consumed by open + + with GLibErrorMessage('libfprint-virtual_device', + GLib.LogLevelFlags.LEVEL_WARNING, 'Could not process command: *'): + self.dev.close_sync() + + with self.assertRaises(GLib.Error) as error: + self.dev.open_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.PROTO)) + + def test_delayed_open(self): + self.send_command('IGNORED_COMMAND') # This will be consumed by close + self.send_sleep(500) # This will be consumed by open + + with GLibErrorMessage('libfprint-virtual_device', + GLib.LogLevelFlags.LEVEL_WARNING, 'Could not process command: *'): + self.dev.close_sync() + + opened = False + def on_opened(dev, res): + nonlocal opened + dev.open_finish(res) + opened = True + + self.dev.open(callback=on_opened) + + self.wait_timeout(10) + self.assertFalse(self.dev.is_open()) + + self.wait_timeout(10) + self.assertFalse(self.dev.is_open()) + + while not opened: + ctx.iteration(True) + def test_enroll(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) self.assertEqual(matching.get_username(), 'testuser') From 25a6c916aa77b46f24bc3ed6dbd8bc676a477969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 02:43:30 +0100 Subject: [PATCH 086/103] fp-device: Fix property getters for enroll stages and driver ID We were returning an invalid type for the enroll stages, while trying to get the class from the private instance for the device driver --- libfprint/fp-device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index f752a487..a5973e87 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -185,7 +185,7 @@ fp_device_get_property (GObject *object, switch (prop_id) { case PROP_NR_ENROLL_STAGES: - g_value_set_int (value, priv->nr_enroll_stages); + g_value_set_uint (value, priv->nr_enroll_stages); break; case PROP_SCAN_TYPE: @@ -197,7 +197,7 @@ fp_device_get_property (GObject *object, break; case PROP_DRIVER: - g_value_set_static_string (value, FP_DEVICE_GET_CLASS (priv)->id); + g_value_set_static_string (value, FP_DEVICE_GET_CLASS (self)->id); break; case PROP_DEVICE_ID: From e4e0937848af7b35d4b30eab0c08e34251079bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 01:35:42 +0100 Subject: [PATCH 087/103] tests/virtual-*: Check for enrolled prints properties --- tests/virtual-device.py | 5 +++++ tests/virtual-image.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 1b98abef..a373128a 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -238,6 +238,11 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(self._enrolled.get_device_stored(), self.dev.has_storage()) + self.assertEqual(self._enrolled.props.driver, self.dev.get_driver()) + self.assertEqual(self._enrolled.props.device_id, self.dev.get_device_id()) + self.assertEqual(self._enrolled.props.device_stored, self.dev.has_storage()) + self.assertEqual(self._enrolled.props.fpi_data.unpack(), nick) + self.assertIsNone(self._enrolled.props.image) return self._enrolled diff --git a/tests/virtual-image.py b/tests/virtual-image.py index ce1df509..7609bd65 100755 --- a/tests/virtual-image.py +++ b/tests/virtual-image.py @@ -223,6 +223,10 @@ class VirtualImage(unittest.TestCase): ctx.iteration(True) self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE) + self.assertEqual(self._enrolled.props.driver, self.dev.get_driver()) + self.assertEqual(self._enrolled.props.device_id, self.dev.get_device_id()) + self.assertEqual(self._enrolled.props.device_stored, self.dev.has_storage()) + self.assertIsNone(self._enrolled.get_image()) return self._enrolled @@ -244,6 +248,7 @@ class VirtualImage(unittest.TestCase): while self._verify_match is None: ctx.iteration(True) assert(self._verify_match) + self.assertIsNotNone(self._verify_fp.props.image) self._verify_match = None self._verify_fp = None From 4da52f78f67b120527bae6124680d2629b14c7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 01:44:29 +0100 Subject: [PATCH 088/103] virtual-device: Check properties match the getters --- tests/virtual-device.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index a373128a..a77a18a7 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -337,6 +337,12 @@ class VirtualDevice(unittest.TestCase): self.assertFalse(self.dev.supports_identify()) self.assertFalse(self.dev.supports_capture()) self.assertFalse(self.dev.has_storage()) + self.assertEqual(self.dev.props.driver, self.dev.get_driver()) + self.assertEqual(self.dev.props.device_id, self.dev.get_device_id()) + self.assertEqual(self.dev.props.name, self.dev.get_name()) + self.assertEqual(self.dev.props.scan_type, self.dev.get_scan_type()) + self.assertEqual(self.dev.props.nr_enroll_stages, self.dev.get_nr_enroll_stages()) + self.assertEqual(self.dev.props.open, self.dev.is_open()) def test_open_error(self): self._close_on_teardown = False From 43cf28b9dafae9c220232ae3000755663a31fbf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 02:27:40 +0100 Subject: [PATCH 089/103] fp-device: Do not try to deference potentially NULL task data In case we do an early error return in verify and identify calls we do not initialize the task data, but still in the finish functions we still try to use it. Avoid doing this, but just nullify the returned values. --- libfprint/fp-device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index a5973e87..fedaa335 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -979,7 +979,7 @@ fp_device_verify_finish (FpDevice *device, data = g_task_get_task_data (G_TASK (result)); - *print = data->print; + *print = data ? data->print : NULL; if (*print) g_object_ref (*print); } @@ -1092,13 +1092,13 @@ fp_device_identify_finish (FpDevice *device, if (print) { - *print = data->print; + *print = data ? data->print : NULL; if (*print) g_object_ref (*print); } if (match) { - *match = data->match; + *match = data ? data->match : NULL; if (*match) g_object_ref (*match); } From 33ba248c44b28a7c084058f3012ba6c58abe3a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 02:30:18 +0100 Subject: [PATCH 090/103] virtual-device: Add test checking for early errors during dev API calls --- tests/virtual-device.py | 117 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index a77a18a7..10684e6d 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -62,7 +62,7 @@ class GLibErrorMessage: GLib.test_assert_expected_messages_internal(self.component, filename, line, func_name) -class VirtualDevice(unittest.TestCase): +class VirtualDeviceBase(unittest.TestCase): @classmethod def setUpClass(cls): @@ -327,6 +327,9 @@ class VirtualDevice(unittest.TestCase): if isinstance(scan_nick, str): self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick) + +class VirtualDevice(VirtualDeviceBase): + def test_device_properties(self): self.assertEqual(self.dev.get_driver(), 'virtual_device') self.assertEqual(self.dev.get_device_id(), '0') @@ -658,6 +661,118 @@ class VirtualDevice(unittest.TestCase): self.assertEqual(close_res.code, int(FPrint.DeviceError.BUSY)) + +class VirtualDeviceClosed(VirtualDeviceBase): + + driver_name = 'virtual_device' + + def setUp(self): + super().setUp() + self._close_on_teardown = False + self.dev.close_sync() + self.assertFalse(self.dev.is_open()) + + def test_close(self): + with self.assertRaises(GLib.Error) as error: + self.dev.close_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + def test_enroll(self): + with self.assertRaises(GLib.Error) as error: + self.dev.enroll_sync(FPrint.Print.new(self.dev)) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + def test_verify(self): + with self.assertRaises(GLib.Error) as error: + self.dev.verify_sync(FPrint.Print.new(self.dev)) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + def test_identify(self): + with self.assertRaises(GLib.Error) as error: + self.dev.identify_sync([FPrint.Print.new(self.dev)]) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + def test_capture(self): + with self.assertRaises(GLib.Error) as error: + self.dev.capture_sync(wait_for_finger=False) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + def test_delete_print(self): + with self.assertRaises(GLib.Error) as error: + self.dev.delete_print_sync(FPrint.Print.new(self.dev)) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + def test_list_prints(self): + with self.assertRaises(GLib.Error) as error: + self.dev.list_prints_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.NOT_OPEN)) + + +class VirtualDeviceBusyDeviceOperations(VirtualDeviceBase): + + driver_name = 'virtual_device' + + def setUp(self): + super().setUp() + self._close_on_teardown = False + self.send_sleep(200) + self.dev.close() + + def tearDown(self): + while self.dev.is_open(): + ctx.iteration(True) + super().tearDown() + + def test_close(self): + with self.assertRaises(GLib.Error) as error: + self.dev.close_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + def test_enroll(self): + with self.assertRaises(GLib.Error) as error: + self.dev.enroll_sync(FPrint.Print.new(self.dev)) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + def test_verify(self): + with self.assertRaises(GLib.Error) as error: + self.dev.verify_sync(FPrint.Print.new(self.dev)) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + def test_identify(self): + with self.assertRaises(GLib.Error) as error: + self.dev.identify_sync([FPrint.Print.new(self.dev)]) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + def test_capture(self): + with self.assertRaises(GLib.Error) as error: + self.dev.capture_sync(wait_for_finger=False) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + def test_delete_print(self): + with self.assertRaises(GLib.Error) as error: + self.dev.delete_print_sync(FPrint.Print.new(self.dev)) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + def test_list_prints(self): + with self.assertRaises(GLib.Error) as error: + self.dev.list_prints_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + class VirtualDeviceStorage(VirtualDevice): def tearDown(self): From 27c2466bda6aff40438232f65a40a4440f56b80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 03:23:43 +0100 Subject: [PATCH 091/103] fpi-device: Mark the device as open and notify it on idle callback We're delaying any completed operation until we've completed an idle, but the open/close state is changed and notified as soon as the device completes the operation. While this can be true, it means that we notify earlier than the finish callback is actually called, while iterations are still needed to get the actual state completed, and the current_task reset. So if we'd open/close and iterate till fp_device_is_open() returns TRUE we'd end up in a state in which the device is marked as ready, but it's actually still busy since it's priv->current_task isn't unset yet. The same if we'd try to do any action on notify::opened. --- libfprint/fpi-device.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index be5b0e98..231dde95 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -752,6 +752,21 @@ fp_device_task_return_in_idle_cb (gpointer user_data) priv->current_action = FPI_DEVICE_ACTION_NONE; priv->current_task_idle_return_source = NULL; + if (action == FPI_DEVICE_ACTION_OPEN && + data->type != FP_DEVICE_TASK_RETURN_ERROR) + { + priv->is_open = TRUE; + g_object_notify (G_OBJECT (data->device), "open"); + } + else if (action == FPI_DEVICE_ACTION_CLOSE) + { + /* Always consider the device closed. Drivers should try hard to close the + * device. Generally, e.g. cancellations should be ignored. + */ + priv->is_open = FALSE; + g_object_notify (G_OBJECT (data->device), "open"); + } + /* Return FP_DEVICE_ERROR_REMOVED if the device is removed, * with the exception of a successful open, which is an odd corner case. */ if (priv->is_removed && @@ -921,12 +936,6 @@ fpi_device_open_complete (FpDevice *device, GError *error) clear_device_cancel_action (device); fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE); - if (!error) - { - priv->is_open = TRUE; - g_object_notify (G_OBJECT (device), "open"); - } - if (!error) fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, GUINT_TO_POINTER (TRUE)); @@ -977,12 +986,6 @@ fpi_device_close_complete (FpDevice *device, GError *error) return; } - /* Always consider the device closed. Drivers should try hard to close the - * device. Generally, e.g. cancellations should be ignored. - */ - priv->is_open = FALSE; - g_object_notify (G_OBJECT (device), "open"); - if (!error) fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, GUINT_TO_POINTER (TRUE)); From acd0a10e76f354dfac6c2d82a92bc526359381e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 03:32:09 +0100 Subject: [PATCH 092/103] virtual-device: Add test that open fails with a busy error if is still ongoing The idea of the test was just checking what happens when we're opening a device multiple times while a first request is still going. However, it actually ends up also checking the previous commit change because without it we'd stop the close iteration before the device is actually closed and stop the open iteration before the device is actually opened, leading to an infinite loop. --- tests/virtual-device.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 10684e6d..414370b1 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -730,6 +730,28 @@ class VirtualDeviceBusyDeviceOperations(VirtualDeviceBase): ctx.iteration(True) super().tearDown() + def test_open(self): + self.send_command('IGNORED_COMMAND') + self.send_sleep(100) + + with GLibErrorMessage('libfprint-virtual_device', + GLib.LogLevelFlags.LEVEL_WARNING, 'Could not process command: *'): + while self.dev.is_open(): + ctx.iteration(True) + + self.assertFalse(self.dev.is_open()) + self.dev.open() + with self.assertRaises(GLib.Error) as error: + self.dev.open_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.BUSY)) + + self.assertFalse(self.dev.is_open()) + while not self.dev.is_open(): + ctx.iteration(True) + + self.dev.close_sync() + def test_close(self): with self.assertRaises(GLib.Error) as error: self.dev.close_sync() From 74f8a8ee27f6356ae86a7fe14e439ac554bc86da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 11:32:46 +0100 Subject: [PATCH 093/103] virtual-device: Handle cancelled state gracefully in should_wait_to_sleep --- libfprint/drivers/virtual-device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 1acfcfef..17c7786e 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -469,7 +469,11 @@ should_wait_to_sleep (FpDeviceVirtualDevice *self, if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX)) { - g_free (process_cmds (self, FALSE, NULL)); + g_autoptr(GError) local_error = NULL; + g_free (process_cmds (self, FALSE, &local_error)); + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return FALSE; g_assert (!self->injected_synthetic_cmd); g_assert (self->sleep_timeout_id != 0); From 2f7c78eb975ebfa88ecaa5c902cde009985cf29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 12:41:21 +0100 Subject: [PATCH 094/103] virtual-device: Make possible to use a script to perform enroll operations --- libfprint/drivers/virtual-device.c | 13 ++++- tests/virtual-device.py | 81 ++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 17c7786e..af589b0c 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -613,7 +613,11 @@ dev_enroll (FpDevice *dev) if (changed) { g_set_error (&error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL, "ID Mismatch"); - fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, error); + fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, + g_steal_pointer (&error)); + + if (!should_wait_to_sleep (self, id, error)) + self->sleep_timeout_id = g_idle_add (sleep_timeout_cb, self); return; } } @@ -639,6 +643,10 @@ dev_enroll (FpDevice *dev) fpi_device_enroll_complete (dev, g_object_ref (print), NULL); self->enroll_stages_passed = 0; } + else if (!should_wait_to_sleep (self, id, error)) + { + self->sleep_timeout_id = g_idle_add (sleep_timeout_cb, self); + } } else { @@ -649,6 +657,9 @@ dev_enroll (FpDevice *dev) if (error && error->domain == FP_DEVICE_RETRY) { fpi_device_enroll_progress (dev, self->enroll_stages_passed, NULL, g_steal_pointer (&error)); + + if (!should_wait_to_sleep (self, id, error)) + self->sleep_timeout_id = g_idle_add (sleep_timeout_cb, self); } else { diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 414370b1..0d272609 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -427,6 +427,87 @@ class VirtualDevice(VirtualDeviceBase): self.check_verify(FPrint.Print.new(self.dev), FPrint.DeviceRetry.TOO_SHORT, match=False) + def test_enroll_script_interactive(self): + enrolled = None + def done_cb(dev, res): + nonlocal enrolled + try: + enrolled = dev.enroll_finish(res) + except Exception as e: + enrolled = e + + enroll_stage = 0 + enroll_progress_error = None + def progress_cb(dev, stage, pnt, data, error): + nonlocal enroll_stage, enroll_progress_error + enroll_stage = stage + enroll_progress_error = error + + def wait_for_next_stage(expected): + nonlocal enroll_stage, enroll_progress_error + enroll_progress_error = None + next_stage = enroll_stage + 1 + while enroll_stage < next_stage and not enroll_progress_error: + ctx.iteration(True) + + if isinstance(expected, FPrint.DeviceRetry): + self.assertEqual(enroll_stage, next_stage - 1) + self.assertEqual(enroll_progress_error.code, int(expected)) + else: + self.assertEqual(enroll_stage, expected) + self.assertIsNone(enroll_progress_error) + self.assertIsNone(enrolled) + + self.send_sleep(50) + self.send_command('SCAN', 'print-id') + self.send_command('SCAN', 'print-id') + self.send_auto(FPrint.DeviceRetry.TOO_SHORT) + self.send_command('SCAN', 'print-id') + self.send_sleep(50) + self.send_command('SCAN', 'print-id') + self.send_auto(FPrint.DeviceRetry.CENTER_FINGER) + self.send_command('SCAN', 'another-id') + self.send_command('SCAN', 'print-id') + + self.dev.enroll(FPrint.Print.new(self.dev), callback=done_cb, + progress_cb=progress_cb) + + wait_for_next_stage(1) + wait_for_next_stage(2) + wait_for_next_stage(FPrint.DeviceRetry.TOO_SHORT) + wait_for_next_stage(3) + wait_for_next_stage(4) + wait_for_next_stage(FPrint.DeviceRetry.CENTER_FINGER) + wait_for_next_stage(FPrint.DeviceRetry.GENERAL) + wait_for_next_stage(5) + + while not enrolled: + ctx.iteration(True) + + self.assertEqual(enrolled.get_driver(), self.dev.get_driver()) + + def test_enroll_script(self): + self.send_command('SET_ENROLL_STAGES', 8) + self.send_command('SCAN', 'print-id') + self.send_command('SCAN', 'print-id') + self.send_auto(FPrint.DeviceRetry.TOO_SHORT) + self.send_command('SCAN', 'print-id') + self.send_auto(FPrint.DeviceRetry.REMOVE_FINGER) + self.send_command('SCAN', 'print-id') + self.send_auto(FPrint.DeviceRetry.CENTER_FINGER) + self.send_command('SCAN', 'print-id') + self.send_sleep(10) + self.send_sleep(20) + self.send_auto(FPrint.DeviceRetry.GENERAL) + self.send_auto(FPrint.DeviceRetry.REMOVE_FINGER) + self.send_command('SCAN', 'print-id') + self.send_command('SCAN', 'another-id') + self.send_command('SCAN', 'print-id') + self.send_command('SCAN', 'print-id') + + enrolled = self.dev.enroll_sync(FPrint.Print.new(self.dev)) + self.assertEqual(enrolled.get_driver(), self.dev.get_driver()) + def test_finger_status(self): self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) From 27a62443a13cbbc55cce40b83eeba903e9ba0b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 12:54:12 +0100 Subject: [PATCH 095/103] virtual-device: Add SET_KEEP_ALIVE command, to keep the listener up We may want to be able to talk with the device while it's closed to queue commands to be performed once it opens (could be even a script), so to do this we need to close the device first, send those commands and eventually process them. We used a trick to send an invalid command before that was ignored by release, but having the device available is just easier to handle. So, when keep alive is enabled we don't stop the listener when closing but only on actual device disposition. --- libfprint/drivers/virtual-device-private.h | 1 + libfprint/drivers/virtual-device.c | 24 +++++++++-- tests/virtual-device.py | 50 +++++++++++++++++++--- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index 75ae6589..5a9a6baa 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -84,6 +84,7 @@ struct _FpDeviceVirtualDevice gboolean supports_cancellation; gboolean injected_synthetic_cmd; gboolean ignore_wait; + gboolean keep_alive; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index af589b0c..f39df4ea 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -44,6 +44,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) #define SET_ENROLL_STAGES_PREFIX "SET_ENROLL_STAGES " #define SET_SCAN_TYPE_PREFIX "SET_SCAN_TYPE " #define SET_CANCELLATION_PREFIX "SET_CANCELLATION_ENABLED " +#define SET_KEEP_ALIVE_PREFIX "SET_KEEP_ALIVE " #define LIST_CMD "LIST" #define UNPLUG_CMD "UNPLUG" @@ -289,6 +290,13 @@ recv_instruction_cb (GObject *source_object, g_debug ("Cancellation support toggled: %d", self->supports_cancellation); } + else if (g_str_has_prefix (cmd, SET_KEEP_ALIVE_PREFIX)) + { + self->keep_alive = g_ascii_strtoull ( + cmd + strlen (SET_KEEP_ALIVE_PREFIX), NULL, 10) != 0; + + g_debug ("Keep alive toggled: %d", self->keep_alive); + } else { g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); @@ -692,6 +700,14 @@ dev_cancel (FpDevice *dev) maybe_continue_current_action (self); } +static void +stop_listener (FpDeviceVirtualDevice *self) +{ + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_object (&self->listener); +} + static void dev_deinit (FpDevice *dev) { @@ -711,10 +727,9 @@ dev_deinit (FpDevice *dev) g_clear_handle_id (&self->wait_command_id, g_source_remove); g_clear_handle_id (&self->sleep_timeout_id, g_source_remove); - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - g_clear_object (&self->listener); - g_clear_object (&self->listener); + + if (!self->keep_alive) + stop_listener (self); fpi_device_close_complete (dev, NULL); } @@ -725,6 +740,7 @@ fpi_device_virtual_device_finalize (GObject *object) FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (object); G_DEBUG_HERE (); + stop_listener (self); g_clear_pointer (&self->pending_commands, g_ptr_array_unref); G_OBJECT_CLASS (fpi_device_virtual_device_parent_class)->finalize (object); } diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 0d272609..7227fd7c 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -123,7 +123,7 @@ class VirtualDeviceBase(unittest.TestCase): def send_command(self, command, *args): self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY', 'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE', - 'SET_CANCELLATION_ENABLED', 'IGNORED_COMMAND']) + 'SET_CANCELLATION_ENABLED', 'SET_KEEP_ALIVE', 'IGNORED_COMMAND']) with Connection(self.sockaddr) as con: params = ' '.join(str(p) for p in args) @@ -162,6 +162,9 @@ class VirtualDeviceBase(unittest.TestCase): else: raise Exception('No known type found for {}'.format(obj)) + def set_keep_alive(self, value): + self.send_command('SET_KEEP_ALIVE', 1 if value else 0) + def send_sleep(self, interval): self.assertGreater(interval, 0) multiplier = 5 if 'UNDER_VALGRIND' in os.environ else 1 @@ -361,6 +364,17 @@ class VirtualDevice(VirtualDeviceBase): self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), FPrint.DeviceError.PROTO)) + def test_open_error_with_keep_alive(self): + self._close_on_teardown = False + self.set_keep_alive(True) + self.dev.close_sync() + + self.send_error(FPrint.DeviceError.PROTO) + with self.assertRaises(GLib.Error) as error: + self.dev.open_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.PROTO)) + def test_delayed_open(self): self.send_command('IGNORED_COMMAND') # This will be consumed by close self.send_sleep(500) # This will be consumed by open @@ -386,6 +400,28 @@ class VirtualDevice(VirtualDeviceBase): while not opened: ctx.iteration(True) + def test_delayed_open_with_keep_alive(self): + self.set_keep_alive(True) + self.dev.close_sync() + + opened = False + def on_opened(dev, res): + nonlocal opened + dev.open_finish(res) + opened = True + + self.send_sleep(500) + self.dev.open(callback=on_opened) + + self.wait_timeout(10) + self.assertFalse(self.dev.is_open()) + + self.wait_timeout(10) + self.assertFalse(self.dev.is_open()) + + while not opened: + ctx.iteration(True) + def test_enroll(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE) self.assertEqual(matching.get_username(), 'testuser') @@ -485,6 +521,7 @@ class VirtualDevice(VirtualDeviceBase): ctx.iteration(True) self.assertEqual(enrolled.get_driver(), self.dev.get_driver()) + self.assertEqual(enrolled.props.fpi_data.unpack(), 'print-id') def test_enroll_script(self): self.send_command('SET_ENROLL_STAGES', 8) @@ -507,6 +544,7 @@ class VirtualDevice(VirtualDeviceBase): enrolled = self.dev.enroll_sync(FPrint.Print.new(self.dev)) self.assertEqual(enrolled.get_driver(), self.dev.get_driver()) + self.assertEqual(enrolled.props.fpi_data.unpack(), 'print-id') def test_finger_status(self): self.start_verify(FPrint.Print.new(self.dev), @@ -812,15 +850,13 @@ class VirtualDeviceBusyDeviceOperations(VirtualDeviceBase): super().tearDown() def test_open(self): - self.send_command('IGNORED_COMMAND') - self.send_sleep(100) + self.set_keep_alive(True) - with GLibErrorMessage('libfprint-virtual_device', - GLib.LogLevelFlags.LEVEL_WARNING, 'Could not process command: *'): - while self.dev.is_open(): - ctx.iteration(True) + while self.dev.is_open(): + ctx.iteration(True) self.assertFalse(self.dev.is_open()) + self.send_sleep(100) self.dev.open() with self.assertRaises(GLib.Error) as error: self.dev.open_sync() From 88117c172e6471064f819d289f44f0d7948e8246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 14:09:50 +0100 Subject: [PATCH 096/103] tests/virtual-device: Add enroll and verify script test --- tests/virtual-device.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 7227fd7c..68728e07 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -159,6 +159,8 @@ class VirtualDeviceBase(unittest.TestCase): self.send_finger_report(obj & FPrint.FingerStatusFlags.PRESENT, iterate=False) elif isinstance(obj, FPrint.ScanType): self.send_command('SET_SCAN_TYPE', obj.value_nick) + elif isinstance(obj, FPrint.Print) and obj.props.fpi_data: + self.send_command('SCAN', obj.props.fpi_data.unpack()) else: raise Exception('No known type found for {}'.format(obj)) @@ -546,6 +548,39 @@ class VirtualDevice(VirtualDeviceBase): self.assertEqual(enrolled.get_driver(), self.dev.get_driver()) self.assertEqual(enrolled.props.fpi_data.unpack(), 'print-id') + return enrolled + + def test_enroll_verify_script(self): + enrolled = self.test_enroll_script() + self.send_auto(FPrint.DeviceRetry.CENTER_FINGER) + with self.assertRaises(GLib.GError) as error: + self.dev.verify_sync(enrolled) + self.assertTrue(error.exception.matches(FPrint.DeviceRetry.quark(), + FPrint.DeviceRetry.CENTER_FINGER)) + + self.send_sleep(50) + self.send_auto(FPrint.DeviceRetry.TOO_SHORT) + with self.assertRaises(GLib.GError) as error: + self.dev.verify_sync(enrolled) + self.assertTrue(error.exception.matches(FPrint.DeviceRetry.quark(), + FPrint.DeviceRetry.TOO_SHORT)) + + self.send_command('SCAN', 'another-id') + if self.dev.has_storage(): + with self.assertRaises(GLib.GError) as error: + self.dev.verify_sync(enrolled) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) + else: + verify_match, verify_fp = self.dev.verify_sync(enrolled) + self.assertFalse(verify_match) + self.assertFalse(verify_fp.equal(enrolled)) + + self.send_auto(enrolled) + verify_match, verify_fp = self.dev.verify_sync(enrolled) + self.assertTrue(verify_match) + self.assertTrue(verify_fp.equal(enrolled)) + def test_finger_status(self): self.start_verify(FPrint.Print.new(self.dev), identify=self.dev.supports_identify()) From b2a64cc980ad73af93ea9361c86cdceb0f188325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 28 Jan 2021 15:21:23 +0100 Subject: [PATCH 097/103] virtual-device: Do actual errors codes checks instead of regex checks --- tests/virtual-device.py | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tests/virtual-device.py b/tests/virtual-device.py index 68728e07..b9889e09 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -456,14 +456,18 @@ class VirtualDevice(VirtualDeviceBase): def test_enroll_verify_error(self): matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING) - with self.assertRaisesRegex(GLib.Error, r"An unspecified error occurred"): + with self.assertRaises(GLib.Error) as error: self.check_verify(matching, FPrint.DeviceError.GENERAL, match=False, identify=self.dev.supports_identify()) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.GENERAL)) def test_enroll_verify_retry(self): - with self.assertRaisesRegex(GLib.GError, 'too short'): + with self.assertRaises(GLib.GError) as error: self.check_verify(FPrint.Print.new(self.dev), FPrint.DeviceRetry.TOO_SHORT, match=False) + self.assertTrue(error.exception.matches(FPrint.DeviceRetry.quark(), + FPrint.DeviceRetry.TOO_SHORT)) def test_enroll_script_interactive(self): enrolled = None @@ -695,8 +699,10 @@ class VirtualDevice(VirtualDeviceBase): self.assertTrue(self.dev.props.removed) self.assertTrue(removed) - with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): + with self.assertRaises(GLib.GError) as error: self.dev.close_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.REMOVED)) def test_device_unplug_during_verify(self): self._close_on_teardown = False @@ -723,13 +729,17 @@ class VirtualDevice(VirtualDeviceBase): self.assertTrue(self.dev.props.removed) self.assertFalse(removed) - with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): + with self.assertRaises(GLib.GError) as error: self.complete_verify() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.REMOVED)) self.assertTrue(removed) - with self.assertRaisesRegex(GLib.GError, 'device has been removed from the system'): + with self.assertRaises(GLib.GError) as error: self.dev.close_sync() + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.REMOVED)) def test_device_sleep(self): self.send_sleep(1500) @@ -1060,26 +1070,34 @@ class VirtualDeviceStorage(VirtualDevice): self.check_verify(rt, 'left-thumb', identify=True, match=False) def test_identify_retry(self): - with self.assertRaisesRegex(GLib.GError, 'too short'): + with self.assertRaises(GLib.GError) as error: self.check_verify(FPrint.Print.new(self.dev), FPrint.DeviceRetry.TOO_SHORT, identify=True, match=False) + self.assertTrue(error.exception.matches(FPrint.DeviceRetry.quark(), + FPrint.DeviceRetry.TOO_SHORT)) def test_delete_multiple_times(self): rt = self.enroll_print('right-thumb', FPrint.Finger.RIGHT_THUMB) self.dev.delete_print_sync(rt) - with self.assertRaisesRegex(GLib.Error, 'Print was not found'): + with self.assertRaises(GLib.Error) as error: self.dev.delete_print_sync(rt) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) def test_verify_missing_print(self): - with self.assertRaisesRegex(GLib.Error, 'Print was not found'): + with self.assertRaises(GLib.Error) as error: self.check_verify(FPrint.Print.new(self.dev), 'not-existing-print', False, identify=False) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) def test_identify_missing_print(self): - with self.assertRaisesRegex(GLib.Error, 'Print was not found'): + with self.assertRaises(GLib.Error) as error: self.check_verify(FPrint.Print.new(self.dev), 'not-existing-print', False, identify=True) + self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(), + FPrint.DeviceError.DATA_NOT_FOUND)) if __name__ == '__main__': From 6a62d32c8110abaef63695271cc035873079e503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 29 Jan 2021 20:02:15 +0100 Subject: [PATCH 098/103] goodix: Consume the retry errors during verify/identify reports We should not pass such kind of errors to complete functions, or we'll fail the identification without ability to retry immediately. --- libfprint/drivers/goodixmoc/goodix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 82913d73..81cdb678 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -468,9 +468,9 @@ fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error) if (error && error->domain == FP_DEVICE_RETRY) { if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY) - fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, error); + fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error)); else - fpi_device_identify_report (dev, NULL, NULL, error); + fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error)); } if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY) From 3bb38e2ff645aae3c1af31c8ebabdc3a7370deec Mon Sep 17 00:00:00 2001 From: fengqiangguo Date: Tue, 19 Jan 2021 03:00:07 -0500 Subject: [PATCH 099/103] goodixmoc: support power button shield feature Some OEM will integrate fingerprint device with powerButton. It's possible that a user may press the power button during fingerprint enroll or identify. This would lead to unintended PC shutdown or hibernation. We add pwr_btn_shield cmd and related process to shield the power button function when the fingerprint functionality (enroll and identify) is used and restore power button function afterwards. --- libfprint/drivers/goodixmoc/goodix.c | 121 ++++++- libfprint/drivers/goodixmoc/goodix.h | 8 +- libfprint/drivers/goodixmoc/goodix_proto.c | 10 + libfprint/drivers/goodixmoc/goodix_proto.h | 11 + tests/goodixmoc/custom.ioctl | 346 ++++++++------------- tests/goodixmoc/device | 103 +++--- 6 files changed, 320 insertions(+), 279 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 81cdb678..9cfdbe68 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -58,6 +58,7 @@ struct _FpiDeviceGoodixMoc GPtrArray *list_result; guint8 template_id[TEMPLATE_ID_SIZE]; gboolean is_enroll_identify; + gboolean is_power_button_shield_on; }; @@ -309,6 +310,35 @@ goodix_sensor_cmd (FpiDeviceGoodixMoc *self, } + +/****************************************************************************** + * + * fp_pwr_btn_shield_cb Function + * + *****************************************************************************/ +static void +fp_pwr_btn_shield_cb (FpiDeviceGoodixMoc *self, + gxfp_cmd_response_t *resp, + GError *error) +{ + if (error) + { + fpi_ssm_mark_failed (self->task_ssm, error); + return; + } + if (resp->result >= GX_FAILED) + { + fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result); + fpi_ssm_mark_failed (self->task_ssm, + fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL)); + return; + } + if (resp->power_button_shield_resp.resp_cmd1 == MOC_CMD1_PWR_BTN_SHIELD_ON) + self->is_power_button_shield_on = true; + else + self->is_power_button_shield_on = false; + fpi_ssm_next_state (self->task_ssm); +} /****************************************************************************** * * fp_verify_xxxx Function @@ -419,7 +449,7 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, fpi_device_identify_report (device, NULL, NULL, error); } - fpi_ssm_mark_completed (self->task_ssm); + fpi_ssm_next_state (self->task_ssm); } @@ -436,6 +466,14 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device) switch (fpi_ssm_get_cur_state (ssm)) { + case FP_VERIFY_PWR_BTN_SHIELD_ON: + goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON, + false, + NULL, + 0, + fp_pwr_btn_shield_cb); + break; + case FP_VERIFY_CAPTURE: fpi_device_report_finger_status_changes (device, FP_FINGER_STATUS_NEEDED, @@ -454,6 +492,14 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device) TEMPLATE_ID_SIZE, fp_verify_cb); break; + + case FP_VERIFY_PWR_BTN_SHIELD_OFF: + goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF, + false, + NULL, + 0, + fp_pwr_btn_shield_cb); + break; } } @@ -812,6 +858,16 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device) } break; + case FP_ENROLL_PWR_BTN_SHIELD_ON: + { + goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON, + false, + NULL, + 0, + fp_pwr_btn_shield_cb); + } + break; + case FP_ENROLL_IDENTIFY: { dummy[0] = 0x01; @@ -926,9 +982,17 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device) } break; + + case FP_ENROLL_PWR_BTN_SHIELD_OFF: + { + goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF, + false, + NULL, + 0, + fp_pwr_btn_shield_cb); + } + break; } - - } static void @@ -1282,6 +1346,7 @@ gx_fp_init (FpDevice *device) int ret = 0; self->max_stored_prints = FP_MAX_FINGERNUM; + self->is_power_button_shield_on = false; self->cancellable = g_cancellable_new (); @@ -1317,20 +1382,59 @@ gx_fp_init (FpDevice *device) } static void -gx_fp_exit (FpDevice *device) +gx_fp_release_interface (FpiDeviceGoodixMoc *self, + GError *error) { - FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device); - GError *error = NULL; + g_autoptr(GError) release_error = NULL; g_clear_object (&self->cancellable); g_clear_pointer (&self->sensorcfg, g_free); /* Release usb interface */ - g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)), - 0, 0, &error); + g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), + 0, 0, &release_error); + /* Retain passed error if set, otherwise propagate error from release. */ + if (error == NULL) + error = g_steal_pointer (&release_error); /* Notify close complete */ fpi_device_close_complete (FP_DEVICE (self), error); + +} + +static void +gx_fp_exit_cb (FpiDeviceGoodixMoc *self, + gxfp_cmd_response_t *resp, + GError *error) +{ + + + if (resp->result >= GX_FAILED) + fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result); + self->is_power_button_shield_on = false; + gx_fp_release_interface (self, error); +} + +static void +gx_fp_exit (FpDevice *device) +{ + FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device); + + if (self->is_power_button_shield_on) + { + goodix_sensor_cmd (self, + MOC_CMD0_PWR_BTN_SHIELD, + MOC_CMD1_PWR_BTN_SHIELD_OFF, + false, + NULL, + 0, + gx_fp_exit_cb); + } + else + { + gx_fp_release_interface (self, NULL); + } + } @@ -1432,7 +1536,6 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self) static void gx_fp_cancel (FpDevice *device) { - FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device); /* Cancel any current interrupt transfer (resulting us to go into diff --git a/libfprint/drivers/goodixmoc/goodix.h b/libfprint/drivers/goodixmoc/goodix.h index c38bf9b9..23e142ac 100644 --- a/libfprint/drivers/goodixmoc/goodix.h +++ b/libfprint/drivers/goodixmoc/goodix.h @@ -40,7 +40,8 @@ typedef enum { typedef enum { - FP_ENROLL_ENUM = 0, + FP_ENROLL_PWR_BTN_SHIELD_ON = 0, + FP_ENROLL_ENUM, FP_ENROLL_IDENTIFY, FP_ENROLL_CREATE, FP_ENROLL_CAPTURE, @@ -48,11 +49,14 @@ typedef enum { FP_ENROLL_WAIT_FINGER_UP, FP_ENROLL_CHECK_DUPLICATE, FP_ENROLL_COMMIT, + FP_ENROLL_PWR_BTN_SHIELD_OFF, FP_ENROLL_NUM_STATES, } FpEnrollState; typedef enum { - FP_VERIFY_CAPTURE = 0, + FP_VERIFY_PWR_BTN_SHIELD_ON = 0, + FP_VERIFY_CAPTURE, FP_VERIFY_IDENTIFY, + FP_VERIFY_PWR_BTN_SHIELD_OFF, FP_VERIFY_NUM_STATES, } FpVerifyState; diff --git a/libfprint/drivers/goodixmoc/goodix_proto.c b/libfprint/drivers/goodixmoc/goodix_proto.c index 962fd6e7..01044a94 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.c +++ b/libfprint/drivers/goodixmoc/goodix_proto.c @@ -317,6 +317,16 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c /* just check result */ break; + case MOC_CMD0_PWR_BTN_SHIELD: + presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd); + if (buffer_len >= 2) + { + uint8_t support_pwr_shield = buffer[1]; + if (support_pwr_shield == 0xFF) + g_debug ("Power button shield feature not supported!\n"); + } + break; + case MOC_CMD0_GET_VERSION: if (buffer_len < sizeof (gxfp_version_info_t) + 1) return -1; diff --git a/libfprint/drivers/goodixmoc/goodix_proto.h b/libfprint/drivers/goodixmoc/goodix_proto.h index e98e4e44..bcd1cdd0 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.h +++ b/libfprint/drivers/goodixmoc/goodix_proto.h @@ -75,6 +75,11 @@ #define MOC_CMD1_GET_FINGER_MODE 0x00 #define MOC_CMD1_SET_FINGER_DOWN 0x01 #define MOC_CMD1_SET_FINGER_UP 0x02 + +#define MOC_CMD0_PWR_BTN_SHIELD 0xE0 +#define MOC_CMD1_PWR_BTN_SHIELD_OFF 0x00 +#define MOC_CMD1_PWR_BTN_SHIELD_ON 0x01 + /* */ typedef struct _gxfp_version_info @@ -173,6 +178,11 @@ typedef struct _fp_finger_config uint8_t max_stored_prints; } fp_finger_config_t, *pfp_finger_config_t; +typedef struct _fp_pwr_btn_shield +{ + uint8_t resp_cmd1; +} fp_pwr_btn_shield_t, *pfp_pwr_btn_shield_t; + typedef struct _fp_cmd_response { uint8_t result; @@ -189,6 +199,7 @@ typedef struct _fp_cmd_response gxfp_version_info_t version_info; fp_finger_status_t finger_status; fp_finger_config_t finger_config; + fp_pwr_btn_shield_t power_button_shield_resp; }; } gxfp_cmd_response_t, *pgxfp_cmd_response_t; diff --git a/tests/goodixmoc/custom.ioctl b/tests/goodixmoc/custom.ioctl index 21c85316..496b43c4 100644 --- a/tests/goodixmoc/custom.ioctl +++ b/tests/goodixmoc/custom.ioctl @@ -1,307 +1,217 @@ -@DEV /dev/bus/usb/001/003 +@DEV /dev/bus/usb/003/008 USBDEVFS_GET_CAPABILITIES 0 FD010000 USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 D00000000500BA4500611A297F USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000008009D6200D00001B5A57582000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000008009D6200D00000239572F5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 D0000001850067980001FE415050000000000030313030303232384C454E4F564F0000474D3138384230004746333230360000312E30322E30310055534200000000005642530000000000303030303030303300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051239DE6303030303033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 140 140 0 C001000184008E71000064500F410C0A1800002300000101000101010100010105050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B737316F3EB36C6A + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 D0000001850067980002FE4150500000000000303130303032343744454C4C00000000474D3138384230004746353238380000312E30342E30352E31302E3530000000000000000000000000000000000000005553420000000000564253000000000030303030303030330000000000000000000000000000000000000000000000000000000000003B5CB43C000000000000555342000000000056425300000000003030303030303033000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 140 140 0 C001000184008E71000064500F41080A1800002300000101000101010100010105050100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B737316F0558B152 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000208004BB400C00101C96A6C6B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000208004BB400C001005F5A6B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 C00100030500FB040093B3ED01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A6000002050049B600C27E4B39 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 C00100030700D12E0014140342C8AE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E00100020400BE41BBC7BACE USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000004080036C900A60001F1AFC9FB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000004080036C900E00101C26FC596000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A60000050600609F000094D6C40E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000030700AC53000F411A349263 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E0010005080054AB00141441240D0ECF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A6000003050022DD00CA3B9C30 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000060800E01F00A20001605AE410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000060800E01F00A60001BCF2ED17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A2000007070007F8005564FA6B157100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A50000042400F40B000000000000000000000000000000000000000000000000000000000000000095D4A28A + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A60000070600B64900007A6860130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000040700BA45000F41625785F3 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000080800CC3300A500013F9036A9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000080800CC3300A20001BA8679AC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A50000090500DE2103D6515435000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A10000050500807F007BE269C4 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000090C00BC430054640027004D0084CD5EED0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A500000524009F60000000000000000000000000000000000000000000000000000000000000000048D9D8CB USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000A08001AE500A10001AE651B42000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000A08001AE500A5000172CD1245000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A100000B250002FD00B786B17D6A044D24C1651C2B1A76F6396D790639F58CA6D62DDDB8E179A9BD4A6C5C6C9200000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000607006C93000F41A33C2AB4 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A500000B050008F703C6DBFA26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A100000605003DC200632D10DE USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000C0800679800A200011C98B985000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000C0800679800A100014526FF87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200000D0700807F0059643EDA283F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000007070055AA016450891085EC + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A100000D25007F8000D7843025CC713EA1543DF81EBAAF6BE244543EB9F4BC6FA74E8F246A711CD8C3EA54665F00000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000007070007F8000F41630A457A USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000E0800B14E00A000013F11196A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00000E0800B14E00A2000151C59D69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000000F070004FB000000E0109A2200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200080500629D004A354747 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200000F0C00C13E003E620027005900101FD1980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000008070012ED016450F8E6B5D9 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001008003FC000B002017532670A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001008003FC000A0000187F37724000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200114500A15E008E0091009E006F0083007C006D00690079008800000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000000000000000000000988D37C39E006F0083007C006D00690079008800000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000907002BD4000F41D2CA1A81 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000001107008A7500000002FCFB4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020009050009F6004270904E USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000120800E91600A20001A47AD7CB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000120800E91600B00201386F43E6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001307000EF1004B640F46BD2D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000A0700C43B016450398D1A9E + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002001345007788008A009C009400880008009A0099008B00080008009100850000000000000000008F00A4009B0090008F00A100A000940088009A0097008D000000000000000000BEDDBBB29400880008009A0099008B00080008009100850000000000000000008F00A4009B0090008F00A100A000940088009A0097008D +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000A07009669000F41D397DA08 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000140800946B00A0000121EDB70D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000140800946B00A200014F39330E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A0000015070021DE0000007BC22C5100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000B0500DF200052FA3E5D + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000150C00E41B004E640027004F00755632510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000B0700AF50016450F9BB7550 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000016080042BD00B002019E7183CF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000016080042BD00A000016CB093E1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200174500DC23008200A200AA0093009F009800A90087009A009100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000000000000000000000F1B14CECAA0093009F009800A90087009A009100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000C0700EB14000F416BC2A256 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000170700F708000000BAA9831600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000C0500C93600FFA00844 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001808006E9100A20001D8B88A5E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001808006E9100B0020144AD1E73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001907008976005664DBD4593000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000D0700D22D01645041EE0D0E + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200194500F00F008C009C009600080086009D0097008E00810092009100850000000000000000008F00A4009A008F008E00A1009F00920087009A0096008C000000000000000000E3A1F2A19600080086009D0097008E00810092009100850000000000000000008F00A4009A008F008E00A1009F00920087009A0096008C +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000D0700807F000F41ABF4CD98 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001A0800B84700A00001FB312AB1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001A0800B84700A2000195E5AEB2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000001B07000DF2000000CA0273AA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000E05001FE000EF2AA657 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001B0C00C8370048640027005A00021B15CE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000000E07006F9001645040B3CD87 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001C0800C53A00B00201E2B3DE5A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001C0800C53A00A000011072CE74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002001D45005BA400A8009100AB0071008B008F009100920093009100000000000000000000000000AF00A500AD00A000B100A300AA00A200A3009C000000000000000000000000008A57E0B3AB0071008B008F009100920093009100000000000000000000000000AF00A500AD00A000B100A300AA00A200A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200000F070056A9000F416A9F62DF + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000001D0700708F003A000B89A2D100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002000F0500748B00E76F715E USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001E080013EC00A2000133FB6E9B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00001E080013EC00B00201AFEEFAB6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200001F0700F40B005A625A6BF72B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000100700E11E016450A25FACED + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002001F45008D720008009900920086008800960097008D007F0091008D00850000000000000000008F00A4009B0090008F00A100A000930087009A0096008D00000000000000000069C4E77C920086008800960097008D007F0091008D00850000000000000000008F00A4009B0090008F00A100A000930087009A0096008D +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000100700B34C000F4148456C7B USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000200800DE2100A000011D15EAC2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000200800DE2100A2000173C16EC1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002107006B94002900A6F807F200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200110500FA0500438F0629 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000210C00AE510048640027005500DD002B870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001107008A750164506269C323 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000022080008F700B00201A289DE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000022080008F700A000015048CE2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200234500966900870088008800700085009600940070001A001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D0000000000000000000000000074CA825A8800700085009600940070001A001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000120700659A000F41892EC33C + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000230700BD420000008C0CEEF100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020012050047B8005B407F33 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000240800758A00A20001D5DFAEE8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000240800758A00B0020149CA3AC5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000250700926D00556427B73E5900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001307005CA3016450A3026C64 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200254500EB14008D00A100900087000800980099008C00080008000800080000000000000000008F00A3009A008F008E00A0009F00930087009A0096008C0000000000000000000F8D1061900087000800980099008C00080008000800080000000000000000008F00A3009A008F008E00A0009F00930087009A0096008C +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001307000EF1000F414918ACF2 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000260800A35C00A00001F6560E07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000260800A35C00A2000198828A04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A0000027070016E90058265460564800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001405003AC500FE5F9E23 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000270C00D32C0057640027004E0017D2351D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001407004AB5016450DB617BF4 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002808008F7000B00201DE4B8395000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002808008F7000A000012C8A93BB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B0020029450011EE007B00950097006E0084008A007400720078008000000000000000000000000000AE00A500AD00A000B100A200AA00A300A3009D000000000000000000000000007AB44F7697006E0084008A007400720078008000000000000000000000000000AE00A500AD00A000B100A200AA00A300A3009D00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000150700738C000F41F14DD4AC + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002907003AC500000044F2661300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020015050051AE00F61A492A USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002A080059A600A200010F033354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002A080059A600B002019316A779000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200002B0700BE4100566455244C8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001607009C630164501A0AD4B3 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002002B4500C7380089009C00920008008A00990098008A007F0093008E00860000000000000000008F00A4009A008F008E00A100A000930087009A0096008D000000000000000000A0269EE8920008008A00990098008A007F0093008E00860000000000000000008F00A4009A008F008E00A100A000930087009A0096008D +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000160700CE31000F41F0101425 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002C080024DB00A000018A945392000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002C080024DB00A20001E440D791000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002D0700916E005F2DD3D14D7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200170500877800E690E739 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200002D0C0054AB004A64002700590057B20D220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000170700F708016450DA3CBB7D USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002E0800F20D00B0020135086750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00002E0800F20D00A00001C7C9777E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002002F45006C9300A80083008A006D00870082008900940074001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000000000000000000000DD3369188A006D00870082008900940074001A00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009D00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000180700E21D000F4141D04BDE + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000002F070047B8004C4C4EAAB86E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200180500C03F00B4605C02 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003008007C8300A2000111FF9D33000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003008007C8300B002018DEA091E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200003107009B6400586440DB796400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000190700DB240164506BFCE486 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200314500E21D00080008000800080088009A0096008F00820092009000080000000000000000008F00A3009A008F008E00A000A000930087009A0096008C000000000000000000E0BA753D0800080088009A0096008F00820092009000080000000000000000008F00A3009A008F008E00A000A000930087009A0096008C +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001907008976000F4181E62410 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000320800AA5500A0000132763DDC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000320800AA5500A200015CA2B9DF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003307001FE072635FE0E8A18200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001A050016E900A4EAF211 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000330C00DA25005464002700500088A694DC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001A070066990164506AA1240F USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000340800D72800B002012BF4C937000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000340800D72800A00001D935D919000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B0020035450049B6007D00920094008C009A008B008400890094006D00000000000000000000000000AE00A500AD00A000B100A300AA00A200A3009D00000000000000000000000000520A47F394008C009A008B008400890094006D00000000000000000000000000AE00A500AD00A000B100A300AA00A200A3009D00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001B07005FA0000F41408D8B57 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000350700629D0000006775A83E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001B05007D8200ACAF2518 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000036080001FE00A20001FABC79F6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000036080001FE00B0020166A9EDDB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000370700E619005964B9BF1A2300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001C07001BE4016450D2F45C51 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002003745009F600008000800080008008600970095000800830090008D00880000000000000000008F00A3009A008F008E00A100A000930087009A0096008C000000000000000000F054EC42080008008600970095000800830090008D00880000000000000000008F00A3009A008F008E00A100A000930087009A0096008C +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001C070049B6000F4138EE9CC7 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003808002DD200A000014EB46049000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003808002DD200A200012060E44A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003907009867725F526A136B6D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002001D050000FF0009B0C408 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000390C005DA2004A640027004F005D569D1A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001D0700708F01645012C2339F USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003A0800FB0400B00201F128548B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003A0800FB0400A0000103E944A5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002003B4500659A0084007D008B0099009C006A009A007B0089008300000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000000000000000000000BAEEF1FA8B0099009C006A009A007B0089008300000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200001E07009F60000F41F9853380 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003B07004EB1000000D6B5F7C500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A300001E0700B649000F41F8F75650 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003C0800867900A20001867E2463000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003C0800867900A30001B114E662000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200003D0700619E005864307089D800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000001F0700A659016450D3A99CD8 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A300003D0500629D009DDA98C4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 A400001F6A001EE1640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900E6F6BD05 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003E080050AF00A00001A5F7848C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00003E080050AF00A40001795F8D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000003F0700E51A0063324BE2275A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200200500708F00DCB5EECB + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A400003F05006B940099962233000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E0000020040049B6AEA0E8AB USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004008001BE400B00201E7BD49D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004008001BE400E00001D5F1C38E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200414500857A0078006F0074009200A6008C0071006C008E009400000000000000000000000000AF00A500AD00A000B100A300A900A200A3009C0000000000000000000000000079DB6FC674009200A6008C0071006C008E009400000000000000000000000000AF00A500AD00A000B100A300A900A200A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000021070039C6000F41C7E8B94B + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E000004108001BE400000000315A099D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A60000210500B74800B39B168D USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000420800CD3200A2000136F5F911000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000420800CD3200A60001EA5DF016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200004307002AD5005A647427533000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000220700D6290164502CAFB954 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 A60000436C00EC130001640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900FA60A49A000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E00100220400FD0253E4FA3B USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000440800B04F00A00001B36299D7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000440800B04F00E0010132DE18BE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A0000045070005FA0061447F5F4C1200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B00200230500CD3200C47A97D1 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E00100450800D22D000000002B1189D3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000230700EF100100238AF5F029 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000460800669900B002010CFEAD15000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000460800669900A2000190EB3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200474500F807009500860087008D00A3006D007D0081009C007C00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C0000000000000000000000000074D7CC3787008D00A3006D007D0081009C007C00000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000240700F906000F417EE0019C + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000470C0016E9004C640027004D005C10F4310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A50000242400B7480000000000000000000000000000000000000000000000000000000000000000664B5D3F USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004808004AB500A200014A37A484000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004808004AB500A50001CF21EB81000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000490700AD52005764F1A7756700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000250700C03F01645054CCAEC4 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A50000499200D22D004C642A00000000640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04D4A2B430F0D25BF63D97E631EC0F0F86A6A3DCDEF50C82BB7E8C2D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E000002504008976203A9633 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004A08009C6300A0000169BE046B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004A08009C6300E00001A9339E1B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000004B070029D60041281F96933800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002605000DF20079AA0FDB + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E000004B08009C63004C642A9C8BFEAB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E0010026040056A9D15D8DC2 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004C0800E11E00B00201703CF080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004C0800E11E00E00101034161C7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002004D45007F80009E008E008E007E00AB00840096007F0092008100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000000000000000000000D393E7738E007E00AB00840096007F0092008100000000000000000000000000AF00A500AD00A000B100A300AA00A300A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000027070044BB000F417FBDC115 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E001004D0800837C004C642ACB9D5A09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A2000027070044BB010023F3CB2730 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00004E080037C800A20001A1744041000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200004F0700D02F005964C7DF8EA700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000028070051AE016450E45131B6 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200004F0C0047B80052640027004D00E19CE96F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A500002824004DB200000000000000000000000000000000000000000000000000000000000000003DB8032C USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000500800B94600A000017742AA0C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000500800B94600A500019C80610A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000005107000CF300624F1EC75A2600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002905004AB5002B5AB4E0 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A5000051920021DE0052642A00000000640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04D4A2B430F0D25BF63D97E631EC0F0F86A6A3DCDEF50CCC7D08E82D30303030303030302D302D30303030303030302D6E6F626F647900954F9F36EAEDD0364E04 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 12 12 0 E00000290400738C14C55D45 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005208006F9000B00201C8DE9ECE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005208006F9000E00001FA921490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B00200534500F10E0077007A00720083007500930073007E006E008200000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C00000000000000000000000000C5190965720083007500930073007E006E008200000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200002A0700D52A000F41CF205E67 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 E000005308006F900052642AB5A4CC36000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 A700002A6A0044BB640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479001CF66539 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000054080012ED00A20001BF88EE26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000054080012ED00A70001544A2520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000550700F50A0058641D3C23CD00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000002B0700EC13016450E50CF13F - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000560800C43B00A000019C014EC9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000570700718E726054F685049700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002C05008A7500968A2CEA - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000580800E81700B00201B41CC35B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002005945007689008C007100780072007A009500A10088009C008F00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000000000000000000000D98A26F0780072007A009500A10088009C008F00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200002D0700C33C000F41B74349F7 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005A08003EC100A200016554739A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200005B0700D926005964EDCD672F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A000002E07002CD30164505C0449E8 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005C080043BC00A00001E0C3135C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000005D0700F609725F58291DE42400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B002002F050037C8008E4555F0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00005E0800956A00B002015F5F279E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002005F45000BF400A30088009D008D00A80071007F0092006F006100000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C000000000000000000000000001A1438ED9D008D00A80071007F0092006F006100000000000000000000000000AE00A400AC009F00B100A200A900A200A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000300700F00F000F4154F2E814 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000060080058A700A200018370B3E9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000610700BF400059646AA8553300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A00000310700C9360164507EDE474C - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006208008E7100A00001A0F91306000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A000006307003BC4006432979DA1E700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 B0020032050004FB00326A5B9D - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000640800F30C00B00201B97BE7ED000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 B002006545006D92008D008F008A00750083008D0092008B0071007A00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000000000000000000000394AB8458A00750083008D0092008B0071007A00000000000000000000000000AE00A500AD00A000B100A200A900A200A3009C00000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A200003307004DB2000F4155AF289D - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000066080025DA00A200016833572C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A20000670700C23D0057645CD0AEF300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A0000034070009F6016450C7D6FF9B - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000068080009F600A00001DC3B4E93000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A00000690700BC43002E00509568C700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A3000035070019E6000F41EC883513 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006A0800DF2000A30001C8D82C7D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A300006B05003BC40055C25B16000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 A40000366A006798640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F647900B5C8699F - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006C0800A25D00A40001A68D87BD000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A400006D0500996600E41BAEE2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 13 13 0 A60000370500689700E8D1ECD8 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00006E0800748B00A6000185042752000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 128 0 A600006F6C0055AA0001640043010107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479006EA4C362000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 A20000380700A15E010023D1112994 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000700800FA0500A20001E14E401B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200007107001DE2005A635942221700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 A50000392400847B000000000000000000000000000000000000000000000000000000000000000038910386 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00007208002CD300A5000129052BF2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A50000739300A15E005A632900000000640043010107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A21C0F44B08232229E7F2E5DBFA70A5CEF58A3966ED710002FF9938030303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A2 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 15 15 0 a200003a07007788010023107a86d3 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA0000700800FA0500A20001E14E401B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A200007107001DE2005A635942221700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 44 44 0 a500003b240052ad0000000000000000000000000000000000000000000000000000000000000000828af704 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA00007208002CD300A5000129052BF2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 192 0 A50000739300A15E005A632900000000640043010107000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E4650312D30303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A21C0F44B08232229E7F2E5DBFA70A5CEF58A3966ED710002FF9938030303030303030302D302D30303030303030302D6E6F626F6479008B7767E4A81CC57C17A2 -USBDEVFS_REAPURBNDELAY 0 3 1 0 0 114 114 0 a700003c6a009b64640043010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e4650312d30303030303030302d302d30303030303030302d6e6f626f647900473c9b29 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 AA000074080051AE00A70001AC924B34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A7000075050011EE00ACFFDA28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A7000055050052AD00C5D5FE86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/tests/goodixmoc/device b/tests/goodixmoc/device index b008eb2b..a076caa1 100644 --- a/tests/goodixmoc/device +++ b/tests/goodixmoc/device @@ -1,30 +1,30 @@ -P: /devices/pci0000:00/0000:00:14.0/usb1/1-8 -N: bus/usb/001/003=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000 -E: DEVNAME=/dev/bus/usb/001/003 +P: /devices/pci0000:00/0000:00:14.0/usb3/3-2 +N: bus/usb/003/008=12010002EF000040C627405800010102030109022000010103A0320904000002FF0000040705830240000007050102400000 +E: DEVNAME=/dev/bus/usb/003/008 E: DEVTYPE=usb_device E: DRIVER=usb -E: PRODUCT=27c6/60a2/100 +E: PRODUCT=27c6/5840/100 E: TYPE=239/0/0 -E: BUSNUM=001 -E: DEVNUM=003 +E: BUSNUM=003 +E: DEVNUM=008 E: MAJOR=189 -E: MINOR=2 +E: MINOR=263 E: SUBSYSTEM=usb E: ID_VENDOR=Goodix_Technology_Co.__Ltd. E: ID_VENDOR_ENC=Goodix\x20Technology\x20Co.\x2c\x20Ltd. E: ID_VENDOR_ID=27c6 E: ID_MODEL=Goodix_USB2.0_MISC E: ID_MODEL_ENC=Goodix\x20USB2.0\x20MISC -E: ID_MODEL_ID=60a2 +E: ID_MODEL_ID=5840 E: ID_REVISION=0100 -E: ID_SERIAL=Goodix_Technology_Co.__Ltd._Goodix_USB2.0_MISC_UIDCBEE4D7B_XXXX_MOC_B0 -E: ID_SERIAL_SHORT=UIDCBEE4D7B_XXXX_MOC_B0 +E: ID_SERIAL=Goodix_Technology_Co.__Ltd._Goodix_USB2.0_MISC_UIDE1AD5CBA_XXXX_MOC_B0 +E: ID_SERIAL_SHORT=UIDE1AD5CBA_XXXX_MOC_B0 E: ID_BUS=usb E: ID_USB_INTERFACES=:ff0000: E: ID_VENDOR_FROM_DATABASE=Shenzhen Goodix Technology Co.,Ltd. -E: ID_PATH=pci-0000:00:14.0-usb-0:8 -E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_8 -E: LIBFPRINT_DRIVER=AuthenTec AES1610 +E: ID_PATH=pci-0000:00:14.0-usb-0:2 +E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2 +E: LIBFPRINT_DRIVER=Goodix MOC Fingerprint Sensor A: authorized=1 A: avoid_reset_quirk=0 A: bConfigurationValue=1 @@ -37,32 +37,32 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0100 A: bmAttributes=a0 -A: busnum=1\n -A: configuration=UIDCBEE4D7B_XXXX_MOC_B0 -H: descriptors=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000 -A: dev=189:2 -A: devnum=3\n -A: devpath=8 +A: busnum=3\n +A: configuration=UIDE1AD5CBA_XXXX_MOC_B0 +H: descriptors=12010002EF000040C627405800010102030109022000010103A0320904000002FF0000040705830240000007050102400000 +A: dev=189:263 +A: devnum=8\n +A: devpath=2 L: driver=../../../../../bus/usb/drivers/usb -A: idProduct=60a2 +A: idProduct=5840 A: idVendor=27c6 A: ltm_capable=no A: manufacturer=Goodix Technology Co., Ltd. A: maxchild=0 -L: port=../1-0:1.0/usb1-port8 -A: power/active_duration=324448 +L: port=../3-0:1.0/usb3-port2 +A: power/active_duration=2684 A: power/async=enabled A: power/autosuspend=2 A: power/autosuspend_delay_ms=2000 -A: power/connected_duration=5916532 +A: power/connected_duration=54348 A: power/control=auto A: power/level=auto A: power/persist=1 A: power/runtime_active_kids=0 -A: power/runtime_active_time=327268 +A: power/runtime_active_time=2518 A: power/runtime_enabled=enabled A: power/runtime_status=active -A: power/runtime_suspended_time=5588987 +A: power/runtime_suspended_time=51550 A: power/runtime_usage=0 A: power/wakeup=disabled A: power/wakeup_abort_count= @@ -75,38 +75,39 @@ A: power/wakeup_max_time_ms= A: power/wakeup_total_time_ms= A: product=Goodix USB2.0 MISC A: quirks=0x0 -A: removable=fixed +A: removable=removable A: rx_lanes=1 -A: serial=UIDCBEE4D7B_XXXX_MOC_B0 +A: serial=UIDE1AD5CBA_XXXX_MOC_B0 A: speed=12 A: tx_lanes=1 -A: urbnum=2180 +A: urbnum=15 A: version= 2.00 -P: /devices/pci0000:00/0000:00:14.0/usb1 -N: bus/usb/001/001=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C -E: DEVNAME=/dev/bus/usb/001/001 +P: /devices/pci0000:00/0000:00:14.0/usb3 +N: bus/usb/003/001=12010002090001406B1D020008050302010109021900010100E0000904000001090000000705810304000C +E: DEVNAME=/dev/bus/usb/003/001 E: DEVTYPE=usb_device E: DRIVER=usb -E: PRODUCT=1d6b/2/504 +E: PRODUCT=1d6b/2/508 E: TYPE=9/0/1 -E: BUSNUM=001 +E: BUSNUM=003 E: DEVNUM=001 E: MAJOR=189 -E: MINOR=0 +E: MINOR=256 E: SUBSYSTEM=usb -E: ID_VENDOR=Linux_5.4.0-29-generic_xhci-hcd -E: ID_VENDOR_ENC=Linux\x205.4.0-29-generic\x20xhci-hcd +E: ID_VENDOR=Linux_5.8.0-38-generic_xhci-hcd +E: ID_VENDOR_ENC=Linux\x205.8.0-38-generic\x20xhci-hcd E: ID_VENDOR_ID=1d6b E: ID_MODEL=xHCI_Host_Controller E: ID_MODEL_ENC=xHCI\x20Host\x20Controller E: ID_MODEL_ID=0002 -E: ID_REVISION=0504 -E: ID_SERIAL=Linux_5.4.0-29-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0 +E: ID_REVISION=0508 +E: ID_SERIAL=Linux_5.8.0-38-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0 E: ID_SERIAL_SHORT=0000:00:14.0 E: ID_BUS=usb E: ID_USB_INTERFACES=:090000: E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_AUTOSUSPEND=1 E: ID_MODEL_FROM_DATABASE=2.0 root hub E: ID_PATH=pci-0000:00:14.0 E: ID_PATH_TAG=pci-0000_00_14_0 @@ -123,12 +124,12 @@ A: bMaxPacketSize0=64 A: bMaxPower=0mA A: bNumConfigurations=1 A: bNumInterfaces= 1 -A: bcdDevice=0504 +A: bcdDevice=0508 A: bmAttributes=e0 -A: busnum=1\n +A: busnum=3\n A: configuration= -H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C -A: dev=189:0 +H: descriptors=12010002090001406B1D020008050302010109021900010100E0000904000001090000000705810304000C +A: dev=189:256 A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb @@ -136,20 +137,20 @@ A: idProduct=0002 A: idVendor=1d6b A: interface_authorized_default=1 A: ltm_capable=no -A: manufacturer=Linux 5.4.0-29-generic xhci-hcd -A: maxchild=12 -A: power/active_duration=5879432 +A: manufacturer=Linux 5.8.0-38-generic xhci-hcd +A: maxchild=4 +A: power/active_duration=2790916 A: power/async=enabled A: power/autosuspend=0 A: power/autosuspend_delay_ms=0 -A: power/connected_duration=5916912 +A: power/connected_duration=15607832 A: power/control=auto A: power/level=auto -A: power/runtime_active_kids=2 -A: power/runtime_active_time=5879430 +A: power/runtime_active_kids=1 +A: power/runtime_active_time=2790874 A: power/runtime_enabled=enabled A: power/runtime_status=active -A: power/runtime_suspended_time=37481 +A: power/runtime_suspended_time=12816956 A: power/runtime_usage=0 A: power/wakeup=disabled A: power/wakeup_abort_count= @@ -167,5 +168,7 @@ A: rx_lanes=1 A: serial=0000:00:14.0 A: speed=480 A: tx_lanes=1 -A: urbnum=1319 +A: urbnum=584 A: version= 2.00 + + From 9e164485f037edb0367461a3638e74d5107b78b3 Mon Sep 17 00:00:00 2001 From: weilei Date: Thu, 4 Feb 2021 11:31:10 +0800 Subject: [PATCH 100/103] goodixmoc:Add new PID Add PID 6594 used by LENOVO --- data/autosuspend.hwdb | 1 + libfprint/drivers/goodixmoc/goodix.c | 1 + 2 files changed, 2 insertions(+) diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb index 63e40cf7..14f45187 100644 --- a/data/autosuspend.hwdb +++ b/data/autosuspend.hwdb @@ -132,6 +132,7 @@ usb:v27C6p6496* usb:v27C6p60A2* usb:v27C6p63AC* usb:v27C6p639C* +usb:v27C6p6594* ID_AUTOSUSPEND=1 # Supported by libfprint driver synaptics diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 9cfdbe68..77278c6e 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -1553,6 +1553,7 @@ static const FpIdEntry id_table[] = { { .vid = 0x27c6, .pid = 0x60A2, }, { .vid = 0x27c6, .pid = 0x63AC, }, { .vid = 0x27c6, .pid = 0x639C, }, + { .vid = 0x27c6, .pid = 0x6594, }, { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */ }; From 966703057d6424f89bdf1fce29dfc916a607a3cd Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Fri, 5 Feb 2021 16:09:24 +0100 Subject: [PATCH 101/103] synaptics: Fix lost messages when sequence counter overflows The device will always use sequence number 0 for certain messages. We use this knowledge to filter the messages and assume that it is one of these special messages rather than a response to a command. However, we could end up sending a command with a sequence counter of 0 which would result in the response being ignored. Fix this by ensuring we correctly wrap from 255 to 1 instead of 0. Fixes: #358 --- libfprint/drivers/synaptics/synaptics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index b4711faf..b2db9bde 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -348,7 +348,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self, * may only be a cancellation currently). */ if (seq_num <= 0) { - self->last_seq_num = MAX (1, self->last_seq_num + 1); + self->last_seq_num = MAX (1, (self->last_seq_num + 1) & 0xff); real_seq_num = self->last_seq_num; if (seq_num == 0) self->cmd_seq_num = self->last_seq_num; From e4a297887b7febd116c493a83090c32dfb9bbf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 22 Feb 2021 19:09:11 +0100 Subject: [PATCH 102/103] virtual-image: Use explicit list of cases in which we want to listen Depending on the enum order is ok, but not really maintainable so better to explicitly list the states we want to listen. --- libfprint/drivers/virtual-image.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libfprint/drivers/virtual-image.c b/libfprint/drivers/virtual-image.c index 6b0043fe..222f022e 100644 --- a/libfprint/drivers/virtual-image.c +++ b/libfprint/drivers/virtual-image.c @@ -188,11 +188,18 @@ on_listener_connected (FpDeviceVirtualListener *listener, g_object_get (self, "fpi-image-device-state", &state, NULL); - /* Only read if we are in AWAIT_FINGER_* or CAPTURE states */ - if (state <= FPI_IMAGE_DEVICE_STATE_DEACTIVATING) - return; - recv_image (self); + switch (state) + { + case FPI_IMAGE_DEVICE_STATE_IDLE: + case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: + case FPI_IMAGE_DEVICE_STATE_CAPTURE: + case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: + recv_image (self); + + default: + break; + } } static void From a1ae3cfdaaf079faca8512351b4b63430bbf1a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 22 Feb 2021 19:37:42 +0100 Subject: [PATCH 103/103] meson: Bump version to 1.90.7+git20200222+tod1 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 5ce2c150..b93c316f 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('libfprint', [ 'c', 'cpp' ], - version: '1.90.7+tod1', + version: '1.90.7+git20210222+tod1', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized',