/* sane - Scanner Access Now Easy.

   Copyright (C) 2006 -2006 Gerard Klaver (gerard at gkall dot hobby dot nl)
   The teco2 and gl646 backend (Frank Zago) are used as a template for 
   this backend.
   For the authentec_add_text routine the add_text routine and font_6x11.h file 
   are taken from the webcam.c file, part of xawtv program,
   (c) 1998-2002 Gerd Knorr (GNU GPL license 2).

   For the init of the device, parts of the following programs are used:
   biopod (Mike Smith, Micah Villmow)
   udrv (David Zeuthen)
   main (Andreas Pehnack)
   aespack	Andreas Grotz
   aes2501-WY	Wittawat Yamwong
   
   This file is part of the SANE package.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program 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
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   MA 02111-1307, USA.

*/

/* 
	$Id: authentec.h,v 1.2 2006/09/15 20:56:15 gerard Exp $ */

/* Commands supported by the fingerprint. */

/*--------------------------------------------------------------------------*/

static inline int
getbitfield (unsigned char *pageaddr, int mask, int shift)
{
  return ((*pageaddr >> shift) & mask);
}

/*--------------------------------------------------------------------------*/

#include <stdio.h>

#define LIBUSB_TIMEOUT					1000	/* ms */

typedef unsigned char byte;

/*--------------------------------------------------------------------------*/

/* Black magic for color adjustment. */
struct dpi_color_adjust
{
  int resolution_x;		/* x-resolution  */
  int resolution_y;		/* y-resolution  */

  int z1_color_0;		/* 0, 1 or 2 */
  int z1_color_1;		/* idem */
  int z1_color_2;		/* idem */
};

/*--------------------------------------------------------------------------*/

enum Authentec_Option
{
  /* Must come first */
  OPT_NUM_OPTS = 0,

  OPT_MODE_GROUP,
  OPT_MODE,			/* fingerprint modes */
  OPT_RESOLUTION,		/* X and Y resolution */
  OPT_BRIGHTNESS,		/* brightness   */

  OPT_ENHANCEMENT_GROUP,
  OPT_WHITE_LEVEL_R,		/*white level red correction */
  OPT_WHITE_LEVEL,		/*white level correction */

  /* must come last: */
  OPT_NUM_OPTIONS
};

/* 
 * Fingerprint scanner supported by this backend. 
 */
struct fingerprint_hardware
{
  /* USB stuff */
  SANE_Word vendor;
  SANE_Word product;
  SANE_Word class;
  enum
  {
    Authentec_AES2501,
    Authentec_AES3400,
    Authentec_AES3500,
    Authentec_AES3500_X50
  }
  authentecref;

  /* Readable names */
  const char *vendor_name;	/* brand on the box */
  const char *product_name;	/* name on the box */

  /* Resolutions supported in color mode. */
  const struct dpi_color_adjust *color_adjust;
};

#define GRAYSCALE_RAW_STR			SANE_I18N("GRAY RAW")
#define GRAYSCALE_TEXT_STR                      SANE_I18N("GRAY TEXT")
/*--------------------------------------------------------------------------*/

