Skip to content

Commit

Permalink
virtual-device: Wait for delayed commands to be processed
Browse files Browse the repository at this point in the history
This allows to mimick the image device better, so that we can start an
operation and send the commands within some delay.
  • Loading branch information
3v1n0 committed Jan 25, 2021
1 parent 89890db commit ce9527d
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 11 deletions.
4 changes: 4 additions & 0 deletions libfprint/drivers/virtual-device-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ struct _FpDeviceVirtualDevice
GPtrArray *pending_commands;

GHashTable *prints_storage;

guint wait_command_id;
};

/* Not really final here, but we can do this to share the FpDeviceVirtualDevice
Expand All @@ -91,3 +93,5 @@ G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_st


char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error);
gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error);
6 changes: 4 additions & 2 deletions libfprint/drivers/virtual-device-storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage,
static void
dev_identify (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
GPtrArray *prints;
GError *error = NULL;
g_autofree char *scan_id = NULL;

fpi_device_get_identify_data (dev, &prints);

scan_id = process_cmds (self, TRUE, &error);
if (should_wait_for_command (self, error))
return;

if (scan_id)
{
Expand Down Expand Up @@ -71,7 +73,7 @@ dev_identify (FpDevice *dev)
NULL);
}

fpi_device_identify_complete (dev, error);
fpi_device_identify_complete (dev, g_steal_pointer (&error));
}

struct ListData
Expand Down
80 changes: 71 additions & 9 deletions libfprint/drivers/virtual-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,34 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)

#define LIST_CMD "LIST"

static void
maybe_continue_current_action (FpDeviceVirtualDevice *self)
{
FpDevice *dev = FP_DEVICE (self);

switch (fpi_device_get_current_action (dev))
{
case FPI_DEVICE_ACTION_ENROLL:
FP_DEVICE_GET_CLASS (self)->enroll (dev);
break;

case FPI_DEVICE_ACTION_VERIFY:
FP_DEVICE_GET_CLASS (self)->verify (dev);
break;

case FPI_DEVICE_ACTION_IDENTIFY:
FP_DEVICE_GET_CLASS (self)->identify (dev);
break;

default:
break;
}
}

char *
process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error)
process_cmds (FpDeviceVirtualDevice * self,
gboolean scan,
GError * *error)
{
while (self->pending_commands->len > 0)
{
Expand Down Expand Up @@ -96,7 +122,7 @@ process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error)
}

/* No commands left, throw a timeout error. */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands left that can be run!");
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No commands left that can be run!");
return NULL;
}

Expand All @@ -120,7 +146,7 @@ recv_instruction_cb (GObject *source_object,
gsize bytes;

bytes = fp_device_virtual_listener_read_finish (listener, res, &error);
fp_dbg ("Got instructions of length %ld\n", bytes);
fp_dbg ("Got instructions of length %ld", bytes);

if (error)
{
Expand All @@ -139,6 +165,7 @@ recv_instruction_cb (GObject *source_object,
self = FP_DEVICE_VIRTUAL_DEVICE (user_data);

cmd = g_strndup (self->recv_buf, bytes);
fp_dbg ("Received command %s", cmd);

if (g_str_has_prefix (cmd, LIST_CMD))
{
Expand All @@ -148,6 +175,9 @@ recv_instruction_cb (GObject *source_object,
else
{
g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd));
g_clear_handle_id (&self->wait_command_id, g_source_remove);

maybe_continue_current_action (self);
}
}

Expand Down Expand Up @@ -204,17 +234,46 @@ dev_init (FpDevice *dev)
fpi_device_open_complete (dev, NULL);
}

static gboolean
wait_for_command_timeout (gpointer data)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data);
GError *error = NULL;

self->wait_command_id = 0;
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
fpi_device_action_error (FP_DEVICE (self), error);

return FALSE;
}

gboolean
should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return FALSE;

if (self->wait_command_id)
return FALSE;

self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
return TRUE;
}

static void
dev_verify (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
FpPrint *print;
GError *error = NULL;
g_autofree char *scan_id = NULL;

fpi_device_get_verify_data (dev, &print);

scan_id = process_cmds (self, TRUE, &error);
if (should_wait_for_command (self, error))
return;

if (scan_id)
{
Expand All @@ -240,23 +299,25 @@ dev_verify (FpDevice *dev)
}
else
{
g_debug ("Virtual device scann failed with error: %s", error->message);
g_debug ("Virtual device scan failed with error: %s", error->message);
}

fpi_device_verify_complete (dev, error);
fpi_device_verify_complete (dev, g_steal_pointer (&error));
}

static void
dev_enroll (FpDevice *dev)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
GError *error = NULL;
FpPrint *print = NULL;
g_autofree char *id = NULL;

fpi_device_get_enroll_data (dev, &print);

id = process_cmds (self, TRUE, &error);
if (should_wait_for_command (self, error))
return;

if (id)
{
Expand All @@ -272,11 +333,11 @@ dev_enroll (FpDevice *dev)
fpi_print_set_device_stored (print, TRUE);
}

fpi_device_enroll_complete (dev, g_object_ref (print), error);
fpi_device_enroll_complete (dev, g_object_ref (print), NULL);
}
else
{
fpi_device_enroll_complete (dev, NULL, error);
fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error));
}
}

Expand All @@ -285,6 +346,7 @@ dev_deinit (FpDevice *dev)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);

g_clear_handle_id (&self->wait_command_id, g_source_remove);
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listener);
Expand Down

0 comments on commit ce9527d

Please sign in to comment.