Compare commits

...

44 Commits

Author SHA1 Message Date
Bastien Nocera
8d871751f6 WIP: shut-up uncrustify 2020-05-07 16:46:00 +02:00
Bastien Nocera
4fdf0eae0f virtual-device: Add non-imaging mock driver
Has 2 variants, one that supports identify, one that doesn't.

The mode of operation for this device is:
- Run fprintd with "FP_VIRTUAL_DEVICE=/tmp/fprint.socket"
- As root:
FP_VIRTUAL_DEVICE=/tmp/fprint.socket ./sendvirtcmd.py "ADD left-middle testuser success"
FP_VIRTUAL_DEVICE=/tmp/fprint.socket ./sendvirtcmd.py "ADD right-middle testuser failure"
- As testuser:
fprintd-enroll -f left-middle-finger
fprintd-enroll -f right-middle-finger

Now, across fprintd restarts (as it has its own storage), verification
will always succeed for user "testuser" with the "left-middle-finger".

Using the FP_VIRTUAL_DEVICE_IDENT envvar instead will allow
identification, with the first found "successful" finger being presented
as the identified one.
2020-05-07 16:46:00 +02:00
Bastien Nocera
8632877b95 examples: Add example to feed non-imaging virtual driver
Add an example script that can add and remove prints from the
non-imaging virtual driver.
2020-05-07 16:46:00 +02:00
Bastien Nocera
170d7c2cf7 virtual-image: Exit early when new connection fails 2020-05-07 16:46:00 +02:00
Bastien Nocera
e2d4b0d249 tests: Add support for creating other virtual readers
Add support for creating more virtual readers.
2020-05-07 16:46:00 +02:00
Bastien Nocera
b0c546164e fpi-device: Allow driver to handle identify for certain variants
Rather than requiring a driver to implement a variant with
identify support, and another one without, ask the driver whether a
particular device supports identification.
2020-05-07 15:01:18 +02:00
Bastien Nocera
f2ae3fb8c5 virtual-image: Remove unnecessary cast 2020-05-07 15:01:18 +02:00
Michal Prívozník
eefc954f91 context: Fix order of PID/VID in a debug message
When no driver is found for an USB device a debug message is
printed. However, it has PID and VID in wrong order - usually it
is Vendor ID which goes first. This is how 'lsusb' prints it.
Matching the order helps debugging.

Signed-off-by: Michal Privoznik <michal@privoznik.com>
2020-04-27 16:16:43 +02:00
Michal Prívozník
5bcf9ac008 print: Include "fpi-compact.h"
In the fpi_print_fill_from_user_id() GDate is defined using
g_autoptr(). However, this requires new enough GLib. For older
versions there's a definition provided locally in fpi-compact.h.
Include the file to fix build with older version of GLib.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2020-04-27 16:16:39 +02:00
Benjamin Berg
d2402309ee examples: Cancel verify operation on Ctrl+C
This makes it easier to do basic testing of cancellation paths in the
drivers.
2020-04-24 18:40:48 +00:00
Benjamin Berg
a651b65401 example: Cancel enroll operation on Ctrl+C
This makes it easier to do basic testing of cancellation paths in the
drivers.
2020-04-24 18:40:48 +00:00
Marco Trevisan (Treviño)
bc3f622b2a context: Factorize duplicated code 2020-04-24 20:21:01 +02:00
Marco Trevisan (Treviño)
5de49b33e6 image-device: Terminate the current action with error on print failure
If we fail when setting the scanned image to a print, we'll have a fatal
error, in such case we can terminate the current action and deactivate the
device.
2020-04-24 20:09:56 +02:00
Marco Trevisan (Treviño)
81e198c034 image: Return an error if we got an empty or NULL minutiae array
In some cases nbim's get_minutiae returns no minutiae without providing an
error code, and if this happens we would crash in the task callback function
as we would try to deference the data->minutiae pointer.

Related to: #251
2020-04-24 20:09:56 +02:00
Marco Trevisan (Treviño)
c0895a858d etes603: Return TOO_SHORT retry error for small images
If the image height is less than the sensor horizontal resolution, then
return a retry error rather than trying to submit the image for further
processing.

Related to: #251
2020-04-24 20:03:51 +02:00
Benjamin Berg
5d5995f201 image: Check for task success rather than just cancellation
The minutiae detection might fail and we must not copy any data at that
point. So check g_task_had_error to ensure that we only do so when the
task was successful.

Fixes: #251
2020-04-24 20:03:37 +02:00
Benjamin Berg
f71045b743 synaptics: Use the FpPrint ID generation functionality
As the functionality is now part of the internal FpPrint API, it makes
sene to use it.
2020-04-20 16:43:52 +02:00
Benjamin Berg
0274d0783b print: Add helpers to generate a unique print ID containing metadata
It makes sense to include this functionality in the core library as more
than one driver will be using it soon.
2020-04-20 16:43:52 +02:00
Bastien Nocera
5c5a4f6907 upekts: Fix memory leak
Don't allocate a new finger print structure,
the fpi_device_get_enroll_data() just below will overwrite it.
2020-04-15 15:55:39 +02:00
Bastien Nocera
5b6f5c9aad synaptics: Don't pass always-NULL value
No need to pass "error" to this report function, it will always be NULL.
2020-04-15 15:55:39 +02:00
Marco Trevisan (Treviño)
41e05b1133 test-fpi-device: Don't compare error pointers that have been cleared
During verify/identify complete we replace the error pointer that the driver
returned with another error we created, after clearing that one.

However, when we initialize a new error the compiler may reuse the same
allocation of the cleared one, and this might lead to a test failure.

So, don't be so fragile and ignore the pointer check
2020-04-15 14:19:53 +02:00
Bastien Nocera
579e01359b fp-print: Fix sign-compare warnings
libfprint/fp-print.c: In function ‘fp_print_equal’:
libfprint/fp-print.c:596:21: warning: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’} [-Wsign-compare]
  596 |       for (i = 0; i < self->prints->len; i++)
      |                     ^
libfprint/fp-print.c: In function ‘fp_print_serialize’:
libfprint/fp-print.c:667:21: warning: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’} [-Wsign-compare]
  667 |       for (i = 0; i < print->prints->len; i++)
      |                     ^
libfprint/fp-print.c: In function ‘fp_print_deserialize’:
libfprint/fp-print.c:823:21: warning: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’} [-Wsign-compare]
  823 |       for (i = 0; i < g_variant_n_children (prints); i++)
      |                     ^
