Sun, Aug 29, 2010 at 10:35 PM, Canek Peláez Valdés wrote: > On Sun, Aug 29, 2010 at 2:51 PM, Bastien Nocera <[email protected]> wrote: > [...] >> 0.1.0-pre2 is old. 0.2.0 is the latest. > Sorry Bastien, I forgot that you moved the project to freedesktop.org. > With libfprint 0.2.0 Hugo's patch still applies (with an offset of 9 > lines for hunk 9) and compiles, but it doesn't work anymore. > fprint_demo says it can't find any devices. > > Given that it worked for 0.1.0-pre2, I suppose it's just a minor > thing; but I don't understand the code enough fo fix it myself. > > Regards. I made a new patch. It should work well with 0.2.0. Thanks Canek for the report.
Regards. Hugo Grostabussiat
diff --git a/AUTHORS b/AUTHORS index cc82954..1cd2e51 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,3 +7,4 @@ Copyright (C) 2007 Cyrille Bagard Copyright (C) 2007 Vasily Khoruzhick Copyright (C) 2007 Jan-Michael Brummer <[email protected]> Copyright (C) 2007 Anthony Bretaudeau <[email protected]> +Copyright (C) 2010 Hugo Grostabussiat <[email protected]> diff --git a/libfprint/drivers/upeksonly.c b/libfprint/drivers/upeksonly.c index 9b9adbb..ad003f8 100644 --- a/libfprint/drivers/upeksonly.c +++ b/libfprint/drivers/upeksonly.c @@ -2,6 +2,9 @@ * UPEK TouchStrip Sensor-Only driver for libfprint * Copyright (C) 2008 Daniel Drake <[email protected]> * + * TCS4C (USB ID 147e:1000) support: + * Copyright (C) 2010 Hugo Grostabussiat <[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 @@ -33,6 +36,11 @@ #define MAX_ROWS 700 #define MIN_ROWS 64 +enum { + UPEKSONLY_2016, + UPEKSONLY_1000, +}; + struct img_transfer_data { int idx; struct fp_img_dev *dev; @@ -61,6 +69,8 @@ struct sonly_dev { gboolean deactivating; uint8_t read_reg_result; + int dev_model; + struct fpi_ssm *loopsm; struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS]; struct img_transfer_data *img_transfer_data; @@ -653,22 +663,42 @@ static void sm_await_intr(struct fpi_ssm *ssm) /***** AWAIT FINGER *****/ -static const struct sonly_regwrite awfsm_writev_1[] = { +static const struct sonly_regwrite awfsm_2016_writev_1[] = { { 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b }, { 0x00, 0x67 }, { 0x00, 0x67 }, }; -static const struct sonly_regwrite awfsm_writev_2[] = { +static const struct sonly_regwrite awfsm_1000_writev_1[] = { + /* Initialize sensor settings */ + { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f }, + { 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, + { 0x0e, 0x0e }, { 0x0f, 0x0d }, + + { 0x13, 0x05 }, { 0x13, 0x45 }, + + /* Initlalize finger detection registers (not enabling yet) */ + { 0x30, 0xe0 }, { 0x15, 0x26 }, + + { 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 }, + { 0x10, 0x00 }, { 0x11, 0xbf }, +}; + +static const struct sonly_regwrite awfsm_2016_writev_2[] = { { 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e }, { 0x0f, 0x0d }, { 0x0b, 0x00 }, }; -static const struct sonly_regwrite awfsm_writev_3[] = { +static const struct sonly_regwrite awfsm_1000_writev_2[] = { + /* Enable finger detection */ + { 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 }, +}; + +static const struct sonly_regwrite awfsm_2016_writev_3[] = { { 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 }, { 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 }, }; -static const struct sonly_regwrite awfsm_writev_4[] = { +static const struct sonly_regwrite awfsm_2016_writev_4[] = { { 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf }, { 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 },\ { 0x05, 0x00 }, { 0x0b, 0x00 }, @@ -678,91 +708,150 @@ static const struct sonly_regwrite awfsm_writev_4[] = { { 0x15, 0x84 }, }; -enum awfsm_states { - AWFSM_WRITEV_1, - AWFSM_READ_01, - AWFSM_WRITE_01, - AWFSM_WRITEV_2, - AWFSM_READ_13, - AWFSM_WRITE_13, - AWFSM_WRITEV_3, - AWFSM_READ_07, - AWFSM_WRITE_07, - AWFSM_WRITEV_4, - AWFSM_NUM_STATES, +enum awfsm_2016_states { + AWFSM_2016_WRITEV_1, + AWFSM_2016_READ_01, + AWFSM_2016_WRITE_01, + AWFSM_2016_WRITEV_2, + AWFSM_2016_READ_13, + AWFSM_2016_WRITE_13, + AWFSM_2016_WRITEV_3, + AWFSM_2016_READ_07, + AWFSM_2016_WRITE_07, + AWFSM_2016_WRITEV_4, + AWFSM_2016_NUM_STATES, +}; + +enum awfsm_1000_states { + AWFSM_1000_WRITEV_1, + AWFSM_1000_WRITEV_2, + AWFSM_1000_NUM_STATES, }; -static void awfsm_run_state(struct fpi_ssm *ssm) +static void awfsm_2016_run_state(struct fpi_ssm *ssm) { struct fp_img_dev *dev = ssm->priv; struct sonly_dev *sdev = dev->priv; switch (ssm->cur_state) { - case AWFSM_WRITEV_1: - sm_write_regs(ssm, awfsm_writev_1, G_N_ELEMENTS(awfsm_writev_1)); + case AWFSM_2016_WRITEV_1: + sm_write_regs(ssm, awfsm_2016_writev_1, G_N_ELEMENTS(awfsm_2016_writev_1)); break; - case AWFSM_READ_01: + case AWFSM_2016_READ_01: sm_read_reg(ssm, 0x01); break; - case AWFSM_WRITE_01: + case AWFSM_2016_WRITE_01: if (sdev->read_reg_result != 0xc6) sm_write_reg(ssm, 0x01, 0x46); else sm_write_reg(ssm, 0x01, 0xc6); break; - case AWFSM_WRITEV_2: - sm_write_regs(ssm, awfsm_writev_2, G_N_ELEMENTS(awfsm_writev_2)); + case AWFSM_2016_WRITEV_2: + sm_write_regs(ssm, awfsm_2016_writev_2, G_N_ELEMENTS(awfsm_2016_writev_2)); break; - case AWFSM_READ_13: + case AWFSM_2016_READ_13: sm_read_reg(ssm, 0x13); break; - case AWFSM_WRITE_13: + case AWFSM_2016_WRITE_13: if (sdev->read_reg_result != 0x45) sm_write_reg(ssm, 0x13, 0x05); else sm_write_reg(ssm, 0x13, 0x45); break; - case AWFSM_WRITEV_3: - sm_write_regs(ssm, awfsm_writev_3, G_N_ELEMENTS(awfsm_writev_3)); + case AWFSM_2016_WRITEV_3: + sm_write_regs(ssm, awfsm_2016_writev_3, G_N_ELEMENTS(awfsm_2016_writev_3)); break; - case AWFSM_READ_07: + case AWFSM_2016_READ_07: sm_read_reg(ssm, 0x07); break; - case AWFSM_WRITE_07: + case AWFSM_2016_WRITE_07: if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90) fp_warn("odd reg7 value %x", sdev->read_reg_result); sm_write_reg(ssm, 0x07, sdev->read_reg_result); break; - case AWFSM_WRITEV_4: - sm_write_regs(ssm, awfsm_writev_4, G_N_ELEMENTS(awfsm_writev_4)); + case AWFSM_2016_WRITEV_4: + sm_write_regs(ssm, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4)); + break; + } +} + +static void awfsm_1000_run_state(struct fpi_ssm *ssm) +{ + switch (ssm->cur_state) { + case AWFSM_1000_WRITEV_1: + sm_write_regs(ssm, awfsm_1000_writev_1, G_N_ELEMENTS(awfsm_1000_writev_1)); + break; + case AWFSM_1000_WRITEV_2: + sm_write_regs(ssm, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2)); break; } } /***** CAPTURE MODE *****/ -static const struct sonly_regwrite capsm_writev[] = { +static const struct sonly_regwrite capsm_2016_writev[] = { /* enter capture mode */ { 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 }, { 0x05, 0x00 }, }; -enum capsm_states { - CAPSM_INIT, - CAPSM_WRITE_15, - CAPSM_WRITE_30, - CAPSM_FIRE_BULK, - CAPSM_WRITEV, - CAPSM_NUM_STATES, +static const struct sonly_regwrite capsm_1000_writev[] = { + { 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */ +}; + +enum capsm_2016_states { + CAPSM_2016_INIT, + CAPSM_2016_WRITE_15, + CAPSM_2016_WRITE_30, + CAPSM_2016_FIRE_BULK, + CAPSM_2016_WRITEV, + CAPSM_2016_NUM_STATES, }; -static void capsm_run_state(struct fpi_ssm *ssm) +enum capsm_1000_states { + CAPSM_1000_INIT, + CAPSM_1000_FIRE_BULK, + CAPSM_1000_WRITEV, + CAPSM_1000_NUM_STATES, +}; + +static void capsm_fire_bulk(struct fpi_ssm *ssm) +{ + struct fp_img_dev *dev = ssm->priv; + struct sonly_dev *sdev = dev->priv; + int i; + for (i = 0; i < NUM_BULK_TRANSFERS; i++) { + int r = libusb_submit_transfer(sdev->img_transfer[i]); + if (r < 0) { + if (i == 0) { + /* first one failed: easy peasy */ + fpi_ssm_mark_aborted(ssm, r); + return; + } + + /* cancel all flying transfers, and request that the SSM + * gets aborted when the last transfer has dropped out of + * the sky */ + sdev->killing_transfers = ABORT_SSM; + sdev->kill_ssm = ssm; + sdev->kill_status_code = r; + cancel_img_transfers(dev); + return; + } + sdev->img_transfer_data[i].flying = TRUE; + sdev->num_flying++; + } + sdev->capturing = TRUE; + fpi_ssm_next_state(ssm); +} + +static void capsm_2016_run_state(struct fpi_ssm *ssm) { struct fp_img_dev *dev = ssm->priv; struct sonly_dev *sdev = dev->priv; switch (ssm->cur_state) { - case CAPSM_INIT: + case CAPSM_2016_INIT: sdev->rowbuf_offset = -1; sdev->num_rows = 0; sdev->wraparounds = -1; @@ -772,61 +861,84 @@ static void capsm_run_state(struct fpi_ssm *ssm) sdev->killing_transfers = 0; fpi_ssm_next_state(ssm); break; - case CAPSM_WRITE_15: + case CAPSM_2016_WRITE_15: sm_write_reg(ssm, 0x15, 0x20); break; - case CAPSM_WRITE_30: + case CAPSM_2016_WRITE_30: sm_write_reg(ssm, 0x30, 0xe0); break; - case CAPSM_FIRE_BULK: ; - int i; - for (i = 0; i < NUM_BULK_TRANSFERS; i++) { - int r = libusb_submit_transfer(sdev->img_transfer[i]); - if (r < 0) { - if (i == 0) { - /* first one failed: easy peasy */ - fpi_ssm_mark_aborted(ssm, r); - return; - } + case CAPSM_2016_FIRE_BULK: ; + capsm_fire_bulk (ssm); + break; + case CAPSM_2016_WRITEV: + sm_write_regs(ssm, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev)); + break; + } +} - /* cancel all flying transfers, and request that the SSM - * gets aborted when the last transfer has dropped out of - * the sky */ - sdev->killing_transfers = ABORT_SSM; - sdev->kill_ssm = ssm; - sdev->kill_status_code = r; - cancel_img_transfers(dev); - return; - } - sdev->img_transfer_data[i].flying = TRUE; - sdev->num_flying++; - } - sdev->capturing = TRUE; +static void capsm_1000_run_state(struct fpi_ssm *ssm) +{ + struct fp_img_dev *dev = ssm->priv; + struct sonly_dev *sdev = dev->priv; + + switch (ssm->cur_state) { + case CAPSM_1000_INIT: + sdev->rowbuf_offset = -1; + sdev->num_rows = 0; + sdev->wraparounds = -1; + sdev->num_blank = 0; + sdev->finger_removed = 0; + sdev->last_seqnum = 16383; + sdev->killing_transfers = 0; fpi_ssm_next_state(ssm); break; - case CAPSM_WRITEV: - sm_write_regs(ssm, capsm_writev, G_N_ELEMENTS(capsm_writev)); + case CAPSM_1000_FIRE_BULK: ; + capsm_fire_bulk (ssm); + break; + case CAPSM_1000_WRITEV: + sm_write_regs(ssm, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev)); break; } } /***** DEINITIALIZATION *****/ -static const struct sonly_regwrite deinitsm_writev[] = { +static const struct sonly_regwrite deinitsm_2016_writev[] = { /* reset + enter low power mode */ { 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 }, }; -enum deinitsm_states { - DEINITSM_WRITEV, - DEINITSM_NUM_STATES, +static const struct sonly_regwrite deinitsm_1000_writev[] = { + { 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */ + + { 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */ +}; + + +enum deinitsm_2016_states { + DEINITSM_2016_WRITEV, + DEINITSM_2016_NUM_STATES, +}; + +enum deinitsm_1000_states { + DEINITSM_1000_WRITEV, + DEINITSM_1000_NUM_STATES, }; -static void deinitsm_run_state(struct fpi_ssm *ssm) +static void deinitsm_2016_run_state(struct fpi_ssm *ssm) +{ + switch (ssm->cur_state) { + case DEINITSM_2016_WRITEV: + sm_write_regs(ssm, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev)); + break; + } +} + +static void deinitsm_1000_run_state(struct fpi_ssm *ssm) { switch (ssm->cur_state) { - case DEINITSM_WRITEV: - sm_write_regs(ssm, deinitsm_writev, G_N_ELEMENTS(deinitsm_writev)); + case DEINITSM_1000_WRITEV: + sm_write_regs(ssm, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev)); break; } } @@ -834,27 +946,41 @@ static void deinitsm_run_state(struct fpi_ssm *ssm) /***** INITIALIZATION *****/ static const struct sonly_regwrite initsm_writev_1[] = { - { 0x49, 0x00 }, - - /* BSAPI writes different values to register 0x3e each time. I initially - * thought this was some kind of clever authentication, but just blasting - * these sniffed values each time seems to work. */ - { 0x3e, 0x83 }, { 0x3e, 0x4f }, { 0x3e, 0x0f }, { 0x3e, 0xbf }, - { 0x3e, 0x45 }, { 0x3e, 0x35 }, { 0x3e, 0x1c }, { 0x3e, 0xae }, + { 0x49, 0x00 }, /* Encryption disabled */ + + /* Setting encryption key. Don't need to be random since we don't use any + * encryption. */ + { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, + { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, +}; +static const struct sonly_regwrite initsm_2016_writev_2[] = { { 0x44, 0x01 }, { 0x43, 0x06 }, { 0x43, 0x05 }, { 0x43, 0x04 }, { 0x44, 0x00 }, { 0x0b, 0x00 }, }; -enum initsm_states { - INITSM_WRITEV_1, - INITSM_READ_09, - INITSM_WRITE_09, - INITSM_READ_13, - INITSM_WRITE_13, - INITSM_WRITE_04, - INITSM_WRITE_05, - INITSM_NUM_STATES, +static const struct sonly_regwrite initsm_1000_writev_2[] = { + { 0x04, 0x00 }, { 0x05, 0x00 }, + + { 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */ +}; + +enum initsm_2016_states { + INITSM_2016_WRITEV_1, + INITSM_2016_WRITEV_2, + INITSM_2016_READ_09, + INITSM_2016_WRITE_09, + INITSM_2016_READ_13, + INITSM_2016_WRITE_13, + INITSM_2016_WRITE_04, + INITSM_2016_WRITE_05, + INITSM_2016_NUM_STATES, +}; + +enum initsm_1000_states { + INITSM_1000_WRITEV_1, + INITSM_1000_WRITEV_2, + INITSM_1000_NUM_STATES, }; static void initsm_run_state(struct fpi_ssm *ssm) @@ -862,27 +988,45 @@ static void initsm_run_state(struct fpi_ssm *ssm) struct fp_img_dev *dev = ssm->priv; struct sonly_dev *sdev = dev->priv; - switch (ssm->cur_state) { - case INITSM_WRITEV_1: - sm_write_regs(ssm, initsm_writev_1, G_N_ELEMENTS(initsm_writev_1)); - break; - case INITSM_READ_09: - sm_read_reg(ssm, 0x09); - break; - case INITSM_WRITE_09: - sm_write_reg(ssm, 0x09, sdev->read_reg_result & ~0x08); - break; - case INITSM_READ_13: - sm_read_reg(ssm, 0x13); - break; - case INITSM_WRITE_13: - sm_write_reg(ssm, 0x13, sdev->read_reg_result & ~0x10); - break; - case INITSM_WRITE_04: - sm_write_reg(ssm, 0x04, 0x00); + switch (sdev->dev_model) { + case UPEKSONLY_2016: + switch (ssm->cur_state) { + case INITSM_2016_WRITEV_1: + sm_write_regs(ssm, initsm_writev_1, G_N_ELEMENTS(initsm_writev_1)); + break; + case INITSM_2016_WRITEV_2: + sm_write_regs(ssm, initsm_2016_writev_2, G_N_ELEMENTS(initsm_2016_writev_2)); + break; + case INITSM_2016_READ_09: + sm_read_reg(ssm, 0x09); + break; + case INITSM_2016_WRITE_09: + sm_write_reg(ssm, 0x09, sdev->read_reg_result & ~0x08); + break; + case INITSM_2016_READ_13: + sm_read_reg(ssm, 0x13); + break; + case INITSM_2016_WRITE_13: + sm_write_reg(ssm, 0x13, sdev->read_reg_result & ~0x10); + break; + case INITSM_2016_WRITE_04: + sm_write_reg(ssm, 0x04, 0x00); + break; + case INITSM_2016_WRITE_05: + sm_write_reg(ssm, 0x05, 0x00); + break; + } break; - case INITSM_WRITE_05: - sm_write_reg(ssm, 0x05, 0x00); + + case UPEKSONLY_1000: + switch (ssm->cur_state) { + case INITSM_1000_WRITEV_1: + sm_write_regs(ssm, initsm_writev_1, G_N_ELEMENTS(initsm_writev_1)); + break; + case INITSM_1000_WRITEV_2: + sm_write_regs(ssm, initsm_1000_writev_2, G_N_ELEMENTS(initsm_1000_writev_2)); + break; + } break; } } @@ -909,8 +1053,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm) if (sdev->deactivating) { fpi_ssm_mark_completed(ssm); } else { - struct fpi_ssm *awfsm = fpi_ssm_new(dev->dev, awfsm_run_state, - AWFSM_NUM_STATES); + struct fpi_ssm *awfsm = NULL; + switch (sdev->dev_model) { + case UPEKSONLY_2016: + awfsm = fpi_ssm_new(dev->dev, awfsm_2016_run_state, + AWFSM_2016_NUM_STATES); + break; + case UPEKSONLY_1000: + awfsm = fpi_ssm_new(dev->dev, awfsm_1000_run_state, + AWFSM_1000_NUM_STATES); + break; + } awfsm->priv = dev; fpi_ssm_start_subsm(ssm, awfsm); } @@ -919,8 +1072,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm) sm_await_intr(ssm); break; case LOOPSM_RUN_CAPSM: ; - struct fpi_ssm *capsm = fpi_ssm_new(dev->dev, capsm_run_state, - CAPSM_NUM_STATES); + struct fpi_ssm *capsm = NULL; + switch (sdev->dev_model) { + case UPEKSONLY_2016: + capsm = fpi_ssm_new(dev->dev, capsm_2016_run_state, + CAPSM_2016_NUM_STATES); + break; + case UPEKSONLY_1000: + capsm = fpi_ssm_new(dev->dev, capsm_1000_run_state, + CAPSM_1000_NUM_STATES); + break; + } capsm->priv = dev; fpi_ssm_start_subsm(ssm, capsm); break; @@ -929,8 +1091,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm) * to push us into next state */ break; case LOOPSM_RUN_DEINITSM: ; - struct fpi_ssm *deinitsm = fpi_ssm_new(dev->dev, deinitsm_run_state, - DEINITSM_NUM_STATES); + struct fpi_ssm *deinitsm = NULL; + switch (sdev->dev_model) { + case UPEKSONLY_2016: + deinitsm = fpi_ssm_new(dev->dev, deinitsm_2016_run_state, + DEINITSM_2016_NUM_STATES); + break; + case UPEKSONLY_1000: + deinitsm = fpi_ssm_new(dev->dev, deinitsm_1000_run_state, + DEINITSM_1000_NUM_STATES); + break; + } sdev->capturing = FALSE; deinitsm->priv = dev; fpi_ssm_start_subsm(ssm, deinitsm); @@ -1039,7 +1210,14 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) 4096, img_data_cb, &sdev->img_transfer_data[i], 0); } - ssm = fpi_ssm_new(dev->dev, initsm_run_state, INITSM_NUM_STATES); + switch (sdev->dev_model) { + case UPEKSONLY_2016: + ssm = fpi_ssm_new(dev->dev, initsm_run_state, INITSM_2016_NUM_STATES); + break; + case UPEKSONLY_1000: + ssm = fpi_ssm_new(dev->dev, initsm_run_state, INITSM_1000_NUM_STATES); + break; + } ssm->priv = dev; fpi_ssm_start(ssm, initsm_complete); return 0; @@ -1062,6 +1240,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) } dev->priv = g_malloc0(sizeof(struct sonly_dev)); + ((struct sonly_dev*)dev->priv)->dev_model = (int)driver_data; fpi_imgdev_open_complete(dev, 0); return 0; } @@ -1075,15 +1254,16 @@ static void dev_deinit(struct fp_img_dev *dev) static int dev_discover(struct libusb_device_descriptor *dsc, uint32_t *devtype) { - /* Revision 1 is what we're interested in */ - if (dsc->bcdDevice == 1) + /* Revision 1 and 0.33 are what we're interested in */ + if (dsc->bcdDevice == 1 || dsc->bcdDevice == 0x0033) return 1; return 0; } static const struct usb_id id_table[] = { - { .vendor = 0x147e, .product = 0x2016 }, + { .vendor = 0x147e, .product = 0x2016, .driver_data = UPEKSONLY_2016 }, + { .vendor = 0x147e, .product = 0x1000, .driver_data = UPEKSONLY_1000 }, { 0, 0, 0, }, };
_______________________________________________ fprint mailing list [email protected] http://lists.reactivated.net/mailman/listinfo/fprint
