From de09730c59b970fe36ad60bd4893c4ab9f1e9c41 Mon Sep 17 00:00:00 2001 From: Juvenn Woo Date: Thu, 16 May 2013 18:25:10 +0800 Subject: [PATCH 1/2] aes3k: extract common routines aes3k from aes4000 --- configure.ac | 8 +++ libfprint/Makefile.am | 6 ++ libfprint/drivers/aes3k.c | 155 ++++++++++++++++++++++++++++++++++++++++++++ libfprint/drivers/aes3k.h | 58 +++++++++++++++++ libfprint/drivers/aes4000.c | 155 ++++++++++---------------------------------- 5 files changed, 261 insertions(+), 121 deletions(-) create mode 100644 libfprint/drivers/aes3k.c create mode 100644 libfprint/drivers/aes3k.h diff --git a/configure.ac b/configure.ac index b2ec4a7..b185d41 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,7 @@ all_drivers="upeke2 upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes16 require_imaging='no' require_aeslib='no' require_aesX660='no' +require_aes3k='no' enable_upeke2='no' enable_upekts='no' enable_upektc='no' @@ -115,6 +116,7 @@ for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do AC_DEFINE([ENABLE_AES4000], [], [Build AuthenTec AES4000 driver]) require_aeslib="yes" require_imaging="yes" + require_aes3k="yes" enable_aes4000="yes" ;; vfs101) @@ -143,6 +145,7 @@ AM_CONDITIONAL([ENABLE_AES2660], [test "$enable_aes2660" = "yes"]) AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" = "yes"]) AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" = "yes"]) AM_CONDITIONAL([REQUIRE_AESX660], [test "$require_aesX660" = "yes"]) +AM_CONDITIONAL([REQUIRE_AES3K], [test "$require_aes3k" = "yes"]) AM_CONDITIONAL([ENABLE_VFS101], [test "$enable_vfs101" = "yes"]) AM_CONDITIONAL([ENABLE_VFS301], [test "$enable_vfs301" = "yes"]) @@ -366,6 +369,11 @@ if test x$require_aesX660 != xno ; then else AC_MSG_NOTICE([ aesX660 common routines disabled]) fi +if test x$require_aes3k != xno ; then + AC_MSG_NOTICE([** aes3k common routines enabled]) +else + AC_MSG_NOTICE([ aes3k common routines disabled]) +fi AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile]) AC_OUTPUT diff --git a/libfprint/Makefile.am b/libfprint/Makefile.am index 7a16782..bac96fb 100644 --- a/libfprint/Makefile.am +++ b/libfprint/Makefile.am @@ -36,6 +36,8 @@ EXTRA_DIST = \ $(VFS301_SRC) \ drivers/aesx660.c \ drivers/aesx660.h \ + drivers/aes3k.c \ + drivers/aes3k.h \ drivers/driver_ids.h \ aeslib.c aeslib.h \ imagemagick.c \ @@ -177,6 +179,10 @@ if REQUIRE_AESX660 OTHER_SRC += drivers/aesx660.c drivers/aesx660.h endif +if REQUIRE_AES3K +OTHER_SRC += drivers/aes3k.c drivers/aes3k.h +endif + libfprint_la_SOURCES = \ fp_internal.h \ async.c \ diff --git a/libfprint/drivers/aes3k.c b/libfprint/drivers/aes3k.c new file mode 100644 index 0000000..fefba3c --- /dev/null +++ b/libfprint/drivers/aes3k.c @@ -0,0 +1,155 @@ +/* + * AuthenTec AES3500/AES4000 common routines + * + * The AES3500 and AES4000 sensors are press-typed, and could capture + * fingerprint images in 128x128 and 96x96 pixels respectively. They + * share a same communication interface: a number of frames are + * transferred and captured, from which a final image could be + * assembled. Each frame has fixed height of 16 pixels. + * + * As the imaging area is a bit small, only a part of finger could be + * captured, the detected minutiae are not so many that the NBIS + * matching works not so good. The verification rate is very low at the + * moment. + * + * This work is derived from Daniel Drake's AES4000 driver. + * + * Copyright (C) 2013 Juvenn Woo + * Copyright (C) 2007-2008 Daniel Drake + * + * 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 "aes3k" + +#include + +#include +#include + +#include +#include + +#include "aes3k.h" + +#define CTRL_TIMEOUT 1000 +#define EP_IN (1 | LIBUSB_ENDPOINT_IN) +#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) + +static void do_capture(struct fp_img_dev *dev); + +static void img_cb(struct libusb_transfer *transfer) +{ + struct fp_img_dev *dev = transfer->user_data; + struct aes3k_dev *aesdev = dev->priv; + unsigned char *ptr = transfer->buffer; + struct fp_img *tmp; + struct fp_img *img; + int i; + + if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { + goto err; + } else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { + fpi_imgdev_session_error(dev, -EIO); + goto err; + } else if (transfer->length != transfer->actual_length) { + fpi_imgdev_session_error(dev, -EPROTO); + goto err; + } + + fpi_imgdev_report_finger_status(dev, TRUE); + + tmp = fpi_img_new(aesdev->frame_width * aesdev->frame_width); + tmp->width = aesdev->frame_width; + tmp->height = aesdev->frame_width; + tmp->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; + for (i = 0; i < aesdev->frame_number; i++) { + fp_dbg("frame header byte %02x", *ptr); + ptr++; + aes_assemble_image(ptr, aesdev->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * aesdev->frame_width * AES3K_FRAME_HEIGHT)); + ptr += aesdev->frame_size; + } + + /* FIXME: this is an ugly hack to make the image big enough for NBIS + * to process reliably */ + img = fpi_im_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor); + fp_img_free(tmp); + fpi_imgdev_image_captured(dev, img); + + /* FIXME: rather than assuming finger has gone, we should poll regs until + * it really has, then restart the capture */ + fpi_imgdev_report_finger_status(dev, FALSE); + + do_capture(dev); + +err: + g_free(transfer->buffer); + aesdev->img_trf = NULL; + libusb_free_transfer(transfer); +} + +static void do_capture(struct fp_img_dev *dev) +{ + struct aes3k_dev *aesdev = dev->priv; + unsigned char *data; + int r; + + aesdev->img_trf = libusb_alloc_transfer(0); + if (!aesdev->img_trf) { + fpi_imgdev_session_error(dev, -EIO); + return; + } + + data = g_malloc(aesdev->data_buflen); + libusb_fill_bulk_transfer(aesdev->img_trf, dev->udev, EP_IN, data, + aesdev->data_buflen, img_cb, dev, 0); + + r = libusb_submit_transfer(aesdev->img_trf); + if (r < 0) { + g_free(data); + libusb_free_transfer(aesdev->img_trf); + aesdev->img_trf = NULL; + fpi_imgdev_session_error(dev, r); + } +} + +static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data) +{ + fpi_imgdev_activate_complete(dev, result); + if (result == 0) + do_capture(dev); +} + +int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) +{ + struct aes3k_dev *aesdev = dev->priv; + aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL); + return 0; +} + +void aes3k_dev_deactivate(struct fp_img_dev *dev) +{ + struct aes3k_dev *aesdev = dev->priv; + + /* FIXME: should wait for cancellation to complete before returning + * from deactivation, otherwise app may legally exit before we've + * cleaned up */ + if (aesdev->img_trf) + libusb_cancel_transfer(aesdev->img_trf); + fpi_imgdev_deactivate_complete(dev); +} + diff --git a/libfprint/drivers/aes3k.h b/libfprint/drivers/aes3k.h new file mode 100644 index 0000000..98750ed --- /dev/null +++ b/libfprint/drivers/aes3k.h @@ -0,0 +1,58 @@ +/* + * AuthenTec AES3500/AES4000 common routines + * + * The AES3500 and AES4000 sensors are press-typed, and could capture + * fingerprint images in 128x128 and 96x96 pixels respectively. They + * share a same communication interface: a number of frames are + * transferred and captured, from which a final image could be + * assembled. Each frame has fixed height of 16 pixels. + * + * As the imaging area is a bit small, only a part of finger could be + * captured, the detected minutiae are not so many that the NBIS + * matching works not so good. The verification rate is very low at the + * moment. + * + * This work is derived from Daniel Drake's AES4000 driver. + * + * Copyright (C) 2013 Juvenn Woo + * Copyright (C) 2007-2008 Daniel Drake + * + * 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 __AES3K_H +#define __AES3K_H + +#define AES3K_FRAME_HEIGHT 16 + +struct aes3k_dev { + struct libusb_transfer *img_trf; + size_t frame_width; /* image size = frame_width x frame_width */ + size_t frame_size; /* 4 bits/pixel: frame_width x AES3K_FRAME_HEIGHT / 2 */ + size_t frame_number; /* number of frames */ + size_t enlarge_factor; + + size_t data_buflen; /* buffer length of usb bulk transfer */ + struct aes_regwrite *init_reqs; /* initial values sent to device */ + size_t init_reqs_len; +}; + + +int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state); +void aes3k_dev_deactivate(struct fp_img_dev *dev); + +#endif diff --git a/libfprint/drivers/aes4000.c b/libfprint/drivers/aes4000.c index 6ff32a2..b849651 100644 --- a/libfprint/drivers/aes4000.c +++ b/libfprint/drivers/aes4000.c @@ -1,5 +1,12 @@ /* * AuthenTec AES4000 driver for libfprint + * + * AES4000 is a press-typed sensor, which captures image in 96x96 + * pixels. + * + * This work is derived from Daniel Drake's AES4000 driver. + * + * Copyright (C) 2013 Juvenn Woo * Copyright (C) 2007-2008 Daniel Drake * * This library is free software; you can redistribute it and/or @@ -27,24 +34,19 @@ #include #include +#include "aes3k.h" #include "driver_ids.h" -#define CTRL_TIMEOUT 1000 -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) -#define DATA_BUFLEN 0x1259 -#define NR_SUBARRAYS 6 -#define SUBARRAY_LEN 768 +#define DATA_BUFLEN 0x1259 -#define IMG_HEIGHT 96 -#define IMG_WIDTH 96 -#define ENLARGE_FACTOR 3 +/* image size = FRAME_WIDTH x FRAME_WIDTH */ +#define FRAME_WIDTH 96 +#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2) +#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT) +#define ENLARGE_FACTOR 3 -struct aes4k_dev { - struct libusb_transfer *img_trf; -}; -static const struct aes_regwrite init_reqs[] = { +static struct aes_regwrite init_reqs[] = { /* master reset */ { 0x80, 0x01 }, { 0, 0 }, @@ -119,119 +121,28 @@ static const struct aes_regwrite init_reqs[] = { { 0x81, 0x00 }, }; -static void do_capture(struct fp_img_dev *dev); - -static void img_cb(struct libusb_transfer *transfer) -{ - struct fp_img_dev *dev = transfer->user_data; - struct aes4k_dev *aesdev = dev->priv; - unsigned char *ptr = transfer->buffer; - struct fp_img *tmp; - struct fp_img *img; - int i; - - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - goto err; - } else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_imgdev_session_error(dev, -EIO); - goto err; - } else if (transfer->length != transfer->actual_length) { - fpi_imgdev_session_error(dev, -EPROTO); - goto err; - } - - fpi_imgdev_report_finger_status(dev, TRUE); - - tmp = fpi_img_new(IMG_WIDTH * IMG_HEIGHT); - tmp->width = IMG_WIDTH; - tmp->height = IMG_HEIGHT; - tmp->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - for (i = 0; i < NR_SUBARRAYS; i++) { - fp_dbg("subarray header byte %02x", *ptr); - ptr++; - aes_assemble_image(ptr, 96, 16, tmp->data + (i * 96 * 16)); - ptr += SUBARRAY_LEN; - } - - /* FIXME: this is an ugly hack to make the image big enough for NBIS - * to process reliably */ - img = fpi_im_resize(tmp, ENLARGE_FACTOR, ENLARGE_FACTOR); - fp_img_free(tmp); - fpi_imgdev_image_captured(dev, img); - - /* FIXME: rather than assuming finger has gone, we should poll regs until - * it really has, then restart the capture */ - fpi_imgdev_report_finger_status(dev, FALSE); - - do_capture(dev); - -err: - g_free(transfer->buffer); - aesdev->img_trf = NULL; - libusb_free_transfer(transfer); -} - -static void do_capture(struct fp_img_dev *dev) -{ - struct aes4k_dev *aesdev = dev->priv; - unsigned char *data; - int r; - - aesdev->img_trf = libusb_alloc_transfer(0); - if (!aesdev->img_trf) { - fpi_imgdev_session_error(dev, -EIO); - return; - } - - data = g_malloc(DATA_BUFLEN); - libusb_fill_bulk_transfer(aesdev->img_trf, dev->udev, EP_IN, data, - DATA_BUFLEN, img_cb, dev, 0); - - r = libusb_submit_transfer(aesdev->img_trf); - if (r < 0) { - g_free(data); - libusb_free_transfer(aesdev->img_trf); - aesdev->img_trf = NULL; - fpi_imgdev_session_error(dev, r); - } -} - -static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data) -{ - fpi_imgdev_activate_complete(dev, result); - if (result == 0) - do_capture(dev); -} - -static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) -{ - aes_write_regv(dev, init_reqs, G_N_ELEMENTS(init_reqs), init_reqs_cb, NULL); - return 0; -} - -static void dev_deactivate(struct fp_img_dev *dev) -{ - struct aes4k_dev *aesdev = dev->priv; - - /* FIXME: should wait for cancellation to complete before returning - * from deactivation, otherwise app may legally exit before we've - * cleaned up */ - if (aesdev->img_trf) - libusb_cancel_transfer(aesdev->img_trf); - fpi_imgdev_deactivate_complete(dev); -} - static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) { int r; + struct aes3k_dev *aesdev; r = libusb_claim_interface(dev->udev, 0); if (r < 0) fp_err("could not claim interface 0"); - dev->priv = g_malloc0(sizeof(struct aes4k_dev)); + aesdev = dev->priv = g_malloc0(sizeof(struct aes3k_dev)); + + if (!aesdev) + return -ENOMEM; if (r == 0) + aesdev->data_buflen = DATA_BUFLEN; + aesdev->frame_width = FRAME_WIDTH; + aesdev->frame_size = FRAME_SIZE; + aesdev->frame_number = FRAME_NUMBER; + aesdev->enlarge_factor = ENLARGE_FACTOR; + aesdev->init_reqs = init_reqs; + aesdev->init_reqs_len = G_N_ELEMENTS(init_reqs); fpi_imgdev_open_complete(dev, 0); return r; @@ -239,11 +150,13 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) static void dev_deinit(struct fp_img_dev *dev) { - g_free(dev->priv); + struct aes3k_dev *aesdev = dev->priv; + g_free(aesdev); libusb_release_interface(dev->udev, 0); fpi_imgdev_close_complete(dev); } + static const struct usb_id id_table[] = { { .vendor = 0x08ff, .product = 0x5501 }, { 0, 0, 0, }, @@ -258,15 +171,15 @@ struct fp_img_driver aes4000_driver = { .scan_type = FP_SCAN_TYPE_PRESS, }, .flags = 0, - .img_height = IMG_HEIGHT * ENLARGE_FACTOR, - .img_width = IMG_WIDTH * ENLARGE_FACTOR, + .img_height = FRAME_WIDTH * ENLARGE_FACTOR, + .img_width = FRAME_WIDTH * ENLARGE_FACTOR, /* temporarily lowered until image quality improves */ .bz3_threshold = 9, .open = dev_init, .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, + .activate = aes3k_dev_activate, + .deactivate = aes3k_dev_deactivate, }; -- 1.8.2.3