2020-04-15 12:48:05 +02:00
Bastien Nocera
cc887c1a37 libfprint: Fix typos 2020-04-14 13:51:02 +02:00
Bastien Nocera
fdd2d6abf8 fprint-list: Fix typos in Copyright statements 2020-04-14 13:51:02 +02:00
Bastien Nocera
6bf29108a1 examples: Fix typo 2020-04-14 13:51:02 +02:00
Bastien Nocera
d0751ae06b tests/elan: Fix typos 2020-04-14 13:51:02 +02:00
Bastien Nocera
a218a5efdd virtual-image: Fix typo 2020-04-14 13:51:01 +02:00
Bastien Nocera
c6ae8e58a4 elan: Fix typo 2020-04-14 13:50:49 +02:00
Bastien Nocera
87c7894c28 synaptics: Fix typos 2020-04-14 13:47:48 +02:00
Marco Trevisan (Treviño)
e7ff4f705c tests: Import FPrint only during execution not when parsing
The unittest_parser script would try to import FPrint gi module, but it
would fail as per the fact that none is installed yet, so make sure that
we don't load any FPrint module until we try to actually run the tests
2020-03-27 21:19:09 +00:00
Marco Trevisan (Treviño)
c26588942a ci: Print coverage data once available so that gitlab can parse it 2020-03-27 00:00:07 +01:00
Laurent Bigonville
3d68cddfe7 Properly set the dependencies in the pkg-config file
The public API uses gio and gobject header, ensure that these are in the
list of Required pkg-config modules, otherwise they are added to
Required.private which is not OK.
2020-03-20 11:13:06 +00:00
Benjamin Berg
96fba323b9 meson: Fix linking issue of libfprint with newer gcc
It appears the order of linking is relevant in this case, change it to
fix some linking issues.

It may be that there are better solutions to this problem.
2020-03-20 12:05:14 +01:00
Benjamin Berg
bd4f118b5e ci: Update CI after the fdo template changes
The CI definition needs to be updated to work with the new fdo
templates.
2020-03-20 12:05:14 +01:00
Benjamin Berg
9d4b5ad682 Revert "ci: Fix CI syntax error"
This reverts commit bd500b2235.

The fix from the commit was not correct.

See https://gitlab.freedesktop.org/libfprint/libfprint/-/merge_requests/124
2020-03-20 12:05:08 +01:00
Benjamin Berg
ca788b6de2 Revert "ci: Fix unknown keys in CI"
This reverts commit ebe5cb58ba.

The fix from the commit was not correct.

See https://gitlab.freedesktop.org/libfprint/libfprint/-/merge_requests/124
2020-03-20 12:04:58 +01:00
Bastien Nocera
90ccf9a0af vfs0050: Fix incorrect destructor for GError 2020-03-13 10:23:52 +01:00
Bastien Nocera
2581f1aa32 aes1610: Fix memory leak
Fix small memory leak when reading some data that's not going to be
processed.
2020-03-13 10:23:52 +01:00
Bastien Nocera
ebe5cb58ba ci: Fix unknown keys in CI
Fix:
root config contains unknown keys: container_fedora_build
2020-03-13 10:14:59 +01:00
Bastien Nocera
bd500b2235 ci: Fix CI syntax error
Fix CI syntax error:
container_fedora_build: unknown keys in `extends` (.fedora@container-build)
Caused by changes in the wayland CI templates:
4a73f030d0
2020-03-13 10:08:58 +01:00
Bastien Nocera
8fa50d667c ci: s/flatpack/flatpak/
“Flatpack” is for IKEA furniture.
2020-03-13 10:08:58 +01:00
Marco Trevisan (Treviño)
2ae8b74e60 meson: Add fpi-compat.h to the private headers 2020-02-27 06:03:21 +01:00
Benjamin Berg
f4ec816a6b tests: Cast to correct pointer type rather than gpointer
This is just a small cleanup
2020-02-19 16:42:30 +01:00
Benjamin Berg
9e2a7235e3 tests: Fix reading of gboolean into pointer
Otherwise the payload will be lost later on when using GPOINTER_TO_INT
to cast it back.

See: #236
2020-02-19 16:42:30 +01:00
39 changed files with 900 additions and 201 deletions

View File

@@ -6,9 +6,9 @@ include:
variables:
extends: .libfprint_common_variables
FEDORA_TAG: rawhide
FEDORA_VERSION: rawhide
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FEDORA_VERSION:$FEDORA_TAG"
FDO_DISTRIBUTION_TAG: latest
FDO_DISTRIBUTION_VERSION: rawhide
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
@@ -16,7 +16,7 @@ stages:
- check-source
- build
- test
- flatpack
- flatpak
image: "$FEDORA_IMAGE"
@@ -59,6 +59,7 @@ test:
- ninja -C _build
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
- ninja -C _build coverage
- cat _build/meson-logs/coverage.txt
artifacts:
paths:
- _build/meson-logs
@@ -107,7 +108,7 @@ test_indent:
.flatpak_master_template: &flatpak_master
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.32
stage: flatpack
stage: flatpak
variables:
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
# From demo/org.freedesktop.libfprint.Demo.json
@@ -135,11 +136,11 @@ flatpak-manual master:
# CONTAINERS creation stage
container_fedora_build:
extends: .fedora@container-build
extends: .fdo.container-build@fedora
only:
variables:
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
# a list of packages to install
FEDORA_RPMS: $LIBFPRINT_DEPENDENCIES
FDO_DISTRIBUTION_PACKAGES: $LIBFPRINT_DEPENDENCIES

View File

@@ -207,6 +207,8 @@ fpi_print_set_type
fpi_print_set_device_stored
fpi_print_add_from_image
fpi_print_bz3_match
fpi_print_generate_user_id
fpi_print_fill_from_user_id
</SECTION>
<SECTION>

View File

