Commit e228f2c7 authored by Daniel Drake's avatar Daniel Drake

Introduce shared functions for authentec drivers

Currently provides register writing functionality only, more common ground
will be moved here soon.
parent 8e0e8e43
......@@ -56,6 +56,8 @@ libfprint_la_SOURCES = \
data.c \
img.c \
imgdev.c \
aeslib.c \
aeslib.h \
$(DRIVER_SRC) \
$(NBIS_SRC)
......
/*
* 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;
}
/*
* 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
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment