diff --git a/doc/libfprint-2-sections.txt b/doc/libfprint-2-sections.txt index 0ea7130d..cb67aef5 100644 --- a/doc/libfprint-2-sections.txt +++ b/doc/libfprint-2-sections.txt @@ -282,6 +282,7 @@ fpi_device_get_current_action fpi_device_retry_new fpi_device_error_new fpi_device_retry_new_msg +fpi_device_emulation_mode_enabled fpi_device_error_new_msg fpi_device_get_driver_data fpi_device_get_enroll_data diff --git a/libfprint/drivers/egismoc/egis_etu905.c b/libfprint/drivers/egismoc/egis_etu905.c index dcd71ff6..994e3ab5 100644 --- a/libfprint/drivers/egismoc/egis_etu905.c +++ b/libfprint/drivers/egismoc/egis_etu905.c @@ -1567,7 +1567,7 @@ egis_etu905_probe (FpDevice *device) return; } - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (device)) serial = g_strdup ("emulated-device"); else serial = g_usb_device_get_string_descriptor (usb_dev, diff --git a/libfprint/drivers/egismoc/egismoc.c b/libfprint/drivers/egismoc/egismoc.c index 06f445d4..89786dce 100644 --- a/libfprint/drivers/egismoc/egismoc.c +++ b/libfprint/drivers/egismoc/egismoc.c @@ -1500,7 +1500,7 @@ egismoc_probe (FpDevice *device) return; } - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (device))) serial = g_strdup ("emulated-device"); else serial = g_usb_device_get_string_descriptor (usb_dev, diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index af631732..e108dba3 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -557,7 +557,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev) else { /* XXX: The timeout is emulated incorrectly, resulting in a zero byte read. */ - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (self))) fpi_ssm_mark_completed (ssm); else fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); diff --git a/libfprint/drivers/elanspi.c b/libfprint/drivers/elanspi.c index 9338013d..5a713dd8 100644 --- a/libfprint/drivers/elanspi.c +++ b/libfprint/drivers/elanspi.c @@ -94,7 +94,7 @@ static void elanspi_do_hwreset (FpiDeviceElanSpi *self, GError **err) { /* Skip in emulation mode, since we don't mock hid devices */ - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (self))) return; /* @@ -485,7 +485,8 @@ elanspi_capture_old_handler (FpiSsm *ssm, FpDevice *dev) if (!(self->sensor_status & 4)) { /* has the timeout expired? -- disabled in testing since valgrind is very slow */ - if (g_get_monotonic_time () > self->capture_timeout && g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0) + if (g_get_monotonic_time () > self->capture_timeout && + !fpi_device_emulation_mode_enabled (FP_DEVICE (self))) { /* end with a timeout */ fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "timed out waiting for new line")); diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index b2c7920d..8c7578e5 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -970,7 +970,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device) user_id_len = MIN (100, user_id_len); finger = 1; - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (self))) memset (self->template_id, 0, TEMPLATE_ID_SIZE); uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, user_id, @@ -1390,7 +1390,7 @@ gx_fp_probe (FpDevice *device) if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error)) goto err_close; - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (self))) { serial = g_strdup ("emulated-device"); diff --git a/libfprint/drivers/mafpmoc/mafpmoc.c b/libfprint/drivers/mafpmoc/mafpmoc.c index f36d72ac..2d9ef95e 100644 --- a/libfprint/drivers/mafpmoc/mafpmoc.c +++ b/libfprint/drivers/mafpmoc/mafpmoc.c @@ -2317,7 +2317,7 @@ mafp_probe (FpDevice *device) if (!g_usb_device_claim_interface (usb_dev, self->interface_num, 0, &error)) goto err_close; - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (device)) { serial = g_strdup ("emulated-device"); } @@ -2378,7 +2378,7 @@ mafp_init (FpDevice *device) else fp_dbg ("device no storage"); - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (device)) { serial = g_strdup ("emulated-device"); } diff --git a/libfprint/drivers/secugen.c b/libfprint/drivers/secugen.c index 57c5bd9c..a2a3965f 100644 --- a/libfprint/drivers/secugen.c +++ b/libfprint/drivers/secugen.c @@ -855,7 +855,7 @@ secugen_frame_chunk_cb (FpiUsbTransfer *transfer, /* Outside emulation a complete sensor frame is expected. */ if (self->bulk_offset < SECUGEN_RAW_SIZE && - g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0) + fpi_device_emulation_mode_enabled (dev)) { fp_warn ("Short image data: got %" G_GSIZE_FORMAT ", expected %d", self->bulk_offset, SECUGEN_RAW_SIZE); @@ -2225,7 +2225,7 @@ dev_change_state (FpImageDevice *dev, * starts with the finger already present, so report it directly - * the same approach other drivers use for replay-incompatible * hardware behavior (e.g. elanspi's HID reset skip). */ - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (self))) { fpi_image_device_report_finger_status (dev, TRUE); break; diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index 53de7e91..164f209e 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -1211,7 +1211,7 @@ prob_msg_cb (FpiDeviceSynaptics *self, return; } - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (self))) serial = g_strdup ("emulated-device"); else serial = g_usb_device_get_string_descriptor (usb_dev, diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index f8d7b6ec..bc599786 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -1380,7 +1380,7 @@ dev_init (FpImageDevice *dev) g_clear_pointer (&self->rand, g_rand_free); self->rand = g_rand_new (); - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (FP_DEVICE (dev))) g_rand_set_seed (self->rand, 0xFACADE); driver_data = fpi_device_get_driver_data (FP_DEVICE (dev)); diff --git a/libfprint/drivers/vfs0050.c b/libfprint/drivers/vfs0050.c index 2442937a..ca2eda9c 100644 --- a/libfprint/drivers/vfs0050.c +++ b/libfprint/drivers/vfs0050.c @@ -119,7 +119,7 @@ async_abort_callback (FpiUsbTransfer *transfer, FpDevice *device, /* In normal case endpoint is empty */ if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) || - (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0 && transfer->actual_length == 0)) + (fpi_device_emulation_mode_enabled (device) && transfer->actual_length == 0)) { g_clear_error (&error); fpi_ssm_next_state (transfer->ssm); diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index cc744f6d..5f73077a 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -50,6 +50,35 @@ fp_device_get_instance_private (FpDevice *self) g_type_class_get_instance_private_offset (dev_class)); } +/** + * fpi_device_emulation_mode_enabled: + * @device: The #FpDevice to check + * + * Checks if the device is running in emulation mode, which is enabled by + * setting the FP_DEVICE_EMULATION environment variable to a '1' value. + * This is used by some drivers to enable special behavior for testing + * and development purposes. + */ +gboolean + (fpi_device_emulation_mode_enabled) (FpDevice *device) +{ + static gsize emulation_mode = 0; + + /* FIXME: Add some build constraints to make sure this cannot ever be enabled + * in production, outside in the installed tests case. + */ + + /* This is a global value for now, but ideally we may support a different + * value per device. + */ + if (g_once_init_enter (&emulation_mode)) + g_once_init_leave (&emulation_mode, + g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0 ? + TRUE : G_MAXSIZE); + + return emulation_mode == TRUE; +} + /** * fpi_device_class_auto_initialize_features: * @device_class: An #FpDeviceClass to initialize diff --git a/libfprint/fpi-device.h b/libfprint/fpi-device.h index be63c1ce..8d65b691 100644 --- a/libfprint/fpi-device.h +++ b/libfprint/fpi-device.h @@ -332,4 +332,11 @@ gboolean fpi_device_report_finger_status_changes (FpDevice *device, FpFingerStatusFlags added_status, FpFingerStatusFlags removed_status); +/* Debugging utilities */ + +#define fpi_device_emulation_mode_enabled(dev) \ + G_UNLIKELY ((fpi_device_emulation_mode_enabled) ((dev))) + +gboolean (fpi_device_emulation_mode_enabled) (FpDevice *device); + G_END_DECLS diff --git a/libfprint/fpi-print.c b/libfprint/fpi-print.c index e9e6d154..b0f5eab4 100644 --- a/libfprint/fpi-print.c +++ b/libfprint/fpi-print.c @@ -295,7 +295,7 @@ fpi_print_generate_user_id (FpPrint *print) if (!username) username = "nobody"; - if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) + if (fpi_device_emulation_mode_enabled (NULL)) rand_id = 0; else rand_id = g_random_int ();