2642fc6560
When a transfer is completed, we automatically unref it since we can't consider it valid anymore since this point. Update the drivers not to free the transfer after submitting anymore.
227 lines
6.7 KiB
C
227 lines
6.7 KiB
C
/*
|
|
* 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 <machese@gmail.com>
|
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
|
*
|
|
* 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 "drivers_api.h"
|
|
#include "aeslib.h"
|
|
#include "aes3k.h"
|
|
|
|
typedef struct
|
|
{
|
|
FpiUsbTransfer *img_trf;
|
|
gboolean deactivating;
|
|
} FpiDeviceAes3kPrivate;
|
|
|
|
#define CTRL_TIMEOUT 1000
|
|
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
|
|
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
|
|
|
|
static void do_capture (FpImageDevice *dev);
|
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAes3k, fpi_device_aes3k, FP_TYPE_IMAGE_DEVICE);
|
|
|
|
static void
|
|
aes3k_assemble_image (unsigned char *input, size_t width, size_t height,
|
|
unsigned char *output)
|
|
{
|
|
size_t row, column;
|
|
|
|
for (column = 0; column < width; column++)
|
|
{
|
|
for (row = 0; row < height; row += 2)
|
|
{
|
|
output[width * row + column] = (*input & 0x0f) * 17;
|
|
output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
|
|
input++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
img_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|
gpointer user_data, GError *error)
|
|
{
|
|
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
|
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (device);
|
|
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
|
|
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
|
|
unsigned char *ptr = transfer->buffer;
|
|
FpImage *tmp;
|
|
FpImage *img;
|
|
int i;
|
|
|
|
priv->img_trf = NULL;
|
|
|
|
if (error)
|
|
{
|
|
if (g_error_matches (error,
|
|
G_IO_ERROR,
|
|
G_IO_ERROR_CANCELLED))
|
|
{
|
|
/* Deactivation was completed. */
|
|
g_error_free (error);
|
|
if (priv->deactivating)
|
|
fpi_image_device_deactivate_complete (dev, NULL);
|
|
return;
|
|
}
|
|
|
|
fpi_image_device_session_error (dev, error);
|
|
}
|
|
|
|
fpi_image_device_report_finger_status (dev, TRUE);
|
|
|
|
tmp = fp_image_new (cls->frame_width, cls->frame_width);
|
|
tmp->width = cls->frame_width;
|
|
tmp->height = cls->frame_width;
|
|
tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
|
|
for (i = 0; i < cls->frame_number; i++)
|
|
{
|
|
fp_dbg ("frame header byte %02x", *ptr);
|
|
ptr++;
|
|
aes3k_assemble_image (ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT));
|
|
ptr += cls->frame_size;
|
|
}
|
|
|
|
/* FIXME: this is an ugly hack to make the image big enough for NBIS
|
|
* to process reliably */
|
|
img = fpi_image_resize (tmp, cls->enlarge_factor, cls->enlarge_factor);
|
|
g_object_unref (tmp);
|
|
fpi_image_device_image_captured (dev, img);
|
|
|
|
/* FIXME: rather than assuming finger has gone, we should poll regs until
|
|
* it really has, then restart the capture */
|
|
fpi_image_device_report_finger_status (dev, FALSE);
|
|
|
|
do_capture (dev);
|
|
}
|
|
|
|
static void
|
|
do_capture (FpImageDevice *dev)
|
|
{
|
|
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
|
|
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
|
|
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
|
|
|
|
priv->img_trf = fpi_usb_transfer_new (FP_DEVICE (dev));
|
|
fpi_usb_transfer_fill_bulk (priv->img_trf, EP_IN, cls->data_buflen);
|
|
priv->img_trf->short_is_error = TRUE;
|
|
fpi_usb_transfer_submit (priv->img_trf, 0,
|
|
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
img_cb, NULL);
|
|
}
|
|
|
|
static void
|
|
init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
|
|
{
|
|
fpi_image_device_activate_complete (dev, result);
|
|
if (!result)
|
|
do_capture (dev);
|
|
}
|
|
|
|
static void
|
|
aes3k_dev_activate (FpImageDevice *dev)
|
|
{
|
|
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
|
|
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
|
|
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
|
|
|
|
priv->deactivating = FALSE;
|
|
aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
|
|
}
|
|
|
|
static void
|
|
aes3k_dev_deactivate (FpImageDevice *dev)
|
|
{
|
|
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
|
|
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
|
|
|
|
priv->deactivating = TRUE;
|
|
if (priv->img_trf)
|
|
return;
|
|
fpi_image_device_deactivate_complete (dev, NULL);
|
|
}
|
|
|
|
static void
|
|
fpi_device_aes3k_init (FpiDeviceAes3k *self)
|
|
{
|
|
}
|
|
|
|
static void
|
|
aes3k_dev_init (FpImageDevice *dev)
|
|
{
|
|
GError *error = NULL;
|
|
|
|
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error))
|
|
{
|
|
fpi_image_device_open_complete (dev, error);
|
|
return;
|
|
}
|
|
|
|
fpi_image_device_open_complete (dev, NULL);
|
|
}
|
|
|
|
static void
|
|
aes3k_dev_deinit (FpImageDevice *dev)
|
|
{
|
|
GError *error = NULL;
|
|
|
|
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
|
0, 0, &error);
|
|
fpi_image_device_close_complete (dev, error);
|
|
}
|
|
|
|
|
|
static void
|
|
fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass)
|
|
{
|
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
|
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
|
|
|
dev_class->type = FP_DEVICE_TYPE_USB;
|
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
|
|
|
img_class->img_open = aes3k_dev_init;
|
|
img_class->img_close = aes3k_dev_deinit;
|
|
img_class->activate = aes3k_dev_activate;
|
|
img_class->deactivate = aes3k_dev_deactivate;
|
|
|
|
/* Extremely low due to low image quality. */
|
|
img_class->bz3_threshold = 9;
|
|
|
|
/* Everything else is set by the subclasses. */
|
|
}
|