Compare commits
7 commits
master
...
wip/hadess
Author | SHA1 | Date | |
---|---|---|---|
|
8d871751f6 | ||
|
4fdf0eae0f | ||
|
8632877b95 | ||
|
170d7c2cf7 | ||
|
e2d4b0d249 | ||
|
b0c546164e | ||
|
f2ae3fb8c5 |
11 changed files with 597 additions and 37 deletions
53
examples/sendvirtcmd.py
Executable file
53
examples/sendvirtcmd.py
Executable 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'))
|
||||||
|
|
456
libfprint/drivers/virtual-device.c
Normal file
456
libfprint/drivers/virtual-device.c
Normal 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;
|
||||||
|
}
|
|
@ -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);
|
g_warning ("Error accepting a new connection: %s", error->message);
|
||||||
start_listen (dev);
|
start_listen (dev);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always further connections (but we disconnect them immediately
|
/* 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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -507,6 +507,9 @@ fp_device_supports_identify (FpDevice *device)
|
||||||
|
|
||||||
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
|
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
|
||||||
|
|
||||||
|
if (cls->supports_identify != NULL)
|
||||||
|
return cls->supports_identify (device);
|
||||||
|
|
||||||
return cls->identify != NULL;
|
return cls->identify != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,6 +949,13 @@ fp_device_identify (FpDevice *device,
|
||||||
if (g_task_return_error_if_cancelled (task))
|
if (g_task_return_error_if_cancelled (task))
|
||||||
return;
|
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)
|
if (!priv->is_open)
|
||||||
{
|
{
|
||||||
g_task_return_error (task,
|
g_task_return_error (task,
|
||||||
|
|
|
@ -79,6 +79,7 @@ struct _FpIdEntry
|
||||||
* @delete: Delete a print from the device
|
* @delete: Delete a print from the device
|
||||||
* @cancel: Called on cancellation, this is a convenience to not need to handle
|
* @cancel: Called on cancellation, this is a convenience to not need to handle
|
||||||
* the #GCancellable directly by using fpi_device_get_cancellable().
|
* 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
|
* NOTE: If your driver is image based, then you should subclass #FpImageDevice
|
||||||
* instead. #FpImageDevice based drivers use a different way of interacting
|
* instead. #FpImageDevice based drivers use a different way of interacting
|
||||||
|
@ -129,6 +130,8 @@ struct _FpDeviceClass
|
||||||
void (*delete) (FpDevice * device);
|
void (*delete) (FpDevice * device);
|
||||||
|
|
||||||
void (*cancel) (FpDevice *device);
|
void (*cancel) (FpDevice *device);
|
||||||
|
|
||||||
|
gboolean (*supports_identify) (FpDevice *device);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -155,6 +155,9 @@ foreach driver: drivers
|
||||||
if driver == 'virtual_image'
|
if driver == 'virtual_image'
|
||||||
drivers_sources += [ 'drivers/virtual-image.c' ]
|
drivers_sources += [ 'drivers/virtual-image.c' ]
|
||||||
endif
|
endif
|
||||||
|
if driver == 'virtual_device'
|
||||||
|
drivers_sources += [ 'drivers/virtual-device.c' ]
|
||||||
|
endif
|
||||||
if driver == 'synaptics'
|
if driver == 'synaptics'
|
||||||
drivers_sources += [
|
drivers_sources += [
|
||||||
'drivers/synaptics/synaptics.c',
|
'drivers/synaptics/synaptics.c',
|
||||||
|
|
|
@ -88,7 +88,7 @@ cairo_dep = dependency('cairo', required: false)
|
||||||
|
|
||||||
# Drivers
|
# Drivers
|
||||||
drivers = get_option('drivers').split(',')
|
drivers = get_option('drivers').split(',')
|
||||||
virtual_drivers = [ 'virtual_image' ]
|
virtual_drivers = [ 'virtual_image', 'virtual_device' ]
|
||||||
default_drivers = [
|
default_drivers = [
|
||||||
'upektc_img',
|
'upektc_img',
|
||||||
'vfs5011',
|
'vfs5011',
|
||||||
|
|
|
@ -49,7 +49,7 @@ test_context_has_virtual_device (void)
|
||||||
GPtrArray *devices;
|
GPtrArray *devices;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
fpt_setup_virtual_device_environment ();
|
fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
|
||||||
|
|
||||||
context = fp_context_new ();
|
context = fp_context_new ();
|
||||||
devices = fp_context_get_devices (context);
|
devices = fp_context_get_devices (context);
|
||||||
|
@ -70,7 +70,7 @@ test_context_has_virtual_device (void)
|
||||||
|
|
||||||
g_assert_true (FP_IS_DEVICE (virtual_device));
|
g_assert_true (FP_IS_DEVICE (virtual_device));
|
||||||
|
|
||||||
fpt_teardown_virtual_device_environment ();
|
fpt_teardown_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -81,7 +81,7 @@ test_context_enumerates_new_devices (void)
|
||||||
|
|
||||||
context = fp_context_new ();
|
context = fp_context_new ();
|
||||||
|
|
||||||
fpt_setup_virtual_device_environment ();
|
fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
|
||||||
|
|
||||||
fp_context_enumerate (context);
|
fp_context_enumerate (context);
|
||||||
devices = fp_context_get_devices (context);
|
devices = fp_context_get_devices (context);
|
||||||
|
@ -89,7 +89,7 @@ test_context_enumerates_new_devices (void)
|
||||||
g_assert_nonnull (devices);
|
g_assert_nonnull (devices);
|
||||||
g_assert_cmpuint (devices->len, ==, 1);
|
g_assert_cmpuint (devices->len, ==, 1);
|
||||||
|
|
||||||
fpt_teardown_virtual_device_environment ();
|
fpt_teardown_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -36,7 +36,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx)
|
||||||
static void
|
static void
|
||||||
test_device_open_async (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);
|
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
|
static void
|
||||||
test_device_close_async (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);
|
fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx);
|
||||||
while (!tctx->user_data)
|
while (!tctx->user_data)
|
||||||
|
@ -76,7 +76,7 @@ static void
|
||||||
test_device_open_sync (void)
|
test_device_open_sync (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
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);
|
fp_device_open_sync (tctx->device, NULL, &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
@ -97,7 +97,7 @@ static void
|
||||||
test_device_open_sync_notify (void)
|
test_device_open_sync_notify (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
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);
|
g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx);
|
||||||
fp_device_open_sync (tctx->device, NULL, &error);
|
fp_device_open_sync (tctx->device, NULL, &error);
|
||||||
|
@ -109,7 +109,7 @@ static void
|
||||||
test_device_close_sync (void)
|
test_device_close_sync (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
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_open_sync (tctx->device, NULL, NULL);
|
||||||
fp_device_close_sync (tctx->device, NULL, &error);
|
fp_device_close_sync (tctx->device, NULL, &error);
|
||||||
|
@ -131,7 +131,7 @@ static void
|
||||||
test_device_close_sync_notify (void)
|
test_device_close_sync_notify (void)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
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_open_sync (tctx->device, NULL, NULL);
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ test_device_close_sync_notify (void)
|
||||||
static void
|
static void
|
||||||
test_device_get_driver (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image");
|
g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image");
|
||||||
|
@ -153,7 +153,7 @@ test_device_get_driver (void)
|
||||||
static void
|
static void
|
||||||
test_device_get_device_id (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0");
|
g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0");
|
||||||
|
@ -162,7 +162,7 @@ test_device_get_device_id (void)
|
||||||
static void
|
static void
|
||||||
test_device_get_name (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_cmpstr (fp_device_get_name (tctx->device), ==,
|
g_assert_cmpstr (fp_device_get_name (tctx->device), ==,
|
||||||
|
@ -172,7 +172,7 @@ test_device_get_name (void)
|
||||||
static void
|
static void
|
||||||
test_device_get_scan_type (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE);
|
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
|
static void
|
||||||
test_device_get_nr_enroll_stages (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5);
|
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
|
static void
|
||||||
test_device_supports_identify (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_true (fp_device_supports_identify (tctx->device));
|
g_assert_true (fp_device_supports_identify (tctx->device));
|
||||||
|
@ -199,7 +199,7 @@ test_device_supports_identify (void)
|
||||||
static void
|
static void
|
||||||
test_device_supports_capture (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_true (fp_device_supports_capture (tctx->device));
|
g_assert_true (fp_device_supports_capture (tctx->device));
|
||||||
|
@ -208,7 +208,7 @@ test_device_supports_capture (void)
|
||||||
static void
|
static void
|
||||||
test_device_has_storage (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);
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
g_assert_false (fp_device_has_storage (tctx->device));
|
g_assert_false (fp_device_has_storage (tctx->device));
|
||||||
|
|
|
@ -22,41 +22,60 @@
|
||||||
|
|
||||||
#include "test-utils.h"
|
#include "test-utils.h"
|
||||||
|
|
||||||
void
|
struct
|
||||||
fpt_teardown_virtual_device_environment (void)
|
|
||||||
{
|
{
|
||||||
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)
|
if (path)
|
||||||
{
|
{
|
||||||
g_autofree char *temp_dir = g_path_get_dirname (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_unlink (path);
|
||||||
g_rmdir (temp_dir);
|
g_rmdir (temp_dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FptVirtualDeviceType global_devtype;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_signal_event (int sig)
|
on_signal_event (int sig)
|
||||||
{
|
{
|
||||||
fpt_teardown_virtual_device_environment ();
|
fpt_teardown_virtual_device_environment (global_devtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fpt_setup_virtual_device_environment (void)
|
fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autofree char *temp_dir = NULL;
|
g_autofree char *temp_dir = NULL;
|
||||||
g_autofree char *temp_path = 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);
|
temp_dir = g_dir_make_tmp ("libfprint-XXXXXX", &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
|
|
||||||
temp_path = g_build_filename (temp_dir, "virtual-image.socket", NULL);
|
filename = g_strdup_printf ("%s.socket", devtype_vars[devtype].device_id);
|
||||||
g_setenv ("FP_VIRTUAL_IMAGE", temp_path, TRUE);
|
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 (SIGKILL, on_signal_event);
|
||||||
signal (SIGABRT, on_signal_event);
|
signal (SIGABRT, on_signal_event);
|
||||||
|
@ -78,13 +97,16 @@ fpt_context_new (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
FptContext *
|
FptContext *
|
||||||
fpt_context_new_with_virtual_imgdev (void)
|
fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype)
|
||||||
{
|
{
|
||||||
FptContext *tctx;
|
FptContext *tctx;
|
||||||
GPtrArray *devices;
|
GPtrArray *devices;
|
||||||
unsigned int i;
|
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 ();
|
tctx = fpt_context_new ();
|
||||||
devices = fp_context_get_devices (tctx->fp_context);
|
devices = fp_context_get_devices (tctx->fp_context);
|
||||||
|
@ -96,7 +118,7 @@ fpt_context_new_with_virtual_imgdev (void)
|
||||||
{
|
{
|
||||||
FpDevice *device = devices->pdata[i];
|
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;
|
tctx->device = device;
|
||||||
break;
|
break;
|
||||||
|
@ -105,6 +127,7 @@ fpt_context_new_with_virtual_imgdev (void)
|
||||||
|
|
||||||
g_assert_true (FP_IS_DEVICE (tctx->device));
|
g_assert_true (FP_IS_DEVICE (tctx->device));
|
||||||
g_object_add_weak_pointer (G_OBJECT (tctx->device), (gpointer) & 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;
|
return tctx;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +135,10 @@ fpt_context_new_with_virtual_imgdev (void)
|
||||||
void
|
void
|
||||||
fpt_context_free (FptContext *tctx)
|
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))
|
if (tctx->device && fp_device_is_open (tctx->device))
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
@ -123,5 +150,5 @@ fpt_context_free (FptContext *tctx)
|
||||||
g_clear_object (&tctx->fp_context);
|
g_clear_object (&tctx->fp_context);
|
||||||
g_free (tctx);
|
g_free (tctx);
|
||||||
|
|
||||||
fpt_teardown_virtual_device_environment ();
|
fpt_teardown_virtual_device_environment (devtype);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,15 @@
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
void fpt_setup_virtual_device_environment (void);
|
typedef enum {
|
||||||
void fpt_teardown_virtual_device_environment (void);
|
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
|
typedef struct _FptContext
|
||||||
{
|
{
|
||||||
|
@ -30,7 +37,7 @@ typedef struct _FptContext
|
||||||
} FptContext;
|
} FptContext;
|
||||||
|
|
||||||
FptContext * fpt_context_new (void);
|
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);
|
void fpt_context_free (FptContext *test_context);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue