diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h index efb1cdf..75ae658 100644 --- a/libfprint/drivers/virtual-device-private.h +++ b/libfprint/drivers/virtual-device-private.h @@ -83,6 +83,7 @@ struct _FpDeviceVirtualDevice gboolean match_reported; gboolean supports_cancellation; gboolean injected_synthetic_cmd; + gboolean ignore_wait; }; /* Not really final here, but we can do this to share the FpDeviceVirtualDevice diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 9db8efe..a4c9425 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -122,10 +122,19 @@ static void dev_list (FpDevice *dev) { g_autoptr(GPtrArray) prints_list = NULL; + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); struct ListData data; - process_cmds (vdev, FALSE, NULL); + process_cmds (vdev, FALSE, &error); + if (should_wait_for_command (vdev, error)) + return; + + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_list_complete (dev, NULL, g_steal_pointer (&error)); + return; + } prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), NULL); data.dev = dev; @@ -140,11 +149,20 @@ static void dev_delete (FpDevice *dev) { g_autoptr(GVariant) data = NULL; + g_autoptr(GError) error = NULL; FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); FpPrint *print = NULL; const char *id = NULL; - process_cmds (vdev, FALSE, NULL); + process_cmds (vdev, FALSE, &error); + if (should_wait_for_command (vdev, error)) + return; + + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_delete_complete (dev, g_steal_pointer (&error)); + return; + } fpi_device_get_delete_data (dev, &print); diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 769b91e..b32610c 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -70,6 +70,14 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self) FP_DEVICE_GET_CLASS (self)->identify (dev); break; + case FPI_DEVICE_ACTION_LIST: + FP_DEVICE_GET_CLASS (self)->list (dev); + break; + + case FPI_DEVICE_ACTION_DELETE: + FP_DEVICE_GET_CLASS (self)->delete (dev); + break; + default: break; } @@ -141,6 +149,14 @@ process_cmds (FpDeviceVirtualDevice * self, return NULL; } + else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX)) + { + g_propagate_error (error, + fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); + + g_ptr_array_remove_index (self->pending_commands, 0); + return NULL; + } /* If we are not scanning, then we have to stop here. */ if (!scan) @@ -153,14 +169,6 @@ process_cmds (FpDeviceVirtualDevice * self, g_ptr_array_remove_index (self->pending_commands, 0); return res; } - else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX)) - { - g_propagate_error (error, - fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); - - g_ptr_array_remove_index (self->pending_commands, 0); - return NULL; - } else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX)) { g_propagate_error (error, @@ -338,6 +346,20 @@ wait_for_command_timeout (gpointer data) GError *error = NULL; self->wait_command_id = 0; + + switch (fpi_device_get_current_action (FP_DEVICE (self))) + { + case FPI_DEVICE_ACTION_LIST: + case FPI_DEVICE_ACTION_DELETE: + self->ignore_wait = TRUE; + maybe_continue_current_action (self); + self->ignore_wait = FALSE; + return FALSE; + + default: + break; + } + 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); @@ -351,6 +373,9 @@ should_wait_for_command (FpDeviceVirtualDevice *self, if (!error && self->sleep_timeout_id) return TRUE; + if (self->ignore_wait) + return FALSE; + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) return FALSE; diff --git a/tests/virtual-device.py b/tests/virtual-device.py index e115656..bce202f 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -586,6 +586,47 @@ class VirtualDeviceStorage(VirtualDevice): self.dev.delete_print_sync(p) self.assertFalse(self.dev.list_prints_sync()) + def test_delete_error(self): + deleted_res = None + def on_deleted(dev, res): + nonlocal deleted_res + try: + deleted_res = dev.delete_print_finish(res) + except GLib.Error as e: + deleted_res = e + + self.send_command('SLEEP', 100) + self.send_error(FPrint.DeviceError.DATA_NOT_FOUND) + self.dev.delete_print(FPrint.Print.new(self.dev), callback=on_deleted) + self.wait_timeout(2) + self.assertIsNone(deleted_res) + + while not deleted_res: + ctx.iteration(True) + + self.assertEqual(deleted_res.code, int(FPrint.DeviceError.DATA_NOT_FOUND)) + + def test_list_error(self): + list_res = None + + def on_listed(dev, res): + nonlocal list_res + try: + list_res = dev.list_prints_finish(res) + except GLib.Error as e: + list_res = e + + self.send_command('SLEEP', 100) + self.send_error(FPrint.DeviceError.BUSY) + self.dev.list_prints(callback=on_listed) + self.wait_timeout(2) + self.assertIsNone(list_res) + + while not list_res: + ctx.iteration(True) + + self.assertEqual(list_res.code, int(FPrint.DeviceError.BUSY)) + def test_list_delete_missing(self): p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB) self.send_command('REMOVE', 'testprint')