| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Virtual driver for "simple" device debugging with storage | ||
| 3 | * | ||
| 4 | * Copyright (C) 2020 Bastien Nocera <hadess@hadess.net> | ||
| 5 | * Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com> | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | /* | ||
| 23 | * This is a virtual driver to debug the non-image based drivers. A small | ||
| 24 | * python script is provided to connect to it via a socket, allowing | ||
| 25 | * prints to registered programmatically. | ||
| 26 | * Using this, it is possible to test libfprint and fprintd. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #define FP_COMPONENT "virtual_device_storage" | ||
| 30 | |||
| 31 | #include "virtual-device-private.h" | ||
| 32 | #include "fpi-log.h" | ||
| 33 | |||
| 34 |
3/4✓ Branch 0 (2→3) taken 121 times.
✓ Branch 1 (2→7) taken 145 times.
✓ Branch 2 (4→5) taken 121 times.
✗ Branch 3 (4→7) not taken.
|
387 | G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, fpi_device_virtual_device_get_type ()) |
| 35 | |||
| 36 | static GPtrArray * get_stored_prints (FpDeviceVirtualDevice * self); | ||
| 37 | |||
| 38 | static void | ||
| 39 | 25 | dev_identify (FpDevice *dev) | |
| 40 | { | ||
| 41 | 25 | g_autoptr(GError) error = NULL; | |
| 42 | 25 | FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); | |
| 43 |
2/4✗ Branch 0 (34→35) not taken.
✓ Branch 1 (34→36) taken 14 times.
✗ Branch 2 (38→39) not taken.
✓ Branch 3 (38→40) taken 11 times.
|
25 | g_autofree char *scan_id = NULL; |
| 44 | |||
| 45 |
2/2✓ Branch 0 (3→4) taken 15 times.
✓ Branch 1 (3→37) taken 10 times.
|
25 | if (!start_scan_command (self, &scan_id, &error)) |
| 46 | return; | ||
| 47 | |||
| 48 |
2/2✓ Branch 0 (4→5) taken 9 times.
✓ Branch 1 (4→25) taken 6 times.
|
15 | if (scan_id) |
| 49 | { | ||
| 50 | 18 | g_autoptr(GPtrArray) stored = get_stored_prints (self); | |
| 51 | 9 | GPtrArray *prints; | |
| 52 | 9 | GVariant *data = NULL; | |
| 53 | 9 | FpPrint *new_scan; | |
| 54 | 9 | FpPrint *match = NULL; | |
| 55 | 9 | guint idx; | |
| 56 | |||
| 57 | 9 | new_scan = fp_print_new (dev); | |
| 58 | 9 | fpi_print_set_type (new_scan, FPI_PRINT_RAW); | |
| 59 | 9 | fpi_print_set_device_stored (new_scan, TRUE); | |
| 60 | 9 | data = g_variant_new_string (scan_id); | |
| 61 | 9 | g_object_set (new_scan, "fpi-data", data, NULL); | |
| 62 | |||
| 63 | 9 | fpi_device_get_identify_data (dev, &prints); | |
| 64 | 9 | g_debug ("Trying to identify print '%s' against a gallery of %u prints", scan_id, prints->len); | |
| 65 | |||
| 66 |
2/2✓ Branch 0 (14→15) taken 4 times.
✓ Branch 1 (14→17) taken 5 times.
|
9 | if (!g_ptr_array_find_with_equal_func (stored, |
| 67 | new_scan, | ||
| 68 | (GEqualFunc) fp_print_equal, | ||
| 69 | NULL)) | ||
| 70 | { | ||
| 71 | 4 | match = FALSE; | |
| 72 |
1/2✓ Branch 0 (15→16) taken 4 times.
✗ Branch 1 (15→20) not taken.
|
4 | g_clear_object (&new_scan); |
| 73 | } | ||
| 74 |
2/2✓ Branch 0 (18→19) taken 3 times.
✓ Branch 1 (18→20) taken 2 times.
|
5 | else if (g_ptr_array_find_with_equal_func (prints, |
| 75 | new_scan, | ||
| 76 | (GEqualFunc) fp_print_equal, | ||
| 77 | &idx)) | ||
| 78 | { | ||
| 79 | 3 | match = g_ptr_array_index (prints, idx); | |
| 80 | } | ||
| 81 | |||
| 82 |
2/2✓ Branch 0 (20→21) taken 8 times.
✓ Branch 1 (20→22) taken 1 times.
|
9 | if (!self->match_reported) |
| 83 | { | ||
| 84 | 8 | self->match_reported = TRUE; | |
| 85 | 8 | fpi_device_identify_report (dev, | |
| 86 | match, | ||
| 87 | new_scan, | ||
| 88 | NULL); | ||
| 89 | } | ||
| 90 | } | ||
| 91 |
3/4✓ Branch 0 (25→26) taken 6 times.
✗ Branch 1 (25→29) not taken.
✓ Branch 2 (27→28) taken 1 times.
✓ Branch 3 (27→29) taken 5 times.
|
6 | else if (error && error->domain == FP_DEVICE_RETRY) |
| 92 | { | ||
| 93 | 1 | fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error)); | |
| 94 | } | ||
| 95 | |||
| 96 | 15 | fpi_device_report_finger_status_changes (FP_DEVICE (self), | |
| 97 | FP_FINGER_STATUS_NONE, | ||
| 98 | FP_FINGER_STATUS_PRESENT); | ||
| 99 | |||
| 100 |
2/2✓ Branch 0 (31→32) taken 14 times.
✓ Branch 1 (31→37) taken 1 times.
|
15 | if (should_wait_to_sleep (self, scan_id, error)) |
| 101 | return; | ||
| 102 | |||
| 103 | 14 | self->match_reported = FALSE; | |
| 104 | 14 | fpi_device_identify_complete (dev, g_steal_pointer (&error)); | |
| 105 | } | ||
| 106 | |||
| 107 | struct ListData | ||
| 108 | { | ||
| 109 | FpDevice *dev; | ||
| 110 | GPtrArray *res; | ||
| 111 | }; | ||
| 112 | |||
| 113 | static void | ||
| 114 | 17 | dev_list_insert_print (gpointer key, | |
| 115 | gpointer value, | ||
| 116 | gpointer user_data) | ||
| 117 | { | ||
| 118 | 17 | struct ListData *data = user_data; | |
| 119 | 17 | FpPrint *print = fp_print_new (data->dev); | |
| 120 | 17 | GVariant *var = NULL; | |
| 121 | |||
| 122 | 17 | fpi_print_fill_from_user_id (print, key); | |
| 123 | 17 | fpi_print_set_type (print, FPI_PRINT_RAW); | |
| 124 | 17 | var = g_variant_new_string (key); | |
| 125 | 17 | g_object_set (print, "fpi-data", var, NULL); | |
| 126 | 17 | g_object_ref_sink (print); | |
| 127 | |||
| 128 | 17 | g_ptr_array_add (data->res, print); | |
| 129 | 17 | } | |
| 130 | |||
| 131 | static GPtrArray * | ||
| 132 | 16 | get_stored_prints (FpDeviceVirtualDevice *self) | |
| 133 | { | ||
| 134 | 16 | GPtrArray * prints_list; | |
| 135 | 16 | struct ListData data; | |
| 136 | |||
| 137 | 16 | prints_list = g_ptr_array_new_full (g_hash_table_size (self->prints_storage), | |
| 138 | g_object_unref); | ||
| 139 | 16 | data.dev = FP_DEVICE (self); | |
| 140 | 16 | data.res = prints_list; | |
| 141 | |||
| 142 | 16 | g_hash_table_foreach (self->prints_storage, dev_list_insert_print, &data); | |
| 143 | |||
| 144 | 16 | return prints_list; | |
| 145 | } | ||
| 146 | |||
| 147 | static void | ||
| 148 | 16 | dev_list (FpDevice *dev) | |
| 149 | { | ||
| 150 | 16 | g_autoptr(GPtrArray) prints_list = NULL; | |
| 151 | 16 | g_autoptr(GError) error = NULL; | |
| 152 | 16 | FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); | |
| 153 | |||
| 154 |
2/2✓ Branch 0 (3→4) taken 8 times.
✓ Branch 1 (3→12) taken 8 times.
|
16 | if (!process_cmds (vdev, FALSE, NULL, &error)) |
| 155 | return; | ||
| 156 | |||
| 157 |
2/2✓ Branch 0 (4→5) taken 1 times.
✓ Branch 1 (4→6) taken 7 times.
|
8 | if (error) |
| 158 | { | ||
| 159 | 1 | fpi_device_list_complete (dev, NULL, g_steal_pointer (&error)); | |
| 160 | 1 | return; | |
| 161 | } | ||
| 162 | |||
| 163 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 7 times.
|
7 | fpi_device_list_complete (dev, get_stored_prints (vdev), NULL); |
| 164 | } | ||
| 165 | |||
| 166 | static void | ||
| 167 | 40 | dev_clear_storage (FpDevice *dev) | |
| 168 | { | ||
| 169 | 40 | g_autoptr(GPtrArray) prints_list = NULL; | |
| 170 | 40 | g_autoptr(GError) error = NULL; | |
| 171 | 40 | FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); | |
| 172 | |||
| 173 |
1/2✓ Branch 0 (3→4) taken 40 times.
✗ Branch 1 (3→12) not taken.
|
40 | if (!process_cmds (vdev, FALSE, NULL, &error)) |
| 174 | return; | ||
| 175 | |||
| 176 |
2/2✓ Branch 0 (4→5) taken 1 times.
✓ Branch 1 (4→6) taken 39 times.
|
40 | if (error) |
| 177 | { | ||
| 178 | 1 | fpi_device_clear_storage_complete (dev, g_steal_pointer (&error)); | |
| 179 | 1 | return; | |
| 180 | } | ||
| 181 | |||
| 182 | 39 | g_hash_table_remove_all (vdev->prints_storage); | |
| 183 | |||
| 184 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 39 times.
|
39 | fpi_device_clear_storage_complete (dev, NULL); |
| 185 | } | ||
| 186 | |||
| 187 | static void | ||
| 188 | 10 | dev_delete (FpDevice *dev) | |
| 189 | { | ||
| 190 | 10 | g_autoptr(GVariant) data = NULL; | |
| 191 |
2/4✓ Branch 0 (22→23) taken 4 times.
✗ Branch 1 (22→24) not taken.
✗ Branch 2 (28→29) not taken.
✓ Branch 3 (28→30) taken 6 times.
|
10 | g_autoptr(GError) error = NULL; |
| 192 | 10 | FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); | |
| 193 | 10 | FpPrint *print = NULL; | |
| 194 | 10 | const char *id = NULL; | |
| 195 | |||
| 196 |
2/2✓ Branch 0 (3→4) taken 5 times.
✓ Branch 1 (3→26) taken 5 times.
|
10 | if (!process_cmds (vdev, FALSE, NULL, &error)) |
| 197 | return; | ||
| 198 | |||
| 199 |
2/2✓ Branch 0 (4→5) taken 1 times.
✓ Branch 1 (4→6) taken 4 times.
|
5 | if (error) |
| 200 | { | ||
| 201 | 1 | fpi_device_delete_complete (dev, g_steal_pointer (&error)); | |
| 202 | 1 | return; | |
| 203 | } | ||
| 204 | |||
| 205 | 4 | fpi_device_get_delete_data (dev, &print); | |
| 206 | |||
| 207 | 4 | g_object_get (print, "fpi-data", &data, NULL); | |
| 208 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→12) taken 4 times.
|
4 | if (data == NULL) |
| 209 | { | ||
| 210 | ✗ | fpi_device_delete_complete (dev, | |
| 211 | fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); | ||
| 212 | ✗ | return; | |
| 213 | } | ||
| 214 | |||
| 215 | 4 | id = g_variant_get_string (data, NULL); | |
| 216 | |||
| 217 | 4 | fp_dbg ("Deleting print %s for user %s", | |
| 218 | id, | ||
| 219 | fp_print_get_username (print)); | ||
| 220 | |||
| 221 |
2/2✓ Branch 0 (16→17) taken 2 times.
✓ Branch 1 (16→18) taken 2 times.
|
4 | if (g_hash_table_remove (vdev->prints_storage, id)) |
| 222 | 2 | fpi_device_delete_complete (dev, NULL); | |
| 223 | else | ||
| 224 | 2 | fpi_device_delete_complete (dev, | |
| 225 | fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); | ||
| 226 | } | ||
| 227 | |||
| 228 | static void | ||
| 229 | 42 | dev_probe (FpDevice *dev) | |
| 230 | { | ||
| 231 | /* Disable features listed in driver_data */ | ||
| 232 | 42 | fpi_device_update_features (dev, fpi_device_get_driver_data (dev), 0); | |
| 233 | |||
| 234 | 42 | fpi_device_probe_complete (dev, NULL, NULL, NULL); | |
| 235 | 42 | } | |
| 236 | |||
| 237 | static void | ||
| 238 | 42 | fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self) | |
| 239 | { | ||
| 240 | 42 | FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (self); | |
| 241 | |||
| 242 | 42 | vdev->prints_storage = g_hash_table_new_full (g_str_hash, | |
| 243 | g_str_equal, | ||
| 244 | g_free, | ||
| 245 | NULL); | ||
| 246 | 42 | } | |
| 247 | |||
| 248 | static void | ||
| 249 | 38 | fpi_device_virtual_device_storage_finalize (GObject *object) | |
| 250 | { | ||
| 251 | 38 | FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (object); | |
| 252 | |||
| 253 | 38 | G_DEBUG_HERE (); | |
| 254 |
1/2✓ Branch 0 (4→5) taken 38 times.
✗ Branch 1 (4→6) not taken.
|
38 | g_clear_pointer (&vdev->prints_storage, g_hash_table_destroy); |
| 255 | 38 | G_OBJECT_CLASS (fpi_device_virtual_device_storage_parent_class)->finalize (object); | |
| 256 | 38 | } | |
| 257 | |||
| 258 | static const FpIdEntry driver_ids[] = { | ||
| 259 | { .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE", .driver_data = 0 }, | ||
| 260 | { .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE_NO_LIST", .driver_data = FP_DEVICE_FEATURE_STORAGE_LIST }, | ||
| 261 | { .virtual_envvar = NULL } | ||
| 262 | }; | ||
| 263 | |||
| 264 | static void | ||
| 265 | 121 | fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass *klass) | |
| 266 | { | ||
| 267 | 121 | FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); | |
| 268 | 121 | GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
| 269 | |||
| 270 | 121 | object_class->finalize = fpi_device_virtual_device_storage_finalize; | |
| 271 | |||
| 272 | 121 | dev_class->id = FP_COMPONENT; | |
| 273 | 121 | dev_class->full_name = "Virtual device with storage and identification for debugging"; | |
| 274 | 121 | dev_class->id_table = driver_ids; | |
| 275 | |||
| 276 | 121 | dev_class->probe = dev_probe; | |
| 277 | 121 | dev_class->identify = dev_identify; | |
| 278 | 121 | dev_class->list = dev_list; | |
| 279 | 121 | dev_class->delete = dev_delete; | |
| 280 | 121 | dev_class->clear_storage = dev_clear_storage; | |
| 281 | |||
| 282 | 121 | fpi_device_class_auto_initialize_features (dev_class); | |
| 283 | 121 | dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK; | |
| 284 | 121 | } | |
| 285 |