diff --git a/libfprint/Makefile.am b/libfprint/Makefile.am index 549deff..3e2702f 100644 --- a/libfprint/Makefile.am +++ b/libfprint/Makefile.am @@ -56,6 +56,8 @@ libfprint_la_SOURCES = \ data.c \ img.c \ imgdev.c \ + aeslib.c \ + aeslib.h \ $(DRIVER_SRC) \ $(NBIS_SRC) diff --git a/libfprint/aeslib.c b/libfprint/aeslib.c new file mode 100644 index 0000000..e93e06f --- /dev/null +++ b/libfprint/aeslib.c @@ -0,0 +1,95 @@ +/* + * Shared functions between libfprint Authentec drivers + * Copyright (C) 2007 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 "aeslib" + +#include + +#include + +#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, ®s[i], add_offset); + if (r < 0) + return r; + } + + return 0; +} + diff --git a/libfprint/aeslib.h b/libfprint/aeslib.h new file mode 100644 index 0000000..19b6cc6 --- /dev/null +++ b/libfprint/aeslib.h @@ -0,0 +1,34 @@ +/* + * Shared functions between libfprint Authentec drivers + * Copyright (C) 2007 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 __AESLIB_H__ +#define __AESLIB_H__ + +#include + +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 + diff --git a/libfprint/drivers/aes1610.c b/libfprint/drivers/aes1610.c index bf42e98..5bc4d80 100644 --- a/libfprint/drivers/aes1610.c +++ b/libfprint/drivers/aes1610.c @@ -29,6 +29,7 @@ #include +#include #include /* 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, ®s[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); diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index 0c8515a..2abfa4e 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -28,6 +28,7 @@ #include +#include #include #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, ®s[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, ®write, 1); + r = aes_write_regv(dev, ®write, 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); diff --git a/libfprint/drivers/aes4000.c b/libfprint/drivers/aes4000.c index 111a824..f300477 100644 --- a/libfprint/drivers/aes4000.c +++ b/libfprint/drivers/aes4000.c @@ -24,6 +24,7 @@ #include #include +#include #include #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);