Introduce shared functions for authentec drivers

Currently provides register writing functionality only, more common ground
will be moved here soon.
This commit is contained in:
Daniel Drake 2007-11-20 12:23:27 +00:00
parent 8e0e8e4386
commit e228f2c7da
6 changed files with 183 additions and 189 deletions

View file

@ -56,6 +56,8 @@ libfprint_la_SOURCES = \
data.c \
img.c \
imgdev.c \
aeslib.c \
aeslib.h \
$(DRIVER_SRC) \
$(NBIS_SRC)

95
libfprint/aeslib.c Normal file
View file

@ -0,0 +1,95 @@
/*
* Shared functions between libfprint Authentec drivers
* Copyright (C) 2007 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 <errno.h>
#include <glib.h>
#include "fp_internal.h"
#include "aeslib.h"
#define MAX_REGWRITES_PER_REQUEST 16
#define BULK_TIMEOUT 4000
#define EP_IN (1 | USB_ENDPOINT_IN)
#define EP_OUT (2 | USB_ENDPOINT_OUT)
static int do_write_regv(struct fp_img_dev *dev, struct aes_regwrite *regs,
unsigned int num)
{
size_t alloc_size = num * 2;
unsigned char *data = g_malloc(alloc_size);
unsigned int i;
size_t offset = 0;
int r;
for (i = 0; i < num; i++) {
data[offset++] = regs[i].reg;
data[offset++] = regs[i].value;
}
r = usb_bulk_write(dev->udev, EP_OUT, data, alloc_size, BULK_TIMEOUT);
g_free(data);
if (r < 0) {
fp_err("bulk write error %d", r);
return r;
} else if ((unsigned int) r < alloc_size) {
fp_err("unexpected short write %d/%d", r, alloc_size);
return -EIO;
}
return 0;
}
int aes_write_regv(struct fp_img_dev *dev, struct aes_regwrite *regs,
unsigned int num)
{
unsigned int i;
int skip = 0;
int add_offset = 0;
fp_dbg("write %d regs", num);
for (i = 0; i < num; i += add_offset + skip) {
int r, j;
int limit = MIN(num, i + MAX_REGWRITES_PER_REQUEST);
skip = 0;
if (!regs[i].reg) {
add_offset = 0;
skip = 1;
continue;
}
for (j = i; j < limit; j++)
if (!regs[j].reg) {
skip = 1;
break;
}
add_offset = j - i;
r = do_write_regv(dev, &regs[i], add_offset);
if (r < 0)
return r;
}
return 0;
}

34
libfprint/aeslib.h Normal file
View file

@ -0,0 +1,34 @@
/*
* Shared functions between libfprint Authentec drivers
* Copyright (C) 2007 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
*/
#ifndef __AESLIB_H__
#define __AESLIB_H__
#include <fp_internal.h>
struct aes_regwrite {
unsigned char reg;
unsigned char value;
};
int aes_write_regv(struct fp_img_dev *dev, struct aes_regwrite *regs,
unsigned int num);
#endif

View file

