From 20e8355c014aff0308b5762a822d99c4b8279dd0 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 21 Sep 2021 19:06:15 +0200 Subject: [PATCH 1/3] tests: Run custom.py from test creation helper when available This allows creating tests both for image and non-image devices using the same script. --- tests/README.md | 22 +++++++++++++--------- tests/create-driver-test.py.in | 11 +++++++++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/tests/README.md b/tests/README.md index d04915a..3012cbc 100644 --- a/tests/README.md +++ b/tests/README.md @@ -3,20 +3,23 @@ `umockdev` tests use fingerprint devices mocked by [`umockdev` toolchain][umockdev]. -This document describes how to create a 'capture' test: a test that -captures a picture of a fingerprint from the device (mocked by -`umockdev`) and compares it with the standard one. +This document describes how to create test cases (for USB devices). Many of +these tests are tests for image devices, where a single image is captured +and stored. Other kinds of `umockdev` tests can be created in a similar manner. For match-on-chip devices you would instead create a test specific `custom.py` script, capture it and store the capture to `custom.pcapng`. -'Capture' Test Creation ------------------------ -A new 'capture' test is created by means of `capture.py` script: +'capture' and 'custom' Test Creation +------------------------------------ + +For image devices the `capture.py` script will be used to capture one reference +image. If the driver is a non-image driver, then a `custom.py` script should be +created in advance, which will be run instead. 1. Make sure that libfprint is built with support for the device driver - that you want to capture a test case for. + that you want to create a test case for. 2. From the build directory, run tests/create-driver-test.py as root. Note that if you're capturing data for a driver which already has a test case @@ -33,8 +36,9 @@ $ sudo tests/create-driver-test.py driver [variant] 5. Check whether `meson test` passes with this new test. -**Note.** To avoid submitting a real fingerprint, the side of finger, -arm, or anything else producing an image with the device can be used. +**Note.** To avoid submitting a real fingerprint when creating a 'capture' test, +the side of finger, arm, or anything else producing an image with the device +can be used. Possible Issues diff --git a/tests/create-driver-test.py.in b/tests/create-driver-test.py.in index 70b48f5..3eabb78 100755 --- a/tests/create-driver-test.py.in +++ b/tests/create-driver-test.py.in @@ -37,6 +37,7 @@ def print_usage(): print(f'Usage: {sys.argv[0]} driver [test-variant-name]') print('A test variant name is optional, and must be all lower case letters, or dashes, with no spaces') print(f'The captured data will be stored in {SRCDIR}/tests/[driver name]-[test variant name]') + print(f'Create custom.py prior to execution for non image device tests.') if len(sys.argv) > 3: print_usage() @@ -118,7 +119,13 @@ if capture_pid == 0: time.sleep(1) print('### Capturing fingerprint, please swipe or press your finger on the reader') -with subprocess.Popen(['python3', SRCDIR + '/tests/capture.py', test_dir + '/capture.png']) as capture_process: +cmd = ['python3', SRCDIR + '/tests/capture.py', test_dir + '/capture.png'] +capture_file = 'capture.pcapng' # capture for "capture" test +if os.path.exists(os.path.join(test_dir, "custom.py")): + cmd = ['python3', os.path.join(test_dir, "custom.py")] + capture_file = "custom.pcapng" + +with subprocess.Popen(cmd) as capture_process: capture_process.wait() if capture_process.returncode != 0: print('Failed to capture fingerprint') @@ -155,7 +162,7 @@ except ChildProcessError: # Filter the capture print(f'\n### Saving USB capture as test case {test_name}') args = ['tshark', '-r', unfiltered_cap_path, '-Y', f'usb.bus_id == {bus_num} and usb.device_address == {device_num}', - '-w', test_dir + '/capture.pcapng'] + '-w', os.path.join(test_dir, capture_file)] with subprocess.Popen(args, stderr=subprocess.DEVNULL) as filter_process: filter_process.wait() From a949594050052b9811e0885ab607a8d2b157c9fe Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Fri, 17 Sep 2021 18:11:48 +0200 Subject: [PATCH 2/3] goodixmoc: Returned device print matched by verify/identify This is needed for the fprintd duplicate checking code. The information is needed to delete stale prints automatically from the device. Related: #415 --- libfprint/drivers/goodixmoc/goodix.c | 90 ++++++++++++++-------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index ebead83..a3c07d3 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -79,6 +79,44 @@ static gboolean parse_print_data (GVariant *data, gsize *tid_len, const guint8 **user_id, gsize *user_id_len); + +static FpPrint * +fp_print_from_template (FpiDeviceGoodixMoc *self, template_format_t *template) +{ + FpPrint *print; + GVariant *data; + GVariant *tid; + GVariant *uid; + g_autofree gchar *userid = NULL; + + userid = g_strndup ((gchar *) template->payload.data, template->payload.size); + + print = fp_print_new (FP_DEVICE (self)); + + tid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + template->tid, + TEMPLATE_ID_SIZE, + 1); + + uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + template->payload.data, + template->payload.size, + 1); + + data = g_variant_new ("(y@ay@ay)", + template->finger_index, + tid, + 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", userid, NULL); + fpi_print_fill_from_user_id (print, userid); + + return print; +} + /****************************************************************************** * * fp_cmd_xxx Function @@ -385,6 +423,7 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, { g_autoptr(GPtrArray) templates = NULL; FpDevice *device = FP_DEVICE (self); + FpPrint *match = NULL; FpPrint *print = NULL; gint cnt = 0; gboolean find = false; @@ -396,6 +435,8 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, } if (resp->verify.match) { + match = fp_print_from_template (self, &resp->verify.template); + if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY) { templates = g_ptr_array_sized_new (1); @@ -409,22 +450,9 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, } for (cnt = 0; cnt < templates->len; cnt++) { - g_autoptr(GVariant) data = NULL; - guint8 finger; - const guint8 *user_id; - gsize user_id_len = 0; - const guint8 *tid; - gsize tid_len = 0; print = g_ptr_array_index (templates, cnt); - g_object_get (print, "fpi-data", &data, NULL); - if (!parse_print_data (data, &finger, &tid, &tid_len, &user_id, &user_id_len)) - { - fpi_ssm_mark_failed (self->task_ssm, - fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID, - "Parse print error")); - return; - } - if (memcmp (&resp->verify.template.tid, tid, TEMPLATE_ID_SIZE) == 0) + + if (fp_print_equal (print, match)) { find = true; break; @@ -434,9 +462,9 @@ fp_verify_cb (FpiDeviceGoodixMoc *self, if (find) { if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY) - fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, error); + fpi_device_verify_report (device, FPI_MATCH_SUCCESS, match, error); else - fpi_device_identify_report (device, print, print, error); + fpi_device_identify_report (device, print, match, error); } } @@ -1224,36 +1252,10 @@ fp_template_list_cb (FpiDeviceGoodixMoc *self, for (int n = 0; n < resp->finger_list_resp.finger_num; n++) { - GVariant *data = NULL; - GVariant *tid = NULL; - GVariant *uid = NULL; FpPrint *print; - gchar *userid; - userid = (gchar *) resp->finger_list_resp.finger_list[n].payload.data; + print = fp_print_from_template (self, &resp->finger_list_resp.finger_list[n]); - print = fp_print_new (FP_DEVICE (self)); - - tid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - resp->finger_list_resp.finger_list[n].tid, - TEMPLATE_ID_SIZE, - 1); - - uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - resp->finger_list_resp.finger_list[n].payload.data, - resp->finger_list_resp.finger_list[n].payload.size, - 1); - - data = g_variant_new ("(y@ay@ay)", - resp->finger_list_resp.finger_list[n].finger_index, - tid, - 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", userid, NULL); - fpi_print_fill_from_user_id (print, userid); g_ptr_array_add (self->list_result, g_object_ref_sink (print)); } From f1559b73f35dec2f1febe865788459527e001902 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Fri, 17 Sep 2021 18:14:49 +0200 Subject: [PATCH 3/3] goodixmoc: Do not run identify step during enroll While useful, there are advantages for this to be done by the surrounding code (i.e. fprintd). As such, remove the identify stage from the goodix driver and rely on fprintd doing it for us. One can probably argue that neither solution is perfect. Ideally, we would probably return the information required to delete the old print to the upper stack and let the driver/device handle the duplicate checking. However, for now this works well. We may need to reconsider this if we get devices that do the duplicate checking transparently and just throw an enroll error. Closes: #415 --- libfprint/drivers/goodixmoc/goodix.c | 46 +----- tests/goodixmoc/custom.ioctl | 217 --------------------------- tests/goodixmoc/custom.pcapng | Bin 0 -> 58132 bytes tests/goodixmoc/device | 163 +++++++++++++------- 4 files changed, 108 insertions(+), 318 deletions(-) delete mode 100644 tests/goodixmoc/custom.ioctl create mode 100644 tests/goodixmoc/custom.pcapng diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index a3c07d3..c47a3f8 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -28,7 +28,7 @@ /* Default enroll stages number */ -#define DEFAULT_ENROLL_SAMPLES 8 +#define DEFAULT_ENROLL_SAMPLES 7 /* Usb port setting */ #define EP_IN (3 | FPI_USB_ENDPOINT_IN) #define EP_OUT (1 | FPI_USB_ENDPOINT_OUT) @@ -56,7 +56,6 @@ struct _FpiDeviceGoodixMoc gint max_stored_prints; GPtrArray *list_result; guint8 template_id[TEMPLATE_ID_SIZE]; - gboolean is_enroll_identify; gboolean is_power_button_shield_on; }; @@ -650,28 +649,6 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self, fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE); } -static void -fp_enroll_identify_cb (FpiDeviceGoodixMoc *self, - gxfp_cmd_response_t *resp, - GError *error) -{ - if (error) - { - fpi_ssm_mark_failed (self->task_ssm, error); - return; - } - if (resp->verify.match) - { - fpi_ssm_mark_failed (self->task_ssm, - fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_DUPLICATE, - "Finger is too similar to another, try use a different finger")); - // maybe need fpi_device_enroll_report_message ... - return; - } - fpi_ssm_next_state (self->task_ssm); - -} - static void fp_enroll_init_cb (FpiDeviceGoodixMoc *self, gxfp_cmd_response_t *resp, @@ -725,11 +702,6 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self, fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE); return; } - if (self->is_enroll_identify) - { - self->is_enroll_identify = false; - fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_IDENTIFY); - } else { fpi_ssm_next_state (self->task_ssm); @@ -895,19 +867,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device) } break; - case FP_ENROLL_IDENTIFY: - { - dummy[0] = 0x01; - dummy[1] = self->sensorcfg->config[10]; - dummy[2] = self->sensorcfg->config[11]; - goodix_sensor_cmd (self, MOC_CMD0_IDENTIFY, MOC_CMD1_DEFAULT, - false, - (const guint8 *) &self->template_id, - TEMPLATE_ID_SIZE, - fp_enroll_identify_cb); - } - break; - case FP_ENROLL_CREATE: { goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT, @@ -1324,7 +1283,7 @@ gx_fp_probe (FpDevice *device) case 0x63AC: case 0x63BC: case 0x6A94: - self->max_enroll_stage = 12; + self->max_enroll_stage = 11; break; default: @@ -1462,7 +1421,6 @@ gx_fp_enroll (FpDevice *device) FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device); self->enroll_stage = 0; - self->is_enroll_identify = true; self->task_ssm = fpi_ssm_new_full (device, fp_enroll_sm_run_state, FP_ENROLL_NUM_STATES, diff --git a/tests/goodixmoc/custom.ioctl b/tests/goodixmoc/custom.ioctl deleted file mode 100644 index 496b43c..0000000 --- a/tests/goodixmoc/custom.ioctl +++ /dev/null @@ -1,217 +0,0 @@ -@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 AA00000008009D6200D00000239572F5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00000208004BB400C001005F5A6B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA000004080036C900E00101C26FC596000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000060800E01F00A60001BCF2ED17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000080800CC3300A20001BA8679AC000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00000A08001AE500A5000172CD1245000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00000C0800679800A100014526FF87000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00000E0800B14E00A2000151C59D69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00001008003FC000A0000187F37724000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000120800E91600B00201386F43E6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000140800946B00A200014F39330E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA000016080042BD00A000016CB093E1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00001808006E9100B0020144AD1E73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00001A0800B84700A2000195E5AEB2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00001C0800C53A00A000011072CE74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00001E080013EC00B00201AFEEFAB6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000200800DE2100A2000173C16EC1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA000022080008F700A000015048CE2E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000240800758A00B0020149CA3AC5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000260800A35C00A2000198828A04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00002808008F7000A000012C8A93BB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00002A080059A600B002019316A779000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00002C080024DB00A20001E440D791000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00002E0800F20D00A00001C7C9777E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00003008007C8300B002018DEA091E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000320800AA5500A200015CA2B9DF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000340800D72800A00001D935D919000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA000036080001FE00B0020166A9EDDB000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00003808002DD200A200012060E44A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00003A0800FB0400A0000103E944A5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00003C0800867900A30001B114E662000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00003E080050AF00A40001795F8D8B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00004008001BE400E00001D5F1C38E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000420800CD3200A60001EA5DF016000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000440800B04F00E0010132DE18BE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA0000460800669900A2000190EB3938000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00004808004AB500A50001CF21EB81000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00004A08009C6300E00001A9339E1B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00004C0800E11E00E00101034161C7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 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 AA0000500800B94600A500019C80610A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA00005208006F9000E00001FA921490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - 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 AA000054080012ED00A70001544A2520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 0 0 - USBDEVFS_REAPURBNDELAY 0 3 131 0 0 2048 64 0 A7000055050052AD00C5D5FE86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/tests/goodixmoc/custom.pcapng b/tests/goodixmoc/custom.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..97f25f3026ca8d6532a56002c4d55c610125dcf2 GIT binary patch literal 58132 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