@@ -1,6 +1,6 @@
/*
* Example fingerprint enrollment program
* Enrolls your choosen finger and saves the print to disk
* Enrolls your chosen finger and saves the print to disk
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
@@ -23,20 +23,25 @@
#include <stdio.h>
#include <libfprint/fprint.h>
#include <glib-unix.h>
#include "storage.h"
#include "utilities.h"
typedef struct _EnrollData
{
GMainLoop *loop;
FpFinger finger;
int ret_value;
GMainLoop *loop;
GCancellable *cancellable;
unsigned int sigint_handler;
FpFinger finger;
int ret_value;
} EnrollData;
static void
enroll_data_free (EnrollData *enroll_data)
{
g_clear_handle_id (&enroll_data->sigint_handler, g_source_remove);
g_clear_object (&enroll_data->cancellable);
g_main_loop_unref (enroll_data->loop);
g_free (enroll_data);
}
@@ -137,11 +142,22 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
printf ("Scan your finger now.\n");
print_template = print_create_template (dev, enroll_data->finger);
fp_device_enroll (dev, print_template, NULL, on_enroll_progress, NULL,
NULL, (GAsyncReadyCallback) on_enroll_completed,
fp_device_enroll (dev, print_template, enroll_data->cancellable,
on_enroll_progress, NULL, NULL,
(GAsyncReadyCallback) on_enroll_completed,
enroll_data);
}
static gboolean
sigint_cb (void *user_data)
{
EnrollData *enroll_data = user_data;
g_cancellable_cancel (enroll_data->cancellable);
return G_SOURCE_CONTINUE;
}
int
main (void)
{
@@ -188,8 +204,15 @@ main (void)
enroll_data->finger = finger;
enroll_data->ret_value = EXIT_FAILURE;
enroll_data->loop = g_main_loop_new (NULL, FALSE);
enroll_data->cancellable = g_cancellable_new ();
enroll_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
SIGINT,
sigint_cb,
enroll_data,
NULL);
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
fp_device_open (dev, enroll_data->cancellable,
(GAsyncReadyCallback) on_device_opened,
enroll_data);
g_main_loop_run (enroll_data->loop);

53
examples/sendvirtcmd.py Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
# This script can be used together with the virtual_imgdev to simulate an
# image based fingerprint reader.
#
# To use, set the FP_VIRTUAL_IMAGE environment variable for both the
# libfprint using program (e.g. fprintd) and this script.
#
# Usually this would work by adding it into the systemd unit file. The
# best way of doing so is to create
# /etc/systemd/system/fprintd.service.d/fprintd-test.conf
#
# [Service]
# RuntimeDirectory=fprint
# Environment=FP_VIRTUAL_DEVICE=/run/fprint/virtdev_sock
# Environment=G_MESSAGES_DEBUG=all
# ReadWritePaths=$RUNTIME_DIR
#
# After that run:
#
# systemctl daemon-reload
# systemctl restart fprintd.service
#
# You may also need to disable selinux.
#
# Then run this script with e.g.
# FP_VIRTUAL_DEVICE=/run/fprint/virtdev_sock ./sendvirtimg.py "ADD <username> <finger> <success|failure>"
import cairo
import sys
import os
import socket
import struct
if len(sys.argv) != 2:
sys.stderr.write('You need to pass commands!\n')
sys.stderr.write('Usage: ./sendvirtimg.py "ADD <finger> <username> <success|failure>"\n')
sys.exit(1)
command = sys.argv[1]
# Send image through socket
sockaddr = os.environ['FP_VIRTUAL_DEVICE']
if not sockaddr:
sockaddr = os.environ['FP_VIRTUAL_DEVICE_IDENT']
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(sockaddr)
sock.sendall(command.encode('utf-8'))

View File

@@ -23,20 +23,25 @@
#include <stdio.h>
#include <libfprint/fprint.h>
#include <glib-unix.h>
#include "storage.h"
#include "utilities.h"
typedef struct _VerifyData
{
GMainLoop *loop;
FpFinger finger;
int ret_value;
GMainLoop *loop;
GCancellable *cancellable;
unsigned int sigint_handler;
FpFinger finger;
int ret_value;
} VerifyData;
static void
verify_data_free (VerifyData *verify_data)
{
g_clear_handle_id (&verify_data->sigint_handler, g_source_remove);
g_clear_object (&verify_data->cancellable);
g_main_loop_unref (verify_data->loop);
g_free (verify_data);
}
@@ -196,7 +201,7 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
fp_print_get_description (verify_print));
g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL,
fp_device_verify (dev, verify_print, verify_data->cancellable,
on_match_cb, verify_data, NULL,
(GAsyncReadyCallback) on_verify_completed,
verify_data);
@@ -250,7 +255,7 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
}
g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL,
fp_device_verify (dev, verify_print, verify_data->cancellable,
NULL, NULL, NULL,
(GAsyncReadyCallback) on_verify_completed,
verify_data);
@@ -276,6 +281,16 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
start_verification (dev, verify_data);
}
static gboolean
sigint_cb (void *user_data)
{
VerifyData *verify_data = user_data;
g_cancellable_cancel (verify_data->cancellable);
return G_SOURCE_CONTINUE;
}
int
main (void)
{
@@ -306,8 +321,14 @@ main (void)
verify_data = g_new0 (VerifyData, 1);
verify_data->ret_value = EXIT_FAILURE;
verify_data->loop = g_main_loop_new (NULL, FALSE);
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
verify_data->cancellable = g_cancellable_new ();
verify_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
SIGINT,
sigint_cb,
verify_data,
NULL);
fp_device_open (dev, verify_data->cancellable,
(GAsyncReadyCallback) on_device_opened,
verify_data);
g_main_loop_run (verify_data->loop);

View File

@@ -138,7 +138,7 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
unsigned char *data;
data = g_malloc (bytes);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, NULL);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, g_free);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,

View File

@@ -733,7 +733,7 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
fp_dbg ("calibration failed");
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Callibration failed!"));
"Calibration failed!"));
}
break;

View File

@@ -859,21 +859,29 @@ m_capture_state (FpiSsm *ssm, FpDevice *dev)
}
else
{
FpImage *img;
unsigned int img_size;
/* Remove empty parts 2 times for the 2 frames */
process_removefpi_end (self);
process_removefpi_end (self);
img_size = self->fp_height * FE_WIDTH;
img = fp_image_new (FE_WIDTH, self->fp_height);
/* Images received are white on black, so invert it. */
/* TODO detect sweep direction */
img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
img->height = self->fp_height;
process_4to8_bpp (self->fp, img_size / 2, img->data);
fp_dbg ("Sending the raw fingerprint image (%dx%d)",
img->width, img->height);
fpi_image_device_image_captured (idev, img);
if (self->fp_height >= FE_WIDTH)
{
FpImage *img = fp_image_new (FE_WIDTH, self->fp_height);
unsigned int img_size = self->fp_height * FE_WIDTH;
/* Images received are white on black, so invert it. */
/* TODO detect sweep direction */
img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
img->height = self->fp_height;
process_4to8_bpp (self->fp, img_size / 2, img->data);
fp_dbg ("Sending the raw fingerprint image (%dx%d)",
img->width, img->height);
fpi_image_device_image_captured (idev, img);
}
else
{
fpi_image_device_retry_scan (idev, FP_DEVICE_RETRY_TOO_SHORT);
}
fpi_image_device_report_finger_status (idev, FALSE);
fpi_ssm_mark_completed (ssm);
}

View File

@@ -316,7 +316,7 @@ typedef struct bmkt_init_resp
*/
typedef struct bmkt_enroll_resp
{
int progress; /**< Shows current progress stutus [0-100] */
int progress; /**< Shows current progress status [0-100] */
uint8_t finger_id; /**< User's finger id [1-10] */
uint8_t user_id[BMKT_MAX_USER_ID_LEN]; /**< User name to be enrolled */
} bmkt_enroll_resp_t;

View File