/* Define a fingerprint occurence. */
typedef struct Authentec_Fingerprint
{
  struct Authentec_Fingerprint *next;
  SANE_Device sane;

  char *devicename;
  SANE_Int fd;			/* device handle */

  /* USB handling */
  size_t buffer_size;		/* size of the buffer */
  SANE_Byte *buffer;		/* for USB transfer. */

  /* Bayer handling */
  size_t output_size;		/* size of the output */
  SANE_Byte *output;		/* for conversion */

  size_t image_size;		/* allocated size of image */
  size_t image_begin;		/* first significant byte in image */
  size_t image_end;		/* first free byte in image */
  SANE_Byte *image;		/* keep the raw image here */

  /* USB control messages handling */
  size_t windoww_size;		/* size of window write */
  size_t windowr_size;		/* size of window read  */
  SANE_Byte *windoww;		/* for window write     */
  SANE_Byte *windowr;		/* for window read      */

  /* Scanner infos. */
  const struct fingerprint_hardware *hw;	/* default options for that fingerprint */

  SANE_Word *resolutions_list;
  SANE_Word *color_sequence_list;

  /* Scanning handling. */
  SANE_Bool scanning;		/* TRUE if a scan is running. */
  SANE_Bool deliver_eof;
  int x_resolution;		/* X resolution */
  int y_resolution;		/* Y resolution */
  int depth;			/* depth per color */
  unsigned int colour;
  int red_s;
  int green_s;
  int blue_s;

  SANE_Parameters s_params;
  enum
  {
    AUTHENTEC_GRAYSCALE_RAW,
    AUTHENTEC_GRAYSCALE,
    AUTHENTEC_GRAYSCALE_TEXT
  }
  scan_mode;

  size_t bytes_left;		/* number of bytes left to give to the backend */
  size_t real_bytes_left;	/* number of bytes left the fingerprint will return. */
  int bytes_pixel;

  const struct dpi_color_adjust *color_adjust;

  SANE_Parameters params;

  /* Options */
  SANE_Option_Descriptor opt[OPT_NUM_OPTIONS];
  Option_Value val[OPT_NUM_OPTIONS];

  char picmsg_ps[50];

}
Authentec_Fingerprint;

/*--------------------------------------------------------------------------*/

/* Debug levels. 
 * Should be common to all backends. */

#define DBG_error0  0
#define DBG_error   1
#define DBG_sense   2
#define DBG_warning 3
#define DBG_inquiry 4
#define DBG_info    5
#define DBG_info2   6
#define DBG_proc    7
#define DBG_read    8
#define DBG_sane_init   10
#define DBG_sane_proc   11
#define DBG_sane_info   12
#define DBG_sane_option 13

/*--------------------------------------------------------*/

static SANE_Byte urb_outbuf_aes2501[0x06] = {
  0xAC, 0x01, 0xAD, 0x1A, 0x81, 0x02
};

static SANE_Byte urb_outbufreset_aes2501[0x0e] = {
            0x80, 0x01, 0x82, 0x40, 0xB0, 0x27, 0x94, 0x0A,
            0x80, 0x04, 0x83, 0x45, 0xA8, 0x41
};
static SANE_Byte urb_outbufinit1_aes2501[0x02] = {
  0xB0, 0x27
};
static SANE_Byte urb_outbufinit2_aes2501[0x04] = {
  0x80, 0x01, 0x82, 0x40
};
static SANE_Byte urb_outbufinit3_aes2501[0x04] = {
  0x80, 0x01, 0x82, 0x40
};
static SANE_Byte urb_outbufinit4_aes2501[0x06] = {
  0xAC, 0x01, 0xAD, 0x1A, 0x81, 0x02
};
static SANE_Byte urb_outbufinit5_aes2501[0x04] = {
  0x80, 0x01, 0x82, 0x40
};
static SANE_Byte urb_outbufinit6_aes2501[0x04] = {
  0x80, 0x01, 0x82, 0x40
};
static SANE_Byte urb_outbufinit7_aes2501[0x04] = {
  0x80, 0x01, 0x82, 0x40
};
static SANE_Byte urb_outbufinit8_aes2501[0x02] = {
  0x80, 0x02
};
static SANE_Byte urb_outbufinit9_aes2501[0x02] = {
  0x80, 0x02
};
static SANE_Byte urb_outbufinit10_aes2501[0x02] = {
  0x80, 0x02
};

static SANE_Byte urb_init_aes2501[0x7e] = {
            0x80, 0x00, 0x81, 0x00, 0x82, 0x40, 0x83, 0x13,
            0x84, 0x07, 0x85, 0x02, 0x86, 0x01, 0x87, 0x01,
            0x88, 0x03, 0x89, 0x02, 0x8A, 0x05, 0x8B, 0x00,
            0x8C, 0x40, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00,
            0x90, 0x00, 0x91, 0x70, 0x92, 0x20, 0x93, 0x00,
            0x94, 0x0A, 0x95, 0x00, 0x96, 0x7F, 0x97, 0x08,
            0x98, 0x20, 0x99, 0x00, 0x9A, 0x10, 0x9B, 0x00,
            0x9C, 0x00, 0x9D, 0x06, 0x9E, 0x03, 0x9F, 0x21,
            0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00,
            0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x02,
            0xA8, 0x01, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00,
            0xAC, 0x20, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x02,
            0xB0, 0x27, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x0F,
            0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x26, 0xB7, 0x0D,
            0xB8, 0x6C, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00,
            0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00
};