@ -29,6 +29,7 @@
#include <usb.h>
#include <aeslib.h>
#include <fp_internal.h>
/* FIXME these need checking */
@ -36,7 +37,6 @@
#define EP_OUT (2 | USB_ENDPOINT_OUT)
#define BULK_TIMEOUT 4000
#define MAX_REGWRITES_PER_REQUEST 16
#define FIRST_AES1610_REG 0x1B
#define LAST_AES1610_REG 0xFF
@ -60,66 +60,6 @@
/* FIXME reduce substantially */
#define MAX_FRAMES 350
struct aes1610_regwrite {
unsigned char reg;
unsigned char value;
};
static int do_write_regv(struct fp_img_dev *dev, const struct aes1610_regwrite *regs,
unsigned int num)
{
size_t alloc_size = num * 2;
unsigned char *data = g_malloc(alloc_size);
unsigned int i;
size_t offset = 0;
int r;
for (i = 0; i < num; i++) {
data[offset++] = regs[i].reg;
data[offset++] = regs[i].value;
}
r = usb_bulk_write(dev->udev, EP_OUT, data, alloc_size, BULK_TIMEOUT);
g_free(data);
if (r < 0) {
fp_err("bulk write error %d", r);
return r;
} else if (r < (int) alloc_size) {
fp_err("unexpected short write %d/%d", r, alloc_size);
return -EIO;
}
return 0;
}
static int write_regv(struct fp_img_dev *dev, const struct aes1610_regwrite *regs,
unsigned int num)
{
unsigned int i;
int skip = 0;
int add_offset = 0;
fp_dbg("write %d regs", num);
for (i = 0; i < num; i += add_offset + skip) {
int r, j;
int limit = MIN(num, i + MAX_REGWRITES_PER_REQUEST);
skip = 0;
for (j = i; j < limit; j++)
if (!regs[j].reg) {
skip = 1;
break;
}
add_offset = j - i;
r = do_write_regv(dev, &regs[i], add_offset);
if (r < 0)
return r;
}
return 0;
}
static int read_data(struct fp_img_dev *dev, unsigned char *data, size_t len)
{
int r;
@ -136,19 +76,14 @@ static int read_data(struct fp_img_dev *dev, unsigned char *data, size_t len)
return 0;
}
static const struct aes1610_regwrite init[] = {
static const struct aes_regwrite init[] = {
{ 0x82, 0x00 }
};
static const struct aes1610_regwrite stop_reader[] = {
static const struct aes_regwrite stop_reader[] = {
{ 0xFF, 0x00 }
};
static int do_init(struct fp_img_dev *dev)
{
return write_regv(dev, init, G_N_ELEMENTS(init));
}
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
int r;
@ -161,12 +96,12 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
/* FIXME check endpoints */
return do_init(dev);
return aes_write_regv(dev, init, G_N_ELEMENTS(init));
}
static int do_exit(struct fp_img_dev *dev)
{
return write_regv(dev, stop_reader, G_N_ELEMENTS(stop_reader));
return aes_write_regv(dev, stop_reader, G_N_ELEMENTS(stop_reader));
}
static void dev_exit(struct fp_img_dev *dev)
@ -175,7 +110,7 @@ static void dev_exit(struct fp_img_dev *dev)
usb_release_interface(dev->udev, 0);
}
static const struct aes1610_regwrite finger_det_reqs[] = {
static const struct aes_regwrite finger_det_reqs[] = {
{ 0x80, 0x01 },
{ 0x80, 0x12 },
{ 0x85, 0x00 },
@ -200,7 +135,7 @@ static const struct aes1610_regwrite finger_det_reqs[] = {
{ 0x81, 0x04 }
};
static const struct aes1610_regwrite finger_det_none[] = {
static const struct aes_regwrite finger_det_none[] = {
{ 0x80, 0x01 },
{ 0x82, 0x00 },
{ 0x86, 0x00 },
@ -215,7 +150,7 @@ static int detect_finger(struct fp_img_dev *dev)
int i;
int sum = 0;
r = write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs));
r = aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs));
if (r < 0)
return r;
@ -228,7 +163,7 @@ static int detect_finger(struct fp_img_dev *dev)
/* We need to answer something if no finger has been detected */
if (sum <= 20) {
r = write_regv(dev, finger_det_none, G_N_ELEMENTS(finger_det_none));
r = aes_write_regv(dev, finger_det_none, G_N_ELEMENTS(finger_det_none));
if (r < 0)
return r;
}
@ -327,7 +262,7 @@ static unsigned int assemble(unsigned char *input, unsigned char *output,
return image_height;
}
static const struct aes1610_regwrite capture_reqs[] = {
static const struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x01 },
{ 0x80, 0x12 },
{ 0x84, 0x01 },
@ -453,7 +388,7 @@ static const struct aes1610_regwrite capture_reqs[] = {
{ 0x81, 0x01 }
};
static const struct aes1610_regwrite strip_scan_reqs[] = {
static const struct aes_regwrite strip_scan_reqs[] = {
{ 0xBE, 0x23 },
{ 0x29, 0x06 },
{ 0x2A, 0x35 },
@ -461,7 +396,7 @@ static const struct aes1610_regwrite strip_scan_reqs[] = {
{ 0xFF, 0x00 }
};
static const struct aes1610_regwrite capture_stop[] = {
static const struct aes_regwrite capture_stop[] = {
{ 0x81,0x00 }
};
@ -482,7 +417,7 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
/* FIXME can do better here in terms of buffer management? */
fp_dbg("");
r = write_regv(dev, capture_reqs, G_N_ELEMENTS(capture_reqs));
r = aes_write_regv(dev, capture_reqs, G_N_ELEMENTS(capture_reqs));
if (r < 0)
return r;
@ -507,7 +442,7 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
/* we start at 2 because we captured 2 frames above. the above captures
* should possibly be moved into the loop below, or discarded altogether */
for (nstrips = 2; nstrips < MAX_FRAMES - 2; nstrips++) {
r = write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs));
r = aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs));
if (r < 0)
goto err;
r = read_data(dev, buf, 665);
@ -544,7 +479,7 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
break;
}
r = write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop));
r = aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop));
if (r < 0)
goto err;
r = read_data(dev, buf, 665);