@@ -35,7 +35,7 @@ static const FpIdEntry id_table[] = {
static void
cmd_recieve_cb (FpiUsbTransfer *transfer,
cmd_receive_cb (FpiUsbTransfer *transfer,
FpDevice *device,
gpointer user_data,
GError *error)
@@ -234,7 +234,7 @@ synaptics_cmd_run_state (FpiSsm *ssm,
fpi_usb_transfer_submit (transfer,
5000,
NULL,
cmd_recieve_cb,
cmd_receive_cb,
fpi_ssm_get_data (ssm));
break;
@@ -321,7 +321,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
g_assert (payload || payload_len == 0);
/* seq_num of 0 means a normal command, -1 means the current commands
* sequence number should not be udpated (i.e. second async command which
* sequence number should not be updated (i.e. second async command which
* may only be a cancellation currently). */
if (seq_num <= 0)
{
@@ -515,39 +515,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
g_object_set (print, "fpi-data", data, NULL);
g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL);
/* The format has 24 bytes at the start and some dashes in the right places */
if (g_str_has_prefix (userid, "FP1-") && strlen (userid) >= 24 &&
userid[12] == '-' && userid[14] == '-' && userid[23] == '-')
{
g_autofree gchar *copy = g_strdup (userid);
g_autoptr(GDate) date = NULL;
gint32 date_ymd;
gint32 finger;
gchar *username;
/* Try to parse information from the string. */
copy[12] = '\0';
date_ymd = g_ascii_strtod (copy + 4, NULL);
if (date_ymd > 0)
date = g_date_new_dmy (date_ymd % 100,
(date_ymd / 100) % 100,
date_ymd / 10000);
else
date = g_date_new ();
fp_print_set_enroll_date (print, date);
copy[14] = '\0';
finger = g_ascii_strtoll (copy + 13, NULL, 16);
fp_print_set_finger (print, finger);
/* We ignore the next chunk, it is just random data.
* Then comes the username; nobody is the default if the metadata
* is unknown */
username = copy + 24;
if (strlen (username) > 0 && g_strcmp0 (username, "nobody") != 0)
fp_print_set_username (print, username);
}
fpi_print_fill_from_user_id (print, userid);
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
}
@@ -635,7 +603,7 @@ verify_msg_cb (FpiDeviceSynaptics *self,
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_info ("Print didn't match");
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error);
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
verify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
@@ -730,7 +698,7 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
if (enroll_resp->progress < 100)
done_stages = MIN (done_stages, ENROLL_SAMPLES - 1);
/* Emit a retry error if there has been no discernable
/* Emit a retry error if there has been no discernible
* progress. Some firmware revisions report more required
* touches. */
if (self->enroll_stage == done_stages)
@@ -795,8 +763,6 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
}
}
#define TEMPLATE_ID_SIZE 20
static void
enroll (FpDevice *device)
{
@@ -804,52 +770,21 @@ enroll (FpDevice *device)
FpPrint *print = NULL;
GVariant *data = NULL;
GVariant *uid = NULL;
const gchar *username;
guint finger;
g_autofree gchar *user_id = NULL;
gssize user_id_len;
g_autofree guint8 *payload = NULL;
const GDate *date;
gint y, m, d;
gint32 rand_id = 0;
fpi_device_get_enroll_data (device, &print);
G_DEBUG_HERE ();
date = fp_print_get_enroll_date (print);
if (date && g_date_valid (date))
{
y = g_date_get_year (date);
m = g_date_get_month (date);
d = g_date_get_day (date);
}
else
{
y = 0;
m = 0;
d = 0;
}
username = fp_print_get_username (print);
if (!username)
username = "nobody";
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
rand_id = 0;
else
rand_id = g_random_int ();
user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s",
y, m, d,
fp_print_get_finger (print),
rand_id,
username);
user_id = fpi_print_generate_user_id (print);
user_id_len = strlen (user_id);
user_id_len = MIN (BMKT_MAX_USER_ID_LEN, user_id_len);
/* We currently always use finger 1 from the devices piont of view */
/* We currently always use finger 1 from the devices point of view */
finger = 1;
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
@@ -1029,7 +964,7 @@ dev_probe (FpDevice *device)
if (!read_ok)
{
g_warning ("Transfer in response to verison query was too short");
g_warning ("Transfer in response to version query was too short");
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
goto err_close;
}

View File

