Daniel Drake wrote:
Hi,

I just spent some time sniffing what UPEK's new libbsapi is doing, and produced a libusb-1.0 app to do the same. It works - it captures image data. I'm not totally clear on the format, but the output file looks quite nice when plotted as 8 bit greyscale with a width of 2306 pixels (although the fingerprint is repeated).

Updated version attached which works from cold boot. Also it now uses the hardware's finger detection capability and deinitializes the device after the scan.
/*
 * reverse engineering 0x147e:0x2016 fingerprint reader
 * Copyright (C) 2007-2008 Daniel Drake <[EMAIL PROTECTED]>
 * 
 * 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
 */

#include <libusb.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

/* 288 pixels wide? */

static int capturing = 500;
static libusb_device_handle *handle;
static FILE *fd;

static const int wait_for_finger = 1;

static int read_reg(uint16_t index)
{
        unsigned char buf[8];
        int r;

        r = libusb_control_transfer(handle, 0xc0, 0x0c, 0, index, buf, 8, 5000);
        printf("read8 %x = %d: %02x %02x %02x %02x %02x %02x %02x %02x\n", 
index, r,
                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
        if (r < 0)
                return r;
        
        return buf[0];
}

static int write_reg(uint16_t reg, uint8_t val)
{
        int r;
        r = libusb_control_transfer(handle, 0x40, 0x0c, 0, reg, &val, 1, 5000);
        printf("write reg %x = %d\n", reg, r);
        return r;
}

static void bulkin(int len)
{
        int actual;
        unsigned char buf[len];
        int r = libusb_bulk_transfer(handle, 0x81, buf, len, &actual, 5000);
        printf("bulkin %d = %d,%d: %02x %02x %02x %02x %02x %02x %02x %02x 
...\n",
                len, actual, r,
                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
}

static void intrin(void)
{
        int actual;
        unsigned char buf[4];
        int r = libusb_interrupt_transfer(handle, 0x83, buf, 4, &actual, 5000);
        printf("intrin %d,%d: %02x %02x %02x %02x...\n",
                actual, r,
                buf[0], buf[1], buf[2], buf[3]);
        if (r < 0)
                exit(1);
}

static void bulkcb(struct libusb_transfer *transfer)
{
        unsigned char *buf = transfer->buffer;
        printf("cb stat=%d,%d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
                transfer->status, transfer->actual_length,
                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
        int i;

        for (i = 0; i < 4096; i += 64)
                fwrite(buf + i + 2, 1, 62, fd);
        capturing--;
        libusb_submit_transfer(transfer);
}

static void onebulk(void)
{
        struct libusb_transfer *transfer = libusb_alloc_transfer(0);
        unsigned char *buf = malloc(4096);
        libusb_fill_bulk_transfer(transfer, handle, 0x81, buf, 4096, bulkcb,
                NULL, 5000);
        libusb_submit_transfer(transfer);
}

static void startbulk(void)
{
        int i;
        for (i = 0; i < 24; i++)
                onebulk();
}

static int init3e(void)
{
        int i;
        int r;
        const unsigned char data3e[] = {
                0x83, 0x4f, 0x0f, 0xbf, 0x45, 0x35, 0x1c, 0xae
        };

        for (i = 0; i < sizeof(data3e); i++) {
                r = write_reg(0x3e, data3e[i]);
                if (r < 0)
                        return r;
        }

        return 0;
}

int main(void)
{
        int r;

        libusb_init(NULL);
        handle = libusb_open_device_with_vid_pid(NULL, 0x147e, 0x2016);
        if (!handle)
                return 2;

        /* ABSOpen */
        libusb_set_configuration(handle, 1);
        read_reg(0x17);
        write_reg(0x49, 0x00);
        init3e();
        write_reg(0x44, 0x01);
        write_reg(0x43, 0x06);
        write_reg(0x43, 0x05);
        read_reg(0x45);
        write_reg(0x43, 0x04);

        write_reg(0x44, 0);
        write_reg(0x44, 0x9d);
        write_reg(0x40, 0x1f);
        write_reg(0x41, 0xb8);
        write_reg(0x42, 0);
        write_reg(0x43, 0x03);
        read_reg(0x45);
        bulkin(64);

        write_reg(0x44, 0);
        write_reg(0x44, 0x9d);
        write_reg(0x40, 0x03);
        write_reg(0x43, 0x03);
        read_reg(0x45);
        bulkin(64);

        write_reg(0x44, 0x00);
        write_reg(0x44, 0x9d);
        write_reg(0x40, 0xff);
        write_reg(0x41, 0xc0);
        write_reg(0x43, 0x03);
        read_reg(0x45);
        read_reg(0x45);
        bulkin(512);

        write_reg(0x44, 0x00);
        write_reg(0x44, 0x9d);
        write_reg(0x41, 0x40);
        write_reg(0x42, 0x03);
        write_reg(0x43, 0x03);
        read_reg(0x45);
        read_reg(0x45);
        bulkin(512);

        write_reg(0x44, 0x00);
        write_reg(0x44, 0x9d);
        write_reg(0x42, 0x05);
        write_reg(0x43, 0x03);
        read_reg(0x45);
        read_reg(0x45);
        bulkin(512);

        write_reg(0x44, 0);
        write_reg(0x44, 0x9d);
        write_reg(0x42, 0x07);
        write_reg(0x43, 0x03);
        read_reg(0x45);
        read_reg(0x45);
        bulkin(512);

        write_reg(0x44, 0);
        read_reg(0x17);
        read_reg(0xb);
        write_reg(0xb, 0);

        r = read_reg(0x9);
        if (r < 0)
                return r;
        write_reg(0x9, r & ~0x08);

        r = read_reg(0x13);
        if (r < 0)
                return r;
        write_reg(0x13, r & ~0x10);

        write_reg(0x4, 0);
        write_reg(0x5, 0);

        /* ABSEnroll */
        if (!wait_for_finger) {
                printf("scan finger now\n");
                sleep(1);
        }
        read_reg(0x17);
        read_reg(0xa);
        write_reg(0xa, 0);
        read_reg(0xa);
        write_reg(0xa, 0);
        read_reg(0x9);
        write_reg(0x09, 0x20);
        read_reg(0x3);
        write_reg(0x3, 0x3b);
        read_reg(0x0);
        write_reg(0x0, 0x67);
        read_reg(0);
        write_reg(0, 0x67);

        r = read_reg(0x1);
        if (r < 0)
                return r;
        else if (r != 0xc6)
                /* cold boot */
                write_reg(1, 0x46);
        else
                write_reg(1, 0xc6);
        read_reg(1);
        write_reg(1, 0xc6);

        write_reg(0xc, 0x13);
        write_reg(0xd, 0x0d);
        write_reg(0xe, 0x0e);
        write_reg(0xf, 0xd);
        read_reg(0xb);
        write_reg(0xb, 0);

        r = read_reg(0x13);
        if (r < 0)
                return 1;
        else if (r != 0x45)
                /* cold boot */
                write_reg(0x13, 0x05);
        else
                write_reg(0x13, 0x45);
        read_reg(0x13);
        write_reg(0x13, 0x45);

        read_reg(0x30);
        write_reg(0x30, 0xe0);

        /* only happens for enroll */
        if (!wait_for_finger) {
                read_reg(0x13);
                write_reg(0x13, 0x55);
        }

        read_reg(0x12);
        write_reg(0x12, 0x01);
        read_reg(0x20);
        write_reg(0x20, 0x01);
        read_reg(0x9);
        write_reg(0x9, 0x20);
        read_reg(0xa);
        write_reg(0xa, 0);
        read_reg(0x30);
        write_reg(0x30, 0xe0);
        read_reg(0x20);
        write_reg(0x20, 0x01);

        /* 90 cold, 10 warm */
        r = read_reg(0x07);
        if (r < 0)
                return r;
        if (r != 0x10 && r != 0x90)
                printf("odd reg7 value %x\n", r);
        write_reg(0x07, r);
        
        read_reg(0x08);
        write_reg(0x08, 0x00);
        write_reg(0x10, 0x00);
        read_reg(0x12);
        write_reg(0x12, 0x01);
        write_reg(0x11, 0xbf);
        read_reg(0x12);
        write_reg(0x12, 0x01);
        read_reg(0x7);
        write_reg(0x7, 0x10);
        read_reg(0x7);
        write_reg(0x7, 0x10);
        write_reg(0x04, 0);
        write_reg(0x5, 0);
        read_reg(0x9);
        read_reg(0xb);
        read_reg(0x13);
        read_reg(0x15);
        read_reg(0x30);
        read_reg(0xb);
        write_reg(0xb, 0x00);

        if (wait_for_finger) {
                read_reg(0x15);
                write_reg(0x15, 0x20),
                read_reg(0x30);
                write_reg(0x30, 0xe1);
                read_reg(0x15);
                write_reg(0x15, 0x24);
                read_reg(0x15);
                write_reg(0x15, 0x04);
                read_reg(0x15);
                write_reg(0x15, 0x84);
                printf("wait for finger\n");
                intrin();
                write_reg(0x15, 0x20);
                write_reg(0x30, 0xe0);
        }

        startbulk();

        write_reg(0x09, 0x28);
        write_reg(0x13, 0x55);
        write_reg(0x0b, 0x80);

        /* after some data comes in */
        write_reg(0x4, 0);
        write_reg(0x5, 0);

        fd = fopen("data.out", "w");
        while (capturing)
                libusb_handle_events(NULL);

        /* deinit */
        read_reg(0xb);
        write_reg(0xb, 0);
        read_reg(0x9);
        write_reg(0x9, 0x20);
        read_reg(0x13);
        write_reg(0x13, 0x45);
        read_reg(0x13);
        write_reg(0x13, 0x45);

        fclose(fd);
        return 0;
}
_______________________________________________
fprint mailing list
[email protected]
http://lists.reactivated.net/mailman/listinfo/fprint

Reply via email to