static SANE_Byte urb_outbufwaitfordata1_aes2501[0x04] = {
            0x80, 0x01, 0x82, 0x40
};
static SANE_Byte urb_outbufwaitfordata2_aes2501[0x2a] = {
            0x80, 0x01, 0x82, 0x40, 0x83, 0x00, 0x88, 0x02,
            0x89, 0x10, 0x8A, 0x05, 0x8C, 0x00, 0x8E, 0x13,
            0x91, 0x44, 0x92, 0x34, 0x95, 0x16, 0x96, 0x16,
            0x97, 0x18, 0xA1, 0x70, 0xA2, 0x02, 0xA7, 0x00,
	    0xAC, 0x01, 0xAD, 0x1A, 0x80, 0x04, 0x81, 0x04,
            0xB4, 0x00
};
static SANE_Byte urb_1810_aes2501[0x2a] = {  /* urb 28 */
            0x80, 0x01, 0x82, 0x40, 0x83, 0x00, 0x88, 0x02,
	    0x89, 0x10, 0x8a, 0x05, 0x8c, 0x00, 0x8e, 0x13,
            0x91, 0x44, 0x92, 0x34, 0x95, 0x16, 0x96, 0x16,
	    0x97, 0x18, 0xa1, 0x70, 0xa2, 0x02, 0xa7, 0x00,
            0xac, 0x01, 0xad, 0x1a, 0x80, 0x04, 0x81, 0x04,
	    0xb4, 0x00
};

static SANE_Byte urb_inbufnodataavailable_aes2501[0x14] = {
            0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0xDF, 0x53, 0x35, 0x45, 0x43, 0x32, 0x43,
            0x53, 0x35, 0x9A, 0x16 
};

static SANE_Byte urb_outbufrequestheader_aes2501[0x04] = {
            0x80, 0x01, 0x82, 0x40
};

static SANE_Byte urb_outbufrequestheader1_aes2501[0x32] = {
            0x80, 0x01, 0x82, 0x40, 0x83, 0x00, 0x88, 0x02,
            0x8C, 0x7C, 0x89, 0x10, 0x8D, 0x24, 0x9B, 0x01,
            0x9C, 0x64, 0x9D, 0x67, 0x9E, 0x40, 0x9F, 0x0C,
	    0xA2, 0x02, 0xA7, 0x00, 0xB6, 0x26, 0xB7, 0x1A,
            0x80, 0x04, 0x98, 0x23, 0x95, 0x10, 0x96, 0x1F,
            0x8E, 0x00, 0x91, 0x70, 0x92, 0x20, 0x81, 0x04,
	    0xB4, 0x00
};

static SANE_Byte urb_outbufrequestheader2_aes2501[0x0e] = {
            0x98, 0x23, 0x95, 0x10, 0x96, 0x1F, 0x8E, 0x03,
            0x91, 0x70, 0x92, 0x20, 0x81, 0x04 
};

static SANE_Byte urb_outbufrequestdata_aes2501[0x0e] = {
            0x98, 0x22, 0x95, 0x00, 0x96, 0x2F, 0x8E, 0x03,
            0x91, 0x27, 0x92, 0x25, 0x81, 0x04
};

static SANE_Byte urb_28_aes2501[0x0c] = {
            0x80, 0x01, 0xa8, 0x41, 0x82, 0x42, 0x83, 0x53,
	    0x80, 0x04, 0x81, 0x02
};
static SANE_Byte urb_31_aes2501[0x0e] = {
            0x80, 0x01, 0x82, 0x40, 0xb0, 0x27, 0x94, 0x0a,
	    0x80, 0x04, 0x83, 0x45, 0xa8, 0x41
};