@@ -1119,7 +1119,6 @@ e_handle_resp02 (FpDevice *dev, unsigned char *data,
else
{
GVariant *fp_data;
print = fp_print_new (dev);
fpi_device_get_enroll_data (dev, &print);

View File

@@ -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_free (error);
g_error_free (error);
fpi_ssm_next_state (transfer->ssm);
return;
}

View File

@@ -0,0 +1,456 @@
/*
* Virtual driver for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
*
* 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 "fpi-log.h"
#include "../fpi-device.h"
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <gio/gunixsocketaddress.h>
#define MAX_LINE_LEN 1024
enum {
VIRTUAL_DEVICE,
VIRTUAL_DEVICE_IDENT
};
struct _FpDeviceVirtualDevice
{
FpDevice parent;
GSocketListener *listener;
GSocketConnection *connection;
GCancellable *cancellable;
gint socket_fd;
gint client_fd;
guint line[MAX_LINE_LEN];
GHashTable *pending_prints; /* key: finger+username value: gboolean */
};
G_DECLARE_FINAL_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP, DEVICE_VIRTUAL_DEVICE, FpDevice)
G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
static void start_listen (FpDeviceVirtualDevice *self);
#define ADD_CMD_PREFIX "ADD "
static FpFinger
str_to_finger (const char *str)
{
g_autoptr(GEnumClass) eclass;
GEnumValue *value;
eclass = g_type_class_ref (FP_TYPE_FINGER);
value = g_enum_get_value_by_nick (eclass, str);
if (value == NULL)
return FP_FINGER_UNKNOWN;
return value->value;
}
static const char *
finger_to_str (FpFinger finger)
{
GEnumClass *eclass;
GEnumValue *value;
eclass = g_type_class_ref (FP_TYPE_FINGER);
value = g_enum_get_value (eclass, finger);
g_type_class_unref (eclass);
if (value == NULL)
return NULL;
return value->value_nick;
}
static gboolean
parse_code (const char *str)
{
if (g_strcmp0 (str, "1") == 0 ||
g_strcmp0 (str, "success") == 0 ||
g_strcmp0 (str, "SUCCESS") == 0 ||
g_strcmp0 (str, "FPI_MATCH_SUCCESS") == 0)
return FPI_MATCH_SUCCESS;
return FPI_MATCH_FAIL;
}
static void
handle_command_line (FpDeviceVirtualDevice *self,
const char *line)
{
if (g_str_has_prefix (line, ADD_CMD_PREFIX))
{
g_auto(GStrv) elems;
FpPrint *print;
FpFinger finger;
gboolean success;
g_autofree char *description = NULL;
char *key;
/* Syntax: ADD <finger> <username> <error when used> */
elems = g_strsplit (line + strlen (ADD_CMD_PREFIX), " ", 3);
if (g_strv_length (elems) != 3)
{
g_warning ("Malformed command: %s", line);
return;
}
finger = str_to_finger (elems[0]);
if (finger == FP_FINGER_UNKNOWN)
{
g_warning ("Unknown finger '%s'", elems[0]);
return;
}
print = fp_print_new (FP_DEVICE (self));
fp_print_set_finger (print, finger);
fp_print_set_username (print, elems[1]);
description = g_strdup_printf ("Fingerprint finger '%s' for user '%s'",
elems[0], elems[1]);
fp_print_set_description (print, description);
success = parse_code (elems[2]);
key = g_strdup_printf ("%s-%s", elems[0], elems[1]);
g_hash_table_insert (self->pending_prints,
key, GINT_TO_POINTER (success));
fp_dbg ("Added pending print %s for user %s (code: %s)",
elems[0], elems[1], success ? "FPI_MATCH_SUCCESS" : "FPI_MATCH_FAIL");
}
else
{
g_warning ("Unhandled command sent: '%s'", line);
}
}
static void
recv_instruction_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self;
gboolean success;
gsize bytes;
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
if (!success || bytes == 0)
{
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 instruction data: %s", error->message);
}
self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
goto out;
}
self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
handle_command_line (self, (const char *) self->line);
out:
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
start_listen (self);
}
static void
recv_instruction (FpDeviceVirtualDevice *self,
GInputStream *stream)
{
memset (&self->line, 0, sizeof (self->line));
g_input_stream_read_all_async (stream,
self->line,
sizeof (self->line),
G_PRIORITY_DEFAULT,
self->cancellable,
recv_instruction_cb,
self);
}
static void
new_connection_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
g_autoptr(GSocketConnection) connection = NULL;
GInputStream *stream;
FpDeviceVirtualDevice *self = 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 (self);
return;
}
/* Always further connections (but we disconnect them immediately
* if we already have a connection). */
if (self->connection)
{
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
start_listen (self);
return;
}
self->connection = g_steal_pointer (&connection);
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
recv_instruction (self, stream);
fp_dbg ("Got a new connection!");
}
static void
start_listen (FpDeviceVirtualDevice *self)
{
fp_dbg ("Starting a new listener");
g_socket_listener_accept_async (self->listener,
self->cancellable,
new_connection_cb,
self);
}
static void
dev_init (FpDevice *dev)
{
fpi_device_open_complete (dev, NULL);
}
static void
dev_verify (FpDevice *dev)
{
FpPrint *print;
g_autoptr(GVariant) data = NULL;
gboolean success;
fpi_device_get_verify_data (dev, &print);
g_object_get (print, "fpi-data", &data, NULL);
success = g_variant_get_boolean (data);
fpi_device_verify_report (dev,
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
NULL, NULL);
fpi_device_verify_complete (dev, NULL);
}
static void
dev_enroll (FpDevice *dev)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
gpointer success_ptr;
FpPrint *print = NULL;
g_autofree char *key = NULL;
fpi_device_get_enroll_data (dev, &print);
key = g_strdup_printf ("%s-%s",
finger_to_str (fp_print_get_finger (print)),
fp_print_get_username (print));
if (g_hash_table_lookup_extended (self->pending_prints, key, NULL, &success_ptr))
{
gboolean success = GPOINTER_TO_INT (success_ptr);
GVariant *fp_data;
fp_data = g_variant_new_boolean (success);
fpi_print_set_type (print, FPI_PRINT_RAW);
if (fpi_device_get_driver_data (dev) == VIRTUAL_DEVICE_IDENT)
fpi_print_set_device_stored (print, TRUE);
g_object_set (print, "fpi-data", fp_data, NULL);
fpi_device_enroll_complete (dev, g_object_ref (print), NULL);
}
else
{
fpi_device_enroll_complete (dev, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"No pending result for this username/finger combination"));
}
}
static void
dev_deinit (FpDevice *dev)
{
fpi_device_close_complete (dev, NULL);
}
static gboolean
dev_supports_identify (FpDevice *dev)
{
return fpi_device_get_driver_data (dev) == VIRTUAL_DEVICE_IDENT;
}
static void
dev_identify (FpDevice *dev)
{
GPtrArray *templates;
FpPrint *result = NULL;
guint i;
g_assert (fpi_device_get_driver_data (dev) == VIRTUAL_DEVICE_IDENT);
fpi_device_get_identify_data (dev, &templates);
for (i = 0; i < templates->len; i++)
{
FpPrint *template = g_ptr_array_index (templates, i);
g_autoptr(GVariant) data = NULL;
gboolean success;
g_object_get (dev, "fpi-data", &template, NULL);
success = g_variant_get_boolean (data);
if (success)
{
result = template;
break;
}
}
if (result)
fpi_device_identify_report (dev, result, NULL, NULL);
fpi_device_identify_complete (dev, NULL);
}
static void
fpi_device_virtual_device_finalize (GObject *object)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (object);
G_DEBUG_HERE ();
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listener);
g_clear_object (&self->connection);
g_hash_table_destroy (self->pending_prints);
}
static void
fpi_device_virtual_device_constructed (GObject *object)
{
g_autoptr(GError) error = NULL;
g_autoptr(GSocketListener) listener = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (object);
const char *env;
g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE ();
self->client_fd = -1;
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))
{
g_warning ("Could not listen on unix socket: %s", error->message);
fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
return;
}
self->listener = g_steal_pointer (&listener);
self->cancellable = g_cancellable_new ();
self->pending_prints = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
NULL);
if (G_OBJECT_CLASS (fpi_device_virtual_device_parent_class)->constructed)
G_OBJECT_CLASS (fpi_device_virtual_device_parent_class)->constructed (object);
start_listen (self);
}
static void
fpi_device_virtual_device_init (FpDeviceVirtualDevice *self)
{
}
static const FpIdEntry driver_ids[] = {
{ .virtual_envvar = "FP_VIRTUAL_DEVICE", .driver_data = VIRTUAL_DEVICE },
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT", .driver_data = VIRTUAL_DEVICE_IDENT },
{ .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->constructed = fpi_device_virtual_device_constructed;
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;
dev_class->identify = dev_identify;
dev_class->supports_identify = dev_supports_identify;
}

View File

@@ -21,7 +21,7 @@
/*
* This is a virtual driver to debug the image based drivers. A small
* python script is provided to connect to it via a socket, allowing
* prints to be sent to this device programatically.
* prints to be sent to this device programmatically.
* Using this it is possible to test libfprint and fprintd.
*/
@@ -215,6 +215,7 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
g_warning ("Error accepting a new connection: %s", error->message);
start_listen (dev);
return;
}
/* Always further connections (but we disconnect them immediately
@@ -277,7 +278,7 @@ dev_init (FpImageDevice *dev)
{
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;
}

View File

@@ -94,22 +94,21 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u
FpContext *context;
FpContextPrivate *priv;
device = (FpDevice *) g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, &error);
if (!device)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
context = FP_CONTEXT (user_data);
priv = fp_context_get_instance_private (context);
priv->pending_devices--;
g_message ("Ignoring device due to initialization error: %s", error->message);
return;
}
device = FP_DEVICE (g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
res, &error));
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
context = FP_CONTEXT (user_data);
priv = fp_context_get_instance_private (context);
priv->pending_devices--;
if (error)
{
g_message ("Ignoring device due to initialization error: %s", error->message);
return;
}
g_ptr_array_add (priv->devices, device);
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
}
@@ -159,7 +158,7 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
if (found_driver == G_TYPE_NONE)
{
g_debug ("No driver found for USB device %04X:%04X", pid, vid);
g_debug ("No driver found for USB device %04X:%04X", vid, pid);
return;
}

View File

@@ -28,7 +28,7 @@
* @title: Internal FpDevice
* @short_description: Internal device routines
*
* The methods that are availabe for drivers to manipulate a device. See
* The methods that are available for drivers to manipulate a device. See
* #FpDeviceClass for more information. Also note that most of these are
* not relevant for image based devices, see #FpImageDeviceClass in that
* case.
@@ -339,7 +339,7 @@ fp_device_class_init (FpDeviceClass *klass)
properties[PROP_OPEN] =
g_param_spec_boolean ("open",
"Opened",
"Wether the device is open or not", FALSE,
"Whether the device is open or not", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
/**
@@ -507,6 +507,9 @@ fp_device_supports_identify (FpDevice *device)
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
if (cls->supports_identify != NULL)
return cls->supports_identify (device);
return cls->identify != NULL;
}
@@ -946,6 +949,13 @@ fp_device_identify (FpDevice *device,
if (g_task_return_error_if_cancelled (task))
return;
if (!fp_device_supports_identify (device))
{
g_task_return_error (task,
fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
return;
}
if (!priv->is_open)
{
g_task_return_error (task,

View File

@@ -79,7 +79,7 @@ typedef enum {
/**
* FpDeviceError:
* @FP_DEVICE_ERROR_GENERAL: A general error occured.
* @FP_DEVICE_ERROR_GENERAL: A general error occurred.
* @FP_DEVICE_ERROR_NOT_SUPPORTED: The device does not support the requested
* operation.
* @FP_DEVICE_ERROR_NOT_OPEN: The device needs to be opened to start this
@@ -113,7 +113,7 @@ GQuark fp_device_error_quark (void);
* FpEnrollProgress:
* @device: a #FpDevice
* @completed_stages: Number of completed stages
* @print: (nullable) (transfer none): The last scaned print
* @print: (nullable) (transfer none): The last scanned print
* @user_data: (nullable) (transfer none): User provided data
* @error: (nullable) (transfer none): #GError or %NULL
*

View File

@@ -100,7 +100,7 @@ fp_image_device_close (FpDevice *device)
* 1. We are inactive
* -> immediately close
* 2. We are waiting for finger off
* -> imediately deactivate
* -> immediately deactivate
* 3. We are deactivating
* -> handled by deactivate_complete */