View file

@ -28,6 +28,7 @@
#include <usb.h>
#include <aeslib.h>
#include <fp_internal.h>
#include "aes2501.h"
@ -36,7 +37,6 @@
#define EP_OUT (2 | USB_ENDPOINT_OUT)
#define BULK_TIMEOUT 4000
#define MAX_REGWRITES_PER_REQUEST 16
/*
* The AES2501 is an imaging device using a swipe-type sensor. It samples
@ -57,66 +57,6 @@
/* FIXME reduce substantially */
#define MAX_FRAMES 150
struct aes2501_regwrite {
unsigned char reg;
unsigned char value;
};
static int do_write_regv(struct fp_img_dev *dev, struct aes2501_regwrite *regs,
unsigned int num)
{
size_t alloc_size = num * 2;
unsigned char *data = g_malloc(alloc_size);
unsigned int i;
size_t offset = 0;
int r;
for (i = 0; i < num; i++) {
data[offset++] = regs[i].reg;
data[offset++] = regs[i].value;
}
r = usb_bulk_write(dev->udev, EP_OUT, data, alloc_size, BULK_TIMEOUT);
g_free(data);
if (r < 0) {
fp_err("bulk write error %d", r);
return r;
} else if (r < alloc_size) {
fp_err("unexpected short write %d/%d", r, alloc_size);
return -EIO;
}
return 0;
}
static int write_regv(struct fp_img_dev *dev, struct aes2501_regwrite *regs,
unsigned int num)
{
unsigned int i;
int skip = 0;
int add_offset = 0;
fp_dbg("write %d regs", num);
for (i = 0; i < num; i += add_offset + skip) {
int r, j;
int limit = MIN(num, i + MAX_REGWRITES_PER_REQUEST);
skip = 0;
for (j = i; j < limit; j++)
if (!regs[j].reg) {
skip = 1;
break;
}
add_offset = j - i;
r = do_write_regv(dev, &regs[i], add_offset);
if (r < 0)
return r;
}
return 0;
}
static int read_data(struct fp_img_dev *dev, unsigned char *data, size_t len)
{
int r;
@ -136,20 +76,20 @@ static int read_data(struct fp_img_dev *dev, unsigned char *data, size_t len)
static int read_regs(struct fp_img_dev *dev, unsigned char *data)
{
int r;
const struct aes2501_regwrite regwrite = {
const struct aes_regwrite regwrite = {
AES2501_REG_CTRL2, AES2501_CTRL2_READ_REGS
};
fp_dbg("");
r = write_regv(dev, &regwrite, 1);
r = aes_write_regv(dev, &regwrite, 1);
if (r < 0)
return r;
return read_data(dev, data, 126);
}
static const struct aes2501_regwrite init_1[] = {
static const struct aes_regwrite init_1[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ 0, 0 },
{ 0xb0, 0x27 }, /* Reserved? */
@ -193,7 +133,7 @@ static const struct aes2501_regwrite init_1[] = {
{ AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE },
};
static const struct aes2501_regwrite init_2[] = {
static const struct aes_regwrite init_2[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ AES2501_REG_EXCITCTRL, 0x40 },
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
@ -203,7 +143,7 @@ static const struct aes2501_regwrite init_2[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE },
};
static const struct aes2501_regwrite init_3[] = {
static const struct aes_regwrite init_3[] = {
{ 0xff, 0x00 },
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ AES2501_REG_AUTOCALOFFSET, 0x41 },
@ -212,7 +152,7 @@ static const struct aes2501_regwrite init_3[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE },
};
static const struct aes2501_regwrite init_4[] = {
static const struct aes_regwrite init_4[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ AES2501_REG_EXCITCTRL, 0x40 },
{ 0xb0, 0x27 },
@ -222,7 +162,7 @@ static const struct aes2501_regwrite init_4[] = {
{ AES2501_REG_AUTOCALOFFSET, 0x41 },
};
static const struct aes2501_regwrite init_5[] = {
static const struct aes_regwrite init_5[] = {
{ 0xb0, 0x27 },
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ AES2501_REG_EXCITCTRL, 0x40 },
@ -248,7 +188,7 @@ static int do_init(struct fp_img_dev *dev)
int i;
/* part 1, probably not needed */
r = write_regv(dev, init_1, G_N_ELEMENTS(init_1));
r = aes_write_regv(dev, init_1, G_N_ELEMENTS(init_1));
if (r < 0)
return r;
@ -257,7 +197,7 @@ static int do_init(struct fp_img_dev *dev)
return r;
/* part 2 */
r = write_regv(dev, init_2, G_N_ELEMENTS(init_2));
r = aes_write_regv(dev, init_2, G_N_ELEMENTS(init_2));
if (r < 0)
return r;
@ -269,7 +209,7 @@ static int do_init(struct fp_img_dev *dev)
fp_dbg("reg 0xaf = %x", buffer[0x5f]);
i = 0;
while (buffer[0x5f] == 0x6b) {
r = write_regv(dev, init_3, G_N_ELEMENTS(init_3));
r = aes_write_regv(dev, init_3, G_N_ELEMENTS(init_3));
if (r < 0)
return r;
r = read_regs(dev, buffer);
@ -280,12 +220,12 @@ static int do_init(struct fp_img_dev *dev)
}
/* part 4 */
r = write_regv(dev, init_4, G_N_ELEMENTS(init_4));
r = aes_write_regv(dev, init_4, G_N_ELEMENTS(init_4));
if (r < 0)
return r;
/* part 5 */
return write_regv(dev, init_5, G_N_ELEMENTS(init_5));
return aes_write_regv(dev, init_5, G_N_ELEMENTS(init_5));
}
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
@ -308,7 +248,7 @@ static void dev_exit(struct fp_img_dev *dev)
usb_release_interface(dev->udev, 0);
}
static const struct aes2501_regwrite finger_det_reqs[] = {
static const struct aes_regwrite finger_det_reqs[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ AES2501_REG_EXCITCTRL, 0x40 },
{ AES2501_REG_DETCTRL,
@ -343,7 +283,7 @@ static int detect_finger(struct fp_img_dev *dev)
int i;
int sum = 0;
r = write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs));
r = aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs));
if (r < 0)
return r;
@ -485,7 +425,7 @@ static unsigned int assemble(unsigned char *input, unsigned char *output,
return image_height;
}
static const struct aes2501_regwrite capture_reqs_1[] = {
static const struct aes_regwrite capture_reqs_1[] = {
{ AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET },
{ 0, 0 },
{ AES2501_REG_EXCITCTRL, 0x40 },
@ -519,7 +459,7 @@ static const struct aes2501_regwrite capture_reqs_1[] = {
{ AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE },
};
static const struct aes2501_regwrite capture_reqs_2[] = {
static const struct aes_regwrite capture_reqs_2[] = {
{ AES2501_REG_IMAGCTRL,
AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE |
AES2501_IMAGCTRL_IMG_DATA_DISABLE },
@ -531,7 +471,7 @@ static const struct aes2501_regwrite capture_reqs_2[] = {
{ AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT },
};
static const struct aes2501_regwrite strip_scan_reqs[] = {
static const struct aes_regwrite strip_scan_reqs[] = {
{ AES2501_REG_IMAGCTRL,
AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE },
{ AES2501_REG_STRTCOL, 0x00 },
@ -558,7 +498,7 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
/* FIXME can do better here in terms of buffer management? */
fp_dbg("");
r = write_regv(dev, capture_reqs_1, G_N_ELEMENTS(capture_reqs_1));
r = aes_write_regv(dev, capture_reqs_1, G_N_ELEMENTS(capture_reqs_1));
if (r < 0)
return r;
@ -566,7 +506,7 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
if (r < 0)
return r;
r = write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2));
r = aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2));
if (r < 0)
return r;
@ -583,7 +523,7 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
for (nstrips = 0; nstrips < MAX_FRAMES; nstrips++) {
int threshold;
r = write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs));
r = aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs));
if (r < 0)
goto err;
r = read_data(dev, buf, 1705);