/* mostly from urb init biopod  */
static SANE_Byte urb_aes2501[0x7c] = {
/* Set default values for the sensor fields */
  0xff, 0x00,
  /*  1, BIOPOD_SENSOR_GAIN_1,Gain rate multiple in 1st stage. */
  /*     .. 0 = 2x, 1=4x, 2=8x, 3=16x */
  0x8e, 0x01,
  /*  2, BIOPOD_SENSOR_GAIN_2, Gain rate multiple in 2nd stage. */
  /*     .. 0 = 2x, 1=4x, 2=8x, 3=16x */
  0x8e, 0x45,
  /*  3, BIOPOD_SENSOR_GAIN, Sensor gain (Combination of */
  /*     .. sensor gains 1 & 2.  No longer used.) */
  0xFF, 0x00,
  /*  4, BIOPOD_CARRIER_NULL, Carrier Null  (15..0) 0...-3.8V  */
  0x90, 0x03,
  /*  5, BIOPOD_CARRIER_NULL_E, Carrier Null  Enable */
  0x90, 0x44,
  /*  6, BIOPOD_AD_REF_HI, A/D Reference Hi (0-31).15625-5V */
  0x91, 0x06,
  /*  7, BIOPOD_AD_REF_LO, A/D Reference Lo (0-31).15625-5V */
  0x92, 0x06,
  /*  8, BIOPOD_FINGER_DETECT, Finger Detect Status bit, 1=ON */
  0x9b, 0x00,
  /*  9, BIOPOD_MEASURE_FREQ, Measure Frequency(0-7)125KHz-2MHz */
  0x8a, 0x02,
  /* 10, BIOPOD_MEASURE_DRIVE, Measure Drive (0-3)   0.3/1/2/4V */
  0x89, 0x01,
  /* 11, BIOPOD_DETECT_FREQ, Detect Frequency(0-7) 125KHz-2Mhz */
  0x87, 0x02,
  /* 12, BIOPOD_DETECT_DRIVE, Detect drive (0-3) 0.3/1/2/4V */
  0x86, 0x01,
  /* 13, BIOPOD_MAX_RES, Use max phase resolution */
  0x00, 0x00,
  /* 14, BIOPOD_COLUMN_SCAN_PER, Column Scan period (0-7) 64 uS */
  /*     .. to 2,048 uS. */
  0x88, 0x02,
  /* 15, BIOPOD_FING_DETECT_CAP, Finger detect capacitor (0-127) */
  /*     .. 93.75ff to 11.8 pf */
  0x85, 0x06,
  /* 16, BIOPOD_FING_DETECT_RES, Finger detect resistor (0-7) */
  /*     .. 500 Ohms to 4K Ohms */
  0x84, 0x02,
  /* 17, BIOPOD_Z_MATRIX_ENABLE, Z-matrix enable. */
  0x8f, 0x44,
  /* 18, BIOPOD_DEMOD_PHASE, Demodulation Phase. */
  0x8C, 0x06,
  /* 19, BIOPOD_REVISION_NUMBER, Chip revision number (chip type) */
  0x9D, 0x06,
  /* 20, BIOPOD_START_SCAN_ROW, Starting Image Scan Row. */
  0x93, 0x03,
  /* 21, BIOPOD_END_SCAN_ROW, Ending Image Scan Row. */
  0x94, 0x03,
  /* 22, BIOPOD_DRIVE_BOOST, Drive Boost Bit. */
  0x82, 0x44,
  /* 23, BIOPOD_NORM_PHASE, "Normalized" Phase (no longer used.) */
  0xFF, 0x00,
  /* 24, BIOPOD_IMAGE_DATA_DISABLE, Image Data Disable. */
  0x98, 0x00,
  /* 25, BIOPOD_HISTOGRAM_EACH_ROW, Histogram each row (subarray) */
  0x98, 0x22,
  /* 26, BIOPOD_MASTER_RESET, Master reset bit. */
  0x80, 0x00,
  /* 27, BIOPOD_SET_ONE_SHOT, One shot bit for a single scan. */
  0x81, 0x22,
  /* 28, BIOPOD_READ_REGISTERS, Read registers bit. */
  0x81, 0x11,
  /* 29, BIOPOD_CONTINUOUS_SCAN, Continuous scan bit. */
  0x81, 0x00,
  /* 30, BIOPOD_ASYNC_REGISTER_UPD, Update registers continuously */
  0x80, 0x22,
  /* 31, BIOPOD_EXCITATION_BIAS, Excitation bias current. */
  0x00, 0x00,
  /* 32, BIOPOD_DEBOUNCE_DELAY, Finger detect debounce delay. */
  0x83, 0x45,
  /* 33, BIOPOD_INTEGRATION_TIME, Scan integration time. */
  0x00, 0x00,
  /* 34, BIOPOD_SENSE_AMP_BIAS, Bias current for sense amps. */
  0x00, 0x00,
  /* 35, BIOPOD_Z_MATRIX_VPATT, Z-Matrix vertical pattern. */
  0x8B, 0x23,
  /* 36, BIOPOD_Z_MATRIX_HPATT, Z-Matrix horizontal pattern. */
  0x8B, 0x01,
  /* 37, BIOPOD_DEMOD_PHASE_1, Demodulation phase 1. */
  0x8D, 0x06,
  /* 38, BIOPOD_DEMOD_PHASE_2, Demodulation phase 2. */
  0x8C, 0x06,
  /* 39, BIOPOD_Z_MATRIX_POWER, Z-Matrix power mode, 1=all times */
  0x00, 0x00,
  /* 40, BIOPOD_SAMPLE_HOLD_BIAS, Sample/hold bias current. */
  0x00, 0x00,
  /* 41, BIOPOD_ANALOG_CHAN_BIAS, Analog channel bias current. */
  0x00, 0x00,
  /* 42, BIOPOD_START_COL, Starting column number. */
  0x95, 0x06,
  /* 43, BIOPOD_END_COL, Ending column number. */
  0x96, 0x06,
  /* 44, BIOPOD_DATA_FORMAT, Data format, 0=normal */
  0x00, 0x00,
  /* 45, BIOPOD_THRESHOLD, Threshold value for binary mode. */
  0x97, 0x03,
  /* 46, BIOPOD_TEST_REG_ENABLE, Enable sending of test registers */
  0x98, 0x55,
  /* 47, BIOPOD_HISTOGRAM_FULL_ARY, Histogram over full array. */
  0x98, 0x33,
  /* 48, BIOPOD_HISTOGRAM_ENABLE, Hardware histogram enable. */
  0x98, 0x11,
  /* 49, BIOPOD_GPO_0, General-purpose output (LED) 0. */
  0x99, 0x00,
  /* 50, BIOPOD_GPO_1, General-purpose output (LED) 1. */
  0x99, 0x11,
  /* 51, BIOPOD_GPO_2, General-purpose output (LED) 2. */
  0x99, 0x22,
  /* 52, BIOPOD_GPO_3, General-purpose output (LED) 3. */
  0x99, 0x33,
  /* 53, BIOPOD_Z_MATRIX_DOUBLER, Z-Matrix doubler enable. */
  0x8B, 0x55,
  /* 54, BIOPOD_CHALLENGE_1, Challenge word -- 1 of 5. */
  0x9B, 0x06,
  /* 55, BIOPOD_CHALLENGE_2, Challenge word -- 2 of 5. */
  0x9C, 0x06,
  /* 56, BIOPOD_CHALLENGE_3, Challenge word -- 3 of 5. */
  0x9D, 0x06,
  /* 57, BIOPOD_CHALLENGE_4, Challenge word -- 4 of 5. */
  0x9E, 0x06,
  /* 58, BIOPOD_CHALLENGE_5, Challenge word -- 5 of 5. */
  0x9F, 0x06,
  /* 59, BIOPOD_EXCITATION_SQUARE, Use square wave. */
  0x82, 0x55,
  /* 60, BIOPOD_FORCE_FINGER_ON, Force finger detect. */
  0xA2, 0x11,
  /* 61, BIOPOD_SSI_INT_ENABLE, Enable Sync. Serial Int. */
  0x81, 0x66
};