View File

@@ -184,10 +184,8 @@ fp_image_detect_minutiae_cb (GObject *source_object,
GTask *task = G_TASK (res);
FpImage *image;
DetectMinutiaeData *data = g_task_get_task_data (task);
GCancellable *cancellable;
cancellable = g_task_get_cancellable (task);
if (!cancellable || !g_cancellable_is_cancelled (cancellable))
if (!g_task_had_error (task))
{
gint i;
image = FP_IMAGE (source_object);
@@ -316,6 +314,14 @@ fp_image_detect_minutiae_thread_func (GTask *task,
return;
}
if (!data->minutiae || data->minutiae->num == 0)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
"No minutiae found");
g_object_unref (task);
return;
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}

View File

@@ -51,7 +51,7 @@ enum {
PROP_IMAGE,
/* The following is metadata that is stored by default for each print.
* Drivers may make use of these during enrollment (e.g. to additionaly store
* Drivers may make use of these during enrollment (e.g. to additionally store
* the metadata on the device). */
PROP_FINGER,
PROP_USERNAME,
@@ -588,7 +588,7 @@ fp_print_equal (FpPrint *self, FpPrint *other)
}
else if (self->type == FPI_PRINT_NBIS)
{
gint i;
guint i;
if (self->prints->len != other->prints->len)
return FALSE;
@@ -661,7 +661,7 @@ fp_print_serialize (FpPrint *print,
if (print->type == FPI_PRINT_NBIS)
{
GVariantBuilder nested = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(a(aiaiai))"));
gint i;
guint i;
g_variant_builder_open (&nested, G_VARIANT_TYPE ("a(aiaiai)"));
for (i = 0; i < print->prints->len; i++)
@@ -812,7 +812,7 @@ fp_print_deserialize (const guchar *data,
if (type == FPI_PRINT_NBIS)
{
g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
gint i;
guint i;
result = g_object_new (FP_TYPE_PRINT,
"driver", driver,

View File

@@ -28,7 +28,7 @@
* @title: Internal FpDevice
* @short_description: Internal device routines
*
* The methods that are availabe for drivers to manipulate a device. See
* The methods that are available for drivers to manipulate a device. See
* #FpDeviceClass for more information. Also note that most of these are
* not relevant for image based devices, see #FpImageDeviceClass in that
* case.
@@ -100,7 +100,7 @@ fpi_device_error_new (FpDeviceError error)
switch (error)
{
case FP_DEVICE_ERROR_GENERAL:
msg = "An unspecified error occured!";
msg = "An unspecified error occurred!";
break;
case FP_DEVICE_ERROR_NOT_SUPPORTED:
@@ -138,7 +138,7 @@ fpi_device_error_new (FpDeviceError error)
default:
g_warning ("Unsupported error, returning general error instead!");
error = FP_DEVICE_ERROR_GENERAL;
msg = "An unspecified error occured!";
msg = "An unspecified error occurred!";
}
return g_error_new_literal (FP_DEVICE_ERROR, error, msg);

View File

@@ -65,10 +65,10 @@ struct _FpIdEntry
* @probe: Called immediately for all devices. Most drivers will not need to
* implement this. Drivers should setup the device identifier from the probe
* callback which will be used to verify the compatibility of stored
* #FpPrint's. It is permissable to temporarily open the USB device if this
* #FpPrint's. It is permissible to temporarily open the USB device if this
* is required for the operation. If an error is returned, then the device
* will be destroyed again immediately and never reported to the API user.
* @open: Open the device for futher operations. Any of the normal actions are
* @open: Open the device for further operations. Any of the normal actions are
* guaranteed to only happen when the device is open (this includes delete).
* @close: Close the device again
* @enroll: Start an enroll operation
@@ -79,6 +79,7 @@ struct _FpIdEntry
* @delete: Delete a print from the device
* @cancel: Called on cancellation, this is a convenience to not need to handle
* the #GCancellable directly by using fpi_device_get_cancellable().
* @supports_identify: Whether identify operations are supported.
*
* NOTE: If your driver is image based, then you should subclass #FpImageDevice
* instead. #FpImageDevice based drivers use a different way of interacting
@@ -128,7 +129,9 @@ struct _FpDeviceClass
void (*list) (FpDevice *device);
void (*delete) (FpDevice * device);
void (*cancel) (FpDevice *device);
void (*cancel) (FpDevice *device);
gboolean (*supports_identify) (FpDevice *device);
};
/**

View File

@@ -171,7 +171,16 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
print = fp_print_new (device);
fpi_print_set_type (print, FPI_PRINT_NBIS);
if (!fpi_print_add_from_image (print, image, &error))
g_clear_object (&print);
{
g_clear_object (&print);
if (error->domain != FP_DEVICE_RETRY)
{
fpi_device_action_error (device, error);
fpi_image_device_deactivate (self);
return;
}
}
}
if (action == FPI_DEVICE_ACTION_ENROLL)

View File

@@ -23,6 +23,7 @@
#include "fp-print-private.h"
#include "fpi-device.h"
#include "fpi-compat.h"
/**
* SECTION: fpi-print
@@ -247,3 +248,115 @@ fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GErr
return FPI_MATCH_FAIL;
}
/**
* fpi_print_generate_user_id:
* @print: #FpPrint to generate the ID for
*
* Generates a string identifier for the represented print. This identifier
* encodes some metadata about the print. It also includes a random string
* and may be assumed to be unique.
*
* This is useful if devices are able to store a string identifier, but more
* storing more metadata may be desirable. In effect, this means the driver
* can provide somewhat more meaningful data to fp_device_list_prints().
*
* The generated ID may be truncated after 23 characters. However, more space
* is required to include the username, and it is recommended to store at
* at least 31 bytes.
*
* The generated format may change in the future. It is versioned though and
* decoding should remain functional.
*
* Returns: A unique string of 23 + strlen(username) characters
*/
gchar *
fpi_print_generate_user_id (FpPrint *print)
{
const gchar *username = NULL;
gchar *user_id = NULL;
const GDate *date;
gint y = 0, m = 0, d = 0;
gint32 rand_id = 0;
g_assert (print);
date = fp_print_get_enroll_date (print);
if (date && g_date_valid (date))
{
y = g_date_get_year (date);
m = g_date_get_month (date);
d = g_date_get_day (date);
}
username = fp_print_get_username (print);
if (!username)
username = "nobody";
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
rand_id = 0;
else
rand_id = g_random_int ();
user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s",
y, m, d,
fp_print_get_finger (print),
rand_id,
username);
return user_id;
}
/**
* fpi_print_fill_from_user_id:
* @print: #FpPrint to fill metadata into
* @user_id: An ID that was likely encoded using fpi_print_generate_user_id()
*
* This is the reverse operation of fpi_print_generate_user_id(), allowing
* the driver to encode some print metadata in a string.
*
* Returns: Whether a valid ID was found
*/
gboolean
fpi_print_fill_from_user_id (FpPrint *print, const char *user_id)
{
g_return_val_if_fail (user_id, FALSE);
/* The format has 24 bytes at the start and some dashes in the right places */
if (g_str_has_prefix (user_id, "FP1-") && strlen (user_id) >= 24 &&
user_id[12] == '-' && user_id[14] == '-' && user_id[23] == '-')
{
g_autofree gchar *copy = g_strdup (user_id);
g_autoptr(GDate) date = NULL;
gint32 date_ymd;
gint32 finger;
gchar *username;
/* Try to parse information from the string. */
copy[12] = '\0';
date_ymd = g_ascii_strtod (copy + 4, NULL);
if (date_ymd > 0)
date = g_date_new_dmy (date_ymd % 100,
(date_ymd / 100) % 100,
date_ymd / 10000);
else
date = g_date_new ();
fp_print_set_enroll_date (print, date);
copy[14] = '\0';
finger = g_ascii_strtoll (copy + 13, NULL, 16);
fp_print_set_finger (print, finger);
/* We ignore the next chunk, it is just random data.
* Then comes the username; nobody is the default if the metadata
* is unknown */
username = copy + 24;
if (strlen (username) > 0 && g_strcmp0 (username, "nobody") != 0)
fp_print_set_username (print, username);
return TRUE;
}
return FALSE;
}

View File

@@ -20,7 +20,7 @@ typedef enum {
/**
* FpiMatchResult:
* @FPI_MATCH_ERROR: An error occured during matching
* @FPI_MATCH_ERROR: An error occurred during matching
* @FPI_MATCH_FAIL: The prints did not match
* @FPI_MATCH_SUCCESS: The prints matched
*/
@@ -47,4 +47,9 @@ FpiMatchResult fpi_print_bz3_match (FpPrint * template,
gint bz3_threshold,
GError **error);
/* Helpers to encode metadata into user ID strings. */
gchar * fpi_print_generate_user_id (FpPrint *print);
gboolean fpi_print_fill_from_user_id (FpPrint *print,
const char *user_id);
G_END_DECLS

View File

@@ -366,7 +366,7 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
*
* Note that #FpiUsbTransfer will be stolen when this function is called.
* So that all associated data will be free'ed automatically, after the
* callback ran unless fpi_usb_transfer_ref() is explictly called.
* callback ran unless fpi_usb_transfer_ref() is explicitly called.
*/
void
fpi_usb_transfer_submit (FpiUsbTransfer *transfer,

View File

@@ -61,7 +61,7 @@ typedef enum {
* @length: The requested length of the transfer in bytes.
* @actual_length: The actual length of the transfer
* (see also fpi_usb_transfer_set_short_error())
* @buffer: The transfered data.
* @buffer: The transferred data.
*
* Helper for handling USB transfers.
*/

View File

@@ -2,7 +2,7 @@
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -2,7 +2,7 @@
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@@ -31,6 +31,7 @@ libfprint_private_headers = [
'fpi-byte-reader.h',
'fpi-byte-utils.h',
'fpi-byte-writer.h',
'fpi-compat.h',
'fpi-context.h',
'fpi-device.h',
'fpi-image-device.h',
@@ -154,6 +155,9 @@ 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 == 'synaptics'
drivers_sources += [
'drivers/synaptics/synaptics.c',
@@ -203,6 +207,7 @@ deps = [
enums_dep,
gio_dep,
glib_dep,
gobject_dep,
gusb_dep,
imaging_dep,
mathlib_dep,
@@ -258,7 +263,7 @@ libfprint = library(versioned_libname.split('lib')[1],
version: libversion,
link_args : vflag,
link_depends : mapfile,
link_with: [libfprint_private, libfprint_drivers],
link_with: [libfprint_drivers, libfprint_private],
dependencies: deps,
install: true)
@@ -268,6 +273,7 @@ libfprint_dep = declare_dependency(link_with: libfprint,
enums_dep,
gio_dep,
glib_dep,
gobject_dep,
gusb_dep,
])
@@ -324,6 +330,7 @@ if get_option('introspection')
link_with : libfprint,
dependencies : [
gio_dep,
gobject_dep,
gusb_dep,
],
includes : [

View File

@@ -79,6 +79,7 @@ versioned_libname = meson.project_name() + '-' + soversion.to_string()
# Dependencies
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
gusb_dep = dependency('gusb', version: '>= 0.2.0')
mathlib_dep = cc.find_library('m', required: false)
@@ -87,7 +88,7 @@ cairo_dep = dependency('cairo', required: false)
# Drivers
drivers = get_option('drivers').split(',')
virtual_drivers = [ 'virtual_image' ]
virtual_drivers = [ 'virtual_image', 'virtual_device' ]
default_drivers = [
'upektc_img',
'vfs5011',
@@ -210,6 +211,7 @@ pkgconfig.generate(
description: 'Generic C API for fingerprint reader access',
version: meson.project_version(),
libraries: libfprint,
requires: [gio_dep, gobject_dep],
subdirs: versioned_libname,
filebase: versioned_libname,
)

File diff suppressed because one or more lines are too long

View File

@@ -189,6 +189,7 @@ static void
fpi_device_fake_capture (FpDevice *device)
{
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
gboolean wait_for_finger;
fake_dev->last_called_function = fpi_device_fake_capture;
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FPI_DEVICE_ACTION_CAPTURE);
@@ -199,7 +200,8 @@ fpi_device_fake_capture (FpDevice *device)
return;
}
fpi_device_get_capture_data (device, (gboolean *) &fake_dev->action_data);
fpi_device_get_capture_data (device, &wait_for_finger);
fake_dev->action_data = GINT_TO_POINTER (wait_for_finger);
fpi_device_capture_complete (device, fake_dev->ret_image, fake_dev->ret_error);
}
@@ -234,7 +236,7 @@ fpi_device_fake_delete (FpDevice *device)
return;
}
fpi_device_get_delete_data (device, (gpointer) (&fake_dev->action_data));
fpi_device_get_delete_data (device, (FpPrint **) (&fake_dev->action_data));
fpi_device_delete_complete (device, fake_dev->ret_error);
}

View File

@@ -49,7 +49,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);
@@ -70,7 +70,7 @@ test_context_has_virtual_device (void)
g_assert_true (FP_IS_DEVICE (virtual_device));
fpt_teardown_virtual_device_environment ();
fpt_teardown_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
}
static void
@@ -81,7 +81,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);
@@ -89,7 +89,7 @@ test_context_enumerates_new_devices (void)
g_assert_nonnull (devices);
g_assert_cmpuint (devices->len, ==, 1);
fpt_teardown_virtual_device_environment ();
fpt_teardown_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
}
int

View File

@@ -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_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);
@@ -190,7 +190,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));
@@ -199,7 +199,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));
@@ -208,7 +208,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));