View file

@ -24,6 +24,7 @@
#include <glib.h>
#include <usb.h>
#include <aeslib.h>
#include <fp_internal.h>
#define CTRL_TIMEOUT 1000
@ -33,25 +34,6 @@
#define NR_SUBARRAYS 6
#define SUBARRAY_LEN 768
static int write_reg(struct fp_img_dev *dev, unsigned char reg,
unsigned char value)
{
unsigned char data[] = { reg, value };
int r;
fp_dbg("%02x=%02x", reg, value);
r = usb_bulk_write(dev->udev, EP_OUT, data, sizeof(data), CTRL_TIMEOUT);
if (r < 0) {
fp_err("bulk write error %d", r);
return r;
} else if (r < sizeof(data)) {
fp_err("unexpected short write %d/%d", r, sizeof(data));
return -EIO;
}
return 0;
}
static void process_subarray(unsigned char *src, unsigned char *dst)
{
int col, row;
@ -66,26 +48,31 @@ static void process_subarray(unsigned char *src, unsigned char *dst)
}
}
static const struct aes4000_regwrite {
unsigned char reg;
unsigned char value;
} init_reqs[] = {
static const struct aes_regwrite init_reqs[] = {
/* master reset */
{ 0x80, 0x01 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0, 0 },
/* scan reset */
{ 0x80, 0x02 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* disable register buffering */
{ 0x80, 0x04 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0, 0 },
/* windows driver reads registers now (81 02) */
{ 0x80, 0x00 },
{ 0x81, 0x00 },
@ -126,10 +113,13 @@ static const struct aes4000_regwrite {
{ 0x9d, 0x09 }, /* set some challenge word bits */
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
{ 0x81, 0x04 },
{ 0, 0 },
{ 0x81, 0x00 },
};
@ -142,11 +132,9 @@ static int capture(struct fp_img_dev *dev, gboolean unconditional,
unsigned char *data;
unsigned char *ptr;
for (i = 0; i < G_N_ELEMENTS(init_reqs); i++) {
r = write_reg(dev, init_reqs[i].reg, init_reqs[i].value);
if (r < 0)
return r;
}
r = aes_write_regv(dev, init_reqs, G_N_ELEMENTS(init_reqs));
if (r < 0)
return r;
img = fpi_img_new_for_imgdev(dev);
data = g_malloc(DATA_BUFLEN);