GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/aes3k.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 98 110 89.1%
Functions: 15 15 100.0%
Branches: 18 31 58.1%

Line Branch Exec Source
1 /*
2 * AuthenTec AES3500/AES4000 common routines
3 *
4 * The AES3500 and AES4000 sensors are press-typed, and could capture
5 * fingerprint images in 128x128 and 96x96 pixels respectively. They
6 * share a same communication interface: a number of frames are
7 * transferred and captured, from which a final image could be
8 * assembled. Each frame has fixed height of 16 pixels.
9 *
10 * As the imaging area is a bit small, only a part of finger could be
11 * captured, the detected minutiae are not so many that the NBIS
12 * matching works not so good. The verification rate is very low at the
13 * moment.
14 *
15 * This work is derived from Daniel Drake's AES4000 driver.
16 *
17 * Copyright (C) 2013 Juvenn Woo <machese@gmail.com>
18 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
19 *
20 * This library is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU Lesser General Public License as
22 * published by the Free Software Foundation; either version 2.1 of the
23 * License, or (at your option) any later version.
24 *
25 * This library is distributed in the hope that it will be useful, but
26 * WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 * 02110-1301 USA
34 *
35 */
36
37 #define FP_COMPONENT "aes3k"
38
39 #include "drivers_api.h"
40 #include "aeslib.h"
41 #include "aes3k.h"
42
43 typedef struct
44 {
45 /* This is used both as a flag that we are in a capture operation
46 * and for cancellation.
47 */
48 GCancellable *img_capture_cancel;
49 } FpiDeviceAes3kPrivate;
50
51 #define CTRL_TIMEOUT 1000
52 #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
53 #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
54
55 static void do_capture (FpImageDevice *dev);
56
57
3/5
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 234 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 117 times.
✗ Branch 4 not taken.
948 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAes3k, fpi_device_aes3k, FP_TYPE_IMAGE_DEVICE);
58
59 static void
60 8 aes3k_assemble_image (unsigned char *input, size_t width, size_t height,
61 unsigned char *output)
62 {
63 8 size_t row, column;
64
65
2/2
✓ Branch 0 taken 1024 times.
✓ Branch 1 taken 8 times.
1032 for (column = 0; column < width; column++)
66 {
67
2/2
✓ Branch 0 taken 8192 times.
✓ Branch 1 taken 1024 times.
9216 for (row = 0; row < height; row += 2)
68 {
69 8192 output[width * row + column] = (*input & 0x0f) * 17;
70 8192 output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
71 8192 input++;
72 }
73 }
74 8 }
75
76 static void
77 1 img_cb (FpiUsbTransfer *transfer, FpDevice *device,
78 gpointer user_data, GError *error)
79 {
80 1 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
81 1 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (device);
82 1 FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
83
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
84 1 unsigned char *ptr = transfer->buffer;
85 1 FpImage *tmp;
86 1 FpImage *img;
87 1 int i;
88
89 /* Image capture operation is finished (error/completed) */
90
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_clear_object (&priv->img_capture_cancel);
91
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error)
93 {
94 if (g_error_matches (error,
95 G_IO_ERROR,
96 G_IO_ERROR_CANCELLED))
97 {
98 /* Cancellation implies we are deactivating. */
99 g_error_free (error);
100 fpi_image_device_deactivate_complete (dev, NULL);
101 return;
102 }
103
104 fpi_image_device_session_error (dev, error);
105 return;
106 }
107
108 1 fpi_image_device_report_finger_status (dev, TRUE);
109
110 1 tmp = fp_image_new (cls->frame_width, cls->frame_width);
111 1 tmp->width = cls->frame_width;
112 1 tmp->height = cls->frame_width;
113 1 tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
114
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 for (i = 0; i < cls->frame_number; i++)
115 {
116 8 fp_dbg ("frame header byte %02x", *ptr);
117 8 ptr++;
118 8 aes3k_assemble_image (ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT));
119 8 ptr += cls->frame_size;
120 }
121
122 /* FIXME: this is an ugly hack to make the image big enough for NBIS
123 * to process reliably */
124 1 img = fpi_image_resize (tmp, cls->enlarge_factor, cls->enlarge_factor);
125 1 g_object_unref (tmp);
126 1 fpi_image_device_image_captured (dev, img);
127
128 /* FIXME: rather than assuming finger has gone, we should poll regs until
129 * it really has. */
130 1 fpi_image_device_report_finger_status (dev, FALSE);
131
132 /* Note: The transfer is re-started when we switch to the AWAIT_FINGER_ON state. */
133 }
134
135 static void
136 1 do_capture (FpImageDevice *dev)
137 {
138 2 g_autoptr(FpiUsbTransfer) img_trf = NULL;
139 1 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
140 1 FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
141 1 FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
142
143 1 img_trf = fpi_usb_transfer_new (FP_DEVICE (dev));
144 1 fpi_usb_transfer_fill_bulk (img_trf, EP_IN, cls->data_buflen);
145 1 img_trf->short_is_error = TRUE;
146 1 fpi_usb_transfer_submit (g_steal_pointer (&img_trf), 0,
147 priv->img_capture_cancel,
148 img_cb, NULL);
149 1 }
150
151 static void
152 1 capture_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
153 {
154 1 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
155 1 FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
156
157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result)
158 {
159 g_clear_object (&priv->img_capture_cancel);
160 fpi_image_device_session_error (dev, result);
161 return;
162 }
163
164 /* FIXME: we never cancel a pending capture. So we are likely leaving the
165 * hardware in a bad state should we abort the capture operation and the
166 * user does not touch the device.
167 * But, we don't know how we might cancel, so just leave it as is. */
168 1 do_capture (dev);
169 }
170
171 static void
172 1 do_capture_start (FpImageDevice *dev)
173 {
174 1 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
175 1 FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
176
177 1 aes_write_regv (dev, cls->capture_reqs, cls->capture_reqs_len, capture_reqs_cb, NULL);
178 1 }
179
180 static void
181 1 init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
182 {
183 1 fpi_image_device_activate_complete (dev, result);
184 1 }
185
186 static void
187 1 aes3k_dev_activate (FpImageDevice *dev)
188 {
189 1 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
190 1 FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
191
192 1 aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
193 1 }
194
195 static void
196 1 aes3k_dev_deactivate (FpImageDevice *dev)
197 {
198 1 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
199 1 FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
200
201 /* If a capture is running, then deactivation finishes from the cancellation handler */
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (priv->img_capture_cancel)
203 g_cancellable_cancel (priv->img_capture_cancel);
204 else
205 1 fpi_image_device_deactivate_complete (dev, NULL);
206 1 }
207
208 static void
209 8 aes3k_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
210 {
211 8 FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
212 8 FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
213
214
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
215 {
216
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_assert (!priv->img_capture_cancel);
217 1 priv->img_capture_cancel = g_cancellable_new ();
218
219 1 do_capture_start (dev);
220 }
221 8 }
222
223 static void
224 1 fpi_device_aes3k_init (FpiDeviceAes3k *self)
225 {
226 1 }
227
228 static void
229 1 aes3k_dev_init (FpImageDevice *dev)
230 {
231 1 GError *error = NULL;
232
233
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error))
234 {
235 fpi_image_device_open_complete (dev, error);
236 return;
237 }
238
239 1 fpi_image_device_open_complete (dev, NULL);
240 }
241
242 static void
243 1 aes3k_dev_deinit (FpImageDevice *dev)
244 {
245 1 GError *error = NULL;
246
247 1 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
248 0, 0, &error);
249 1 fpi_image_device_close_complete (dev, error);
250 1 }
251
252
253 static void
254 117 fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass)
255 {
256 117 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
257 117 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
258
259 117 dev_class->type = FP_DEVICE_TYPE_USB;
260 117 dev_class->scan_type = FP_SCAN_TYPE_PRESS;
261
262 117 img_class->img_open = aes3k_dev_init;
263 117 img_class->img_close = aes3k_dev_deinit;
264 117 img_class->activate = aes3k_dev_activate;
265 117 img_class->change_state = aes3k_dev_change_state;
266 117 img_class->deactivate = aes3k_dev_deactivate;
267
268 /* Extremely low due to low image quality. */
269 117 img_class->bz3_threshold = 9;
270
271 /* Everything else is set by the subclasses. */
272 }
273