View File

@@ -959,7 +959,7 @@ test_driver_verify_complete_retry (void)
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
g_assert_true (error != g_steal_pointer (&fake_dev->user_data));
g_steal_pointer (&fake_dev->user_data);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_assert_true (match_data->called);
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
@@ -981,7 +981,7 @@ test_driver_verify_complete_retry (void)
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
g_assert_true (error != g_steal_pointer (&fake_dev->user_data));
g_steal_pointer (&fake_dev->user_data);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_assert_true (match_data->called);
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
@@ -1001,7 +1001,7 @@ test_driver_verify_complete_retry (void)
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
g_assert_true (error != g_steal_pointer (&fake_dev->user_data));
g_steal_pointer (&fake_dev->user_data);
g_assert_error (error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL);
g_assert_true (match_data->called);
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL);
@@ -1296,7 +1296,7 @@ test_driver_identify_complete_retry (void)
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
g_assert_true (error != g_steal_pointer (&fake_dev->user_data));
g_steal_pointer (&fake_dev->user_data);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_assert_true (match_data->called);
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);

View File

@@ -22,41 +22,60 @@
#include "test-utils.h"
void
fpt_teardown_virtual_device_environment (void)
struct
{
const char *path = g_getenv ("FP_VIRTUAL_IMAGE");
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 */
{ "FP_VIRTUAL_DEVICE", "virtual_device", "virtual_device" }, /* FPT_VIRTUAL_DEVICE */
{ "FP_VIRTUAL_DEVICE_IDENT", "virtual_device", "virtual_device_ident" } /* FPT_VIRTUAL_DEVICE_IDENT */
};
void
fpt_teardown_virtual_device_environment (FptVirtualDeviceType devtype)
{
const char *path;
path = g_getenv (devtype_vars[devtype].envvar);
if (path)
{
g_autofree char *temp_dir = g_path_get_dirname (path);
g_unsetenv ("FP_VIRTUAL_IMAGE");
g_unsetenv (devtype_vars[devtype].envvar);
g_unlink (path);
g_rmdir (temp_dir);
}
}
static FptVirtualDeviceType global_devtype;
static void
on_signal_event (int sig)
{
fpt_teardown_virtual_device_environment ();
fpt_teardown_virtual_device_environment (global_devtype);
}
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 +97,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 +118,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;
@@ -105,6 +127,7 @@ fpt_context_new_with_virtual_imgdev (void)
g_assert_true (FP_IS_DEVICE (tctx->device));
g_object_add_weak_pointer (G_OBJECT (tctx->device), (gpointer) & tctx->device);
g_object_set_data (G_OBJECT (tctx->fp_context), "devtype", GUINT_TO_POINTER (devtype));
return tctx;
}
@@ -112,6 +135,10 @@ fpt_context_new_with_virtual_imgdev (void)
void
fpt_context_free (FptContext *tctx)
{
FptVirtualDeviceType devtype;
devtype = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tctx->fp_context), "devtype"));
if (tctx->device && fp_device_is_open (tctx->device))
{
g_autoptr(GError) error = NULL;
@@ -123,5 +150,5 @@ fpt_context_free (FptContext *tctx)
g_clear_object (&tctx->fp_context);
g_free (tctx);
fpt_teardown_virtual_device_environment ();
fpt_teardown_virtual_device_environment (devtype);
}