static SANE_Byte urb_init_biopod[0x7c] = {
/* Set default values for the sensor fields */
  0xff, 0x00,
  /*  1, BIOPOD_SENSOR_GAIN_1,Gain rate multiple in 1st stage. */
  /*     .. 0 = 2x, 1=4x, 2=8x, 3=16x */
  0x8e, 0x01,
  /*  2, BIOPOD_SENSOR_GAIN_2, Gain rate multiple in 2nd stage. */
  /*     .. 0 = 2x, 1=4x, 2=8x, 3=16x */
  0x8e, 0x45,
  /*  3, BIOPOD_SENSOR_GAIN, Sensor gain (Combination of */
  /*     .. sensor gains 1 & 2.  No longer used.) */
  0xFF, 0x00,
  /*  4, BIOPOD_CARRIER_NULL, Carrier Null  (15..0) 0...-3.8V  */
  0x90, 0x03,
  /*  5, BIOPOD_CARRIER_NULL_E, Carrier Null  Enable */
  0x90, 0x44,
  /*  6, BIOPOD_AD_REF_HI, A/D Reference Hi (0-31).15625-5V */
  0x91, 0x06,
  /*  7, BIOPOD_AD_REF_LO, A/D Reference Lo (0-31).15625-5V */
  0x92, 0x06,
  /*  8, BIOPOD_FINGER_DETECT, Finger Detect Status bit, 1=ON */
  0x9b, 0x00,
  /*  9, BIOPOD_MEASURE_FREQ, Measure Frequency(0-7)125KHz-2MHz */
  0x8a, 0x02,
  /* 10, BIOPOD_MEASURE_DRIVE, Measure Drive (0-3)   0.3/1/2/4V */
  0x89, 0x01,
  /* 11, BIOPOD_DETECT_FREQ, Detect Frequency(0-7) 125KHz-2Mhz */
  0x87, 0x02,
  /* 12, BIOPOD_DETECT_DRIVE, Detect drive (0-3) 0.3/1/2/4V */
  0x86, 0x01,
  /* 13, BIOPOD_MAX_RES, Use max phase resolution */
  0x00, 0x00,
  /* 14, BIOPOD_COLUMN_SCAN_PER, Column Scan period (0-7) 64 uS */
  /*     .. to 2,048 uS. */
  0x88, 0x02,
  /* 15, BIOPOD_FING_DETECT_CAP, Finger detect capacitor (0-127) */
  /*     .. 93.75ff to 11.8 pf */
  0x85, 0x06,
  /* 16, BIOPOD_FING_DETECT_RES, Finger detect resistor (0-7) */
  /*     .. 500 Ohms to 4K Ohms */
  0x84, 0x02,
  /* 17, BIOPOD_Z_MATRIX_ENABLE, Z-matrix enable. */
  0x8f, 0x44,
  /* 18, BIOPOD_DEMOD_PHASE, Demodulation Phase. */
  0x8C, 0x06,
  /* 19, BIOPOD_REVISION_NUMBER, Chip revision number (chip type) */
  0x9D, 0x06,
  /* 20, BIOPOD_START_SCAN_ROW, Starting Image Scan Row. */
  0x93, 0x03,
  /* 21, BIOPOD_END_SCAN_ROW, Ending Image Scan Row. */
  0x94, 0x03,
  /* 22, BIOPOD_DRIVE_BOOST, Drive Boost Bit. */
  0x82, 0x44,
  /* 23, BIOPOD_NORM_PHASE, "Normalized" Phase (no longer used.) */
  0xFF, 0x00,
  /* 24, BIOPOD_IMAGE_DATA_DISABLE, Image Data Disable. */
  0x98, 0x00,
  /* 25, BIOPOD_HISTOGRAM_EACH_ROW, Histogram each row (subarray) */
  0x98, 0x22,
  /* 26, BIOPOD_MASTER_RESET, Master reset bit. */
  0x80, 0x00,
  /* 27, BIOPOD_SET_ONE_SHOT, One shot bit for a single scan. */
  0x81, 0x22,
  /* 28, BIOPOD_READ_REGISTERS, Read registers bit. */
  0x81, 0x11,
  /* 29, BIOPOD_CONTINUOUS_SCAN, Continuous scan bit. */
  0x81, 0x00,
  /* 30, BIOPOD_ASYNC_REGISTER_UPD, Update registers continuously */
  0x80, 0x22,
  /* 31, BIOPOD_EXCITATION_BIAS, Excitation bias current. */
  0x00, 0x00,
  /* 32, BIOPOD_DEBOUNCE_DELAY, Finger detect debounce delay. */
  0x83, 0x45,
  /* 33, BIOPOD_INTEGRATION_TIME, Scan integration time. */
  0x00, 0x00,
  /* 34, BIOPOD_SENSE_AMP_BIAS, Bias current for sense amps. */
  0x00, 0x00,
  /* 35, BIOPOD_Z_MATRIX_VPATT, Z-Matrix vertical pattern. */
  0x8B, 0x23,
  /* 36, BIOPOD_Z_MATRIX_HPATT, Z-Matrix horizontal pattern. */
  0x8B, 0x01,
  /* 37, BIOPOD_DEMOD_PHASE_1, Demodulation phase 1. */
  0x8D, 0x06,
  /* 38, BIOPOD_DEMOD_PHASE_2, Demodulation phase 2. */
  0x8C, 0x06,
  /* 39, BIOPOD_Z_MATRIX_POWER, Z-Matrix power mode, 1=all times */
  0x00, 0x00,
  /* 40, BIOPOD_SAMPLE_HOLD_BIAS, Sample/hold bias current. */
  0x00, 0x00,
  /* 41, BIOPOD_ANALOG_CHAN_BIAS, Analog channel bias current. */
  0x00, 0x00,
  /* 42, BIOPOD_START_COL, Starting column number. */
  0x95, 0x06,
  /* 43, BIOPOD_END_COL, Ending column number. */
  0x96, 0x06,
  /* 44, BIOPOD_DATA_FORMAT, Data format, 0=normal */
  0x00, 0x00,
  /* 45, BIOPOD_THRESHOLD, Threshold value for binary mode. */
  0x97, 0x03,
  /* 46, BIOPOD_TEST_REG_ENABLE, Enable sending of test registers */
  0x98, 0x55,
  /* 47, BIOPOD_HISTOGRAM_FULL_ARY, Histogram over full array. */
  0x98, 0x33,
  /* 48, BIOPOD_HISTOGRAM_ENABLE, Hardware histogram enable. */
  0x98, 0x11,
  /* 49, BIOPOD_GPO_0, General-purpose output (LED) 0. */
  0x99, 0x00,
  /* 50, BIOPOD_GPO_1, General-purpose output (LED) 1. */
  0x99, 0x11,
  /* 51, BIOPOD_GPO_2, General-purpose output (LED) 2. */
  0x99, 0x22,
  /* 52, BIOPOD_GPO_3, General-purpose output (LED) 3. */
  0x99, 0x33,
  /* 53, BIOPOD_Z_MATRIX_DOUBLER, Z-Matrix doubler enable. */
  0x8B, 0x55,
  /* 54, BIOPOD_CHALLENGE_1, Challenge word -- 1 of 5. */
  0x9B, 0x06,
  /* 55, BIOPOD_CHALLENGE_2, Challenge word -- 2 of 5. */
  0x9C, 0x06,
  /* 56, BIOPOD_CHALLENGE_3, Challenge word -- 3 of 5. */
  0x9D, 0x06,
  /* 57, BIOPOD_CHALLENGE_4, Challenge word -- 4 of 5. */
  0x9E, 0x06,
  /* 58, BIOPOD_CHALLENGE_5, Challenge word -- 5 of 5. */
  0x9F, 0x06,
  /* 59, BIOPOD_EXCITATION_SQUARE, Use square wave. */
  0x82, 0x55,
  /* 60, BIOPOD_FORCE_FINGER_ON, Force finger detect. */
  0xA2, 0x11,
  /* 61, BIOPOD_SSI_INT_ENABLE, Enable Sync. Serial Int. */
  0x81, 0x66
};

static SANE_Byte urb_size[0x08] = {
  0x93, 0x00,
  0x94, 0x0f,
  0x95, 0x00,
  0x96, 0xc0
};
static SANE_Byte urb_init_udrv[0x06] = {
  0x80, 0x01,
  0x81, 0x07,
  0x97, 0x08
};
static SANE_Byte urb_init_write_udrv[0x06] = {
  0x81, 0x07,
  0x87, 0x01,
  0x99, 0x0c    /* swap byte between 0c and 0x at each write loop */
};

static SANE_Byte urb_init_read_udrv[0x08] = {
  0x93, 0x00,
  0x94, 0x01,
  0x95, 0x00,
  0x96, 0xbf
};
