From a1e46de462757e3c900d3d959b4e53a0d2410e49 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 30 Dec 2018 16:35:33 +0100 Subject: [PATCH 01/50] lib: Fix examples not working Remove the sanity check added in commit b1afa9d, having a poll setup isn't necessary to use timeouts, as long as only sync functions are used. Closes: #139 --- libfprint/fpi-poll.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libfprint/fpi-poll.c b/libfprint/fpi-poll.c index af0c4bee..0691cc3b 100644 --- a/libfprint/fpi-poll.c +++ b/libfprint/fpi-poll.c @@ -91,8 +91,6 @@ struct fpi_timeout { char *name; }; -static gboolean fpi_poll_is_setup(void); - static int timeout_sort_fn(gconstpointer _a, gconstpointer _b) { fpi_timeout *a = (fpi_timeout *) _a; @@ -167,7 +165,6 @@ fpi_timeout *fpi_timeout_add(unsigned int msec, int r; g_return_val_if_fail (dev != NULL, NULL); - g_return_val_if_fail (fpi_poll_is_setup(), NULL); fp_dbg("in %dms", msec); @@ -487,12 +484,6 @@ void fpi_poll_exit(void) libusb_set_pollfd_notifiers(fpi_usb_ctx, NULL, NULL, NULL); } -static gboolean -fpi_poll_is_setup(void) -{ - return (fd_added_cb != NULL && fd_removed_cb != NULL); -} - void fpi_timeout_cancel_all_for_dev(struct fp_dev *dev) { From ea6820ed5138f7b0d42c14ae86319c76da8c3552 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 21 Jan 2019 15:26:56 +0100 Subject: [PATCH 02/50] lib: Better docs for no devices case in fp_discover_devs() Document the behaviour of fp_discover_devs() when there are no supported devices, rather than errors listing the devices. --- libfprint/fpi-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libfprint/fpi-core.c b/libfprint/fpi-core.c index 2b5d3c6f..7a93a1b2 100644 --- a/libfprint/fpi-core.c +++ b/libfprint/fpi-core.c @@ -270,10 +270,12 @@ static struct fp_dscv_dev *discover_dev(libusb_device *udev) * fp_discover_devs: * * Scans the system and returns a list of discovered devices. This is your - * entry point into finding a fingerprint reader to operate. + * entry point into finding a fingerprint reader to operate. Note that %NULL + * is only returned on error. When there are no supported readers available, + * an empty list is returned instead. * - * Returns: a nul-terminated list of discovered devices. Must be freed with - * fp_dscv_devs_free() after use. + * Returns: a nul-terminated list of discovered devices or %NULL on error. + * Must be freed with fp_dscv_devs_free() after use. */ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void) { From b9af7952a450b39d8bb042c19821a7d07b5027db Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 21 Jan 2019 15:28:33 +0100 Subject: [PATCH 03/50] demo: Fix crash when there are no supported devices Handle the empty list output from fp_discover_devs() when there are no supported devices. Closes: #146 --- demo/gtk-libfprint-test.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/demo/gtk-libfprint-test.c b/demo/gtk-libfprint-test.c index b23e38dd..d0dd0c1e 100644 --- a/demo/gtk-libfprint-test.c +++ b/demo/gtk-libfprint-test.c @@ -473,8 +473,17 @@ libfprint_demo_window_init (LibfprintDemoWindow *window) setup_pollfds (); discovered_devs = fp_discover_devs(); - if (!discovered_devs) + if (!discovered_devs) { + libfprint_demo_set_mode (window, ERROR_MODE); return; + } + + /* Empty list? */ + if (discovered_devs[0] == NULL) { + fp_dscv_devs_free (discovered_devs); + libfprint_demo_set_mode (window, EMPTY_MODE); + return; + } if (!fp_driver_supports_imaging(fp_dscv_dev_get_driver(discovered_devs[0]))) { libfprint_demo_set_mode (window, NOIMAGING_MODE); From 07143803604c32f97f9036a9d2c9f9360851d8a5 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 21 Jan 2019 15:37:04 +0100 Subject: [PATCH 04/50] build: Disable GTK+ demo app by default Given that it's not usable yet. --- meson_options.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson_options.txt b/meson_options.txt index 3e63304b..f40ebc31 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -17,7 +17,7 @@ option('x11-examples', option('gtk-examples', description: 'Whether to build GTK+ example applications', type: 'boolean', - value: true) + value: false) option('doc', description: 'Whether to build the API documentation', type: 'boolean', From ca26e85fd4f42162657aee5a065e93a4cab2b052 Mon Sep 17 00:00:00 2001 From: Seong-Joong Kim Date: Wed, 20 Feb 2019 14:17:27 +0900 Subject: [PATCH 05/50] uru4000: Fix integer overflow in imaging_run_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘img->key_number’ variable is originally from the device through bulk endpoint of USB. The variable is immediately assigned to ‘buf[0]’ for sending to control endpoint of the device. Here, integer overflow may occur when the ‘img->key_number’ attempts to assign a value that is outside of type range of ‘char’ to the ‘buf[0]’ --- libfprint/drivers/uru4000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index 7830c562..6a3722b8 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -710,7 +710,7 @@ static void imaging_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data uint32_t key; uint8_t flags, num_lines; int i, r, to, dev2; - char buf[5]; + unsigned char buf[5]; switch (fpi_ssm_get_cur_state(ssm)) { case IMAGING_CAPTURE: From b121fa2cc95ce8f95b7b78dd40c0971ed963c255 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 21 Mar 2019 15:37:01 +0100 Subject: [PATCH 06/50] uru4000: Work-around SELinux AVC warnings when driver starts Work-around SELinux AVC warnings caused by p11-kit (which is an NSS dependency) trying to load the root user's p11-kit configs. We disable this feature using the P11_KIT_NO_USER_CONFIG envvar. See https://bugzilla.redhat.com/show_bug.cgi?id=1688583 --- libfprint/drivers/uru4000.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index 6a3722b8..7e54addf 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -1340,6 +1340,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) goto out; } + /* Disable loading p11-kit's user configuration */ + g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE); + /* Initialise NSS early */ rv = NSS_NoDB_Init("."); if (rv != SECSuccess) { From 6f4c3789333e4bc56065b1b24b0fc5c16e97805c Mon Sep 17 00:00:00 2001 From: Diego Date: Sun, 5 May 2019 15:26:54 +0000 Subject: [PATCH 07/50] vfs5011: Add support for Lenovo Preferred Pro Keyboard (KUF1256) Add support for the Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256 by declaring support for USB ID 138a:0015. Closes: #125 --- libfprint/drivers/vfs5011.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index 2fcb822a..e1858332 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -879,6 +879,7 @@ static void dev_deactivate(struct fp_img_dev *dev) static const struct usb_id id_table[] = { { .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ }, { .vendor = 0x138a, .product = 0x0011 /* vfs5011 */ }, + { .vendor = 0x138a, .product = 0x0015 /* Validity device from Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256 */ }, { .vendor = 0x138a, .product = 0x0017 /* Validity device from Lenovo T440 laptops */ }, { .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ }, { 0, 0, 0, }, From 6764ec79ae00dc49d1597f007cbc44cc364b1ee5 Mon Sep 17 00:00:00 2001 From: Peter Maatman Date: Mon, 15 Apr 2019 20:31:54 +0200 Subject: [PATCH 08/50] etes603: Prevent hang during enroll process This commit fixes a hang in gnome-settings when trying to enroll a finger. The same issue could be seen in the enroll example. Previously the enroll example would hang on "deactivating" because at some point dev->is_active is set to false and m_exit_start is never called. --- libfprint/drivers/etes603.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/etes603.c b/libfprint/drivers/etes603.c index 97b6913b..8f3ec458 100644 --- a/libfprint/drivers/etes603.c +++ b/libfprint/drivers/etes603.c @@ -1430,8 +1430,9 @@ static void dev_deactivate(struct fp_img_dev *idev) /* this can be called even if still activated. */ if (dev->is_active == TRUE) { dev->is_active = FALSE; - m_exit_start(idev); } + + m_exit_start(idev); } static int dev_open(struct fp_img_dev *idev, unsigned long driver_data) From 6ba9439bbb994753cd4a11583bce0322c884090d Mon Sep 17 00:00:00 2001 From: Peter Maatman Date: Wed, 1 May 2019 16:04:27 +0200 Subject: [PATCH 09/50] examples: Remove sleep call in enroll examples The call to sleep(1) inside of the enrollment loop caused a crash on at least the etes603 driver. Because in fp_enroll_finger_img the function enters an event handling loop. This loop needs to start before the next libusb event timeout. Which would not happen in the etes603 driver because the timeout there was set to 1 second as well. --- examples/enroll.c | 3 +-- examples/verify_live.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/enroll.c b/examples/enroll.c index 4eea39ad..2c42a9e4 100644 --- a/examples/enroll.c +++ b/examples/enroll.c @@ -45,8 +45,7 @@ struct fp_print_data *enroll(struct fp_dev *dev) { do { struct fp_img *img = NULL; - - sleep(1); + printf("\nScan your finger now.\n"); r = fp_enroll_finger_img(dev, &enrolled_print, &img); diff --git a/examples/verify_live.c b/examples/verify_live.c index 82ec2abc..4c02ff2f 100644 --- a/examples/verify_live.c +++ b/examples/verify_live.c @@ -43,7 +43,6 @@ struct fp_print_data *enroll(struct fp_dev *dev) { "complete the process.\n", fp_dev_get_nr_enroll_stages(dev)); do { - sleep(1); printf("\nScan your finger now.\n"); r = fp_enroll_finger(dev, &enrolled_print); if (r < 0) { From 66461e4c81f6b07e9050830291b380b14b83fdb1 Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:27:14 -0400 Subject: [PATCH 10/50] elan: Add quirk definition for device 04f3:0c42 --- libfprint/drivers/elan.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libfprint/drivers/elan.h b/libfprint/drivers/elan.h index 853f31de..63c811f4 100644 --- a/libfprint/drivers/elan.h +++ b/libfprint/drivers/elan.h @@ -31,6 +31,7 @@ /* devices with quirks */ #define ELAN_0907 (1 << 0) #define ELAN_0C03 (1 << 1) +#define ELAN_0C42 (1 << 2) /* devices which don't require frame rotation before assembling */ #define ELAN_NOT_ROTATED ELAN_0C03 From b20a74a22cefb4809f04e44958771c6d3509e49a Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:27:56 -0400 Subject: [PATCH 11/50] elan: Work-around sensors returning incorrect dimensions The dimensions some sensors return is the maximum zero-based index rather than the number of pixels. Assuming every sensor has an even number of pixels is safe. --- libfprint/drivers/elan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index ed474b05..3216bf16 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -755,6 +755,14 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat elandev->frame_height = elandev->raw_frame_height = elandev->last_read[0]; } + /* Work-around sensors returning the sizes as zero-based index + * rather than the number of pixels. */ + if ((elandev->frame_width % 2 == 1) && + (elandev->frame_height % 2 == 1)) { + elandev->frame_width++; + elandev->frame_height++; + elandev->raw_frame_height = elandev->frame_height; + } if (elandev->frame_height > ELAN_MAX_FRAME_HEIGHT) elandev->frame_height = ELAN_MAX_FRAME_HEIGHT; fp_dbg("sensor dimensions, WxH: %dx%d", elandev->frame_width, From ce31c1d704b6343cc095e5e57ded0e3c2467caad Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:28:41 -0400 Subject: [PATCH 12/50] elan: Work-around one-byte responses being two-bytes long On the ELAN_0C42 device, one-byte responses are 2 bytes long. Adapt our expected response length. --- libfprint/drivers/elan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 3216bf16..46346be1 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -383,6 +383,12 @@ static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev) return; } + if (elandev->dev_type == ELAN_0C42) { + /* ELAN_0C42 sends an extra byte in one byte responses */ + if (elandev->cmd->response_len == 1) + response_len = 2; + } + if (elandev->cmd->cmd == get_image_cmd.cmd) /* raw data has 2-byte "pixels" and the frame is vertical */ response_len = From 83af40679a77ad7754da2006853ddc5fc4eca4bf Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:29:32 -0400 Subject: [PATCH 13/50] elan: ELAN_0C42 always supports calibration Split off calibration support checks into elan_supports_calibration() --- libfprint/drivers/elan.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 46346be1..12997956 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -627,6 +627,14 @@ enum calibrate_states { CALIBRATE_NUM_STATES, }; +static gboolean elan_supports_calibration(struct elan_dev *elandev) +{ + if (elandev->dev_type == ELAN_0C42) + return TRUE; + + return elandev->fw_ver >= ELAN_MIN_CALIBRATION_FW; +} + static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) { struct fp_img_dev *dev = user_data; @@ -640,7 +648,7 @@ static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da break; case CALIBRATE_SAVE_BACKGROUND: elan_save_background(elandev); - if (elandev->fw_ver < ELAN_MIN_CALIBRATION_FW) { + if (!elan_supports_calibration(elandev)) { fp_dbg("FW does not support calibration"); fpi_ssm_mark_completed(ssm); } else From 2babfa062572b93ad11923ec5aaa343491ac18e7 Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:30:07 -0400 Subject: [PATCH 14/50] elan: Simplify calibration check for ELAN_0C42 Check for the mean calibration being outside of range to know whether we require a recalibration. Continue with the usual checks if the calibration value is within range. --- libfprint/drivers/elan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 12997956..3314d8d5 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -603,6 +603,14 @@ static int elan_need_calibration(struct elan_dev *elandev) g_assert(frame_size != 0); + if (elandev->dev_type == ELAN_0C42) { + if (calib_mean > 5500 || + calib_mean < 2500) { + fp_dbg("Forcing needed recalibration"); + return 1; + } + } + for (int i = 0; i < frame_size; i++) bg_mean += elandev->background[i]; bg_mean /= frame_size; From 3e666130c29db4526d9685e63543d6430a0f535c Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:30:48 -0400 Subject: [PATCH 15/50] elan: Skip more final frames to avoid bulging captures If users put their finger on the sensor between the bulge and "un-bulge" area first and then swipe, the captured image would be bad. Skipping more frames can reduce the impact, so bump ELAN_SKIP_LAST_FRAMES to 2. --- libfprint/drivers/elan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/elan.h b/libfprint/drivers/elan.h index 63c811f4..c574e58b 100644 --- a/libfprint/drivers/elan.h +++ b/libfprint/drivers/elan.h @@ -56,7 +56,7 @@ /* number of frames to drop at the end of capture because frames captured * while the finger is being lifted can be bad */ -#define ELAN_SKIP_LAST_FRAMES 1 +#define ELAN_SKIP_LAST_FRAMES 2 #define ELAN_CMD_LEN 0x2 #define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT) From 8c7ff259af1bb51a9d5bac9b39d8b354e1ba8d82 Mon Sep 17 00:00:00 2001 From: Dave Date: Tue, 9 Apr 2019 02:31:32 -0400 Subject: [PATCH 16/50] elan: Add 04f3:0c42 to the supported devices Now that all the quirks are in place to support it. --- libfprint/drivers/elan.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libfprint/drivers/elan.h b/libfprint/drivers/elan.h index c574e58b..c5f0f191 100644 --- a/libfprint/drivers/elan.h +++ b/libfprint/drivers/elan.h @@ -208,6 +208,7 @@ static const struct usb_id elan_id_table[] = { {.vendor = ELAN_VEND_ID,.product = 0x0c31,.driver_data = ELAN_ALL_DEV}, {.vendor = ELAN_VEND_ID,.product = 0x0c32,.driver_data = ELAN_ALL_DEV}, {.vendor = ELAN_VEND_ID,.product = 0x0c33,.driver_data = ELAN_ALL_DEV}, + {.vendor = ELAN_VEND_ID,.product = 0x0c42,.driver_data = ELAN_0C42}, {0, 0, 0,}, }; From 953c75575b0f014eca64d1446f9850de543f0b5d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Sun, 9 Jun 2019 18:13:41 +0200 Subject: [PATCH 17/50] poll: Remove fpi_timeout_cancel_for_dev The function was committed by accident as part of commit d18e1053 (lib: Add a way to name timeouts). It is not used anywhere and fpi_timeout_cancel_all_for_dev exists, is exported and used and serves the same purpose. --- libfprint/fpi-poll.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/libfprint/fpi-poll.c b/libfprint/fpi-poll.c index 0691cc3b..3f2c898f 100644 --- a/libfprint/fpi-poll.c +++ b/libfprint/fpi-poll.c @@ -207,26 +207,6 @@ void fpi_timeout_cancel(fpi_timeout *timeout) fpi_timeout_free(timeout); } -void -fpi_timeout_cancel_for_dev(struct fp_dev *dev) -{ - GSList *l; - - g_return_if_fail (dev != NULL); - - l = active_timers; - while (l) { - struct fpi_timeout *timeout = l->data; - GSList *current = l; - - l = l->next; - if (timeout->dev == dev) { - fpi_timeout_free (timeout); - active_timers = g_slist_delete_link (active_timers, current); - } - } -} - /* get the expiry time and optionally the timeout structure for the next * timeout. returns 0 if there are no expired timers, or 1 if the * timeval/timeout output parameters were populated. if the returned timeval From 1db2dc3f58c274f2b50013f9651ef0ae83bba405 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 11 Jun 2019 16:42:12 +0200 Subject: [PATCH 18/50] core: Add guards to public API Add appropriate g_return_val_if_fail macros to all public API functions to guard against NULL pointers being passed into libfprint. --- libfprint/fpi-core.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/libfprint/fpi-core.c b/libfprint/fpi-core.c index 7a93a1b2..6009c82d 100644 --- a/libfprint/fpi-core.c +++ b/libfprint/fpi-core.c @@ -346,6 +346,8 @@ API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs) */ API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev) { + g_return_val_if_fail(dev, NULL); + return dev->drv; } @@ -360,6 +362,8 @@ API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev) */ API_EXPORTED uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev) { + g_return_val_if_fail(dev, 0); + return fp_driver_get_driver_id(fp_dscv_dev_get_driver(dev)); } @@ -373,6 +377,8 @@ API_EXPORTED uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev) */ API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev) { + g_return_val_if_fail(dev, 0); + return dev->devtype; } @@ -402,6 +408,9 @@ enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv) API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev, struct fp_print_data *print) { + g_return_val_if_fail(dev, 0); + g_return_val_if_fail(print, 0); + return fpi_print_data_compatible(dev->drv->id, dev->devtype, fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype, print->type); @@ -422,6 +431,9 @@ API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev, API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev, struct fp_dscv_print *print) { + g_return_val_if_fail(dev, 0); + g_return_val_if_fail(print, 0); + return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0, print->driver_id, print->devtype, 0); } @@ -445,6 +457,9 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev * struct fp_dscv_dev *ddev; int i; + g_return_val_if_fail(devs, NULL); + g_return_val_if_fail(print, NULL); + for (i = 0; (ddev = devs[i]); i++) if (fp_dscv_dev_supports_print_data(ddev, print)) return ddev; @@ -470,6 +485,9 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev * struct fp_dscv_dev *ddev; int i; + g_return_val_if_fail(devs, NULL); + g_return_val_if_fail(print, NULL); + for (i = 0; (ddev = devs[i]); i++) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -490,6 +508,8 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev * */ API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev) { + g_return_val_if_fail(dev, NULL); + return dev->drv; } @@ -504,6 +524,8 @@ API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev) */ API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev) { + g_return_val_if_fail(dev, 0); + return dev->nr_enroll_stages; } @@ -517,6 +539,8 @@ API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev) */ API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev) { + g_return_val_if_fail(dev, 0); + return dev->devtype; } @@ -532,6 +556,9 @@ API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev) API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data) { + g_return_val_if_fail(dev, 0); + g_return_val_if_fail(data, 0); + return fpi_print_data_compatible(dev->drv->id, dev->devtype, fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype, data->type); @@ -552,6 +579,9 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev, API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print) { + g_return_val_if_fail(dev, 0); + g_return_val_if_fail(print, 0); + return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0, print->driver_id, print->devtype, 0); } @@ -566,6 +596,8 @@ API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev, */ API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv) { + g_return_val_if_fail(drv, NULL); + return drv->name; } @@ -579,6 +611,8 @@ API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv) */ API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv) { + g_return_val_if_fail(drv, NULL); + return drv->full_name; } @@ -592,6 +626,8 @@ API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv) */ API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv) { + g_return_val_if_fail(drv, 0); + return drv->id; } @@ -605,6 +641,8 @@ API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv) */ API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv) { + g_return_val_if_fail(drv, FP_SCAN_TYPE_PRESS); + return drv->scan_type; } @@ -623,6 +661,8 @@ API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv) */ API_EXPORTED int fp_driver_supports_imaging(struct fp_driver *drv) { + g_return_val_if_fail(drv, 0); + return drv->capture_start != NULL; } @@ -641,6 +681,8 @@ API_EXPORTED int fp_driver_supports_imaging(struct fp_driver *drv) */ API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev) { + g_return_val_if_fail(dev, 0); + return dev->drv->capture_start != NULL; } @@ -656,6 +698,8 @@ API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev) */ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev) { + g_return_val_if_fail(dev, 0); + return dev->drv->identify_start != NULL; } @@ -673,6 +717,8 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev) */ API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev) { + g_return_val_if_fail(dev, -1); + if (!dev->img_dev) { fp_dbg("get image width for non-imaging device"); return -1; @@ -695,6 +741,8 @@ API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev) */ API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev) { + g_return_val_if_fail(dev, -1); + if (!dev->img_dev) { fp_dbg("get image height for non-imaging device"); return -1; From 0a45ed7af68f7d44211844ba7d8f90dd42bf2de0 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 11 Jun 2019 16:48:35 +0200 Subject: [PATCH 19/50] data: Deprecate print storage API The only API user currently seems to be the examples. fprintd has its own storage and that will be a good idea in general. So deprecate the API, we'll need to find a different solution for the examples eventually. --- examples/enroll.c | 3 +++ examples/verify.c | 3 +++ libfprint/fpi-data.c | 23 +++++++++++++++++++---- libfprint/fprint.h | 8 +++++--- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/examples/enroll.c b/examples/enroll.c index 2c42a9e4..0fe10bbc 100644 --- a/examples/enroll.c +++ b/examples/enroll.c @@ -142,7 +142,10 @@ int main(void) if (!data) goto out_close; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" r = fp_print_data_save(data, RIGHT_INDEX); +#pragma GCC diagnostic pop if (r < 0) fprintf(stderr, "Data save failed, code %d\n", r); diff --git a/examples/verify.c b/examples/verify.c index 26566edd..713c39c1 100644 --- a/examples/verify.c +++ b/examples/verify.c @@ -117,7 +117,10 @@ int main(void) printf("Opened device. Loading previously enrolled right index finger " "data...\n"); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" r = fp_print_data_load(dev, RIGHT_INDEX, &data); +#pragma GCC diagnostic pop if (r != 0) { fprintf(stderr, "Failed to load fingerprint, error %d\n", r); fprintf(stderr, "Did you remember to enroll your right index finger " diff --git a/libfprint/fpi-data.c b/libfprint/fpi-data.c index 0ac0f987..f377404b 100644 --- a/libfprint/fpi-data.c +++ b/libfprint/fpi-data.c @@ -56,12 +56,15 @@ struct fpi_print_data_item_fp2 { * * This page documents the various operations you can do with a stored print. * Note that by default, "stored prints" are not actually stored anywhere - * except in RAM. For the simple scenarios, libfprint provides a simple API - * for you to save and load the stored prints referring to a single user in - * their home directory. For more advanced users, libfprint provides APIs for - * you to convert print data to a byte string, and to reconstruct stored prints + * except in RAM. Storage needs to be handled by the API user by using the + * fp_print_data_get_data() and fp_print_data_from_data(). This API allows + * to convert print data into byte strings, and to reconstruct stored prints * from such data at a later point. You are welcome to store these byte strings * in any fashion that suits you. + * + * The provided API to store data on disk is deprecated and should not be + * used anymore. This API stored the prints in the current user's home + * directory. */ /* @@ -366,6 +369,10 @@ static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger) * directory beneath the current user's home directory. * * Returns: 0 on success, non-zero on error. + * + * Deprecated: Data storage should be handled outside of libfprint. + * See stored prints description + * for more information. */ API_EXPORTED int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger) @@ -478,6 +485,10 @@ static int load_from_file(char *path, struct fp_print_data **data) * obscure error conditions (e.g. corruption). * * Returns: 0 on success, non-zero on error + * + * Deprecated: Data storage should be handled outside of libfprint. + * See stored prints description + * for more information. */ API_EXPORTED int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger, struct fp_print_data **data) @@ -513,6 +524,10 @@ API_EXPORTED int fp_print_data_load(struct fp_dev *dev, * Removes a stored print from disk previously saved with fp_print_data_save(). * * Returns: 0 on success, negative on error + * + * Deprecated: Data storage should be handled outside of libfprint. + * See stored prints description + * for more information. */ API_EXPORTED int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger) diff --git a/libfprint/fprint.h b/libfprint/fprint.h index b9b09092..4b68e4aa 100644 --- a/libfprint/fprint.h +++ b/libfprint/fprint.h @@ -275,11 +275,13 @@ int fp_identify_finger(struct fp_dev *dev, /* Data handling */ int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger, - struct fp_print_data **data); + struct fp_print_data **data) LIBFPRINT_DEPRECATED; int fp_print_data_from_dscv_print(struct fp_dscv_print *print, struct fp_print_data **data) LIBFPRINT_DEPRECATED; -int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger); -int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger); +int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger) + LIBFPRINT_DEPRECATED; +int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger) + LIBFPRINT_DEPRECATED; void fp_print_data_free(struct fp_print_data *data); size_t fp_print_data_get_data(struct fp_print_data *data, unsigned char **ret); struct fp_print_data *fp_print_data_from_data(unsigned char *buf, From 3b757ee738d4d078ef4ae45be1442e39e0585198 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 12 Jun 2019 11:58:58 +0200 Subject: [PATCH 20/50] build: Fix source files of upekts and upketc drivers The upekts driver needs upek_proto.c while the upektc driver does not. Move the corresponding source file entries so that both drivers compile standalone. --- libfprint/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index abd00054..2b452da4 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -76,10 +76,10 @@ drivers_sources = [] drivers_cflags = [] foreach driver: drivers if driver == 'upekts' - drivers_sources += [ 'drivers/upekts.c' ] + drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ] endif if driver == 'upektc' - drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ] + drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ] endif if driver == 'upeksonly' drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ] From 7dce8dbfaa84651e17e08e5bba3c743c96f14fee Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 12 Jun 2019 12:09:39 +0200 Subject: [PATCH 21/50] build: Remove header files from drivers_sources It is not necessary to list all the headers in the drivers_sources list, so remove them. --- libfprint/meson.build | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index 2b452da4..2db47498 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -76,13 +76,13 @@ drivers_sources = [] drivers_cflags = [] foreach driver: drivers if driver == 'upekts' - drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ] + drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c' ] endif if driver == 'upektc' - drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ] + drivers_sources += [ 'drivers/upektc.c' ] endif if driver == 'upeksonly' - drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ] + drivers_sources += [ 'drivers/upeksonly.c' ] endif if driver == 'uru4000' drivers_sources += [ 'drivers/uru4000.c' ] @@ -92,20 +92,20 @@ foreach driver: drivers aeslib = true endif if driver == 'aes1660' - drivers_sources += [ 'drivers/aes1660.c', 'drivers/aes1660.h' ] + drivers_sources += [ 'drivers/aes1660.c' ] aeslib = true aesx660 = true endif if driver == 'aes2501' - drivers_sources += [ 'drivers/aes2501.c', 'drivers/aes2501.h' ] + drivers_sources += [ 'drivers/aes2501.c' ] aeslib = true endif if driver == 'aes2550' - drivers_sources += [ 'drivers/aes2550.c', 'drivers/aes2550.h' ] + drivers_sources += [ 'drivers/aes2550.c' ] aeslib = true endif if driver == 'aes2660' - drivers_sources += [ 'drivers/aes2660.c', 'drivers/aes2660.h' ] + drivers_sources += [ 'drivers/aes2660.c' ] aeslib = true aesx660 = true endif @@ -129,33 +129,33 @@ foreach driver: drivers drivers_sources += [ 'drivers/vfs101.c' ] endif if driver == 'vfs301' - drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c', 'drivers/vfs301_proto.h', 'drivers/vfs301_proto_fragments.h' ] + drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c' ] endif if driver == 'vfs5011' - drivers_sources += [ 'drivers/vfs5011.c', 'drivers/vfs5011_proto.h' ] + drivers_sources += [ 'drivers/vfs5011.c' ] endif if driver == 'upektc_img' - drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ] + drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upek_proto.c' ] endif if driver == 'etes603' drivers_sources += [ 'drivers/etes603.c' ] endif if driver == 'vfs0050' - drivers_sources += [ 'drivers/vfs0050.c', 'drivers/vfs0050.h' ] + drivers_sources += [ 'drivers/vfs0050.c' ] endif if driver == 'elan' - drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ] + drivers_sources += [ 'drivers/elan.c' ] endif endforeach if aeslib - drivers_sources += [ 'drivers/aeslib.c', 'drivers/aeslib.h' ] + drivers_sources += [ 'drivers/aeslib.c' ] endif if aesx660 - drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ] + drivers_sources += ['drivers/aesx660.c' ] endif if aes3k - drivers_sources += ['drivers/aes3k.c', 'drivers/aes3k.h' ] + drivers_sources += ['drivers/aes3k.c' ] endif other_sources = [] From f52276bd062c4490c8b50c9e2998de66ba7394ef Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 12 Jun 2019 16:07:44 +0200 Subject: [PATCH 22/50] build: Remove header files from libfprint_sources There is no need to list them in the sources. --- libfprint/meson.build | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index 2db47498..7ccf0aa8 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -1,30 +1,15 @@ libfprint_sources = [ - 'fp_internal.h', - 'nbis-helpers.h', - 'drivers_api.h', 'fpi-async.c', - 'fpi-async.h', 'fpi-assembling.c', - 'fpi-assembling.h', 'fpi-core.c', - 'fpi-core.h', 'fpi-data.c', - 'fpi-data.h', 'fpi-dev.c', - 'fpi-dev.h', 'fpi-dev-img.c', - 'fpi-dev-img.h', 'fpi-img.c', - 'fpi-img.h', - 'fpi-log.h', 'fpi-ssm.c', - 'fpi-ssm.h', 'fpi-sync.c', - 'fpi-poll.h', 'fpi-poll.c', - 'fpi-usb.h', 'fpi-usb.c', - 'drivers/driver_ids.h', ] nbis_sources = [ From 66891274a7fbfb7b0c97c271aebad87a083bc612 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 12 Jun 2019 16:08:29 +0200 Subject: [PATCH 23/50] build: Remove header files from nbis_sources There is no need to list them in the sources. --- libfprint/meson.build | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index 7ccf0aa8..2b8227e2 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -13,13 +13,6 @@ libfprint_sources = [ ] nbis_sources = [ - 'nbis/include/bozorth.h', - 'nbis/include/bz_array.h', - 'nbis/include/defs.h', - 'nbis/include/lfs.h', - 'nbis/include/log.h', - 'nbis/include/morph.h', - 'nbis/include/sunrast.h', 'nbis/bozorth3/bozorth3.c', 'nbis/bozorth3/bz_alloc.c', 'nbis/bozorth3/bz_drvrs.c', From ef90938eb997d96d965cc80b90edb98907a3c2d3 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Jun 2019 13:54:48 +0200 Subject: [PATCH 24/50] build: Bump GLib dependency to 2.50 and add guards libfprint already uses G_DEBUG_HERE in a lot of places which requires GLib 2.50. Also add the appropriate defines so that usage of newer API will result in warnings. --- meson.build | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index db5008f1..c925afcd 100644 --- a/meson.build +++ b/meson.build @@ -27,7 +27,9 @@ common_cflags = cc.get_supported_arguments([ '-Wstrict-prototypes', '-Werror-implicit-function-declaration', '-Wno-pointer-sign', - '-Wshadow' + '-Wshadow', + '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_50', + '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_50', ]) # maintaining compatibility with the previous libtool versioning @@ -39,7 +41,7 @@ revision = 0 libversion = '@0@.@1@.@2@'.format(soversion, current, revision) # Dependencies -glib_dep = dependency('glib-2.0', version: '>= 2.28') +glib_dep = dependency('glib-2.0', version: '>= 2.50') libusb_dep = dependency('libusb-1.0', version: '>= 0.9.1') mathlib_dep = cc.find_library('m', required: false) From a4b6813ebf95b3a08c63dd26000aa4a4bf2a7fde Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Jun 2019 15:09:19 +0200 Subject: [PATCH 25/50] examples: Add simple storage implementation using GVariant This is useful so that the enroll and verify examples will not use the deprecated API anymore. --- examples/storage.c | 136 +++++++++++++++++++++++++++++++++++++++++++++ examples/storage.h | 27 +++++++++ 2 files changed, 163 insertions(+) create mode 100644 examples/storage.c create mode 100644 examples/storage.h diff --git a/examples/storage.c b/examples/storage.c new file mode 100644 index 00000000..aa399e0f --- /dev/null +++ b/examples/storage.c @@ -0,0 +1,136 @@ +/* + * Trivial storage driver for example programs + * + * Copyright (C) 2019 Benjamin Berg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include + +#define STORAGE_FILE "test-storage.variant" + +static char * +get_print_data_descriptor (struct fp_print_data *data, struct fp_dev *dev, enum fp_finger finger) +{ + gint drv_id; + gint devtype; + + if (data) { + drv_id = fp_print_data_get_driver_id (data); + devtype = fp_print_data_get_devtype (data); + } else { + drv_id = fp_driver_get_driver_id(fp_dev_get_driver (dev)); + devtype = fp_dev_get_devtype (dev); + } + + return g_strdup_printf("%x/%08x/%x", + drv_id, + devtype, + finger); +} + +static GVariantDict* +load_data(void) +{ + GVariantDict *res; + GVariant *var; + gchar *contents = NULL; + gssize length = 0; + + if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) { + g_warning ("Error loading storage, assuming it is empty"); + return g_variant_dict_new(NULL); + } + + var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL); + + res = g_variant_dict_new(var); + g_variant_unref(var); + return res; +} + +static int +save_data(GVariant *data) +{ + const gchar *contents = NULL; + gsize length; + + length = g_variant_get_size(data); + contents = (gchar*) g_variant_get_data (data); + + if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) { + g_warning ("Error saving storage,!"); + return -1; + } + + g_variant_ref_sink(data); + g_variant_unref(data); + + return 0; +} + +int +print_data_save(struct fp_print_data *fp_data, enum fp_finger finger) +{ + gchar *descr = get_print_data_descriptor (fp_data, NULL, finger); + GVariantDict *dict; + GVariant *val; + guchar *data; + gsize size; + int res; + + dict = load_data(); + + size = fp_print_data_get_data(fp_data, &data); + val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1); + g_variant_dict_insert_value (dict, descr, val); + + res = save_data(g_variant_dict_end(dict)); + g_variant_dict_unref(dict); + + return res; +} + +struct fp_print_data* +print_data_load(struct fp_dev *dev, enum fp_finger finger) +{ + gchar *descr = get_print_data_descriptor (NULL, dev, finger); + GVariantDict *dict; + guchar *stored_data; + gsize stored_len; + GVariant *val; + struct fp_print_data *res = NULL; + + dict = load_data(); + val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); + + if (val) { + stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1); + res = fp_print_data_from_data(stored_data, stored_len); + + g_variant_unref(val); + } + + g_variant_dict_unref(dict); + g_free(descr); + + return res; +} diff --git a/examples/storage.h b/examples/storage.h new file mode 100644 index 00000000..fc86813e --- /dev/null +++ b/examples/storage.h @@ -0,0 +1,27 @@ +/* + * Trivial storage driver for example programs + * + * Copyright (C) 2019 Benjamin Berg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __STORAGE_H +#define __STORAGE_H + +int print_data_save(struct fp_print_data *fp_data, enum fp_finger finger); +struct fp_print_data* print_data_load(struct fp_dev *dev, enum fp_finger finger); + +#endif /* __STORAGE_H */ From a9600e23a1bed47499fa240910d36304f37f8edd Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Jun 2019 15:10:25 +0200 Subject: [PATCH 26/50] examples: Link examples to the new GVariant based storage For now just compile and link it, we do not yet use the new storage code. --- examples/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/meson.build b/examples/meson.build index cba326fb..7596be64 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -2,8 +2,8 @@ examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ] foreach example: examples executable(example, - example + '.c', - dependencies: libfprint_dep, + [example + '.c', 'storage.c'], + dependencies: [libfprint_dep, glib_dep], include_directories: [ root_inc, ], From 16875d77769380395096ef8565dabd838dc83ddc Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 13 Jun 2019 15:10:59 +0200 Subject: [PATCH 27/50] examples: Port enroll and verify examples to new storage This ports the enroll and verify examples to the new storage so that they do not need any deprecated API anymore. --- examples/enroll.c | 7 +++---- examples/verify.c | 9 ++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/examples/enroll.c b/examples/enroll.c index 0fe10bbc..9814f68e 100644 --- a/examples/enroll.c +++ b/examples/enroll.c @@ -24,6 +24,8 @@ #include +#include "storage.h" + struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) { struct fp_dscv_dev *ddev = discovered_devs[0]; @@ -142,10 +144,7 @@ int main(void) if (!data) goto out_close; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - r = fp_print_data_save(data, RIGHT_INDEX); -#pragma GCC diagnostic pop + r = print_data_save(data, RIGHT_INDEX); if (r < 0) fprintf(stderr, "Data save failed, code %d\n", r); diff --git a/examples/verify.c b/examples/verify.c index 713c39c1..38b925c5 100644 --- a/examples/verify.c +++ b/examples/verify.c @@ -24,6 +24,8 @@ #include +#include "storage.h" + struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) { struct fp_dscv_dev *ddev = discovered_devs[0]; @@ -117,11 +119,8 @@ int main(void) printf("Opened device. Loading previously enrolled right index finger " "data...\n"); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - r = fp_print_data_load(dev, RIGHT_INDEX, &data); -#pragma GCC diagnostic pop - if (r != 0) { + data = print_data_load(dev, RIGHT_INDEX); + if (!data) { fprintf(stderr, "Failed to load fingerprint, error %d\n", r); fprintf(stderr, "Did you remember to enroll your right index finger " "first?\n"); From 3b32baccf6493ff73d9c2c75a710f1a1697c156c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 18 Jun 2019 16:42:58 +0200 Subject: [PATCH 28/50] fdu2000: Remove driver as it has been defunct for long The driver was never ported to the new asynchronous model, meaning it has been defunct since some time in 2008. Remove the driver, as seemingly no one has complained about this and we have no proper way to even verify a port is correct. --- libfprint/drivers/driver_ids.h | 2 +- libfprint/drivers/fdu2000.c | 318 --------------------------------- libfprint/meson.build | 3 - 3 files changed, 1 insertion(+), 322 deletions(-) delete mode 100644 libfprint/drivers/fdu2000.c diff --git a/libfprint/drivers/driver_ids.h b/libfprint/drivers/driver_ids.h index 8839a744..012a3d06 100644 --- a/libfprint/drivers/driver_ids.h +++ b/libfprint/drivers/driver_ids.h @@ -27,7 +27,7 @@ enum { AES2501_ID = 4, UPEKTC_ID = 5, AES1610_ID = 6, - FDU2000_ID = 7, + /* FDU2000_ID = 7, */ VCOM5S_ID = 8, UPEKSONLY_ID = 9, VFS101_ID = 10, diff --git a/libfprint/drivers/fdu2000.c b/libfprint/drivers/fdu2000.c deleted file mode 100644 index 44b993dc..00000000 --- a/libfprint/drivers/fdu2000.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Secugen FDU2000 driver for libfprint - * Copyright (C) 2007 Gustavo Chain - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define FP_COMPONENT "fdu2000" - -#include "drivers_api.h" - -#ifndef HAVE_MEMMEM -gpointer -memmem(const gpointer haystack, size_t haystack_len, const gpointer needle, size_t needle_len) { - const gchar *begin; - const char *const last_possible = (const char *) haystack + haystack_len - needle_len; - - /* The first occurrence of the empty string is deemed to occur at - * the beginning of the string. */ - if (needle_len == 0) - return (void *) haystack; - - /* Sanity check, otherwise the loop might search through the whole - * memory. */ - if (haystack_len < needle_len) - return NULL; - - for (begin = (const char *) haystack; begin <= last_possible; ++begin) - if (begin[0] == ((const char *) needle)[0] && - !memcmp((const void *) &begin[1], - (const void *) ((const char *) needle + 1), - needle_len - 1)) - return (void *) begin; - - return NULL; -} -#endif /* HAVE_MEMMEM */ - -#define EP_IMAGE ( 0x02 | LIBUSB_ENDPOINT_IN ) -#define EP_REPLY ( 0x01 | LIBUSB_ENDPOINT_IN ) -#define EP_CMD ( 0x01 | LIBUSB_ENDPOINT_OUT ) -#define BULK_TIMEOUT 200 - -/* fdu_req[] index */ -typedef enum { - CAPTURE_READY, - CAPTURE_READ, - CAPTURE_END, - LED_OFF, - LED_ON -} req_index; - - -#define CMD_LEN 2 -#define ACK_LEN 8 -static const struct fdu2000_req { - const gchar cmd[CMD_LEN]; // Command to send - const gchar ack[ACK_LEN]; // Expected ACK - const guint ack_len; // ACK has variable length -} fdu_req[] = { - /* Capture */ - { - .cmd = { 0x00, 0x04 }, - .ack = { 0x00, 0x04, 0x01, 0x01 }, - .ack_len = 4 - }, - - { - .cmd = { 0x00, 0x01 }, - .ack = { 0x00, 0x01, 0x01, 0x01 }, - .ack_len = 4 - }, - - { - .cmd = { 0x00, 0x05 }, - .ack = { 0x00, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - .ack_len = 8 - }, - - /* Led */ - { - .cmd = { 0x05, 0x00 }, - .ack = {}, - .ack_len = 0 - }, - - { - .cmd = { 0x05, 0x01 }, - .ack = {}, - .ack_len = 0 - } -}; - -/* - * Write a command and verify reponse - */ -static gint -bulk_write_safe(libusb_dev_handle *dev, req_index rIndex) { - - gchar reponse[ACK_LEN]; - gint r; - gchar *cmd = (gchar *)fdu_req[rIndex].cmd; - gchar *ack = (gchar *)fdu_req[rIndex].ack; - gint ack_len = fdu_req[rIndex].ack_len; - struct libusb_bulk_transfer wrmsg = { - .endpoint = EP_CMD, - .data = cmd, - .length = sizeof(cmd), - }; - struct libusb_bulk_transfer readmsg = { - .endpoint = EP_REPLY, - .data = reponse, - .length = sizeof(reponse), - }; - int trf; - - r = libusb_bulk_transfer(dev, &wrmsg, &trf, BULK_TIMEOUT); - if (r < 0) - return r; - - if (ack_len == 0) - return 0; - - /* Check reply from FP */ - r = libusb_bulk_transfer(dev, &readmsg, &trf, BULK_TIMEOUT); - if (r < 0) - return r; - - if (!strncmp(ack, reponse, ack_len)) - return 0; - - fp_err("Expected different ACK from dev"); - return 1; /* Error */ -} - -static gint -capture(struct fp_img_dev *dev, gboolean unconditional, - struct fp_img **ret) -{ -#define RAW_IMAGE_WIDTH 398 -#define RAW_IMAGE_HEIGTH 301 -#define RAW_IMAGE_SIZE (RAW_IMAGE_WIDTH * RAW_IMAGE_HEIGTH) - - struct fp_img *img = NULL; - int bytes, r; - const gchar SOF[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x07 }; // Start of frame - const gchar SOL[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0b, 0x06 }; // Start of line + { L L } (L: Line num) (8 nibbles) - gchar *buffer = g_malloc0(RAW_IMAGE_SIZE * 6); - gchar *image; - gchar *p; - guint offset; - struct libusb_bulk_transfer msg = { - .endpoint = EP_IMAGE, - .data = buffer, - .length = RAW_IMAGE_SIZE * 6, - }; - - image = g_malloc0(RAW_IMAGE_SIZE); - - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_ON))) { - fp_err("Command: LED_ON"); - goto out; - } - - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READY))) { - fp_err("Command: CAPTURE_READY"); - goto out; - } - -read: - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READ))) { - fp_err("Command: CAPTURE_READ"); - goto out; - } - - /* Now we are ready to read from dev */ - - r = libusb_bulk_transfer(fpi_dev_get_usb_dev(FP_DEV(dev)), &msg, &bytes, BULK_TIMEOUT * 10); - if (r < 0 || bytes < 1) - goto read; - - /* - * Find SOF (start of line) - */ - p = memmem(buffer, RAW_IMAGE_SIZE * 6, - (const gpointer)SOF, sizeof SOF); - fp_dbg("Read %d byte/s from dev", bytes); - if (!p) - goto out; - - p += sizeof SOF; - - int i = 0; - bytes = 0; - while(p) { - if ( i >= RAW_IMAGE_HEIGTH ) - break; - - offset = p - buffer; - p = memmem(p, (RAW_IMAGE_SIZE * 6) - (offset), - (const gpointer)SOL, sizeof SOL); - if (p) { - p += sizeof SOL + 4; - int j; - for (j = 0; j < RAW_IMAGE_WIDTH; j++) { - /* - * Convert from 4 to 8 bits - * The SECUGEN-FDU2000 has 4 lines of data, so we need to join 2 bytes into 1 - */ - *(image + bytes + j) = *(p + (j * 2) + 0) << 4 & 0xf0; - *(image + bytes + j) |= *(p + (j * 2) + 1) & 0x0f; - } - p += RAW_IMAGE_WIDTH * 2; - bytes += RAW_IMAGE_WIDTH; - i++; - } - } - - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) { - fp_err("Command: CAPTURE_END"); - goto out; - } - - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) { - fp_err("Command: LED_OFF"); - goto out; - } - - img = fpi_img_new_for_imgdev(dev); - memcpy(img->data, image, RAW_IMAGE_SIZE); - img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - *ret = img; - -out: - g_free(buffer); - g_free(image); - - return r; -} - -static -gint dev_init(struct fp_img_dev *dev, unsigned long driver_data) -{ - gint r; - //if ( (r = usb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 ) - // goto out; - - if ( (r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0)) < 0 ) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - - //if ( (r = usb_set_altinterface(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 ) - // goto out; - - //if ( (r = usb_clear_halt(fpi_dev_get_usb_dev(FP_DEV(dev)), EP_CMD)) < 0 ) - // goto out; - - /* Make sure sensor mode is not capture_{ready|read} */ - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) { - fp_err("Command: CAPTURE_END"); - goto out; - } - - if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) { - fp_err("Command: LED_OFF"); - goto out; - } - - return 0; - -out: - fp_err("could not init dev"); - return r; -} - -static -void dev_exit(struct fp_img_dev *dev) -{ - if (bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END)) - fp_err("Command: CAPTURE_END"); - - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); -} - -static const struct usb_id id_table[] = { - { .vendor = 0x1162, .product = 0x0300 }, - { 0, 0, 0, }, -}; - -struct fp_img_driver fdu2000_driver = { - .driver = { - .id = FDU2000_ID, - .name = FP_COMPONENT, - .full_name = "Secugen FDU 2000", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .img_height = RAW_IMAGE_HEIGTH, - .img_width = RAW_IMAGE_WIDTH, - .bz3_threshold = 23, - - .init = dev_init, - .exit = dev_exit, - .capture = capture, -}; diff --git a/libfprint/meson.build b/libfprint/meson.build index 2b8227e2..976c70c8 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -97,9 +97,6 @@ foreach driver: drivers aeslib = true aes3k = true endif - if driver == 'fdu2000' - drivers_sources += [ 'drivers/fdu2000.c' ] - endif if driver == 'vcom5s' drivers_sources += [ 'drivers/vcom5s.c' ] endif From 4cec28416eb622a223ad30b9d63306573b9d04de Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 18 Jun 2019 18:12:28 +0200 Subject: [PATCH 29/50] lib: Remove state from fp_img_driver activate handler The state was always AWAIT_FINGER and it was never used by any driver (except for error checking). So remove it, in particular as a correct state change will be done after activation anyway. The only driver with code that actually did anything based on this was the URU4000 driver. However, all it did was an explicit state change execution. This is not necessary, as the state_change handler is called anyway (i.e. we now only write the AWAIT_FINGER register once rather than twice). Manual changes plus: @ init @ identifier driver_name; identifier activate_func; @@ struct fp_img_driver driver_name = { ..., .activate = activate_func, ..., }; @ remove_arg @ identifier dev; identifier state; identifier init.activate_func; @@ activate_func ( struct fp_img_dev *dev - , enum fp_imgdev_state state ) { <... - if (state != IMGDEV_STATE_AWAIT_FINGER_ON) { ... } ...> } --- libfprint/drivers/aes1610.c | 2 +- libfprint/drivers/aes2501.c | 2 +- libfprint/drivers/aes2550.c | 2 +- libfprint/drivers/aes3k.c | 2 +- libfprint/drivers/aes3k.h | 2 +- libfprint/drivers/aesx660.c | 2 +- libfprint/drivers/aesx660.h | 2 +- libfprint/drivers/elan.c | 2 +- libfprint/drivers/etes603.c | 8 +------- libfprint/drivers/upeksonly.c | 2 +- libfprint/drivers/upektc.c | 2 +- libfprint/drivers/upektc_img.c | 2 +- libfprint/drivers/uru4000.c | 13 +------------ libfprint/drivers/vcom5s.c | 2 +- libfprint/drivers/vfs0050.c | 2 +- libfprint/drivers/vfs101.c | 2 +- libfprint/drivers/vfs301.c | 2 +- libfprint/drivers/vfs5011.c | 2 +- libfprint/fpi-core.h | 2 +- libfprint/fpi-dev-img.c | 6 +++--- 20 files changed, 22 insertions(+), 39 deletions(-) diff --git a/libfprint/drivers/aes1610.c b/libfprint/drivers/aes1610.c index 1e7b3b9b..927cca78 100644 --- a/libfprint/drivers/aes1610.c +++ b/libfprint/drivers/aes1610.c @@ -749,7 +749,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d fpi_ssm_free(ssm); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index 2a031732..3511893a 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -792,7 +792,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d fpi_ssm_free(ssm); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, diff --git a/libfprint/drivers/aes2550.c b/libfprint/drivers/aes2550.c index ce5b6c2b..ba021d3d 100644 --- a/libfprint/drivers/aes2550.c +++ b/libfprint/drivers/aes2550.c @@ -541,7 +541,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d fpi_ssm_free(ssm); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, ACTIVATE_NUM_STATES, dev); diff --git a/libfprint/drivers/aes3k.c b/libfprint/drivers/aes3k.c index 59c91bcc..ddb94c9b 100644 --- a/libfprint/drivers/aes3k.c +++ b/libfprint/drivers/aes3k.c @@ -137,7 +137,7 @@ static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data) do_capture(dev); } -int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +int aes3k_dev_activate(struct fp_img_dev *dev) { struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL); diff --git a/libfprint/drivers/aes3k.h b/libfprint/drivers/aes3k.h index 98750ede..a54199d0 100644 --- a/libfprint/drivers/aes3k.h +++ b/libfprint/drivers/aes3k.h @@ -52,7 +52,7 @@ struct aes3k_dev { }; -int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state); +int aes3k_dev_activate(struct fp_img_dev *dev); void aes3k_dev_deactivate(struct fp_img_dev *dev); #endif diff --git a/libfprint/drivers/aesx660.c b/libfprint/drivers/aesx660.c index 852c7509..47da51f5 100644 --- a/libfprint/drivers/aesx660.c +++ b/libfprint/drivers/aesx660.c @@ -589,7 +589,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d start_finger_detection(dev); } -int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +int aesX660_dev_activate(struct fp_img_dev *dev) { fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, ACTIVATE_NUM_STATES, dev); diff --git a/libfprint/drivers/aesx660.h b/libfprint/drivers/aesx660.h index 2106ca2d..8d8f3501 100644 --- a/libfprint/drivers/aesx660.h +++ b/libfprint/drivers/aesx660.h @@ -116,7 +116,7 @@ static const unsigned char calibrate_cmd[] = { 0x06, }; -int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state); +int aesX660_dev_activate(struct fp_img_dev *dev); void aesX660_dev_deactivate(struct fp_img_dev *dev); #endif diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 3314d8d5..7c014aa0 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -874,7 +874,7 @@ static void dev_deinit(struct fp_img_dev *dev) fpi_imgdev_close_complete(dev); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { G_DEBUG_HERE(); elan_activate(dev); diff --git a/libfprint/drivers/etes603.c b/libfprint/drivers/etes603.c index 8f3ec458..f46a4a55 100644 --- a/libfprint/drivers/etes603.c +++ b/libfprint/drivers/etes603.c @@ -1390,19 +1390,13 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) fpi_ssm_free(ssm); } -static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *idev) { struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); fpi_ssm *ssm; g_assert(dev); - if (state != IMGDEV_STATE_AWAIT_FINGER_ON) { - fp_err("The driver is in an unexpected state: %d.", state); - fpi_imgdev_activate_complete(idev, 1); - return -1; - } - /* Reset info and data */ dev->is_active = TRUE; diff --git a/libfprint/drivers/upeksonly.c b/libfprint/drivers/upeksonly.c index 99c5ffae..2f37ceff 100644 --- a/libfprint/drivers/upeksonly.c +++ b/libfprint/drivers/upeksonly.c @@ -1268,7 +1268,7 @@ static void initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) fpi_ssm_start(sdev->loopsm, loopsm_complete); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm = NULL; diff --git a/libfprint/drivers/upektc.c b/libfprint/drivers/upektc.c index 0042833e..00d9c553 100644 --- a/libfprint/drivers/upektc.c +++ b/libfprint/drivers/upektc.c @@ -377,7 +377,7 @@ static void start_capture(struct fp_img_dev *dev) fpi_ssm_start(ssm, capture_sm_complete); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, diff --git a/libfprint/drivers/upektc_img.c b/libfprint/drivers/upektc_img.c index d749ac51..dfa16029 100644 --- a/libfprint/drivers/upektc_img.c +++ b/libfprint/drivers/upektc_img.c @@ -567,7 +567,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d start_capture(dev); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index 7e54addf..8f648ef1 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -1161,20 +1161,10 @@ static void activate_initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *us int r = fpi_ssm_get_error(ssm); fpi_ssm_free(ssm); - if (r) { - fpi_imgdev_activate_complete(dev, r); - return; - } - - r = execute_state_change(dev); fpi_imgdev_activate_complete(dev, r); } -/* FIXME: having state parameter here is kinda useless, will we ever - * see a scenario where the parameter is useful so early on in the activation - * process? asynchronity means that it'll only be used in a later function - * call. */ -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm; @@ -1185,7 +1175,6 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) return r; urudev->scanpwr_irq_timeouts = 0; - urudev->activate_state = state; ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev); fpi_ssm_start(ssm, activate_initsm_complete); return 0; diff --git a/libfprint/drivers/vcom5s.c b/libfprint/drivers/vcom5s.c index 4ed71f69..b0c6c452 100644 --- a/libfprint/drivers/vcom5s.c +++ b/libfprint/drivers/vcom5s.c @@ -302,7 +302,7 @@ static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) fpi_imgdev_deactivate_complete(dev); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state, diff --git a/libfprint/drivers/vfs0050.c b/libfprint/drivers/vfs0050.c index a437df4f..3f9bbf0e 100644 --- a/libfprint/drivers/vfs0050.c +++ b/libfprint/drivers/vfs0050.c @@ -684,7 +684,7 @@ static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_ } /* Activate device */ -static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *idev) { struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); diff --git a/libfprint/drivers/vfs101.c b/libfprint/drivers/vfs101.c index 8faaa230..af64a589 100644 --- a/libfprint/drivers/vfs101.c +++ b/libfprint/drivers/vfs101.c @@ -1424,7 +1424,7 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) } /* Activate device */ -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); fpi_ssm *ssm; diff --git a/libfprint/drivers/vfs301.c b/libfprint/drivers/vfs301.c index 4116e71e..94837de0 100644 --- a/libfprint/drivers/vfs301.c +++ b/libfprint/drivers/vfs301.c @@ -191,7 +191,7 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) } /* Activate device */ -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { fpi_ssm *ssm; diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index e1858332..ec62317d 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -846,7 +846,7 @@ static void start_scan(struct fp_img_dev *dev) fp_dbg("ssm done, getting out"); } -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *dev) { struct vfs5011_data *data; diff --git a/libfprint/fpi-core.h b/libfprint/fpi-core.h index a5a0a44d..d183f885 100644 --- a/libfprint/fpi-core.h +++ b/libfprint/fpi-core.h @@ -110,7 +110,7 @@ struct fp_img_driver { /* Device operations */ int (*open)(struct fp_img_dev *dev, unsigned long driver_data); void (*close)(struct fp_img_dev *dev); - int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state); + int (*activate)(struct fp_img_dev *dev); int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state); void (*deactivate)(struct fp_img_dev *dev); }; diff --git a/libfprint/fpi-dev-img.c b/libfprint/fpi-dev-img.c index 93f1f47e..a7c24104 100644 --- a/libfprint/fpi-dev-img.c +++ b/libfprint/fpi-dev-img.c @@ -533,14 +533,14 @@ int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev) return height; } -static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state) +static int dev_activate(struct fp_img_dev *imgdev) { struct fp_driver *drv = FP_DEV(imgdev)->drv; struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); if (!imgdrv->activate) return 0; - return imgdrv->activate(imgdev, state); + return imgdrv->activate(imgdev); } static void dev_deactivate(struct fp_img_dev *imgdev) @@ -562,7 +562,7 @@ static int generic_acquire_start(struct fp_dev *dev, int action) imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING; imgdev->enroll_stage = 0; - r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON); + r = dev_activate(imgdev); if (r < 0) fp_err("activation failed with error %d", r); From 5b171f957778c174e4333a7e876e8cd8df135d25 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 25 Jul 2019 12:02:44 +0200 Subject: [PATCH 30/50] Add code of conduct document --- code-of-conduct.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 code-of-conduct.md diff --git a/code-of-conduct.md b/code-of-conduct.md new file mode 100644 index 00000000..a429a426 --- /dev/null +++ b/code-of-conduct.md @@ -0,0 +1,3 @@ +This project and its community follow the [Freedesktop.org code of conduct] + +[Freedesktop.org code of conduct]: https://www.freedesktop.org/wiki/CodeOfConduct/ From 76db6a5a162d28ab1743f515fbc2de5a70df3c02 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:12:45 +0200 Subject: [PATCH 31/50] aes*: Fix a number of typos --- libfprint/drivers/aes1610.c | 8 ++++---- libfprint/drivers/aes2501.c | 2 +- libfprint/drivers/aes2501.h | 2 +- libfprint/drivers/aes2550.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libfprint/drivers/aes1610.c b/libfprint/drivers/aes1610.c index 927cca78..df5b5695 100644 --- a/libfprint/drivers/aes1610.c +++ b/libfprint/drivers/aes1610.c @@ -404,7 +404,7 @@ static unsigned char list_BD_values[10] = { /* * Adjust the gain according to the histogram data * 0xbd, 0xbe, 0x29 and 0x2A registers are affected - * Returns 0 if no problem occured + * Returns 0 if no problem occurred * TODO: This is a basic support for gain. It needs testing/tweaking. */ static int adjust_gain(unsigned char *buffer, int status) { @@ -412,7 +412,7 @@ static int adjust_gain(unsigned char *buffer, int status) static int pos_list_BE = 0; static int pos_list_BD = 0; - // This is the first adjustement (we begin acquisition) + // This is the first adjustment (we begin acquisition) // We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step if (status == GAIN_STATUS_FIRST) { if (buffer[1] > 0x78) { // maximum gain needed @@ -534,7 +534,7 @@ static void restore_gain(void) /* capture SM movement: * request and read strip, - * jump back to request UNLESS theres no finger, in which case exit SM, + * jump back to request UNLESS there's no finger, in which case exit SM, * report lack of finger presence, and move to finger detection */ enum capture_states { @@ -728,7 +728,7 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat struct fp_img_dev *dev = user_data; /* activation on aes1610 seems much more straightforward compared to aes2501 */ - /* verify theres anything missing here */ + /* verify there's anything missing here */ switch (fpi_ssm_get_cur_state(ssm)) { case WRITE_INIT: fp_dbg("write init"); diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index 3511893a..91e02a39 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -415,7 +415,7 @@ static struct aes_regwrite strip_scan_reqs[] = { /* capture SM movement: * write reqs and read data 1 + 2, * request and read strip, - * jump back to request UNLESS theres no finger, in which case exit SM, + * jump back to request UNLESS there's no finger, in which case exit SM, * report lack of finger presence, and move to finger detection */ enum capture_states { diff --git a/libfprint/drivers/aes2501.h b/libfprint/drivers/aes2501.h index 9f2f1b6e..19adcc90 100644 --- a/libfprint/drivers/aes2501.h +++ b/libfprint/drivers/aes2501.h @@ -109,7 +109,7 @@ enum aes2501_mesure_drive { /* Select (1=square | 0=sine) wave drive during measure */ #define AES2501_MEASDRV_SQUARE 0x20 -/* 0 = use mesure drive setting, 1 = when sine wave is selected */ +/* 0 = use measure drive setting, 1 = when sine wave is selected */ #define AES2501_MEASDRV_MEASURE_SQUARE 0x10 enum aes2501_measure_freq { diff --git a/libfprint/drivers/aes2550.c b/libfprint/drivers/aes2550.c index ba021d3d..72a86132 100644 --- a/libfprint/drivers/aes2550.c +++ b/libfprint/drivers/aes2550.c @@ -447,7 +447,7 @@ static void init_read_data_cb(struct libusb_transfer *transfer) } /* TODO: use calibration table, datasheet is rather terse on that - * need more info for implementaion */ + * need more info for implementation */ static void calibrate_read_data_cb(struct libusb_transfer *transfer) { fpi_ssm *ssm = transfer->user_data; From 0400bcc85e153a409d0ee11e8e4567a42aba04e4 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:13:10 +0200 Subject: [PATCH 32/50] vfs*: Fix a number of typos --- libfprint/drivers/vfs0050.c | 2 +- libfprint/drivers/vfs101.c | 12 ++++++------ libfprint/drivers/vfs301_proto.h | 2 +- libfprint/drivers/vfs301_proto_fragments.h | 2 +- libfprint/drivers/vfs5011.c | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libfprint/drivers/vfs0050.c b/libfprint/drivers/vfs0050.c index 3f9bbf0e..b2f8395e 100644 --- a/libfprint/drivers/vfs0050.c +++ b/libfprint/drivers/vfs0050.c @@ -577,7 +577,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) vdev->need_report = 0; } - /* Asyncronously enquire an interrupt */ + /* Asynchronously enquire an interrupt */ vdev->transfer = fpi_usb_alloc(); vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, 0x83, diff --git a/libfprint/drivers/vfs101.c b/libfprint/drivers/vfs101.c index af64a589..60f0a819 100644 --- a/libfprint/drivers/vfs101.c +++ b/libfprint/drivers/vfs101.c @@ -47,7 +47,7 @@ /* Minimum image height */ #define VFS_IMG_MIN_HEIGHT 200 -/* Scan level thresold */ +/* Scan level threshold */ #define VFS_IMG_SLT_BEGIN 768 #define VFS_IMG_SLT_END 64 #define VFS_IMG_SLT_LINES 4 @@ -641,7 +641,7 @@ static int action_completed(struct fp_img_dev *dev) #define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE)) -/* Screen image to remove noise and find bottom line and height od image */ +/* Screen image to remove noise and find bottom line and height of image */ static void img_screen(struct vfs101_dev *vdev) { int y, x, count, top; @@ -654,7 +654,7 @@ static void img_screen(struct vfs101_dev *vdev) /* Image returned from sensor can contain many empty lines, * for remove these lines compare byte 282-283 (scan level information) - * with two differents threshold, one for the begin of finger image and + * with two different thresholds, one for the begin of finger image and * one for the end. To increase stability of the code use a counter * of lines that satisfy the threshold. */ @@ -700,7 +700,7 @@ static void img_screen(struct vfs101_dev *vdev) vdev->height = top - vdev->bottom + 1; - /* Checkk max height */ + /* Check max height */ if (vdev->height > VFS_IMG_MAX_HEIGHT) vdev->height = VFS_IMG_MAX_HEIGHT; @@ -1178,7 +1178,7 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) switch (fpi_ssm_get_cur_state(ssm)) { case M_INIT_0_RECV_DIRTY: - /* Recv eventualy dirty data */ + /* Recv eventually dirty data */ vdev->ignore_error = TRUE; async_recv(ssm, dev); break; @@ -1463,7 +1463,7 @@ static void dev_deactivate(struct fp_img_dev *dev) /* Reset active state */ vdev->active = FALSE; - /* Handle eventualy existing events */ + /* Handle eventually existing events */ while (vdev->transfer) fp_handle_events(); diff --git a/libfprint/drivers/vfs301_proto.h b/libfprint/drivers/vfs301_proto.h index daa629aa..2ae587a1 100644 --- a/libfprint/drivers/vfs301_proto.h +++ b/libfprint/drivers/vfs301_proto.h @@ -109,7 +109,7 @@ typedef struct { unsigned char scan[VFS301_FP_WIDTH]; - /* A offseted, stretched, inverted copy of scan... probably could + /* A offsetted, stretched, inverted copy of scan... probably could * serve finger motion speed detection? * Seems to be subdivided to some 10B + 53B + 1B blocks */ unsigned char mirror[64]; diff --git a/libfprint/drivers/vfs301_proto_fragments.h b/libfprint/drivers/vfs301_proto_fragments.h index c000441c..39441a13 100644 --- a/libfprint/drivers/vfs301_proto_fragments.h +++ b/libfprint/drivers/vfs301_proto_fragments.h @@ -1147,7 +1147,7 @@ static const unsigned char vfs301_24[] = { /* 119 B */ * * The contents of PACKET() inside this blob seems to be some kind * of a micro-program, which specifies which columns contain what. LE seems - * to be used also here. Not neccessarily is 1 output column described + * to be used also here. Not necessarily is 1 output column described * by 1 operation. For example the vfs301_line_t::sum section seems * to perform 2 operations for each column - probably some kind of diff between * input lines? diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index ec62317d..70023162 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -405,7 +405,7 @@ submit_image(fpi_ssm *ssm, g_slist_free_full(data->rows, g_free); data->rows = NULL; - fp_dbg("Image captured, commiting"); + fp_dbg("Image captured, committing"); fpi_imgdev_image_captured(dev, img); } From 2ef8ace543b1adfe224a1b8fbb3e72a3a56e8f3a Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:13:42 +0200 Subject: [PATCH 33/50] etes603: Fix a typo --- libfprint/drivers/etes603.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/etes603.c b/libfprint/drivers/etes603.c index f46a4a55..f82fb05f 100644 --- a/libfprint/drivers/etes603.c +++ b/libfprint/drivers/etes603.c @@ -1316,7 +1316,7 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) fpi_ssm_next_state(ssm); break; case INIT_SENSOR_REQ: - /* In captured traffic, those are splitted. */ + /* In captured traffic, those are split. */ msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP, REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08, REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT, From 6361c208bde78883ce65e9d2b3fa7b674d15ee57 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:14:03 +0200 Subject: [PATCH 34/50] upeksonly: Fix a number of typos --- libfprint/drivers/upeksonly.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfprint/drivers/upeksonly.c b/libfprint/drivers/upeksonly.c index 2f37ceff..69a79e69 100644 --- a/libfprint/drivers/upeksonly.c +++ b/libfprint/drivers/upeksonly.c @@ -136,7 +136,7 @@ static unsigned char upeksonly_get_pixel(struct fpi_line_asmbl_ctx *ctx, unsigned char *buf; unsigned offset; - /* The scans from this device are rolled right by two colums */ + /* The scans from this device are rolled right by two columns */ if (x < ctx->line_width - 2) offset = x + 2; else if ((x > ctx->line_width - 2) && (x < ctx->line_width)) @@ -296,12 +296,12 @@ static void row_complete(struct fp_img_dev *dev) sdev->num_blank = 0; } else { sdev->num_blank++; - /* Don't consider the scan complete unless theres at least + /* Don't consider the scan complete unless there's at least * MIN_ROWS recorded or very long blank read occurred. * * Typical problem spot: one brief touch before starting the * actual scan. Happens most commonly if scan is started - * from before the first joint resulting in a gap after the inital touch. + * from before the first joint resulting in a gap after the initial touch. */ if (sdev->num_blank > FINGER_REMOVED_THRESHOLD) { sdev->finger_state = FINGER_REMOVED; From 252180e0883e93606e6af3baf77cf4c1cfc11ed3 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:14:15 +0200 Subject: [PATCH 35/50] upektc: Fix a typo --- libfprint/drivers/upektc_img.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/upektc_img.c b/libfprint/drivers/upektc_img.c index dfa16029..988793dc 100644 --- a/libfprint/drivers/upektc_img.c +++ b/libfprint/drivers/upektc_img.c @@ -287,7 +287,7 @@ static void capture_read_data_cb(struct libusb_transfer *transfer) fpi_ssm_mark_completed(ssm); break; default: - fp_err("Uknown response!\n"); + fp_err("Unknown response!\n"); fpi_ssm_mark_failed(ssm, -EIO); break; } From e9041da7f4bd72e2a7f9cf0a510e4efa7088e7bd Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:14:34 +0200 Subject: [PATCH 36/50] uru4000: Fix a typo --- libfprint/drivers/uru4000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c index 8f648ef1..79c48c5b 100644 --- a/libfprint/drivers/uru4000.c +++ b/libfprint/drivers/uru4000.c @@ -668,7 +668,7 @@ static uint32_t do_decode(uint8_t *data, int num_bytes, uint32_t key) data[i] = data[i+1] ^ xorbyte; } - /* the final byte is implictly zero */ + /* the final byte is implicitly zero */ data[i] = 0; return update_key(key); } From 0352995cb35718a12f11fb0cef5e284e657dd12b Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:14:59 +0200 Subject: [PATCH 37/50] data: Fix a number of typos --- libfprint/fpi-data.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfprint/fpi-data.c b/libfprint/fpi-data.c index f377404b..c19142ac 100644 --- a/libfprint/fpi-data.c +++ b/libfprint/fpi-data.c @@ -214,7 +214,7 @@ API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data, item = list_item->data; out_item = (struct fpi_print_data_item_fp2 *)buf; out_item->length = GUINT32_TO_LE(item->length); - /* FIXME: fp_print_data_item->data content is not endianess agnostic */ + /* FIXME: fp_print_data_item->data content is not endianness agnostic */ memcpy(out_item->data, item->data, item->length); buf += sizeof(*out_item); buf += item->length; @@ -236,7 +236,7 @@ static struct fp_print_data *fpi_print_data_from_fp1_data(unsigned char *buf, data = print_data_new(GUINT16_FROM_LE(raw->driver_id), GUINT32_FROM_LE(raw->devtype), raw->data_type); item = fpi_print_data_item_new(print_data_len); - /* FIXME: fp_print_data->data content is not endianess agnostic */ + /* FIXME: fp_print_data->data content is not endianness agnostic */ memcpy(item->data, raw->data, print_data_len); data->prints = g_slist_prepend(data->prints, item); @@ -272,7 +272,7 @@ static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf, total_data_len -= item_len; item = fpi_print_data_item_new(item_len); - /* FIXME: fp_print_data->data content is not endianess agnostic */ + /* FIXME: fp_print_data->data content is not endianness agnostic */ memcpy(item->data, raw_item->data, item_len); data->prints = g_slist_prepend(data->prints, item); From 3597a5b0edbd9e5fadc9f6fc7bf26c0f1eebc0df Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:15:21 +0200 Subject: [PATCH 38/50] img: Fix a typo --- libfprint/fpi-img.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/fpi-img.c b/libfprint/fpi-img.c index f5ebea7f..c7f44c24 100644 --- a/libfprint/fpi-img.c +++ b/libfprint/fpi-img.c @@ -405,7 +405,7 @@ int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, } } - /* FIXME: space is wasted if we dont hit the max minutiae count. would + /* FIXME: space is wasted if we don't hit the max minutiae count. would * be good to make this dynamic. */ print = fpi_print_data_new(FP_DEV(imgdev)); item = fpi_print_data_item_new(sizeof(struct xyt_struct)); From 13deaa66fdefe061393bff4e8a014a6cf5eb0102 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:15:34 +0200 Subject: [PATCH 39/50] lib: Fix a typo --- libfprint/fpi-sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/fpi-sync.c b/libfprint/fpi-sync.c index e5a64f81..c2dd7927 100644 --- a/libfprint/fpi-sync.c +++ b/libfprint/fpi-sync.c @@ -149,7 +149,7 @@ static void enroll_stop_cb(struct fp_dev *dev, void *user_data) * or I/O problems. * * The RETRY codes from #fp_enroll_result may be returned from any enroll - * stage. These codes indicate that the scan was not succesful in that the + * stage. These codes indicate that the scan was not successful in that the * user did not position their finger correctly or similar. When a RETRY code * is returned, the enrollment stage is not advanced, so the next call * into this function will retry the current stage again. The current stage may From cb2f46ed08be32c60bb6008d6f254484f5be9670 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:15:48 +0200 Subject: [PATCH 40/50] HACKING: Fix a typo --- HACKING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HACKING.md b/HACKING.md index e43cbf2b..0c3728d8 100644 --- a/HACKING.md +++ b/HACKING.md @@ -3,8 +3,8 @@ ## GLib Although the library uses GLib internally, libfprint is designed to provide -a completely neutral interface to it's application users. So, the public -APIs should never return GLib data types or anything like that. +a completely neutral interface to its application users. So, the public +APIs should never return GLib data types. ## Two-faced-ness From 860a256f4b8cf0b550d12c8aac0c3dc28e206498 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 13:32:06 +0200 Subject: [PATCH 41/50] HACKING: Clarify the intent of the license --- HACKING.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/HACKING.md b/HACKING.md index 0c3728d8..21e17a4b 100644 --- a/HACKING.md +++ b/HACKING.md @@ -6,6 +6,27 @@ Although the library uses GLib internally, libfprint is designed to provide a completely neutral interface to its application users. So, the public APIs should never return GLib data types. +## License clarification + +Although this library's license could allow for shims that hook up into +proprietary blobs to add driver support for some unsupported devices, the +intent of the original authors, and of current maintainers of the library, +was for this license to allow _integration into_ proprietary stacks, not +_integration of_ proprietary code in the library. + +As such, no code to integrate proprietary drivers will be accepted in libfprint +upstream. Proprietary drivers would make it impossible to debug problems in +libfprint, as we wouldn't know what the proprietary driver does behind the +library's back. The closed source nature of drivers is usually used to hide +parts of the hardware setup, such as encryption keys, or protocols, in order +to protect the hardware's integrity. Unfortunately, this is only [security through +obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity). + +We however encourage potential contributors to take advantage of libfprint's +source availability to create such shims to make it easier to reverse-engineer +proprietary drivers in order to create new free software drivers, to the extent +permitted by local laws. + ## Two-faced-ness Like any decent library, this one is designed to provide a stable and From ae1b10dba85b92b2b5cfad32d9342259ab4680a0 Mon Sep 17 00:00:00 2001 From: Igor Filatov Date: Sun, 23 Dec 2018 11:51:55 +0200 Subject: [PATCH 42/50] elan: Fix frame leak in elan_submit_image --- libfprint/drivers/elan.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 7c014aa0..897f34f9 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -293,23 +293,22 @@ static void elan_process_frame_thirds(unsigned short *raw_frame, static void elan_submit_image(struct fp_img_dev *dev) { struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + int num_frames; + GSList *raw_frames; GSList *frames = NULL; struct fp_img *img; G_DEBUG_HERE(); - for (int i = 0; i < ELAN_SKIP_LAST_FRAMES; i++) - elandev->frames = g_slist_next(elandev->frames); - elandev->num_frames -= ELAN_SKIP_LAST_FRAMES; + num_frames = elandev->num_frames - ELAN_SKIP_LAST_FRAMES; + raw_frames = g_slist_nth(elandev->frames, ELAN_SKIP_LAST_FRAMES); assembling_ctx.frame_width = elandev->frame_width; assembling_ctx.frame_height = elandev->frame_height; assembling_ctx.image_width = elandev->frame_width * 3 / 2; - g_slist_foreach(elandev->frames, (GFunc) elandev->process_frame, - &frames); - fpi_do_movement_estimation(&assembling_ctx, frames, - elandev->num_frames); - img = fpi_assemble_frames(&assembling_ctx, frames, elandev->num_frames); + g_slist_foreach(raw_frames, (GFunc) elandev->process_frame, &frames); + fpi_do_movement_estimation(&assembling_ctx, frames, num_frames); + img = fpi_assemble_frames(&assembling_ctx, frames, num_frames); img->flags |= FP_IMG_PARTIAL; fpi_imgdev_image_captured(dev, img); From f309f586c9e224eadb0fd3f061cae661ffb752d1 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 19:18:43 +0200 Subject: [PATCH 43/50] ci: Add ABI check Last ABI break was when we fixed the return value for fp_get_pollfds() in commit 056ea54. --- .ci/check-abi | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ .gitlab-ci.yml | 7 +++ 2 files changed, 120 insertions(+) create mode 100755 .ci/check-abi diff --git a/.ci/check-abi b/.ci/check-abi new file mode 100755 index 00000000..06eb1aca --- /dev/null +++ b/.ci/check-abi @@ -0,0 +1,113 @@ +#!/usr/bin/python3 + + +import argparse +import contextlib +import os +import shutil +import subprocess +import sys + + +def format_title(title): + box = { + 'tl': '╔', 'tr': '╗', 'bl': '╚', 'br': '╝', 'h': '═', 'v': '║', + } + hline = box['h'] * (len(title) + 2) + + return '\n'.join([ + f"{box['tl']}{hline}{box['tr']}", + f"{box['v']} {title} {box['v']}", + f"{box['bl']}{hline}{box['br']}", + ]) + + +def rm_rf(path): + try: + shutil.rmtree(path) + except FileNotFoundError: + pass + + +def sanitize_path(name): + return name.replace('/', '-') + + +def get_current_revision(): + revision = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], + encoding='utf-8').strip() + + if revision == 'HEAD': + # This is a detached HEAD, get the commit hash + revision = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8') + + return revision + + +@contextlib.contextmanager +def checkout_git_revision(revision): + current_revision = get_current_revision() + subprocess.check_call(['git', 'checkout', '-q', revision]) + + try: + yield + finally: + subprocess.check_call(['git', 'checkout', '-q', current_revision]) + + +def build_install(revision): + build_dir = '_build' + dest_dir = os.path.abspath(sanitize_path(revision)) + print(format_title(f'# Building and installing {revision} in {dest_dir}'), + end='\n\n', flush=True) + + with checkout_git_revision(revision): + rm_rf(build_dir) + rm_rf(revision) + + subprocess.check_call(['meson', build_dir, + '--prefix=/usr', '--libdir=lib', + '-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false']) + subprocess.check_call(['ninja', '-v', '-C', build_dir]) + subprocess.check_call(['ninja', '-v', '-C', build_dir, 'install'], + env={'DESTDIR': dest_dir}) + + return dest_dir + + +def compare(old_tree, new_tree): + print(format_title(f'# Comparing the two ABIs'), end='\n\n', flush=True) + + old_headers = os.path.join(old_tree, 'usr', 'include') + old_lib = os.path.join(old_tree, 'usr', 'lib', 'libfprint.so') + + new_headers = os.path.join(new_tree, 'usr', 'include') + new_lib = os.path.join(new_tree, 'usr', 'lib', 'libfprint.so') + + subprocess.check_call([ + 'abidiff', '--headers-dir1', old_headers, '--headers-dir2', new_headers, + '--drop-private-types', '--fail-no-debug-info', '--no-added-syms', old_lib, new_lib]) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + + parser.add_argument('old', help='the previous revision, considered the reference') + parser.add_argument('new', help='the new revision, to compare to the reference') + + args = parser.parse_args() + + if args.old == args.new: + print("Let's not waste time comparing something to itself") + sys.exit(0) + + old_tree = build_install(args.old) + new_tree = build_install(args.new) + + try: + compare(old_tree, new_tree) + + except Exception: + sys.exit(1) + + print(f'Hurray! {args.old} and {args.new} are ABI-compatible!') diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 838c33c3..82846fbd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,7 @@ variables: DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder BUNDLE: "org.freedesktop.libfprint.Demo.flatpak" + LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546" .build_one_driver_template: &build_one_driver script: @@ -24,10 +25,16 @@ variables: - ninja -C _build - ninja -C _build install +.build_template: &check_abi + script: + - dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES doxygen libabigail git + - ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD) + build: stage: build <<: *build_one_driver <<: *build + <<: *check_abi .flatpak_script_template: &flatpak_script script: From dce52ed0818762009a433bc1abc7cd1653599c28 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 19:09:51 +0200 Subject: [PATCH 44/50] vfs5011: Use memmove(), g_memmove() is deprecated --- libfprint/drivers/vfs5011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c index 70023162..c7121f9d 100644 --- a/libfprint/drivers/vfs5011.c +++ b/libfprint/drivers/vfs5011.c @@ -371,7 +371,7 @@ static int process_chunk(struct vfs5011_data *data, int transferred) VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) { data->lastline = g_malloc(VFS5011_LINE_SIZE); data->rows = g_slist_prepend(data->rows, data->lastline); - g_memmove(data->lastline, linebuf, VFS5011_LINE_SIZE); + memmove(data->lastline, linebuf, VFS5011_LINE_SIZE); data->lines_recorded++; if (data->lines_recorded >= data->max_lines_recorded) { fp_dbg("process_chunk: recorded %d lines, finishing", From 658c301e3c2311e097b3e270011e58c6ac9c67ec Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Mon, 5 Aug 2019 19:10:16 +0200 Subject: [PATCH 45/50] lib: Use memmove(), g_memmove() is deprecated --- libfprint/fpi-assembling.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfprint/fpi-assembling.c b/libfprint/fpi-assembling.c index e33dafe5..65fad4d7 100644 --- a/libfprint/fpi-assembling.c +++ b/libfprint/fpi-assembling.c @@ -365,7 +365,7 @@ static void median_filter(int *data, int size, int filtersize) i1 = 0; if (i2 >= size) i2 = size-1; - g_memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int)); + memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int)); g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL); result[i] = sortbuf[(i2-i1+1)/2]; } @@ -480,7 +480,7 @@ out: img->height = line_ind; img->width = ctx->line_width; img->flags = FP_IMG_V_FLIPPED; - g_memmove(img->data, output, ctx->line_width * line_ind); + memmove(img->data, output, ctx->line_width * line_ind); g_free(offsets); g_free(output); return img; From c11126181ea6f4f29e1937ff19f32dc1a3639f01 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 8 Aug 2019 14:17:15 +0200 Subject: [PATCH 46/50] aeslib: Fix use-after-free in aeslib If a USB transfer is started but not completed in one go, the wdata we pass to continue_write_regv() will already be freed by the time we try to use it again. Only free() the wdata on error, or when the USB transfer is completed. Closes: #180 --- libfprint/drivers/aeslib.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libfprint/drivers/aeslib.c b/libfprint/drivers/aeslib.c index 1ff3986d..24e307ce 100644 --- a/libfprint/drivers/aeslib.c +++ b/libfprint/drivers/aeslib.c @@ -53,12 +53,15 @@ static void write_regv_trf_complete(struct libusb_transfer *transfer) { struct write_regv_data *wdata = transfer->user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) + if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { wdata->callback(wdata->imgdev, -EIO, wdata->user_data); - else if (transfer->length != transfer->actual_length) + g_free(wdata); + } else if (transfer->length != transfer->actual_length) { wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data); - else + g_free(wdata); + } else { continue_write_regv(wdata); + } g_free(transfer->buffer); libusb_free_transfer(transfer); @@ -109,6 +112,7 @@ static void continue_write_regv(struct write_regv_data *wdata) if (offset >= wdata->num_regs) { fp_dbg("all registers written"); wdata->callback(wdata->imgdev, 0, wdata->user_data); + g_free(wdata); return; } if (wdata->regs[offset].reg) @@ -132,6 +136,7 @@ static void continue_write_regv(struct write_regv_data *wdata) r = do_write_regv(wdata, upper_bound); if (r < 0) { wdata->callback(wdata->imgdev, r, wdata->user_data); + g_free(wdata); return; } @@ -155,8 +160,6 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, wdata->callback = callback; wdata->user_data = user_data; continue_write_regv(wdata); - - g_free(wdata); } unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, From 50461b4d7d191c43c0a3dd707d93af4aaed4afa5 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 7 Aug 2019 17:26:40 +0200 Subject: [PATCH 47/50] lib: Make fp_async_*_stop() not throw warning if already in right state Make it possible to call fp_async_*_stop() multiple times without penalty. --- libfprint/fpi-async.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/libfprint/fpi-async.c b/libfprint/fpi-async.c index ddf5230b..6339c9ca 100644 --- a/libfprint/fpi-async.c +++ b/libfprint/fpi-async.c @@ -387,9 +387,21 @@ API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev, g_return_val_if_fail(dev != NULL, -ENODEV); + G_DEBUG_HERE(); + + if (dev->state == DEV_STATE_VERIFY_STOPPING) { + fp_dbg ("Already stopping verification, returning -EINPROGRESS"); + return -EINPROGRESS; + } + + if (dev->state == DEV_STATE_INITIALIZED) { + if (callback) + callback(dev, user_data); + return 0; + } + drv = dev->drv; - G_DEBUG_HERE(); BUG_ON(dev->state != DEV_STATE_ERROR && dev->state != DEV_STATE_VERIFYING && dev->state != DEV_STATE_VERIFY_DONE); @@ -511,9 +523,21 @@ API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev, g_return_val_if_fail(dev != NULL, -ENODEV); + G_DEBUG_HERE(); + + if (dev->state == DEV_STATE_IDENTIFY_STOPPING) { + fp_dbg ("Already stopping identification, returning -EINPROGRESS"); + return -EINPROGRESS; + } + + if (dev->state == DEV_STATE_INITIALIZED) { + if (callback) + callback(dev, user_data); + return 0; + } + drv = dev->drv; - G_DEBUG_HERE(); BUG_ON(dev->state != DEV_STATE_IDENTIFYING && dev->state != DEV_STATE_IDENTIFY_DONE); From 0e44eb4c1c371a8c15504e18c53b2b8d5397fd7d Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 8 Aug 2019 13:31:37 +0200 Subject: [PATCH 48/50] elan: Better debug when skipping commands --- libfprint/drivers/elan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 897f34f9..e9dad43e 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -424,7 +424,8 @@ elan_run_cmd(fpi_ssm *ssm, elandev->cmd_timeout = cmd_timeout; if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & elandev->dev_type)) { - fp_dbg("skipping for this device"); + fp_dbg("skipping command 0x%x 0x%x for this device (for devices 0x%x but device is 0x%x)", + cmd->cmd[0], cmd->cmd[1], cmd->devices, elandev->dev_type); elan_cmd_done(ssm); return; } From 19732341d6b0accddb87786858580eba3889e7ad Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 8 Aug 2019 13:42:31 +0200 Subject: [PATCH 49/50] lib: Fix overwriting action after deactivating callback If one of the callbacks called from fpi_imgdev_deactivate_complete() was reactivating the device, then we would be overwriting whichever "action" got set in the callback, leading to fpi_imgdev_activate_complete() failing as it doesn't handle the "none" action. Reset the action before calling the callbacks. --- libfprint/fpi-dev-img.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libfprint/fpi-dev-img.c b/libfprint/fpi-dev-img.c index a7c24104..b9d27831 100644 --- a/libfprint/fpi-dev-img.c +++ b/libfprint/fpi-dev-img.c @@ -485,9 +485,15 @@ void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status) */ void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev) { + enum fp_imgdev_action action; + G_DEBUG_HERE(); - switch (imgdev->action) { + action = imgdev->action; + imgdev->action = IMG_ACTION_NONE; + imgdev->action_state = 0; + + switch (action) { case IMG_ACTION_ENROLL: fpi_drvcb_enroll_stopped(FP_DEV(imgdev)); break; @@ -504,9 +510,6 @@ void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev) fp_err("unhandled action %d", imgdev->action); break; } - - imgdev->action = IMG_ACTION_NONE; - imgdev->action_state = 0; } int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev) From 823f2c1067a27deae4153dd9ece6ce24bedc0680 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 8 Aug 2019 14:40:30 +0200 Subject: [PATCH 50/50] 1.0 --- NEWS | 27 +++++++++++++++++++++++++++ meson.build | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 34d6cc2e..ba0ccc3d 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,33 @@ This file lists notable changes in each release. For the full history of all changes, see ChangeLog. +2019-08-08: v1.0 release +* Library: + - Add guards to the public API and require GLib 2.50 + - Deprecate print storage API + - Better documentation for fp_discover_devs() + - Remove unused internal fpi_timeout_cancel_for_dev() + - Remove state from fp_img_driver activate handler + - Bug fixes related to restarting a failed verification immediately + +* Drivers: + - The Elan driver received a lot of bug fixes including a fix for a + hang when verifying prints with fprintd, quirks for some devices, + a memory leak fix and support for 04f3:0c42 + - Fix a probable crash in all the AES drivers + - Add support for Lenovo Preferred Pro Keyboard (KUF1256) to vfs5011 + - Prevent hang during enroll process in etes603 driver + - Fix possible integer overflow in uru4000 + - Work-around SELinux AVC warnings when uru4000 driver starts + - Remove long-unmaintained and broken fdu2000 driver + +* Tools/Examples: + - Fix examples not working due to an overly strict check + - Fix crash in GTK demo when there's no supported devices + - Disable GTK demo until we have a USB Flatpak portal + - Remove sleep() in enroll example which caused a crash in some drivers + - Add a simple storage implementation example + 2018-12-14: v0.99.0 release * Library: - All the internal API for device driver writers is now covered by the diff --git a/meson.build b/meson.build index c925afcd..b7f7f315 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('libfprint', [ 'c', 'cpp' ], - version: '0.99.0', + version: '1.0', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized',