virtual-device: Wait for delayed commands to be processed

This allows to mimick the image device better, so that we can start an
operation and send the commands within some delay.
This commit is contained in:
Marco Trevisan (Treviño) 2021-01-24 01:15:19 +01:00
parent 89890dbd1f
commit ce9527d2cb
3 changed files with 79 additions and 11 deletions

View file

@ -76,6 +76,8 @@ struct _FpDeviceVirtualDevice
GPtrArray *pending_commands; GPtrArray *pending_commands;
GHashTable *prints_storage; GHashTable *prints_storage;
guint wait_command_id;
}; };
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice /* Not really final here, but we can do this to share the FpDeviceVirtualDevice
@ -91,3 +93,5 @@ G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_st
char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error); char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error);
gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error);

View file

@ -36,14 +36,16 @@ G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage,
static void static void
dev_identify (FpDevice *dev) dev_identify (FpDevice *dev)
{ {
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
GPtrArray *prints; GPtrArray *prints;
GError *error = NULL;
g_autofree char *scan_id = NULL; g_autofree char *scan_id = NULL;
fpi_device_get_identify_data (dev, &prints); fpi_device_get_identify_data (dev, &prints);
scan_id = process_cmds (self, TRUE, &error); scan_id = process_cmds (self, TRUE, &error);
if (should_wait_for_command (self, error))
return;
if (scan_id) if (scan_id)
{ {
@ -71,7 +73,7 @@ dev_identify (FpDevice *dev)
NULL); NULL);
} }
fpi_device_identify_complete (dev, error); fpi_device_identify_complete (dev, g_steal_pointer (&error));
} }
struct ListData struct ListData

View file

@ -41,8 +41,34 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
#define LIST_CMD "LIST" #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 * char *
process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error) process_cmds (FpDeviceVirtualDevice * self,
gboolean scan,
GError * *error)
{ {
while (self->pending_commands->len > 0) while (self->pending_commands->len > 0)
{ {
@ -96,7 +122,7 @@ process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error)
} }
/* No commands left, throw a timeout 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; return NULL;
} }
@ -120,7 +146,7 @@ recv_instruction_cb (GObject *source_object,
gsize bytes; gsize bytes;
bytes = fp_device_virtual_listener_read_finish (listener, res, &error); 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) if (error)
{ {
@ -139,6 +165,7 @@ recv_instruction_cb (GObject *source_object,
self = FP_DEVICE_VIRTUAL_DEVICE (user_data); self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
cmd = g_strndup (self->recv_buf, bytes); cmd = g_strndup (self->recv_buf, bytes);
fp_dbg ("Received command %s", cmd);
if (g_str_has_prefix (cmd, LIST_CMD)) if (g_str_has_prefix (cmd, LIST_CMD))
{ {
@ -148,6 +175,9 @@ recv_instruction_cb (GObject *source_object,
else else
{ {
g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); 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);
} }
} }
@ -204,17 +234,46 @@ dev_init (FpDevice *dev)
fpi_device_open_complete (dev, NULL); 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 static void
dev_verify (FpDevice *dev) dev_verify (FpDevice *dev)
{ {
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
FpPrint *print; FpPrint *print;
GError *error = NULL;
g_autofree char *scan_id = NULL; g_autofree char *scan_id = NULL;
fpi_device_get_verify_data (dev, &print); fpi_device_get_verify_data (dev, &print);
scan_id = process_cmds (self, TRUE, &error); scan_id = process_cmds (self, TRUE, &error);
if (should_wait_for_command (self, error))
return;
if (scan_id) if (scan_id)
{ {
@ -240,23 +299,25 @@ dev_verify (FpDevice *dev)
} }
else 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 static void
dev_enroll (FpDevice *dev) dev_enroll (FpDevice *dev)
{ {
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
GError *error = NULL;
FpPrint *print = NULL; FpPrint *print = NULL;
g_autofree char *id = NULL; g_autofree char *id = NULL;
fpi_device_get_enroll_data (dev, &print); fpi_device_get_enroll_data (dev, &print);
id = process_cmds (self, TRUE, &error); id = process_cmds (self, TRUE, &error);
if (should_wait_for_command (self, error))
return;
if (id) if (id)
{ {
@ -272,11 +333,11 @@ dev_enroll (FpDevice *dev)
fpi_print_set_device_stored (print, TRUE); 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 else
{ {
fpi_device_enroll_complete (dev, NULL, error); fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error));
} }
} }
@ -285,6 +346,7 @@ dev_deinit (FpDevice *dev)
{ {
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (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_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable); g_clear_object (&self->cancellable);
g_clear_object (&self->listener); g_clear_object (&self->listener);