libfprint/libfprint/drivers/aeslib.c

170 lines
4.9 KiB
C
Raw Normal View History

/*
* Shared functions between libfprint Authentec drivers
2008-02-10 18:35:19 +00:00
* 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 "aeslib"
#include "drivers_api.h"
#include <errno.h>
#include <string.h>
#include "aeslib.h"
2019-11-19 20:13:11 +00:00
#define MAX_REGWRITES_PER_REQUEST 16
#define BULK_TIMEOUT 4000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
struct write_regv_data
{
unsigned int num_regs;
const struct aes_regwrite *regs;
unsigned int offset;
aes_write_regv_cb callback;
void *user_data;
2008-02-10 18:35:19 +00:00
};
2019-11-19 20:13:11 +00:00
static void continue_write_regv (FpImageDevice *dev,
struct write_regv_data *wdata);
2008-02-10 18:35:19 +00:00
/* libusb bulk callback for regv write completion transfer. continues the
* transaction */
2019-11-19 20:13:11 +00:00
static void
write_regv_trf_complete (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
2019-11-19 20:13:11 +00:00
struct write_regv_data *wdata = user_data;
if (error)
{
wdata->callback (FP_IMAGE_DEVICE (device), error, wdata->user_data);
g_free (wdata);
}
else
{
continue_write_regv (FP_IMAGE_DEVICE (device), wdata);
}
2008-02-10 18:35:19 +00:00
}
/* write from wdata->offset to upper_bound (inclusive) of wdata->regs */
2019-11-19 20:13:11 +00:00
static void
do_write_regv (FpImageDevice *dev, struct write_regv_data *wdata, int upper_bound)
2008-02-10 18:35:19 +00:00
{
2019-11-19 20:13:11 +00:00
unsigned int offset = wdata->offset;
unsigned int num = upper_bound - offset + 1;
size_t alloc_size = num * 2;
unsigned int i;
size_t data_offset = 0;
FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk (transfer, EP_OUT, alloc_size);
for (i = offset; i < offset + num; i++)
{
const struct aes_regwrite *regwrite = &wdata->regs[i];
transfer->buffer[data_offset++] = regwrite->reg;
transfer->buffer[data_offset++] = regwrite->value;
}
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_regv_trf_complete, wdata);
}
2008-02-10 18:35:19 +00:00
/* write the next batch of registers to be written, or if there are no more,
* indicate completion to the caller */
2019-11-19 20:13:11 +00:00
static void
continue_write_regv (FpImageDevice *dev, struct write_regv_data *wdata)
{
2019-11-19 20:13:11 +00:00
unsigned int offset = wdata->offset;
unsigned int regs_remaining;
unsigned int limit;
unsigned int upper_bound;
int i;
/* skip all zeros and ensure there is still work to do */
while (TRUE)
{
if (offset >= wdata->num_regs)
{
fp_dbg ("all registers written");
wdata->callback (dev, 0, wdata->user_data);
g_free (wdata);
return;
}
if (wdata->regs[offset].reg)
break;
offset++;
}
wdata->offset = offset;
regs_remaining = wdata->num_regs - offset;
limit = MIN (regs_remaining, MAX_REGWRITES_PER_REQUEST);
upper_bound = offset + limit - 1;
/* determine if we can write the entire of the regs at once, or if there
* is a zero dividing things up */
for (i = offset; i <= upper_bound; i++)
if (!wdata->regs[i].reg)
{
upper_bound = i - 1;
break;
}
do_write_regv (dev, wdata, upper_bound);
wdata->offset = upper_bound + 1;
2008-02-10 18:35:19 +00:00
}
/* write a load of registers to the device, combining multiple writes in a
* single URB up to a limit. insert writes to non-existent register 0 to force
* specific groups of writes to be separated by different URBs. */
2019-11-19 20:13:11 +00:00
void
aes_write_regv (FpImageDevice *dev, const struct aes_regwrite *regs,
unsigned int num_regs, aes_write_regv_cb callback,
void *user_data)
2008-02-10 18:35:19 +00:00
{
2019-11-19 20:13:11 +00:00
struct write_regv_data *wdata;
fp_dbg ("write %d regs", num_regs);
wdata = g_malloc (sizeof (*wdata));
wdata->num_regs = num_regs;
wdata->regs = regs;
wdata->offset = 0;
wdata->callback = callback;
wdata->user_data = user_data;
continue_write_regv (dev, wdata);
}
2019-11-19 20:13:11 +00:00
unsigned char
aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned int x,
unsigned int y)
{
2019-11-19 20:13:11 +00:00
unsigned char ret;
2019-11-19 20:13:11 +00:00
ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)];
ret = y % 2 ? ret >> 4 : ret & 0xf;
ret *= 17;
2019-11-19 20:13:11 +00:00
return ret;
}