View File

@@ -19,8 +19,15 @@
#include <glib.h>
void fpt_setup_virtual_device_environment (void);
void fpt_teardown_virtual_device_environment (void);
typedef enum {
FPT_VIRTUAL_DEVICE_IMAGE = 0,
FPT_VIRTUAL_DEVICE,
FPT_VIRTUAL_DEVICE_IDENTIFY,
FPT_NUM_VIRTUAL_DEVICE_TYPES
} FptVirtualDeviceType;
void fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype);
void fpt_teardown_virtual_device_environment (FptVirtualDeviceType devtype);
typedef struct _FptContext
{
@@ -30,7 +37,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);

View File

@@ -3,11 +3,10 @@
import sys
try:
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib, Gio
import os
import sys
from gi.repository import GLib, Gio
import unittest
import socket
import struct
@@ -20,6 +19,8 @@ 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:
@@ -101,12 +102,14 @@ class VirtualImage(unittest.TestCase):
del self.con
self.dev.close_sync()
def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT, iterate=True):
def send_retry(self, retry_error=None, iterate=True):
retry_error = retry_error if retry_error else FPrint.DeviceRetry.TOO_SHORT
self.con.sendall(struct.pack('ii', -1, retry_error))
while iterate and ctx.pending():
ctx.iteration(False)
def send_error(self, device_error=FPrint.DeviceError.GENERAL, iterate=True):
def send_error(self, device_error=None, iterate=True):
device_error = device_error if device_error else FPrint.DeviceError.GENERAL
self.con.sendall(struct.pack('ii', -2, device_error))
while iterate and ctx.pending():
ctx.iteration(False)
@@ -346,5 +349,12 @@ class VirtualImage(unittest.TestCase):
assert(not self._verify_match)
if __name__ == '__main__':
try:
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint
except Exception as e:
print("Missing dependencies: %s" % str(e))
sys.exit(77)
# avoid writing to stderr
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))