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 |
4/5✓ Branch 0 taken 120 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
|
768 | 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 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
25 | g_autofree char *scan_id = NULL; |
44 | |||
45 |
2/2✓ Branch 1 taken 15 times.
✓ Branch 2 taken 10 times.
|
25 | if (!start_scan_command (self, &scan_id, &error)) |
46 | return; | ||
47 | |||
48 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 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 1 taken 4 times.
✓ Branch 2 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 taken 4 times.
✗ Branch 1 not taken.
|
4 | g_clear_object (&new_scan); |
73 | } | ||
74 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 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 taken 8 times.
✓ Branch 1 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 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 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 1 taken 14 times.
✓ Branch 2 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 1 taken 8 times.
✓ Branch 2 taken 8 times.
|
16 | if (!process_cmds (vdev, FALSE, NULL, &error)) |
155 | return; | ||
156 | |||
157 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 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 2 not taken.
✓ Branch 3 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 1 taken 40 times.
✗ Branch 2 not taken.
|
40 | if (!process_cmds (vdev, FALSE, NULL, &error)) |
174 | return; | ||
175 | |||
176 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 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 1 not taken.
✓ Branch 2 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 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 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 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | if (!process_cmds (vdev, FALSE, NULL, &error)) |
197 | return; | ||
198 | |||
199 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 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 not taken.
✓ Branch 1 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 1 taken 2 times.
✓ Branch 2 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 taken 38 times.
✗ Branch 1 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 | 120 | fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass *klass) | |
266 | { | ||
267 | 120 | FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); | |
268 | 120 | GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
269 | |||
270 | 120 | object_class->finalize = fpi_device_virtual_device_storage_finalize; | |
271 | |||
272 | 120 | dev_class->id = FP_COMPONENT; | |
273 | 120 | dev_class->full_name = "Virtual device with storage and identification for debugging"; | |
274 | 120 | dev_class->id_table = driver_ids; | |
275 | |||
276 | 120 | dev_class->probe = dev_probe; | |
277 | 120 | dev_class->identify = dev_identify; | |
278 | 120 | dev_class->list = dev_list; | |
279 | 120 | dev_class->delete = dev_delete; | |
280 | 120 | dev_class->clear_storage = dev_clear_storage; | |
281 | |||
282 | 120 | fpi_device_class_auto_initialize_features (dev_class); | |
283 | 120 | dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK; | |
284 | 120 | } | |
285 |