diff --git a/backend/hp3900.c b/backend/hp3900.c new file mode 100644 index 000000000..459f5d571 --- /dev/null +++ b/backend/hp3900.c @@ -0,0 +1,61 @@ +/* HP Scanjet 3900 series - Stand-alone/SANE Backend controller + + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + + +/* Backend info */ +#define BACKEND_NAME hp3900 +#define BACKEND_VRSN "0.10" +#define BACKEND_AUTHOR "Jonathan Bravo Lopez (JKD)" +#define BACKEND_EMAIL "jkdsoft@gmail.com" +#define BACKEND_URL "http://jkdsoftware.dyndns.org" +#define BACKEND_LICENSE "General Public License (GPL)" + +/* if you want to compile this one as a sane backend then comment next line */ +/* Caution: Sources included in SANE project don't provide hp3900_stdalone.c */ + +/*#define STANDALONE*/ + +#ifdef STANDALONE +#include "hp3900_stdalone.c" +#else +#include "hp3900_sane.c" +#endif diff --git a/backend/hp3900.conf.in b/backend/hp3900.conf.in new file mode 100644 index 000000000..37323c5f3 --- /dev/null +++ b/backend/hp3900.conf.in @@ -0,0 +1,25 @@ +# +# Configuration file for the hp3900 backend +# + +# HP Scanjet 3800 +usb 0x03f0 0x2605 + +# HP Scanjet 3970c +usb 0x03f0 0x2305 + +# HP Scanjet 4070 Photosmart +usb 0x03f0 0x2405 + +# HP Scanjet 4370 +usb 0x03f0 0x4105 + +# HP Scanjet G3010 +usb 0x03f0 0x4205 + +# UMAX Astra 4900/4950 +usb 0x06dc 0x0020 + +# BenQ 5550 +usb 0x04a5 0x2211 + diff --git a/backend/hp3900_config.c b/backend/hp3900_config.c new file mode 100644 index 000000000..6b6f597b4 --- /dev/null +++ b/backend/hp3900_config.c @@ -0,0 +1,5773 @@ +/* HP Scanjet 3900 series - RTS8822 internal config + + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +/* returns device model according to given product and vendor id's */ +static SANE_Int cfg_device_get(SANE_Int product, SANE_Int vendor); + +/* returns information and capabilities about selected chipset model */ +static SANE_Int cfg_chipset_get(SANE_Int model, struct st_chip *chipset); + +/* returns the chipset model for each scanner */ +static SANE_Int cfg_chipset_model_get(SANE_Int device); + +/* buttons for each scanner */ +static SANE_Int cfg_buttons_get(struct st_buttons *reg); + +/* area constrains for each scanner */ +static SANE_Int cfg_constrains_get(struct st_constrains *constrain); + +/* spectrum clock generator for each scanner */ +static SANE_Int cfg_sscg_get(SANE_Int *enable, SANE_Int *mode, SANE_Int *clock); + +/* motor general configuration for each scanner */ +static SANE_Int cfg_motor_get(struct st_motorcfg *reg); + +/* motor resource for each scanner */ +static SANE_Byte *cfg_motor_resource_get(SANE_Byte *size); + +/* sensor general configuration for each scanner */ +static SANE_Int cfg_sensor_get(struct st_sensorcfg *reg); + +/* reference voltages for each scanner */ +static void cfg_refvoltages_get(SANE_Int sensortype, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs); +static void hp3800_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs); +static void hp3970_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs); + +/* offset calibration start and length */ +static void cfg_offset_get(SANE_Int sensortype, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); +static void ua4900_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); +static void hp3800_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); +static void hp3970_offset(SANE_Int sensor, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); +static void hp4370_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); + +/* autoref configuration */ +static void cfg_autoref_get(struct st_autoref *reg); + +/* autoref start effective pixel */ +static SANE_Int cfg_effectivepixel_get(SANE_Int sensortype, SANE_Int resolution); +static SANE_Int ua4900_effectivepixel(SANE_Int resolution); +static SANE_Int hp3800_effectivepixel(SANE_Int resolution); +static SANE_Int hp3970_effectivepixel(SANE_Int sensor, SANE_Int resolution); +static SANE_Int hp4370_effectivepixel(SANE_Int resolution); + +/* default values for gain and offset */ +static SANE_Int cfg_gainoffset_get(SANE_Int sensortype, struct st_gain_offset *reg); +static SANE_Int bq5550_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); +static SANE_Int ua4900_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); +static SANE_Int hp3800_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); +static SANE_Int hp3970_gainoffset(SANE_Int usb, SANE_Int sensor, struct st_gain_offset *myreg); +static SANE_Int hp4370_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); + +/* values to detect optimum pulse-width modulation */ +static SANE_Int cfg_checkstable_get(SANE_Int lamp, struct st_checkstable *check); +static SANE_Int ua4900_checkstable(SANE_Int lamp, struct st_checkstable *check); +static SANE_Int hp3800_checkstable(SANE_Int lamp, struct st_checkstable *check); +static SANE_Int hp3970_checkstable(SANE_Int lamp, struct st_checkstable *check); +static SANE_Int hp4370_checkstable(SANE_Int lamp, struct st_checkstable *check); + +/* fixed pulse-width modulation values */ +static SANE_Int cfg_fixedpwm_get(SANE_Int sensortype, SANE_Int scantype); +static SANE_Int ua4900_fixedpwm(SANE_Int scantype, SANE_Int usb); +static SANE_Int hp3800_fixedpwm(SANE_Int scantype, SANE_Int usb); +static SANE_Int hp3970_fixedpwm(SANE_Int scantype, SANE_Int usb, SANE_Int sensor); +static SANE_Int hp4370_fixedpwm(SANE_Int scantype, SANE_Int usb); + +/* virtual origin (ser and ler references) */ +static void cfg_vrefs_get(SANE_Int sensortype, SANE_Int res, SANE_Int *ser, SANE_Int *ler); +static void hp3800_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler); +static void hp3970_vrefs(SANE_Int usb, SANE_Int sensor, SANE_Int res, SANE_Int *ser, SANE_Int *ler); +static void hp4370_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler); + +/* scanmodes supported by each scanner */ +static SANE_Int cfg_scanmode_get(SANE_Int sensortype, SANE_Int sm, struct st_scanmode *mymode); +static SANE_Int bq5550_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); +static SANE_Int ua4900_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); +static SANE_Int hp3800_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); +static SANE_Int hp3970_scanmodes(SANE_Int usb, SANE_Int ccd, SANE_Int sm, struct st_scanmode *mymode); +static SANE_Int hp4370_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); + +/* timing values for ccd sensors */ +static SANE_Int cfg_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg); +static SANE_Int bq5550_timing_get(SANE_Int tm, struct st_timing *reg); +static SANE_Int ua4900_timing_get(SANE_Int tm, struct st_timing *reg); +static SANE_Int hp3800_timing_get(SANE_Int tm, struct st_timing *reg); +static SANE_Int hp3970_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg); +static SANE_Int hp4370_timing_get(SANE_Int tm, struct st_timing *reg); + +/* motor movements */ +static SANE_Int cfg_motormove_get(SANE_Int sensortype, SANE_Int mm, struct st_motormove *reg); +static SANE_Int bq5550_motormove(SANE_Int item, struct st_motormove *reg); +static SANE_Int hp3800_motormove(SANE_Int item, struct st_motormove *reg); +static SANE_Int hp3970_motormove(SANE_Int usb, SANE_Int ccd, SANE_Int item, struct st_motormove *reg); + +/* motor curves */ +static SANE_Int *cfg_motorcurve_get(void); +static SANE_Int *bq5550_motor(void); +static SANE_Int *hp3800_motor(void); +static SANE_Int *hp3970_motor(void); +static SANE_Int *hp4370_motor(void); + +/* shading cut values */ +static void cfg_shading_cut_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void ua4900_shading_cut(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void hp3800_shading_cut(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void hp3970_shading_cut(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void hp4370_shading_cut(SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); + +/* wrefs values */ +static void cfg_wrefs_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void ua4900_wrefs(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void hp3800_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void hp3970_wrefs(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); +static void hp4370_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); + + +/* DEPRECATED FUNCTIONS !!!!!!!!!!!!!!!!!!! */ + + +static int get_value(int section, int option, int defvalue, int file); + +/* HP Scanjet 3800 */ +static int hp3800_calibreflective(int option, int defvalue); +static int hp3800_calibtransparent(int option, int defvalue); +static int hp3800_calibnegative(int option, int defvalue); +static int srt_hp3800_scanparam_get(int option, int defvalue); + +/* UMAX Astra 4900 */ +static int ua4900_calibreflective(int option, int defvalue); +static int ua4900_calibtransparent(int option, int defvalue); +static int ua4900_calibnegative(int option, int defvalue); + +/* HP Scanjet 3970 */ +static int hp3970_calibreflective(int option, int defvalue); +static int hp3970_calibtransparent(int option, int defvalue); +static int hp3970_calibnegative(int option, int defvalue); +static int srt_hp3970_scanparam_get(int file, int option, int defvalue); +static int srt_hp3970_platform_get(int option, int defvalue); + +/* HP Scanjet 4370 */ +static int hp4370_calibreflective(int option, int defvalue); +static int hp4370_calibtransparent(int option, int defvalue); +static int hp4370_calibnegative(int option, int defvalue); +static int srt_hp4370_scanparam_get(int file, int option, int defvalue); + +/* ----- Implementation ----- */ + +enum ConfigFiles +{ + FITCALIBRATE=0, + + T_RTINIFILE, T_USB1INIFILE, + S_RTINIFILE, S_USB1INIFILE +}; + +enum fcsec6 +{ + SONY_LAMP = 0, TOSHIBA_LAMP, + + CHECKSTABLE, + + CALIBREFLECTIVE, CALIBTRANSPARENT, CALIBNEGATIVEFILM, + + SCANINFO, + SCAN_CALI, + + WSTRIPXPOS, WSTRIPYPOS, + BSTRIPXPOS, BSTRIPYPOS, + + BREFR, BREFG, BREFB, + + REFBITDEPTH, + OFFSETHEIGHT, + + OFFSETNSIGMA, OFFSETTARGETMAX, OFFSETTARGETMIN, + OFFSETAVGTARGETR, OFFSETAVGTARGETG, OFFSETAVGTARGETB, + + ADCOFFEVENODD, + CALIBOFFSET1ON, + + ADCOFFQUICKWAY, ADCOFFPREDICTSTART, ADCOFFPREDICTEND, + + OFFSETTUNESTEP1, OFFSETBOUNDARYRATIO1, OFFSETAVGRATIO1, + + OFFSETEVEN1R, OFFSETEVEN1G, OFFSETEVEN1B, + OFFSETODD1R, OFFSETODD1G, OFFSETODD1B, + + ADCOFFPREDICTR, ADCOFFPREDICTG, ADCOFFPREDICTB, + ADCOFFEVEN1R_1ST, ADCOFFEVEN1G_1ST, ADCOFFEVEN1B_1ST, + ADCOFFODD1R_1ST, ADCOFFODD1G_1ST, ADCOFFODD1B_1ST, + + PEAKR, PEAKG, PEAKB, + MINR, MING, MINB, + + CALIBOFFSET2ON, + OFFSETTUNESTEP2, OFFSETBOUNDARYRATIO2, OFFSETAVGRATIO2, + + OFFSETEVEN2R, OFFSETEVEN2G, OFFSETEVEN2B, + OFFSETODD2R, OFFSETODD2G, OFFSETODD2B, + + GAINHEIGHT, GAINTARGETFACTOR, + + CALIBPAGON, + + HIPAGR, HIPAGG, HIPAGB, + LOPAGR, LOPAGG, LOPAGB, + PAGR, PAGG, PAGB, + + CALIBGAIN1ON, GAIN1R, GAIN1G, GAIN1B, + CALIBGAIN2ON, GAIN2R, GAIN2G, GAIN2B, + + TOTSHADING, + + BSHADINGON, BSHADINGHEIGHT, BSHADINGPREDIFFR, BSHADINGPREDIFFG, BSHADINGPREDIFFB, + BSHADINGDEFCUTOFF, + WSHADINGON, WSHADINGHEIGHT, WSHADINGPREDIFFR, WSHADINGPREDIFFG, WSHADINGPREDIFFB, + + PARKHOMEAFTERCALIB, + + SHADINGTIME_16BIT, SHADOWTIME_16BIT, SHADINGTIME_8BIT, SHADOWTIME_8BIT, + PREVIEWDPI, + + FIRSTDCOFFSETEVEN0, FIRSTDCOFFSETODD0, FIRSTDCOFFSETEVEN1, + FIRSTDCOFFSETODD1, FIRSTDCOFFSETEVEN2, FIRSTDCOFFSETODD2, + + CALIBOFFSET10N, CALIBOFFSET20N, + CALIBGAIN10N, CALIBGAIN20N, + ARRANGELINE, + COMPRESSION, + + TA_X_START, TA_Y_START, + + DPIGAINCONTROL600, + DPIGAINCONTROL_TA600, + DPIGAINCONTROL_NEG600, + + DPILUMPING100, + + CRVS, MLOCK, + ENABLEWARMUP, + + NMAXTARGET, NMINTARGET, + NMAXTARGETTA, NMINTARGETTA, + NMAXTARGETNEG, NMINTARGETNEG, + + STABLEDIFF, + DELTAPWM, + + PWMLAMPENABLED, PWMLAMPLEVEL, + + TMAPWMDUTY, + + PAG1, PAG2, PAG3, + + LEFTLEADING, + + WAVE_XSTART, + + WAVE_S575_XDUMMY_2400, WAVE_S575_XDUMMY_1200, WAVE_S575_XDUMMY_600, + + ODD_DCOFFSET11, ODD_DCOFFSET12, ODD_DCOFFSET13, + ODD_DCOFFSET21, ODD_DCOFFSET22, ODD_DCOFFSET23, + + EVEN_DCOFFSET11, EVEN_DCOFFSET12, EVEN_DCOFFSET13, + EVEN_DCOFFSET21, EVEN_DCOFFSET22, EVEN_DCOFFSET23, + + DCGAIN11, DCGAIN12, DCGAIN13, + DCGAIN21, DCGAIN22, DCGAIN23, + + CRYSTALFREQ, + + PGA1, PGA2, PGA3, + + VGAGAIN11, VGAGAIN12, VGAGAIN13, + + DCSTEPEVEN1, DCSTEPODD1, + DCSTEPEVEN2, DCSTEPODD2, + DCSTEPEVEN3, DCSTEPODD3, + + FIRSTDCOFFSETEVEN11, FIRSTDCOFFSETODD11, + FIRSTDCOFFSETEVEN12, FIRSTDCOFFSETODD12, + FIRSTDCOFFSETEVEN13, FIRSTDCOFFSETODD13, + + DCOFFSETEVEN11, DCOFFSETODD11, + DCOFFSETEVEN12, DCOFFSETODD12, + DCOFFSETEVEN13, DCOFFSETODD13, + + SHADINGBASE, SHADINGFACT1, SHADINGFACT2, SHADINGFACT3, + + PIXELDARKLEVEL, + + EXPOSURETIME, + SCANYSTART, SCANYLINES, + + BINARYTHRESHOLDH, BINARYTHRESHOLDL, + CLOSETIME, + PLATFORM, + SCAN_PARAM, + USB1_PWM, USB2_PWM, + WAVETEST, + DMA_PARAM, + TRUE_GRAY_PARAM, + CALI_PARAM, + DUMMYLINE, + + MEXPT1, MEXPT2, MEXPT3, + EXPT1, EXPT2, EXPT3, + + STARTPOS, + LINEDARLAMPOFF, + MCLKIOC +}; + +static SANE_Int cfg_device_get(SANE_Int product, SANE_Int vendor) +{ + struct st_myreg + { + SANE_Int vendor, product, device; + }; + + struct st_myreg myreg[] = + { + /*vendor, prodct, device */ + { 0x4a5, 0x2211, BQ5550 }, /* BenQ 5550 */ + { 0x6dc, 0x0020, UA4900 }, /* UMAX Astra 4900 */ + { 0x3f0, 0x2605, HP3800 }, /* HP Scanjet 3800 */ + { 0x3f0, 0x2305, HP3970 }, /* HP Scanjet 3970c */ + { 0x3f0, 0x2405, HP4070 }, /* HP Scanjet 4070 Photosmart */ + { 0x3f0, 0x4105, HP4370 }, /* HP Scanjet 4370 */ + { 0x3f0, 0x4205, HPG3010} /* HP Scanjet G3010 */ + }; + + SANE_Int rst = -1; /* default */ + SANE_Int a; + + for (a = 0; a < DEVSCOUNT; a++) + { + if ((vendor == myreg[a].vendor)&&(product == myreg[a].product)) + { + rst = myreg[a].device; + + break; + } + } + + return rst; +} + +static SANE_Int cfg_chipset_model_get(SANE_Int device) +{ + /* returns the chipset model for each scanner */ + struct st_myreg + { + SANE_Int device, chipset; + }; + + struct st_myreg myreg[] = + { + /*device , chipset */ + { HP3800 , RTS8822BL_03A }, + { BQ5550 , RTS8823L_01E }, + { UA4900 , RTS8822L_01H }, + { HP3970 , RTS8822L_01H }, + { HP4070 , RTS8822L_01H }, + { HP4370 , RTS8822L_02A }, + { HPG3010, RTS8822L_02A } + }; + + SANE_Int rst = RTS8822L_01H; /* default */ + SANE_Int a; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (device == myreg[a].device) + { + rst = myreg[a].chipset; + + break; + } + } + + return rst; +} + +static SANE_Int cfg_chipset_get(SANE_Int model, struct st_chip *chipset) +{ + /* returns info and capabilities of selected chipset */ + SANE_Int rst = ERROR; + + if (chipset != NULL) + { + struct st_chip data[] = + { + /* model , capabilities, name */ + {RTS8823L_01E , 0 , "RTS8823L-01E" }, + {RTS8822BL_03A, CAP_EEPROM , "RTS8822BL-03A"}, + {RTS8822L_02A , CAP_EEPROM , "RTS8822L-02A" }, + {RTS8822L_01H , CAP_EEPROM , "RTS8822L-01H" } + }; + + SANE_Int a; + + for (a = 0; a < 4; a++) + { + if (model == data[a].model) + { + /* model found, fill information */ + chipset->model = data[a].model; + chipset->capabilities = data[a].capabilities; + chipset->name = strdup(data[a].name); + + if (chipset->name != NULL) + rst = OK; + + break; + } + } + } + + return rst; +} + +/** SEC: Device's Buttons ---------- */ + +static SANE_Int cfg_buttons_get(struct st_buttons *reg) +{ + /* buttons for each scanner */ + SANE_Int rst = ERROR; + + if (reg != NULL) + { + struct st_myreg + { + SANE_Int device; + struct st_buttons value; + }; + + struct st_myreg myreg[] = + { + /*device, {count, {btn1, btn2, btn3, btn4, btn5, btn6)} */ + { BQ5550 , {3 , {0x01, 0x02, 0x08, -1, -1, -1}}}, + { UA4900 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, + { HP3800 , {3 , {0x01, 0x02, 0x04, -1, -1, -1}}}, + { HP3970 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, + { HP4070 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, + { HP4370 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, + { HPG3010, {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}} + }; + + SANE_Int a; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (RTS_Debug->dev_model == myreg[a].device) + { + memcpy(reg, &myreg[a].value, sizeof(struct st_buttons)); + rst = OK; + + break; + } + } + } + + return rst; +} + +/** SEC: Spectrum clock generator ---------- */ + +static SANE_Int cfg_sscg_get(SANE_Int *enable, SANE_Int *mode, SANE_Int *clock) +{ + SANE_Int rst = ERROR; + + if ((enable != NULL)&&(mode != NULL)&&(clock != NULL)) + { + struct st_myreg + { + SANE_Int device; + SANE_Int value[3]; + }; + + struct st_myreg myreg[] = + { + /*device, {enable, mode, clock} */ + { BQ5550, {1 , 1, 1}}, + { UA4900, {1 , 1, 0}}, + { HP3800, {1 , 1, 0}}, + { HP3970, {1 , 1, 0}}, + { HP4070, {1 , 1, 0}}, + { HP4370, {1 , 1, 0}}, + {HPG3010, {1 , 1, 0}} + }; + + SANE_Int a; + + /* default values */ + *enable = 0; + *mode = 0; + *clock = 3; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (RTS_Debug->dev_model == myreg[a].device) + { + *enable = myreg[a].value[0]; + *mode = myreg[a].value[1]; + *clock = myreg[a].value[2]; + rst = OK; + + break; + } + } + } + return rst; +} + +/** SEC: Motors ---------- */ + +static SANE_Int cfg_motor_get(struct st_motorcfg *reg) +{ + SANE_Int rst = ERROR; + + if (reg != NULL) + { + struct st_myreg + { + SANE_Int device; + struct st_motorcfg motor; + }; + + struct st_myreg myreg[] = + { + /*device, {type , res, freq, speed, basemove, highmove, parkmove, change}} */ + { BQ5550, {MT_OUTPUTSTATE, 1200, 30, 800, 1, 0, 0, TRUE}}, + { UA4900, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, + { HP3800, {MT_OUTPUTSTATE, 1200, 30, 800, 1, 0, 0, TRUE}}, + { HP3970, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, + { HP4070, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, + { HP4370, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, + {HPG3010, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}} + }; + + SANE_Int a; + + /* default values */ + memset(reg, 0, sizeof(struct st_motorcfg)); + reg->type = -1; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (RTS_Debug->dev_model == myreg[a].device) + { + memcpy(reg, &myreg[a].motor, sizeof(struct st_motorcfg)); + rst = OK; + + break; + } + } + } + + return rst; +} + +/** SEC: Sensors ---------- */ + +static SANE_Int cfg_sensor_get(struct st_sensorcfg *reg) +{ + SANE_Int rst = ERROR; + + if (reg != NULL) + { + struct st_myreg + { + SANE_Int device; + struct st_sensorcfg sensor; + }; + + struct st_myreg myreg[] = + { + /*device, {type , name , resolution, {chnl_colors }, {chnl_gray }, {rgb_order }, line_dist, evenodd_dist} */ + { BQ5550, {CCD_SENSOR, -1, 1200 , {CL_BLUE, CL_GREEN, CL_RED }, {CL_GREEN, 0}, {CL_BLUE, CL_GREEN, CL_RED }, 24 , 4 }}, + { UA4900, {CIS_SENSOR, SNYS575, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 24 , 0 }}, + { HP3800, {CCD_SENSOR, TCD2905, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 64 , 8 }}, + { HP3970, {CCD_SENSOR, TCD2952, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 24 , 4 }}, + { HP4070, {CCD_SENSOR, TCD2952, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 24 , 4 }}, + { HP4370, {CCD_SENSOR, TCD2958, 4800 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 128 , 6 }}, + {HPG3010, {CCD_SENSOR, TCD2958, 4800 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 128 , 6 }} + }; + + SANE_Int a; + + /* default values */ + memset(reg, 0, sizeof(struct st_sensorcfg)); + reg->type = -1; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (RTS_Debug->dev_model == myreg[a].device) + { + memcpy(reg, &myreg[a].sensor, sizeof(struct st_sensorcfg)); + rst = OK; + + break; + } + } + } + + return rst; +} + +/** SEC: Reference voltages ---------- */ + +static void hp3800_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs) +{ + /* this function returns top, middle and bottom reference voltages for each scanner */ + struct st_reg + { + SANE_Int usb; + SANE_Int sensor; + SANE_Byte values[3]; + }; + + struct st_reg myreg[] = + { + /* usb, sensor , {vrts, vrms, vrbs} */ + {USB20, CCD_SENSOR, { 2, 3, 2}}, + {USB11, CCD_SENSOR, { 2, 3, 2}}, + }; + + if ((vrts != NULL)&&(vrms != NULL)&&(vrbs != NULL)) + { + SANE_Int a; + + *vrts = *vrms = *vrbs = 0; + + for (a = 0; a < 2; a++) + { + if ((myreg[a].usb == usb)&&(myreg[a].sensor == sensor)) + { + *vrts = myreg[a].values[0]; + *vrms = myreg[a].values[1]; + *vrbs = myreg[a].values[2]; + } + } + } +} + +static void hp3970_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs) +{ + /* this function returns top, middle and bottom reference voltages for each scanner */ + struct st_reg + { + SANE_Int usb; + SANE_Int sensor; + SANE_Byte values[3]; + }; + + struct st_reg myreg[] = + { + /* usb, sensor , {vrts, vrms, vrbs} */ + {USB20, CCD_SENSOR, { 0, 0, 0}}, + {USB11, CCD_SENSOR, { 0, 0, 0}}, + {USB20, CIS_SENSOR, { 0, 0, 0}}, + {USB11, CIS_SENSOR, { 0, 0, 0}} + }; + + if ((vrts != NULL)&&(vrms != NULL)&&(vrbs != NULL)) + { + SANE_Int a; + + *vrts = *vrms = *vrbs = 0; + + for (a = 0; a < 4; a++) + { + if ((myreg[a].usb == usb)&&(myreg[a].sensor == sensor)) + { + *vrts = myreg[a].values[0]; + *vrms = myreg[a].values[1]; + *vrbs = myreg[a].values[2]; + } + } + } +} + +static void cfg_refvoltages_get(SANE_Int sensortype, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs) +{ + /* this function returns top, middle and bottom reference voltages for each scanner */ + switch(RTS_Debug->dev_model) + { + case HP3800: + hp3800_refvoltages(RTS_Debug->usbtype, sensortype, vrts, vrms, vrbs); + break; + default: + /* at this momment all analyzed scanners have the same values */ + hp3970_refvoltages(RTS_Debug->usbtype, sensortype, vrts, vrms, vrbs); + break; + } +} + +/** SEC: Calibration Offset ---------- */ + +static void hp3800_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) +{ + /* this function provides left coordinate and width to calculate offset + Sensor = Toshiba T2905 + */ + + struct st_ofst + { + SANE_Int left; + SANE_Int width; + }; + + struct st_reg + { + SANE_Int resolution; + struct st_ofst values[3]; + }; + + struct st_reg myreg[] = + { + /*res , {ref(L,W), tma(L,W), neg(L,W)} */ + { 2400, {{15, 20}, {15, 20}, {15, 20}}}, + { 1200, {{10, 10}, {10, 10}, {10, 10}}}, + { 600, {{ 2, 10}, { 5, 10}, { 5, 10}}}, + { 300, {{ 1, 5}, { 1, 5}, { 1, 5}}}, + { 150, {{ 0, 3}, { 0, 3}, { 0, 3}}} + }; + + if ((left != NULL)&&(width != NULL)) + { + SANE_Int a; + + for (a = 0; a < 5; a++) + { + if (myreg[a].resolution == resolution) + { + scantype--; + + *left = myreg[a].values[scantype].left; + *width = myreg[a].values[scantype].width; + + break; + } + } + } +} + +static void hp3970_offset(SANE_Int sensor, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) +{ + /* this function provides left coordinate and width to calculate offset */ + + struct st_ofst + { + SANE_Int left; + SANE_Int width; + }; + + struct st_reg + { + SANE_Int sensor; + SANE_Int resolution; + struct st_ofst values[3]; + }; + + struct st_reg myreg[] = + { + /* sensor , res , {ref(L,W), tma(L,W), neg(L,W)} */ + {CCD_SENSOR, 2400, {{16, 20}, {16, 20}, {16, 20}}}, + {CCD_SENSOR, 1200, {{16, 10}, {16, 10}, {16, 10}}}, + {CCD_SENSOR, 600, {{15, 10}, {15, 10}, {15, 10}}}, + {CCD_SENSOR, 300, {{ 7, 5}, { 7, 5}, { 7, 5}}}, + {CCD_SENSOR, 200, {{ 7, 3}, { 7, 3}, { 7, 3}}}, + {CCD_SENSOR, 100, {{ 3, 3}, { 3, 3}, { 3, 3}}}, + + /* sensor , res , {ref(L,W), tma(L,W), neg(L,W)} */ + {CIS_SENSOR, 2400, {{84, 20}, {84, 20}, {84, 20}}}, + {CIS_SENSOR, 1200, {{54, 10}, {54, 10}, {54, 10}}}, + {CIS_SENSOR, 600, {{28, 10}, {28, 10}, {28, 10}}}, + {CIS_SENSOR, 300, {{15, 5}, {15, 5}, {15, 5}}}, + {CIS_SENSOR, 200, {{ 5, 3}, { 5, 3}, { 5, 3}}}, + {CIS_SENSOR, 100, {{ 2, 3}, { 2, 3}, { 2, 3}}} + }; + + if ((left != NULL)&&(width != NULL)) + { + SANE_Int a; + + for (a = 0; a < 12; a++) + { + if ((myreg[a].sensor == sensor)&&(myreg[a].resolution == resolution)) + { + scantype--; + + *left = myreg[a].values[scantype].left; + *width = myreg[a].values[scantype].width; + + break; + } + } + } +} + +static void hp4370_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) +{ + /* this function provides left coordinate and width to calculate offset */ + + struct st_ofst + { + SANE_Int left; + SANE_Int width; + }; + + struct st_reg + { + SANE_Int resolution; + struct st_ofst values[3]; + }; + + struct st_reg myreg[] = + { + /* res, {ref(L,W), tma(L,W), neg(L,W)} */ + { 4800, {{42, 20}, {42, 20}, {52, 26}}}, + { 2400, {{14, 20}, {14, 20}, {14, 26}}}, + { 1200, {{ 8, 14}, { 8, 14}, { 8, 14}}}, + { 600, {{ 4, 8}, { 4, 8}, { 4, 8}}}, + { 300, {{ 2, 4}, { 2, 4}, { 2, 4}}}, + { 150, {{ 1, 2}, { 1, 2}, { 1, 2}}} + }; + + if ((left != NULL)&&(width != NULL)) + { + SANE_Int a; + + for (a = 0; a < 6; a++) + { + if (myreg[a].resolution == resolution) + { + scantype--; + + *left = myreg[a].values[scantype].left; + *width = myreg[a].values[scantype].width; + + break; + } + } + } +} + +static void ua4900_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) +{ + /* this function provides left coordinate and width to calculate offset */ + + struct st_ofst + { + SANE_Int left; + SANE_Int width; + }; + + struct st_reg + { + SANE_Int resolution; + struct st_ofst values[3]; + }; + + struct st_reg myreg[] = + { + /* res , {ref(L,W), tma(L,W), neg(L,W)} */ + { 2400, {{20, 20}, {16, 20}, {16, 20}}}, + { 1200, {{20, 10}, {10, 10}, {10, 10}}}, + { 600, {{ 7, 10}, {15, 10}, {15, 10}}}, + { 300, {{ 5, 10}, { 7, 8}, { 7, 8}}}, + { 200, {{ 2, 10}, { 7, 6}, { 7, 6}}}, + { 100, {{ 0, 10}, { 3, 4}, { 3, 4}}} + }; + + if ((left != NULL)&&(width != NULL)) + { + SANE_Int a; + + for (a = 0; a < 12; a++) + { + if (myreg[a].resolution == resolution) + { + scantype--; + + *left = myreg[a].values[scantype].left; + *width = myreg[a].values[scantype].width; + + break; + } + } + } +} + +static void cfg_offset_get(SANE_Int sensortype, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) +{ + switch(RTS_Debug->dev_model) + { + case UA4900: + ua4900_offset(resolution, scantype, left, width); + break; + + case HP3800: + hp3800_offset(resolution, scantype, left, width); + break; + + case HPG3010: + case HP4370: + hp4370_offset(resolution, scantype, left, width); + break; + + default: + hp3970_offset(sensortype, resolution, scantype, left, width); + break; + } +} + +/** SEC: Device constrains ---------- */ + +static SANE_Int cfg_constrains_get(struct st_constrains *constrain) +{ + SANE_Int rst = ERROR; + + struct st_reg + { + SANE_Int device; + struct st_constrains constrain; + }; + + struct st_reg reg[] = + { + /* constrains are set in milimeters */ + /*device , reflective , negative , transparent */ + /* , {{left, width, top, height}, {left, width, top, height}, {left, width, top, height}}}, */ + { BQ5550 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, + { HP3800 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, + { HP3970 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, + { HP4070 , {{ 0, 220, 0, 300}, { 58, 99, 0, 197}, { 58, 99, 0, 197}}}, + { HP4370 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, + { UA4900 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, + {HPG3010 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}} + }; + + if (constrain != NULL) + { + SANE_Int a; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (reg[a].device == RTS_Debug->dev_model) + { + memcpy(constrain, ®[a].constrain, sizeof(struct st_constrains)); + rst = OK; + break; + } + } + } + + return rst; +} + +/** SEC: Motor resource ------------------- */ +static SANE_Byte *cfg_motor_resource_get(SANE_Byte *size) +{ + /* this function returns the proper motor resources for a given device */ + SANE_Byte *rst = NULL; + + /* Until now, resource size is always 32 bytes */ + rst = (SANE_Byte *)malloc(sizeof(SANE_Byte) * 32); + if (size != NULL) + *size = 0; + + if (rst != NULL) + { + bzero(rst, sizeof(SANE_Byte) * 32); + + switch(RTS_Debug->dev_model) + { + case BQ5550: + { + SANE_Byte Resource[] = {0xff, 0xb4, 0xb0, 0xd4, 0xd0, 0x70, 0x50, 0x54, 0x30, 0x34, 0x14, 0x38, 0x18, 0x0c, 0x08, 0x28, 0x04, 0x24, 0x20, 0x44, 0x40, 0xe0, 0xc0, 0xc4, 0xa0, 0xa4, 0x84, 0xa8, 0x88, 0x9c, 0x98, 0xb8}; + memcpy(rst, &Resource, sizeof(SANE_Byte) * 32); + if (size != NULL) + *size = 32; + } + break; + default: + { + SANE_Byte Resource[] = {0xff, 0x90, 0xb0, 0xd4, 0xd0, 0x70, 0x50, 0x54, 0x30, 0x10, 0x14, 0x38, 0x18, 0x0c, 0x08, 0x28, 0x04, 0x00, 0x20, 0x44, 0x40, 0xe0, 0xc0, 0xc4, 0xa0, 0x80, 0x84, 0xa8, 0x88, 0x9c, 0x98, 0xb8}; + memcpy(rst, &Resource, sizeof(SANE_Byte) * 32); + if (size != NULL) + *size = 32; + } + break; + } + } + + return rst; +} + +/** SEC: Auto reference position ---------- */ + +static void cfg_autoref_get(struct st_autoref *reg) +{ + if (reg != NULL) + { + struct st_reg + { + SANE_Int device; + struct st_autoref value; + }; + + struct st_reg myreg[] = + { + /* device, { type , x , y , resolution, extern_boundary}*/ + { BQ5550 , {REF_NONE , -40, -40, 600 , 40}}, + { UA4900 , {REF_NONE , -40, -40, 600 , 40}}, + { HP3800 , {REF_TAKEFROMSCANNER, 88, 624, 600 , 40}}, + { HP3970 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, + { HP4070 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, + { HP4370 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, + {HPG3010 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}} + }; + + SANE_Int a; + + for (a = 0; a < DEVSCOUNT; a++) + { + if (myreg[a].device == RTS_Debug->dev_model) + { + memcpy(reg, &myreg[a].value, sizeof(struct st_autoref)); + break; + } + } + } +} + +static SANE_Int hp3800_effectivepixel(SANE_Int resolution) +{ + struct st_reg + { + SANE_Int resolution; + SANE_Int pixel; + }; + + struct st_reg reg[] = + { + /* res , pixel */ + { 2400, 134 }, + { 1200, 134 }, + { 600, 230 }, + { 300, 172 }, + { 200, 230 }, + { 100, 230 } + }; + + SANE_Int a; + SANE_Int rst = 230; /* default */ + + for (a = 0; a < 6; a++) + { + if (reg[a].resolution == resolution) + { + rst = reg[a].pixel; + break; + } + } + + return rst; +} + +static SANE_Int hp3970_effectivepixel(SANE_Int sensor, SANE_Int resolution) +{ + struct st_reg + { + SANE_Int resolution; + SANE_Int pixel[2]; + }; + + struct st_reg reg[] = + { + /* res , {Toshiba, sony}} */ + { 2400, {134 , 218 }}, + { 1200, {134 , 240 }}, + { 600, {230 , 242 }}, + { 300, {160 , 172 }}, + { 200, {230 , 242 }}, + { 100, {230 , 242 }} + }; + + SANE_Int a; + SANE_Int rst = 230; /* default */ + + for (a = 0; a < 6; a++) + { + if (reg[a].resolution == resolution) + { + rst = (sensor == CCD_SENSOR)? reg[a].pixel[0] : reg[a].pixel[1]; + break; + } + } + + return rst; +} + +static SANE_Int hp4370_effectivepixel(SANE_Int resolution) +{ + struct st_reg + { + SANE_Int resolution; + SANE_Int pixel; + }; + + struct st_reg reg[] = + { + /* res , pxl */ + { 4800, 134}, + { 2400, 134}, + { 1200, 134}, + { 600, 230}, + { 300, 230}, + { 150, 230} + }; + + SANE_Int a; + SANE_Int rst = 230; /* default */ + + for (a = 0; a < 6; a++) + { + if (reg[a].resolution == resolution) + { + rst = reg[a].pixel; + break; + } + } + + return rst; +} + +static SANE_Int ua4900_effectivepixel(SANE_Int resolution) +{ + struct st_reg + { + SANE_Int resolution; + SANE_Int pixel; + }; + + struct st_reg reg[] = + { + /* res , pixel */ + { 2400, 134 }, + { 1200, 134 }, + { 600, 230 }, + { 300, 172 }, + { 200, 230 }, + { 100, 230 } + }; + + SANE_Int a; + SANE_Int rst = 230; /* default */ + + for (a = 0; a < 6; a++) + { + if (reg[a].resolution == resolution) + { + rst = reg[a].pixel; + break; + } + } + + return rst; +} + +static SANE_Int cfg_effectivepixel_get(SANE_Int sensortype, SANE_Int resolution) +{ + SANE_Int rst; + + switch(RTS_Debug->dev_model) + { + case UA4900: + rst = ua4900_effectivepixel(resolution); + break; + + case HP3800: + rst = hp3800_effectivepixel(resolution); + break; + + case HP4370: + case HPG3010: + rst = hp4370_effectivepixel(resolution); + break; + + default: + rst = hp3970_effectivepixel(sensortype, resolution); + break; + } + + return rst; +} + +/** SEC: Gain and offset values ---------- */ + +static SANE_Int bq5550_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) +{ + struct st_reg + { + SANE_Int usb; + struct st_gain_offset values; + }; + + struct st_reg reg[] = + { + /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ + { USB20, {{264, 264, 264}, {0, 0, 0}, {262, 262, 262}, {0, 0, 0}, {3, 3, 3}, {27, 27, 27}, {4, 4, 4}}}, + { USB11, {{264, 264, 264}, {0, 0, 0}, {262, 262, 262}, {0, 0, 0}, {3, 3, 3}, {27, 27, 27}, {4, 4, 4}}} + }; + + SANE_Int rst = ERROR; + + if (myreg != NULL) + { + SANE_Int a; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int hp3800_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) +{ + struct st_reg + { + SANE_Int usb; + struct st_gain_offset values; + }; + + struct st_reg reg[] = + { + /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ + { USB20, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {2, 2, 2}, {4, 4, 4}, {4, 4, 4}}}, + { USB11, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {2, 2, 2}, {4, 4, 4}, {4, 4, 4}}} + }; + + SANE_Int rst = ERROR; + + if (myreg != NULL) + { + SANE_Int a; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int hp3970_gainoffset(SANE_Int usb, SANE_Int sensor, struct st_gain_offset *myreg) +{ + struct st_reg + { + SANE_Int usb; + SANE_Int sensor; + struct st_gain_offset values; + }; + + struct st_reg reg[] = + { + /* usb , sensor , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ + { USB20, CCD_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, + { USB11, CCD_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, + + { USB20, CIS_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, + { USB11, CIS_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}} + }; + + SANE_Int rst = ERROR; + + if (myreg != NULL) + { + SANE_Int a; + + for (a = 0; a < 4; a++) + { + if ((reg[a].usb == usb)&&(reg[a].sensor == sensor)) + { + memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int hp4370_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) +{ + struct st_reg + { + SANE_Int usb; + struct st_gain_offset values; + }; + + struct st_reg reg[] = + { + /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }} */ + { USB20, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, + { USB11, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}} + }; + + SANE_Int rst = ERROR; + + if (myreg != NULL) + { + SANE_Int a; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int ua4900_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) +{ + struct st_reg + { + SANE_Int usb; + struct st_gain_offset values; + }; + + struct st_reg reg[] = + { + /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ + { USB20, {{321, 321, 321}, {0, 0, 0}, {321, 321, 321}, {0, 0, 0}, {0, 0, 0}, {24, 21, 19}, {8, 8, 8}}}, + { USB11, {{321, 321, 321}, {0, 0, 0}, {321, 321, 321}, {0, 0, 0}, {0, 0, 0}, {16, 16, 16}, {4, 4, 4}}} + }; + + SANE_Int rst = ERROR; + + if (myreg != NULL) + { + SANE_Int a; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int cfg_gainoffset_get(SANE_Int sensortype, struct st_gain_offset *reg) +{ + SANE_Int rst; + + switch(RTS_Debug->dev_model) + { + case BQ5550: + rst = bq5550_gainoffset(RTS_Debug->usbtype, reg); + break; + + case UA4900: + rst = ua4900_gainoffset(RTS_Debug->usbtype, reg); + break; + + case HP3800: + rst = hp3800_gainoffset(RTS_Debug->usbtype, reg); + break; + + case HP4370: + case HPG3010: + rst = hp4370_gainoffset(RTS_Debug->usbtype, reg); + break; + + default: + rst = hp3970_gainoffset(RTS_Debug->usbtype, sensortype, reg); + break; + } + + return rst; +} + +/** SEC: Pulse-width modulation check stable ---------- */ + +static SANE_Int hp3800_checkstable(SANE_Int lamp, struct st_checkstable *check) +{ + struct st_reg + { + SANE_Int lamp; + struct st_checkstable values; + }; + + struct st_reg reg[] = + { + /* lamp , { diff, interval, tottime } */ + { 0 , { 100., 200, 10000}}, + { FLB_LAMP, { 100., 200, 10000}}, + { TMA_LAMP, { 100., 200, 10000}} + }; + + SANE_Int rst = ERROR; + + if (reg != NULL) + { + SANE_Int a; + + for (a = 0; a < 3; a++) + { + if (reg[a].lamp == lamp) + { + memcpy(check, ®[a].values, sizeof(struct st_checkstable)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int hp3970_checkstable(SANE_Int lamp, struct st_checkstable *check) +{ + struct st_reg + { + SANE_Int lamp; + struct st_checkstable values; + }; + + struct st_reg reg[] = + { + /* lamp , { diff, interval, tottime } */ + { 0 , {1000., 200, 5000}}, + { FLB_LAMP, { 500., 200, 5000}}, + { TMA_LAMP, { 500., 200, 5000}} + }; + + SANE_Int rst = ERROR; + + if (reg != NULL) + { + SANE_Int a; + + for (a = 0; a < 3; a++) + { + if (reg[a].lamp == lamp) + { + memcpy(check, ®[a].values, sizeof(struct st_checkstable)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int hp4370_checkstable(SANE_Int lamp, struct st_checkstable *check) +{ + struct st_reg + { + SANE_Int lamp; + struct st_checkstable values; + }; + + struct st_reg reg[] = + { + /* lamp , { diff, interval, tottime } */ + { 0 , { 100., 200, 5000}}, + { FLB_LAMP, { 300., 200, 5000}}, + { TMA_LAMP, { 0., 200, 25000}} + }; + + SANE_Int rst = ERROR; + + if (reg != NULL) + { + SANE_Int a; + + for (a = 0; a < 3; a++) + { + if (reg[a].lamp == lamp) + { + memcpy(check, ®[a].values, sizeof(struct st_checkstable)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int ua4900_checkstable(SANE_Int lamp, struct st_checkstable *check) +{ + struct st_reg + { + SANE_Int lamp; + struct st_checkstable values; + }; + + struct st_reg reg[] = + { + /* lamp , { diff, interval, tottime } */ + { 0 , { 100., 200, 5000}}, + { FLB_LAMP, { 10., 200, 5000}}, + { TMA_LAMP, { 10., 200, 25000}} + }; + + SANE_Int rst = ERROR; + + if (reg != NULL) + { + SANE_Int a; + + for (a = 0; a < 3; a++) + { + if (reg[a].lamp == lamp) + { + memcpy(check, ®[a].values, sizeof(struct st_checkstable)); + rst = OK; + break; + } + } + } + + return rst; +} + +static SANE_Int cfg_checkstable_get(SANE_Int lamp, struct st_checkstable *check) +{ + SANE_Int rst; + + switch(RTS_Debug->dev_model) + { + case UA4900: + rst = ua4900_checkstable(lamp, check); + break; + + case HP3800: + rst = hp3800_checkstable(lamp, check); + break; + + case HP4370: + case HPG3010: + rst = hp4370_checkstable(lamp, check); + break; + + default: + rst = hp3970_checkstable(lamp, check); + break; + } + + return rst; +} + +/** SEC: Fixed pulse-width modulation values ---------- */ + +static SANE_Int hp3800_fixedpwm(SANE_Int scantype, SANE_Int usb) +{ + struct st_reg + { + SANE_Int usb; + SANE_Int pwm[3]; + }; + + struct st_reg reg[] = + { + /* usb , { ST_NORMAL, ST_TA, ST_NEG} */ + { USB20, { 0, 0, 0}}, + { USB11, { 0, 0, 0}} + }; + + SANE_Int a, rst = 0x16; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) + scantype = ST_NORMAL; + + rst = reg[a].pwm[scantype - 1]; + break; + } + } + + return rst; +} + +static SANE_Int hp3970_fixedpwm(SANE_Int scantype, SANE_Int usb, SANE_Int sensor) +{ + struct st_reg + { + SANE_Int usb; + SANE_Int sensor; + SANE_Int pwm[3]; + }; + + struct st_reg reg[] = + { + /* usb , sensor , { ST_NORMAL, ST_TA, ST_NEG} */ + { USB20, CCD_SENSOR, { 22, 22, 22}}, + { USB11, CCD_SENSOR, { 22, 22, 22}}, + + { USB20, CIS_SENSOR, { 22, 22, 22}}, + { USB11, CIS_SENSOR, { 22, 22, 22}} + }; + + SANE_Int a, rst = 0x16; + + for (a = 0; a < 4; a++) + { + if ((reg[a].usb == usb)&&(reg[a].sensor == sensor)) + { + if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) + scantype = ST_NORMAL; + + rst = reg[a].pwm[scantype - 1]; + break; + } + } + + return rst; +} + +static SANE_Int hp4370_fixedpwm(SANE_Int scantype, SANE_Int usb) +{ + struct st_reg + { + SANE_Int usb; + SANE_Int pwm[3]; + }; + + struct st_reg reg[] = + { + /* usb , { ST_NORMAL, ST_TA, ST_NEG} */ + { USB20, { 20, 28, 28}}, + { USB11, { 20, 28, 28}} + }; + + SANE_Int a, rst = 0x16; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) + scantype = ST_NORMAL; + + rst = reg[a].pwm[scantype - 1]; + break; + } + } + + return rst; +} + +static SANE_Int ua4900_fixedpwm(SANE_Int scantype, SANE_Int usb) +{ + struct st_reg + { + SANE_Int usb; + SANE_Int pwm[3]; + }; + + struct st_reg reg[] = + { + /* usb , { ST_NORMAL, ST_TA, ST_NEG} */ + { USB20, { 20, 28, 28}}, + { USB11, { 20, 28, 28}} + }; + + SANE_Int a, rst = 0x16; + + for (a = 0; a < 2; a++) + { + if (reg[a].usb == usb) + { + if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) + scantype = ST_NORMAL; + + rst = reg[a].pwm[scantype - 1]; + break; + } + } + + return rst; +} + +static SANE_Int cfg_fixedpwm_get(SANE_Int sensortype, SANE_Int scantype) +{ + SANE_Int rst; + + switch(RTS_Debug->dev_model) + { + case UA4900: + rst = ua4900_fixedpwm(scantype, RTS_Debug->usbtype); + break; + + case HP3800: + rst = hp3800_fixedpwm(scantype, RTS_Debug->usbtype); + break; + + case HP4370: + case HPG3010: + rst = hp4370_fixedpwm(scantype, RTS_Debug->usbtype); + break; + + default: + rst = hp3970_fixedpwm(scantype, RTS_Debug->usbtype, sensortype); + break; + } + + return rst; +} + +/** SEC: Fixed reference positions ---------- */ + +static void cfg_vrefs_get(SANE_Int sensortype, SANE_Int res, SANE_Int *ser, SANE_Int *ler) +{ + switch(RTS_Debug->dev_model) + { + case HP3800: + hp3800_vrefs(res, ser, ler); + break; + + case HP4370: + case HPG3010: + hp4370_vrefs(res, ser, ler); + break; + + default: + hp3970_vrefs(RTS_Debug->usbtype, sensortype, res, ser, ler); + break; + } +} + +static void hp3800_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler) +{ + struct st_reg + { + SANE_Int resolution; + SANE_Int vref[2]; + }; + + struct st_reg reg[] = + { + /* res, { ser, ler} */ + { 150, { 25, 50}}, + { 300, { 50, 101}}, + { 600, { 102, 202}}, + { 1200, { 204, 404}}, + { 2400, { 408, 808}} + }; + + SANE_Int total = 5; + + if ((ser != NULL)&&(ler != NULL)) + { + SANE_Int a; + + /* values by default */ + *ser = *ler = 0; + + for (a = 0; a < total; a++) + { + if (reg[a].resolution == res) + { + *ser = reg[a].vref[0]; + *ler = reg[a].vref[1]; + break; + } + } + } +} + +static void hp3970_vrefs(SANE_Int usb, SANE_Int sensor, SANE_Int res, SANE_Int *ser, SANE_Int *ler) +{ + struct st_reg + { + SANE_Int usb; + SANE_Int sensor; + SANE_Int resolution; + SANE_Int vref[2]; + }; + + /* I think these references should be the same in all usb versions and in + all sensor types but windows driver has some different values in some cases. + */ + + struct st_reg reg[] = + { + /* usb , sensor , res, { ser, ler} */ + { USB20, CCD_SENSOR, 100, { 28, 60}}, + { USB20, CCD_SENSOR, 200, { 37, 117}}, + { USB20, CCD_SENSOR, 300, { 52, 162}}, + { USB20, CCD_SENSOR, 600, { 103, 344}}, + { USB20, CCD_SENSOR, 1200, { 156, 660}}, + { USB20, CCD_SENSOR, 2400, { 309, 1262}}, + + /* usb , sensor , res, { ser, ler} */ + { USB11, CCD_SENSOR, 100, { 28, 60}}, + { USB11, CCD_SENSOR, 200, { 37, 117}}, + { USB11, CCD_SENSOR, 300, { 52, 162}}, + { USB11, CCD_SENSOR, 600, { 103, 344}}, + { USB11, CCD_SENSOR, 1200, { 156, 660}}, + { USB11, CCD_SENSOR, 2400, { 309, 1262}}, + + /* usb , sensor , res, { ser, ler} */ + { USB20, CIS_SENSOR, 100, { 15, 60}}, + { USB20, CIS_SENSOR, 200, { 39, 117}}, + { USB20, CIS_SENSOR, 300, { 56, 161}}, + { USB20, CIS_SENSOR, 600, { 108, 342}}, + { USB20, CIS_SENSOR, 1200, { 221, 642}}, + { USB20, CIS_SENSOR, 2400, { 407, 1285}}, + + /* usb , sensor , res, { ser, ler} */ + { USB11, CIS_SENSOR, 100, { 15, 60}}, + { USB11, CIS_SENSOR, 200, { 39, 117}}, + { USB11, CIS_SENSOR, 300, { 56, 161}}, + { USB11, CIS_SENSOR, 600, { 108, 342}}, + { USB11, CIS_SENSOR, 1200, { 221, 642}}, + { USB11, CIS_SENSOR, 2400, { 407, 1285}} + }; + + if ((ser != NULL)&&(ler != NULL)) + { + SANE_Int a; + + /* values by default */ + *ser = *ler = 0; + + for (a = 0; a < 24; a++) + { + if ((reg[a].usb == usb)&&(reg[a].sensor == sensor)&&(reg[a].resolution == res)) + { + *ser = reg[a].vref[0]; + *ler = reg[a].vref[1]; + break; + } + } + } +} + +static void hp4370_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler) +{ + struct st_reg + { + SANE_Int resolution; + SANE_Int vref[2]; + }; + + struct st_reg reg[] = + { + /* res, { ser, ler} */ + { 150, { 31, 81}}, + { 300, { 61, 162}}, + { 600, { 122, 324}}, + { 1200, { 244, 648}}, + { 2400, { 488, 1256}}, + { 4800, { 976, 2512}} + }; + + if ((ser != NULL)&&(ler != NULL)) + { + SANE_Int a; + + /* values by default */ + *ser = *ler = 0; + + for (a = 0; a < 6; a++) + { + if (reg[a].resolution == res) + { + *ser = reg[a].vref[0]; + *ler = reg[a].vref[1]; + break; + } + } + } +} + +/** SEC: Motor movements ---------- */ + +static SANE_Int cfg_motormove_get(SANE_Int sensortype, SANE_Int item, struct st_motormove *reg) +{ + SANE_Int rst = ERROR; + + switch(RTS_Debug->dev_model) + { + case BQ5550: + rst = bq5550_motormove(item, reg); + break; + case HP3800: + rst = hp3800_motormove(item, reg); + break; + + default: + rst = hp3970_motormove(RTS_Debug->usbtype, sensortype, item, reg); + break; + } + + return rst; +} + +static SANE_Int bq5550_motormove(SANE_Int item, struct st_motormove *reg) +{ + SANE_Int rst = ERROR; + + /* data is the same in all usb types and sensors so those args aren't needed */ + + if (reg != NULL) + { + struct st_motormove mv[] = + { + /* systemclock, ctpc, steptype , motorcurve } */ + { 0x05 , 4059, STT_HALF , 0 }, + { 0x02 , 1200, STT_QUART, -1 } + }; + + rst = OK; + + if ((item < 2)&&(item > -1)) + memcpy(reg, &mv[item], sizeof(struct st_motormove)); + else rst = ERROR; + } + + return rst; +} + +static SANE_Int hp3800_motormove(SANE_Int item, struct st_motormove *reg) +{ + SANE_Int rst = ERROR; + + /* data is the same in all usb types and sensors so those args aren't needed */ + + if (reg != NULL) + { + struct st_motormove mv[] = + { + /* systemclock, ctpc, steptype, motorcurve } */ + { 0x04 , 1991, STT_HALF, 2 }, + { 0x02 , 1991, STT_HALF, -1 } + }; + + rst = OK; + + if ((item < 2)&&(item > -1)) + memcpy(reg, &mv[item], sizeof(struct st_motormove)); + else rst = ERROR; + } + + return rst; +} + +static SANE_Int hp3970_motormove(SANE_Int usb, SANE_Int ccd, SANE_Int item, struct st_motormove *reg) +{ + SANE_Int rst = ERROR; + + struct st_mtmove + { + SANE_Int usbtype; + SANE_Int sensor; + struct st_motormove move; + }; + + if (reg != NULL) + { + struct st_mtmove mv[] = + { + /* usb, sensor , {systemclock, ctpc, steptype, motorcurve } */ + {USB20, CCD_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, + {USB20, CCD_SENSOR, {0x02 , 2000, STT_HALF, -1 }}, + + {USB20, CIS_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, + {USB20, CIS_SENSOR, {0x02 , 2000, STT_HALF, -1 }}, + + {USB11, CCD_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, + {USB11, CCD_SENSOR, {0x02 , 2000, STT_HALF, -1 }}, + + {USB11, CIS_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, + {USB11, CIS_SENSOR, {0x02 , 2000, STT_HALF, -1 }} + }; + + if (item < 2) + { + SANE_Int a, count = 0; + + for (a = 0; a < 8; a++) + { + if ((mv[a].usbtype == usb)&&(mv[a].sensor == ccd)) + { + if (item == count) + { + memcpy(reg, &mv[a].move, sizeof(struct st_motormove)); + rst = OK; + break; + } else count++; + } + } + } + } + + return rst; +} + +/** SEC: Scanning modes ---------- */ + +static SANE_Int cfg_scanmode_get(SANE_Int sensortype, SANE_Int sm, struct st_scanmode *mymode) +{ + SANE_Int rst = ERROR; + + switch(RTS_Debug->dev_model) + { + case BQ5550: + rst = bq5550_scanmodes(RTS_Debug->usbtype, sm, mymode); + break; + + case UA4900: + rst = ua4900_scanmodes(RTS_Debug->usbtype, sm, mymode); + break; + + case HP3800: + rst = hp3800_scanmodes(RTS_Debug->usbtype, sm, mymode); + break; + + case HP4370: + case HPG3010: + rst = hp4370_scanmodes(RTS_Debug->usbtype, sm, mymode); + break; + + default: /* hp3970 hp4070 */ + rst = hp3970_scanmodes(RTS_Debug->usbtype, sensortype, sm, mymode); + break; + } + + return rst; +} + +static SANE_Int hp3970_scanmodes(SANE_Int usb, SANE_Int ccd, SANE_Int sm, struct st_scanmode *mymode) +{ + struct st_modes + { + SANE_Int usb; + SANE_Int sensor; + struct st_scanmode mode; + }; + + struct st_modes reg[] = + { + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , 2 , PIXEL_RATE, 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , 2 , PIXEL_RATE, 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x03 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x04 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 21999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 10727, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 5591, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x04 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 6999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 4671, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 21999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 10727, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 5591, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x04 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 6999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 4671, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, CIS_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CIS_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} + }; + + SANE_Int rst = ERROR; + + if (mymode != NULL) + { + SANE_Int a; + SANE_Int total = 156; + SANE_Int count = 0; + struct st_modes *md; + + for (a = 0; a < total; a++) + { + md = ®[a]; + if ((md->usb == usb)&&(md->sensor == ccd)) + { + if (count == sm) + { + memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); + rst = OK; + break; + } + + count++; + } + } + } + + return rst; +} + +static SANE_Int hp4370_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) +{ + struct st_modes + { + SANE_Int usb; + struct st_scanmode mode; + }; + + struct st_modes reg[] = + { + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NORMAL, CM_COLOR , 4800, 0x00 , -1 , PIXEL_RATE, 0x05 , 47799, 256 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NORMAL, CM_GRAY , 4800, 0x05 , -1 , LINE_RATE , 0x05 , 47799, 256 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 600, 0x08 , 2 , LINE_RATE , 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 300, 0x09 , 3 , LINE_RATE , 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_TA , CM_COLOR , 4800, 0x0A , -1 , PIXEL_RATE, 0x05 , 53999, 256 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 8999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2959, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_TA , CM_GRAY , 4800, 0x0B , -1 , LINE_RATE , 0x05 , 53999, 256 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 600, 0x08 , 3 , LINE_RATE , 0x05 , 8999, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 300, 0x09 , 4 , LINE_RATE , 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x05 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NEG , CM_COLOR , 4800, 0x0C , -1 , PIXEL_RATE, 0x05 , 60599, 256 , STT_HALF, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599, 145799}, 0 , 1 , -1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 89999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 600, 0x03 , -1 , PIXEL_RATE, 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 300, 0x04 , -1 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 150, 0x04 , 3 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NEG , CM_GRAY , 4800, 0x0D , -1 , LINE_RATE , 0x05 , 60599, 256 , STT_FULL, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599, 145799}, 0 , 1 , -1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 89999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 600, 0x08 , -1 , LINE_RATE , 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 300, 0x09 , -1 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 150, 0x09 , 3 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, {ST_NORMAL, CM_COLOR , 4800, 0x00 , -1 , PIXEL_RATE, 0x05 , 47799, 64 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, {ST_NORMAL, CM_GRAY , 4800, 0x05 , -1 , LINE_RATE , 0x05 , 47799, 64 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 600, 0x08 , 2 , LINE_RATE , 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 300, 0x09 , 3 , LINE_RATE , 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, {ST_TA , CM_COLOR , 4800, 0x0A , -1 , PIXEL_RATE, 0x05 , 53999, 64 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 8999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2959, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, {ST_TA , CM_GRAY , 4800, 0x0B , -1 , LINE_RATE , 0x05 , 53999, 64 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 600, 0x08 , 3 , LINE_RATE , 0x05 , 8999, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 300, 0x09 , 4 , LINE_RATE , 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x05 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, {ST_NEG , CM_COLOR , 4800, 0x0C , -1 , PIXEL_RATE, 0x05 , 60599, 64 , STT_HALF, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 ,145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599,145799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 89999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 600, 0x03 , -1 , PIXEL_RATE, 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 300, 0x04 , -1 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 150, 0x04 , 3 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, {ST_NEG , CM_GRAY , 4800, 0x0D , -1 , LINE_RATE , 0x05 , 60599, 64 , STT_FULL, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 ,145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599,145799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 59999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 600, 0x08 , -1 , LINE_RATE , 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 300, 0x09 , -1 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 150, 0x09 , 3 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} + }; + + SANE_Int rst = ERROR; + + if (mymode != NULL) + { + SANE_Int a; + SANE_Int total = 72; + SANE_Int count = 0; + struct st_modes *md; + + for (a = 0; a < total; a++) + { + md = ®[a]; + if (md->usb == usb) + { + if (count == sm) + { + memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); + rst = OK; + break; + } + + count++; + } + } + } + + return rst; +} + +static SANE_Int hp3800_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) +{ + struct st_modes + { + SANE_Int usb; + struct st_scanmode mode; + }; + + struct st_modes reg[] = + { + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 300, 0x03 , 9 , PIXEL_RATE, 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 300, 0x08 , 9 , LINE_RATE , 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 600, 0x09 , -1 , PIXEL_RATE, 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NEG , CM_COLOR , 2400, 0x0A , -1 , PIXEL_RATE, 0x04 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 1200, 0x0B , -1 , PIXEL_RATE, 0x05 ,127999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 600, 0x0C , -1 , PIXEL_RATE, 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 300, 0x0D , -1 , PIXEL_RATE, 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 150, 0x0D , 10 , PIXEL_RATE, 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NEG , CM_GRAY , 2400, 0x0F , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 1200, 0x10 , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 600, 0x11 , -1 , LINE_RATE , 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 300, 0x12 , -1 , LINE_RATE , 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 150, 0x12 , 10 , LINE_RATE , 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 5 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 300, 0x03 , 9 , PIXEL_RATE, 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 300, 0x08 , 9 , LINE_RATE , 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NORMAL, CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 600, 0x09 , -1 , PIXEL_RATE, 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_TA , CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB11, {ST_NEG , CM_COLOR , 2400, 0x0A , -1 , PIXEL_RATE, 0x04 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 1200, 0x0B , -1 , PIXEL_RATE, 0x05 ,127999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 600, 0x0C , -1 , PIXEL_RATE, 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 300, 0x0D , -1 , PIXEL_RATE, 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_COLOR , 150, 0x0D , 10 , PIXEL_RATE, 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB11, {ST_NEG , CM_GRAY , 2400, 0x0F , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 1200, 0x10 , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 600, 0x11 , -1 , LINE_RATE , 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 300, 0x12 , -1 , LINE_RATE , 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB11, {ST_NEG , CM_GRAY , 150, 0x12 , 10 , LINE_RATE , 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} + }; + + SANE_Int rst = ERROR; + + if (mymode != NULL) + { + SANE_Int a; + SANE_Int total = 60; + SANE_Int count = 0; + struct st_modes *md; + + for (a = 0; a < total; a++) + { + md = ®[a]; + if (md->usb == usb) + { + if (count == sm) + { + memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); + rst = OK; + break; + } + + count++; + } + } + } + + return rst; +} + +static SANE_Int bq5550_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) +{ + struct st_modes + { + SANE_Int usb; + struct st_scanmode mode; + }; + + struct st_modes reg[] = + { + /* usb, {scantype , colormode , res , timing, curve, samplerate, clock, ctpc , backstp, steptype , dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 12999, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x05 , 6999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 5 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 300, 0x02 , 0 , PIXEL_RATE, 0x05 , 5599, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 150, 0x02 , 0 , PIXEL_RATE, 0x05 , 6439, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 100, 0x02 , 0 , PIXEL_RATE, 0x05 , 5759, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x03 , -1 , LINE_RATE , 0x05 , 12999, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 600, 0x04 , -1 , LINE_RATE , 0x05 , 7199, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 300, 0x05 , 0 , LINE_RATE , 0x05 , 5599, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 150, 0x05 , 0 , LINE_RATE , 0x05 , 6239, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 100, 0x05 , 0 , LINE_RATE , 0x05 , 5759, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NORMAL, CM_LINEART, 1200, 0x03 , -1 , LINE_RATE , 0x05 , 12999, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_LINEART, 600, 0x04 , -1 , LINE_RATE , 0x05 , 7199, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_LINEART, 300, 0x05 , 0 , LINE_RATE , 0x05 , 5599, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_LINEART, 150, 0x05 , 0 , LINE_RATE , 0x05 , 6239, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_LINEART, 100, 0x05 , 0 , LINE_RATE , 0x05 , 5759, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode , res , timing, curve, samplerate, clock, ctpc , backstp, steptype , dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_TA , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 9899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x05 , 9999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 300, 0x02 , 0 , PIXEL_RATE, 0x05 , 4799, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 150, 0x02 , 0 , PIXEL_RATE, 0x05 , 4959, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 100, 0x02 , 0 , PIXEL_RATE, 0x05 , 5059, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_TA , CM_GRAY , 1200, 0x03 , -1 , LINE_RATE , 0x05 , 9899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 600, 0x04 , -1 , LINE_RATE , 0x05 , 9999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 300, 0x05 , 0 , LINE_RATE , 0x05 , 4799, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 150, 0x05 , 0 , LINE_RATE , 0x05 , 4959, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 100, 0x05 , 0 , LINE_RATE , 0x05 , 5059, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_TA , CM_LINEART, 1200, 0x03 , -1 , LINE_RATE , 0x05 , 9899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_LINEART, 600, 0x04 , -1 , LINE_RATE , 0x05 , 9999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_LINEART, 300, 0x05 , 0 , LINE_RATE , 0x05 , 4799, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_LINEART, 150, 0x05 , 0 , LINE_RATE , 0x05 , 4959, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_LINEART, 100, 0x05 , 0 , LINE_RATE , 0x05 , 5059, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode , res , timing, curve, samplerate, clock, ctpc , backstp, steptype , dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NEG , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 51899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x05 , 51799, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 300, 0x02 , 0 , PIXEL_RATE, 0x05 , 25899, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 150, 0x02 , 0 , PIXEL_RATE, 0x05 , 25899, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 100, 0x02 , 0 , PIXEL_RATE, 0x05 , 25499, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NEG , CM_GRAY , 1200, 0x03 , -1 , LINE_RATE , 0x05 , 51899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 600, 0x04 , -1 , LINE_RATE , 0x05 , 51799, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 300, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 150, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 100, 0x05 , 0 , LINE_RATE , 0x05 , 25499, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NEG , CM_LINEART, 1200, 0x03 , -1 , LINE_RATE , 0x05 , 51899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_LINEART, 600, 0x04 , -1 , LINE_RATE , 0x05 , 51799, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_LINEART, 300, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_LINEART, 150, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_LINEART, 100, 0x05 , 0 , LINE_RATE , 0x05 , 25499, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} + }; + + SANE_Int rst = ERROR; + + /* silence compiler */ + usb = usb; + + if (mymode != NULL) + { + SANE_Int a; + SANE_Int total = 45; + SANE_Int count = 0; + struct st_modes *md; + + for (a = 0; a < total; a++) + { + md = ®[a]; + if (count == sm) + { + memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); + rst = OK; + break; + } + + count++; + } + } + + return rst; +} + +static SANE_Int ua4900_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) +{ + struct st_modes + { + SANE_Int usb; + struct st_scanmode mode; + }; + + struct st_modes reg[] = + { + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 600, 0x01 , 2 , PIXEL_RATE, 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 300, 0x02 , 3 , PIXEL_RATE, 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 200, 0x03 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x05 , -1 , LINE_RATE , 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 600, 0x06 , 2 , LINE_RATE , 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 300, 0x07 , 3 , LINE_RATE , 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 200, 0x08 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_TA , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 300, 0x02 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 200, 0x03 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_TA , CM_GRAY , 1200, 0x05 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 600, 0x06 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 300, 0x07 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 200, 0x08 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ + {USB20, {ST_NEG , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 300, 0x02 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 200, 0x03 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + + {USB20, {ST_NEG , CM_GRAY , 1200, 0x05 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 600, 0x06 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 300, 0x07 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 200, 0x08 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, + {USB20, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} + }; + + SANE_Int rst = ERROR; + + if (mymode != NULL) + { + SANE_Int a; + SANE_Int total = 30; + SANE_Int count = 0; + struct st_modes *md; + + for (a = 0; a < total; a++) + { + md = ®[a]; + if (md->usb == usb) + { + if (count == sm) + { + memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); + rst = OK; + break; + } + + count++; + } + } + } + + return rst; +} + +/** SEC: Calibration wreferences ---------- */ + +static void hp3970_wrefs(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + struct st_wref + { + SANE_Int usb; + SANE_Int sensor; + SANE_Int depth; + SANE_Int res; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + struct st_wref wrefs[] = + { + /*usb , sensor , depth, res , {transparent }, {negative} */ + {USB20, CCD_SENSOR, 8 , 2400, { 78, 78, 68}, {120, 136, 157}}, + {USB20, CCD_SENSOR, 8 , 1200, { 78, 78, 68}, {120, 136, 157}}, + {USB20, CCD_SENSOR, 8 , 600 , { 79, 80, 70}, {119, 136, 157}}, + {USB20, CCD_SENSOR, 8 , 300 , { 79, 80, 70}, {119, 136, 157}}, + {USB20, CCD_SENSOR, 8 , 200 , { 79, 80, 70}, {119, 136, 157}}, + {USB20, CCD_SENSOR, 8 , 100 , { 79, 80, 70}, {119, 136, 157}}, + + {USB20, CCD_SENSOR, 16 , 2400, { 81, 81, 71}, {119, 137, 158}}, + {USB20, CCD_SENSOR, 16 , 1200, { 81, 81, 71}, {119, 137, 158}}, + {USB20, CCD_SENSOR, 16 , 600 , { 81, 82, 72}, {119, 137, 158}}, + {USB20, CCD_SENSOR, 16 , 300 , { 81, 82, 72}, {119, 137, 158}}, + {USB20, CCD_SENSOR, 16 , 200 , { 81, 82, 72}, {119, 137, 158}}, + {USB20, CCD_SENSOR, 16 , 100 , { 81, 82, 72}, {119, 137, 158}}, + + /*usb , sensor , depth, res , {transparent }, {negative } */ + {USB20, CIS_SENSOR, 8 , 2400, { 94, 85, 78}, { 94, 85, 78}}, + {USB20, CIS_SENSOR, 8 , 1200, { 83, 82, 75}, {140, 155, 155}}, + {USB20, CIS_SENSOR, 8 , 600 , { 84, 84, 76}, {145, 155, 165}}, + {USB20, CIS_SENSOR, 8 , 300 , {146, 166, 166}, {146, 166, 166}}, + {USB20, CIS_SENSOR, 8 , 200 , {145, 310, 160}, {145, 310, 160}}, + {USB20, CIS_SENSOR, 8 , 100 , {140, 300, 155}, {140, 300, 155}}, + + {USB20, CIS_SENSOR, 16 , 2400, { 94, 85, 78}, { 94, 85, 78}}, + {USB20, CIS_SENSOR, 16 , 1200, { 83, 82, 75}, {140, 155, 155}}, + {USB20, CIS_SENSOR, 16 , 600 , { 84, 84, 76}, {145, 155, 165}}, + {USB20, CIS_SENSOR, 16 , 300 , {146, 166, 166}, {146, 166, 166}}, + {USB20, CIS_SENSOR, 16 , 200 , {145, 310, 160}, {145, 310, 160}}, + {USB20, CIS_SENSOR, 16 , 100 , {140, 300, 155}, {140, 300, 155}}, + + /*usb , sensor , depth, res , {transparent }, {negative } */ + {USB11, CCD_SENSOR, 8 , 2400, { 78, 78, 68}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 8 , 1200, { 78, 78, 68}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 8 , 600 , { 79, 79, 70}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 8 , 300 , { 79, 79, 70}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 8 , 200 , { 79, 79, 70}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 8 , 100 , { 79, 79, 70}, {120, 137, 158}}, + + {USB11, CCD_SENSOR, 16 , 2400, { 80, 80, 70}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 16 , 1200, { 80, 80, 70}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 16 , 600 , { 80, 81, 71}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 16 , 300 , { 80, 81, 71}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 16 , 200 , { 80, 81, 71}, {120, 137, 158}}, + {USB11, CCD_SENSOR, 16 , 100 , { 80, 81, 71}, {120, 137, 158}}, + + /*usb , sensor , depth, res , {transparent }, {negative} */ + {USB11, CIS_SENSOR, 8 , 2400, { 94, 85, 78}, {94 , 85 , 78}}, + {USB11, CIS_SENSOR, 8 , 1200, { 83, 82, 75}, {140, 155, 155}}, + {USB11, CIS_SENSOR, 8 , 600 , { 84, 84, 76}, {145, 155, 165}}, + {USB11, CIS_SENSOR, 8 , 300 , {146, 166, 166}, {146, 166, 166}}, + {USB11, CIS_SENSOR, 8 , 200 , {145, 310, 160}, {145, 310, 160}}, + {USB11, CIS_SENSOR, 8 , 100 , {140, 300, 155}, {140, 300, 155}}, + + {USB11, CIS_SENSOR, 16 , 2400, { 94, 85, 78}, { 94, 85, 78}}, + {USB11, CIS_SENSOR, 16 , 1200, { 83, 82, 75}, {140, 155, 155}}, + {USB11, CIS_SENSOR, 16 , 600 , { 84, 84, 76}, {145, 155, 165}}, + {USB11, CIS_SENSOR, 16 , 300 , {146, 166, 166}, {146, 166, 166}}, + {USB11, CIS_SENSOR, 16 , 200 , {145, 310, 160}, {145, 310, 160}}, + {USB11, CIS_SENSOR, 16 , 100 , {140, 300, 155}, {140, 300, 155}} + }; + + struct st_wref *rf; + + *red = *green = *blue = 0x50; + + if (res <= 100) + res = 100; + else if (res <= 200) + res = 200; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else if (res <= 1200) + res = 1200; + else res = 2400; + + if (scantype != ST_NORMAL) + { + SANE_Int a; + + for (a = 0; a < 48; a++) + { + rf = &wrefs[a]; + if ((rf->usb == usb)&&(rf->sensor == ccd)&&(rf->depth == depth)&&(rf->res == res)) + { + switch(scantype) + { + case ST_NEG: + *red = rf->negative[CL_RED]; + *green = rf->negative[CL_GREEN]; + *blue = rf->negative[CL_BLUE]; + break; + case ST_TA: + *red = rf->transparent[CL_RED]; + *green = rf->transparent[CL_GREEN]; + *blue = rf->transparent[CL_BLUE]; + break; + } + + break; + } + } + } else + { + /* reflective mode */ + *red = 233; + *green = 230; + *blue = 222; + } +} + +static void ua4900_wrefs(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + struct st_wref + { + SANE_Int usb; + SANE_Int depth; + SANE_Int res; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + struct st_wref wrefs[] = + { + /*usb , depth, res , {transparent }, {negative } */ + {USB20, 8 , 1200, {136, 131, 121}, {215, 210, 260}}, + {USB20, 8 , 600 , {133, 129, 118}, {219, 215, 264}}, + {USB20, 8 , 300 , {133, 129, 119}, {218, 215, 261}}, + {USB20, 8 , 200 , {133, 130, 119}, {218, 215, 261}}, + {USB20, 8 , 100 , {132, 128, 118}, {218, 215, 261}}, + + {USB20, 16 , 1200, {264, 263, 266}, { 0, 0, 0}}, + {USB20, 16 , 600 , {264, 265, 268}, { 0, 0, 0}}, + {USB20, 16 , 300 , {264, 260, 263}, { 0, 0, 0}}, + {USB20, 16 , 200 , {257, 255, 253}, { 0, 0, 0}}, + {USB20, 16 , 100 , {258, 259, 256}, { 0, 0, 0}}, + + /*usb , depth, res , {transparent }, {negative } */ + {USB11, 8 , 1200, {135, 130, 119}, {220, 215, 264}}, + {USB11, 8 , 600 , {132, 128, 117}, {217, 213, 259}}, + {USB11, 8 , 300 , {132, 128, 117}, {216, 211, 259}}, + {USB11, 8 , 200 , {132, 128, 118}, {215, 352, 259}}, + {USB11, 8 , 100 , {266, 264, 264}, {215, 352, 259}}, + + {USB11, 16 , 1200, {264, 263, 266}, { 0, 0, 0}}, + {USB11, 16 , 600 , {257, 256, 253}, { 0, 0, 0}}, + {USB11, 16 , 300 , {259, 252, 254}, { 0, 0, 0}}, + {USB11, 16 , 200 , {257, 255, 253}, { 0, 0, 0}}, + {USB11, 16 , 100 , {258, 259, 256}, { 0, 0, 0}} + }; + + struct st_wref *rf; + + *red = *green = *blue = 0x50; + + if (res <= 100) + res = 100; + else if (res <= 200) + res = 200; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else res = 1200; + + if (scantype != ST_NORMAL) + { + SANE_Int a; + + for (a = 0; a < 20; a++) + { + rf = &wrefs[a]; + if ((rf->usb == usb)&&(rf->depth == depth)&&(rf->res == res)) + { + switch(scantype) + { + case ST_NEG: + *red = rf->negative[CL_RED]; + *green = rf->negative[CL_GREEN]; + *blue = rf->negative[CL_BLUE]; + break; + case ST_TA: + *red = rf->transparent[CL_RED]; + *green = rf->transparent[CL_GREEN]; + *blue = rf->transparent[CL_BLUE]; + break; + } + + break; + } + } + } else + { + /* reflective mode */ + *red = 233; + *green = 230; + *blue = 222; + } +} + +static void hp3800_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + /* in this scanner, values are the same in all usb versions and depths */ + struct st_wref + { + SANE_Int res; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + struct st_wref wrefs[] = + { + /* res , {transparent }, {negative } */ + { 2400, {276, 279, 243}, { 98, 162, 229}}, + { 1200, {276, 279, 243}, { 98, 162, 229}}, + { 600, {276, 279, 243}, {100, 162, 229}}, + { 300, {276, 279, 243}, {100, 162, 229}}, + { 150, {276, 279, 243}, {100, 162, 229}}, + }; + + struct st_wref *rf; + + *red = *green = *blue = 0x50; + + if (res <= 150) + res = 150; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else if (res <= 1200) + res = 1200; + else res = 2400; + + if (scantype != ST_NORMAL) + { + SANE_Int a; + + for (a = 0; a < 20; a++) + { + rf = &wrefs[a]; + if (rf->res == res) + { + switch(scantype) + { + case ST_NEG: + *red = rf->negative[CL_RED]; + *green = rf->negative[CL_GREEN]; + *blue = rf->negative[CL_BLUE]; + break; + case ST_TA: + *red = rf->transparent[CL_RED]; + *green = rf->transparent[CL_GREEN]; + *blue = rf->transparent[CL_BLUE]; + break; + } + + break; + } + } + } else + { + /* reflective mode */ + *red = 248; + *green = 250; + *blue = 248; + } +} + +static void hp4370_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + struct st_wref + { + SANE_Int res; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + /* values are the same in all usb versions and depths */ + + struct st_wref wrefs[] = + { + /* res, {transparent }, {negative} */ + { 4800, { 93, 93, 82}, {156, 308, 454}}, + { 2400, { 93, 93, 82}, {156, 156, 153}}, + { 1200, { 93, 93, 82}, {156, 156, 153}}, + { 600, { 93, 93, 82}, {155, 155, 152}}, + { 300, { 94, 94, 83}, {155, 155, 152}}, + { 150, { 86, 87, 77}, {148, 145, 138}} + }; + + struct st_wref *rf; + + SANE_Int a; + + *red = *green = *blue = 0x50; + + if (res <= 150) + res = 150; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else if (res <= 1200) + res = 1200; + else if (res <= 2400) + res = 2400; + else res = 4800; + + if (scantype != ST_NORMAL) + { + for (a = 0; a < 6; a++) + { + rf = &wrefs[a]; + if (rf->res == res) + { + switch(scantype) + { + case ST_NEG: + *red = rf->negative[CL_RED]; + *green = rf->negative[CL_GREEN]; + *blue = rf->negative[CL_BLUE]; + break; + case ST_TA: + *red = rf->transparent[CL_RED]; + *green = rf->transparent[CL_GREEN]; + *blue = rf->transparent[CL_BLUE]; + break; + } + + break; + } + } + } else + { + /* reflective mode */ + *red = 233; + *green = 232; + *blue = 223; + } +} + +static void cfg_wrefs_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + switch(RTS_Debug->dev_model) + { + case UA4900: + ua4900_wrefs(RTS_Debug->usbtype, depth, res, scantype, red, green, blue); + break; + + case HP3800: + hp3800_wrefs(res, scantype, red, green, blue); + break; + + case HP4370: + case HPG3010: + hp4370_wrefs(res, scantype, red, green, blue); + break; + + default: + /* hp3970 and hp4070 */ + hp3970_wrefs(RTS_Debug->usbtype, sensortype, depth, res, scantype, red, green, blue); + break; + } +} + +static void hp3800_shading_cut(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + /* values are the same in all usb versions and depths */ + struct st_cut + { + SANE_Int res; + SANE_Int reflective[3]; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + struct st_cut cuts[] = + { + /* res, {reflective }, {transparent }, {negative } */ + { 2400, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}}, + { 1200, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}}, + { 600, { 10, 9, 12}, {-75, -75, -75}, {440, -300, -250}}, + { 300, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}}, + { 150, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}} + }; + + struct st_cut *ct; + + SANE_Int a; + + *red = *green = *blue = 0; + + if (res <= 150) + res = 150; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else if (res <= 1200) + res = 1200; + else res = 2400; + + for (a = 0; a < 5; a++) + { + ct = &cuts[a]; + if (ct->res == res) + { + switch(scantype) + { + case ST_NEG: + *red = ct->negative[CL_RED]; + *green = ct->negative[CL_GREEN]; + *blue = ct->negative[CL_BLUE]; + break; + case ST_TA: + *red = ct->transparent[CL_RED]; + *green = ct->transparent[CL_GREEN]; + *blue = ct->transparent[CL_BLUE]; + break; + default: /* reflective */ + *red = ct->reflective[CL_RED]; + *green = ct->reflective[CL_GREEN]; + *blue = ct->reflective[CL_BLUE]; + break; + } + break; + } + } +} + +static void hp3970_shading_cut(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + struct st_cut + { + SANE_Int usb; + SANE_Int sensor; + SANE_Int depth; + SANE_Int res; + SANE_Int reflective[3]; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + struct st_cut cuts[] = + { + /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ + {USB20, CCD_SENSOR, 8 , 2400, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 3}}, + {USB20, CCD_SENSOR, 8 , 1200, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 5}}, + {USB20, CCD_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, + {USB20, CCD_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, + {USB20, CCD_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, + {USB20, CCD_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, + + {USB20, CCD_SENSOR, 16 , 2400, {-15, -15, -15}, { -7, -7, -7}, {43, 0, 3}}, + {USB20, CCD_SENSOR, 16 , 1200, {-15, -15, -15}, {-15, -15, -15}, {63, 0, 5}}, + {USB20, CCD_SENSOR, 16 , 600 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, + {USB20, CCD_SENSOR, 16 , 300 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, + {USB20, CCD_SENSOR, 16 , 200 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, + {USB20, CCD_SENSOR, 16 , 100 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, + + /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ + {USB20, CIS_SENSOR, 8 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 8 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + + {USB20, CIS_SENSOR, 16 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 16 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 16 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 16 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 16 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB20, CIS_SENSOR, 16 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + + /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ + {USB11, CCD_SENSOR, 8 , 2400, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 3}}, + {USB11, CCD_SENSOR, 8 , 1200, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 5}}, + {USB11, CCD_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, + {USB11, CCD_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, + {USB11, CCD_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, + {USB11, CCD_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, + + {USB11, CCD_SENSOR, 16 , 2400, {-15, -15, -15}, { -7, -7, -7}, {43, 0, 3}}, + {USB11, CCD_SENSOR, 16 , 1200, {-15, -15, -15}, {-15, -15, -15}, {63, 0, 5}}, + {USB11, CCD_SENSOR, 16 , 600 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, + {USB11, CCD_SENSOR, 16 , 300 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, + {USB11, CCD_SENSOR, 16 , 200 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, + {USB11, CCD_SENSOR, 16 , 100 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, + + /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ + {USB11, CIS_SENSOR, 8 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 8 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + + {USB11, CIS_SENSOR, 16 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 16 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 16 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 16 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 16 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, + {USB11, CIS_SENSOR, 16 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}} + }; + + struct st_cut *ct; + + SANE_Int a; + + *red = *green = *blue = 0; + + if (res <= 100) + res = 100; + else if (res <= 200) + res = 200; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else if (res <= 1200) + res = 1200; + else res = 2400; + + for (a = 0; a < 48; a++) + { + ct = &cuts[a]; + if ((ct->usb == usb)&&(ct->sensor == ccd)&&(ct->depth == depth)&&(ct->res == res)) + { + switch(scantype) + { + case ST_NEG: + *red = ct->negative[CL_RED]; + *green = ct->negative[CL_GREEN]; + *blue = ct->negative[CL_BLUE]; + break; + case ST_TA: + *red = ct->transparent[CL_RED]; + *green = ct->transparent[CL_GREEN]; + *blue = ct->transparent[CL_BLUE]; + break; + default: /* reflective */ + *red = ct->reflective[CL_RED]; + *green = ct->reflective[CL_GREEN]; + *blue = ct->reflective[CL_BLUE]; + break; + } + break; + } + } +} + +static void hp4370_shading_cut(SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + struct st_cut + { + SANE_Int depth; + SANE_Int res; + SANE_Int reflective[3]; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + /* values are the same in all usb versions for each depth */ + struct st_cut cuts[] = + { + /* depth, res , {reflective }, {transparent }, {negative } */ + { 8 , 4800, { 0, 0, 0}, { -3, -3, -3}, {35, -10, -7}}, + { 8 , 2400, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -7}}, + { 8 , 1200, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -22}}, + { 8 , 600 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, + { 8 , 300 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, + { 8 , 150 , {-15, -15, -15}, { 0, 0, 0}, {50, -23, -14}}, + + { 16 , 4800, { 0, 0, 0}, { -3, -3, -3}, {35, -10, -7}}, + { 16 , 2400, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -7}}, + { 16 , 1200, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -22}}, + { 16 , 600 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, + { 16 , 300 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, + { 16 , 150 , {-15, -15, -15}, {-15, -15, -15}, {40, -15, -5}} + }; + + struct st_cut *ct; + + SANE_Int a; + + *red = *green = *blue = 0; + + if (res <= 150) + res = 150; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else if (res <= 1200) + res = 1200; + else if (res <= 2400) + res = 2400; + else res = 4800; + + for (a = 0; a < 12; a++) + { + ct = &cuts[a]; + if ((ct->depth == depth)&&(ct->res == res)) + { + switch(scantype) + { + case ST_NEG: + *red = ct->negative[CL_RED]; + *green = ct->negative[CL_GREEN]; + *blue = ct->negative[CL_BLUE]; + break; + case ST_TA: + *red = ct->transparent[CL_RED]; + *green = ct->transparent[CL_GREEN]; + *blue = ct->transparent[CL_BLUE]; + break; + default: /* reflective */ + *red = ct->reflective[CL_RED]; + *green = ct->reflective[CL_GREEN]; + *blue = ct->reflective[CL_BLUE]; + break; + } + break; + } + } +} + +static void ua4900_shading_cut(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + struct st_cut + { + SANE_Int usb; + SANE_Int depth; + SANE_Int res; + SANE_Int reflective[3]; + SANE_Int transparent[3]; + SANE_Int negative[3]; + }; + + struct st_cut cuts[] = + { + /*usb , depth, res , {reflective }, {transparent }, {negative } */ + {USB20, 8 , 1200, {-15, -17, -13}, { 6, 0, 0}, {110, 15, 250}}, + {USB20, 8 , 600 , {-16, -15, -15}, { 6, 7, 5}, {105, 11, 20}}, + {USB20, 8 , 300 , {-15, -15, -15}, { 6, 7, 5}, {105, 10, 25}}, + {USB20, 8 , 200 , {-15, -15, -15}, { 5, 5, 5}, {110, 15, 32}}, + {USB20, 8 , 100 , {-15, -15, -15}, { 5, 5, 5}, {110, 15, 32}}, + + {USB20, 16 , 1200, {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB20, 16 , 600 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB20, 16 , 300 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB20, 16 , 200 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB20, 16 , 100 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + + /*usb , depth, res , {reflective }, {transparent }, {negative } */ + {USB11, 8 , 1200, {-15, -17, -13}, { 5, 5, 5}, {105, 12, 23}}, + {USB11, 8 , 600 , {-17, -15, -16}, { 8, 8, 8}, {105, 12, 20}}, + {USB11, 8 , 300 , {-15, -15, -15}, { 8, 8, 8}, {105, 15, 25}}, + {USB11, 8 , 200 , {-15, -15, -15}, { 8, 8, 8}, {105, 40, 25}}, + {USB11, 8 , 100 , {-15, -15, -15}, { 8, 8, 8}, {-20, 50, 23}}, + + {USB11, 16 , 1200, {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB11, 16 , 600 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB11, 16 , 300 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB11, 16 , 200 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, + {USB11, 16 , 100 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}} + }; + + struct st_cut *ct; + + SANE_Int a; + + *red = *green = *blue = 0; + + if (res <= 100) + res = 100; + else if (res <= 200) + res = 200; + else if (res <= 300) + res = 300; + else if (res <= 600) + res = 600; + else res = 1200; + + for (a = 0; a < 20; a++) + { + ct = &cuts[a]; + if ((ct->usb == usb)&&(ct->depth == depth)&&(ct->res == res)) + { + switch(scantype) + { + case ST_NEG: + *red = ct->negative[CL_RED]; + *green = ct->negative[CL_GREEN]; + *blue = ct->negative[CL_BLUE]; + break; + case ST_TA: + *red = ct->transparent[CL_RED]; + *green = ct->transparent[CL_GREEN]; + *blue = ct->transparent[CL_BLUE]; + break; + default: /* reflective */ + *red = ct->reflective[CL_RED]; + *green = ct->reflective[CL_GREEN]; + *blue = ct->reflective[CL_BLUE]; + break; + } + break; + } + } +} + +static void cfg_shading_cut_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) +{ + switch(RTS_Debug->dev_model) + { + case UA4900: + ua4900_shading_cut(RTS_Debug->usbtype, depth, res, scantype, red, green, blue); + break; + + case HP3800: + hp3800_shading_cut(res, scantype, red, green, blue); + break; + + case HP4370: + case HPG3010: + hp4370_shading_cut(depth, res, scantype, red, green, blue); + break; + + default: + /* hp3970 and hp4070 */ + hp3970_shading_cut(RTS_Debug->usbtype, sensortype, depth, res, scantype, red, green, blue); + break; + } +} + +/** SEC: Sensor Timings ---------- */ + +/* ccd timing values for bq5550 scanner */ +static SANE_Int bq5550_timing_get(SANE_Int tm, struct st_timing *reg) +{ + SANE_Int rst = ERROR; + + if ((tm < 7)&&(reg != NULL)) + { + /* bq5550 sensor timing values for each resolution and color mode */ + + struct st_timing data[] = + { + /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0F , 0x1F }, {0x12 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{66571993091., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {125829120. , 0. , 0x00 , 0x01 , 0x00 }, {67654057987., 0. , 0x00 , 0x01 , 0x00 }, {1065418748. , 0. , 0x00 , 0x01 , 0x01 }, {16383. , 0. , 0x00 , 0x01 , 0x00 }, {68182605824., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0F , 0x1F }, {0x12 , 0x22 }, {0x00 , 0x00 }, {262140. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{66571993091., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {262140. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {125829120. , 0. , 0x00 , 0x01 , 0x00 }, {67654057987., 0. , 0x00 , 0x01 , 0x00 }, {1065418748. , 0. , 0x00 , 0x01 , 0x01 }, {16383. , 0. , 0x00 , 0x01 , 0x00 }, {68182605824., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {524284. , 0. }, 0x00} + }; + + memcpy(reg, &data[tm], sizeof(struct st_timing)); + rst = OK; + } + + return rst; +} + +/* ccd timing values for hp3800 scanner */ +static SANE_Int hp3800_timing_get(SANE_Int tm, struct st_timing *reg) +{ + SANE_Int rst = ERROR; + + if ((tm < 20)&&(reg != NULL)) + { + /* Toshiba T2905 sensor timing values for each resolution and color mode */ + + struct st_timing data[] = + { + /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ + {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 0. , 0x00 , 0x01 , 0x01 }, {68719476732., 0. , 0x00 , 0x01 , 0x01 }, {134217216. , 0. , 0x01 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 0. , 0x00 , 0x01 , 0x01 }, {66571993087., 0. , 0x00 , 0x01 , 0x01 }, {524287. , 0. , 0x00 , 0x01 , 0x00 }, {68718952448., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {1069563840. , 0. , 0x00 , 0x01 , 0x00 }, {67649912895., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x03 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {477225440. , 0. , 0x00 , 0x01 , 0x00 }, {68242251295., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x0096, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {13743895344., 0. , 0x00 , 0x01 , 0x00 }, {54975581391., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x01 , 0x21 }, {0x02 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + + {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 0. , 0x00 , 0x01 , 0x01 }, {68719476732., 0. , 0x00 , 0x01 , 0x01 }, {134217216. , 0. , 0x01 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 0. , 0x00 , 0x01 , 0x01 }, {66571993087., 0. , 0x00 , 0x01 , 0x01 }, {524287. , 0. , 0x00 , 0x01 , 0x00 }, {68718952448., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {1069563840. , 0. , 0x00 , 0x01 , 0x00 }, {67649912895., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x03 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {477225440. , 0. , 0x00 , 0x01 , 0x00 }, {68242251295., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {266346464. , 0. , 0x00 , 0x01 , 0x00 }, {68453130271., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x04 , 0x21 }, {0x06 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + + {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 8589934588. , 0x00 , 0x01 , 0x01 }, {68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 64692944895., 0x00 , 0x01 , 0x01 }, {66571993087., 66571993087., 0x00 , 0x01 , 0x01 }, {524287. , 524287. , 0x00 , 0x01 , 0x00 }, {68718952448., 68718952448., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {534781920. , 534781920. , 0x00 , 0x01 , 0x00 }, {68184694815., 68184694815., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x20FF , 0x01 , -1 , {0x05 , 0x21 }, {0x07 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {477225440. , 477225440. , 0x00 , 0x01 , 0x00 }, {68242251295., 68242251295., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x11FF , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x0096, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {13743895344., 13743895344., 0x00 , 0x01 , 0x00 }, {54975581391., 54975581391., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x110F , 0x01 , -1 , {0x01 , 0x21 }, {0x02 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + + {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 8589934588. , 0x00 , 0x01 , 0x01 }, {68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 64692944895., 0x00 , 0x01 , 0x01 }, {66571993087., 66571993087., 0x00 , 0x01 , 0x01 }, {524287. , 524287. , 0x00 , 0x01 , 0x00 }, {68718952448., 68718952448., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {534781920. , 534781920. , 0x00 , 0x01 , 0x00 }, {68184694815., 68184694815., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x20FF , 0x01 , -1 , {0x05 , 0x21 }, {0x07 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {477225440. , 477225440. , 0x00 , 0x01 , 0x00 }, {68242251295., 68242251295., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x110F , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x0096, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {13743895344., 13743895344., 0x00 , 0x01 , 0x00 }, {54975581391., 54975581391., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x110F , 0x01 , -1 , {0x01 , 0x21 }, {0x02 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + }; + + memcpy(reg, &data[tm], sizeof(struct st_timing)); + rst = OK; + } + + return rst; +} + +/* ccd timing values for hp3970 scanner */ +static SANE_Int hp3970_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg) +{ + SANE_Int rst = ERROR; + + if ((tm < 12)&&(reg != NULL)) + { + rst = OK; + if (sensortype == CCD_SENSOR) + { + /* Toshiba T2952 sensor timing values for each resolution and color mode */ + struct st_timing data[] = + { + /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ + {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34376515584., 0. , 0x00 , 0x01 , 0x00 }, {8455716864. , 0. , 0x01 , 0x01 , 0x00 }, {60246982656., 0. , 0x01 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x04 , 0x09 }, {0x06 , 0x0B }, {0x00 , 0x00 }, {27481079808., 0. }, 0x00}, + {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {64424511232., 0. , 0x00 , 0x01 , 0x00 }, {68711088128., 0. , 0x00 , 0x01 , 0x00 }, {8388352. , 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x15 }, {0x0C , 0x18 }, {0x00 , 0x00 }, {33351135232., 33351135232.}, 0x01}, + {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {60129570816., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x12 }, {0x0C , 0x14 }, {0x00 , 0x00 }, {64677150720., 0. }, 0x00}, + {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51539611648., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {1057222656. , 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {8084643840. , 0. }, 0x00}, + {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68182605888., 0. , 0x00 , 0x01 , 0x00 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1B }, {0x0C , 0x1D }, {0x00 , 0x00 }, {4164816768. , 0. }, 0x00}, + {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34376515584., 0. , 0x00 , 0x01 , 0x00 }, {8455716864. , 0. , 0x01 , 0x01 , 0x00 }, {60246982656., 0. , 0x01 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x04 , 0x09 }, {0x06 , 0x0B }, {0x00 , 0x00 }, {2113929216. , 0. }, 0x00}, + {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {64424511232., 0. , 0x00 , 0x01 , 0x00 }, {68711088128., 0. , 0x00 , 0x01 , 0x00 }, {8388352. , 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x15 }, {0x0C , 0x18 }, {0x00 , 0x00 }, {67104768. , 67104768. }, 0x01}, + {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {60129570816., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x12 }, {0x0C , 0x14 }, {0x00 , 0x00 }, {268369920. , 0. }, 0x00}, + {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51539611648., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {1057222656. , 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {33546240. , 0. }, 0x00}, + {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68585258944., 0. , 0x00 , 0x01 , 0x00 }, {536870784. , 0. , 0x00 , 0x01 , 0x00 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1B }, {0x0C , 0x1C }, {0x00 , 0x00 }, {4194176. , 0. }, 0x00}, + {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34359738368., 0. , 0x00 , 0x01 , 0x00 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {2114445438. , 0. }, 0x00}, + {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34359738368., 0. , 0x00 , 0x01 , 0x00 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {524286. , 0. }, 0x00} + }; + + memcpy(reg, &data[tm], sizeof(struct st_timing)); + } else + { + /* Sony S575 sensor timing values for each resolution and color mode + I haven't found any hp3970 scanner using sony sensor but windows drivers support this case */ + struct st_timing data[] = + { + /* res , cnpp, {cvtrp1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ + {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60112764928., 0. , 0x00 , 0x01 , 0x00 }, {34326183936., 0. , 0x00 , 0x01 , 0x00 }, {1056964608. , 0. , 0x01 , 0x01 , 0x00 }, {67645734912., 0. , 0x01 , 0x01 , 0x01 }, {1056964608. , 0. , 0x00 , 0x01 , 0x00 }, {67645734912., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x05 , 0x09 }, {0x07 , 0x0b }, {0x00 , 0x00 }, {27481079808., 0. }, 0x00}, + {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68316823296., 0. , 0x00 , 0x01 , 0x00 }, {42949672704., 0. , 0x00 , 0x01 , 0x00 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0B , 0x17 }, {0x0D , 0x19 }, {0x00 , 0x00 }, {16675567616., 16675567616.}, 0x01}, + {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{67914166272., 0. , 0x00 , 0x01 , 0x00 }, {42949668864., 0. , 0x00 , 0x01 , 0x00 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x15 }, {0x0B , 0x17 }, {0x00 , 0x00 }, {8084643840. , 0. }, 0x00}, + {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60129538048., 0. , 0x00 , 0x01 , 0x00 }, {34359730176., 0. , 0x00 , 0x01 , 0x00 }, {1057222656. , 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {8084643840. , 0. }, 0x00}, + {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68585258944., 0. , 0x00 , 0x01 , 0x00 }, {536870784. , 0. , 0x00 , 0x01 , 0x00 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1A }, {0x0C , 0x1C }, {0x00 , 0x00 }, {8329633536. , 0. }, 0x00}, + {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60112764928., 0. , 0x00 , 0x01 , 0x00 }, {34326183936., 0. , 0x00 , 0x01 , 0x00 }, {1056964608. , 0. , 0x01 , 0x01 , 0x00 }, {67645734912., 0. , 0x01 , 0x01 , 0x01 }, {1056964608. , 0. , 0x00 , 0x01 , 0x00 }, {67645734912., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x05 , 0x09 }, {0x07 , 0x0B }, {0x00 , 0x00 }, {2113929216. , 0. }, 0x00}, + {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68316823296., 0. , 0x00 , 0x01 , 0x00 }, {42949672704., 0. , 0x00 , 0x01 , 0x00 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0B , 0x17 }, {0x0D , 0x19 }, {0x00 , 0x00 }, {33552384. , 33552384. }, 0x01}, + {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{67914166272., 0. , 0x00 , 0x01 , 0x00 }, {42949668864., 0. , 0x00 , 0x01 , 0x00 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x15 }, {0x0B , 0x17 }, {0x00 , 0x00 }, {33546240. , 0. }, 0x00}, + {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60129538048., 0. , 0x00 , 0x01 , 0x00 }, {34359730176., 0. , 0x00 , 0x01 , 0x00 }, {34359730176., 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {33546240. , 0. }, 0x00}, + {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68182605888., 0. , 0x00 , 0x01 , 0x00 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1A }, {0x0C , 0x1D }, {0x00 , 0x00 }, {4194176. , 0. }, 0x00}, + {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{51539607551., 0. , 0x00 , 0x01 , 0x00 }, {34359738366., 0. , 0x00 , 0x01 , 0x00 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {2114445438. , 0. }, 0x00}, + {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{51539607551., 0. , 0x00 , 0x01 , 0x00 }, {34359738366., 0. , 0x00 , 0x01 , 0x00 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {524286. , 0. }, 0x00} + }; + + memcpy(reg, &data[tm], sizeof(struct st_timing)); + } + } + + return rst; +} + +/* ccd timing values for hp4370 scanner */ +static SANE_Int hp4370_timing_get(SANE_Int tm, struct st_timing *reg) +{ + SANE_Int rst = ERROR; + + if ((reg != NULL)&&(tm < 14)) + { + /* Toshiba T2958 sensor timing values for each resolution and color mode */ + + struct st_timing data[] = + { + /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ + {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x5D5B , 0xBAB7 , 0x1A , -1 , {0x08 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {8084644321. , 8084644321. }, 0x00}, + {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869182., 0. , 0x00 , 0x01 , 0x01 }, {268434432. , 0. , 0x01 , 0x01 , 0x00 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , -1 , {0x07 , 0x18 }, {0x0B , 0x1E }, {0x00 , 0x00 }, {67662254016., 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719475967., 0. , 0x00 , 0x01 , 0x01 }, {1048572. , 0. , 0x00 , 0x01 , 0x01 }, {68718428163., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x1F , 0x17 }, {0x21 , 0x19 }, {0x01 , 0x01 }, {34888349727., 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719476731., 0. , 0x00 , 0x01 , 0x01 }, {4261672960. , 0. , 0x00 , 0x01 , 0x00 }, {64457803775., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x00 , 0x1F }, {0x03 , 0x21 }, {0x00 , 0x00 }, {8457781752. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51808043007., 0. , 0x00 , 0x01 , 0x01 }, {8084644320. , 0. , 0x00 , 0x01 , 0x00 }, {60634832415., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x09 , 0x20 }, {0x0A , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, + {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x5D5B , 0xBAB7 , 0x1A , -1 , {0x08 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {33546240. , 33546240. }, 0x00}, + {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869182., 0. , 0x00 , 0x01 , 0x01 }, {268434432. , 0. , 0x01 , 0x01 , 0x00 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , -1 , {0x07 , 0x18 }, {0x0B , 0x1E }, {0x00 , 0x00 }, {16777152. , 0. }, 0x00}, + {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719475967., 0. , 0x00 , 0x01 , 0x01 }, {1048572. , 0. , 0x00 , 0x01 , 0x01 }, {68718428163., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x1F , 0x17 }, {0x21 , 0x19 }, {0x01 , 0x01 }, {536868864. , 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719476731., 0. , 0x00 , 0x01 , 0x01 }, {4261672960. , 0. , 0x00 , 0x01 , 0x00 }, {64457803775., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x00 , 0x1F }, {0x03 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00}, + {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51808043007., 0. , 0x00 , 0x01 , 0x01 }, {8084644320. , 0. , 0x00 , 0x01 , 0x00 }, {60634832415., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x09 , 0x20 }, {0x0A , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, + {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x6977 , 0xD2EF , 0x1A , -1 , {0x07 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {8084644321. , 8084644321. }, 0x00}, + {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x6977 , 0xD2EF , 0x1A , -1 , {0x07 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {33546240. , 33546240. }, 0x00}, + {0x12C0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {8589934591. , 8589934591. , 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x765B , 0xECB7 , 0x1A , -1 , {0x07 , 0x1B }, {0x0D , 0x21 }, {0x00 , 0x00 }, {8457781752. , 8457781752. }, 0x00}, + {0x12C0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {8589934591. , 8589934591. , 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x765B , 0xECB7 , 0x1A , -1 , {0x07 , 0x1B }, {0x0D , 0x21 }, {0x00 , 0x00 }, {2097144. , 2097144. }, 0x00} + }; + + memcpy(reg, &data[tm], sizeof(struct st_timing)); + rst = OK; + } + + return rst; +} + +/* ccd timing values for ua4900 scanner */ +static SANE_Int ua4900_timing_get(SANE_Int tm, struct st_timing *reg) +{ + SANE_Int rst = ERROR; + + if ((tm < 10)&&(reg != NULL)) + { + /* Sony S575 sensor timing values for each resolution and color mode */ + struct st_timing data[] = + { + /* res , cnpp, {cvtrp1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ + {0x04b0, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{ 1073737728., 0. , 0x01 , 0x01 , 0x00 }, {67645739007., 0. , 0x01 , 0x01 , 0x01 }, {67645739007., 0. , 0x01 , 0x01 , 0x01 }, { 1073737728., 0. , 0x01 , 0x01 , 0x00 }, {25769803776., 0. , 0x00 , 0x01 , 0x00 }, { 62., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x1c }, {0x0A , 0x1e }, {0x00 , 0x00 }, {67662254016., 0. }, 0x00}, + {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x03 , 0x03 , {{ 262143., 0. , 0x00 , 0x01 , 0x00 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, { 262143., 3. , 0x00 , 0x01 , 0x00 }, { 2080374784., 0. , 0x00 , 0x01 , 0x00 }, {64424509455., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x10 , 0x1d }, {0x12 , 0x1f }, {0x00 , 0x00 }, {33831127008., 0. }, 0x00}, + {0x012c, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{ 32767., 0. , 0x00 , 0x01 , 0x00 }, {68182605824., 0. , 0x00 , 0x01 , 0x01 }, { 2130837500., 0. , 0x00 , 0x01 , 0x01 }, {66588639235., 0. , 0x00 , 0x01 , 0x00 }, { 117440512., 0. , 0x00 , 0x01 , 0x00 }, {68182605825., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x12 , 0x1f }, {0x14 , 0x21 }, {0x00 , 0x00 }, { 8457781752., 0. }, 0x00}, + {0x00c8, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x10 , 0x1f }, {0x12 , 0x21 }, {0x00 , 0x00 }, { 8457781752., 0. }, 0x00}, + {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x10 , 0x1f }, {0x12 , 0x21 }, {0x00 , 0x00 }, { 8457781752., 0. }, 0x00}, + {0x04b0, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{ 268434432., 0. , 0x01 , 0x01 , 0x00 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, { 268434432., 0. , 0x01 , 0x01 , 0x00 }, {51539607552., 0. , 0x00 , 0x01 , 0x00 }, {30. , 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x1d }, {0x09 , 0x1e }, {0x00 , 0x00 }, {16777152. , 0. }, 0x00}, + {0x0258, 0x1d, {0x00, 0x00, 0x00}, 0x0f , 0x03 , 0x03 , {{ 2097088., 0. , 0x00 , 0x01 , 0x00 }, {68717379632., 0. , 0x00 , 0x01 , 0x01 }, {68717379632., 0. , 0x00 , 0x01 , 0x01 }, { 2097088., 3. , 0x00 , 0x01 , 0x00 }, { 1879048192., 0. , 0x00 , 0x01 , 0x00 }, {60129542592., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0d , 0x16 }, {0x0f , 0x18 }, {0x00 , 0x00 }, {134213632. , 0. }, 0x00}, + {0x012c, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{64424510463., 0. , 0x00 , 0x01 , 0x00 }, { 4278190080., 0. , 0x00 , 0x01 , 0x01 }, { 267390975., 0. , 0x00 , 0x01 , 0x01 }, {68452085760., 0. , 0x00 , 0x01 , 0x00 }, { 6291456., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x15 , 0x1f }, {0x17 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00}, + {0x00C8, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x17 , 0x1f }, {0x19 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00}, + {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x17 , 0x1f }, {0x19 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00} + }; + + memcpy(reg, &data[tm], sizeof(struct st_timing)); + rst = OK; + } + + return rst; +} + +static SANE_Int cfg_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg) +{ + /* return timing values for current device */ + + SANE_Int rst = ERROR; + + switch(RTS_Debug->dev_model) + { + case BQ5550: + rst = bq5550_timing_get(tm, reg); + break; + + case UA4900: + rst = ua4900_timing_get(tm, reg); + break; + + case HP4370: + case HPG3010: + rst = hp4370_timing_get(tm, reg); + break; + + case HP3800: + rst = hp3800_timing_get(tm, reg); + break; + + default: + /* hp3970 and hp4070 */ + rst = hp3970_timing_get(sensortype, tm, reg); + break; + } + + return rst; +} + +/** SEC: Motor curves ---------- */ + +static SANE_Int *bq5550_motor() +{ + SANE_Int *rst = NULL; + SANE_Int steps[] = + { + /* motorcurve 1 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 20000 ,6323 ,4095 ,3270 ,2823 ,2533 ,2318 ,2151 ,2016 ,1905 ,1811 ,1730 ,1660 ,1599 ,1544 ,1494 ,1450 ,1409 ,1373 ,1339 ,1307 ,1278 ,1251 ,1225 ,1201 ,1179 ,1158 ,1138 ,1119 ,1101 ,1084 ,1067 ,1052 ,1037 ,1023 ,1009 ,996 ,984 ,972 ,960 ,949 ,938 ,928 ,918 ,909 ,899 ,890 ,882 ,873 ,865 ,857 ,849 ,842 ,835 ,828 ,821 ,814 ,807 ,801 ,795 ,789 ,783 ,777 ,772 ,766 ,761 ,756 ,751 ,746 ,741 ,736 ,731 ,727 ,722 ,718 ,714 ,709 ,705 ,701 ,697 ,693 ,690 ,686 ,682 ,678 ,675 ,671 ,668 ,665 ,661 ,658 ,655 ,652 ,649 ,645 ,642 ,640 ,637 ,634 ,631 ,628 ,625 ,623 ,620 ,617 ,615 ,612 ,610 ,607 ,605 ,602 ,600 ,597 ,595 ,593 ,591 ,588 ,586 ,584 ,582 ,580 ,577 ,575 ,573 ,571 ,569 ,567 ,565 ,563 ,562 ,560 ,558 ,556 ,554 ,552 ,550 ,549 ,547 ,545 ,543 ,542 ,540 ,538 ,537 ,535 ,534 ,532 ,530 ,529 ,527 ,526 ,524 ,523 ,521 ,520 ,518 ,517 ,515 ,514 ,513 ,511 ,510 ,508 ,507 ,506 ,504 ,503 ,502 ,501 ,499 ,498 ,497 ,495 ,494 ,493 ,492 ,491 ,489 ,488 ,487 ,486 ,485 ,484 ,482 ,481 ,480 ,479 ,478 ,477 ,476 ,475 ,474 ,473 ,472 ,470 ,469 ,468 ,467 ,466 ,465 ,464 ,463 ,462 ,461 ,460 ,460 ,459 ,458 ,457 ,456 ,455 ,454 ,453 ,452 ,451 ,450 ,449 ,449 ,448 ,447 ,446 ,445 ,444 ,443 ,443 ,442 ,441 ,440 ,439 ,438 ,438 ,437 ,436 ,435 ,434 ,434 ,433 ,432 ,431 ,431 ,430 ,429 ,428 ,428 ,427 ,426 ,425 ,425 ,424 ,423 ,422 ,422 ,421 ,420 ,420 ,419 ,418 ,418 ,417 ,416 ,416 ,415 ,414 ,414 ,413 ,412 ,412 ,411 ,410 ,410 ,409 ,408 ,408 ,407 ,407 ,406 ,405 ,405 ,404 ,404 ,403 ,402 ,402 ,401 ,401 ,400 ,399 ,399 ,398 ,398 ,397 ,397 ,396 ,395 ,395 ,394 ,394 ,393 ,393 ,392 ,392 ,391 ,390 ,390 ,389 ,389 ,388 ,388 ,387 ,387 ,386 ,386 ,385 ,385 ,384 ,384 ,383 ,383 ,382 ,382 ,381 ,381 ,380 ,380 ,379 ,379 ,378 ,378 ,377 ,377 ,377 ,376 ,376 ,375 ,375 ,374 ,374 ,373 ,373 ,372 ,372 ,372 ,371 ,371 ,370 ,370 ,369 ,369 ,368 ,368 ,368 ,367 ,367 ,366 ,366 ,365 ,365 ,365 ,364 ,364 ,363 ,363 ,363 ,362 ,362 ,361 ,361 ,361 ,360 ,360 ,359 ,359 ,359 ,358 ,358 ,357 ,357 ,357 ,356 ,356 ,356 ,355 ,355 ,354 ,354 ,354 ,353 ,353 ,353 ,352 ,352 ,351 ,351 ,351 ,350 ,350 ,350 ,349 ,349 ,349 ,348 ,348 ,348 ,347 ,347 ,347 ,346 ,346 ,346 ,345 ,345 ,345 ,344 ,344 ,344 ,343 ,343 ,343 ,342 ,342 ,342 ,341 ,341 ,341 ,340 ,340 ,340 ,339 ,339 ,339 ,338 ,338 ,338 ,337 ,337 ,337 ,337 ,336 ,336 ,336 ,335 ,335 ,335 ,334 ,334 ,334 ,334 ,333 ,333 ,333 ,332 ,332 ,332 ,332 ,331 ,331 ,331 ,330 ,330 ,330 ,330 ,329 ,329 ,329 ,328 ,328 ,328 ,328 ,327 ,327 ,327 ,326 ,326 ,326 ,326 ,325 ,325 ,325 ,325 ,324 ,324 ,324 ,324 ,323 ,323 ,323 ,323 ,322 ,322 ,322 ,321 ,321 ,321 ,321 ,320 ,320 ,320 ,320 ,319 ,319 ,319 ,319 ,318 ,318 ,318 ,318 ,317 ,317 ,317 ,317 ,317 ,316 ,316 ,316 ,316 ,315 ,315 ,315 ,315 ,314 ,314 ,314 ,314 ,313 ,313 ,313 ,313 ,313 ,312 ,312 ,312 ,312 ,311 ,311 ,311 ,311 ,311 ,310 ,310 ,310 ,310 ,309 ,309 ,309 ,309 ,309 ,308 ,308 ,308 ,308 ,307 ,307 ,307 ,307 ,307 ,306 ,306 ,306 ,306 ,306 ,305 ,305 ,305 ,305 ,305 ,304 ,304 ,304 ,304 ,303 ,303 ,303 ,303 ,303 ,302 ,302 ,302 ,302 ,302 ,301 ,301 ,301 ,301 ,301 ,300 ,300 ,300 ,300 ,300 ,300 ,299 ,299 ,299 ,299 ,299 ,298 ,298 ,298 ,298 ,298 ,297 ,297 ,297 ,297 ,297 ,297 ,296 ,296 ,296 ,296 ,296 ,295 ,295 ,295 ,295 ,295 ,295 ,294 ,294 ,294 ,294 ,294 ,293 ,293 ,293 ,293 ,293 ,293 ,292 ,292 ,292 ,292 ,292 ,292 ,291 ,291 ,291 ,291 ,291 ,290 ,290 ,290 ,290 ,290 ,290 ,289 ,289 ,289 ,289 ,289 ,289 ,288 ,288 ,288 ,288 ,288 ,288 ,288 ,287 ,287 ,287 ,287 ,287 ,287 ,286 ,286 ,286 ,286 ,286 ,286 ,285 ,285 ,285 ,285 ,285 ,285, 0, + ACC_CURVE,CRV_SMEARING , 4000, 3877, 3377, 2777, 2127, 1724, 1449, 1250, 0, + DEC_CURVE,CRV_NORMALSCAN, 479 ,500 ,547 ,607 ,682 ,766 ,865 ,950 ,1040 ,1200 ,1369 ,1580 ,1810 ,2087 ,2500 ,3048 ,3877 ,4818 ,5822 ,6896, 0, + DEC_CURVE,CRV_SMEARING , 1250, 1449, 1724, 2127, 2777, 3377, 3877, 4000, 0, + DEC_CURVE,CRV_BUFFERFULL, 479 ,500 ,547 ,607 ,682 ,766 ,865 ,950 ,1040 ,1200 ,1369 ,1580 ,1810 ,2087 ,2500 ,3048 ,3877 ,4818 ,5822 ,6896, 0, + -1 + }; + + rst = (SANE_Int *)malloc(sizeof(steps)); + if (rst != NULL) + memcpy(rst, &steps, sizeof(steps)); + + return rst; +} + +static SANE_Int *hp4370_motor() +{ + SANE_Int *rst = NULL; + SANE_Int steps[] = + { + /* motorcurve 1 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 2000, 1984, 1968, 1953, 1937, 1921, 1906, 1890, 1874, 1859, 1843, 1827, 1812, 1796, 1781, 1765, 1749, 1734, 1715, 1700, 1684, 1669, 1653, 1637, 1622, 1606, 1590, 1572, 1556, 1541, 1525, 1510, 1494, 1478, 1463, 1447, 1431, 1416, 1400, 1384, 1366, 1351, 1335, 1319, 1304, 1288, 1272, 1257, 1241, 1225, 1210, 1194, 1179, 1160, 1145, 1129, 1113, 1098, 1082, 1066, 1051, 1035, 1017, 1001, 986, 970, 954, 939, 923, 907, 892, 876, 861, 845, 829, 814, 798, 782, 767, 749, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, + ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, + DEC_CURVE,CRV_NORMALSCAN, 749, 1166, 1583, 2000, 0, + DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, + DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, + DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, + -2, + + /* motorcurve 2 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, + ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, + DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, + DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, + DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, + -2, + + /* motorcurve 3 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 5360, 3655, 2855, 2422, 2142, 1944, 1795, 1678, 1582, 1503, 1434, 1374, 0, + ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 684, 677, 669, 662, 655, 648, 642, 636, 629, 624, 618, 612, 607, 602, 596, 591, 587, 582, 577, 573, 568, 564, 560, 556, 552, 548, 544, 540, 537, 533, 530, 526, 523, 520, 516, 513, 510, 507, 504, 501, 498, 496, 493, 490, 488, 485, 482, 480, 477, 475, 472, 470, 468, 466, 463, 461, 459, 457, 455, 453, 450, 448, 446, 444, 443, 441, 439, 437, 435, 433, 431, 430, 428, 426, 425, 423, 421, 420, 418, 416, 415, 413, 412, 410, 409, 407, 406, 405, 403, 402, 400, 399, 398, 396, 395, 394, 392, 391, 390, 389, 387, 386, 385, 384, 382, 381, 380, 379, 378, 377, 376, 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, 353, 352, 351, 350, 349, 348, 0, + ACC_CURVE,CRV_SMEARING , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 0, + DEC_CURVE,CRV_NORMALSCAN, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, + DEC_CURVE,CRV_PARKHOME , 348, 351, 353, 356, 359, 362, 365, 368, 371, 374, 378, 381, 385, 389, 392, 396, 400, 405, 409, 413, 418, 423, 428, 433, 439, 444, 450, 457, 463, 470, 477, 485, 493, 501, 510, 520, 530, 540, 552, 564, 577, 591, 607, 624, 642, 662, 684, 709, 737, 769, 805, 847, 897, 958, 1034, 1131, 1264, 1458, 1791, 2628, 5360, 0, + DEC_CURVE,CRV_SMEARING , 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, + DEC_CURVE,CRV_BUFFERFULL, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, + -2, + + /* motorcurve 4 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2888, 2234, 1878, 1648, 1485, 1362, 1265, 1186, 1120, 1064, 1016, 973, 936, 903, 873, 845, 821, 798, 777, 758, 740, 723, 708, 693, 679, 666, 654, 643, 632, 621, 612, 602, 593, 585, 576, 569, 561, 554, 547, 540, 534, 528, 522, 516, 510, 505, 499, 494, 490, 485, 480, 476, 471, 467, 463, 459, 455, 451, 448, 444, 440, 437, 434, 430, 427, 424, 421, 418, 415, 412, 409, 407, 404, 401, 399, 396, 394, 391, 389, 387, 384, 382, 380, 378, 376, 374, 371, 369, 367, 366, 364, 362, 360, 358, 356, 354, 353, 351, 349, 348, 346, 344, 343, 341, 340, 338, 337, 335, 334, 332, 331, 329, 328, 327, 325, 324, 323, 321, 320, 319, 318, 316, 315, 314, 313, 312, 311, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 285, 284, 283, 282, 281, 280, 279, 279, 278, 277, 276, 275, 275, 274, 273, 272, 272, 271, 270, 269, 269, 268, 267, 267, 266, 265, 264, 264, 263, 262, 262, 261, 260, 260, 259, 259, 258, 257, 257, 256, 255, 255, 254, 254, 253, 252, 252, 251, 251, 250, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 243, 242, 242, 241, 241, 240, 240, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 231, 230, 230, 229, 229, 228, 228, 228, 227, 227, 226, 226, 225, 225, 225, 224, 224, 223, 223, 223, 222, 222, 222, 221, 221, 220, 220, 220, 219, 219, 219, 218, 218, 217, 217, 217, 216, 216, 216, 215, 215, 215, 214, 214, 214, 213, 213, 213, 212, 212, 212, 211, 211, 211, 210, 210, 210, 209, 209, 209, 208, 208, 208, 207, 207, 207, 207, 206, 206, 206, 205, 205, 205, 204, 204, 204, 204, 203, 203, 203, 202, 202, 202, 202, 201, 201, 201, 200, 200, 200, 200, 199, 199, 199, 199, 198, 198, 198, 198, 197, 197, 197, 196, 196, 196, 196, 195, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 171, 171, 171, 171, 0, + ACC_CURVE,CRV_SMEARING , 4705, 3056, 2724, 2497, 1498, 1498, 1374, 1276, 1196, 1130, 1073, 1025, 982, 944, 911, 880, 853, 828, 805, 784, 764, 746, 730, 714, 699, 685, 675, 0, + DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + DEC_CURVE,CRV_PARKHOME , 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 182, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246, 247, 249, 251, 253, 254, 256, 258, 260, 262, 264, 266, 268, 271, 273, 275, 278, 280, 282, 285, 288, 290, 293, 296, 299, 302, 305, 309, 312, 316, 319, 323, 327, 331, 336, 340, 345, 350, 355, 360, 365, 371, 377, 384, 391, 398, 406, 414, 422, 432, 441, 452, 463, 476, 489, 504, 520, 538, 558, 580, 605, 633, 667, 706, 752, 810, 883, 979, 1116, 1326, 1714, 4705, 0, + DEC_CURVE,CRV_SMEARING , 675, 685, 699, 714, 730, 746, 764, 784, 805, 828, 853, 880, 911, 944, 982, 1025, 1073, 1130, 1196, 1276, 1374, 1498, 1498, 2497, 2724, 3056, 4705, 0, + DEC_CURVE,CRV_BUFFERFULL, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + -2, + + /* motorcurve 5 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 3763, 3763, 3763, 3763, 3763, 3763, 2444, 2178, 1997, 1198, 1198, 1098, 1020, 956, 903, 858, 819, 785, 754, 727, 703, 681, 662, 644, 626, 610, 596, 582, 571, 558, 547, 537, 527, 518, 509, 500, 492, 485, 478, 471, 464, 458, 452, 446, 440, 435, 430, 425, 420, 415, 410, 407, 402, 398, 394, 391, 386, 383, 380, 376, 373, 369, 366, 364, 360, 357, 355, 352, 349, 347, 344, 341, 338, 337, 334, 332, 329, 328, 325, 323, 321, 319, 317, 315, 313, 311, 310, 308, 306, 304, 302, 301, 299, 297, 295, 294, 293, 291, 290, 288, 286, 285, 284, 283, 281, 280, 278, 277, 275, 275, 274, 272, 271, 270, 268, 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, 257, 256, 255, 254, 253, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 243, 242, 241, 240, 239, 239, 238, 237, 236, 235, 235, 234, 233, 232, 231, 230, 230, 230, 229, 228, 228, 227, 226, 225, 225,224, 223, 222, 222, 221, 221, 221, 220, 219, 219, 218, 217, 217, 216, 215, 215, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 190, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 181, 180, 180, 180, 179, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 171, 170, 170, 170, 169, 169, 169, 169, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101,101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, + ACC_CURVE,CRV_PARKHOME , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, + ACC_CURVE,CRV_SMEARING , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, + DEC_CURVE,CRV_NORMALSCAN, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 345, 348, 351, 354, 357, 360, 363, 366, 369, 372, 375, 378, 381, 384, 387, 391, 395, 399, 403, 407, 411, 415, 419, 422, 425, 429, 433, 437, 441, 445, 449, 453, 458, 463, 468, 473, 478, 483, 489, 495, 501, 507, 514, 521, 528, 536, 544, 553, 562, 572, 582, 593, 604, 616, 629, 643, 658, 674, 692, 711, 732, 755, 781, 810, 843, 880, 923, 974,1035, 1110, 1205, 1331, 1510, 1796, 2368, 3400, 4922, 0, + DEC_CURVE,CRV_PARKHOME , 138, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_SMEARING , 138, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184, 184, 184, 185, 185, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 194, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 203, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 218, 218, 219, 220, 220, 221, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 230, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 239, 239, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 266, 267, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 282, 283, 284, 285, 287, 289, 290, 292, 293, 294, 296, 298, 300, 301, 302, 304, 306, 308, 310, 311, 313, 315, 318, 320, 321, 323, 326, 328, 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, 355, 358, 361, 364, 366, 370, 374, 376, 380, 383, 387, 391, 394, 399, 402, 407, 411, 416, 420, 425, 430, 436, 441, 446, 453, 458, 464, 472, 478, 485, 493, 501, 509, 518, 527, 537, 548, 559, 571, 583, 597, 611, 626, 644, 662, 682, 704, 728, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_BUFFERFULL, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + -2, + + /* motorcurve 6 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2888, 2234, 1878, 1648, 1485, 1362, 1265, 1186, 1120, 1064, 1016, 973, 936, 903, 873, 845, 821, 798, 777, 758, 740, 723, 708, 693, 679, 666, 654, 643, 632, 621, 612, 602, 593, 585, 576, 569, 561, 554, 547, 540, 534, 528, 522, 516, 510, 505, 499, 494, 490, 485, 480, 476, 471, 467, 463, 459, 455, 451, 448, 444, 440, 437, 434, 430, 427, 424, 421, 418, 415, 412, 409, 407, 404, 401, 399, 396, 394, 391, 389, 387, 384, 382, 380, 378, 376, 374, 371, 369, 367, 366, 364, 362, 360, 358, 356, 354, 353, 351, 349, 348, 346, 344, 343, 341, 340, 338, 337, 335, 334, 332, 331, 329, 328, 327, 325, 324, 323, 321, 320, 319, 318, 316, 315, 314, 313, 312, 311, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 285, 284, 283, 282, 281, 280, 279, 279, 278, 277, 276, 275, 275, 274, 273, 272, 272, 271, 270, 269, 269, 268, 267, 267, 266, 265, 264, 264, 263, 262, 262, 261, 260, 260, 259, 259, 258, 257, 257, 256, 255, 255, 254, 254, 253, 252, 252, 251, 251, 250, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 243, 242, 242, 241, 241, 240, 240, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 231, 230, 230, 229, 229, 228, 228, 228, 227, 227, 226, 226, 225, 225, 225, 224, 224, 223, 223, 223, 222, 222, 222, 221, 221, 220, 220, 220, 219, 219, 219, 218, 218, 217, 217, 217, 216, 216, 216, 215, 215, 215, 214, 214, 214, 213, 213, 213, 212, 212, 212, 211, 211, 211, 210, 210, 210, 209, 209, 209, 208, 208, 208, 207, 207, 207, 207, 206, 206, 206, 205, 205, 205, 204, 204, 204, 204, 203, 203, 203, 202, 202, 202, 202, 201, 201, 201, 200, 200, 200, 200, 199, 199, 199, 199, 198, 198, 198, 198, 197, 197, 197, 196, 196, 196, 196, 195, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 171, 171, 171, 171, 0, + ACC_CURVE,CRV_SMEARING , 4705, 3056, 2724, 2497, 1498, 1498, 1374, 1276, 1196, 1130, 1073, 1025, 982, 944, 911, 880, 853, 828, 805, 784, 764, 746, 730, 714, 699, 685, 675, 0, + DEC_CURVE,CRV_NORMALSCAN, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + DEC_CURVE,CRV_PARKHOME , 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 182, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246, 247, 249, 251, 253, 254, 256, 258, 260, 262, 264, 266, 268, 271, 273, 275, 278, 280, 282, 285, 288, 290, 293, 296, 299, 302, 305, 309, 312, 316, 319, 323, 327, 331, 336, 340, 345, 350, 355, 360, 365, 371, 377, 384, 391, 398, 406, 414, 422, 432, 441, 452, 463, 476, 489, 504, 520, 538, 558, 580, 605, 633, 667, 706, 752, 810, 883, 979, 1116, 1326, 1714, 4705, 0, + DEC_CURVE,CRV_SMEARING , 675, 685, 699, 714, 730, 746, 764, 784, 805, 828, 853, 880, 911, 944, 982, 1025, 1073, 1130, 1196, 1276, 1374, 1498, 1498, 2497, 2724, 3056, 4705, 0, + DEC_CURVE,CRV_BUFFERFULL, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + -2, + + /* motorcurve 7 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 3763, 3763, 3763, 3763, 3763, 3763, 2444, 2178, 1997, 1198, 1198, 1098, 1020, 956, 903, 858, 819, 785, 754, 727, 703, 681, 662, 644, 626, 610, 596, 582, 571, 558, 547, 537, 527, 518, 509, 500, 492, 485, 478, 471, 464, 458, 452, 446, 440, 435, 430, 425, 420, 415, 410, 407, 402, 398, 394, 391, 386, 383, 380, 376, 373, 369, 366, 364, 360, 357, 355, 352, 349, 347, 344, 341, 338, 337, 334, 332, 329, 328, 325, 323, 321, 319, 317, 315, 313, 311, 310, 308, 306, 304, 302, 301, 299, 297, 295, 294, 293, 291, 290, 288, 286, 285, 284, 283, 281, 280, 278, 277, 275, 275, 274, 272, 271, 270, 268, 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, 257, 256, 255, 254, 253, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 243, 242, 241, 240, 239, 239, 238, 237, 236, 235, 235, 234, 233, 232, 231, 230, 230, 230, 229, 228, 228, 227, 226, 225, 225,224, 223, 222, 222, 221, 221, 221, 220, 219, 219, 218, 217, 217, 216, 215, 215, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 190, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 181, 180, 180, 180, 179, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 171, 170, 170, 170, 169, 169, 169, 169, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101,101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, + ACC_CURVE,CRV_PARKHOME , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, + ACC_CURVE,CRV_SMEARING , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, + DEC_CURVE,CRV_NORMALSCAN, 522, 522, 528, 536, 544, 553, 562, 572, 582, 593, 604, 616, 629, 643, 658, 674, 692, 711, 732, 755, 781, 810, 843, 880, 923, 974, 1035, 1110, 1205, 1331, 1510, 1796, 2368, 3400, 4922, 0, + DEC_CURVE,CRV_PARKHOME , 138, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_SMEARING , 138, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184, 184, 184, 185, 185, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 194, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 203, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 218, 218, 219, 220, 220, 221, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 230, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 239, 239, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 266, 267, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 282, 283, 284, 285, 287, 289, 290, 292, 293, 294, 296, 298, 300, 301, 302, 304, 306, 308, 310, 311, 313, 315, 318, 320, 321, 323, 326, 328, 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, 355, 358, 361, 364, 366, 370, 374, 376, 380, 383, 387, 391, 394, 399, 402, 407, 411, 416, 420, 425, 430, 436, 441, 446, 453, 458, 464, 472, 478, 485, 493, 501, 509, 518, 527, 537, 548, 559, 571, 583, 597, 611, 626, 644, 662, 682, 704, 728, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_BUFFERFULL, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + -2, + + /* motorcurve 8 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 1046, 1046, 1046, 1046, 1046, 1046, 647, 501, 421, 370, 333, 305, 284, 266, 251, 239, 228, 218, 210, 202, 196, 190, 184, 179, 174, 170, 166, 162, 159, 155, 152, 149, 147, 144, 142, 139, 137, 135, 133, 131, 129, 127, 126, 124, 123, 121, 120, 118, 117, 116, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 100, 99, 98, 97, 96, 96, 95, 94, 94, 93, 92, 92, 91, 91, 90, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79, 79, 79, 78, 78, 78, 77, 77, 76, 76, 76, 75, 75, 75, 74, 74, 74, 74, 73, 73, 73, 72, 72, 72, 71, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 64, 64, 64, 64, 63, 63, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 0, + ACC_CURVE,CRV_PARKHOME , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, + ACC_CURVE,CRV_SMEARING , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, + DEC_CURVE,CRV_NORMALSCAN, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + DEC_CURVE,CRV_PARKHOME , 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + DEC_CURVE,CRV_SMEARING , 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 81, 81, 81, 82, 82, 83, 83, 84, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 98, 99, 99, 100, 101, 102, 103, 104, 105, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 118, 119, 120, 122, 123, 125, 127, 128, 130, 132, 134, 136, 138, 140, 142, 145, 147, 150, 153, 156, 159, 163, 167, 171, 175, 180, 185, 190, 196, 203, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + DEC_CURVE,CRV_BUFFERFULL, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + -1 + }; + + rst = (SANE_Int *)malloc(sizeof(steps)); + if (rst != NULL) + memcpy(rst, &steps, sizeof(steps)); + + return rst; +} + +static SANE_Int *hp3970_motor() +{ + SANE_Int *rst = NULL; + SANE_Int steps[] = + { + /* motorcurve 1 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 2000, 1984, 1968, 1953, 1937, 1921, 1906, 1890, 1874, 1859, 1843, 1827, 1812, 1796, 1781, 1765, 1749, 1734, 1715, 1700, 1684, 1669, 1653, 1637, 1622, 1606, 1590, 1572, 1556, 1541, 1525, 1510, 1494, 1478, 1463, 1447, 1431, 1416, 1400, 1384, 1366, 1351, 1335, 1319, 1304, 1288, 1272, 1257, 1241, 1225, 1210, 1194, 1179, 1160, 1145, 1129, 1113, 1098, 1082, 1066, 1051, 1035, 1017, 1001, 986, 970, 954, 939, 923, 907, 892, 876, 861, 845, 829, 814, 798, 782, 767, 749, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, + ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, + DEC_CURVE,CRV_NORMALSCAN, 749, 1166, 1583, 2000, 0, + DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, + DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, + DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, + -2, + + /* motorcurve 2 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, + ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, + DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, + DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, + DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, + -2, + + /* motorcurve 3 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 5360, 3655, 2855, 2422, 2142, 1944, 1795, 1678, 1582, 1503, 1434, 1374, 0, + ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 684, 677, 669, 662, 655, 648, 642, 636, 629, 624, 618, 612, 607, 602, 596, 591, 587, 582, 577, 573, 568, 564, 560, 556, 552, 548, 544, 540, 537, 533, 530, 526, 523, 520, 516, 513, 510, 507, 504, 501, 498, 496, 493, 490, 488, 485, 482, 480, 477, 475, 472, 470, 468, 466, 463, 461, 459, 457, 455, 453, 450, 448, 446, 444, 443, 441, 439, 437, 435, 433, 431, 430, 428, 426, 425, 423, 421, 420, 418, 416, 415, 413, 412, 410, 409, 407, 406, 405, 403, 402, 400, 399, 398, 396, 395, 394, 392, 391, 390, 389, 387, 386, 385, 384, 382, 381, 380, 379, 378, 377, 376, 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, 353, 352, 351, 350, 349, 348, 0, + ACC_CURVE,CRV_SMEARING , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 0, + DEC_CURVE,CRV_NORMALSCAN, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, + DEC_CURVE,CRV_PARKHOME , 348, 351, 353, 356, 359, 362, 365, 368, 371, 374, 378, 381, 385, 389, 392, 396, 400, 405, 409, 413, 418, 423, 428, 433, 439, 444, 450, 457, 463, 470, 477, 485, 493, 501, 510, 520, 530, 540, 552, 564, 577, 591, 607, 624, 642, 662, 684, 709, 737, 769, 805, 847, 897, 958, 1034, 1131, 1264, 1458, 1791, 2628, 5360, 0, + DEC_CURVE,CRV_SMEARING , 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, + DEC_CURVE,CRV_BUFFERFULL, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, + -2, + + /* motorcurve 4 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, + ACC_CURVE,CRV_PARKHOME , 4705, 2888, 2234, 1878, 1648, 1485, 1362, 1265, 1186, 1120, 1064, 1016, 973, 936, 903, 873, 845, 821, 798, 777, 758, 740, 723, 708, 693, 679, 666, 654, 643, 632, 621, 612, 602, 593, 585, 576, 569, 561, 554, 547, 540, 534, 528, 522, 516, 510, 505, 499, 494, 490, 485, 480, 476, 471, 467, 463, 459, 455, 451, 448, 444, 440, 437, 434, 430, 427, 424, 421, 418, 415, 412, 409, 407, 404, 401, 399, 396, 394, 391, 389, 387, 384, 382, 380, 378, 376, 374, 371, 369, 367, 366, 364, 362, 360, 358, 356, 354, 353, 351, 349, 348, 346, 344, 343, 341, 340, 338, 337, 335, 334, 332, 331, 329, 328, 327, 325, 324, 323, 321, 320, 319, 318, 316, 315, 314, 313, 312, 311, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 285, 284, 283, 282, 281, 280, 279, 279, 278, 277, 276, 275, 275, 274, 273, 272, 272, 271, 270, 269, 269, 268, 267, 267, 266, 265, 264, 264, 263, 262, 262, 261, 260, 260, 259, 259, 258, 257, 257, 256, 255, 255, 254, 254, 253, 252, 252, 251, 251, 250, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 243, 242, 242, 241, 241, 240, 240, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 231, 230, 230, 229, 229, 228, 228, 228, 227, 227, 226, 226, 225, 225, 225, 224, 224, 223, 223, 223, 222, 222, 222, 221, 221, 220, 220, 220, 219, 219, 219, 218, 218, 217, 217, 217, 216, 216, 216, 215, 215, 215, 214, 214, 214, 213, 213, 213, 212, 212, 212, 211, 211, 211, 210, 210, 210, 209, 209, 209, 208, 208, 208, 207, 207, 207, 207, 206, 206, 206, 205, 205, 205, 204, 204, 204, 204, 203, 203, 203, 202, 202, 202, 202, 201, 201, 201, 200, 200, 200, 200, 199, 199, 199, 199, 198, 198, 198, 198, 197, 197, 197, 196, 196, 196, 196, 195, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 171, 171, 171, 171, 0, + ACC_CURVE,CRV_SMEARING , 4705, 3056, 2724, 2497, 1498, 1498, 1374, 1276, 1196, 1130, 1073, 1025, 982, 944, 911, 880, 853, 828, 805, 784, 764, 746, 730, 714, 699, 685, 675, 0, + DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + DEC_CURVE,CRV_PARKHOME , 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 182, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246, 247, 249, 251, 253, 254, 256, 258, 260, 262, 264, 266, 268, 271, 273, 275, 278, 280, 282, 285, 288, 290, 293, 296, 299, 302, 305, 309, 312, 316, 319, 323, 327, 331, 336, 340, 345, 350, 355, 360, 365, 371, 377, 384, 391, 398, 406, 414, 422, 432, 441, 452, 463, 476, 489, 504, 520, 538, 558, 580, 605, 633, 667, 706, 752, 810, 883, 979, 1116, 1326, 1714, 4705, 0, + DEC_CURVE,CRV_SMEARING , 675, 685, 699, 714, 730, 746, 764, 784, 805, 828, 853, 880, 911, 944, 982, 1025, 1073, 1130, 1196, 1276, 1374, 1498, 1498, 2497, 2724, 3056, 4705, 0, + DEC_CURVE,CRV_BUFFERFULL, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, + -2, + + /* motorcurve 5 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 3763, 3763, 3763, 3763, 3763, 3763, 2444, 2178, 1997, 1198, 1198, 1098, 1020, 956, 903, 858, 819, 785, 754, 727, 703, 681, 662, 644, 626, 610, 596, 582, 571, 558, 547, 537, 527, 518, 509, 500, 492, 485, 478, 471, 464, 458, 452, 446, 440, 435, 430, 425, 420, 415, 410, 407, 402, 398, 394, 391, 386, 383, 380, 376, 373, 369, 366, 364, 360, 357, 355, 352, 349, 347, 344, 341, 338, 337, 334, 332, 329, 328, 325, 323, 321, 319, 317, 315, 313, 311, 310, 308, 306, 304, 302, 301, 299, 297, 295, 294, 293, 291, 290, 288, 286, 285, 284, 283, 281, 280, 278, 277, 275, 275, 274, 272, 271, 270, 268, 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, 257, 256, 255, 254, 253, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 243, 242, 241, 240, 239, 239, 238, 237, 236, 235, 235, 234, 233, 232, 231, 230, 230, 230, 229, 228, 228, 227, 226, 225, 225,224, 223, 222, 222, 221, 221, 221, 220, 219, 219, 218, 217, 217, 216, 215, 215, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 190, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 181, 180, 180, 180, 179, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 171, 170, 170, 170, 169, 169, 169, 169, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101,101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, + ACC_CURVE,CRV_PARKHOME , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, + ACC_CURVE,CRV_SMEARING , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, + DEC_CURVE,CRV_NORMALSCAN, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 92, 92, 92, 92, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_PARKHOME , 138, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_SMEARING , 138, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184, 184, 184, 185, 185, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 194, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 203, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 218, 218, 219, 220, 220, 221, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 230, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 239, 239, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 266, 267, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 282, 283, 284, 285, 287, 289, 290, 292, 293, 294, 296, 298, 300, 301, 302, 304, 306, 308, 310, 311, 313, 315, 318, 320, 321, 323, 326, 328, 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, 355, 358, 361, 364, 366, 370, 374, 376, 380, 383, 387, 391, 394, 399, 402, 407, 411, 416, 420, 425, 430, 436, 441, 446, 453, 458, 464, 472, 478, 485, 493, 501, 509, 518, 527, 537, 548, 559, 571, 583, 597, 611, 626, 644, 662, 682, 704, 728, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + DEC_CURVE,CRV_BUFFERFULL, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, + -2, + + /* motorcurve 6 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 23999, 0, + ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 0, + ACC_CURVE,CRV_SMEARING , 23999, 0, + DEC_CURVE,CRV_NORMALSCAN, 23999, 0, + DEC_CURVE,CRV_PARKHOME , 692, 700, 709, 718, 727, 737, 747, 758, 769, 780, 792, 805, 818, 832, 847, 863, 880, 897, 916, 937, 958, 981, 1006, 1034, 1063, 1096, 1131, 1170, 1214, 1264, 1319, 1384, 1458, 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, + DEC_CURVE,CRV_SMEARING , 23999, 0, + DEC_CURVE,CRV_BUFFERFULL, 23999, 0, + -2, + + /* motorcurve 7 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 6667, 0, + ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 0, + ACC_CURVE,CRV_SMEARING , 6667, 0, + DEC_CURVE,CRV_NORMALSCAN, 6667, 0, + DEC_CURVE,CRV_PARKHOME , 692, 700, 709, 718, 727, 737, 747, 758, 769, 780, 792, 805, 818, 832, 847, 863, 880, 897, 916, 937, 958, 981, 1006, 1034, 1063, 1096, 1131, 1170, 1214, 1264, 1319, 1384, 1458, 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, + DEC_CURVE,CRV_SMEARING , 6667, 0, + DEC_CURVE,CRV_BUFFERFULL, 6667, 0, + -2, + + /* motorcurve 8 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN, 1046, 1046, 1046, 1046, 1046, 1046, 647, 501, 421, 370, 333, 305, 284, 266, 251, 239, 228, 218, 210, 202, 196, 190, 184, 179, 174, 170, 166, 162, 159, 155, 152, 149, 147, 144, 142, 139, 137, 135, 133, 131, 129, 127, 126, 124, 123, 121, 120, 118, 117, 116, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 100, 99, 98, 97, 96, 96, 95, 94, 94, 93, 92, 92, 91, 91, 90, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79, 79, 79, 78, 78, 78, 77, 77, 76, 76, 76, 75, 75, 75, 74, 74, 74, 74, 73, 73, 73, 72, 72, 72, 71, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 64, 64, 64, 64, 63, 63, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 0, + ACC_CURVE,CRV_PARKHOME , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, + ACC_CURVE,CRV_SMEARING , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, + DEC_CURVE,CRV_NORMALSCAN, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + DEC_CURVE,CRV_PARKHOME , 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + DEC_CURVE,CRV_SMEARING , 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 81, 81, 81, 82, 82, 83, 83, 84, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 98, 99, 99, 100, 101, 102, 103, 104, 105, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 118, 119, 120, 122, 123, 125, 127, 128, 130, 132, 134, 136, 138, 140, 142, 145, 147, 150, 153, 156, 159, 163, 167, 171, 175, 180, 185, 190, 196, 203, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + DEC_CURVE,CRV_BUFFERFULL, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, + -1 + }; + + rst = (SANE_Int *)malloc(sizeof(steps)); + if (rst != NULL) + memcpy(rst, &steps, sizeof(steps)); + + return rst; +} + +static SANE_Int *hp3800_motor() +{ + SANE_Int *rst = NULL; + SANE_Int steps[] = + { + /* motorcurve 1 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,2000,1984,1968,1953,1937,1921,1906,1890,1874,1859,1843,1827,1812,1796,1781,1765,1749,1734,1715,1700,1684,1669,1653,1637,1622,1606,1590,1572,1556,1541,1525,1510,1494,1478,1463,1447,1431,1416,1400,1384,1366,1351,1335,1319,1304,1288,1272,1257,1241,1225,1210,1194,1179,1160,1145,1129,1113,1098,1082,1066,1051,1035,1017,1001,986,970,954,939,923,907,892,876,861,845,829,814,798,782,767,749, 0, + ACC_CURVE,CRV_PARKHOME ,4705,2913,2253,1894,1662,1498,1374,1276,1196,1129,1073,1024,981,944,910,880,852,827,804,783,764,746,729,713,699,685,672,659,648,637,626,616,607,598,589,581,573,565,558,551,544,538,532,526,520,514,509,503,500, 0, + ACC_CURVE,CRV_SMEARING ,200,12,14,16, 0, + DEC_CURVE,CRV_NORMALSCAN,749,1166,1583,2000, 0, + DEC_CURVE,CRV_PARKHOME ,500,503,509,514,520,526,532,538,544,551,558,565,573,581,589,598,607,616,626,637,648,659,672,685,699,713,729,746,764,783,804,827,852,880,910,944,981,1024,1073,1129,1196,1276,1374,1498,1662,1894,2253,2913,4705, 0, + DEC_CURVE,CRV_SMEARING ,300,234,167,100, 0, + DEC_CURVE,CRV_BUFFERFULL,1100,867,633,400, 0, + -2, + + /* motorcurve 2 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,4705,2664,2061,1732,1521,1370,1257,1167,1094,1033,982,937,898,864,833,805,780,757,736,717,699,683,667,653,640,627,615,604,593,583,574,564,556,547,540,532,525,518,511,505,499,493,487,481,476,471,466,461,456,452,447,443,439,435,431,427,424,420,417,413,410,407,403,400,397,394,391,389,386,383,381,378,375,373,371,368,366,364,361,359,357,355,353,351,349,347,345,343,341,339,338,336,334,332,331,329,327,326,324,323,321,320,318,317,315,314,312,311,310,308,307,306,304,303,302,301,299,298,297,296,295,293,292,291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,270,269,268,267,266,265,264,264,263,262,261,260,260,259,258,257,257,256,255,255,254,253,252,252,251,250,250,249,248,248,247,246,246,245,244,244,243,242,242,241,241,240,239,239,238,238,237,237,236,235,235,234,234,233,233,232,232,231,231,230,230,229,229,228,227,227,227,226,226,225,225,224,224,223,223,222,222,221,221,220,220,219,219,219,218,218,217,217,216,216,216,215,215,214,214,214,213,213,212,212,212,211,211,210,210,210,209,209,208,208,208,207,207,207,206,206,206,205,205,204,204,204,203,203,203,202,202,202,201,201,201,200,200,200,199,199,199,198,198,198,197,197,197,197,196,196,196,195,195,195,194,194,194,194,193,193,193,192,192,192,192,191,191,191,190,190,190,190,189,189,189,188,188,188,188,187,187,187,187,186,186,186,186,185,185,185,185,184,184,184,184,183,183,183,183,182,182,182,182,181,181,181,181,181,180,180,180,180,179,179,179,179,178,178,178,178,178,177,177,177,177,177,176,176,176,176,175,175,175,175,175,174,174,174,174,174,173,173,173,173,173,172,172,172,172,172,171,171,171, 0, + ACC_CURVE,CRV_PARKHOME ,4705,2913,2253,1894,1662,1498,1374,1276,1196,1129,1073,1024,981,944,910,880,852,827,804,783,764,746,729,713,699,685,672,659,648,637,626,616,607,598,589,581,573,565,558,551,544,538,532,526,520,514,509,503,500, 0, + ACC_CURVE,CRV_SMEARING ,200,12,14,16, 0, + DEC_CURVE,CRV_NORMALSCAN,171,172,172,173,174,174,175,176,176,177,178,178,179,180,181,181,182,183,184,184,185,186,187,188,189,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,213,214,215,217,218,219,221,222,224,225,227,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255,258,260,262,265,268,270,273,276,279,282,285,289,292,296,299,303,307,311,316,320,325,330,335,341,347,353,359,366,373,381,390,398,408,418,429,441,455,469,485,503,523,545,571,601,636,678,730,796,883,1005,1195,1544,4705, 0, + DEC_CURVE,CRV_PARKHOME ,500,503,509,514,520,526,532,538,544,551,558,565,573,581,589,598,607,616,626,637,648,659,672,685,699,713,729,746,764,783,804,827,852,880,910,944,981,1024,1073,1129,1196,1276,1374,1498,1662,1894,2253,2913,4705, 0, + DEC_CURVE,CRV_SMEARING ,300,234,167,100, 0, + DEC_CURVE,CRV_BUFFERFULL,1100,867,633,400, 0, + -2, + + /* motorcurve 3 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,5360,3655,2855,2422,2142,1944,1795,1678,1582,1503,1434,1374, 0, + ACC_CURVE,CRV_PARKHOME ,5360,3362,2628,2229,1973,1791,1654,1547,1458,1384,1319,1264,1214,1170,1131,1096,1063,1034,1006,981,958,937,916,897,880,863,847,832,818,805,792,780,769,758,747,737,727,718,709,700,692,684,677,669,662,655,648,642,636,629,624,618,612,607,602,596,591,587,582,577,573,568,564,560,556,552,548,544,540,537,533,530,526,523,520,516,513,510,507,504,501,498,496,493,490,488,485,482,480,477,475,472,470,468,466,463,461,459,457,455,453,450,448,446,444,443,441,439,437,435,433,431,430,428,426,425,423,421,420,418,416,415,413,412,410,409,407,406,405,403,402,400,399,398,396,395,394,392,391,390,389,387,386,385,384,382,381,380,379,378,377,376,374,373,372,371,370,369,368,367,366,365,364,363,362,361,360,359,358,357,356,355,354,353,353,352,351,350,349,348, 0, + ACC_CURVE,CRV_SMEARING ,5360,3362,2628,2229,1973,1791,1654,1547, 0, + DEC_CURVE,CRV_NORMALSCAN,1374,1434,1503,1582,1678,1795,1944,2142,2422,2855,3655,5360, 0, + DEC_CURVE,CRV_PARKHOME ,348,351,353,356,359,362,365,368,371,374,378,381,385,389,392,396,400,405,409,413,418,423,428,433,439,444,450,457,463,470,477,485,493,501,510,520,530,540,552,564,577,591,607,624,642,662,684,709,737,769,805,847,897,958,1034,1131,1264,1458,1791,2628,5360, 0, + DEC_CURVE,CRV_SMEARING ,1547,1654,1791,1973,2229,2628,3362,5360, 0, + DEC_CURVE,CRV_BUFFERFULL,1374,1434,1503,1582,1678,1795,1944,2142,2422,2855,3655,5360, 0, + -2, + + /* motorcurve 4 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,4705,2664,2061,1732,1521,1370,1257,1167,1094,1033,982,937,898,864,833,805,780,757,736,717,699,683,667,653,640,627,615,604,593,583,574,564,556,547,540,532,525,518,511,505,499,493,487,481,476,471,466,461,456,452,447,443,439,435,431,427,424,420,417,413,410,407,403,400,397,394,391,389,386,383,381,378,375,373,371,368,366,364,361,359,357,355,353,351,349,347,345,343,341,339,338,336,334,332,331,329,327,326,324,323,321,320,318,317,315,314,312,311,310,308,307,306,304,303,302,301,299,298,297,296,295,293,292,291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,270,269,268,267,266,265,264,264,263,262,261,260,260,259,258,257,257,256,255,255,254,253,252,252,251,250,250,249,248,248,247,246,246,245,244,244,243,242,242,241,241,240,239,239,238,238,237,237,236,235,235,234,234,233,233,232,232,231,231,230,230,229,229,228,227,227,227,226,226,225,225,224,224,223,223,222,222,221,221,220,220,219,219,219,218,218,217,217,216,216,216,215,215,214,214,214,213,213,212,212,212,211,211,210,210,210,209,209,208,208,208,207,207,207,206,206,206,205,205,204,204,204,203,203,203,202,202,202,201,201,201,200,200,200,199,199,199,198,198,198,197,197,197,197,196,196,196,195,195,195,194,194,194,194,193,193,193,192,192,192,192,191,191,191,190,190,190,190,189,189,189,188,188,188,188,187,187,187,187,186,186,186,186,185,185,185,185,184,184,184,184,183,183,183,183,182,182,182,182,181,181,181,181,181,180,180,180,180,179,179,179,179,178,178,178,178,178,177,177,177,177,177,176,176,176,176,175,175,175,175,175,174,174,174,174,174,173,173,173,173,173,172,172,172,172,172,171,171,171, 0, + ACC_CURVE,CRV_PARKHOME ,4705,2888,2234,1878,1648,1485,1362,1265,1186,1120,1064,1016,973,936,903,873,845,821,798,777,758,740,723,708,693,679,666,654,643,632,621,612,602,593,585,576,569,561,554,547,540,534,528,522,516,510,505,499,494,490,485,480,476,471,467,463,459,455,451,448,444,440,437,434,430,427,424,421,418,415,412,409,407,404,401,399,396,394,391,389,387,384,382,380,378,376,374,371,369,367,366,364,362,360,358,356,354,353,351,349,348,346,344,343,341,340,338,337,335,334,332,331,329,328,327,325,324,323,321,320,319,318,316,315,314,313,312,311,309,308,307,306,305,304,303,302,301,300,299,298,297,296,295,294,293,292,291,290,289,288,287,286,285,285,284,283,282,281,280,279,279,278,277,276,275,275,274,273,272,272,271,270,269,269,268,267,267,266,265,264,264,263,262,262,261,260,260,259,259,258,257,257,256,255,255,254,254,253,252,252,251,251,250,249,249,248,248,247,247,246,246,245,245,244,243,243,242,242,241,241,240,240,239,239,238,238,237,237,237,236,236,235,235,234,234,233,233,232,232,231,231,231,230,230,229,229,228,228,228,227,227,226,226,225,225,225,224,224,223,223,223,222,222,222,221,221,220,220,220,219,219,219,218,218,217,217,217,216,216,216,215,215,215,214,214,214,213,213,213,212,212,212,211,211,211,210,210,210,209,209,209,208,208,208,207,207,207,207,206,206,206,205,205,205,204,204,204,204,203,203,203,202,202,202,202,201,201,201,200,200,200,200,199,199,199,199,198,198,198,198,197,197,197,196,196,196,196,195,195,195,195,194,194,194,194,193,193,193,193,192,192,192,192,192,191,191,191,191,190,190,190,190,189,189,189,189,189,188,188,188,188,187,187,187,187,187,186,186,186,186,186,185,185,185,185,184,184,184,184,184,183,183,183,183,183,182,182,182,182,182,181,181,181,181,181,180,180,180,180,180,180,179,179,179,179,179,178,178,178,178,178,177,177,177,177,177,177,176,176,176,176,176,176,175,175,175,175,175,174,174,174,174,174,174,173,173,173,173,173,173,172,172,172,172,172,172,171,171,171,171, 0, + ACC_CURVE,CRV_SMEARING ,4705,3056,2724,2497,1498,1498,1374,1276,1196,1130,1073,1025,982,944,911,880,853,828,805,784,764,746,730,714,699,685,675, 0, + DEC_CURVE,CRV_NORMALSCAN,171,172,172,173,174,174,175,176,176,177,178,178,179,180,181,181,182,183,184,184,185,186,187,188,189,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,213,214,215,217,218,219,221,222,224,225,227,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255,258,260,262,265,268,270,273,276,279,282,285,289,292,296,299,303,307,311,316,320,325,330,335,341,347,353,359,366,373,381,390,398,408,418,429,441,455,469,485,503,523,545,571,601,636,678,730,796,883,1005,1195,1544,4705, 0, + DEC_CURVE,CRV_PARKHOME ,171,172,172,173,173,174,174,175,175,176,176,177,177,178,179,179,180,180,181,182,182,183,183,184,185,185,186,187,187,188,189,189,190,191,192,192,193,194,195,195,196,197,198,199,199,200,201,202,203,204,205,206,206,207,208,209,210,211,212,213,214,215,217,218,219,220,221,222,223,225,226,227,228,230,231,232,234,235,237,238,240,241,243,244,246,247,249,251,253,254,256,258,260,262,264,266,268,271,273,275,278,280,282,285,288,290,293,296,299,302,305,309,312,316,319,323,327,331,336,340,345,350,355,360,365,371,377,384,391,398,406,414,422,432,441,452,463,476,489,504,520,538,558,580,605,633,667,706,752,810,883,979,1116,1326,1714,4705, 0, + DEC_CURVE,CRV_SMEARING ,675,685,699,714,730,746,764,784,805,828,853,880,911,944,982,1025,1073,1130,1196,1276,1374,1498,1498,2497,2724,3056,4705, 0, + DEC_CURVE,CRV_BUFFERFULL,171,172,172,173,174,174,175,176,176,177,178,178,179,180,181,181,182,183,184,184,185,186,187,188,189,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,213,214,215,217,218,219,221,222,224,225,227,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255,258,260,262,265,268,270,273,276,279,282,285,289,292,296,299,303,307,311,316,320,325,330,335,341,347,353,359,366,373,381,390,398,408,418,429,441,455,469,485,503,523,545,571,601,636,678,730,796,883,1005,1195,1544,4705, 0, + -2, + + /* motorcurve 5 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,3763,3763,3763,3763,3763,3763,2444,2178,1997,1198,1198,1098,1020,956,903,858,819,785,754,727,703,681,662,644,626,610,596,582,571,558,547,537,527,518,509,500,492,485,478,471,464,458,452,446,440,435,430,425,420,415,410,407,402,398,394,391,386,383,380,376,373,369,366,364,360,357,355,352,349,347,344,341,338,337,334,332,329,328,325,323,321,319,317,315,313,311,310,308,306,304,302,301,299,297,295,294,293,291,290,288,286,285,284,283,281,280,278,277,275,275,274,272,271,270,268,267,266,265,264,263,262,261,259,258,257,257,256,255,254,253,251,250,249,248,248,247,246,245,244,243,243,242,241,240,239,239,238,237,236,235,235,234,233,232,231,230,230,230,229,228,228,227,226,225,225,224,223,222,222,221,221,221,220,219,219,218,217,217,216,215,215,214,213,213,212,212,212,211,211,210,209,209,208,208,207,207,206,206,205,204,204,203,203,203,203,202,202,201,201,200,200,199,199,198,198,197,197,196,196,195,195,194,194,194,194,194,193,193,192,192,191,191,190,190,190,189,189,188,188,188,187,187,186,186,185,185,185,185,185,185,184,184,183,183,183,182,182,182,181,181,180,180,180,179,179,179,178,178,178,177,177,177,176,176,176,176,176,176,175,175,175,174,174,174,173,173,173,172,172,172,171,171,171,171,170,170,170,169,169,169,169,168,168,168,167,167,167,167,167,167,167,166,166,166,166,165,165,165,165,164,164,164,163,163,163,163,162,162,162,162,161,161,161,161,160,160,160,160,159,159,159,159,159,158,158,158,158,158,158,158,158,157,157,157,157,157,156,156,156,156,155,155,155,155,155,154,154,154,154,154,153,153,153,153,152,152,152,152,152,151,151,151,151,151,150,150,150,150,150,149,149,149,149,149,149,149,149,149,149,149,148,148,148,148,148,147,147,147,147,147,147,146,146,146,146,146,145,145,145,145,145,145,144,144,144,144,144,144,143,143,143,143,143,143,142,142,142,142,142,142,141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,140,140,140,139,139,139,139,139,139,139,138,138,138,138,138,138,138,137,137,137,137,137,137,137,136,136,136,136,136,136,136,135,135,135,135,135,135,135,134,134,134,134,134,134,134,134,133,133,133,133,133,133,133,133,132,132,132,132,132,132,132,132,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,130,130,130,130,130,130,130,130,129,129,129,129,129,129,129,129,129,128,128,128,128,128,128,128,128,128,127,127,127,127,127,127,127,127,127,126,126,126,126,126,126,126,126,126,125,125,125,125,125,125,125,125,125,125,124,124,124,124,124,124,124,124,124,124,123,123,123,123,123,123,123,123,123,123,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,121,121,121,121,121,121,121,121,121,121,121,120,120,120,120,120,120,120,120,120,120,120,119,119,119,119,119,119,119,119,119,119,119,119,118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,116,116,116,116,116,116,116,116,116,116,116,116,115,115,115,115,115,115,115,115,115,115,115,115,115,114,114,114,114,114,114,114,114,114,114,114,114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, 0, + ACC_CURVE,CRV_PARKHOME ,3763,2330,1803,1515,1330,1198,1099,1021,957,904,859,819,785,755,728,704,682,662,644,626,611,597,583,571,559,548,537,527,518,509,501,493,485,478,472,464,458,453,446,441,436,430,425,420,416,411,407,402,399,394,391,387,383,380,376,374,370,366,364,361,358,355,352,349,347,344,342,339,337,335,332,330,328,326,323,321,320,318,315,313,311,310,308,306,304,302,301,300,298,296,294,293,292,290,289,287,285,284,283,282,280,279,277,276,275,274,273,271,270,269,267,266,266,265,263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,248,248,247,246,245,244,243,242,241,240,239,239,239,238,237,236,235,234,233,233,232,231,230,230,230,229,228,227,227,226,225,224,224,223,222,221,221,221,220,220,219,218,218,217,216,216,215,214,214,213,213,212,212,212,211,211,210,209,209,208,208,207,207,206,205,205,204,204,203,203,203,203,202,202,201,201,200,200,199,199,198,198,197,197,196,196,195,195,194,194,194,194,194,193,193,192,192,191,191,191,190,190,189,189,188,188,188,187,187,186,186,186,185,185,185,185,185,184,184,184,183,183,182,182,182,181,181,181,180,180,180,179,179,178,178,178,177,177,177,176,176,176,176,176,176,175,175,175,174,174,174,174,173,173,173,172,172,172,171,171,171,170,170,170,170,169,169,169,168,168,168,168,167,167,167,167,167,167,167,166,166,166,166,165,165,165,165,164,164,164,163,163,163,163,162,162,162,162,161,161,161,161,160,160,160,160,160,159,159,159,159,158,158,158,158,158,158,158,158,157,157,157,157,157,156,156,156,156,155,155,155,155,155,154,154,154,154,154,153,153,153,153,153,152,152,152,152,152,151,151,151,151,151,150,150,150,150,150,149,149,149,149,149,149,149,149,149,149,148,148,148,148,148,148,147,147,147,147,147,147,146,146,146,146,146,145,145,145,145,145,145,144,144,144,144,144,144,143,143,143,143,143,143,142,142,142,142,142,142,141,141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,140,140,140,139,139,139,139,139,139,139,138, 0, + ACC_CURVE,CRV_SMEARING ,3763,2330,1803,1515,1330,1198,1099,1021,957,904,859,819,785,755,728,704,682,662,644,626,611,597,583,571,559,548,540, 0, + DEC_CURVE,CRV_NORMALSCAN,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,87,87,87,87,87,87,87,87,88,88,88,88,88,88,88,88,89,89,89,89,89,89,89,90,90,90,90,90,90,91,91,91,91,91,92,92,92,92,93,93,93,93,94,94,94,95,95,95,95,95,96,96,97,97,98,98,99,99,100,100,101,101,102,102,103,104,104,105,106,107,108,109,110,111,112,113,113,115,117,119,121,122,124,127,130,132,135,139,142,146,149,153,158,162,167,171,176,180,186,193,202,209,216,223,232,243,254,266,279,292,306,320,335,337,351,367,380,396,414,437,464,493,520,549,583,611,644,675,711,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, + DEC_CURVE,CRV_PARKHOME ,138,142,146,149,153,158,162,167,171,176,180,186,193,202,209,216,223,232,243,254,266,279,292,306,320,335,337,351,367,380,396,414,437,464,493,520,549,583,611,644,675,711,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, + DEC_CURVE,CRV_SMEARING ,138,139,139,139,139,139,139,139,140,140,140,140,140,140,140,140,140,140,140,140,140,141,141,141,141,141,141,141,142,142,142,142,142,142,143,143,143,143,143,143,144,144,144,144,144,144,145,145,145,145,145,145,146,146,146,146,146,147,147,147,147,147,147,148,148,148,148,148,148,149,149,149,149,149,149,149,149,149,149,150,150,150,150,150,151,151,151,151,151,152,152,152,152,152,153,153,153,153,153,154,154,154,154,154,155,155,155,155,155,156,156,156,156,157,157,157,157,157,158,158,158,158,158,158,158,158,159,159,159,159,160,160,160,160,160,161,161,161,161,162,162,162,162,163,163,163,163,164,164,164,165,165,165,165,166,166,166,166,167,167,167,167,167,167,167,168,168,168,168,169,169,169,170,170,170,170,171,171,171,172,172,172,173,173,173,174,174,174,174,175,175,175,176,176,176,176,176,176,177,177,177,178,178,178,179,179,180,180,180,181,181,181,182,182,182,183,183,184,184,184,185,185,185,185,185,186,186,186,187,187,188,188,188,189,189,190,190,191,191,191,192,192,193,193,194,194,194,194,194,195,195,196,196,197,197,198,198,199,199,200,200,201,201,202,202,203,203,203,203,204,204,205,205,206,207,207,208,208,209,209,210,211,211,212,212,212,213,213,214,214,215,216,216,217,218,218,219,220,220,221,221,221,222,223,224,224,225,226,227,227,228,229,230,230,230,231,232,233,233,234,235,236,237,238,239,239,239,240,241,242,243,244,245,246,247,248,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,265,266,266,267,269,270,271,273,274,275,276,277,279,280,282,283,284,285,287,289,290,292,293,294,296,298,300,301,302,304,306,308,310,311,313,315,318,320,321,323,326,328,330,332,335,337,339,342,344,347,349,352,355,358,361,364,366,370,374,376,380,383,387,391,394,399,402,407,411,416,420,425,430,436,441,446,453,458,464,472,478,485,493,501,509,518,527,537,548,559,571,583,597,611,626,644,662,682,704,728,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, + DEC_CURVE,CRV_BUFFERFULL,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,94,94,94,95,95,95,95,95,96,96,97,97,98,98,99,99,100,100,101,101,102,102,103,104,104,105,106,107,108,109,110,111,112,113,113,115,117,119,121,122,124,127,130,132,135,139,142,146,149,153,158,162,167,171,176,180,186,193,202,209,216,223,232,243,254,266,279,292,306,320,335,337,351,367,380,396,414,437,464,493,520,549,583,611,644,675,711,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, + -2, + + /* motorcurve 6 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,23999, 0, + ACC_CURVE,CRV_PARKHOME ,5360,3362,2628,2229,1973,1791,1654,1547,1458,1384,1319,1264,1214,1170,1131,1096,1063,1034,1006,981,958,937,916,897,880,863,847,832,818,805,792,780,769,758,747,737,727,718,709,700,692, 0, + ACC_CURVE,CRV_SMEARING ,23999, 0, + DEC_CURVE,CRV_NORMALSCAN,23999, 0, + DEC_CURVE,CRV_PARKHOME ,692,700,709,718,727,737,747,758,769,780,792,805,818,832,847,863,880,897,916,937,958,981,1006,1034,1063,1096,1131,1170,1214,1264,1319,1384,1458,1547,1654,1791,1973,2229,2628,3362,5360, 0, + DEC_CURVE,CRV_SMEARING ,23999, 0, + DEC_CURVE,CRV_BUFFERFULL,23999, 0, + -2, + + /* motorcurve 7 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,6667, 0, + ACC_CURVE,CRV_PARKHOME ,5360,3362,2628,2229,1973,1791,1654,1547,1458,1384,1319,1264,1214,1170,1131,1096,1063,1034,1006,981,958,937,916,897,880,863,847,832,818,805,792,780,769,758,747,737,727,718,709,700,692, 0, + ACC_CURVE,CRV_SMEARING ,6667, 0, + DEC_CURVE,CRV_NORMALSCAN,6667, 0, + DEC_CURVE,CRV_PARKHOME ,692,700,709,718,727,737,747,758,769,780,792,805,818,832,847,863,880,897,916,937,958,981,1006,1034,1063,1096,1131,1170,1214,1264,1319,1384,1458,1547,1654,1791,1973,2229,2628,3362,5360, 0, + DEC_CURVE,CRV_SMEARING ,6667, 0, + DEC_CURVE,CRV_BUFFERFULL,6667, 0, + -2, + + /* motorcurve 8 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,1046,1046,1046,1046,1046,1046,647,501,421,370,333,305,284,266,251,239,228,218,210,202,196,190,184,179,174,170,166,162,159,155,152,149,147,144,142,139,137,135,133,131,129,127,126,124,123,121,120,118,117,116,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,100,99,98,97,96,96,95,94,94,93,92,92,91,91,90,89,89,88,88,87,87,86,86,85,85,84,84,83,83,82,82,82,81,81,80,80,79,79,79,78,78,78,77,77,76,76,76,75,75,75,74,74,74,74,73,73,73,72,72,72,71,71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66,66,66,66,65,65,65,65,64,64,64,64,63,63,63,63,62,62,62,62,61,61,61,61,61,60,60,60,60,60,60,59,59,59,59,59,59,59,58,58,58,58,58,58,57,57,57,57,57,57,57,56,56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,51,51,50,50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,23,23, 0, + ACC_CURVE,CRV_PARKHOME ,1045,678,604,554,332,332,304,283,265,250,238,227,217,209,201,195,189,183,178,173,169,165,161,158,154,151,148,146,143,141,138,136,134,132,130,128,126,125,123,122,120,119,117,116,115,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,99,98,97,96,95,95,94,93,93,92,91,91,90,90,89,88,88,87,87,86,86,85,85,84,84,83,83,82,82,81,81,81,80,80,79,79,78,78,78,77,77,77,76,76,75,75,75,74,74,74,73,73,73,73,72,72,72,71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66,66,66,66,65,65,65,65,65,64,64,64,64,64,63,63,63,63,63,62,62,62,62,62,61,61,61,61,61,61,60,60,60,60,60,60,59,59,59,59,59,59,58,58,58,58,58,58,58,57,57,57,57,57,57,57,56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,53,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,50,50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47,47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,39, 0, + ACC_CURVE,CRV_SMEARING ,1045,678,604,554,332,332,304,283,265,250,238,227,217,209,201,195,189,183,178,173,169,165,161,158,154,151,148,146,143,141,138,136,134,132,130,128,126,125,123,122,120,119,117,116,115,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,99,98,97,96,95,95,94,93,93,92,91,91,90,90,89,88,88,87,87,86,86,85,85,84,84,83,83,82,82,81,81,81,80,80,79,79,78,78,78,77,77,77,76,76,75,75,75,74,74,74,73,73,73,73,72,72,72,71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66,66,66,66,65,65,65,65,65,64,64,64,64,64,63,63,63,63,63,62,62,62,62,62,61,61,61,61,61,61,60,60,60,60,60,60,59,59,59,59,59,59,58,58,58,58,58,58,58,57,57,57,57,57,57,57,56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,53,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,50,50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47,47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,39, 0, + DEC_CURVE,CRV_NORMALSCAN,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,30,30,30,30,31,31,31,31,32,32,32,32,33,33,34,34,35,35,36,37,38,38,39,40,41,42,43,45,46,47,48,50,51,53,54,57,59,61,63,65,68,71,75,78,82,86,90,94,94,98,103,106,111,116,122,130,138,145,153,163,171,180,188,198,211,219,228,239,252,267,284,306,334,370,422,502,648,1045, 0, + DEC_CURVE,CRV_PARKHOME ,39,40,41,42,43,45,46,47,48,50,51,53,54,57,59,61,63,65,68,71,75,78,82,86,90,94,94,98,103,106,111,116,122,130,138,145,153,163,171,180,188,198,211,219,228,239,252,267,284,306,334,370,422,502,648,1045, 0, + DEC_CURVE,CRV_SMEARING ,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48,48,49,49,49,49,49,49,49,49,49,49,49,49,49,50,50,50,50,50,50,50,50,50,50,50,50,51,51,51,51,51,51,51,51,51,51,51,52,52,52,52,52,52,52,52,52,52,53,53,53,53,53,53,53,53,53,53,54,54,54,54,54,54,54,54,54,55,55,55,55,55,55,55,55,55,56,56,56,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,59,59,59,59,59,59,59,60,60,60,60,60,60,60,61,61,61,61,61,61,62,62,62,62,62,62,63,63,63,63,63,64,64,64,64,64,65,65,65,65,65,66,66,66,66,66,67,67,67,67,67,68,68,68,68,69,69,69,69,70,70,70,70,71,71,71,71,72,72,72,73,73,73,73,74,74,74,75,75,75,76,76,76,77,77,77,78,78,78,79,79,79,80,80,81,81,81,82,82,83,83,84,84,84,85,85,86,86,87,87,88,88,89,90,90,91,91,92,93,93,94,94,95,96,96,97,98,99,99,100,101,102,103,104,105,105,106,107,108,109,110,112,113,114,115,116,118,119,120,122,123,125,127,128,130,132,134,136,138,140,142,145,147,150,153,156,159,163,167,171,175,180,185,190,196,203,211,219,228,239,252,267,284,306,334,370,422,502,648,1045, 0, + DEC_CURVE,CRV_BUFFERFULL,1045,648,502,422,370,334,306,284,267,252,239,228,219,211,198,188,180,171,163,153,145,138,130,122,116,111,106,103,98,94,94,90,86,82,78,75,71,68,65,63,61,59,57,54,53,51,50,48,47,46,45,43,42,41,40,39,38,38,37,36,35,35,34,34,33,33,32,32,32,32,31,31,31,31,30,30,30,30,29,29,29,29,29,29,29,28,28,28,28,28,28,28,28,27,27,27,27,27,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, 0, + -2, + + /* motorcurve 9 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, + ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166,166,166, 0, + ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,455, 0, + DEC_CURVE,CRV_NORMALSCAN,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136,3136,3136,3136,3136,3136, 0, + DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136,3136,3136,3136,3136,3136, 0, + DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136,3136,3136,3136,3136,3136, 0, + DEC_CURVE,CRV_BUFFERFULL,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,127,127,128,128,129,129,130,131,132,133,133,134,135,136,137,138,139,140,141,143,144,145,146,147,149,150,151,153,154,156,157,159,161,162,164,166,168,170,172,174,176,179,181,184,186,189,192,195,198,202,206,209,213,218,222,227,233,239,245,252,259,267,276,282,286,291,298,305,310,319,325,331,342,354,362,376,387,404,417,431,456,475,509,551,586,654,715,850,998,1664,3136,3136, 0, + -2, + + /* motorcurve 10 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376, 0, + ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, + ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,455, 0, + DEC_CURVE,CRV_NORMALSCAN,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, + DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, + DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, + DEC_CURVE,CRV_BUFFERFULL,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, + -2, + + /* motorcurve 11 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, + ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, + ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, + DEC_CURVE,CRV_NORMALSCAN,167,168,169,170,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,190,191,192,193,194,196,197,198,200,201,203,204,206,207,209,211,212,214,216,218,219,221,223,225,227,230,232,234,236,239,241,244,247,249,252,255,258,261,265,268,272,275,279,283,288,292,297,302,307,313,318,325,331,338,346,353,362,371,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, + DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, + DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, + DEC_CURVE,CRV_BUFFERFULL,167,168,169,170,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,190,191,192,193,194,196,197,198,200,201,203,204,206,207,209,211,212,214,216,218,219,221,223,225,227,230,232,234,236,239,241,244,247,249,252,255,258,261,265,268,272,275,279,283,288,292,297,302,307,313,318,325,331,338,346,353,362,371,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, + -2, + + /* motorcurve 12 */ + 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ + ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166,166,166,165,165,165,164,164,163,163,163,162,162,162,161,161,161,160,160,160,159,159,159,158,158,158,157,157,157,156,156,156,156,155,155,155,154,154,154,153,153,153,153,152,152,152,151,151,151,151,150,150,150,150,149,149,149,148,148,148,148,147,147,147,147,146,146,146,146,145,145,145,145,144,144,144,144,144,143,143,143,143,142,142,142,142,141,141,141,141,141,140,140,140,140,140,139,139,139,139,138,138,138,138,138,137,137,137,137,137,136,136,136,136,136,135,135,135,135,135,135,134,134,134,134,134,133,133,133,133,133,133,132,132,132,132,132,131,131,131,131,131,131,130,130,130,130,130,130,129,129,129,129,129,129,128,128,128,128,128,128,127,127,127,127,127,127,127,126,126,126,126,126,126,125, 0, + ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, + ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,455, 0, + DEC_CURVE,CRV_NORMALSCAN,110,110,110,110,110,110,110,110,111,111,111,111,111,112,112,112,112,112,113,113,113,113,114,114,114,114,115,115,115,115,115,116,116,116,116,117,117,117,117,118,118,118,118,119,119,119,120,120,120,120,121,121,121,121,122,122,122,123,123,123,124,124,124,124,125,125,125,126,126,126,127,127,127,128,128,128,129,129,129,130,130,130,131,131,132,132,132,133,133,133,134,134,135,135,135,136,136,137,137,138,138,138,139,139,140,140,141,141,142,142,142,143,143,144,144,145,145,146,146,147,148,148,149,149,150,150,151,151,152,153,153,154,154,155,156,156,157,158,158,159,160,160,161,162,163,163,164,165,166,166,167,168,169,170,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,190,191,192,193,194,196,197,198,200,201,203,204,206,207,209,211,212,214,216,218,219,221,223,225,227,230,232,234,236,239,241,244,247,249,252,255,258,261,265,268,272,275,279,283,288,292,297,302,307,313,318,325,331,338,346,353,362,371,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, + DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, + DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, + DEC_CURVE,CRV_BUFFERFULL,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,127,127,128,128,129,129,130,131,132,133,133,134,135,136,137,138,139,140,141,143,144,145,146,147,149,150,151,153,154,156,157,159,161,162,164,166,168,170,172,174,176,179,181,184,186,189,192,195,198,202,206,209,213,218,222,227,233,239,245,252,259,267,276,282,286,291,298,305,310,319,325,331,342,354,362,376,387,404,417,431,456,475,509,551,586,654,715,850,998,1664,3136, 0, + -1 + }; + + rst = (SANE_Int *)malloc(sizeof(steps)); + if (rst != NULL) + memcpy(rst, &steps, sizeof(steps)); + + return rst; +} + +static SANE_Int *cfg_motorcurve_get() +{ + /* returns motor setting buffer for a device */ + + SANE_Int *rst = NULL; + + switch(RTS_Debug->dev_model) + { + case BQ5550: + rst = bq5550_motor(); + break; + + case HP3800: + rst = hp3800_motor(); + break; + + case HP4370: + case HPG3010: + rst = hp4370_motor(); + break; + + default: + rst = hp3970_motor(); + break; + } + + return rst; +} + +static int ua4900_calibreflective(int option, int defvalue) +{ + int rst = defvalue; + + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 0; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 300; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 310; break; + case OFFSETODD1R: rst = 310; break; + case OFFSETEVEN1G: rst = 313; break; + case OFFSETODD1G: rst = 313; break; + case OFFSETEVEN1B: rst = 319; break; + case OFFSETODD1B: rst = 319; break; + case ADCOFFPREDICTR: rst = 321; break; + case ADCOFFPREDICTG: rst = 321; break; + case ADCOFFPREDICTB: rst = 321; break; + case ADCOFFEVEN1R_1ST: rst = 344; break; + case ADCOFFODD1R_1ST: rst = 344; break; + case ADCOFFEVEN1G_1ST: rst = 328; break; + case ADCOFFODD1G_1ST: rst = 328; break; + case ADCOFFEVEN1B_1ST: rst = 341; break; + case ADCOFFODD1B_1ST: rst = 341; break; + case PEAKR: rst = 122; break; + case PEAKG: rst = 122; break; + case PEAKB: rst = 122; break; + case MINR: rst = 50; break; + case MING: rst = 50; break; + case MINB: rst = 50; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 10; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 8; break; + case GAIN1G: rst = 8; break; + case GAIN1B: rst = 8; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 8; break; + case GAIN2G: rst = 8; break; + case GAIN2B: rst = 8; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -2; break; + case BSHADINGHEIGHT: rst = 10; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 1; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 15; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp3800_calibreflective(int option, int defvalue) +{ + int rst = defvalue; + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 0; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 300; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 310; break; + case OFFSETODD1R: rst = 310; break; + case OFFSETEVEN1G: rst = 317; break; + case OFFSETODD1G: rst = 317; break; + case OFFSETEVEN1B: rst = 293; break; + case OFFSETODD1B: rst = 293; break; + case ADCOFFPREDICTR: rst = 500; break; + case ADCOFFPREDICTG: rst = 500; break; + case ADCOFFPREDICTB: rst = 500; break; + case ADCOFFEVEN1R_1ST: rst = 128; break; + case ADCOFFODD1R_1ST: rst = 128; break; + case ADCOFFEVEN1G_1ST: rst = 128; break; + case ADCOFFODD1G_1ST: rst = 128; break; + case ADCOFFEVEN1B_1ST: rst = 128; break; + case ADCOFFODD1B_1ST: rst = 128; break; + case PEAKR: rst = 104; break; + case PEAKG: rst = 111; break; + case PEAKB: rst = 105; break; + case MINR: rst = 50; break; + case MING: rst = 56; break; + case MINB: rst = 57; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 10; break; + case GAINTARGETFACTOR: rst = 80; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 23; break; + case GAIN1G: rst = 19; break; + case GAIN1B: rst = 0; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -3; break; + case BSHADINGHEIGHT: rst = 20; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp3970_calibreflective(int option, int defvalue) +{ + int rst = defvalue; + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 0; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 300; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 327; break; + case OFFSETODD1R: rst = 327; break; + case OFFSETEVEN1G: rst = 315; break; + case OFFSETODD1G: rst = 315; break; + case OFFSETEVEN1B: rst = 322; break; + case OFFSETODD1B: rst = 322; break; + case ADCOFFPREDICTR: rst = 322; break; + case ADCOFFPREDICTG: rst = 310; break; + case ADCOFFPREDICTB: rst = 322; break; + case ADCOFFEVEN1R_1ST: rst = 344; break; + case ADCOFFODD1R_1ST: rst = 344; break; + case ADCOFFEVEN1G_1ST: rst = 328; break; + case ADCOFFODD1G_1ST: rst = 328; break; + case ADCOFFEVEN1B_1ST: rst = 341; break; + case ADCOFFODD1B_1ST: rst = 341; break; + case PEAKR: rst = 82; break; + case PEAKG: rst = 117; break; + case PEAKB: rst = 116; break; + case MINR: rst = 37; break; + case MING: rst = 51; break; + case MINB: rst = 53; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 10; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 28; break; + case GAIN1G: rst = 22; break; + case GAIN1B: rst = 21; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -2; break; + case BSHADINGHEIGHT: rst = 10; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp4370_calibreflective(int option, int defvalue) +{ + int rst = defvalue; + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 0; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 300; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 305; break; + case OFFSETODD1R: rst = 3305; break; + case OFFSETEVEN1G: rst = 313; break; + case OFFSETODD1G: rst = 313; break; + case OFFSETEVEN1B: rst = 317; break; + case OFFSETODD1B: rst = 317; break; + case ADCOFFPREDICTR: rst = 500; break; + case ADCOFFPREDICTG: rst = 500; break; + case ADCOFFPREDICTB: rst = 500; break; + case ADCOFFEVEN1R_1ST: rst = 344; break; + case ADCOFFODD1R_1ST: rst = 344; break; + case ADCOFFEVEN1G_1ST: rst = 328; break; + case ADCOFFODD1G_1ST: rst = 328; break; + case ADCOFFEVEN1B_1ST: rst = 341; break; + case ADCOFFODD1B_1ST: rst = 341; break; + case PEAKR: rst = 159; break; + case PEAKG: rst = 191; break; + case PEAKB: rst = 191; break; + case MINR: rst = 146; break; + case MING: rst = 180; break; + case MINB: rst = 179; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 10; break; + case GAINTARGETFACTOR: rst = 80; break; + case CALIBPAGON: rst = 0; break; + case HIPAGR: rst = 3; break; + case HIPAGG: rst = 0; break; + case HIPAGB: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case LOPAGR: rst = 3; break; + case LOPAGG: rst = 3; break; + case LOPAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 10; break; + case GAIN1G: rst = 2; break; + case GAIN1B: rst = 1; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -2; break; + case BSHADINGHEIGHT: rst = 10; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int fc_calibreflective(int option, int defvalue) +{ + int rst; + + switch(RTS_Debug->dev_model) + { + case UA4900: rst = ua4900_calibreflective(option, defvalue); break; + case HP3800: rst = hp3800_calibreflective(option, defvalue); break; + case HPG3010: + case HP4370: rst = hp4370_calibreflective(option, defvalue); break; + default : rst = hp3970_calibreflective(option, defvalue); break; + } + + return rst; +} + +static int ua4900_calibtransparent(int option, int defvalue) +{ + int rst = defvalue; + + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 12100; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 2; break; + case BREFG: rst = 2; break; + case BREFB: rst = 2; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 13; break; + case OFFSETAVGTARGETG: rst = 13; break; + case OFFSETAVGTARGETB: rst = 13; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 321; break; + case OFFSETODD1R: rst = 321; break; + case OFFSETEVEN1G: rst = 321; break; + case OFFSETODD1G: rst = 321; break; + case OFFSETEVEN1B: rst = 321; break; + case OFFSETODD1B: rst = 321; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 177; break; + case PEAKG: rst = 177; break; + case PEAKB: rst = 177; break; + case MINR: rst = 136; break; + case MING: rst = 136; break; + case MINB: rst = 136; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 0; break; + case PAGG: rst = 0; break; + case PAGB: rst = 0; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 24; break; + case GAIN1G: rst = 21; break; + case GAIN1B: rst = 19; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 8; break; + case GAIN2G: rst = 8; break; + case GAIN2B: rst = 8; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = 2; break; + case BSHADINGHEIGHT: rst = 10; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp3800_calibtransparent(int option, int defvalue) +{ + int rst = defvalue; + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 4155; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 2; break; + case BREFG: rst = 2; break; + case BREFB: rst = 2; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 310; break; + case OFFSETODD1R: rst = 310; break; + case OFFSETEVEN1G: rst = 299; break; + case OFFSETODD1G: rst = 299; break; + case OFFSETEVEN1B: rst = 309; break; + case OFFSETODD1B: rst = 309; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 67; break; + case PEAKG: rst = 61; break; + case PEAKB: rst = 57; break; + case MINR: rst = 10; break; + case MING: rst = 10; break; + case MINB: rst = 10; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 2; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 9; break; + case GAIN1G: rst = 12; break; + case GAIN1B: rst = 10; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -3; break; + case BSHADINGHEIGHT: rst = 30; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp3970_calibtransparent(int option, int defvalue) +{ + int rst = defvalue; + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 7500; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 2; break; + case BREFG: rst = 2; break; + case BREFB: rst = 2; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 323; break; + case OFFSETODD1R: rst = 323; break; + case OFFSETEVEN1G: rst = 327; break; + case OFFSETODD1G: rst = 327; break; + case OFFSETEVEN1B: rst = 327; break; + case OFFSETODD1B: rst = 327; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 42; break; + case PEAKG: rst = 55; break; + case PEAKB: rst = 53; break; + case MINR: rst = 31; break; + case MING: rst = 39; break; + case MINB: rst = 38; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 2; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 21; break; + case GAIN1G: rst = 14; break; + case GAIN1B: rst = 12; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = 1; break; + case BSHADINGHEIGHT: rst = 30; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp4370_calibtransparent(int option, int defvalue) +{ + int rst = defvalue; + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 6580; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 2; break; + case BREFG: rst = 2; break; + case BREFB: rst = 2; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 315; break; + case OFFSETODD1R: rst = 321; break; + case OFFSETEVEN1G: rst = 321; break; + case OFFSETODD1G: rst = 324; break; + case OFFSETEVEN1B: rst = 324; break; + case OFFSETODD1B: rst = 327; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 62; break; + case PEAKG: rst = 66; break; + case PEAKB: rst = 54; break; + case MINR: rst = 42; break; + case MING: rst = 45; break; + case MINB: rst = 45; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 80; break; + case CALIBPAGON: rst = 0; break; + case HIPAGR: rst = 3; break; + case HIPAGG: rst = 3; break; + case HIPAGB: rst = 2; break; + case LOPAGR: rst = 3; break; + case LOPAGG: rst = 3; break; + case LOPAGB: rst = 2; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 2; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 11; break; + case GAIN1G: rst = 9; break; + case GAIN1B: rst = 12; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -2; break; + case BSHADINGHEIGHT: rst = 30; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int fc_calibtransparent(int option, int defvalue) +{ + int rst; + + switch(RTS_Debug->dev_model) + { + case UA4900: rst = ua4900_calibtransparent(option, defvalue); break; + case HP3800: rst = hp3800_calibtransparent(option, defvalue); break; + case HPG3010: + case HP4370: rst = hp4370_calibtransparent(option, defvalue); break; + default : rst = hp3970_calibtransparent(option, defvalue); break; + } + + return rst; +} + +static int ua4900_calibnegative(int option, int defvalue) +{ + int rst = defvalue; + + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 12100; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 2; break; + case BREFG: rst = 2; break; + case BREFB: rst = 2; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 5; break; + case OFFSETAVGTARGETG: rst = 5; break; + case OFFSETAVGTARGETB: rst = 5; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 283; break; + case OFFSETODD1R: rst = 283; break; + case OFFSETEVEN1G: rst = 279; break; + case OFFSETODD1G: rst = 279; break; + case OFFSETEVEN1B: rst = 295; break; + case OFFSETODD1B: rst = 295; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 113; break; + case PEAKG: rst = 145; break; + case PEAKB: rst = 126; break; + case MINR: rst = 80; break; + case MING: rst = 105; break; + case MINB: rst = 96; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 10; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 0; break; + case PAGG: rst = 0; break; + case PAGB: rst = 0; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 8; break; + case GAIN1G: rst = 8; break; + case GAIN1B: rst = 8; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 8; break; + case GAIN2G: rst = 8; break; + case GAIN2B: rst = 8; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = 2; break; + case BSHADINGHEIGHT: rst = 10; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp3800_calibnegative(int option, int defvalue) +{ + int rst = defvalue; + + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 4155; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 315; break; + case OFFSETODD1R: rst = 315; break; + case OFFSETEVEN1G: rst = 307; break; + case OFFSETODD1G: rst = 304; break; + case OFFSETEVEN1B: rst = 309; break; + case OFFSETODD1B: rst = 309; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 37; break; + case PEAKG: rst = 234; break; + case PEAKB: rst = 202; break; + case MINR: rst = 32; break; + case MING: rst = 195; break; + case MINB: rst = 166; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 30; break; + case GAIN1G: rst = 3; break; + case GAIN1B: rst = 0; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -2; break; + case BSHADINGHEIGHT: rst = 30; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp3970_calibnegative(int option, int defvalue) +{ + int rst = defvalue; + + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 7500; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 294; break; + case OFFSETODD1R: rst = 294; break; + case OFFSETEVEN1G: rst = 276; break; + case OFFSETODD1G: rst = 276; break; + case OFFSETEVEN1B: rst = 266; break; + case OFFSETODD1B: rst = 266; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 33; break; + case PEAKG: rst = 75; break; + case PEAKB: rst = 105; break; + case MINR: rst = 19; break; + case MING: rst = 34; break; + case MINB: rst = 42; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 90; break; + case CALIBPAGON: rst = 0; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 23; break; + case GAIN1G: rst = 18; break; + case GAIN1B: rst = 23; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = 1; break; + case BSHADINGHEIGHT: rst = 30; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int hp4370_calibnegative(int option, int defvalue) +{ + int rst = defvalue; + + switch(option) + { + case WSTRIPXPOS: rst = 0; break; + case WSTRIPYPOS: rst = 6580; break; + case BSTRIPXPOS: rst = 0; break; + case BSTRIPYPOS: rst = 0; break; + case BREFR: rst = 10; break; + case BREFG: rst = 10; break; + case BREFB: rst = 10; break; + case REFBITDEPTH: rst = 8; break; + case OFFSETHEIGHT: rst = 10; break; + case OFFSETNSIGMA: rst = 2; break; + case OFFSETTARGETMAX: rst = 50; break; + case OFFSETTARGETMIN: rst = 2; break; + case OFFSETAVGTARGETR: rst = 10; break; + case OFFSETAVGTARGETG: rst = 10; break; + case OFFSETAVGTARGETB: rst = 10; break; + case ADCOFFEVENODD: rst = 1; break; + case CALIBOFFSET1ON: rst = 2; break; + case ADCOFFQUICKWAY: rst = 1; break; + case ADCOFFPREDICTSTART: rst = 200; break; + case ADCOFFPREDICTEND: rst = 500; break; + case OFFSETTUNESTEP1: rst = 5; break; + case OFFSETBOUNDARYRATIO1: rst = 100; break; + case OFFSETAVGRATIO1: rst = 100; break; + case OFFSETEVEN1R: rst = 308; break; + case OFFSETODD1R: rst = 308; break; + case OFFSETEVEN1G: rst = 317; break; + case OFFSETODD1G: rst = 317; break; + case OFFSETEVEN1B: rst = 319; break; + case OFFSETODD1B: rst = 319; break; + case ADCOFFPREDICTR: rst = 333; break; + case ADCOFFPREDICTG: rst = 313; break; + case ADCOFFPREDICTB: rst = 317; break; + case ADCOFFEVEN1R_1ST: rst = 69; break; + case ADCOFFODD1R_1ST: rst = 69; break; + case ADCOFFEVEN1G_1ST: rst = 87; break; + case ADCOFFODD1G_1ST: rst = 87; break; + case ADCOFFEVEN1B_1ST: rst = 106; break; + case ADCOFFODD1B_1ST: rst = 106; break; + case PEAKR: rst = 116; break; + case PEAKG: rst = 126; break; + case PEAKB: rst = 102; break; + case MINR: rst = 103; break; + case MING: rst = 112; break; + case MINB: rst = 80; break; + case CALIBOFFSET2ON: rst = 0; break; + case OFFSETTUNESTEP2: rst = 1; break; + case OFFSETBOUNDARYRATIO2: rst = 100; break; + case OFFSETAVGRATIO2: rst = 100; break; + case OFFSETEVEN2R: rst = 0; break; + case OFFSETODD2R: rst = 0; break; + case OFFSETEVEN2G: rst = 0; break; + case OFFSETODD2G: rst = 0; break; + case OFFSETEVEN2B: rst = 0; break; + case OFFSETODD2B: rst = 0; break; + case GAINHEIGHT: rst = 30; break; + case GAINTARGETFACTOR: rst = 80; break; + case CALIBPAGON: rst = 0; break; + case HIPAGR: rst = 3; break; + case HIPAGG: rst = 3; break; + case HIPAGB: rst = 3; break; + case LOPAGR: rst = 3; break; + case LOPAGG: rst = 3; break; + case LOPAGB: rst = 3; break; + case PAGR: rst = 3; break; + case PAGG: rst = 3; break; + case PAGB: rst = 3; break; + case CALIBGAIN1ON: rst = 1; break; + case GAIN1R: rst = 6; break; + case GAIN1G: rst = 1; break; + case GAIN1B: rst = 7; break; + case CALIBGAIN2ON: rst = 0; break; + case GAIN2R: rst = 4; break; + case GAIN2G: rst = 4; break; + case GAIN2B: rst = 4; break; + case TOTSHADING: rst = 0; break; + case BSHADINGON: rst = -2; break; + case BSHADINGHEIGHT: rst = 30; break; + case BSHADINGPREDIFFR: rst = 2; break; + case BSHADINGPREDIFFG: rst = 2; break; + case BSHADINGPREDIFFB: rst = 2; break; + case BSHADINGDEFCUTOFF: rst = 0; break; + case WSHADINGON: rst = 3; break; + case WSHADINGHEIGHT: rst = 24; break; + case WSHADINGPREDIFFR: rst = -1; break; + case WSHADINGPREDIFFG: rst = -1; break; + case WSHADINGPREDIFFB: rst = -1; break; + } + + return rst; +} + +static int fc_calibnegative(int option, int defvalue) +{ + int rst; + + switch(RTS_Debug->dev_model) + { + case UA4900: rst = ua4900_calibnegative(option, defvalue); break; + case HP3800: rst = hp3800_calibnegative(option, defvalue); break; + case HPG3010: + case HP4370: rst = hp4370_calibnegative(option, defvalue); break; + default : rst = hp3970_calibnegative(option, defvalue); break; + } + + return rst; +} + +static int fc_scaninfo_get(int option, int defvalue) +{ + int value[] = {1, 0, 0, 0, 0, 100}; + int ua4900_value[] = {1, 0xcdcdcdcd, 0xcdcdcdcd, 0xcdcdcdcd, 0xcdcdcdcd, 100}; + + int rst = defvalue; + int *myvalue = NULL; + + switch(RTS_Debug->dev_model) + { + case UA4900: myvalue = ua4900_value; break; + default: myvalue = value; break; + } + + switch(option) + { + case PARKHOMEAFTERCALIB: rst = myvalue[0]; break; + case SHADINGTIME_16BIT: rst = myvalue[1]; break; + case SHADOWTIME_16BIT: rst = myvalue[2]; break; + case SHADINGTIME_8BIT: rst = myvalue[3]; break; + case SHADOWTIME_8BIT: rst = myvalue[4]; break; + case PREVIEWDPI: rst = myvalue[5]; break; + } + + return rst; +} + +/* fitcalibrate */ +static int fitcalibrate_get(int section, int option, int defvalue) +{ + int rst = defvalue; + + switch(section) + { + case CALIBREFLECTIVE: + rst = fc_calibreflective(option, defvalue); break; + case CALIBTRANSPARENT: + rst = fc_calibtransparent(option, defvalue); break; + case CALIBNEGATIVEFILM: + rst = fc_calibnegative(option, defvalue); break; + case SCANINFO: + rst = fc_scaninfo_get(option, defvalue); break; + } + + return rst; +} + +static int srt_hp3800_scanparam_get(int option, int defvalue) +{ + int rst = defvalue; + + /* t_rtinifile */ + int value3[] = {1, 0, 0, 0, 1, 0, 12, 0, 1, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 0}; + + int *value = value3; + + if (value != NULL) + switch(option) + { + case ARRANGELINE: rst = value[0]; break; + case COMPRESSION: rst = value[1]; break; + case TA_X_START: rst = value[2]; break; + case TA_Y_START: rst = value[3]; break; + case DPIGAINCONTROL600: rst = value[4]; break; + case DPILUMPING100: rst = value[5]; break; + case CRVS: rst = value[6]; break; + case MLOCK: rst = value[7]; break; + case ENABLEWARMUP: rst = value[8]; break; + case NMAXTARGET: rst = value[9]; break; + case NMINTARGET: rst = value[10]; break; + case NMAXTARGETTA: rst = value[11]; break; + case NMINTARGETTA: rst = value[12]; break; + case NMAXTARGETNEG: rst = value[13]; break; + case NMINTARGETNEG: rst = value[14]; break; + case STABLEDIFF: rst = value[15]; break; + case DELTAPWM: rst = value[16]; break; + case PWMLAMPENABLED: rst = value[17]; break; + case PWMLAMPLEVEL: rst = value[18]; break; + case TMAPWMDUTY: rst = value[19]; break; + case LEFTLEADING: rst = value[20]; break; + } + + return rst; +} + +static int srt_hp3970_scanparam_get(int file, int option, int defvalue) +{ + int rst = defvalue; + /* s_rtinifile */ + int value1[] = {1, 0, 150, 0, 1, 0, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 360}; + /* s_usb1inifile */ + int value2[] = {1, 0, 150, 0, 1, 0, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 360}; + /* t_rtinifile */ + int value3[] = {1, 0, 150, 0, 1, 0, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 0}; + /* t_usb1inifile */ + int value4[] = {1, 0, 150, 0, 1, 0, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 0}; + + int *value = NULL; + + switch(file) + { + case S_RTINIFILE: value = value1; break; + case S_USB1INIFILE: value = value2; break; + case T_RTINIFILE: value = value3; break; + case T_USB1INIFILE: value = value4; break; + } + + if (value != NULL) + switch(option) + { + case ARRANGELINE: rst = value[0]; break; + case COMPRESSION: rst = value[1]; break; + case TA_X_START: rst = value[2]; break; + case TA_Y_START: rst = value[3]; break; + case DPIGAINCONTROL600: rst = value[4]; break; + case DPILUMPING100: rst = value[5]; break; + case CRVS: rst = value[6]; break; + case MLOCK: rst = value[7]; break; + case ENABLEWARMUP: rst = value[8]; break; + case NMAXTARGET: rst = value[9]; break; + case NMINTARGET: rst = value[10]; break; + case NMAXTARGETTA: rst = value[11]; break; + case NMINTARGETTA: rst = value[12]; break; + case NMAXTARGETNEG: rst = value[13]; break; + case NMINTARGETNEG: rst = value[14]; break; + case STABLEDIFF: rst = value[15]; break; + case DELTAPWM: rst = value[16]; break; + case PWMLAMPENABLED: rst = value[17]; break; + case PWMLAMPLEVEL: rst = value[18]; break; + case TMAPWMDUTY: rst = value[19]; break; + case LEFTLEADING: rst = value[20]; break; + } + + return rst; +} + +static int srt_hp4370_scanparam_get(int file, int option, int defvalue) +{ + /* s_rtinifile */ + int value1[] = {1, 0, 150, 0, 1, 0, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 360}; + /* s_usb1inifile */ + int value2[] = {1, 0, 150, 0, 1, 0, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 360}; + /* t_rtinifile */ + int value3[] = {1, 0, 150, 0, 1, 0, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 0}; + /* t_usb1inifile */ + int value4[] = {1, 0, 150, 0, 1, 0, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 1, 0, 36, 0}; + int *value = NULL; + + int rst = defvalue; + + switch(file) + { + case S_RTINIFILE: value = value1; break; + case S_USB1INIFILE: value = value2; break; + case T_RTINIFILE: value = value3; break; + case T_USB1INIFILE: value = value4; break; + } + + if (value != NULL) + switch(option) + { + case ARRANGELINE: rst = value[0]; break; + case COMPRESSION: rst = value[1]; break; + case TA_X_START: rst = value[2]; break; + case TA_Y_START: rst = value[3]; break; + case DPIGAINCONTROL600: rst = value[4]; break; + case DPILUMPING100: rst = value[5]; break; + case CRVS: rst = value[6]; break; + case MLOCK: rst = value[7]; break; + case ENABLEWARMUP: rst = value[8]; break; + case NMAXTARGET: rst = value[9]; break; + case NMINTARGET: rst = value[10]; break; + case NMAXTARGETTA: rst = value[11]; break; + case NMINTARGETTA: rst = value[12]; break; + case NMAXTARGETNEG: rst = value[13]; break; + case NMINTARGETNEG: rst = value[14]; break; + case STABLEDIFF: rst = value[15]; break; + case DELTAPWM: rst = value[16]; break; + case PWMLAMPENABLED: rst = value[17]; break; + case PWMLAMPLEVEL: rst = value[18]; break; + case TMAPWMDUTY: rst = value[19]; break; + case LEFTLEADING: rst = value[20]; break; + } + + return rst; +} + +static int srt_scancali_get(int file, int option, int defvalue) +{ + int rst = defvalue; + /* s_rtinifile */ + int value1[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 91, 91, + 53, 53, 48, 48, 104, 104, 59, 59, 64,64}; + /* s_usb1inifile */ + int value2[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 91, 91, + 53, 53, 48, 48, 104, 104, 59, 59, 64, 64}; + /* t_rtinifile*/ + int value3[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 270, 270, + 511, 511, 511, 511, 270, 270, 511, 511, 511, 511}; + /* t_usb1inifile*/ + int value4[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 270, 270, + 511, 511, 511, 511, 270, 270, 511, 511, 511, 511}; + int *value = NULL; + + switch(file) + { + case S_RTINIFILE: value = value1; break; + case S_USB1INIFILE: value = value2; break; + case T_RTINIFILE: value = value3; break; + case T_USB1INIFILE: value = value4; break; + } + + if (value != NULL) + switch(option) + { + case PGA1: rst = value[0]; break; + case PGA2: rst = value[1]; break; + case PGA3: rst = value[2]; break; + case VGAGAIN11: rst = value[3]; break; + case VGAGAIN12: rst = value[4]; break; + case VGAGAIN13: rst = value[5]; break; + case DCSTEPEVEN1: rst = value[6]; break; + case DCSTEPODD1: rst = value[7]; break; + case DCSTEPEVEN2: rst = value[8]; break; + case DCSTEPODD2: rst = value[9]; break; + case DCSTEPEVEN3: rst = value[10]; break; + case DCSTEPODD3: rst = value[11]; break; + case FIRSTDCOFFSETEVEN11: rst = value[12]; break; + case FIRSTDCOFFSETODD11: rst = value[13]; break; + case FIRSTDCOFFSETEVEN12: rst = value[14]; break; + case FIRSTDCOFFSETODD12: rst = value[15]; break; + case FIRSTDCOFFSETEVEN13: rst = value[16]; break; + case FIRSTDCOFFSETODD13: rst = value[17]; break; + case DCOFFSETEVEN11: rst = value[18]; break; + case DCOFFSETODD11: rst = value[19]; break; + case DCOFFSETEVEN12: rst = value[20]; break; + case DCOFFSETODD12: rst = value[21]; break; + case DCOFFSETEVEN13: rst = value[22]; break; + case DCOFFSETODD13: rst = value[23]; break; + } + + return rst; +} + +static int srt_truegrayparam_get(int file, int option, int defvalue) +{ + int rst = defvalue; + /* s_rtinifile */ + int value1[] = {100, 30, 59, 11}; + /* s_usb1inifile */ + int value2[] = {100, 30, 59, 11}; + /* t_rtinifile */ + int value3[] = {100, 30, 59, 11}; + /* t_usb1inifile */ + int value4[] = {100, 30, 59, 11}; + int *value = NULL; + + switch(file) + { + case S_RTINIFILE: value = value1; break; + case S_USB1INIFILE: value = value2; break; + case T_RTINIFILE: value = value3; break; + case T_USB1INIFILE: value = value4; break; + } + + if (value != NULL) + switch(option) + { + case SHADINGBASE: rst = value[0]; break; + case SHADINGFACT1: rst = value[1]; break; + case SHADINGFACT2: rst = value[2]; break; + case SHADINGFACT3: rst = value[3]; break; + } + + return rst; +} + +static int srt_caliparam_get(int file, int option, int defvalue) +{ + int rst = defvalue; + /* s_rtinifile */ + int value1[] = {0xffff}; + /* s_usb1inifile */ + int value2[] = {0xffff}; + /* t_rtinifile */ + int value3[] = {0xffff}; + /* t_usb1inifile */ + int value4[] = {0xffff}; + int *value = NULL; + + switch(file) + { + case S_RTINIFILE: value = value1; break; + case S_USB1INIFILE: value = value2; break; + case T_RTINIFILE: value = value3; break; + case T_USB1INIFILE: value = value4; break; + } + + if (value != NULL) + switch(option) + { + case PIXELDARKLEVEL: rst = value[0]; break; + } + + return rst; +} + +static int srt_hp3800_platform_get(int option, int defvalue) +{ + /* s_rtinifile*/ + int value1[] = {100, 99, 1214636}; + + int *value = value1; + int rst = defvalue; + + if (value != NULL) + { + switch(option) + { + case BINARYTHRESHOLDH: rst = value[0]; break; + case BINARYTHRESHOLDL: rst = value[1]; break; + case CLOSETIME: rst = value[2]; break; + } + } + + return rst; +} + +static int srt_hp3970_platform_get(int option, int defvalue) +{ + /* s_rtinifile*/ + int value1[] = {128, 127, 1214636}; + + int *value = value1; + int rst = defvalue; + + if (value != NULL) + { + switch(option) + { + case BINARYTHRESHOLDH: rst = value[0]; break; + case BINARYTHRESHOLDL: rst = value[1]; break; + case CLOSETIME: rst = value[2]; break; + } + } + + return rst; +} + + +static int srt_ua4900_platform_get(int option, int defvalue) +{ + int value1[] = {128, 127, 1214636}; + int *value = value1; + int rst = defvalue; + + if (value != NULL) + { + switch(option) + { + case BINARYTHRESHOLDH: rst = value[0]; break; + case BINARYTHRESHOLDL: rst = value[1]; break; + case CLOSETIME: rst = value[2]; break; + } + } + + return rst; +} + +static int srt_hp4370_platform_get(int option, int defvalue) +{ + /* t_rtinifile */ + int value3[] = {128, 127, 1214636}; + + int *value = value3; + int rst = defvalue; + + if (value != NULL) + { + switch(option) + { + case BINARYTHRESHOLDH: rst = value[0]; break; + case BINARYTHRESHOLDL: rst = value[1]; break; + case CLOSETIME: rst = value[2]; break; + } + } + + return rst; +} + +static int srt_scaninfo_get(int file, int option, int defvalue) +{ + int rst = defvalue; + int value1[] = {0, 0, 0, 0}; + int value2[] = {0, 0, 0, 0}; + int value3[] = {0, 0, 0, 0}; + int value4[] = {0, 0, 0, 0}; + int *value = NULL; + + switch(file) + { + case S_RTINIFILE: value = value1; break; + case S_USB1INIFILE: value = value2; break; + case T_RTINIFILE: value = value3; break; + case T_USB1INIFILE: value = value4; break; + } + + if (value != NULL) + { + switch(option) + { + case SHADINGTIME_16BIT: rst = value[0]; break; + case SHADOWTIME_16BIT: rst = value[1]; break; + case SHADINGTIME_8BIT: rst = value[2]; break; + case SHADOWTIME_8BIT: rst = value[3]; break; + } + } + + return rst; +} + +static int srt_sec_get(int file, int section, int option, int defvalue) +{ + int rst = defvalue; + + switch(section) + { + case SCAN_PARAM: + switch(RTS_Debug->dev_model) + { + case HP3800: rst = srt_hp3800_scanparam_get(option, defvalue); break; + case HPG3010: + case HP4370: rst = srt_hp4370_scanparam_get(file, option, defvalue); break; + default : rst = srt_hp3970_scanparam_get(file, option, defvalue); break; + } + break; + case SCAN_CALI: + rst = srt_scancali_get(file, option, defvalue); break; + case TRUE_GRAY_PARAM: + rst = srt_truegrayparam_get(file, option, defvalue); break; + case CALI_PARAM: + rst = srt_caliparam_get(file, option, defvalue); break; + case PLATFORM: + switch(RTS_Debug->dev_model) + { + case HP3800: rst = srt_hp3800_platform_get(option, defvalue); break; + case UA4900: rst = srt_ua4900_platform_get(option, defvalue); break; + case HPG3010: + case HP4370: rst = srt_hp4370_platform_get(option, defvalue); break; + default : rst = srt_hp3970_platform_get(option, defvalue); break; + } + break; + case SCANINFO: + rst = srt_scaninfo_get(file, option, defvalue); break; + } + + return rst; +} + +static int get_value(int section, int option, int defvalue, int file) +{ + int rst = defvalue; + + switch(file) + { + case FITCALIBRATE: + rst = fitcalibrate_get(section, option, defvalue); break; + case S_RTINIFILE: + case S_USB1INIFILE: + case T_RTINIFILE: + case T_USB1INIFILE: + rst = srt_sec_get(file, section, option, defvalue); break; + } + + return rst; +} diff --git a/backend/hp3900_debug.c b/backend/hp3900_debug.c new file mode 100644 index 000000000..9296b7444 --- /dev/null +++ b/backend/hp3900_debug.c @@ -0,0 +1,1574 @@ +/* HP Scanjet 3900 series - Debugging functions for standalone + + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +/* debugging level messages */ +#define DBG_ERR 0x00 /* Only important errors */ +#define DBG_VRB 0x01 /* verbose messages */ +#define DBG_FNC 0x02 /* Function names and parameters */ +#define DBG_CTL 0x03 /* USB Ctl data */ +#define DBG_BLK 0x04 /* USB Bulk data */ + +#include +#include /* dbg_tiff_save */ + +/* headers */ + +static void dump_shading (struct st_calibration *myCalib); +static char *dbg_scantype (char *text, SANE_Int type); +static void dbg_scanmodes (struct st_device *dev); +static void dbg_motorcurves (struct st_device *dev); +static void dbg_motormoves (struct st_device *dev); +static void dbg_hwdcfg (struct st_hwdconfig *params); +static void dbg_ScanParams (struct st_scanparams *params); +static void dbg_calibtable (struct st_gain_offset *params); +static char *dbg_colour (char *text, SANE_Int colour); +static void dbg_motorcfg (struct st_motorcfg *motorcfg); +static void dbg_buttons (struct st_buttons *buttons); +static void dbg_sensor (struct st_sensorcfg *sensor); +static void dbg_timing (struct st_timing *mt); +static void dbg_sensorclock (struct st_cph *cph); +static void dbg_tiff_save (char *sFile, SANE_Int width, SANE_Int height, + SANE_Int depth, SANE_Int colortype, SANE_Int res_x, + SANE_Int res_y, SANE_Byte * buffer, SANE_Int size); +static void dbg_autoref (struct st_scanparams *scancfg, SANE_Byte * pattern, + SANE_Int ser1, SANE_Int ser2, SANE_Int ler); + +#ifdef developing +static void dbg_buffer (SANE_Int level, char *title, SANE_Byte * buffer, + SANE_Int size, SANE_Int start); +static void dbg_registers (SANE_Byte * buffer); +#endif + +#ifdef STANDALONE + +/* implementation */ + +int DBG_LEVEL = 0; + +static void +DBG (int level, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + + if (level <= DBG_LEVEL) + vfprintf (stderr, msg, ap); + + va_end (ap); +} + +#endif + +/* debugging functions */ + +static void +dump_shading (struct st_calibration *myCalib) +{ + if (myCalib != NULL) + { + SANE_Int colour, a; + FILE *shadingfile[3]; + + shadingfile[0] = fopen ("RShading.txt", "w"); + shadingfile[1] = fopen ("GShading.txt", "w"); + shadingfile[2] = fopen ("BShading.txt", "w"); + + for (colour = 0; colour < 3; colour++) + { + if (shadingfile[colour] != NULL) + { + for (a = 0; a < myCalib->shadinglength; a++) + fprintf (shadingfile[colour], "%04i: %04x %04x\n", a, + (unsigned int) myCalib->white_shading[colour][a], + (unsigned int) myCalib->black_shading[colour][a]); + fclose (shadingfile[colour]); + } + } + } +} + +static char * +dbg_scantype (char *text, SANE_Int type) +{ + if (text != NULL) + switch (type) + { + case ST_NORMAL: + strcpy (text, "ST_NORMAL"); + break; + case ST_TA: + strcpy (text, "ST_TA"); + break; + case ST_NEG: + strcpy (text, "ST_NEG"); + break; + default: + snprintf (text, 10, "%i", type); + break; + } + + return text; +} + +static void +dbg_sensorclock (struct st_cph *cph) +{ + if (cph != NULL) + { + DBG (DBG_FNC, " -> cph->p1 = %f\n", cph->p1); + DBG (DBG_FNC, " -> cph->p2 = %f\n", cph->p2); + DBG (DBG_FNC, " -> cph->ps = %i\n", cph->ps); + DBG (DBG_FNC, " -> cph->ge = %i\n", cph->ge); + DBG (DBG_FNC, " -> cph->go = %i\n", cph->go); + } + else + DBG (DBG_FNC, " -> cph is NULL\n"); +} + +static void +dbg_timing (struct st_timing *mt) +{ + if (mt != NULL) + { + DBG (DBG_FNC, " -> mt->cdss[0] = %i\n", _B0 (mt->cdss[0])); + DBG (DBG_FNC, " -> mt->cdsc[0] = %i\n", _B0 (mt->cdsc[0])); + DBG (DBG_FNC, " -> mt->cdss[1] = %i\n", _B0 (mt->cdss[1])); + DBG (DBG_FNC, " -> mt->cdsc[1] = %i\n", _B0 (mt->cdsc[1])); + DBG (DBG_FNC, " -> mt->cnpp = %i\n", _B0 (mt->cnpp)); + DBG (DBG_FNC, " -> mt->cvtrp0 = %i\n", _B0 (mt->cvtrp[0])); + DBG (DBG_FNC, " -> mt->cvtrp1 = %i\n", _B0 (mt->cvtrp[1])); + DBG (DBG_FNC, " -> mt->cvtrp2 = %i\n", _B0 (mt->cvtrp[2])); + DBG (DBG_FNC, " -> mt->cvtrfpw = %i\n", _B0 (mt->cvtrfpw)); + DBG (DBG_FNC, " -> mt->cvtrbpw = %i\n", _B0 (mt->cvtrbpw)); + DBG (DBG_FNC, " -> mt->cvtrw = %i\n", _B0 (mt->cvtrw)); + DBG (DBG_FNC, " -> mt->clamps = 0x%08x\n", mt->clamps); + DBG (DBG_FNC, " -> mt->clampe = 0x%08x\n", mt->clampe); + DBG (DBG_FNC, " -> mt->adcclkp0 = %f\n", mt->adcclkp[0]); + DBG (DBG_FNC, " -> mt->adcclkp1 = %f\n", mt->adcclkp[1]); + DBG (DBG_FNC, " -> mt->adcclkp2e = %i\n", mt->adcclkp2e); + DBG (DBG_FNC, " -> mt->cphbp2s = %i\n", mt->cphbp2s); + DBG (DBG_FNC, " -> mt->cphbp2e = %i\n", mt->cphbp2e); + } + else + DBG (DBG_FNC, " -> mt is NULL\n"); +} + +static void +dbg_sensor (struct st_sensorcfg *sensor) +{ + if (sensor != NULL) + { + DBG (DBG_FNC, + " -> type, name, res , {chn_color }, {chn_gray}, {rgb_order }, line_dist, evnodd_dist\n"); + DBG (DBG_FNC, + " -> ----, ----, --- , {--, --, --}, {--, -- }, {--, --, --}, ---------, -----------\n"); + DBG (DBG_FNC, + " -> %4i, %4i, %4i, {%2i, %2i, %2i}, {%2i, %2i }, {%2i, %2i, %2i}, %9i, %11i\n", + sensor->type, sensor->name, sensor->resolution, + sensor->channel_color[0], sensor->channel_color[1], + sensor->channel_color[2], sensor->channel_gray[0], + sensor->channel_gray[1], sensor->rgb_order[0], + sensor->rgb_order[1], sensor->rgb_order[2], sensor->line_distance, + sensor->evenodd_distance); + } + else + DBG (DBG_FNC, " -> sensor is NULL\n"); +} + +static void +dbg_buttons (struct st_buttons *buttons) +{ + if (buttons != NULL) + { + DBG (DBG_FNC, " -> count, btn1, btn2, btn3, btn4, btn5, btn6\n"); + DBG (DBG_FNC, " -> -----, ----, ----, ----, ----, ----, ----\n"); + DBG (DBG_FNC, " -> %5i, %4i, %4i, %4i, %4i, %4i, %4i\n", + buttons->count, buttons->mask[0], buttons->mask[1], + buttons->mask[2], buttons->mask[3], buttons->mask[4], + buttons->mask[5]); + } + else + DBG (DBG_FNC, " -> buttons is NULL\n"); +} + +static void +dbg_scanmodes (struct st_device *dev) +{ + if (dev->scanmodes_count > 0) + { + SANE_Int a; + struct st_scanmode *reg; + char sdebug[20], scm[20]; + + DBG (DBG_FNC, + " -> ##, ST , CM , RES , TM, CV, SR, CLK, CTPC , BKS , STT, DML, { Exposure times }, { Max exposure times }, MP , MExp16, MExpF, MExp, MRI, MSI, MMTIR, MMTIRH, SK\n"); + DBG (DBG_FNC, + " -> --, ---------, ----------, --- , --, --, --, ---, ------, ----, ---, ---, {------ ------ ------}, {------ ------ ------}, ---, ------, -----, ----, ---, ---, -----, ------, --\n"); + for (a = 0; a < dev->scanmodes_count; a++) + { + reg = dev->scanmodes[a]; + if (reg != NULL) + { + DBG (DBG_FNC, + " -> %2i, %9s, %10s, %4i, %2i, %2i, %2i, %3i, %6i, %4i, %3i, %3i, {%6i, %6i, %6i}, {%6i, %6i, %6i}, %3i, %6i, %5i, %4i, %3i, %3i, %5i, %6i, %2i\n", + a, dbg_scantype (sdebug, reg->scantype), dbg_colour (scm, + reg-> + colormode), + reg->resolution, reg->timing, reg->motorcurve, + reg->samplerate, reg->systemclock, reg->ctpc, + reg->motorbackstep, reg->scanmotorsteptype, reg->dummyline, + reg->expt[0], reg->expt[1], reg->expt[2], reg->mexpt[0], + reg->mexpt[1], reg->mexpt[2], reg->motorplus, + reg->multiexposurefor16bitmode, + reg->multiexposureforfullspeed, reg->multiexposure, + reg->mri, reg->msi, reg->mmtir, reg->mmtirh, + reg->skiplinecount); + } + } + } +} + +static void +dbg_motorcurves (struct st_device *dev) +{ + if (dev->mtrsetting != NULL) + { + struct st_motorcurve *mtc; + SANE_Int a = 0; + + while (a < dev->mtrsetting_count) + { + DBG (DBG_FNC, " -> Motorcurve %2i: ", a); + mtc = dev->mtrsetting[a]; + if (mtc != NULL) + { + DBG (DBG_FNC, "mri=%i msi=%i skip=%i bckstp=%i\n", mtc->mri, + mtc->msi, mtc->skiplinecount, mtc->motorbackstep); + if (mtc->curve_count > 0) + { + char *sdata = (char *) malloc (256); + if (sdata != NULL) + { + char *sline = (char *) malloc (256); + if (sline != NULL) + { + SANE_Int count; + struct st_curve *crv; + + DBG (DBG_FNC, + " -> ##, dir, type , count, from, to , steps\n"); + DBG (DBG_FNC, + " -> --, ---, ----------, -----, ----, ----, -----\n"); + + count = 0; + while (count < mtc->curve_count) + { + memset (sline, 0, 256); + + snprintf (sdata, 256, " -> %02i, ", count); + strcat (sline, sdata); + + crv = mtc->curve[count]; + if (crv != NULL) + { + if (crv->crv_speed == ACC_CURVE) + strcat (sline, "ACC, "); + else + strcat (sline, "DEC, "); + + switch (crv->crv_type) + { + case CRV_NORMALSCAN: + strcat (sline, "NORMALSCAN, "); + break; + case CRV_PARKHOME: + strcat (sline, "PARKHOME , "); + break; + case CRV_SMEARING: + strcat (sline, "SMEARING , "); + break; + case CRV_BUFFERFULL: + strcat (sline, "BUFFERFULL, "); + break; + default: + snprintf (sdata, 256, "unknown %2i, ", + crv->crv_type); + strcat (sline, sdata); + break; + } + + snprintf (sdata, 256, "%5i, ", + crv->step_count); + strcat (sline, sdata); + if (crv->step_count > 0) + { + SANE_Int stpcount = 0; + + snprintf (sdata, 256, "%4i, %4i| ", + crv->step[0], + crv->step[crv->step_count - + 1]); + strcat (sline, sdata); + + while (stpcount < crv->step_count) + { + if (stpcount == 10) + { + strcat (sline, "..."); + break; + } + if (stpcount > 0) + strcat (sline, ", "); + + snprintf (sdata, 256, "%4i", + crv->step[stpcount]); + strcat (sline, sdata); + + stpcount++; + } + strcat (sline, "\n"); + } + else + strcat (sline, "NONE\n"); + } + else + strcat (sline, "NULL ...\n"); + + DBG (DBG_FNC, "%s", sline); + + count++; + } + + free (sline); + } + free (sdata); + } + } + } + else + DBG (DBG_FNC, "NULL\n"); + a++; + } + } +} + +static void +dbg_motormoves (struct st_device *dev) +{ + if (dev->motormove_count > 0) + { + SANE_Int a; + struct st_motormove *reg; + + DBG (DBG_FNC, " -> ##, CLK, CTPC, STT, CV\n"); + DBG (DBG_FNC, " -> --, ---, ----, ---, --\n"); + for (a = 0; a < dev->motormove_count; a++) + { + reg = dev->motormove[a]; + if (reg != NULL) + { + DBG (DBG_FNC, " -> %2i, %3i, %4i, %3i, %2i\n", + a, reg->systemclock, reg->ctpc, + reg->scanmotorsteptype, reg->motorcurve); + } + } + } +} + +static void +dbg_hwdcfg (struct st_hwdconfig *params) +{ + if (params != NULL) + { + char sdebug[20]; + + DBG (DBG_FNC, " -> Low level config:\n"); + DBG (DBG_FNC, " -> startpos = %i\n", params->startpos); + DBG (DBG_FNC, " -> arrangeline = %s\n", + (params->arrangeline == + FIX_BY_SOFT) ? "FIX_BY_SOFT" : (params->arrangeline == + FIX_BY_HARD) ? "FIX_BY_HARD" : + "FIX_BY_NONE"); + DBG (DBG_FNC, " -> scantype = %s\n", + dbg_scantype (sdebug, params->scantype)); + DBG (DBG_FNC, " -> compression = %i\n", params->compression); + DBG (DBG_FNC, " -> use_gamma_tables = %i\n", + params->use_gamma_tables); + DBG (DBG_FNC, " -> gamma_tablesize = %i\n", + params->gamma_tablesize); + DBG (DBG_FNC, " -> white_shading = %i\n", + params->white_shading); + DBG (DBG_FNC, " -> black_shading = %i\n", + params->black_shading); + DBG (DBG_FNC, " -> unk3 = %i\n", params->unk3); + DBG (DBG_FNC, " -> motorplus = %i\n", params->motorplus); + DBG (DBG_FNC, " -> static_head = %i\n", params->static_head); + DBG (DBG_FNC, " -> motor_direction = %s\n", + (params->motor_direction == MTR_FORWARD) ? "FORWARD" : "BACKWARD"); + DBG (DBG_FNC, " -> dummy_scan = %i\n", params->dummy_scan); + DBG (DBG_FNC, " -> highresolution = %i\n", + params->highresolution); + DBG (DBG_FNC, " -> sensorevenodddistance = %i\n", + params->sensorevenodddistance); + DBG (DBG_FNC, " -> calibrate = %i\n", params->calibrate); + } +} + +static void +dbg_ScanParams (struct st_scanparams *params) +{ + if (params != NULL) + { + char scm[20], ssc[20]; + + DBG (DBG_FNC, " -> Scan params:\n"); + DBG (DBG_FNC, " -> colormode = %s\n", + dbg_colour (scm, params->colormode)); + DBG (DBG_FNC, " -> depth = %i\n", params->depth); + DBG (DBG_FNC, " -> samplerate = %i\n", params->samplerate); + DBG (DBG_FNC, " -> timing = %i\n", params->timing); + DBG (DBG_FNC, " -> channel = %i\n", params->channel); + DBG (DBG_FNC, " -> sensorresolution = %i\n", params->sensorresolution); + DBG (DBG_FNC, " -> resolution_x = %i\n", params->resolution_x); + DBG (DBG_FNC, " -> resolution_y = %i\n", params->resolution_y); + DBG (DBG_FNC, " -> left = %i\n", params->coord.left); + DBG (DBG_FNC, " -> width = %i\n", params->coord.width); + DBG (DBG_FNC, " -> top = %i\n", params->coord.top); + DBG (DBG_FNC, " -> height = %i\n", params->coord.height); + DBG (DBG_FNC, " -> shadinglength = %i\n", params->shadinglength); + DBG (DBG_FNC, " -> v157c = %i\n", params->v157c); + DBG (DBG_FNC, " -> bytesperline = %i\n", params->bytesperline); + DBG (DBG_FNC, " -> expt = %i\n", params->expt); + DBG (DBG_FNC, " *> startpos = %i\n", params->startpos); + DBG (DBG_FNC, " *> leftleading = %i\n", params->leftleading); + DBG (DBG_FNC, " *> ser = %i\n", params->ser); + DBG (DBG_FNC, " *> ler = %i\n", params->ler); + DBG (DBG_FNC, " *> scantype = %s\n", + dbg_scantype (ssc, params->scantype)); + } +} + +static void +dbg_calibtable (struct st_gain_offset *params) +{ + if (params != NULL) + { + DBG (DBG_FNC, " -> Calib table:\n"); + DBG (DBG_FNC, " -> edcg1 = %3i , %3i , %3i\n", params->edcg1[0], + params->edcg1[1], params->edcg1[2]); + DBG (DBG_FNC, " -> edcg2 = %3i , %3i , %3i\n", params->edcg2[0], + params->edcg2[1], params->edcg2[2]); + DBG (DBG_FNC, " -> odcg1 = %3i , %3i , %3i\n", params->odcg1[0], + params->odcg1[1], params->odcg1[2]); + DBG (DBG_FNC, " -> odcg2 = %3i , %3i , %3i\n", params->odcg2[0], + params->odcg2[1], params->odcg2[2]); + DBG (DBG_FNC, " -> pag = %3i , %3i , %3i\n", params->pag[0], + params->pag[1], params->pag[2]); + DBG (DBG_FNC, " -> vgag1 = %3i , %3i , %3i\n", params->vgag1[0], + params->vgag1[1], params->vgag1[2]); + DBG (DBG_FNC, " -> vgag2 = %3i , %3i , %3i\n", params->vgag2[0], + params->vgag2[1], params->vgag2[2]); + } +} + +static char * +dbg_colour (char *text, SANE_Int colour) +{ + if (text != NULL) + switch (colour) + { + case CM_COLOR: + strcpy (text, "CM_COLOR"); + break; + case CM_GRAY: + strcpy (text, "CM_GRAY"); + break; + case CM_LINEART: + strcpy (text, "CM_LINEART"); + break; + default: + snprintf (text, 20, "%i", colour); + break; + } + + return text; +} + +static void +dbg_motorcfg (struct st_motorcfg *motorcfg) +{ + if (motorcfg != NULL) + { + DBG (DBG_FNC, + " -> type, res , freq, speed, base, high, park, change\n"); + DBG (DBG_FNC, + " -> ----, --- , ----, -----, ----, ----, ----, ------\n"); + DBG (DBG_FNC, " -> %4i, %4i, %4i, %5i, %4i, %4i, %4i, %6i\n", + motorcfg->type, motorcfg->resolution, motorcfg->pwmfrequency, + motorcfg->basespeedpps, motorcfg->basespeedmotormove, + motorcfg->highspeedmotormove, motorcfg->parkhomemotormove, + motorcfg->changemotorcurrent); + } +} + +static void +dbg_tiff_save (char *sFile, SANE_Int width, SANE_Int height, SANE_Int depth, + SANE_Int colortype, SANE_Int res_x, SANE_Int res_y, + SANE_Byte * buffer, SANE_Int size) +{ + if (buffer != NULL) + { + char *path = getenv ("HOME"); + + if (path != NULL) + { + char filename[512]; + TIFF *image; + + if (snprintf (filename, 512, "%s/%s", path, sFile) > 0) + { + /* Open the TIFF file */ + if ((image = TIFFOpen (filename, "w")) != NULL) + { + char desc[256]; + + SANE_Int spp = (colortype == CM_GRAY) ? 1 : 3; + SANE_Int ct = + (colortype == + CM_GRAY) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB; + + snprintf (desc, 256, "Created with hp3900 %s", + BACKEND_VRSN); + + /* We need to set some values for basic tags before we can add any data */ + TIFFSetField (image, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField (image, TIFFTAG_IMAGELENGTH, height); + TIFFSetField (image, TIFFTAG_BITSPERSAMPLE, depth); + TIFFSetField (image, TIFFTAG_SAMPLESPERPIXEL, spp); + + TIFFSetField (image, TIFFTAG_PHOTOMETRIC, ct); + TIFFSetField (image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField (image, TIFFTAG_PLANARCONFIG, + PLANARCONFIG_CONTIG); + + TIFFSetField (image, TIFFTAG_XRESOLUTION, (double) res_x); + TIFFSetField (image, TIFFTAG_YRESOLUTION, (double) res_y); + TIFFSetField (image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + TIFFSetField (image, TIFFTAG_IMAGEDESCRIPTION, desc); + + /* Write the information to the file */ + TIFFWriteRawStrip (image, 0, buffer, size); + TIFFClose (image); + } + } + else + DBG (DBG_ERR, "- dbg_tiff_save: Error generating filename\n"); + } + else + DBG (DBG_ERR, + "- dbg_tiff_save: Enviroment HOME variable does not exist\n"); + } +} + +static void +dbg_autoref (struct st_scanparams *scancfg, SANE_Byte * pattern, + SANE_Int ser1, SANE_Int ser2, SANE_Int ler) +{ + /* this function generates post-autoref.tiff */ + SANE_Byte *img = + malloc (sizeof (SANE_Byte) * + (scancfg->coord.width * scancfg->coord.height * 3)); + + if (img != NULL) + { + SANE_Int c, value; + + /* generate image from 1 gray channel to 3 color channels */ + for (c = 0; c < (scancfg->coord.width * scancfg->coord.height); c++) + { + value = *(pattern + c); + *(img + (3 * c)) = value; + *(img + (3 * c) + 1) = value; + *(img + (3 * c) + 2) = value; + } + + for (c = 0; c < scancfg->coord.height; c++) + { + /* line for first SER */ + if (c < (ler + 5)) + { + *(img + (scancfg->coord.width * c * 3) + (3 * ser1)) = 0; + *(img + (scancfg->coord.width * c * 3) + (3 * ser1) + 1) = 255; + *(img + (scancfg->coord.width * c * 3) + (3 * ser1) + 2) = 0; + } + + /* line for second SER */ + if (c > (ler - 5)) + { + *(img + (scancfg->coord.width * c * 3) + (3 * ser2)) = 90; + *(img + (scancfg->coord.width * c * 3) + (3 * ser2) + 1) = 90; + *(img + (scancfg->coord.width * c * 3) + (3 * ser2) + 2) = 255; + } + + /* vertical lines of the pointer */ + if ((c > (ler - 5)) && (c < (ler + 5))) + { + if ((ser2 - 5) >= 0) + { + *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 - 5))) = + 255; + *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 - 5)) + + 1) = 255; + *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 - 5)) + + 2) = 0; + } + + if ((ser2 + 5) < scancfg->coord.width) + { + *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 + 5))) = + 255; + *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 + 5)) + + 1) = 255; + *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 + 5)) + + 2) = 0; + } + } + } + + /* line for first LER */ + for (c = 0; c < scancfg->coord.width; c++) + { + if ((c > (ser1 - 5)) && (c < (ser2 + 5))) + { + if (c != (ser2 - 5)) + { + *(img + (scancfg->coord.width * ler * 3) + (3 * c)) = 255; + *(img + (scancfg->coord.width * ler * 3) + (3 * c) + 1) = + 90; + *(img + (scancfg->coord.width * ler * 3) + (3 * c) + 2) = + 90; + } + + /* horizontal lines of the pointer */ + if ((c > (ser2 - 5)) && (c < (ser2 + 5))) + { + if ((ler - 5) >= 0) + { + *(img + (scancfg->coord.width * (ler - 5) * 3) + + (3 * c)) = 255; + *(img + (scancfg->coord.width * (ler - 5) * 3) + + (3 * c) + 1) = 255; + *(img + (scancfg->coord.width * (ler - 5) * 3) + + (3 * c) + 2) = 0; + } + + if ((ler + 5) < scancfg->coord.height) + { + *(img + (scancfg->coord.width * (ler + 5) * 3) + + (3 * c)) = 255; + *(img + (scancfg->coord.width * (ler + 5) * 3) + + (3 * c) + 1) = 255; + *(img + (scancfg->coord.width * (ler + 5) * 3) + + (3 * c) + 2) = 0; + } + } + } + } + + dbg_tiff_save ("post-autoref.tiff", scancfg->coord.width, + scancfg->coord.height, 8, CM_COLOR, + scancfg->resolution_x, scancfg->resolution_y, img, + scancfg->coord.height * scancfg->coord.width * 3); + + /* free generated image */ + free (img); + } +} + +#ifdef developing +static void +dbg_buffer (SANE_Int level, char *title, SANE_Byte * buffer, SANE_Int size, + SANE_Int start) +{ + if (level <= DBG_LEVEL) + { + DBG (level, "%s ", title); + if ((size > 0) && (buffer != NULL)) + { + SANE_Int cont, data, offset = 0; + SANE_Int col = 0; + char text[9]; + char *sline = NULL; + char *sdata = NULL; + + sline = (char *) malloc (81); + if (sline != NULL) + { + sdata = (char *) malloc (81); + if (sdata != NULL) + { + for (cont = 0; cont < size; cont++) + { + if (col == 0) + { + if (cont == 0) + snprintf (sline, 80, " BF: "); + else + snprintf (sline, 80, " "); + bzero (&text, sizeof (text)); + } + data = _B0 (buffer[cont]); + text[col] = (data > 31) ? data : '·'; + snprintf (sdata, 80, "%02x ", data); + sline = strcat (sline, sdata); + col++; + offset++; + if (col == 8) + { + col = 0; + snprintf (sdata, 80, " : %s : 0x%04x\n", text, + start + offset - 8); + sline = strcat (sline, sdata); + DBG (level, "%s", sline); + bzero (sline, 81); + } + } + if (col > 0) + { + for (cont = col; cont < 8; cont++) + { + snprintf (sdata, 80, "-- "); + sline = strcat (sline, sdata); + offset++; + } + snprintf (sdata, 80, " : %s : 0x%04x\n", text, + start + offset - 8); + sline = strcat (sline, sdata); + DBG (level, "%s", sline); + bzero (sline, 81); + } + free (sdata); + } + free (sline); + } + } + else + DBG (level, " BF: Empty buffer\n"); + } +} + +static void +dbg_registers (SANE_Byte * buffer) +{ + /* buffer size must be RT_BUFFER_LEN bytes */ + /*SANE_Int iValue, iValue2; + double dValue; + + DBG(DBG_FNC, "\n----------------------------------------------------\n"); + DBG(DBG_FNC, """RTS8822 Control Registers Info""\nAddress Info\n------- ----\n"); + iValue = data_lsb_get(&buffer[0x000], 1); + DBG(DBG_FNC, "\n0x0000"); + DBG(DBG_FNC, " bit[0..3] = systemclock: 0x%02x\n", iValue & 0x0f); + DBG(DBG_FNC, " bit[4] = 0x%02x : MLOCK\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[5] = 0x%02x : Bit to reset scanner\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[6] = 0x%02x : ?\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = 0x%02x : RTS_IsExecuting\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x001], 1); + DBG(DBG_FNC, "0x0001 bit[0] = 0x%02x : ?\n", iValue & 1); + DBG(DBG_FNC, " bit[1] = 0x%02x : (is 1 if has motorcurves)\n", (iValue >> 1) & 1); + DBG(DBG_FNC, " bit[2] = 0x%02x : ?\n", (iValue >> 2) & 1); + DBG(DBG_FNC, " bit[3] = 0x%02x : ?\n", (iValue >> 3) & 1); + DBG(DBG_FNC, " bit[4] = 0x%02x : dummy scan\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[5..7] = 0x%02x : ?\n", (iValue >> 5) & 7); + + dbg_buffer(DBG_FNC, "\n0x0002", &buffer[0x002], 0x0e, 0x02); + + iValue = data_lsb_get(&buffer[0x010], 1); + DBG(DBG_FNC, "\n0x0010 bit[0..4] = 0x%02x : cvrs\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5] = 0x%02x : Enable CCD\n", ((iValue >> 5) & 1)); + DBG(DBG_FNC, " bit[6] = 0x%02x : Enable CCD channel 1\n", ((iValue >> 6) & 1)); + DBG(DBG_FNC, " bit[7] = 0x%02x : Enable CCD channel 2\n", ((iValue >> 7) & 1)); + + iValue = data_lsb_get(&buffer[0x011], 1); + DBG(DBG_FNC, "\n0x0011 bit[0..6] = ?: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[7] = 0x%02x : sensor type (CCD=0|CIS=1)\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x012], 1); + DBG(DBG_FNC, "0x0012 bit[0..5] = 0x%02x [0x%02x,0x%02x,0x%02x] rgb channel order\n", (iValue & 0x3f), (iValue >> 4) & 3, (iValue >> 2) & 3, iValue & 3); + DBG(DBG_FNC, " bit[6..7] = channels_per_dot : 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x013], 1); + DBG(DBG_FNC, "\n0x0013"); + DBG(DBG_FNC, " bit[0..1] = Pre-Amplifier Gain[RED] : 0x%02x\n", iValue & 3); + DBG(DBG_FNC, " bit[2..3] = Pre-Amplifier Gain[GREEN] : 0x%02x\n", (iValue >> 2) & 3); + DBG(DBG_FNC, " bit[4..5] = Pre-Amplifier Gain[BLUE] : 0x%02x\n", (iValue >> 4) & 3); + DBG(DBG_FNC, " bit[6] = ? : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = Enable CCD channel 3: : 0x%02x\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x014], 1); + DBG(DBG_FNC, "\n0x0014"); + DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 1 [RED] : 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = Top Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x015], 1); + DBG(DBG_FNC, "0x0015"); + DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 1 [GREEN] : 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = Middle Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x016], 1); + DBG(DBG_FNC, "0x0016"); + DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 1 [BLUE] : 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = Bottom Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x017], 1); + DBG(DBG_FNC, "0x0017"); + DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 2 [RED] : 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = Top Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x018], 1); + DBG(DBG_FNC, "0x0018"); + DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 2 [GREEN] : 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = Middle Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x019], 1); + DBG(DBG_FNC, "0x0019"); + DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 2 [BLUE] : 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = Bottom Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x01a], 1); + iValue2 = data_lsb_get(&buffer[0x01b], 1); + DBG(DBG_FNC, "\n0x001a-0x001b\n"); + DBG(DBG_FNC, " Red Even offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); + DBG(DBG_FNC, " Red Even offset 2: 0x%02x\n", iValue2 & 0x3f); + + iValue = data_lsb_get(&buffer[0x01c], 1); + iValue2 = data_lsb_get(&buffer[0x01d], 1); + DBG(DBG_FNC, "0x001c-0x001d\n"); + DBG(DBG_FNC, " Red Odd offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); + DBG(DBG_FNC, " Red Odd offset 2: 0x%02x\n", iValue2 & 0x3f); + + iValue = data_lsb_get(&buffer[0x01e], 1); + iValue2 = data_lsb_get(&buffer[0x01f], 1); + DBG(DBG_FNC, "0x001e-0x001f\n"); + DBG(DBG_FNC, " Green Even offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); + DBG(DBG_FNC, " Green Even offset 2: 0x%02x\n", iValue2 & 0x3f); + + iValue = data_lsb_get(&buffer[0x020], 1); + iValue2 = data_lsb_get(&buffer[0x021], 1); + DBG(DBG_FNC, "0x0020-0x0021\n"); + DBG(DBG_FNC, " Green Odd offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); + DBG(DBG_FNC, " Green Odd offset 2: 0x%02x\n", iValue2 & 0x3f); + + iValue = data_lsb_get(&buffer[0x022], 1); + iValue2 = data_lsb_get(&buffer[0x023], 1); + DBG(DBG_FNC, "0x0022-0x0023\n"); + DBG(DBG_FNC, " Blue Even offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); + DBG(DBG_FNC, " Blue Even offset 2: 0x%02x\n", iValue2 & 0x3f); + + iValue = data_lsb_get(&buffer[0x024], 1); + iValue2 = data_lsb_get(&buffer[0x025], 1); + DBG(DBG_FNC, "0x0024-0x0025\n"); + DBG(DBG_FNC, " Blue Odd offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); + DBG(DBG_FNC, " Blue Odd offset 2: 0x%02x\n", iValue2 & 0x3f); + + dbg_buffer(DBG_FNC, "\n0x0026", &buffer[0x026], 0x03, 0x26); + + iValue = data_lsb_get(&buffer[0x029], 1); + DBG(DBG_FNC, "\n0x0029"); + DBG(DBG_FNC, " First connection to scanner? : 0x%02x\n", iValue); + + dbg_buffer(DBG_FNC, "\n0x002a", &buffer[0x02a], 0x06, 0x2a); + + DBG(DBG_FNC, "\nExposure times:\n"); + iValue = data_lsb_get(&buffer[0x030], 3); + DBG(DBG_FNC, "0x0030 Line exposure time : %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x033], 3); + DBG(DBG_FNC, "\n0x0033 mexpts[RED] : %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x036], 3); + DBG(DBG_FNC, "0x0036 expts[RED] : %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x039], 3); + DBG(DBG_FNC, "0x0039 mexpts[GREEN]: %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x03c], 3); + DBG(DBG_FNC, "0x003c expts[GREEN]: %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x03f], 3); + DBG(DBG_FNC, "0x003f mexpts[BLUE] : %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x042], 3); + DBG(DBG_FNC, "0x0042 expts[BLUE] : %i us\n", iValue); + + iValue = data_lsb_get(&buffer[0x045], 1); + DBG(DBG_FNC, "\n0x0045 bit[0..4] = timing.cvtrfpw: 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5] = timing.cvtrp[2]: 0x%02x\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[6] = timing.cvtrp[1]: 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = timing.cvtrp[0]: 0x%02x\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x046], 1); + DBG(DBG_FNC, "0x0046"); + DBG(DBG_FNC, " bit[0..4] = timing.cvtrbpw: 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 3); + + iValue = data_lsb_get(&buffer[0x047], 1); + DBG(DBG_FNC, "0x0047"); + DBG(DBG_FNC, " timing.cvtrw: 0x%02x\n", iValue); + + iValue = data_lsb_get(&buffer[0x04c], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x04a], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x048], 0x02); + DBG(DBG_FNC, "\n0x0048 Linear image sensor clock 1\n"); + DBG(DBG_FNC, " bit[0..35] = timing.cph0p1: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x04c], 0x01); + DBG(DBG_FNC, " bit[36] = timing.cph0go: 0x%02x\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[37] = timing.cph0ge: 0x%02x\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[38] = timing.cph0ps: 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x051], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x04f], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x04d], 0x02); + DBG(DBG_FNC, "0x004d"); + DBG(DBG_FNC, " bit[0..35] = timing.cph0p2: %.0f.\n", dValue); + + iValue = data_lsb_get(&buffer[0x056], 1) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x054], 2); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x052], 2); + DBG(DBG_FNC, "\n0x0052 Linear image sensor clock 2\n"); + DBG(DBG_FNC, " bit[0..35] = timing.cph1p1: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x056], 1); + DBG(DBG_FNC, " bit[36] = timing.cph1go: 0x%02x\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[37] = timing.cph1ge: 0x%02x\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[38] = timing.cph1ps: 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 7) & 1); + + + iValue = data_lsb_get(&buffer[0x05b], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x059], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x057], 0x02); + DBG(DBG_FNC, "0x0057"); + DBG(DBG_FNC, " bit[0..35] = timing.cph1p2: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x05b], 0x01); + DBG(DBG_FNC, " bits[36..39] = %02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: %02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: %02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: %02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: %02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x060], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x05e], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x05c], 0x02); + DBG(DBG_FNC, "\n0x005c Linear Image Sensor Clock 3\n"); + DBG(DBG_FNC, " bit[0..35] = timing.cph2p1: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x060], 0x01); + DBG(DBG_FNC, " bit[36] = timing.cph2go: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = timing.cph2ge: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = timing.cph2ps: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x065], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x063], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x061], 0x02); + DBG(DBG_FNC, "0x0061"); + DBG(DBG_FNC, " bit[0..35] = timing.cph2p2: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x065], 0x01); + DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x06a], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x068], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x066], 0x02); + DBG(DBG_FNC, "\n0x0066 Linear Image Sensor Clock 4\n"); + DBG(DBG_FNC, " bit[0..35] = timing.cph3p1: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x06a], 0x01); + DBG(DBG_FNC, " bit[36] = timing.cph3go: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = timing.cph3ge: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = timing.cph3ps: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x06f], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x06d], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x06b], 0x02); + DBG(DBG_FNC, "0x006b"); + DBG(DBG_FNC, " bit[0..35] = timing.cph3p2: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x06f], 0x01); + DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x074], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x072], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x070], 0x02); + DBG(DBG_FNC, "\n0x0070 Linear Image Sensor Clock 5\n"); + DBG(DBG_FNC, " bit[0..35] = timing.cph4p1: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x074], 0x01); + DBG(DBG_FNC, " bit[36] = timing.cph4go: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = timing.cph4ge: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = timing.cph4ps: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x079], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x077], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x075], 0x02); + DBG(DBG_FNC, "0x0075"); + DBG(DBG_FNC, " bit[0..35] = timing.cph4p2: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x079], 0x01); + DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x07e], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x07c], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x07a], 0x02); + DBG(DBG_FNC, "\n0x007a Linear Image Sensor Clock 6\n"); + DBG(DBG_FNC, " bit[0..35] = timing.cph5p1: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x07e], 0x01); + DBG(DBG_FNC, " bit[36] = timing.cph5go: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = timing.cph5ge: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = timing.cph5ps: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x083], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x081], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x07f], 0x02); + DBG(DBG_FNC, "0x007f"); + DBG(DBG_FNC, " bit[0..35] = timing.cph5p2: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x083], 0x01); + DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + iValue = data_lsb_get(&buffer[0x084], 3); + DBG(DBG_FNC, "\n0x0084"); + DBG(DBG_FNC, " timing.cphbp2s : 0x%06x\n", iValue); + + iValue = data_lsb_get(&buffer[0x087], 3); + DBG(DBG_FNC, "0x0087"); + DBG(DBG_FNC, " timing.cphbp2e : 0x%06x\n", iValue); + + iValue = data_lsb_get(&buffer[0x08a], 3); + DBG(DBG_FNC, "0x008a"); + DBG(DBG_FNC, " timing.clamps : 0x%08x\n", iValue); + + iValue = data_lsb_get(&buffer[0x08d], 3); + DBG(DBG_FNC, "0x008d"); + DBG(DBG_FNC, " timing.clampe or cphbp2e : 0x%08x\n", iValue); + + iValue = data_lsb_get(&buffer[0x092], 0x01); + DBG(DBG_FNC, "\n0x0092 Correlated-Double-Sample 1\n"); + DBG(DBG_FNC, " bit[0..5] = timing.cdss[0]: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x093], 0x01); + DBG(DBG_FNC, "0x0093"); + DBG(DBG_FNC, " bit[0..5] = timing.cdsc[0]: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x094], 0x01); + DBG(DBG_FNC, "\n0x0094 Correlated-Double-Sample 2\n"); + DBG(DBG_FNC, " bit[0..5] = timing.cdss[1]: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x095], 0x01); + DBG(DBG_FNC, "0x0095"); + DBG(DBG_FNC, " bit[0..5] = timing.cdsc[1]: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x096], 0x01); + DBG(DBG_FNC, "0x0096"); + DBG(DBG_FNC, " bit[0..5] = timing.cnpp: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x09b], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x099], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x097], 0x02); + DBG(DBG_FNC, "\n0x0097 Analog to Digital Converter clock 1\n"); + DBG(DBG_FNC, " bit[0..35] = timing.adcclkp[0]: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x09b], 0x01); + DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + dbg_buffer(DBG_FNC, "\n0x009c CIS sensor 1", &buffer[0x09c], 0x06, 0x9c); + dbg_buffer(DBG_FNC, "0x00a2 CIS sensor 2", &buffer[0x0a2], 0x06, 0xa2); + dbg_buffer(DBG_FNC, "0x00a8 CIS sensor 3", &buffer[0x0a8], 0x06, 0xa8); + + iValue = data_lsb_get(&buffer[0x0ae], 0x01); + DBG(DBG_FNC, "\n0x00ae"); + DBG(DBG_FNC, " bit[0..5] = ?: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x0af], 0x01); + DBG(DBG_FNC, "0x00af"); + DBG(DBG_FNC, " bit[0..2] = ?: 0x%02x\n", iValue & 7); + DBG(DBG_FNC, " bit[3..7] = ?: 0x%02x\n", (iValue >> 3) & 0x1f); + + iValue = data_lsb_get(&buffer[0x0b0], 2); + DBG(DBG_FNC, "\n0x00b0"); + DBG(DBG_FNC, " Left : 0x%04x\n", iValue); + + iValue = data_lsb_get(&buffer[0x0b2], 2); + DBG(DBG_FNC, "0x00b2"); + DBG(DBG_FNC, " Right: 0x%04x\n", iValue); + + dbg_buffer(DBG_FNC, "\n0x00b4", &buffer[0x0b4], 12, 0xb4); + + iValue = data_lsb_get(&buffer[0x0c0], 0x01); + DBG(DBG_FNC, "\n0x00c0"); + DBG(DBG_FNC, " bit[0..4] = resolution ratio: 0x%02x\n", iValue & 0x1f); + DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 7); + + iValue = data_lsb_get(&buffer[0x0c5], 0x01) & 0x0f; + dValue = iValue * pow(2, 32); + iValue = data_lsb_get(&buffer[0x0c3], 0x02); + dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x0c1], 2); + DBG(DBG_FNC, "\n0x00c1 Analog to Digital Converter clock 2\n"); + DBG(DBG_FNC, " bit[0..35] = timing.adcclkp[1]: %.0f.\n", dValue); + iValue = data_lsb_get(&buffer[0x0c5], 0x01); + DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); + DBG(DBG_FNC, " bit[36] = ?: 0x%02x (equal to bit[32])\n", (iValue >> 0x04) & 0x01); + DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); + DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); + DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); + + dbg_buffer(DBG_FNC, "\n0x00c6", &buffer[0x0c6], 0x0a, 0xc6); + + iValue = ((buffer[0x0d4] & 0x0f) << 0x10) + data_lsb_get(&buffer[0x0d0], 0x02); + DBG(DBG_FNC, "\n0x00d0"); + DBG(DBG_FNC, " Top : 0x%04x\n", iValue); + + iValue = ((buffer[0x0d4] & 0xf0) << 0x06)+ data_lsb_get(&buffer[0x0d2], 0x02); + DBG(DBG_FNC, "x00d2"); + DBG(DBG_FNC, " Down: 0x%04x\n", iValue); + + iValue = _B0(buffer[0x0d5]); + DBG(DBG_FNC, "0x00d5"); + DBG(DBG_FNC, " ?: 0x%04x\n", iValue); + + iValue = data_lsb_get(&buffer[0x0d6], 1); + DBG(DBG_FNC, "\n0x00d6"); + DBG(DBG_FNC, " bit[0..3] = ? : 0x%02x\n", iValue & 0xf); + DBG(DBG_FNC, " bit[4..7] = dummyline: 0x%02x\n", (iValue >> 4) & 0xf); + + iValue = data_lsb_get(&buffer[0x0d7], 0x01); + DBG(DBG_FNC, "\n0x00d7"); + DBG(DBG_FNC, " bit[0..5] = motor pwm frequency: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6] = ?: 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = motor type: 0x%02x ", (iValue >> 7) & 1); + if (((iValue >> 7) & 1) == MT_OUTPUTSTATE) + DBG(DBG_FNC, ": Output state machine\n"); + else DBG(DBG_FNC, "On-Chip PWM\n"); + + iValue = data_lsb_get(&buffer[0x0d8], 0x01); + DBG(DBG_FNC, "\n0x00d8"); + DBG(DBG_FNC, " bit[0..5] = ?: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6] = scantype (0=Normal|1=TMA) : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = enable head movement : 0x%02x :", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x0d9], 0x01); + DBG(DBG_FNC, "\n0x00d9"); + DBG(DBG_FNC, " bit[0..2] = ?: 0x%02x\n", iValue & 7); + DBG(DBG_FNC, " bit[3] = ?: 0x%02x\n", (iValue >> 3) & 1); + DBG(DBG_FNC, " bit[4..6] = motor step type: 0x%02x: ", (iValue >> 4) & 7); + switch((iValue >> 4) & 7) + { + case 0: DBG(DBG_FNC, "full (1)\n"); break; + case 1: DBG(DBG_FNC, "half (1/2)\n"); break; + case 2: DBG(DBG_FNC, "quart (1/4)\n"); break; + case 3: DBG(DBG_FNC, "(1/8)\n"); break; + default: DBG(DBG_FNC, "unknown\n"); break; + } + DBG(DBG_FNC, " bit[7] = Motor direction: 0x%02x = ", (iValue >> 7) & 1); + if (((iValue >> 7) & 1) == 0) + DBG(DBG_FNC, "Backward\n"); + else DBG(DBG_FNC, "Forward\n"); + + iValue = data_lsb_get(&buffer[0x0dd], 0x01); + DBG(DBG_FNC, "\n0x00da"); + DBG(DBG_FNC, " msi = 0x%03x\n", ((iValue & 3) << 8) + data_lsb_get(&buffer[0x0da], 1)); + + DBG(DBG_FNC, "0x00db"); + DBG(DBG_FNC, " motorbackstep1 = 0x%03x\n", ((iValue & 0x0c) << 6) + data_lsb_get(&buffer[0x0db], 1)); + + DBG(DBG_FNC, "0x00dc"); + DBG(DBG_FNC, " motorbackstep2 = 0x%03x\n", ((iValue & 0x30) << 4) + data_lsb_get(&buffer[0x0dc], 1)); + + iValue = data_lsb_get(&buffer[0x0dd], 0x01); + DBG(DBG_FNC, "0x00dd"); + DBG(DBG_FNC, " bit[7] = Motor enabled?: 0x%02x = ", (iValue >> 7) & 1); + if (((iValue >> 7) & 1) == 0) + DBG(DBG_FNC, "Yes\n"); + else DBG(DBG_FNC, "No\n"); + + iValue = data_lsb_get(&buffer[0x0de], 0x02); + DBG(DBG_FNC, "\n0x00de"); + DBG(DBG_FNC, " bit[00..11] = ?: 0x%02x\n", iValue & 0xfff); + DBG(DBG_FNC, " bit[12..15] = ?: 0x%02x\n", (iValue >> 12) & 0x0f); + + iValue = data_lsb_get(&buffer[0x0df], 0x01); + DBG(DBG_FNC, "\n0x00df"); + DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0x0f); + DBG(DBG_FNC, " bit[4] = has_motorcurves?: 0x%02x\n", (iValue >> 4) & 0x01); + DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 7); + + iValue = data_lsb_get(&buffer[0x0e0], 1); + DBG(DBG_FNC, "\n0x00e0 step size - 1 : 0x%02x\n", iValue); + + iValue = data_lsb_get(&buffer[0x0e1], 3); + DBG(DBG_FNC, "\n0x00e1 0x%06x : last step of accurve.normalscan table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0e4], 3); + DBG(DBG_FNC, "0x00e4 0x%06x : last step of accurve.smearing table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0e7], 3); + DBG(DBG_FNC, "0x00e7 0x%06x : last step of accurve.parkhome table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0ea], 3); + DBG(DBG_FNC, "0x00ea 0x%06x : last step of deccurve.scanbufferfull table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0ed], 3); + DBG(DBG_FNC, "0x00ed 0x%06x : last step of deccurve.normalscan table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0f0], 3); + DBG(DBG_FNC, "0x00f0 0x%06x : last step of deccurve.smearing table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0f3], 3); + DBG(DBG_FNC, "0x00f3 0x%06x : last step of deccurve.parkhome table\n", iValue); + + iValue = data_lsb_get(&buffer[0x0f6], 2); + DBG(DBG_FNC, "\n0x00f6 bit[00..13] = 0x%04x : ptr to accurve.normalscan step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x0f8], 2); + DBG(DBG_FNC, "0x00f8"); + DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.scanbufferfull step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x0fa], 2); + DBG(DBG_FNC, "0x00fa"); + DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to accurve.smearing step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x0fc], 2); + DBG(DBG_FNC, "0x00fc"); + DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.smearing step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x0fe], 2); + DBG(DBG_FNC, "0x00fe"); + DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.normalscan step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x100], 2); + DBG(DBG_FNC, "0x0100"); + DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to accurve.parkhome step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x102], 2); + DBG(DBG_FNC, "0x0102"); + DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.parkhome step table\n", iValue & 0x3fff); + DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); + + dbg_buffer(DBG_FNC, "\n0x0104 Motor resource", &buffer[0x104], 0x20, 0x104); + + dbg_buffer(DBG_FNC, "\n0x0124", &buffer[0x124], 0x22, 0x124); + + iValue = data_lsb_get(&buffer[0x146], 1); + DBG(DBG_FNC, "\n0x0146"); + DBG(DBG_FNC, " bit[0..3] = Lamp pulse-width modulation frequency : 0x%02x\n", iValue & 0xf); + DBG(DBG_FNC, " bit[4] = timer enabled? : 0x%02x\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[5] = ? : 0x%02x\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[6] = lamp turned on? : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = sensor type : 0x%02x ", (iValue >> 7) & 1); + if (((iValue >> 7) & 1) != 0) + DBG(DBG_FNC, "CCD\n"); + else DBG(DBG_FNC, "CIS\n"); + + iValue = data_lsb_get(&buffer[0x147], 1); + DBG(DBG_FNC, "\n0x0147"); + DBG(DBG_FNC, " time to turn off lamp = 0x%02x (minutes * 2.682163611980331)\n", iValue); + + iValue = data_lsb_get(&buffer[0x148], 1); + DBG(DBG_FNC, "\n0x0148"); + DBG(DBG_FNC, " bit[0..5] = Lamp pulse-width modulation duty cycle : 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ? : 0x%02x\n",(iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x149], 1); + DBG(DBG_FNC, "\n0x0149"); + DBG(DBG_FNC, " bit[0..5] = even_odd_distance : 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ? : 0x%02x\n",(iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x14a], 1); + DBG(DBG_FNC, "0x014a"); + DBG(DBG_FNC, " bit[0..5] = sensor line distance : 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n",(iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x14b], 1); + DBG(DBG_FNC, "0x014b"); + DBG(DBG_FNC, " bit[0..5] = sensor line distance + even_odd_distance: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n",(iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x14c], 1); + DBG(DBG_FNC, "0x014c"); + DBG(DBG_FNC, " bit[0..5] = sensor line distance * 2: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x14d], 1); + DBG(DBG_FNC, "0x014d"); + DBG(DBG_FNC, " bit[0..5] = (sensor line distance * 2) + even_odd_distance: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); + + iValue = data_lsb_get(&buffer[0x14e], 1); + DBG(DBG_FNC, "\n0x014e"); + DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0xf); + DBG(DBG_FNC, " bit[4] = ?: 0x%02x\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 7); + + dbg_buffer(DBG_FNC, "\n0x014f", &buffer[0x14f], 0x05, 0x14f); + + iValue = data_lsb_get(&buffer[0x154], 1); + DBG(DBG_FNC, "\n0x0154"); + DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0xf); + DBG(DBG_FNC, " bit[4..5] = ?: 0x%02x\n", (iValue >> 4) & 3); + DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 7); + + iValue = data_lsb_get(&buffer[0x155], 1); + DBG(DBG_FNC, "\n0x0155"); + DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0x0f); + DBG(DBG_FNC, " bit[4] = 0x%02x : ", (iValue >> 4) & 1); + if (((iValue >> 4) & 1) == 0) + DBG(DBG_FNC, "flb lamp\n"); + else DBG(DBG_FNC, "tma lamp\n"); + DBG(DBG_FNC, " bit[5..7] = ? : 0x%02x\n", (iValue >> 5) & 7); + + dbg_buffer(DBG_FNC, "\n0x0156", &buffer[0x156], 0x02, 0x156); + + iValue = data_lsb_get(&buffer[0x158], 1); + DBG(DBG_FNC, "\n0x0158"); + DBG(DBG_FNC, " bit[0..3] = %02x : Scanner buttons ", iValue & 0x0f); + if ((iValue & 0x0f) == 0x0f) + DBG(DBG_FNC, "enabled\n"); + else DBG(DBG_FNC, "dissabled\n"); + DBG(DBG_FNC, " bit[4..7] = ? : 0x%02x\n", (iValue >> 4) & 0x0f); + + dbg_buffer(DBG_FNC, "\n0x0159", &buffer[0x159], 11, 0x159); + + iValue = data_lsb_get(&buffer[0x164], 1); + DBG(DBG_FNC, "\n0x0164"); + DBG(DBG_FNC, " bit[0..6] = ?: 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); + + dbg_buffer(DBG_FNC, "\n0x0165", &buffer[0x165], 3, 0x165); + + iValue = data_lsb_get(&buffer[0x168], 1); + DBG(DBG_FNC, "\n0x0168 Buttons status : 0x%02x\n", iValue); + DBG(DBG_FNC, " bit[0] = button 1 : 0x%02x\n", iValue & 1); + DBG(DBG_FNC, " bit[1] = button 2 : 0x%02x\n", (iValue >> 1) & 1); + DBG(DBG_FNC, " bit[2] = button 4 : 0x%02x\n", (iValue >> 2) & 1); + DBG(DBG_FNC, " bit[3] = button 3 : 0x%02x\n", (iValue >> 3) & 1); + DBG(DBG_FNC, " bit[4] = button ? : 0x%02x\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[5] = button ? : 0x%02x\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[6] = ? : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x169], 1); + DBG(DBG_FNC, "\n0x0169", iValue); + DBG(DBG_FNC, " bit[0] = ? : 0x%02x\n", iValue & 1); + DBG(DBG_FNC, " bit[1] = tma attached? : 0x%02x\n", (iValue >> 1) & 1); + DBG(DBG_FNC, " bit[2..7] = ? : 0x%02x\n", (iValue >> 2) & 0x3f); + + iValue = data_lsb_get(&buffer[0x16a], 1); + DBG(DBG_FNC, "\n0x016a Buttons status 2: 0x%02x\n", iValue); + DBG(DBG_FNC, " bit[0] = button 1 : 0x%02x\n", iValue & 1); + DBG(DBG_FNC, " bit[1] = button 2 : 0x%02x\n", (iValue >> 1) & 1); + DBG(DBG_FNC, " bit[2] = button 4 : 0x%02x\n", (iValue >> 2) & 1); + DBG(DBG_FNC, " bit[3] = button 3 : 0x%02x\n", (iValue >> 3) & 1); + DBG(DBG_FNC, " bit[4] = button ? : 0x%02x\n", (iValue >> 4) & 1); + DBG(DBG_FNC, " bit[5] = button ? : 0x%02x\n", (iValue >> 5) & 1); + DBG(DBG_FNC, " bit[6] = ? : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); + + dbg_buffer(DBG_FNC, "\n0x016b", &buffer[0x16b], 4, 0x16b); + + iValue = data_lsb_get(&buffer[0x16f], 1); + DBG(DBG_FNC, "\n0x016f"); + DBG(DBG_FNC, " bit[0..5] = ? : 0x%02x\n", iValue & 0x3f); + DBG(DBG_FNC, " bit[6] = is lamp at home? : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = ?: %02x\n", (iValue >> 7) & 1); + + dbg_buffer(DBG_FNC, "\n0x0170", &buffer[0x170], 0x17, 0x170); + + iValue = data_lsb_get(&buffer[0x187], 1); + DBG(DBG_FNC, "\n0x0187"); + DBG(DBG_FNC, " bit[0..3] = ? : 0x%02x\n", iValue & 0xf); + DBG(DBG_FNC, " bit[4..7] = mclkioc : 0x%02x\n", (iValue >> 4) & 0xf); + + dbg_buffer(DBG_FNC, "\n0x0188", &buffer[0x188], 0x16, 0x188); + + iValue = data_lsb_get(&buffer[0x19e], 2); + DBG(DBG_FNC, "\n0x019e"); + DBG(DBG_FNC, " binary threshold low : 0x%04x\n", (iValue >> 8) + ((iValue << 8) & 0xff00)); + + iValue = data_lsb_get(&buffer[0x1a0], 2); + DBG(DBG_FNC, "\n0x01a0"); + DBG(DBG_FNC, " binary threshold high : 0x%04x\n", (iValue >> 8) + ((iValue << 8) & 0xff00)); + + dbg_buffer(DBG_FNC, "\n0x01a2", &buffer[0x1a2], 0x12, 0x1a2); + + iValue = data_lsb_get(&buffer[0x1b4], 2); + DBG(DBG_FNC, "\n0x01b4"); + DBG(DBG_FNC, " bit[00..13] = Ptr to red gamma table (table_size * 0) : 0x%04x\n", (iValue & 0x3fff)); + DBG(DBG_FNC, " bit[14..15] = ? : 0x%02x\n", (iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x1b6], 2); + DBG(DBG_FNC, "0x01b6"); + DBG(DBG_FNC, " bit[00..13] = Ptr to green gamma table (table_size * 1) : 0x%04x\n", (iValue & 0x3fff)); + DBG(DBG_FNC, " bit[14..15] = ? : 0x%02x\n", (iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x1b8], 2); + DBG(DBG_FNC, "0x01b8"); + DBG(DBG_FNC, " bit[00..13] = Ptr to blue gamma table (table_size * 2) : 0x%04x\n", (iValue & 0x3fff)); + DBG(DBG_FNC, " bit[14..15] = ? : 0x%02x\n", (iValue >> 14) & 3); + + iValue = data_lsb_get(&buffer[0x1ba], 1); + DBG(DBG_FNC, "\n0x01ba"); + DBG(DBG_FNC, " ? : 0x%02x\n", iValue); + + iValue = data_lsb_get(&buffer[0x1bb], 2); + DBG(DBG_FNC, "0x01bb"); + DBG(DBG_FNC, " ? : 0x%04x\n", iValue + ((data_lsb_get(&buffer[0x1bf], 1) & 1) << 16)); + + iValue = data_lsb_get(&buffer[0x1bd], 2); + DBG(DBG_FNC, "0x01bd"); + DBG(DBG_FNC, " ? : 0x%04x\n", iValue + (((data_lsb_get(&buffer[0x1bf], 1) >> 1) & 3) << 16)); + + iValue = data_lsb_get(&buffer[0x1c0], 3); + DBG(DBG_FNC, "0x01c0"); + DBG(DBG_FNC, " bit[0..19] = ? : 0x%06x\n", iValue & 0xfffff); + + iValue = data_lsb_get(&buffer[0x1bf], 2); + DBG(DBG_FNC, "\n0x01bf"); + DBG(DBG_FNC, " bit[3..4] = ? : 0x%02x\n", (iValue >> 3) & 3); + DBG(DBG_FNC, " bit[5..7] = ? : 0x%02x\n", (iValue >> 5) & 7); + + iValue = data_lsb_get(&buffer[0x1c2], 3); + DBG(DBG_FNC, "\n0x01c2"); + DBG(DBG_FNC, " bit[4..23] = ? : 0x%06x\n", ((iValue >> 8) & 0xffff) + (((iValue >> 4) & 0xf) << 16)); + + iValue = data_lsb_get(&buffer[0x1c5], 3); + DBG(DBG_FNC, "0x01c5"); + DBG(DBG_FNC, " bit[00..19] = ? : 0x%06x\n", iValue & 0xfffff); + DBG(DBG_FNC, " bit[20..23] = ? : 0x%02x\n", (iValue >> 20) & 0xf); + + dbg_buffer(DBG_FNC, "\n0x01c8", &buffer[0x1c8], 7, 0x1c8); + + iValue = data_lsb_get(&buffer[0x1cf], 3); + DBG(DBG_FNC, "\n0x01cf"); + DBG(DBG_FNC, " bit[0] = ? : 0x%02x\n", iValue & 1); + DBG(DBG_FNC, " bit[1] = shading base (0 = 0x4000|1= 0x2000) : 0x%02x\n", (iValue >> 1) & 1); + DBG(DBG_FNC, " bit[2] = white shading correction : 0x%02x\n", (iValue >> 2) & 1); + DBG(DBG_FNC, " bit[3] = black shading correction : 0x%02x\n", (iValue >> 3) & 1); + DBG(DBG_FNC, " bit[4..5] = 0x%02x : ", (iValue >> 4) & 3); + switch ((iValue >> 4) & 3) + { + case 0: DBG(DBG_FNC, "8 bits per channel"); break; + case 1: DBG(DBG_FNC, "12 bits per channel"); break; + case 2: DBG(DBG_FNC, "16 bits per channel"); break; + case 3: DBG(DBG_FNC, "lineart mode"); break; + } + DBG(DBG_FNC, "\n"); + DBG(DBG_FNC, " bit[6] = samplerate: 0x%02x ", (iValue >> 6) & 1); + if (((iValue >> 6) & 1) == PIXEL_RATE) + DBG(DBG_FNC, "PIXEL_RATE\n"); + else DBG(DBG_FNC, "LINE_RATE\n"); + DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); + + iValue = data_lsb_get(&buffer[0x1d0], 1); + DBG(DBG_FNC, "\n0x01d0"); + DBG(DBG_FNC, " bit[0] = 0x%02x\n", iValue & 1); + DBG(DBG_FNC, " bit[1] = 0x%02x\n", (iValue >> 1) & 1); + DBG(DBG_FNC, " bit[2..3] = gamma table size : 0x%02x ", (iValue >> 2) & 3); + switch ((iValue >> 2) & 3) + { + case 0: DBG(DBG_FNC, "bit[0] + 0x100") ;break; + case 1: DBG(DBG_FNC, "bit[0] + 0x400") ;break; + case 2: DBG(DBG_FNC, "bit[0] + 0x1000") ;break; + } + DBG(DBG_FNC, "\n"); + DBG(DBG_FNC, " bit[4..5] = ? : 0x%02x\n", (iValue >> 4) & 3); + DBG(DBG_FNC, " bit[6] = use gamma tables? : 0x%02x\n", (iValue >> 6) & 1); + DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); + + dbg_buffer(DBG_FNC, "\n0x01d1", &buffer[0x1d1], 0x430, 0x1d1); + + DBG(DBG_FNC, "----------------------------------------------------\n\n"); + */ + /*exit(0); */ +} +#endif diff --git a/backend/hp3900_rts8822.c b/backend/hp3900_rts8822.c new file mode 100644 index 000000000..45afb5d15 --- /dev/null +++ b/backend/hp3900_rts8822.c @@ -0,0 +1,15379 @@ +/* HP Scanjet 3900 series - RTS8822 Core + + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + + +/* + This code is still a bit ugly due to it's the result of applying + reverse engineering techniques to windows driver. So at this + moment what you see is exactly what windows driver does. + And so many global vars exist that will be erased when driver + is entirely debugged. There are some variables with unknown + purpose. So they have no meaning name in form v+address. I + hope to change their names when driver is debugged completely. +*/ + +#ifndef RTS8822_CORE + +#define RTS8822_CORE + +#define GetTickCount() (time(0) * 1000) +#define min(A,B) (((A)<(B)) ? (A) : (B)) +#define max(A,B) (((A)>(B)) ? (A) : (B)) +#define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_)) +#define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4) + +#include +#include +#include /* bzero() */ +#include /* clock() */ +#include /* truncf() */ +#include /* tolower() */ +#include /* usleep() */ + +#include "hp3900_types.c" +#include "hp3900_debug.c" +#include "hp3900_config.c" +#include "hp3900_usb.c" + +/*-------------------- Exported function headers --------------------*/ + +#ifdef developing +static SANE_Int hp4370_prueba (struct st_device *dev); +static void prueba (SANE_Byte * a); +void shadingtest1 (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib); +static SANE_Int Calib_test (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib, + struct st_scanparams *scancfg); +static SANE_Int Calib_BlackShading_jkd (struct st_device *dev, + SANE_Byte * Regs, + struct st_calibration *myCalib, + struct st_scanparams *scancfg); +#endif + +/*static void show_diff(struct st_device *dev, SANE_Byte *original);*/ + +/* functions to allocate and free space for a device */ +static struct st_device *RTS_Alloc (void); +static void RTS_Free (struct st_device *dev); + +/* Scanner level commands */ +static SANE_Int RTS_Scanner_Init (struct st_device *dev); +static SANE_Int RTS_Scanner_SetParams (struct st_device *dev, + struct params *param); +static SANE_Int RTS_Scanner_StartScan (struct st_device *dev); +static void RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait); +static void RTS_Scanner_End (struct st_device *dev); + +/* loading configuration functions */ +static SANE_Int Load_Buttons (struct st_device *dev); +static SANE_Int Load_Chipset (struct st_device *dev); +static SANE_Int Load_Config (struct st_device *dev); +static SANE_Int Load_Constrains (struct st_device *dev); +static SANE_Int Load_Motor (struct st_device *dev); +static SANE_Int Load_MotorCurves (struct st_device *dev); +static SANE_Int Load_Motormoves (struct st_device *dev); +static SANE_Int Load_Scanmodes (struct st_device *dev); +static SANE_Int Load_Sensor (struct st_device *dev); +static SANE_Int Load_Timings (struct st_device *dev); + +/* freeing configuration functions */ +static void Free_Buttons (struct st_device *dev); +static void Free_Chipset (struct st_device *dev); +static void Free_Config (struct st_device *dev); +static void Free_Constrains (struct st_device *dev); +static void Free_Motor (struct st_device *dev); +static void Free_MotorCurves (struct st_device *dev); +static void Free_Motormoves (struct st_device *dev); +static void Free_Scanmodes (struct st_device *dev); +static void Free_Sensor (struct st_device *dev); +static void Free_Timings (struct st_device *dev); +static void Free_Vars (void); + +/* Functions to manage data */ +static SANE_Byte data_bitget (SANE_Byte * address, SANE_Int mask); +static void data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data); +static SANE_Int data_lsb_get (SANE_Byte * address, SANE_Int size); +static void data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size); +static void data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size); +static void data_wide_bitset (SANE_Byte * address, SANE_Int mask, + SANE_Int data); +static SANE_Int data_swap_endianess (SANE_Int address, SANE_Int size); + +static SANE_Int Device_get (SANE_Int product, SANE_Int vendor); + +/* Chipset related commands */ +static SANE_Int Chipset_ID (struct st_device *dev); +static SANE_Int Chipset_Name (struct st_device *dev, char *name, + SANE_Int size); +static SANE_Int Chipset_Reset (struct st_device *dev); + +/* Initializing functions */ +static SANE_Int Init_Registers (struct st_device *dev); +static SANE_Int Init_USBData (struct st_device *dev); +static SANE_Int Init_Vars (void); + +/* scanmode functions */ +static SANE_Int Scanmode_fitres (struct st_device *dev, SANE_Int scantype, + SANE_Int colormode, SANE_Int resolution); +static SANE_Int Scanmode_maxres (struct st_device *dev, SANE_Int scantype, + SANE_Int colormode); +static SANE_Int Scanmode_minres (struct st_device *dev, SANE_Int scantype, + SANE_Int colormode); + +/* Chipset management useful commands*/ +static SANE_Int RTS_USBType (struct st_device *dev); +static SANE_Byte RTS_Sensor_Type (USB_Handle usb_handle); +static void RTS_DebugInit (void); +static SANE_Int RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, + SANE_Int channels); + +/* DMA management commands */ +static SANE_Int RTS_DMA_Cancel (struct st_device *dev); +static SANE_Int RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs); +static SANE_Int RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, + SANE_Int size, SANE_Int options); +static SANE_Int RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, + SANE_Int size, SANE_Int options); +static SANE_Int RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, + SANE_Int options, SANE_Int size, + SANE_Byte * buffer); +static SANE_Int RTS_DMA_Reset (struct st_device *dev); +static SANE_Int RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, + SANE_Byte ramtype); +static SANE_Int RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs); +static SANE_Int RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, + SANE_Int options, SANE_Int size, + SANE_Byte * buffer); + +/* EEPROM management commands */ +static SANE_Int RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * data); +static SANE_Int RTS_EEPROM_ReadInteger (USB_Handle usb_handle, + SANE_Int address, SANE_Int * data); +static SANE_Int RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, + SANE_Int * data); +static SANE_Int RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, + SANE_Int address, SANE_Byte * data, + SANE_Int size); +static SANE_Int RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte data); +static SANE_Int RTS_EEPROM_WriteInteger (USB_Handle usb_handle, + SANE_Int address, SANE_Int data); +static SANE_Int RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, + SANE_Int data); + +static SANE_Int RTS_Execute (struct st_device *dev); +static SANE_Int RTS_Warm_Reset (struct st_device *dev); +static SANE_Byte RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs); + +static SANE_Int RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, + SANE_Int colormode, SANE_Int resolution); +static SANE_Int RTS_GetImage (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_gain_offset *gain_offset, + SANE_Byte * buffer, + struct st_calibration *myCalib, + SANE_Int options, SANE_Int gainmode); +static SANE_Int RTS_GetImage_GetBuffer (struct st_device *dev, double dSize, + SANE_Byte * buffer, + double *transferred); +static SANE_Int RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer, + struct st_scanparams *myvar, + struct st_hwdconfig *hwdcfg); + +static SANE_Int RTS_isTmaAttached (struct st_device *dev); + +/* functions to wait for a process tp finish */ +static SANE_Int RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs); +static SANE_Int RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs); + +/* functions to read/write control registers */ +static SANE_Int RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer); +static SANE_Int RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer); + +/* functions to manage the scan counter */ +static SANE_Int RTS_ScanCounter_Inc (struct st_device *dev); +static SANE_Int RTS_ScanCounter_Get (struct st_device *dev); + +/* functions to setup control registers */ +static SANE_Int RTS_Setup (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *myvar, + struct st_hwdconfig *hwdcfg, + struct st_gain_offset *gain_offset); +static void RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + SANE_Int mycolormode); +static void RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop, + SANE_Int width, SANE_Int height); +static SANE_Int RTS_Setup_Depth (SANE_Byte * Regs, + struct st_scanparams *scancfg, + SANE_Int mycolormode); +static void RTS_Setup_Exposure_Times (SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_scanmode *sm); +static void RTS_Setup_GainOffset (SANE_Byte * Regs, + struct st_gain_offset *gain_offset); +static void RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *lowcfg); +static SANE_Int RTS_Setup_Line_Distances (struct st_device *dev, + SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_hwdconfig *hwdcfg, + SANE_Int mycolormode, + SANE_Int arrangeline); +static SANE_Int RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *myvar, + SANE_Int somevalue); +static void RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs); +static void RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming, + SANE_Byte * Regs); +static void RTS_Setup_Shading (SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_hwdconfig *hwdcfg, + SANE_Int bytes_per_line); + +static SANE_Int Scan_Start (struct st_device *dev); + +static void SetLock (USB_Handle usb_handle, SANE_Byte * Regs, + SANE_Byte Enable); +static SANE_Int fn3330 (struct st_device *dev, SANE_Byte * Regs, + struct st_cal2 *calbuffers, + SANE_Int sensorchannelcolor, SANE_Int * tablepos, + SANE_Int data); +static SANE_Int fn3560 (USHORT * table, struct st_cal2 *calbuffers, + SANE_Int * tablepos); +static SANE_Int fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, + SANE_Byte * Regs, USHORT * table, + SANE_Int sensorchannelcolor, SANE_Int data); + +static SANE_Int Reading_CreateBuffers (struct st_device *dev); +static SANE_Int Reading_DestroyBuffers (struct st_device *dev); +static SANE_Int Reading_NotifySize (struct st_device *dev, SANE_Int data, + SANE_Int size); +static SANE_Int Reading_Start (struct st_device *dev); +static SANE_Int Reading_Wait (struct st_device *dev, + SANE_Byte Channels_per_dot, + SANE_Byte Channel_size, SANE_Int size, + SANE_Int * last_amount, SANE_Int seconds, + SANE_Byte op); + +static SANE_Int Read_Image (struct st_device *dev, SANE_Int buffer_size, + SANE_Byte * buffer, SANE_Int * transferred); +static SANE_Int Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, + SANE_Int * transferred); +static SANE_Int Read_Block (struct st_device *dev, SANE_Int buffer_size, + SANE_Byte * buffer, SANE_Int * transferred); +static SANE_Int Read_NonColor_Block (struct st_device *dev, + SANE_Byte * buffer, SANE_Int buffer_size, + SANE_Byte ColorMode, + SANE_Int * transferred); + +/* Ref functions */ +static SANE_Int Refs_Analyze_Pattern (struct st_scanparams *scancfg, + SANE_Byte * scanned_pattern, + SANE_Int * ler1, SANE_Int ler1order, + SANE_Int * ser1, SANE_Int ser1order); +static SANE_Byte Refs_Counter_Load (struct st_device *dev); +static SANE_Int Refs_Counter_Inc (struct st_device *dev); +static SANE_Int Refs_Counter_Save (struct st_device *dev, SANE_Byte data); +static SANE_Int Refs_Detect (struct st_device *dev, SANE_Byte * Regs, + SANE_Int resolution_x, SANE_Int resolution_y); +static SANE_Int Refs_Load (struct st_device *dev, SANE_Int * left_leading, + SANE_Int * start_pos); +static SANE_Int Refs_Save (struct st_device *dev, SANE_Int left_leading, + SANE_Int start_pos); +static SANE_Int Refs_Set (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *myscan, SANE_Int autoref); + +/* Coordinates' constrains functions */ +static SANE_Int Constrains_Check (struct st_device *dev, SANE_Int Resolution, + SANE_Int scantype, + struct st_coords *mycoords); +static struct st_coords *Constrains_Get (struct st_device *dev, + SANE_Byte scantype); + +/* Pulse-Width Modulation functions */ +static SANE_Int PWM_GetDutyCycle (struct st_device *dev, SANE_Int * data); +static SANE_Int PWM_GetReady (struct st_device *dev, SANE_Int resolution, + SANE_Int * last_colour, double diff, + long totaltime, SANE_Int SANE_Interval, + SANE_Int value); +static SANE_Int PWM_SetDutyCycle (struct st_device *dev, SANE_Int duty_cycle); +static SANE_Int PWM_use (struct st_device *dev, SANE_Int enable); + +/* Fixed Pulse-Width Modulation functions */ +static SANE_Int FixedPWM_Get (struct st_device *dev, SANE_Byte type); +static SANE_Int FixedPWM_Save (struct st_device *dev, SANE_Int fixedpwm); +static SANE_Int FixedPWM_SaveStatus (struct st_device *dev, SANE_Byte status); + +/* Gain and offset functions */ +static SANE_Int GainOffset_Clear (struct st_device *dev); +static SANE_Int GainOffset_Get (struct st_device *dev); +static SANE_Byte GainOffset_LoadCount (struct st_device *dev); +static SANE_Int GainOffset_IncCount (struct st_device *dev, SANE_Int * arg1); +static SANE_Int GainOffset_Save (struct st_device *dev, SANE_Int * offset, + SANE_Byte * gain); +static SANE_Int GainOffset_SaveCount (struct st_device *dev, SANE_Byte data); + +/* Gamma functions*/ +static SANE_Int Gamma_AllocTable (SANE_Byte * table); +static SANE_Int Gamma_Apply (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_hwdconfig *hwdcfg, + struct st_gammatables *mygamma); +static void Gamma_FreeTables (void); +static SANE_Int Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs, + SANE_Byte * gammatable, SANE_Int size); +static SANE_Int Gamma_GetTables (struct st_device *dev, + SANE_Byte * Gamma_buffer); + +/* Lamp functions */ +static void Lamp_OverDrive (struct st_device *dev, SANE_Int itime, + SANE_Int lamp); +static SANE_Byte Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution, + SANE_Byte scantype); +static SANE_Int Lamp_GetStatus (struct st_device *dev, SANE_Byte * flb_lamp, + SANE_Byte * tma_lamp); +static SANE_Int Lamp_IsAtHome (struct st_device *dev, SANE_Byte * Regs); +static void Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs, + SANE_Int resolution, SANE_Byte gainmode); +static SANE_Int Lamp_SetStatus (struct st_device *dev, SANE_Byte * Regs, + SANE_Int turn_on, SANE_Int lamp); +static SANE_Int Lamp_SetStatus2 (struct st_device *dev, SANE_Int turnon, + SANE_Int lamp); +static SANE_Int Lamp_SetTimer (struct st_device *dev, SANE_Int minutes); +static SANE_Int Lamp_SetupPwm (struct st_device *dev, SANE_Int lamp); +static SANE_Int Lamp_WaitForPWM (struct st_device *dev, SANE_Int resolution, + SANE_Int lamp); +static SANE_Int Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, + SANE_Int lamp); + +/* Motor functions */ +static SANE_Byte *Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, + SANE_Int step); +static SANE_Int Motor_Change (struct st_device *dev, SANE_Byte * buffer, + SANE_Byte value); +static SANE_Int Motor_GetFromResolution (SANE_Int resolution); +static SANE_Int Motor_Move (struct st_device *dev, SANE_Byte * Regs, + struct st_motormove *mymotor, + struct st_motorpos *mtrpos); +static SANE_Int Motor_ParkHome (struct st_device *dev, SANE_Int bWait, + SANE_Int movement); +static void Motor_Release (struct st_device *dev); +static SANE_Int Motor_Relocate (struct st_device *dev, SANE_Int speed, + SANE_Int direction, SANE_Int ypos); +static SANE_Int Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs, + SANE_Int mysetting); + +/* motorcurve functions */ +static SANE_Int Motorcurve_Equal (struct st_device *dev, + SANE_Int motorsetting, SANE_Int direction, + SANE_Int curve1, SANE_Int curve2); +static void Motorcurve_Free (struct st_motorcurve **motorcurves, + SANE_Int * mtc_count); +static struct st_curve *Motorcurve_Get (struct st_device *dev, + SANE_Int motorcurve, + SANE_Int direction, SANE_Int itype); +static struct st_motorcurve **Motorcurve_Parse (SANE_Int * mtc_count, + SANE_Int * buffer); + +/* Functions to arrange scanned lines */ +static SANE_Int Arrange_Colour (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, SANE_Int * transferred); +static SANE_Int Arrange_Compose (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, + SANE_Int * transferred); +static SANE_Int Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, + SANE_Int * transferred); + +/* Composing RGB triplet functions */ +static void Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2, + SANE_Byte * buffer, SANE_Int channels_count); +static void Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2, + SANE_Byte * buffer, SANE_Int channels_count); +static void Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed, + SANE_Byte * pGreen, SANE_Byte * pBlue, + SANE_Byte * buffer, SANE_Int dots); +static void Triplet_Compose_HRes (SANE_Byte * pPointer1, + SANE_Byte * pPointer2, + SANE_Byte * pPointer3, + SANE_Byte * pPointer4, + SANE_Byte * pPointer5, + SANE_Byte * pPointer6, SANE_Byte * buffer, + SANE_Int Width); +static void Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, + SANE_Byte * pBlue, SANE_Byte * buffer, + SANE_Int dots); +static void Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed, + SANE_Byte * pGreen, SANE_Byte * pBlue, + SANE_Byte * buffer, SANE_Int Width); +static void Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, + SANE_Byte * pBlue1, SANE_Byte * pRed2, + SANE_Byte * pGreen2, SANE_Byte * pBlue2, + SANE_Byte * buffer, SANE_Int Width); +static void Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer, + SANE_Byte * pChannel1, SANE_Byte * pChannel2, + SANE_Byte * pChannel3); + +/* Timing functions */ +static SANE_Int Timing_SetLinearImageSensorClock (SANE_Byte * Regs, + struct st_cph *cph); + +/* Functions used to resize retrieved image */ +static SANE_Int Resize_Start (struct st_device *dev, SANE_Int * transferred); +static SANE_Int Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, + SANE_Int size2, SANE_Int size3); +static SANE_Int Resize_DestroyBuffers (struct st_device *dev); +static SANE_Int Resize_Increase (SANE_Byte * to_buffer, + SANE_Int to_resolution, SANE_Int to_width, + SANE_Byte * from_buffer, + SANE_Int from_resolution, + SANE_Int from_width, SANE_Int myresize_mode); +static SANE_Int Resize_Decrease (SANE_Byte * to_buffer, + SANE_Int to_resolution, SANE_Int to_width, + SANE_Byte * from_buffer, + SANE_Int from_resolution, + SANE_Int from_width, SANE_Int myresize_mode); + +/* Scanner buttons support */ +static SANE_Int Buttons_Count (struct st_device *dev); +static SANE_Int Buttons_Enable (struct st_device *dev); +static SANE_Int Buttons_Order (struct st_device *dev, SANE_Int mask); +static SANE_Int Buttons_Status (struct st_device *dev); +static SANE_Int Buttons_Released (struct st_device *dev); + +/* Calibration functions */ +static SANE_Int Calib_CreateBuffers (struct st_device *dev, + struct st_calibration *buffer, + SANE_Int my14b4); +static SANE_Int Calib_CreateFixedBuffers (void); +static void Calib_FreeBuffers (struct st_calibration *caltables); +static void Calib_LoadCut (struct st_device *dev, + struct st_scanparams *scancfg, SANE_Int scantype, + struct st_calibration_config *calibcfg); +static SANE_Int Calib_AdcGain (struct st_device *dev, + struct st_calibration_config *calibcfg, + SANE_Int arg2, SANE_Int gainmode); +static SANE_Int Calib_AdcOffsetRT (struct st_device *dev, + struct st_calibration_config *calibcfg, + SANE_Int value); +static SANE_Int Calib_BlackShading (struct st_device *dev, + struct st_calibration_config *calibcfg, + struct st_calibration *myCalib, + SANE_Int gainmode); +static SANE_Int Calib_BWShading (struct st_calibration_config *calibcfg, + struct st_calibration *myCalib, + SANE_Int gainmode); +static SANE_Int Calib_WhiteShading_3 (struct st_device *dev, + struct st_calibration_config *calibcfg, + struct st_calibration *myCalib, + SANE_Int gainmode); +static void Calibrate_Free (struct st_cal2 *calbuffers); +static SANE_Int Calibrate_Malloc (struct st_cal2 *calbuffers, + SANE_Byte * Regs, + struct st_calibration *myCalib, + SANE_Int somelength); +static SANE_Int Calib_ReadTable (struct st_device *dev, SANE_Byte * table, + SANE_Int size, SANE_Int data); +static SANE_Int Calib_WriteTable (struct st_device *dev, SANE_Byte * table, + SANE_Int size, SANE_Int data); +static SANE_Int Calib_LoadConfig (struct st_device *dev, + struct st_calibration_config *calibcfg, + SANE_Int scantype, SANE_Int resolution, + SANE_Int bitmode); +static SANE_Int Calib_PAGain (struct st_device *dev, + struct st_calibration_config *calibcfg, + SANE_Int gainmode); +static SANE_Int Calibration (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_calibration *myCalib, SANE_Int value); + +/* function for white shading correction */ +static SANE_Int WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib, + struct st_scanparams *scancfg); +static void WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, + SANE_Int size, SANE_Int depth); + +/* functions for shading calibration */ +static SANE_Int Shading_apply (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *myvar, + struct st_calibration *myCalib); +static SANE_Int Shading_black_apply (struct st_device *dev, SANE_Byte * Regs, + SANE_Int channels, + struct st_calibration *myCalib, + struct st_cal2 *calbuffers); +static SANE_Int Shading_white_apply (struct st_device *dev, SANE_Byte * Regs, + SANE_Int channels, + struct st_calibration *myCalib, + struct st_cal2 *calbuffers); + +/* Spread-Spectrum Clock Generator functions */ +static SANE_Int SSCG_Enable (struct st_device *dev); + +static void Split_into_12bit_channels (SANE_Byte * destino, + SANE_Byte * fuente, SANE_Int size); +static SANE_Int Scan_Read_BufferA (struct st_device *dev, + SANE_Int buffer_size, SANE_Int arg2, + SANE_Byte * pBuffer, + SANE_Int * bytes_transfered); + +static SANE_Int Get_Scanner_Buffer_Size (struct st_device *dev, + SANE_Byte channels_per_dot, + SANE_Int channel_size); +static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op, + SANE_Int buffer_size, SANE_Byte * buffer, + SANE_Int * transfered); +static SANE_Int Get_PAG_Value (SANE_Byte scantype, SANE_Byte color); +static SANE_Int GetOneLineInfo (struct st_device *dev, SANE_Int resolution, + SANE_Int * maximus, SANE_Int * minimus, + double *average); + +static SANE_Int Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, + SANE_Int * xpos); + +/*static SANE_Int Free_Fixed_CalBuffer(void);*/ +static SANE_Int SetMultiExposure (struct st_device *dev, SANE_Byte * Regs); + +static void Set_E950_Mode (struct st_device *dev, SANE_Byte mode); + +static SANE_Int LoadImagingParams (struct st_device *dev, SANE_Int inifile); + +static SANE_Int SetScanParams (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_hwdconfig *hwdcfg); +static SANE_Int IsScannerLinked (struct st_device *dev); + +static SANE_Int Read_FE3E (struct st_device *dev, SANE_Byte * destino); + +static double get_shrd (double value, SANE_Int desp); +static char get_byte (double value); +/*static SANE_Int RTS8822_GetRegisters(SANE_Byte *buffer);*/ + +/* ----------------- Implementation ------------------*/ + +static void +RTS_Scanner_End (struct st_device *dev) +{ + Gamma_FreeTables (); + Free_Config (dev); + Free_Vars (); +} + +static SANE_Int +Device_get (SANE_Int product, SANE_Int vendor) +{ + return cfg_device_get (product, vendor); +} + +static SANE_Int +RTS_Scanner_Init (struct st_device *dev) +{ + SANE_Int rst; + + DBG (DBG_FNC, "> RTS_Scanner_Init:\n"); + + DBG (DBG_FNC, "> Backend version: %s\n", BACKEND_VRSN); + + rst = ERROR; + + /* gets usb type of this scanner if it's not already set by user */ + if (RTS_Debug->usbtype == -1) + RTS_Debug->usbtype = RTS_USBType (dev); + + if (RTS_Debug->usbtype != ERROR) + { + DBG (DBG_FNC, " -> Chipset model ID: %i\n", Chipset_ID (dev)); + + Chipset_Reset (dev); + + if (Load_Config (dev) == OK) + { + if (IsScannerLinked (dev) == OK) + { + Set_E950_Mode (dev, 0); + Gamma_AllocTable (NULL); + rst = OK; + } + else + Free_Config (dev); + } + } + + return rst; +} + +static SANE_Int +RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer) +{ + SANE_Int rst = ERROR; + + if (buffer != NULL) + rst = + Write_Buffer (usb_handle, 0xe800, buffer, + RT_BUFFER_LEN * sizeof (SANE_Byte)); + + return rst; +} + +static SANE_Int +RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer) +{ + SANE_Int rst = ERROR; + + if (buffer != NULL) + rst = + Read_Buffer (usb_handle, 0xe800, buffer, + RT_BUFFER_LEN * sizeof (SANE_Byte)); + + return rst; +} + +static void +SetLock (USB_Handle usb_handle, SANE_Byte * Regs, SANE_Byte Enable) +{ + SANE_Byte lock; + + DBG (DBG_FNC, "+ SetLock(*Regs, Enable=%i):\n", Enable); + + if (Regs == NULL) + { + if (Read_Byte (usb_handle, 0xee00, &lock) != OK) + lock = 0; + } + else + lock = Regs[0x600]; + + if (Enable == FALSE) + lock &= 0xfb; + else + lock |= 4; + + if (Regs != NULL) + Regs[0x600] = lock; + + Write_Byte (usb_handle, 0xee00, lock); + + DBG (DBG_FNC, "- SetLock\n"); +} + +static void +Set_E950_Mode (struct st_device *dev, SANE_Byte mode) +{ + SANE_Int data; + + DBG (DBG_FNC, "+ Set_E950_Mode(mode=%i):\n", mode); + + if (Read_Word (dev->usb_handle, 0xe950, &data) == OK) + { + data = (mode == 0) ? data & 0xffbf : data | 0x40; + Write_Word (dev->usb_handle, 0xe950, data); + } + + DBG (DBG_FNC, "- Set_E950_Mode\n"); +} + +static struct st_curve * +Motorcurve_Get (struct st_device *dev, SANE_Int motorcurve, + SANE_Int direction, SANE_Int itype) +{ + struct st_curve *rst = NULL; + + if (dev != NULL) + { + if ((dev->mtrsetting != NULL) && (motorcurve < dev->mtrsetting_count)) + { + struct st_motorcurve *mtc = dev->mtrsetting[motorcurve]; + + if (mtc != NULL) + { + if ((mtc->curve != NULL) && (mtc->curve_count > 0)) + { + struct st_curve *crv; + SANE_Int a = 0; + + while (a < mtc->curve_count) + { + /* get each curve */ + crv = mtc->curve[a]; + if (crv != NULL) + { + /* check direction and type */ + if ((crv->crv_speed == direction) + && (crv->crv_type == itype)) + { + /* found ! */ + rst = crv; + break; + } + } + a++; + } + } + } + } + } + + return rst; +} + +static SANE_Int +Motorcurve_Equal (struct st_device *dev, SANE_Int motorsetting, + SANE_Int direction, SANE_Int curve1, SANE_Int curve2) +{ + /* compares two curves of the same direction + returns TRUE if both buffers are equal */ + + SANE_Int rst = FALSE; + struct st_curve *crv1 = + Motorcurve_Get (dev, motorsetting, direction, curve1); + struct st_curve *crv2 = + Motorcurve_Get (dev, motorsetting, direction, curve2); + + if ((crv1 != NULL) && (crv2 != NULL)) + { + if (crv1->step_count == crv2->step_count) + { + rst = TRUE; + + if (crv1->step_count > 0) + { + SANE_Int a = 0; + + while ((a < crv1->step_count) && (rst == TRUE)) + { + rst = (crv1->step[a] == crv2->step[a]) ? TRUE : FALSE; + a++; + } + } + } + } + + return rst; +} + +static struct st_motorcurve ** +Motorcurve_Parse (SANE_Int * mtc_count, SANE_Int * buffer) +{ + /* this function parses motorcurve buffer to get all motor settings */ + struct st_motorcurve **rst = NULL; + + *mtc_count = 0; + + if (buffer != NULL) + { + /* phases: + -1 : null phase + 0 : + -3 : initial config + */ + struct st_motorcurve *mtc = NULL; + SANE_Int phase; + + phase = -1; + while (*buffer != -1) + { + if (*buffer == -2) + { + /* end of motorcurve */ + /* complete any openned phase */ + /* close phase */ + phase = -1; + } + else + { + /* step */ + if (phase == -1) + { + /* new motorcurve */ + phase = 0; + mtc = + (struct st_motorcurve *) + malloc (sizeof (struct st_motorcurve)); + if (mtc != NULL) + { + *mtc_count += 1; + rst = + realloc (rst, + sizeof (struct st_motorcurve **) * + *mtc_count); + if (rst != NULL) + { + rst[*mtc_count - 1] = mtc; + memset (mtc, 0, sizeof (struct st_motorcurve)); + phase = -3; /* initial config */ + } + else + { + /* memory error */ + *mtc_count = 0; + break; + } + } + else + break; /* some error */ + } + + if (mtc != NULL) + { + switch (phase) + { + case -3: /* initial config */ + mtc->mri = *(buffer); + mtc->msi = *(buffer + 1); + mtc->skiplinecount = *(buffer + 2); + mtc->motorbackstep = *(buffer + 3); + buffer += 3; + + phase = -4; + break; + + case -4: + /**/ + { + /* create new step curve */ + struct st_curve *curve = + malloc (sizeof (struct st_curve)); + if (curve != NULL) + { + /* add to step curve list */ + mtc->curve = + (struct st_curve **) realloc (mtc->curve, + sizeof (struct + st_curve + **) * + (mtc-> + curve_count + + 1)); + if (mtc->curve != NULL) + { + mtc->curve_count++; + mtc->curve[mtc->curve_count - 1] = curve; + + memset (curve, 0, sizeof (struct st_curve)); + /* read crv speed and type */ + curve->crv_speed = *buffer; + curve->crv_type = *(buffer + 1); + buffer += 2; + + /* get length of step buffer */ + while (*(buffer + curve->step_count) != 0) + curve->step_count++; + + if (curve->step_count > 0) + { + /* allocate step buffer */ + curve->step = + (SANE_Int *) malloc (sizeof (SANE_Int) * + curve->step_count); + if (curve->step != NULL) + { + memcpy (curve->step, buffer, + sizeof (SANE_Int) * + curve->step_count); + buffer += curve->step_count; + } + else + curve->step_count = 0; + } + } + else + { + mtc->curve_count = 0; + free (curve); + } + } + else + break; + } + break; + } + } + } + buffer++; + } + } + + return rst; +} + +static void +Motorcurve_Free (struct st_motorcurve **motorcurves, SANE_Int * mtc_count) +{ + if ((motorcurves != NULL) && (mtc_count != NULL)) + { + struct st_motorcurve *mtc; + struct st_curve *curve; + + while (*mtc_count > 0) + { + mtc = motorcurves[*mtc_count - 1]; + if (mtc != NULL) + { + if (mtc->curve != NULL) + { + while (mtc->curve_count > 0) + { + curve = mtc->curve[mtc->curve_count - 1]; + if (curve != NULL) + { + if (curve->step != NULL) + free (curve->step); + + free (curve); + } + mtc->curve_count--; + } + } + free (mtc); + } + *mtc_count -= 1; + } + + free (motorcurves); + } +} + +static SANE_Byte +RTS_Sensor_Type (USB_Handle usb_handle) +{ + /* + Returns sensor type + 01 = CCD + 00 = CIS + */ + + SANE_Int a, b, c; + SANE_Byte rst; + char *strccd[] = { "CCD", "CIS" }; + + DBG (DBG_FNC, "+ RTS_Sensor_Type:\n"); + + a = b = c = 0; + + /* Save data first */ + Read_Word (usb_handle, 0xe950, &a); + Read_Word (usb_handle, 0xe956, &b); + + /* Enables GPIO 0xe950 writing directly 0x13ff */ + Write_Word (usb_handle, 0xe950, 0x13ff); + /* Sets GPIO 0xe956 writing 0xfcf0 */ + Write_Word (usb_handle, 0xe956, 0xfcf0); + /* Makes a sleep of 200 ms */ + usleep (1000 * 200); + /* Get GPIO 0xe968 */ + Read_Word (usb_handle, 0xe968, &c); + /* Restore data */ + Write_Word (usb_handle, 0xe950, a); + Write_Word (usb_handle, 0xe956, b); + + rst = ((_B1 (c) & 1) == 0) ? CCD_SENSOR : CIS_SENSOR; + + a = (rst == CCD_SENSOR) ? 0 : 1; + DBG (DBG_FNC, "- RTS_Sensor_Type: %s\n", strccd[a]); + + return rst; +} + +static void +Free_Scanmodes (struct st_device *dev) +{ + DBG (DBG_FNC, "> Free_Scanmodes\n"); + + if (dev->scanmodes != NULL) + { + if (dev->scanmodes_count > 0) + { + SANE_Int a; + for (a = 0; a < dev->scanmodes_count; a++) + if (dev->scanmodes[a] != NULL) + free (dev->scanmodes[a]); + } + + free (dev->scanmodes); + dev->scanmodes = NULL; + } + + dev->scanmodes_count = 0; +} + +static SANE_Int +Load_Scanmodes (struct st_device *dev) +{ + SANE_Int rst = OK; + SANE_Int a, b; + struct st_scanmode reg, *mode; + + DBG (DBG_FNC, "> Load_Scanmodes\n"); + + if ((dev->scanmodes != NULL) || (dev->scanmodes_count > 0)) + Free_Scanmodes (dev); + + a = 0; + while ((cfg_scanmode_get (dev->sensorcfg->type, a, ®) == OK) + && (rst == OK)) + { + mode = (struct st_scanmode *) malloc (sizeof (struct st_scanmode)); + if (mode != NULL) + { + memcpy (mode, ®, sizeof (struct st_scanmode)); + + for (b = 0; b < 3; b++) + { + if (mode->mexpt[b] == 0) + { + mode->mexpt[b] = mode->ctpc; + if (mode->multiexposure != 1) + mode->expt[b] = mode->ctpc; + } + } + + mode->ctpc = ((mode->ctpc + 1) * mode->multiexposure) - 1; + + dev->scanmodes = + (struct st_scanmode **) realloc (dev->scanmodes, + (dev->scanmodes_count + + 1) * + sizeof (struct st_scanmode **)); + if (dev->scanmodes != NULL) + { + dev->scanmodes[dev->scanmodes_count] = mode; + dev->scanmodes_count++; + } + else + rst = ERROR; + } + else + rst = ERROR; + + a++; + } + + if (rst == ERROR) + Free_Scanmodes (dev); + + DBG (DBG_FNC, " -> Found %i scanmodes\n", dev->scanmodes_count); + dbg_scanmodes (dev); + + return rst; +} + +static void +Free_Config (struct st_device *dev) +{ + DBG (DBG_FNC, "+ Free_Config\n"); + + /* free buttons */ + Free_Buttons (dev); + + /* free motor general configuration */ + Free_Motor (dev); + + /* free sensor main configuration */ + Free_Sensor (dev); + + /* free ccd sensor timing tables */ + Free_Timings (dev); + + /* free motor curves */ + Free_MotorCurves (dev); + + /* free motor movements */ + Free_Motormoves (dev); + + /* free scan modes */ + Free_Scanmodes (dev); + + /* free constrains */ + Free_Constrains (dev); + + /* free chipset configuration */ + Free_Chipset (dev); + + DBG (DBG_FNC, "- Free_Config\n"); +} + +static void +Free_Chipset (struct st_device *dev) +{ + DBG (DBG_FNC, "> Free_Chipset\n"); + + if (dev->chipset != NULL) + { + if (dev->chipset->name != NULL) + free (dev->chipset->name); + + free (dev->chipset); + dev->chipset = NULL; + } +} + +static SANE_Int +Load_Chipset (struct st_device *dev) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "> Load_Chipset\n"); + + if (dev->chipset != NULL) + Free_Chipset (dev); + + dev->chipset = malloc (sizeof (struct st_chip)); + if (dev->chipset != NULL) + { + SANE_Int model; + + bzero (dev->chipset, sizeof (struct st_chip)); + + /* get chipset model of selected scanner */ + model = cfg_chipset_model_get (RTS_Debug->dev_model); + + /* get configuration for selected chipset */ + rst = cfg_chipset_get (model, dev->chipset); + } + + /* if rst == ERROR may be related to allocating space for chipset name */ + + return rst; +} + +static SANE_Int +Load_Config (struct st_device *dev) +{ + DBG (DBG_FNC, "+ Load_Config\n"); + + /* load chipset configuration */ + Load_Chipset (dev); + + /* load scanner's buttons */ + Load_Buttons (dev); + + /* load scanner area constrains */ + Load_Constrains (dev); + + /* load motor general configuration */ + Load_Motor (dev); + + /* load sensor main configuration */ + Load_Sensor (dev); + + if (dev->sensorcfg->type == -1) + /* get sensor from gpio */ + dev->sensorcfg->type = RTS_Sensor_Type (dev->usb_handle); + + /* load ccd sensor timing tables */ + Load_Timings (dev); + + /* load motor curves */ + Load_MotorCurves (dev); + + /* load motor movements */ + Load_Motormoves (dev); + + /* load scan modes */ + Load_Scanmodes (dev); + + /* deprecated */ + if (dev->sensorcfg->type == CCD_SENSOR) + /* ccd */ usbfile = + (RTS_Debug->usbtype == USB20) ? T_RTINIFILE : T_USB1INIFILE; + else /* cis */ + usbfile = (RTS_Debug->usbtype == USB20) ? S_RTINIFILE : S_USB1INIFILE; + + scantype = ST_NORMAL; + + pwmlampenabled = get_value (SCAN_PARAM, PWMLAMPENABLED, 2, usbfile); + pwmlamplevel = get_value (SCAN_PARAM, PWMLAMPLEVEL, 1, usbfile); + + dpi100Lumping = get_value (SCAN_PARAM, DPILUMPING100, 0, usbfile); + + arrangeline2 = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, usbfile); + + binarythresholdh = get_value (PLATFORM, BINARYTHRESHOLDH, 0x80, usbfile); + binarythresholdl = get_value (PLATFORM, BINARYTHRESHOLDL, 0x7f, usbfile); + + shadingbase = get_value (TRUE_GRAY_PARAM, SHADINGBASE, 3, usbfile); + shadingfact[0] = get_value (TRUE_GRAY_PARAM, SHADINGFACT1, 1, usbfile); + shadingfact[1] = get_value (TRUE_GRAY_PARAM, SHADINGFACT2, 1, usbfile); + shadingfact[2] = get_value (TRUE_GRAY_PARAM, SHADINGFACT3, 1, usbfile); + + LoadImagingParams (dev, usbfile); + + DBG (DBG_FNC, "- Load_Config\n"); + + return OK; +} + +static SANE_Int +LoadImagingParams (struct st_device *dev, SANE_Int inifile) +{ + DBG (DBG_FNC, "> LoadImagingParams(inifile='%i'):\n", inifile); + + scan.startpos = get_value (SCAN_PARAM, STARTPOS, 0, inifile); + scan.leftleading = get_value (SCAN_PARAM, LEFTLEADING, 0, inifile); + arrangeline = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, inifile); + compression = get_value (SCAN_PARAM, COMPRESSION, 0, inifile); + + /* get default gain and offset values */ + cfg_gainoffset_get (dev->sensorcfg->type, default_gain_offset); + + linedarlampoff = get_value (CALI_PARAM, LINEDARLAMPOFF, 0, inifile); + + pixeldarklevel = get_value (CALI_PARAM, PIXELDARKLEVEL, 0x00ffff, inifile); + + binarythresholdh = get_value (PLATFORM, BINARYTHRESHOLDH, 0x80, inifile); + binarythresholdl = get_value (PLATFORM, BINARYTHRESHOLDL, 0x7f, inifile); + + return OK; +} + +static SANE_Int +Arrange_Colour (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, SANE_Int * transferred) +{ + /* + 05F0FA78 04EC00D8 /CALL to Assumed StdFunc2 from hpgt3970.04EC00D3 + 05F0FA7C 05D10048 |Arg1 = 05D10048 + 05F0FA80 0000F906 \Arg2 = 0000F906 + */ + SANE_Int mydistance; + SANE_Int Lines_Count; + SANE_Int space; + SANE_Int rst = OK; + SANE_Int c; + struct st_scanning *scn; + + DBG (DBG_FNC, "> Arrange_Colour(*buffer, buffer_size=%i, *transferred)\n", + buffer_size); + + /* this is just to make code more legible */ + scn = dev->scanning; + + if (scn->imagebuffer == NULL) + { + if (dev->sensorcfg->type == CCD_SENSOR) + mydistance = + (dev->sensorcfg->line_distance * scan2.resolution_y) / + dev->sensorcfg->resolution; + else + mydistance = 0; + + /*aafa */ + if (mydistance != 0) + { + scn->bfsize = + (scn->arrange_hres == + TRUE) ? scn->arrange_sensor_evenodd_dist : 0; + scn->bfsize = (scn->bfsize + (mydistance * 2) + 1) * line_size; + } + else + scn->bfsize = line_size * 2; + + /*ab3c */ + space = + (((scn->bfsize / line_size) * bytesperline) > + scn->bfsize) ? (scn->bfsize / line_size) * + bytesperline : scn->bfsize; + + scn->imagebuffer = (SANE_Byte *) malloc (space * sizeof (SANE_Byte)); + if (scn->imagebuffer == NULL) + return ERROR; + + scn->imagepointer = scn->imagebuffer; + + if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) != OK) + return ERROR; + + scn->arrange_orderchannel = FALSE; + scn->channel_size = (scan2.depth == 8) ? 1 : 2; + + /* Calculate channel displacements */ + for (c = CL_RED; c <= CL_BLUE; c++) + { + if (mydistance == 0) + { + /*ab9b */ + if (scn->arrange_hres == FALSE) + { + if ((((dev->sensorcfg->line_distance * scan2.resolution_y) * + 2) / dev->sensorcfg->resolution) == 1) + scn->arrange_orderchannel = TRUE; + + if (scn->arrange_orderchannel == TRUE) + scn->desp[c] = + ((dev->sensorcfg->rgb_order[c] / 2) * line_size) + + (scn->channel_size * c); + else + scn->desp[c] = scn->channel_size * c; + } + } + else + { + /*ac32 */ + scn->desp[c] = + (dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) + + (scn->channel_size * c); + + if (scn->arrange_hres == TRUE) + { + scn->desp1[c] = scn->desp[c]; + scn->desp2[c] = + ((scn->channel_size * 3) + scn->desp[c]) + + (scn->arrange_sensor_evenodd_dist * line_size); + } + } + } + + /*ace2 */ + for (c = CL_RED; c <= CL_BLUE; c++) + { + if (scn->arrange_hres == TRUE) + { + scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; + scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; + } + else + scn->pColour[c] = scn->imagebuffer + scn->desp[c]; + } + } + + /*ad91 */ + Lines_Count = buffer_size / line_size; + while (Lines_Count > 0) + { + if (scn->arrange_orderchannel == FALSE) + { + if (scn->arrange_hres == TRUE) + Triplet_Colour_HRes (scn->pColour1[CL_RED], + scn->pColour1[CL_GREEN], + scn->pColour1[CL_BLUE], + scn->pColour2[CL_RED], + scn->pColour2[CL_GREEN], + scn->pColour2[CL_BLUE], buffer, + line_size / (scn->channel_size * 3)); + else + Triplet_Colour_LRes (line_size / (scn->channel_size * 3), buffer, + scn->pColour[CL_RED], scn->pColour[CL_GREEN], + scn->pColour[CL_BLUE]); + } + else + Triplet_Colour_Order (dev, scn->pColour[CL_RED], + scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], + buffer, line_size / (scn->channel_size * 3)); + + scn->arrange_size -= bytesperline; + if (scn->arrange_size < 0) + v15bc--; + + buffer += line_size; + + Lines_Count--; + if (Lines_Count == 0) + { + if ((scn->arrange_size | v15bc) == 0) + return OK; + } + + if (Read_Block (dev, line_size, scn->imagepointer, transferred) == + ERROR) + return ERROR; + + /* Update displacements */ + for (c = CL_RED; c <= CL_BLUE; c++) + { + if (scn->arrange_hres == TRUE) + { + /*aeb7 */ + scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize; + scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize; + + scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; + scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; + } + else + { + /*af86 */ + scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize; + scn->pColour[c] = scn->imagebuffer + scn->desp[c]; + } + } + + /*aff3 */ + scn->imagepointer += line_size; + if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) + scn->imagepointer = scn->imagebuffer; + } + + return rst; +} + +static SANE_Int +RTS_Scanner_SetParams (struct st_device *dev, struct params *param) +{ + SANE_Int rst = ERROR; + char scm[20], ssc[20]; + + DBG (DBG_FNC, "+ RTS_Scanner_SetParams:\n"); + DBG (DBG_FNC, "-> param->resolution_x=%i\n", param->resolution_x); + DBG (DBG_FNC, "-> param->resolution_y=%i\n", param->resolution_y); + DBG (DBG_FNC, "-> param->left =%i\n", param->coords.left); + DBG (DBG_FNC, "-> param->width =%i\n", param->coords.width); + DBG (DBG_FNC, "-> param->top =%i\n", param->coords.top); + DBG (DBG_FNC, "-> param->height =%i\n", param->coords.height); + DBG (DBG_FNC, "-> param->colormode =%s\n", + dbg_colour (scm, param->colormode)); + DBG (DBG_FNC, "-> param->scantype =%s\n", + dbg_scantype (ssc, param->scantype)); + DBG (DBG_FNC, "-> param->depth =%i\n", param->depth); + DBG (DBG_FNC, "-> param->channel =%i\n", param->channel); + + /* validate area size to scan */ + if ((param->coords.width != 0) && (param->coords.height != 0)) + { + SANE_Byte mybuffer[1]; + struct st_hwdconfig hwdcfg; + + /* setting coordinates */ + memcpy (&scan.coord, ¶m->coords, sizeof (struct st_coords)); + + /* setting resolution */ + scan.resolution_x = param->resolution_x; + scan.resolution_y = param->resolution_y; + + /* setting colormode and depth */ + scan.colormode = param->colormode; + scan.depth = (param->colormode == CM_LINEART) ? 8 : param->depth; + + /* setting color channel for non color scans */ + scan.channel = _B0 (param->channel); + + arrangeline = FIX_BY_HARD; + if ((scan.resolution_x == 2400) || ((scan.resolution_x == 4800))) + { + if (scan.colormode != CM_COLOR) + { + if (scan.colormode == CM_GRAY) + { + if (scan.channel == 3) + arrangeline = FIX_BY_SOFT; + } + } + else + arrangeline = FIX_BY_SOFT; + } + + /* setting scan type */ + if ((param->scantype > 0) && (param->scantype < 4)) + scan.scantype = param->scantype; + else + scan.scantype = ST_NORMAL; + + /* setting scanner lamp */ + data_bitset (&dev->init_regs[0x146], 0x40, + ((dev->sensorcfg->type == CIS_SENSOR) ? 0 : 1)); + + /* turn on appropiate lamp */ + if (scan.scantype == ST_NORMAL) + Lamp_SetStatus2 (dev, TRUE, FLB_LAMP); + else + Lamp_SetStatus2 (dev, TRUE, TMA_LAMP); + + mybuffer[0] = 0; + if (RTS_IsExecuting (dev, mybuffer) == FALSE) + RTS_WriteRegs (dev->usb_handle, dev->init_regs); + + if (scan.depth == 16) + compression = FALSE; + + /* resetting low level config */ + bzero (&hwdcfg, sizeof (struct st_hwdconfig)); + + /* setting low level config */ + hwdcfg.scantype = scan.scantype; + hwdcfg.calibrate = mybuffer[0]; + hwdcfg.arrangeline = arrangeline; /*1 */ + hwdcfg.highresolution = (scan.resolution_x > 1200) ? TRUE : FALSE; + hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance; + + SetScanParams (dev, dev->init_regs, &scan, &hwdcfg); + + scan.shadinglength = + (((scan.sensorresolution * 17) / 2) + 3) & 0xfffffffc; + + rst = OK; + } + + DBG (DBG_FNC, "- RTS_Scanner_SetParams: %i\n", rst); + + return rst; +} + +static SANE_Int +SetScanParams (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg) +{ + struct st_coords mycoords; + SANE_Int mycolormode; + SANE_Int myvalue; + SANE_Int mymode; + SANE_Int channel_size; + SANE_Int channel_count; + SANE_Int dots_per_block; + SANE_Int aditional_dots; + + DBG (DBG_FNC, "+ SetScanParams:\n"); + dbg_ScanParams (scancfg); + dbg_hwdcfg (hwdcfg); + + bzero (&mycoords, sizeof (struct st_coords)); + /* Copy scancfg to scan2 */ + memcpy (&scan2, scancfg, sizeof (struct st_scanparams)); + + mycolormode = scancfg->colormode; + myvalue = scancfg->colormode; + scantype = hwdcfg->scantype; + + if (scancfg->colormode == CM_LINEART) + scan2.depth = 8; + + if ((scancfg->colormode != CM_COLOR) && (scancfg->channel == 3)) /*channel = 0x00 */ + { + if (scancfg->colormode == CM_GRAY) + { + mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR; + } + else + mycolormode = 3; + myvalue = mycolormode; + } + + dev->Resize->resolution_x = scancfg->resolution_x; + dev->Resize->resolution_y = scancfg->resolution_y; + + mymode = RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scancfg->resolution_x); /*0x0b */ + if (mymode == -1) + { + /* Non supported resolution. We will resize image after scanning */ + SANE_Int fitres; + + fitres = + Scanmode_fitres (dev, hwdcfg->scantype, scancfg->colormode, + scancfg->resolution_x); + if (fitres != -1) + { + /* supported resolution found */ + dev->Resize->type = RSZ_DECREASE; + } + else + { + dev->Resize->type = RSZ_INCREASE; + fitres = + Scanmode_maxres (dev, hwdcfg->scantype, scancfg->colormode); + } + + scan2.resolution_x = fitres; + scan2.resolution_y = fitres; + + mymode = + RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scan2.resolution_x); + if (mymode == -1) + return ERROR; + + imageheight = scancfg->coord.height; + dev->Resize->towidth = scancfg->coord.width; + + /* Calculate coords for new resolution */ + mycoords.left = + (scan2.resolution_x * scancfg->coord.left) / + dev->Resize->resolution_x; + mycoords.width = + (scan2.resolution_x * scancfg->coord.width) / + dev->Resize->resolution_x; + mycoords.top = + (scan2.resolution_y * scancfg->coord.top) / dev->Resize->resolution_y; + mycoords.height = + ((scan2.resolution_y * scancfg->coord.height) / + dev->Resize->resolution_y) + 2; + + switch (scan2.colormode) + { + case CM_GRAY: + if ((dev->scanmodes[mymode]->samplerate == PIXEL_RATE) + && (mycolormode != 3)) + dev->Resize->towidth *= 2; + + channel_size = (scan2.depth == 8) ? 1 : 2; + dev->Resize->mode = (scan2.depth == 8) ? RSZ_GRAYL : RSZ_GRAYH; + dev->Resize->bytesperline = dev->Resize->towidth * channel_size; + break; + case CM_LINEART: + if (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) + dev->Resize->towidth *= 2; + + dev->Resize->mode = RSZ_LINEART; + dev->Resize->bytesperline = (dev->Resize->towidth + 7) / 8; + break; + default: /*CM_COLOR */ + channel_count = 3; + channel_size = (scan2.depth == 8) ? 1 : 2; + dev->Resize->mode = (scan2.depth == 8) ? RSZ_COLOURL : RSZ_COLOURH; + dev->Resize->bytesperline = + scancfg->coord.width * (channel_count * channel_size); + break; + } + } + else + { + /* Supported scanmode */ + dev->Resize->type = RSZ_NONE; + scan2.resolution_x = scancfg->resolution_x; + scan2.resolution_y = scancfg->resolution_y; + mycoords.left = scancfg->coord.left; + mycoords.top = scancfg->coord.top; + mycoords.width = scancfg->coord.width; + mycoords.height = scancfg->coord.height; + } + + scancfg->timing = dev->scanmodes[mymode]->timing; + + scan2.sensorresolution = dev->timings[scancfg->timing]->sensorresolution; + if ((scantype > 0) && (scantype < 5)) + scan2.shadinglength = + (((scan2.sensorresolution * 17) / 2) + 3) & 0xfffffffc; + + scancfg->sensorresolution = scan2.sensorresolution; + scancfg->shadinglength = scan2.shadinglength; + + if ((mycolormode != CM_LINEART) && (scan2.depth <= 8)) + dev->scanning->arrange_compression = hwdcfg->compression; + else + dev->scanning->arrange_compression = FALSE; + + if ((arrangeline2 == FIX_BY_HARD) || (mycolormode == CM_LINEART)) + arrangeline2 = mycolormode; /*¿? */ + else if ((mycolormode == CM_GRAY) && (hwdcfg->highresolution == FALSE)) + arrangeline2 = 0; + + if (hwdcfg->highresolution == FALSE) + { + /* resolution < 1200 dpi */ + dev->scanning->arrange_hres = FALSE; + dev->scanning->arrange_sensor_evenodd_dist = 0; + } + else + { + /* resolution > 1200 dpi */ + dev->scanning->arrange_hres = TRUE; + dev->scanning->arrange_sensor_evenodd_dist = + hwdcfg->sensorevenodddistance; + } + + /* with must be adjusted to fit in the dots count per block */ + aditional_dots = 0; + if (mycolormode != CM_LINEART) + { + dots_per_block = ((scan2.resolution_x > 2400) + && (scancfg->samplerate == PIXEL_RATE)) ? 8 : 4; + + /* fit width */ + if ((mycoords.width % dots_per_block) != 0) + { + aditional_dots = dots_per_block - (mycoords.width % dots_per_block); + mycoords.width += aditional_dots; + } + } + else + { + /* Lineart */ + dots_per_block = 32 - (mycoords.width & 0x1f); + if (dots_per_block < 32) + { + mycoords.width += dots_per_block; + aditional_dots = (dots_per_block / 8); + } + } + + DBG (DBG_FNC, " -> dots_per_block: %i\n", dots_per_block); + DBG (DBG_FNC, " -> aditional_dots: %i\n", aditional_dots); + + if (mycolormode == CM_LINEART) + { + bytesperline = + (dev->scanmodes[mymode]->samplerate == + PIXEL_RATE) ? mycoords.width / 4 : mycoords.width / 8; + imagewidth3 = bytesperline; + lineart_width = bytesperline * 8; + line_size = bytesperline - aditional_dots; + dev->Resize->fromwidth = line_size * 8; + } + else + { + /*4510 */ + switch (mycolormode) + { + case CM_COLOR: + channel_count = 3; + break; + case 3: + channel_count = 1; + break; + case CM_GRAY: + channel_count = (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) ? 2 : 1; /*1 */ + break; + } + + channel_size = (scan2.depth == 8) ? 1 : 2; + bytesperline = mycoords.width * (channel_count * channel_size); + imagewidth3 = bytesperline / channel_count; + lineart_width = imagewidth3 / channel_size; + line_size = + bytesperline - (aditional_dots * (channel_count * channel_size)); + dev->Resize->fromwidth = line_size / (channel_count * channel_size); + } + + imagesize = mycoords.height * bytesperline; + v15b4 = 0; + dev->scanning->arrange_size = imagesize; + v15bc = 0; + + /* set resolution ratio */ + data_bitset (&Regs[0xc0], 0x1f, + scancfg->sensorresolution / scancfg->resolution_x); + + scancfg->coord.left = mycoords.left; + scancfg->coord.top = mycoords.top; + scancfg->coord.width = mycoords.width; + scancfg->coord.height = mycoords.height; + scancfg->resolution_x = scan2.resolution_x; + scancfg->resolution_y = scan2.resolution_y; + + myvalue = + (dev->Resize->type == RSZ_NONE) ? line_size : dev->Resize->bytesperline; + scancfg->bytesperline = bytesperline; + + scancfg->v157c = myvalue; + + if (scan.colormode != CM_COLOR) + { + if (mycolormode == CM_COLOR) + scancfg->v157c = (scancfg->v157c / 3); + } + + if (scan.colormode == CM_LINEART) + { + if (mycolormode == 3) + { + scancfg->v157c = (scancfg->v157c + 7) / 8; + scancfg->bytesperline = (scancfg->bytesperline + 7) / 8; + } + } + + DBG (DBG_FNC, "- SetScanParams:\n"); + + return OK; +} + +static SANE_Int +GainOffset_SaveCount (struct st_device *dev, SANE_Byte data) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "> GainOffset_SaveCount(data=%i):\n", data); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + data = min (data, 0x0f); + rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x0077, data); + } + + return rst; +} + +static SANE_Int +GainOffset_IncCount (struct st_device *dev, SANE_Int * arg1) +{ + SANE_Byte count; + SANE_Int rst; + + DBG (DBG_FNC, "+ GainOffset_IncCount:\n"); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + count = GainOffset_LoadCount (dev); + if ((count >= 0x0f) || (GainOffset_Get (dev) != OK)) + { + offset[CL_BLUE] = offset[CL_GREEN] = offset[CL_RED] = 0; + gain[CL_BLUE] = gain[CL_GREEN] = gain[CL_RED] = 0; + count = 0; + } + else + { + count++; + if (arg1 != NULL) + *arg1 = 1; + } + + rst = GainOffset_SaveCount (dev, count); + } + else + rst = OK; + + DBG (DBG_FNC, "- GainOffset_IncCount: %i\n", rst); + + return rst; +} + +static SANE_Int +GainOffset_Get (struct st_device *dev) +{ + SANE_Int a, data, rst; + SANE_Byte checksum; + + DBG (DBG_FNC, "+ GainOffset_Get:\n"); + + checksum = 0; + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + /* get current checksum */ + if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x76, &checksum) == OK) + { + rst = OK; + + /* read gain and offset values from EEPROM */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x70 + (2 * a), &data) + == ERROR) + { + rst = ERROR; + break; + } + else + offset[a] = data; + } + + /* check checksum */ + checksum = + _B0 (checksum + offset[CL_GREEN] + offset[CL_BLUE] + + offset[CL_RED]); + } + else + rst = ERROR; + } + else + rst = ERROR; + + /* extract gain and offset values */ + if ((rst == OK) && (checksum == 0x5b)) + { + for (a = CL_RED; a <= CL_BLUE; a++) + { + gain[a] = (offset[a] >> 9) & 0x1f; + offset[a] &= 0x01ff; + } + } + else + { + /* null values, let's reset them */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + gain[a] = 0; + offset[a] = 0; + } + + rst = ERROR; + } + + DBG (DBG_FNC, + "-> Preview gainR=%i, gainG=%i, gainB=%i, offsetR=%i, offsetG=%i, offsetB=%i\n", + gain[CL_RED], gain[CL_GREEN], gain[CL_BLUE], offset[CL_RED], + offset[CL_GREEN], offset[CL_BLUE]); + + DBG (DBG_FNC, "- GainOffset_Get: %i\n", rst); + + return rst; +} + +static SANE_Int +Scanmode_maxres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode) +{ + /* returns position in scanmodes table where data fits with given arguments */ + SANE_Int rst = 0; + SANE_Int a; + struct st_scanmode *reg; + char scm[20], sct[20]; + + for (a = 0; a < dev->scanmodes_count; a++) + { + reg = dev->scanmodes[a]; + if (reg != NULL) + { + if ((reg->scantype == scantype) && (reg->colormode == colormode)) + rst = max (rst, reg->resolution); /* found ! */ + } + } + + if (rst == 0) + { + /* There isn't any mode for these arguments. + Most devices doesn't support specific setup to scan in lineart mode + so they use gray colormode. Lets check this case */ + if (colormode == CM_LINEART) + rst = Scanmode_maxres (dev, scantype, CM_GRAY); + } + + DBG (DBG_FNC, "> Scanmode_maxres(scantype=%s, colormode=%s): %i\n", + dbg_scantype (sct, scantype), dbg_colour (scm, colormode), rst); + + return rst; +} + +static SANE_Int +Scanmode_minres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode) +{ + /* returns position in scanmodes table where data fits with given arguments */ + SANE_Int rst, a; + struct st_scanmode *reg; + char scm[20], sct[20]; + + rst = Scanmode_maxres (dev, scantype, colormode); + + for (a = 0; a < dev->scanmodes_count; a++) + { + reg = dev->scanmodes[a]; + if (reg != NULL) + { + if ((reg->scantype == scantype) && (reg->colormode == colormode)) + rst = min (rst, reg->resolution); /* found ! */ + } + } + + if (rst == 0) + { + /* There isn't any mode for these arguments. + Most devices doesn't support specific setup to scan in lineart mode + so they use gray colormode. Lets check this case */ + if (colormode == CM_LINEART) + rst = Scanmode_minres (dev, scantype, CM_GRAY); + } + + DBG (DBG_FNC, "> Scanmode_minres(scantype=%s, colormode=%s): %i\n", + dbg_scantype (sct, scantype), dbg_colour (scm, colormode), rst); + + return rst; +} + +static SANE_Int +Scanmode_fitres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, + SANE_Int resolution) +{ + /* returns a supported resolution */ + SANE_Int rst; + SANE_Int a, nullres; + struct st_scanmode *reg; + char scm[20], sct[20]; + + nullres = Scanmode_maxres (dev, scantype, colormode) + 1; + rst = nullres; + + for (a = 0; a < dev->scanmodes_count; a++) + { + reg = dev->scanmodes[a]; + if (reg != NULL) + { + if ((reg->scantype == scantype) && (reg->colormode == colormode)) + { + if ((reg->resolution < rst) && (resolution <= reg->resolution)) + rst = reg->resolution; + } + } + } + + if (rst == nullres) + { + /* There isn't any mode for these arguments. + Most devices doesn't support specific setup to scan in lineart mode + so they use gray colormode. Lets check this case */ + if (colormode != CM_LINEART) + { + /* at this point, given resolution is bigger than maximum supported resolution */ + rst = -1; + } + else + rst = Scanmode_minres (dev, scantype, CM_GRAY); + } + + DBG (DBG_FNC, + "> Scanmode_fitres(scantype=%s, colormode=%s, resolution=%i): %i\n", + dbg_scantype (sct, scantype), dbg_colour (scm, colormode), resolution, + rst); + + return rst; +} + +static SANE_Int +RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, + SANE_Int resolution) +{ + /* returns position in scanmodes table where data fits with given arguments */ + SANE_Int rst = -1; + SANE_Int a; + struct st_scanmode *reg; + char scm[20], sct[20]; + + for (a = 0; a < dev->scanmodes_count; a++) + { + reg = dev->scanmodes[a]; + if (reg != NULL) + { + if ((reg->scantype == scantype) && (reg->colormode == colormode) + && (reg->resolution == resolution)) + { + /* found ! */ + rst = a; + break; + } + } + } + + if (rst == -1) + { + /* There isn't any mode for these arguments. + May be given resolution isn't supported by chipset. + Most devices doesn't support specific setup to scan in lineart mode + so they use gray colormode. Lets check this case */ + if ((colormode == CM_LINEART) || (colormode == 3)) + rst = RTS_GetScanmode (dev, scantype, CM_GRAY, resolution); + } + + DBG (DBG_FNC, + "> RTS_GetScanmode(scantype=%s, colormode=%s, resolution=%i): %i\n", + dbg_scantype (sct, scantype), dbg_colour (scm, colormode), resolution, + rst); + + return rst; +} + +static void +Free_Motor (struct st_device *dev) +{ + /* this function releases space for stepper motor */ + + DBG (DBG_FNC, "> Free_Motor\n"); + + if (dev->motorcfg != NULL) + { + free (dev->motorcfg); + dev->motorcfg = NULL; + } +} + +static SANE_Int +Load_Motor (struct st_device *dev) +{ + /* this function loads general configuration for motor */ + + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "> Load_Motor\n"); + + if (dev->motorcfg != NULL) + Free_Motor (dev); + + dev->motorcfg = malloc (sizeof (struct st_motorcfg)); + if (dev->motorcfg != NULL) + { + rst = cfg_motor_get (dev->motorcfg); + dbg_motorcfg (dev->motorcfg); + } + + return rst; +} + +static void +Free_Sensor (struct st_device *dev) +{ + /* this function releases space for ccd sensor */ + + DBG (DBG_FNC, "> Free_Sensor\n"); + + if (dev->sensorcfg != NULL) + { + free (dev->sensorcfg); + dev->sensorcfg = NULL; + } +} + +static void +Free_Buttons (struct st_device *dev) +{ + /* this function releases space for buttons */ + + DBG (DBG_FNC, "> Free_Buttons\n"); + + if (dev->buttons != NULL) + { + free (dev->buttons); + dev->buttons = NULL; + } +} + +static SANE_Int +Load_Buttons (struct st_device *dev) +{ + /* this function loads configuration for ccd sensor */ + + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "> Load_Buttons\n"); + + if (dev->buttons != NULL) + Free_Buttons (dev); + + dev->buttons = malloc (sizeof (struct st_buttons)); + if (dev->buttons != NULL) + { + rst = cfg_buttons_get (dev->buttons); + dbg_buttons (dev->buttons); + } + + return rst; +} + +static SANE_Int +Load_Sensor (struct st_device *dev) +{ + /* this function loads configuration for ccd sensor */ + + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "> Load_Sensor\n"); + + if (dev->sensorcfg != NULL) + Free_Sensor (dev); + + dev->sensorcfg = malloc (sizeof (struct st_sensorcfg)); + if (dev->sensorcfg != NULL) + { + rst = cfg_sensor_get (dev->sensorcfg); + dbg_sensor (dev->sensorcfg); + } + + return rst; +} + +static void +Free_Timings (struct st_device *dev) +{ + /* this function frees all ccd sensor timing tables */ + DBG (DBG_FNC, "> Free_Timings\n"); + + if (dev->timings != NULL) + { + if (dev->timings_count > 0) + { + SANE_Int a; + for (a = 0; a < dev->timings_count; a++) + if (dev->timings[a] != NULL) + free (dev->timings[a]); + + dev->timings_count = 0; + } + + free (dev->timings); + dev->timings = NULL; + } +} + +static SANE_Int +Load_Timings (struct st_device *dev) +{ + SANE_Int rst = OK; + SANE_Int a; + struct st_timing reg, *tmg; + + DBG (DBG_FNC, "> Load_Timings\n"); + + if (dev->timings != NULL) + Free_Timings (dev); + + a = 0; + + while ((cfg_timing_get (dev->sensorcfg->type, a, ®) == OK) + && (rst == OK)) + { + tmg = (struct st_timing *) malloc (sizeof (struct st_timing)); + if (tmg != NULL) + { + memcpy (tmg, ®, sizeof (struct st_timing)); + + dev->timings_count++; + dev->timings = + (struct st_timing **) realloc (dev->timings, + sizeof (struct st_timing **) * + dev->timings_count); + if (dev->timings == NULL) + { + rst = ERROR; + dev->timings_count = 0; + } + else + dev->timings[dev->timings_count - 1] = tmg; + } + else + rst = ERROR; + + a++; + } + + if (rst == ERROR) + Free_Timings (dev); + + DBG (DBG_FNC, " -> Found %i timing registers\n", dev->timings_count); + + return rst; +} + +static SANE_Int +IsScannerLinked (struct st_device *dev) +{ + SANE_Int var2; + SANE_Byte BL; + + DBG (DBG_FNC, "+ IsScannerLinked:\n"); + + Read_FE3E (dev, &v1619); + Init_USBData (dev); + scan.scantype = ST_NORMAL; + + RTS_WaitInitEnd (dev, 0x30000); + + BL = 0; + + /* Comprobar si es la primera conexión con el escaner */ + if (Read_Word (dev->usb_handle, 0xe829, &var2) == OK) + { + SANE_Int firstconnection; + +#ifdef STANDALONE + firstconnection = TRUE; +#else + firstconnection = (var2 == 0) ? TRUE : FALSE; +#endif + + if (firstconnection == TRUE) + { + /* primera conexión */ + SANE_Byte flb_lamp, tma_lamp; + + flb_lamp = 0; + tma_lamp = 0; + Lamp_GetStatus (dev, &flb_lamp, &tma_lamp); + + if (flb_lamp == 0) + { + /* if tma_lamp is turned on, bl = 1 else bl = 0 */ + if (tma_lamp != 0) + BL = 1; + } + + /*Clear GainOffset count */ + GainOffset_Clear (dev); + GainOffset_SaveCount (dev, 0); + + /* Clear AutoRef count */ + Refs_Counter_Save (dev, 0); + + Buttons_Enable (dev); + Lamp_SetTimer (dev, 13); + } + else + BL = _B0 (var2); + } + + if (RTS_Warm_Reset (dev) != OK) + return ERROR; + + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + + Lamp_SetTimer (dev, 13); + + /* Use fixed pwm? */ + if (RTS_Debug->use_fixed_pwm != FALSE) + { + FixedPWM_Save (dev, FixedPWM_Get (dev, ST_NORMAL)); + /* Lets enable using fixed pwm */ + FixedPWM_SaveStatus (dev, TRUE); + } + + Lamp_SetupPwm (dev, (BL == 0) ? FLB_LAMP : TMA_LAMP); + + DBG (DBG_FNC, "- IsScannerLinked:\n"); + + return OK; +} + +static SANE_Int +FixedPWM_SaveStatus (struct st_device *dev, SANE_Byte status) +{ + SANE_Byte mypwm; + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ FixedPWM_SaveStatus(status=%i):\n", status); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + rst = ERROR; + + if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x007b, &mypwm) == OK) + { + mypwm = (status == FALSE) ? mypwm & 0x7f : mypwm | 0x80; + + if (RTS_EEPROM_WriteByte (dev->usb_handle, 0x007b, mypwm) == OK) + rst = OK; + } + } + + DBG (DBG_FNC, "- FixedPWM_SaveStatus: %i\n", rst); + + return rst; +} + +static SANE_Int +FixedPWM_Save (struct st_device *dev, SANE_Int fixedpwm) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ FixedPWM_Save(fixedpwm=%i):\n", fixedpwm); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + rst = + RTS_EEPROM_WriteByte (dev->usb_handle, 0x7b, ((fixedpwm << 2) | 0x80)); + else + rst = OK; + + DBG (DBG_FNC, "- FixedPWM_Save: %i\n", rst); + + return rst; +} + +static SANE_Int +FixedPWM_Get (struct st_device *dev, SANE_Byte type) +{ + char sdebug[20]; + SANE_Int rst; + + rst = cfg_fixedpwm_get (dev->sensorcfg->type, type); + + DBG (DBG_FNC, "> FixedPWM_Get(type=%s): %i\n", dbg_scantype (sdebug, type), + rst); + + return rst; +} + +static SANE_Int +Lamp_SetupPwm (struct st_device *dev, SANE_Int lamp) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ Lamp_SetupPwm(lamp=%s):\n", + (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP"); + + if (PWM_use (dev, 1) == OK) + { + SANE_Int fixedpwm, currentpwd; + + currentpwd = 0; + fixedpwm = FixedPWM_Get (dev, (lamp == FLB_LAMP) ? ST_NORMAL : ST_TA); + + if (PWM_GetDutyCycle (dev, ¤tpwd) == OK) + { + /* set duty cycle if current one is different */ + if (currentpwd != fixedpwm) + rst = PWM_SetDutyCycle (dev, fixedpwm); + } + else + rst = PWM_SetDutyCycle (dev, fixedpwm); + } + + DBG (DBG_FNC, "- Lamp_SetupPwm: %i\n", rst); + + return rst; +} + +static SANE_Int +PWM_GetDutyCycle (struct st_device *dev, SANE_Int * data) +{ + SANE_Byte a; + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ PWM_GetDutyCycle:\n"); + + if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK) + { + *data = a & 0x3f; + rst = OK; + } + + DBG (DBG_FNC, "- PWM_GetDutyCycle = %i: %i\n", *data, rst); + + return rst; +} + +static SANE_Int +PWM_SetDutyCycle (struct st_device *dev, SANE_Int duty_cycle) +{ + SANE_Byte *Regs; + SANE_Int rst; + + DBG (DBG_FNC, "+ PWM_SetDutyCycle(duty_cycle=%i):\n", duty_cycle); + + rst = ERROR; + + Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (Regs != NULL) + { + if (RTS_ReadRegs (dev->usb_handle, Regs) == OK) + { + data_bitset (&Regs[0x148], 0x3f, duty_cycle); + + if (pwmlamplevel == 0) + { + data_bitset (&Regs[0x148], 0x40, 0); + Regs[0x1e0] |= ((duty_cycle >> 1) & 0x40); + } + + data_bitset (&dev->init_regs[0x148], 0x7f, Regs[0x148]); + data_bitset (&dev->init_regs[0x1e0], 0x3f, Regs[0x1e0]); + + Write_Byte (dev->usb_handle, 0xe948, Regs[0x0148]); + + rst = Write_Byte (dev->usb_handle, 0xe9e0, Regs[0x01e0]); + } + + free (Regs); + } + + DBG (DBG_FNC, "- PWM_SetDutyCycle: %i\n", rst); + + return rst; +} + +static SANE_Int +Motor_ParkHome (struct st_device *dev, SANE_Int bWait, SANE_Int movement) +{ + SANE_Int rst = ERROR; + SANE_Byte *Regs; + + DBG (DBG_FNC, "+ Motor_ParkHome(bWait=%i, movement=%i):\n", bWait, + movement); + + Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (Regs != NULL) + { + rst = OK; + + memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + /* Lets wait if it's required when is already executing */ + if (bWait != FALSE) + { + if (RTS_WaitScanEnd (dev, 0x3a98) != OK) + { + DBG (DBG_FNC, " -> Motor_ParkHome: RTS_WaitScanEnd Timeout\n"); + rst = ERROR; /* timeout */ + } + } + else + { + if (RTS_IsExecuting (dev, Regs) == FALSE) + { + DBG (DBG_FNC, + " -> Motor_ParkHome: RTS_IsExecuting = 0, exiting function\n"); + rst = ERROR; /* if NOT executing */ + } + } + + /* Check if lamp is at home */ + if ((rst == OK) && (Lamp_IsAtHome (dev, Regs) == FALSE)) + { + struct st_motormove mymotor; + struct st_motorpos mtrpos; + + DBG (DBG_FNC, + "-> Motor_ParkHome: Lamp is not at home, lets move\n"); + + /* it isn't */ + if ((movement != -1) && (movement < dev->motormove_count)) + { + memcpy (&mymotor, dev->motormove[movement], + sizeof (struct st_motormove)); + } + else + { + /* debug this code. Shouldn't have any relationship with offsets */ + if (default_gain_offset->edcg2[CL_BLUE] < 4) + mymotor.scanmotorsteptype = + default_gain_offset->edcg2[CL_BLUE]; + + mymotor.ctpc = default_gain_offset->odcg2[1]; + mymotor.systemclock = default_gain_offset->edcg2[1]; /*? */ + } + + mtrpos.options = MTR_ENABLED | MTR_BACKWARD; + mtrpos.v12e448 = 0x01; + mtrpos.v12e44c = 0x00; + mtrpos.coord_y = 0x4e20; + + Motor_Move (dev, Regs, &mymotor, &mtrpos); + + /* Should we wait? */ + if (bWait != FALSE) + rst = RTS_WaitScanEnd (dev, 15000); + } + + free (Regs); + } + + DBG (DBG_FNC, "- Motor_ParkHome: %i:\n", rst); + + return rst; +} + +static SANE_Int +Motor_Move (struct st_device *dev, SANE_Byte * Regs, + struct st_motormove *mymotor, struct st_motorpos *mtrpos) +{ + SANE_Byte *cpRegs; + SANE_Int rst; + + DBG (DBG_FNC, "+ Motor_Move:\n"); + + rst = ERROR; + + cpRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (cpRegs != NULL) + { + SANE_Int data, v12dcf8, coord_y, step_type; + + memcpy (cpRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + v12dcf8 = 0; + + /* resolution = 1 dpi */ + data_bitset (&cpRegs[0xc0], 0x1f, 1); /*---xxxxx*/ + + /* set motor step type */ + data_bitset (&cpRegs[0xd9], 0x70, mymotor->scanmotorsteptype); /*-xxx----*/ + + /* set motor direction (polarity) */ + data_bitset (&cpRegs[0xd9], 0x80, mtrpos->options >> 3); /*e------- */ + + /* next value doesn't seem to have any effect */ + data_bitset (&cpRegs[0xd9], 0x0f, mtrpos->options); /*----efgh*/ + + /* 0 enable/1 disable motor */ + data_bitset (&cpRegs[0xdd], 0x80, mtrpos->options >> 4); /*d------- */ + + /* next value doesn't seem to have any effect */ + data_bitset (&cpRegs[0xdd], 0x40, mtrpos->options >> 4); /*-d------*/ + + switch (mymotor->scanmotorsteptype) + { + case STT_OCT: + step_type = 8; + break; + case STT_QUART: + step_type = 4; + break; + case STT_HALF: + step_type = 2; + break; + case STT_FULL: + step_type = 1; + break; + default: + step_type = 0; + break; /* shouldn't be used */ + } + + coord_y = (mtrpos->coord_y * step_type) & 0xffff; + if (coord_y < 2) + coord_y = 2; + + /* Sets dummyline to 1 */ + data_bitset (&cpRegs[0xd6], 0xf0, 1); + + /* set step_size - 1 */ + cpRegs[0xe0] = 0; + + cpRegs[0x01] &= 0xf9; + cpRegs[0x01] |= (mtrpos->v12e448 & 1) << 2; + + /* set dummy scan */ + data_bitset (&cpRegs[0x01], 0x10, 1); /*---x----*/ + + /* set samplerate */ + data_bitset (&cpRegs[0x1cf], 0x40, PIXEL_RATE); /*-x------*/ + + /* unknown data */ + data_bitset (&cpRegs[0x1cf], 0x80, 1); /*x------- */ + + /* sets one chanel per color */ + data_bitset (&cpRegs[0x12], 0x3f, 0); /* channel */ + data_bitset (&cpRegs[0x12], 0xc0, 1); /* 1 channel */ + + /* timing cnpp */ + data_bitset (&cpRegs[0x96], 0x3f, 0x0b); /*--001011*/ + + /* set systemclock */ + data_bitset (&cpRegs[0x00], 0x0f, mymotor->systemclock); /*----xxxx*/ + + /* set last step of accurve.smearing table to 2 */ + data_lsb_set (&cpRegs[0xe4], 2, 3); + + /* set last step of deccurve.scanbufferfull table to 16 */ + data_lsb_set (&Regs[0xea], 0x10, 3); + + /* set last step of deccurve.normalscan table to 16 */ + data_lsb_set (&Regs[0xed], 0x10, 3); + + /* set last step of deccurve.smearing table to 16 */ + data_lsb_set (&Regs[0xf0], 0x10, 3); + + /* set last step of deccurve.parkhome table to 16 */ + data_lsb_set (&Regs[0xf3], 0x10, 3); + + /* set msi */ + cpRegs[0xda] = 2; + cpRegs[0xdd] &= 0xfc; + + /* set if motor has motorcurves */ + data_bitset (&cpRegs[0xdf], 0x10, + ((mymotor->motorcurve != -1) ? 1 : 0)); + + if (mymotor->motorcurve != -1) + { + struct st_curve *crv; + + /* set last step of accurve.normalscan table */ + crv = + Motorcurve_Get (dev, mymotor->motorcurve, ACC_CURVE, + CRV_NORMALSCAN); + if (crv != NULL) + data_lsb_set (&cpRegs[0xe1], crv->step[crv->step_count - 1], 3); + + DBG (DBG_FNC, " -> Setting up stepper motor using motorcurve %i\n", + mymotor->motorcurve); + v12dcf8 = Motor_Setup_Steps (dev, cpRegs, mymotor->motorcurve); + + /* set step_size - 1 */ + cpRegs[0xe0] = 0; + + crv = + Motorcurve_Get (dev, mymotor->motorcurve, DEC_CURVE, + CRV_NORMALSCAN); + if (crv != NULL) + coord_y -= (v12dcf8 + crv->step_count); + + /* set line exposure time */ + data_lsb_set (&cpRegs[0x30], mymotor->ctpc, 3); + + /* set last step of accurve.smearing table */ + data_lsb_set (&cpRegs[0xe4], 0, 3); + } + else + { + /* Setting some motor step */ + SANE_Int some_step; + + switch (Regs[0x00] & 0x0f) + { + case 0x00: + some_step = 0x00895440; + break; /* 3 x 0x2DC6C0 */ + case 0x08: + case 0x01: + some_step = 0x00b71b00; + break; /* 4 x 0x2DC6C0 */ + case 0x02: + some_step = 0x0112a880; + break; /* 6 x 0x2DC6C0 */ + case 0x0a: + case 0x03: + some_step = 0x016e3600; + break; /* 8 x 0x2DC6C0 */ + case 0x04: + some_step = 0x02255100; + break; /* 12 x 0x2DC6C0 */ + case 0x0c: + some_step = 0x02dc6c00; + break; /* 16 x 0x2DC6C0 */ + case 0x05: + some_step = 0x044aa200; + break; /* 24 x 0x2DC6C0 */ + case 0x0d: + some_step = 0x05b8d800; + break; /* 32 x 0x2DC6C0 */ + + case 0x09: + some_step = 0x00f42400; + break; + case 0x0b: + some_step = 0x01e84800; + break; /* = case 9 * 2 */ + default: + some_step = 0x0478f7f8; + break; + } + + /* divide by timing.cnpp */ + some_step /= ((cpRegs[0x96] & 0x3f) + 1); + if (mymotor->ctpc > 0) + some_step /= mymotor->ctpc; + + /* set line exposure time */ + data_lsb_set (&cpRegs[0x30], some_step, 3); + + /* set last step of accurve.normalscan table */ + data_lsb_set (&cpRegs[0xe1], some_step, 3); + } + + /* Setting coords */ + RTS_Setup_Coords (cpRegs, 100, coord_y - 1, 800, 1); + + /* enable head movement */ + data_bitset (&cpRegs[0xd8], 0x80, 1); + + /* release motor before executing */ + Motor_Release (dev); + + RTS_Warm_Reset (dev); + + /* action! */ + data = RTS_WriteRegs (dev->usb_handle, cpRegs); + if (data == OK) + RTS_Execute (dev); + + /* wait 10 seconds */ + RTS_WaitScanEnd (dev, 10000); + + rst = (data != OK) ? v12dcf8 : RTS_WaitScanEnd (dev, 20000); + + free (cpRegs); + } + + DBG (DBG_FNC, "- Motor_Move: %i\n", rst); + + return rst; +} + +static void +Free_Motormoves (struct st_device *dev) +{ + DBG (DBG_FNC, "> Free_Motormoves\n"); + + if (dev->motormove != NULL) + { + SANE_Int a; + struct st_motormove *ms; + + for (a = 0; a < dev->motormove_count; a++) + { + ms = dev->motormove[a]; + if (ms != NULL) + free (ms); + } + + free (dev->motormove); + dev->motormove = NULL; + } + + dev->motormove_count = 0; +} + +static void +Free_MotorCurves (struct st_device *dev) +{ + DBG (DBG_FNC, "> Free_MotorCurves\n"); + if (dev->mtrsetting != NULL) + Motorcurve_Free (dev->mtrsetting, &dev->mtrsetting_count); + + dev->mtrsetting = NULL; + dev->mtrsetting_count = 0; +} + +static SANE_Int +Load_MotorCurves (struct st_device *dev) +{ + SANE_Int rst = ERROR; + SANE_Int *mtc = NULL; + + if (dev->mtrsetting != NULL) + Free_MotorCurves (dev); + + DBG (DBG_FNC, "> Load_MotorCurves\n"); + + /* get motor setttings buffer for this device */ + mtc = cfg_motorcurve_get (); + if (mtc != NULL) + { + /* parse buffer to get all motorcurves */ + dev->mtrsetting = Motorcurve_Parse (&dev->mtrsetting_count, mtc); + if (dev->mtrsetting != NULL) + rst = OK; + } + + if (rst != ERROR) + { + DBG (DBG_FNC, " -> Found %i motor settings\n", dev->mtrsetting_count); + dbg_motorcurves (dev); + } + else + DBG (DBG_ERR, "- Load_MotorCurves error!!\n"); + + return rst; +} + +static SANE_Int +Load_Motormoves (struct st_device *dev) +{ + SANE_Int rst = OK; + SANE_Int a; + struct st_motormove reg, *mm; + + DBG (DBG_FNC, "> Load_Motormoves\n"); + + /* if there is already any movement loaded let's free it */ + if (dev->motormove != NULL) + Free_Motormoves (dev); + + a = 0; + while ((cfg_motormove_get (dev->sensorcfg->type, a, ®) != ERROR) + && (rst == OK)) + { + dev->motormove_count++; + dev->motormove = + (struct st_motormove **) realloc (dev->motormove, + sizeof (struct st_motormove **) * + dev->motormove_count); + if (dev->motormove != NULL) + { + mm = (struct st_motormove *) malloc (sizeof (struct st_motormove)); + if (mm != NULL) + { + memcpy (mm, ®, sizeof (struct st_motormove)); + dev->motormove[dev->motormove_count - 1] = mm; + } + else + rst = ERROR; + } + else + rst = ERROR; + + a++; + } + + if (rst == ERROR) + Free_Motormoves (dev); + + DBG (DBG_FNC, " -> Found %i motormoves\n", dev->motormove_count); + dbg_motormoves (dev); + + return rst; +} + +static SANE_Byte * +Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, SANE_Int step) +{ + steps = (SANE_Byte *) realloc (steps, sizeof (SANE_Byte) * (*bwriten + 3)); + if (steps != NULL) + { + data_msb_set (&steps[*bwriten], step, 3); + *bwriten += 3; + } + else + *bwriten = 0; + + return steps; +} + +static SANE_Int +Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs, + SANE_Int mysetting) +{ + SANE_Int varx10, cont, last_acc_step, varx20, varx2b, stepbuffer_size, + mystep, bwriten; + SANE_Int myvar, var1, myvalor, mybwriten; + struct st_curve *mycurve; + SANE_Byte *steps; + + DBG (DBG_FNC, "+ Motor_Setup_Steps(*Regs, motorsetting=%i):\n", mysetting); + + varx10 = 0; + cont = 0; + varx20 = 0; + varx2b = 0; + stepbuffer_size = (v15f8 << 4) & 0xffff; + steps = NULL; + bwriten = 0; + deccurvecount = 0; + acccurvecount = 0; + last_acc_step = 0; + + /* mycurve points to acc normalscan steps table */ + mycurve = Motorcurve_Get (dev, mysetting, ACC_CURVE, CRV_NORMALSCAN); + + if (mycurve != NULL) + { + /* acccurvecount has the number of steps in acc normalscan table */ + acccurvecount = mycurve->step_count; + + /* get last acccurve step from acc.normalscan step table */ + last_acc_step = data_lsb_get (&Regs[0xe1], 3); + + /* sets pointer to acc.normalscan step table */ + data_wide_bitset (&Regs[0xf6], 0x3fff, stepbuffer_size); + + /* Separate each step in three bytes */ + if (mycurve->step_count > 0) + for (cont = 0; cont < mycurve->step_count; cont++) + { + mystep = mycurve->step[cont]; + if (mystep <= last_acc_step) + { + acccurvecount = cont; + break; + } + varx20 += mystep + 1; + steps = Motor_AddStep (steps, &bwriten, mystep); + } + } + + if (acccurvecount == 0) + { + /* Write one step (last_acc_step + 0x01) to buffer */ + acccurvecount++; + varx20 += (last_acc_step + 1) + 1; + steps = Motor_AddStep (steps, &bwriten, last_acc_step + 1); + } + + /* write another step (last_acc_step) */ + acccurvecount++; + varx20 += last_acc_step + 1; + steps = Motor_AddStep (steps, &bwriten, last_acc_step); + + /* get line exposure time */ + myvar = data_lsb_get (&Regs[0x30], 3) + 1; + + var1 = (varx20 + myvar - 1) / myvar; + var1 = ((var1 * myvar) + mycurve->step[0] - varx20) - 0x0d; + if (steps != NULL) + data_msb_set (&steps[0], var1, 3); + + /* dec.scanbufferfull step table */ + /* set pointer to next table */ + stepbuffer_size += (acccurvecount * 3); + data_wide_bitset (&Regs[0xf8], 0x3fff, stepbuffer_size); + + /* set last step of deccurve.scanbufferfull table */ + mycurve = Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_BUFFERFULL); + deccurvecount = mycurve->step_count; + data_lsb_set (&Regs[0xea], mycurve->step[mycurve->step_count - 1], 3); + + /* write another step mycurve->step_count,cont,last_acc_step */ + deccurvecount++; + steps = Motor_AddStep (steps, &bwriten, last_acc_step); + + /* Separate each step in three bytes */ + if (mycurve->step_count > 1) + for (cont = 0; cont < (mycurve->step_count - 1); cont++) + { + mystep = mycurve->step[cont]; + if (mystep > last_acc_step) + steps = Motor_AddStep (steps, &bwriten, mystep); + else + deccurvecount--; + } + + myvalor = dev->mtrsetting[mysetting]->motorbackstep; + if (myvalor > 0) + { + SANE_Int step_size = _B0 (Regs[0xe0]) + 1; + + myvalor = ((myvalor - deccurvecount) - acccurvecount) + 2; + varx10 = myvalor; + myvalor /= step_size; + myvalor *= step_size; + var1 = mycurve->step[mycurve->step_count - 1]; /* last deccurve step */ + if (last_acc_step >= var1) + var1 = last_acc_step + 1; + deccurvecount += (varx10 - myvalor); + myvalor = varx10 - myvalor; + } + else + myvalor = varx10; + + if (myvalor > 0) + for (cont = myvalor; cont > 0; cont--) + steps = Motor_AddStep (steps, &bwriten, var1 - 1); + + /* write another step , bwriten tiene 4b */ + steps = Motor_AddStep (steps, &bwriten, var1); + + /* acc.smearing step table */ + if (Motorcurve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING) != NULL) + { + /* acc.smearing curve enabled */ + if (Motorcurve_Equal + (dev, mysetting, ACC_CURVE, CRV_SMEARING, CRV_NORMALSCAN) == TRUE) + { + /* acc.smearing pointer points to acc.normalscan table */ + data_wide_bitset (&Regs[0xfa], 0x3fff, + data_lsb_get (&Regs[0xf6], 2)); + /* last step of acc.smearing table is the same as acc.normalscan */ + data_lsb_set (&Regs[0xe4], data_lsb_get (&Regs[0xe1], 3), 3); + } + else + { + /* set pointer to next step table */ + stepbuffer_size += (deccurvecount * 3); + data_wide_bitset (&Regs[0xfa], 0x3fff, stepbuffer_size); + + /* set last step of acc.smearing table */ + mycurve = Motorcurve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING); + if (mycurve != NULL) + { + smearacccurvecount = mycurve->step_count; + data_lsb_set (&Regs[0xe4], + mycurve->step[mycurve->step_count - 1], 3); + + /* generate acc.smearing table */ + if (mycurve->step_count > 0) + for (cont = 0; cont < mycurve->step_count; cont++) + steps = + Motor_AddStep (steps, &bwriten, mycurve->step[cont]); + } + } + } + else + { + /* acc.smearing curve disabled */ + data_wide_bitset (&Regs[0xfa], 0x3fff, 0); + } + + /* dec.smearing */ + if (Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING) != NULL) + { + /* dec.smearing curve enabled */ + if (Motorcurve_Equal + (dev, mysetting, DEC_CURVE, CRV_SMEARING, CRV_BUFFERFULL) == TRUE) + { + /* dec.smearing pointer points to dec.scanbufferfull table */ + data_wide_bitset (&Regs[0x00fc], 0x3fff, + data_lsb_get (&Regs[0x00f8], 2)); + /* last step of dec.smearing table is the same as dec.scanbufferfull */ + data_lsb_set (&Regs[0x00f0], data_lsb_get (&Regs[0x00ea], 3), 3); + } + else + { + /* set pointer to next step table */ + if (mycurve != NULL) + stepbuffer_size += (mycurve->step_count * 3); + data_wide_bitset (&Regs[0xfc], 0x3fff, stepbuffer_size); + + /* set last step of dec.smearing table */ + mycurve = Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING); + if (mycurve != NULL) + { + smeardeccurvecount = mycurve->step_count; + data_lsb_set (&Regs[0xf0], + mycurve->step[mycurve->step_count - 1], 3); + + /* generate dec.smearing table */ + if (mycurve->step_count > 0) + for (cont = 0; cont < mycurve->step_count; cont++) + steps = + Motor_AddStep (steps, &bwriten, mycurve->step[cont]); + } + } + } + else + { + /* dec.smearing curve disabled */ + data_wide_bitset (&Regs[0x00fc], 0x3fff, 0); + } + + /* dec.normalscan */ + if (Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN) != NULL) + { + /* dec.normalscan enabled */ + if (Motorcurve_Equal + (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_BUFFERFULL) == TRUE) + { + /* dec.normalscan pointer points to dec.scanbufferfull table */ + data_wide_bitset (&Regs[0xfe], 0x3fff, + data_lsb_get (&Regs[0xf8], 2)); + /* last step of dec.normalscan table is the same as dec.scanbufferfull */ + data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xea], 3), 3); + } + else + if (Motorcurve_Equal + (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_SMEARING) == TRUE) + { + /* dec.normalscan pointer points to dec.smearing table */ + data_wide_bitset (&Regs[0xfe], 0x3fff, + data_lsb_get (&Regs[0xfc], 2)); + /* last step of dec.normalscan table is the same as dec.smearing */ + data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xf0], 3), 3); + } + else + { + /* set pointer to next step table */ + if (mycurve != NULL) + stepbuffer_size += (mycurve->step_count * 3); + data_wide_bitset (&Regs[0xfe], 0x3fff, stepbuffer_size); + + /* set last step of dec.normalscan table */ + mycurve = + Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN); + if (mycurve != NULL) + { + data_lsb_set (&Regs[0xed], + mycurve->step[mycurve->step_count - 1], 3); + + /* generate dec.normalscan table */ + if (mycurve->step_count > 0) + for (cont = 0; cont < mycurve->step_count; cont++) + steps = + Motor_AddStep (steps, &bwriten, mycurve->step[cont]); + } + } + } + else + { + /* dec.normalscan disabled */ + data_wide_bitset (&Regs[0xfe], 0x3fff, 0); + } + + /* acc.parkhome */ + if (Motorcurve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME) != NULL) + { + /* parkhome curve enabled */ + + if (Motorcurve_Equal + (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE) + { + /* acc.parkhome pointer points to acc.normalscan table */ + data_wide_bitset (&Regs[0x100], 0x3fff, + data_lsb_get (&Regs[0xf6], 2)); + + /* last step of acc.parkhome table is the same as acc.normalscan */ + data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe1], 3), 3); + } + else + if (Motorcurve_Equal + (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE) + { + /* acc.parkhome pointer points to acc.smearing table */ + data_wide_bitset (&Regs[0x100], 0x3fff, + data_lsb_get (&Regs[0xfa], 2)); + /* last step of acc.parkhome table is the same as acc.smearing */ + data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe4], 3), 3); + } + else + { + /* set pointer to next step table */ + if (mycurve != NULL) + stepbuffer_size += (mycurve->step_count * 3); + data_wide_bitset (&Regs[0x100], 0x3fff, stepbuffer_size); + + /* set last step of acc.parkhome table */ + mycurve = Motorcurve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME); + if (mycurve != NULL) + { + data_lsb_set (&Regs[0xe7], + mycurve->step[mycurve->step_count - 1], 3); + + /* generate acc.parkhome table */ + if (mycurve->step_count > 0) + for (cont = 0; cont < mycurve->step_count; cont++) + steps = + Motor_AddStep (steps, &bwriten, mycurve->step[cont]); + } + } + } + else + { + /* parkhome curve is disabled */ + /* acc.parkhome pointer points to 0 */ + data_wide_bitset (&Regs[0x100], 0x3fff, 0); + data_lsb_set (&Regs[0xe7], 16, 3); + } + + /* dec.parkhome */ + if (Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME) != NULL) + { + /* parkhome curve enabled */ + if (Motorcurve_Equal + (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_BUFFERFULL) == TRUE) + { + /* dec.parkhome pointer points to dec.scanbufferfull table */ + data_wide_bitset (&Regs[0x102], 0x3fff, + data_lsb_get (&Regs[0xf8], 2)); + /* last step of dec.parkhome table is the same as dec.scanbufferfull */ + data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xe4], 3), 3); + } + else + if (Motorcurve_Equal + (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE) + { + /* dec.parkhome pointer points to dec.smearing table */ + data_wide_bitset (&Regs[0x102], 0x3fff, + data_lsb_get (&Regs[0xfe], 2)); + /* last step of dec.parkhome table is the same as dec.smearing */ + data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xf0], 3), 3); + } + else + if (Motorcurve_Equal + (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE) + { + /* dec.parkhome pointer points to dec.normalscan table */ + data_wide_bitset (&Regs[0x102], 0x3fff, + data_lsb_get (&Regs[0xfe], 2)); + /* last step of dec.parkhome table is the same as dec.normalscan */ + data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xed], 3), 3); + } + else + { + /* set pointer to next step table */ + if (mycurve != NULL) + stepbuffer_size += (mycurve->step_count * 3); + data_wide_bitset (&Regs[0x102], 0x3fff, stepbuffer_size); + + /* set last step of dec.parkhome table */ + mycurve = Motorcurve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME); + if (mycurve != NULL) + { + data_lsb_set (&Regs[0xf3], + mycurve->step[mycurve->step_count - 1], 3); + + /* generate dec.parkhome table */ + if (mycurve->step_count > 0) + for (cont = 0; cont < mycurve->step_count; cont++) + steps = + Motor_AddStep (steps, &bwriten, mycurve->step[cont]); + } + } + } + else + { + /* parkhome curve is disabled */ + + /* dec.parkhome pointer points to 0 */ + data_wide_bitset (&Regs[0x102], 0x3fff, 0); + data_lsb_set (&Regs[0xf3], 16, 3); + } + + mybwriten = bwriten & 0x8000000f; + if (mybwriten < 0) + mybwriten = ((mybwriten - 1) | 0xfffffff0) + 1; + + if (mybwriten != 0) + bwriten = (((bwriten & 0xffff) >> 0x04) + 1) << 0x04; + bwriten = bwriten & 0xffff; + + /* display table */ + DBG (DBG_FNC, " -> Direction Type Offset Last step\n"); + DBG (DBG_FNC, " -> --------- -------------- ------ ---------\n"); + DBG (DBG_FNC, " -> ACC_CURVE CRV_NORMALSCAN %6i %6i\n", + data_lsb_get (&Regs[0x0f6], 2) & 0x3fff, data_lsb_get (&Regs[0x0e1], + 3)); + DBG (DBG_FNC, " -> ACC_CURVE CRV_SMEARING %6i %6i\n", + data_lsb_get (&Regs[0x0fa], 2) & 0x3fff, data_lsb_get (&Regs[0x0e4], + 3)); + DBG (DBG_FNC, " -> ACC_CURVE CRV_PARKHOME %6i %6i\n", + data_lsb_get (&Regs[0x100], 2) & 0x3fff, data_lsb_get (&Regs[0x0e7], + 3)); + DBG (DBG_FNC, " -> DEC_CURVE CRV_NORMALSCAN %6i %6i\n", + data_lsb_get (&Regs[0x0fe], 2) & 0x3fff, data_lsb_get (&Regs[0x0ed], + 3)); + DBG (DBG_FNC, " -> DEC_CURVE CRV_SMEARING %6i %6i\n", + data_lsb_get (&Regs[0x0fc], 2) & 0x3fff, data_lsb_get (&Regs[0x0f0], + 3)); + DBG (DBG_FNC, " -> DEC_CURVE CRV_PARKHOME %6i %6i\n", + data_lsb_get (&Regs[0x102], 2) & 0x3fff, data_lsb_get (&Regs[0x0f3], + 3)); + DBG (DBG_FNC, " -> DEC_CURVE CRV_BUFFERFULL %6i %6i\n", + data_lsb_get (&Regs[0x0f8], 2) & 0x3fff, data_lsb_get (&Regs[0x0ea], + 3)); + + RTS_Warm_Reset (dev); + + /* send motor steps */ + if (steps != NULL) + { + if (bwriten > 0) + { + /* lock */ + SetLock (dev->usb_handle, Regs, TRUE); + + /* send steps */ + RTS_DMA_Write (dev, 0x0000, v15f8, bwriten, steps); + + /* unlock */ + SetLock (dev->usb_handle, Regs, FALSE); + } + + free (steps); + } + + DBG (DBG_FNC, "- Motor_Setup_Steps: %i\n", acccurvecount); + + return acccurvecount; +} + +static SANE_Int +PWM_use (struct st_device *dev, SANE_Int enable) +{ + SANE_Byte a, b; + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ PWM_use(enable=%i):\n", enable); + + if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK) + { + if (Read_Byte (dev->usb_handle, 0xe9e0, &b) == OK) + { + if (enable != 0) + { + if (pwmlamplevel != 0x00) + { + b |= 0x80; + dev->init_regs[0x01e0] &= 0x3f; + dev->init_regs[0x01e0] |= 0x80; + } + else + { + a |= 0x40; + b &= 0x3f; + dev->init_regs[0x0148] |= 0x40; + dev->init_regs[0x01e0] &= 0x3f; + } + } + else + { + b &= 0x7f; + a &= 0xbf; + } + + if (Write_Byte (dev->usb_handle, 0xe948, a) == OK) + rst = Write_Byte (dev->usb_handle, 0xe9e0, b); + } + } + + DBG (DBG_FNC, "- PWM_use: %i\n", rst); + + return rst; +} + +static SANE_Int +SSCG_Enable (struct st_device *dev) +{ + SANE_Int rst; + SANE_Int sscg; + SANE_Byte data1, data2; + SANE_Int enable, mode, clock; + + DBG (DBG_FNC, "+ SSCG_Enable:\n"); + + rst = cfg_sscg_get (&enable, &mode, &clock); + + if (rst == OK) + { + if ((Read_Byte (dev->usb_handle, 0xfe3a, &data1) == OK) + && (Read_Byte (dev->usb_handle, 0xfe39, &data2) == OK)) + { + if (enable != FALSE) + { + /* clock values: 0=0.25%; 1=0.50%; 2=0.75%; 3=1.00% */ + data2 = (mode == 0) ? data2 & 0x7f : data2 | 0x80; + + sscg = (data1 & 0xf3) | (((clock & 0x03) | 0x04) << 0x02); + sscg = (sscg << 8) | data2; + } + else + sscg = ((data1 & 0xef) << 8) | _B0 (data2); + + rst = Write_Word (dev->usb_handle, 0xfe39, sscg); + } + else + rst = ERROR; + } + + DBG (DBG_FNC, "- SSCG_Enable: %i\n", rst); + + return rst; +} + +static void +RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs) +{ + /* this function sets top, midle and bottom reference voltages */ + + DBG (DBG_FNC, "> RTS_Setup_RefVoltages\n"); + + if (Regs != NULL) + { + SANE_Byte vrts, vrms, vrbs; + + cfg_refvoltages_get (dev->sensorcfg->type, &vrts, &vrms, &vrbs); + + /* Top Reference Voltage */ + data_bitset (&Regs[0x14], 0xe0, vrts); /*xxx----- */ + + /* Middle Reference Voltage */ + data_bitset (&Regs[0x15], 0xe0, vrms); /*xxx----- */ + + /* Bottom Reference Voltage */ + data_bitset (&Regs[0x16], 0xe0, vrbs); /*xxx----- */ + } +} + +static SANE_Int +Init_USBData (struct st_device *dev) +{ + SANE_Byte data; + SANE_Byte *resource; + + DBG (DBG_FNC, "+ Init_USBData:\n"); + + if (Read_Byte (dev->usb_handle, 0xf8ff, &data) != OK) + return ERROR; + + data = (data | 1); + if (Write_Byte (dev->usb_handle, 0xf8ff, data) != OK) + return ERROR; + + if (SSCG_Enable (dev) != OK) + return ERROR; + + Init_Registers (dev); + + /* Gamma table size = 0x100 */ + data_bitset (&dev->init_regs[0x1d0], 0x30, 0x00); /*--00----*/ + + /* Set 3 channels_per_dot */ + data_bitset (&dev->init_regs[0x12], 0xc0, 0x03); /*xx------ */ + + /* systemclock */ + data_bitset (&dev->init_regs[0x00], 0x0f, 0x05); /*----xxxx*/ + + /* timing cnpp */ + data_bitset (&dev->init_regs[0x96], 0x3f, 0x17); /*--xxxxxx*/ + + /* set sensor_channel_color_order */ + data_bitset (&dev->init_regs[0x60a], 0x7f, 0x24); /*-xxxxxxx*/ + + /* set crvs */ + data_bitset (&dev->init_regs[0x10], 0x1f, get_value (SCAN_PARAM, CRVS, 7, usbfile)); /*---xxxxx*/ + + /* set reference voltages */ + RTS_Setup_RefVoltages (dev, dev->init_regs); + + dev->init_regs[0x11] |= 0x10; + + data_bitset (&dev->init_regs[0x26], 0x70, 5); /*-101----*/ + + dev->init_regs[0x185] = 0x88; + dev->init_regs[0x186] = 0x88; + + /* SDRAM clock */ + data = get_value (SCAN_PARAM, MCLKIOC, 8, usbfile); + data_bitset (&dev->init_regs[0x187], 0x0f, 0x08); /*----xxxx*/ + data_bitset (&dev->init_regs[0x187], 0xf0, data); /*xxxx---- */ + + data--; + + if (data < 7) + { + switch (data) + { + case 0: + data |= 0xc0; + break; + case 1: + data |= 0xa0; + break; + case 2: + data |= 0xe0; + break; + case 3: + data |= 0x90; + break; + case 4: + data |= 0xd0; + break; + case 5: + data |= 0xb0; + break; + case 6: + data = (data & 0x0f); + break; + } + dev->init_regs[0x187] = _B0 (data); + } + + data_bitset (&dev->init_regs[0x26], 0x0f, 0); /*----0000*/ + + dev->init_regs[0x27] &= 0x3f; + dev->init_regs[0x29] = 0x24; + dev->init_regs[0x2a] = 0x10; + dev->init_regs[0x150] = 0xff; + dev->init_regs[0x151] = 0x13; + dev->init_regs[0x156] = 0xf0; + dev->init_regs[0x157] = 0xfd; + + if (dev->motorcfg->changemotorcurrent != FALSE) + Motor_Change (dev, dev->init_regs, 3); + + + dev->init_regs[0xde] = 0; + data_bitset (&dev->init_regs[0xdf], 0x0f, 0); + + /* loads motor resource for this dev */ + resource = cfg_motor_resource_get (&data); + if ((resource != NULL) && (data > 1)) + memcpy (&dev->init_regs[0x104], resource, data); + + /* this bit is set but I don't know its purpose */ + dev->init_regs[0x01] |= 0x40; /*-1------*/ + + dev->init_regs[0x124] = 0x94; + + /* release motor */ + Motor_Release (dev); + + DBG (DBG_FNC, "- Init_USBData:\n"); + + return OK; +} + +static SANE_Int +Init_Registers (struct st_device *dev) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ Init_Registers:\n"); + + /* Lee dev->init_regs */ + bzero (dev->init_regs, RT_BUFFER_LEN); + RTS_ReadRegs (dev->usb_handle, dev->init_regs); + Read_FE3E (dev, &v1619); + + if (dev->sensorcfg->type == CCD_SENSOR) + { + /* CCD sensor */ + data_bitset (&dev->init_regs[0x11], 0xc0, 0); /*xx------ */ + data_bitset (&dev->init_regs[0x146], 0x80, 1); /*x------- */ + data_bitset (&dev->init_regs[0x146], 0x40, 1); /*-x------*/ + + } + else + { + /* CIS sensor */ + data_bitset (&dev->init_regs[0x146], 0x80, 0); /*0------- */ + data_bitset (&dev->init_regs[0x146], 0x40, 0); /*-0------*/ + data_bitset (&dev->init_regs[0x11], 0xc0, 2); /*xx------ */ + data_bitset (&dev->init_regs[0xae], 0x3f, 0x14); /*--xxxxxx*/ + data_bitset (&dev->init_regs[0xaf], 0x07, 1); /*-----xxx*/ + + dev->init_regs[0x9c] = dev->init_regs[0xa2] = dev->init_regs[0xa8] = + (RTS_Debug->dev_model != UA4900) ? 1 : 0; + dev->init_regs[0x9d] = dev->init_regs[0xa3] = dev->init_regs[0xa9] = 0; + dev->init_regs[0x9e] = dev->init_regs[0xa4] = dev->init_regs[0xaa] = 0; + dev->init_regs[0x9f] = dev->init_regs[0xa5] = dev->init_regs[0xab] = 0; + dev->init_regs[0xa0] = dev->init_regs[0xa6] = dev->init_regs[0xac] = 0; + dev->init_regs[0xa1] = dev->init_regs[0xa7] = dev->init_regs[0xad] = + (RTS_Debug->dev_model != UA4900) ? 0x80 : 0; + } + + /* disable CCD channels */ + data_bitset (&dev->init_regs[0x10], 0xe0, 0); /*xxx----- */ + data_bitset (&dev->init_regs[0x13], 0x80, 0); /*x------- */ + + /* enable timer to switch off lamp */ + data_bitset (&dev->init_regs[0x146], 0x10, 1); /*---x----*/ + + /* set time to switch off lamp */ + dev->init_regs[0x147] = 0xff; + + /* set last acccurve step */ + data_lsb_set (&dev->init_regs[0xe1], 0x2af8, 3); + + /* set msi 0x02 */ + dev->init_regs[0xda] = 0x02; + data_bitset (&dev->init_regs[0xdd], 0x03, 0); /*------xx*/ + + /* set binary threshold high and low in little endian */ + data_lsb_set (&dev->init_regs[0x19e], binarythresholdl, 2); + data_lsb_set (&dev->init_regs[0x1a0], binarythresholdh, 2); + + + data_bitset (&dev->init_regs[0x01], 0x08, 0); /*----x---*/ + data_bitset (&dev->init_regs[0x16f], 0x40, 0); /*-x------*/ + dev->init_regs[0x0bf] = (dev->init_regs[0x00bf] & 0xe0) | 0x20; + dev->init_regs[0x163] = (dev->init_regs[0x0163] & 0x3f) | 0x40; + + data_bitset (&dev->init_regs[0xd6], 0x0f, 8); /*----xxxx*/ + data_bitset (&dev->init_regs[0x164], 0x80, 1); /*x------- */ + + dev->init_regs[0x0bc] = 0x00; + dev->init_regs[0x0bd] = 0x00; + + dev->init_regs[0x165] = (dev->init_regs[0x0165] & 0x3f) | 0x80; + dev->init_regs[0x0ed] = 0x10; + dev->init_regs[0x0be] = 0x00; + dev->init_regs[0x0d5] = 0x00; + + dev->init_regs[0xee] = 0x00; + dev->init_regs[0xef] = 0x00; + dev->init_regs[0xde] = 0xff; + + /* set bit[4] has_curves = 0 | bit[0..3] unknown = 0 */ + data_bitset (&dev->init_regs[0xdf], 0x10, 0); /*---x----*/ + data_bitset (&dev->init_regs[0xdf], 0x0f, 0); /*----xxxx*/ + + /* Set motor type */ + data_bitset (&dev->init_regs[0xd7], 0x80, dev->motorcfg->type); /*x------- */ + + if (dev->motorcfg->type == MT_ONCHIP_PWM) + { + data_bitset (&dev->init_regs[0x14e], 0x10, 1); /*---x----*/ + + /* set motorpwmfrequency */ + data_bitset (&dev->init_regs[0xd7], 0x3f, dev->motorcfg->pwmfrequency); /*--xxxxxx*/ + } + + dev->init_regs[0x600] &= 0xfb; + dev->init_regs[0x1d8] |= 0x08; + + v160c = 0x04; + v1610 = 0x80000; + + /* check and setup installed ram */ + RTS_DMA_CheckType (dev, dev->init_regs); + rst = RTS_DMA_WaitReady (dev, 1500); + + DBG (DBG_FNC, "- Init_Registers: %i\n", rst); + + return rst; +} + +static SANE_Int +Read_FE3E (struct st_device *dev, SANE_Byte * destino) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ Read_FE3E:\n"); + + rst = ERROR; + if (destino != NULL) + { + SANE_Byte data; + if (Read_Byte (dev->usb_handle, 0xfe3e, &data) == 0) + { + *destino = data; + rst = OK; + DBG (DBG_FNC, " -> %02x\n", _B0 (data)); + } + } + + DBG (DBG_FNC, "- Read_FE3E: %i\n", rst); + + return rst; +} + +static SANE_Int +Lamp_IsAtHome (struct st_device *dev, SANE_Byte * Regs) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ Lamp_IsAtHome:\n"); + + /* if returns TRUE, lamp is at home. Otherwise it returns FALSE */ + rst = 0; + + if (Regs != NULL) + { + SANE_Byte data; + if (Read_Byte (dev->usb_handle, 0xe96f, &data) == OK) + { + Regs[0x16f] = _B0 (data); + rst = (data >> 6) & 1; + } + } + + rst = (rst == 1) ? TRUE : FALSE; + + DBG (DBG_FNC, "- Lamp_IsAtHome: %s\n", (rst == TRUE) ? "Yes" : "No"); + + return rst; +} + +static SANE_Byte +RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs) +{ + SANE_Byte rst; + + DBG (DBG_FNC, "+ RTS_IsExecuting:\n"); + + rst = 0; + + if (Regs != NULL) + { + SANE_Byte data; + if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) + { + Regs[0x00] = data; + rst = (data >> 7) & 1; + } + } + + DBG (DBG_FNC, "- RTS_IsExecuting: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs) +{ + SANE_Byte data; + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_WaitScanEnd(msecs=%i):\n", msecs); + + /* returns 0 if ok or timeout + returns -1 if fails */ + + rst = ERROR; + + if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) + { + long ticks = GetTickCount () + msecs; + rst = OK; + while (((data & 0x80) != 0) && (ticks > GetTickCount ()) && (rst == OK)) + rst = Read_Byte (dev->usb_handle, 0xe800, &data); + } + + DBG (DBG_FNC, "- RTS_WaitScanEnd: Ending with rst=%i\n", rst); + + return rst; +} + +static SANE_Int +RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ RTS_Enable_CCD(*Regs, arg2=%i):\n", channels); + + if (Read_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4) == OK) + { + data_bitset (&Regs[0x10], 0xe0, channels); /*xxx----- */ + data_bitset (&Regs[0x13], 0x80, channels >> 3); /*x------- */ + + Write_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4); + rst = OK; + } + + DBG (DBG_FNC, "- RTS_Enable_CCD: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_Warm_Reset (struct st_device *dev) +{ + SANE_Byte data; + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_Warm_Reset:\n"); + + rst = ERROR; + if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) + { + data = (data & 0x3f) | 0x40; /*01------ */ + if (Write_Byte (dev->usb_handle, 0xe800, data) == OK) + { + data &= 0xbf; /*-0------*/ + rst = Write_Byte (dev->usb_handle, 0xe800, data); + } + } + + DBG (DBG_FNC, "- RTS_Warm_Reset: %i\n", rst); + + return rst; +} + +static SANE_Int +Lamp_SetTimer (struct st_device *dev, SANE_Int minutes) +{ + SANE_Byte MyBuffer[2]; + SANE_Int rst; + + DBG (DBG_FNC, "+ Lamp_SetTimer(minutes=%i):\n", minutes); + + MyBuffer[0] = dev->init_regs[0x0146] & 0xef; + MyBuffer[1] = dev->init_regs[0x0147]; + + if (minutes > 0) + { + double rst, op2; + + minutes = _B0 (minutes); + op2 = 2.682163611980331; + MyBuffer[0x00] |= 0x10; + rst = (minutes * op2); + MyBuffer[0x01] = (SANE_Byte) floor (rst); + } + + dev->init_regs[0x147] = MyBuffer[1]; + dev->init_regs[0x146] = + (dev->init_regs[0x146] & 0xef) | (MyBuffer[0] & 0x10); + + rst = + Write_Word (dev->usb_handle, 0xe946, + (SANE_Int) ((MyBuffer[1] << 8) + MyBuffer[0])); + + DBG (DBG_FNC, "- Lamp_SetTimer: %i\n", rst); + + return rst; +} + +static SANE_Int +Buttons_Enable (struct st_device *dev) +{ + SANE_Int data, rst; + + DBG (DBG_FNC, "+ Buttons_Enable:\n"); + + if (Read_Word (dev->usb_handle, 0xe958, &data) == OK) + { + data |= 0x0f; + rst = Write_Word (dev->usb_handle, 0xe958, data); + } + else + rst = ERROR; + + DBG (DBG_FNC, "- Buttons_Enable: %i\n", rst); + + return rst; +} + +static SANE_Int +Buttons_Count (struct st_device *dev) +{ + SANE_Int rst = 0; + + /* This chipset supports up to six buttons */ + + if (dev->buttons != NULL) + rst = dev->buttons->count; + + DBG (DBG_FNC, "> Buttons_Count: %i\n", rst); + + return rst; +} + +static SANE_Int +Buttons_Status (struct st_device *dev) +{ + SANE_Int rst = -1; + SANE_Byte data; + + DBG (DBG_FNC, "+ Buttons_Status\n"); + + /* Each bit is 1 if button is not pressed, and 0 if it is pressed + This chipset supports up to six buttons */ + + if (Read_Byte (dev->usb_handle, 0xe968, &data) == OK) + rst = _B0 (data); + + DBG (DBG_FNC, "- Buttons_Status: %i\n", rst); + + return rst; +} + +static SANE_Int +Buttons_Released (struct st_device *dev) +{ + SANE_Int rst = -1; + SANE_Byte data; + + DBG (DBG_FNC, "+ Buttons_Released\n"); + + /* Each bit is 1 if button is released, until reading this register. Then + entire register is cleared. This chipset supports up to six buttons */ + + if (Read_Byte (dev->usb_handle, 0xe96a, &data) == OK) + rst = _B0 (data); + + DBG (DBG_FNC, "- Buttons_Released: %i\n", rst); + + return rst; +} + +static SANE_Int +Buttons_Order (struct st_device *dev, SANE_Int mask) +{ + /* this is a way to order each button according to its bit in register 0xe968 */ + SANE_Int rst = -1; + + if (dev->buttons != NULL) + { + SANE_Int a; + + for (a = 0; a < 6; a++) + { + if (dev->buttons->mask[a] == mask) + { + rst = a; + break; + } + } + } + + return rst; +} + +static SANE_Int +GainOffset_Clear (struct st_device *dev) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ GainOffset_Clear:\n"); + + /* clear offsets */ + offset[CL_RED] = offset[CL_GREEN] = offset[CL_BLUE] = 0; + + /* save offsets */ + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + SANE_Int a; + + for (a = CL_RED; a <= CL_BLUE; a++) + RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (2 * a), 0); + + /* update checksum */ + rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, 0); + } + + DBG (DBG_FNC, "- GainOffset_Clear: %i\n", rst); + + return rst; +} + +static SANE_Int +Lamp_GetStatus (struct st_device *dev, SANE_Byte * flb_lamp, + SANE_Byte * tma_lamp) +{ + /* The only reason that I think windows driver uses two variables to get + which lamp is switched on instead of one variable is that some chipset + model could have both lamps switched on, so I'm maintaining such var */ + SANE_Int data1, rst; + SANE_Byte data2; + + DBG (DBG_FNC, "+ Lamp_GetStatus:\n"); + + rst = ERROR; + if (Read_Byte (dev->usb_handle, 0xe946, &data2) == OK) + { + if (Read_Word (dev->usb_handle, 0xe954, &data1) == OK) + { + rst = OK; + + *flb_lamp = 0; + *tma_lamp = 0; + + switch (dev->chipset->model) + { + case RTS8822BL_03A: + *flb_lamp = ((data2 & 0x40) != 0) ? 1 : 0; + *tma_lamp = (((data2 & 0x20) != 0) + && ((data1 & 0x10) == 1)) ? 1 : 0; + break; + default: + if ((_B1 (data1) & 0x10) == 0) + *flb_lamp = (data2 >> 6) & 1; + else + *tma_lamp = (data2 >> 6) & 1; + break; + } + } + } + + DBG (DBG_FNC, "- Lamp_GetStatus: rst=%i flb=%i tma=%i\n", rst, + _B0 (*flb_lamp), _B0 (*tma_lamp)); + + return rst; +} + +static SANE_Int +RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs) +{ + SANE_Byte data; + SANE_Int rst; + long mytime; + + DBG (DBG_FNC, "+ RTS_DMA_WaitReady(msecs=%i):\n", msecs); + + rst = OK; + mytime = GetTickCount () + msecs; + + while ((mytime > GetTickCount ()) && (rst == OK)) + { + if (Read_Byte (dev->usb_handle, 0xef09, &data) == OK) + { + if ((data & 1) == 0) + usleep (1000 * 100); + else + break; + } + else + rst = ERROR; + } + + DBG (DBG_FNC, "- RTS_DMA_WaitReady: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs) +{ + SANE_Byte data; + SANE_Int rst; + long mytime; + + DBG (DBG_FNC, "+ RTS_WaitInitEnd(msecs=%i):\n", msecs); + + rst = OK; + mytime = GetTickCount () + msecs; + + while ((mytime > GetTickCount ()) && (rst == OK)) + { + if (Read_Byte (dev->usb_handle, 0xf910, &data) == OK) + { + if ((data & 8) == 0) + usleep (1000 * 100); + else + break; + } + else + rst = ERROR; + } + + DBG (DBG_FNC, "- RTS_WaitInitEnd: %i\n", rst); + + return rst; +} + +static SANE_Int +Motor_Change (struct st_device *dev, SANE_Byte * buffer, SANE_Byte value) +{ + SANE_Int data, rst; + + DBG (DBG_FNC, "+ Motor_Change(*buffer, value=%i):\n", value); + + if (Read_Word (dev->usb_handle, 0xe954, &data) == OK) + { + data &= 0xcf; /*--00----*/ + value--; + switch (value) + { + case 2: + data |= 0x30; + break; /*--11----*/ + case 1: + data |= 0x20; + break; /*--10----*/ + case 0: + data |= 0x10; + break; /*--01----*/ + } + buffer[0x154] = _B0 (data); + + rst = Write_Byte (dev->usb_handle, 0xe954, buffer[0x154]); + } + else + rst = ERROR; + + DBG (DBG_FNC, "- Motor_Change: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int options, + SANE_Int size, SANE_Byte * buffer) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, + "+ RTS_DMA_Read(dmacs=%04x, options=%04x, size=%i., *buffer):\n", + dmacs, options, size); + + /* is there any buffer to send? */ + if ((buffer != NULL) && (size > 0)) + { + /* reset dma */ + if (RTS_DMA_Reset (dev) == OK) + { + /* prepare dma to read */ + if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == OK) + { + SANE_Int transferred; + + rst = + Bulk_Operation (dev, BLK_READ, size, buffer, &transferred); + } + } + } + + DBG (DBG_FNC, "- RTS_DMA_Read(): %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int options, + SANE_Int size, SANE_Byte * buffer) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, + "+ RTS_DMA_Write(dmacs=%04x, options=%04x, size=%i., *buffer):\n", + dmacs, options, size); + + /* is there any buffer to send? */ + if ((buffer != NULL) && (size > 0)) + { + /* reset dma */ + if (RTS_DMA_Reset (dev) == OK) + { + /* prepare dma to write */ + if (RTS_DMA_Enable_Write (dev, dmacs, size, options) == OK) + { + SANE_Int transferred; + SANE_Byte *check_buffer; + + check_buffer = (SANE_Byte *) malloc (size); + if (check_buffer != NULL) + { + /* if some transfer fails we try again until ten times */ + SANE_Int a; + for (a = 10; a > 0; a--) + { + /* send buffer */ + Bulk_Operation (dev, BLK_WRITE, size, buffer, + &transferred); + + /* prepare dma to read */ + if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == + OK) + { + SANE_Int b = 0, diff = FALSE; + + /* read buffer */ + Bulk_Operation (dev, BLK_READ, size, check_buffer, + &transferred); + + /* check buffers */ + while ((b < size) && (diff == FALSE)) + { + if (buffer[b] == check_buffer[b]) + b++; + else + diff = TRUE; + } + + /* if buffers are equal we can break loop */ + if (diff == TRUE) + { + /* cancel dma */ + RTS_DMA_Cancel (dev); + + /* prepare dma to write buffer again */ + if (RTS_DMA_Enable_Write + (dev, dmacs, size, options) != OK) + break; + } + else + { + /* everything went ok */ + rst = OK; + break; + } + } + else + break; + } + + /* free check buffer */ + free (check_buffer); + } + else + { + /* for some reason it's not posible to allocate space to check + sent buffer so we just write data */ + Bulk_Operation (dev, BLK_WRITE, size, buffer, &transferred); + rst = OK; + } + } + } + } + + DBG (DBG_FNC, "- RTS_DMA_Write(): %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs) +{ + /* This function tries to detect what kind of RAM supports chipset */ + /* Returns a value between 0 and 4. -1 means error */ + + SANE_Int rst = -1; + + DBG (DBG_FNC, "+ RTS_DMA_CheckType(*Regs):\n"); + + if (Regs != NULL) + { + SANE_Byte *out_buffer; + + /* define buffer to send */ + out_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072); + if (out_buffer != NULL) + { + SANE_Byte *in_buffer; + + /* define incoming buffer */ + in_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072); + if (in_buffer != NULL) + { + SANE_Int a, b, diff; + + /* fill outgoing buffer with a known pattern */ + b = 0; + for (a = 0; a < 2072; a++) + { + out_buffer[a] = b; + b++; + if (b == 0x61) + b = 0; + } + + /* let's send buffer with different ram types and compare + incoming buffer until getting the right type */ + + for (a = 4; a >= 0; a--) + { + /* set ram type */ + if (RTS_DMA_SetType (dev, Regs, a) != OK) + break; + + /* wait 1500 miliseconds */ + if (RTS_DMA_WaitReady (dev, 1500) == OK) + { + /* reset dma */ + RTS_DMA_Reset (dev); + + /* write buffer */ + RTS_DMA_Write (dev, 0x0004, 0x102, 2072, out_buffer); + + /* now read buffer */ + RTS_DMA_Read (dev, 0x0004, 0x102, 2072, in_buffer); + + /* check buffers */ + b = 0; + diff = FALSE; + while ((b < 2072) && (diff == FALSE)) + { + if (out_buffer[b] == in_buffer[b]) + b++; + else + diff = TRUE; + } + + /* if buffers are equal */ + if (diff == FALSE) + { + SANE_Int data = 0; + + /* buffers are equal so we've found the right ram type */ + memset (out_buffer, 0, 0x20); + for (b = 0; b < 0x20; b += 2) + out_buffer[b] = b; + + /* write buffer */ + if (RTS_DMA_Write + (dev, 0x0004, 0x0000, 0x20, out_buffer) == OK) + { + SANE_Int c = 0; + diff = TRUE; + + do + { + c++; + for (b = 1; b < 0x20; b += 2) + out_buffer[b] = c; + + if (RTS_DMA_Write + (dev, 0x0004, (_B0 (c) << 0x11) >> 0x04, + 0x20, out_buffer) == OK) + { + if (RTS_DMA_Read + (dev, 0x0004, 0x0000, 0x20, + in_buffer) == OK) + { + b = 0; + diff = FALSE; + while ((b < 0x20) + && (diff == FALSE)) + { + if (out_buffer[b] == + in_buffer[b]) + b++; + else + diff = TRUE; + } + + if (diff == FALSE) + data = c << 7; + } + } + } + while ((c < 0x80) && (diff == TRUE)); + } + + switch (data) + { + case 16384: + Regs[0x708] &= 0x1f; + Regs[0x708] |= 0x80; + break; + case 8192: + Regs[0x708] &= 0x1f; + Regs[0x708] |= 0x60; + break; + case 4096: + Regs[0x708] &= 0x1f; + Regs[0x708] |= 0x40; + break; + case 2048: + Regs[0x708] &= 0x1f; + Regs[0x708] |= 0x20; + break; + case 1024: + Regs[0x708] &= 0x1f; + data = 0x200; + break; + case 128: + Regs[0x708] &= 0x1f; + break; + } + + DBG (DBG_FNC, " -> data1 = 0x%08x\n", + (data * 4) * 1024); + DBG (DBG_FNC, " -> data2 = 0x%08x\n", data * 1024); + DBG (DBG_FNC, " -> type = 0x%04x\n", + Regs[0x708] >> 5); + + RTS_DMA_SetType (dev, Regs, Regs[0x708] >> 5); + + rst = OK; + break; + } + } + else + break; + } + + free (in_buffer); + } + + free (out_buffer); + } + } + + DBG (DBG_FNC, "- RTS_DMA_CheckType(): %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, SANE_Byte ramtype) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ RTS_DMA_SetType(*Regs, ramtype=%i):\n", ramtype); + + if (Regs != NULL) + { + data_bitset (&Regs[0x708], 0x08, 0); /*----0---*/ + + if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK) + { + data_bitset (&Regs[0x708], 0xe0, ramtype); + + if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK) + { + data_bitset (&Regs[0x708], 0x08, 1); /*----1---*/ + rst = Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]); + } + } + } + + DBG (DBG_FNC, "- RTS_DMA_SetType: %i\n", rst); + + return rst; +} + +static void +Motor_Release (struct st_device *dev) +{ + SANE_Byte data = 0; + + DBG (DBG_FNC, "+ Motor_Release:\n"); + + if (Read_Byte (dev->usb_handle, 0xe8d9, &data) == OK) + { + data |= 4; + Write_Byte (dev->usb_handle, 0xe8d9, data); + } + + DBG (DBG_FNC, "- Motor_Release:\n"); +} + +static SANE_Byte +GainOffset_LoadCount (struct st_device *dev) +{ + SANE_Byte data = 0x0f; + + DBG (DBG_FNC, "+ GainOffset_LoadCount:\n"); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x77, &data) != OK) + data = 0x0f; + + DBG (DBG_FNC, "- GainOffset_LoadCount: %i\n", _B0 (data)); + + return data; +} + +static SANE_Int +RTS_Execute (struct st_device *dev) +{ + SANE_Byte e813, e800; + SANE_Int ret; + + DBG (DBG_FNC, "+ RTS_Execute:\n"); + + e813 = 0; + e800 = 0; + ret = ERROR; + + if (Read_Byte (dev->usb_handle, 0xe800, &e800) == OK) + { + if (Read_Byte (dev->usb_handle, 0xe813, &e813) == OK) + { + e813 &= 0xbf; + if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK) + { + e800 |= 0x40; + if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK) + { + e813 |= 0x40; + if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK) + { + e800 &= 0xbf; + if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK) + { + usleep (1000 * 100); + e800 |= 0x80; + ret = Write_Byte (dev->usb_handle, 0xe800, e800); + } + } + } + } + } + } + + DBG (DBG_FNC, "- RTS_Execute: %i\n", ret); + + return ret; +} + +static SANE_Int +RTS_isTmaAttached (struct st_device *dev) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_isTmaAttached:\n"); + + /* returns 0 if Tma is attached. Otherwise 1 */ + if (Read_Word (dev->usb_handle, 0xe968, &rst) == OK) + { + rst = ((_B1 (rst) & 2) != 0) ? FALSE : TRUE; + } + else + rst = TRUE; + + DBG (DBG_FNC, "- RTS_isTmaAttached: %s\n", (rst == TRUE) ? "Yes" : "No"); + + return rst; +} + +static SANE_Int +Gamma_AllocTable (SANE_Byte * table) +{ + SANE_Int C; + SANE_Int rst = OK; + + hp_gamma->depth = 8; + + for (C = 0; C < 3; C++) + if (hp_gamma->table[C] == NULL) + hp_gamma->table[C] = malloc (sizeof (SANE_Byte) * 256); + + if ((hp_gamma->table[CL_RED] != NULL) && + (hp_gamma->table[CL_GREEN] != NULL) && + (hp_gamma->table[CL_BLUE] != NULL)) + { + /* All tables allocated */ + for (C = 0; C < 256; C++) + { + if ((table != NULL) && (RTS_Debug->EnableGamma == TRUE)) + { + /* fill gamma tables with user defined values */ + hp_gamma->table[CL_RED][C] = table[C]; + hp_gamma->table[CL_GREEN][C] = table[0x100 + C]; + hp_gamma->table[CL_BLUE][C] = table[0x200 + C]; + } + else + { + hp_gamma->table[CL_RED][C] = C; + hp_gamma->table[CL_GREEN][C] = C; + hp_gamma->table[CL_BLUE][C] = C; + } + } + + /* Locate threshold of bw */ + for (C = 0; C < 256; C++) + if (hp_gamma->table[CL_RED][C] != 0) + break; + + bw_threshold = C - 1; + } + else + { + /* Some alloc failed */ + rst = ERROR; + + Gamma_FreeTables (); + } + + DBG (DBG_FNC, "> Gamma_AllocTable: %i >> bw_threshold = %i\n", rst, + bw_threshold); + + return rst; +} + +static SANE_Int +Gamma_Apply (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, + struct st_gammatables *mygamma) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ Gamma_Apply(*Regs, *scancfg, *hwdcfg, *mygamma):\n"); + dbg_ScanParams (scancfg); + + if (hwdcfg->use_gamma_tables == FALSE) + { + DBG (DBG_FNC, "-> Gamma tables are not used\n"); + + v1600 = NULL; + v1604 = NULL; + v1608 = NULL; + } + else + { + /*390b */ + SANE_Int table_size, buffersize, c; + SANE_Byte channels, *gammabuffer; + + DBG (DBG_FNC, "-> Using gamma tables\n"); + + /* get channels count */ + channels = 3; /* default */ + + if (scancfg->colormode != CM_COLOR) + { + if (scancfg->channel != 3) + { + if (scancfg->colormode != 3) + channels = (scancfg->samplerate == PIXEL_RATE) ? 2 : 1; + } + } + + /* get size for gamma tables */ + switch (mygamma->depth & 0x0c) + { + case 0: + table_size = 0x100 + (mygamma->depth & 1); + break; + case 4: + table_size = 0x400 + (mygamma->depth & 1); + break; + case 8: + table_size = 0x1000 + (mygamma->depth & 1); + break; + default: + table_size = 2; + break; + } + + /* allocate space for gamma buffer */ + buffersize = table_size * channels; + gammabuffer = (SANE_Byte *) malloc (buffersize * sizeof (SANE_Byte)); + if (gammabuffer != NULL) + { + /* update gamma pointers for each channel */ + v1600 = (SANE_Byte *) & mygamma->table[CL_RED]; + v1604 = (SANE_Byte *) & mygamma->table[CL_GREEN]; + v1608 = (SANE_Byte *) & mygamma->table[CL_BLUE]; + + /* include gamma tables into one buffer */ + for (c = 0; c < channels; c++) + memcpy (gammabuffer + (c * table_size), mygamma->table[c], + table_size); + + /* send gamma buffer to scanner */ + Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b] & 0xaf); + rst = Gamma_SendTables (dev, Regs, gammabuffer, buffersize); + Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); + + /* free gamma buffer */ + free (gammabuffer); + } + else + rst = ERROR; + } + + return rst; +} + +static SANE_Int +Refs_Analyze_Pattern (struct st_scanparams *scancfg, + SANE_Byte * scanned_pattern, SANE_Int * ler1, + SANE_Int ler1order, SANE_Int * ser1, SANE_Int ser1order) +{ + SANE_Int a, buffersize, buffer_pos, xpos, ypos, data, rst, cnt; + double *buffer1, *buffer2, data1, mydata1, d0, d1; + SANE_Int vector[3]; + + DBG (DBG_FNC, + "+ Refs_Analyze_Pattern(depth=%i, width=%i, height=%i, *scanned_pattern, *ler1, ler1order=%i, *ser1, ser1order=%i)\n", + scancfg->depth, scancfg->coord.width, scancfg->coord.height, ler1order, + ser1order); + + buffersize = max (scancfg->coord.width, scancfg->coord.height); + + buffer1 = (double *) malloc (sizeof (double) * buffersize); + if (buffer1 == NULL) + return ERROR; + + buffer2 = (double *) malloc (sizeof (double) * buffersize); + if (buffer2 == NULL) + { + free (buffer1); + return ERROR; + } + + /*-------- 1st SER -------- */ + /* Buffers created, clear them */ + bzero (buffer1, sizeof (double) * buffersize); + bzero (buffer2, sizeof (double) * buffersize); + + buffer_pos = 0; + for (xpos = 0; xpos < scancfg->coord.width; xpos++) + { + for (a = 0; a < 20; a++) + { + data = _B0 (scanned_pattern[(scancfg->coord.width * a) + xpos]); + if (scancfg->depth > 8) + data = + ((_B0 (scanned_pattern[(scancfg->coord.width * a) + xpos + 1]) + << 8) + data) & 0xffff; + buffer1[buffer_pos] += data; + } + buffer_pos++; + } + + /* d41f */ + rst = 1; + + data1 = + (ser1order != 0) ? buffer1[0] - buffer1[1] : buffer1[1] - buffer1[0]; + buffer2[0] = data1; + + cnt = 1; /* contador */ + if ((scancfg->coord.width - 5) > 1) + { + /*d473 */ + buffer_pos = 1; + do + { + mydata1 = + (ser1order != + 0) ? buffer1[buffer_pos] - buffer1[buffer_pos + + 5] : buffer1[buffer_pos + 5] - + buffer1[buffer_pos]; + buffer2[buffer_pos] = mydata1; + + if ((mydata1 >= 0) && (mydata1 > data1)) + { + /*d4df */ + data1 = mydata1; + + d0 = abs (buffer2[rst] - buffer2[rst - 1]); + d1 = abs (buffer2[buffer_pos] - buffer2[buffer_pos - 1]); + + if (d1 > d0) + rst = cnt; + } + /*d551 */ + buffer_pos++; + cnt++; + } + while (cnt < (scancfg->coord.width - 5)); + + } + + vector[0] = rst + 5; + + if (ser1 != NULL) + { + *ser1 = rst; + DBG (DBG_FNC, "-> 1st SER=%x\n", *ser1); + } + + if (_B0 (rst) < 0x0f) + { + /* Error */ + free (buffer1); + free (buffer2); + return ERROR; + } + + /* Clear buffers again */ + bzero (buffer1, sizeof (double) * buffersize); + bzero (buffer2, sizeof (double) * buffersize); + + buffer_pos = 0; + for (ypos = 0; ypos < scancfg->coord.height; ypos++) + { + for (a = rst; a < (rst + 0x28); a++) + { + data = _B0 (scanned_pattern[(scancfg->coord.width * ypos) + a]); + if (scancfg->depth > 8) + data = + ((_B0 (scanned_pattern[(scancfg->coord.width * ypos) + a + 1]) + << 8) + data) & 0xffff; + buffer1[buffer_pos] += data; + } + buffer_pos++; + } + + rst = 1; + data1 = + (ler1order != 0) ? buffer1[0] - buffer1[1] : buffer1[1] - buffer1[0]; + buffer2[0] = data1; + cnt = 1; + if ((scancfg->coord.height - 5) > 1) + { + buffer_pos = 1; + do + { + mydata1 = + (ler1order != + 0) ? buffer1[buffer_pos] - buffer1[buffer_pos + + 5] : buffer1[buffer_pos + 5] - + buffer1[buffer_pos]; + buffer2[buffer_pos] = mydata1; + + if ((mydata1 >= 0) && (mydata1 > data1)) + { + data1 = mydata1; + + d0 = abs (buffer2[rst] - buffer2[rst - 1]); + d1 = abs (buffer2[buffer_pos] - buffer2[buffer_pos - 1]); + + if (d1 > d0) + rst = cnt; + } + buffer_pos++; + cnt++; + } + while (cnt < (scancfg->coord.height - 5)); + } + + vector[1] = rst + 5; + + if (ler1 != NULL) + { + *ler1 = rst + 5; + DBG (DBG_FNC, "> 1st LER=%x\n", *ler1); + } + + if ((rst + 5) < 0x96) + { + /* Error */ + free (buffer1); + free (buffer2); + return ERROR; + } + + /* Clear buffers again */ + bzero (buffer1, sizeof (double) * buffersize); + bzero (buffer2, sizeof (double) * buffersize); + + buffer_pos = 0; + for (xpos = 0; xpos < scancfg->coord.width; xpos++) + { + for (a = rst + 4; a < scancfg->coord.height; a++) + { + data = _B0 (scanned_pattern[(scancfg->coord.width * a) + xpos]); + if (scancfg->depth > 8) + data = + ((_B0 (scanned_pattern[(scancfg->coord.width * a) + xpos + 1]) + << 8) + data) & 0xffff; + buffer1[buffer_pos] += data; + } + buffer_pos++; + } + + data1 = + (ser1order != 0) ? buffer1[0] - buffer1[1] : buffer1[1] - buffer1[0]; + buffer2[0] = data1; + cnt = 1; + if ((scancfg->coord.width - 5) > 1) + { + buffer_pos = 1; + do + { + mydata1 = + (ser1order != + 0) ? buffer1[buffer_pos] - buffer1[buffer_pos + + 5] : buffer1[buffer_pos + 5] - + buffer1[buffer_pos]; + buffer2[buffer_pos] = mydata1; + + if ((mydata1 >= 0) && (mydata1 > data1)) + { + data1 = mydata1; + + d0 = abs (buffer2[rst] - buffer2[rst - 1]); + d1 = abs (buffer2[buffer_pos] - buffer2[buffer_pos - 1]); + + if (d1 > d0) + rst = cnt; + } + buffer_pos++; + cnt++; + } + while (cnt < (scancfg->coord.width - 5)); + + } + + rst += 5; + + vector[2] = rst; + + if (ser1 != NULL) + { + if (rst > *ser1) + { + *ser1 = rst; + DBG (DBG_FNC, "> 2nd SER=%x\n", *ser1); + } + else + { + /* Free memory */ + free (buffer1); + free (buffer2); + return ERROR; + } + } + + /* Free memory */ + free (buffer1); + free (buffer2); + + /* save image */ + if (RTS_Debug->SaveCalibFile != FALSE) + dbg_autoref (scancfg, scanned_pattern, vector[0], vector[2], vector[1]); + + DBG (DBG_FNC, "- Refs_Analyze_Pattern(*ser1=%i, *ler1=%i)\n", *ser1, *ler1); + + return OK; +} + +static double +get_shrd (double value, SANE_Int desp) +{ + if (desp <= 0x40) + return value / pow (2, desp); + else + return 0; +} + +static char +get_byte (double value) +{ + unsigned int data; + double temp; + + if (value > 0xffffffff) + { + temp = floor (get_shrd (value, 0x20)); + temp *= pow (2, 32); + value -= temp; + } + + data = (unsigned int) value; + + data = _B0 (data); + + return data; +} + +static SANE_Int +Timing_SetLinearImageSensorClock (SANE_Byte * Regs, struct st_cph *cph) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, + "+ Timing_SetLinearImageSensorClock(SANE_Byte *Regs, struct st_cph *cph)\n"); + + dbg_sensorclock (cph); + + if ((Regs != NULL) && (cph != NULL)) + { + Regs[0x00] = get_byte (cph->p1); + Regs[0x01] = get_byte (get_shrd (cph->p1, 0x08)); + Regs[0x02] = get_byte (get_shrd (cph->p1, 0x10)); + Regs[0x03] = get_byte (get_shrd (cph->p1, 0x18)); + + Regs[0x04] &= 0x80; + Regs[0x04] |= ((get_byte (get_shrd (cph->p1, 0x20))) & 0x0f); + Regs[0x04] |= ((cph->ps & 1) << 6); + Regs[0x04] |= ((cph->ge & 1) << 5); + Regs[0x04] |= ((cph->go & 1) << 4); + + Regs[0x05] = get_byte (cph->p2); + Regs[0x06] = get_byte (get_shrd (cph->p2, 0x08)); + Regs[0x07] = get_byte (get_shrd (cph->p2, 0x10)); + Regs[0x08] = get_byte (get_shrd (cph->p2, 0x18)); + Regs[0x09] &= 0xf0; + Regs[0x09] |= ((get_byte (get_shrd (cph->p2, 0x20))) & 0x0f); + + rst = OK; + } + + DBG (DBG_FNC, "- Timing_SetLinearImageSensorClock: %i\n", rst); + + return rst; +} + +static void +RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming, + SANE_Byte * Regs) +{ + DBG (DBG_FNC, "+ RTS_Setup_SensorTiming(mytiming=%i, *Regs):\n", mytiming); + + if ((Regs != NULL) && (mytiming < dev->timings_count)) + { + struct st_timing *mt = dev->timings[mytiming]; + + if (mt != NULL) + { + dbg_timing (mt); + + /* Correlated-Double-Sample 1 & 2 */ + data_bitset (&Regs[0x92], 0x3f, mt->cdss[0]); + data_bitset (&Regs[0x93], 0x3f, mt->cdsc[0]); + data_bitset (&Regs[0x94], 0x3f, mt->cdss[1]); + data_bitset (&Regs[0x95], 0x3f, mt->cdsc[1]); + + data_bitset (&Regs[0x96], 0x3f, mt->cnpp); + + /* Linear image sensor transfer gates */ + data_bitset (&Regs[0x45], 0x80, mt->cvtrp[0]); + data_bitset (&Regs[0x45], 0x40, mt->cvtrp[1]); + data_bitset (&Regs[0x45], 0x20, mt->cvtrp[2]); + + data_bitset (&Regs[0x45], 0x1f, mt->cvtrfpw); + data_bitset (&Regs[0x46], 0x1f, mt->cvtrbpw); + + data_lsb_set (&Regs[0x47], mt->cvtrw, 1); + + data_lsb_set (&Regs[0x84], mt->cphbp2s, 3); + data_lsb_set (&Regs[0x87], mt->cphbp2e, 3); + + data_lsb_set (&Regs[0x8a], mt->clamps, 3); + data_lsb_set (&Regs[0x8d], mt->clampe, 3); + + if (dev->chipset->model == RTS8822L_02A) + { + if (mt->clampe == -1) + data_lsb_set (&Regs[0x8d], mt->cphbp2e, 3); + } + + Regs[0x97] = get_byte (mt->adcclkp[0]); + Regs[0x98] = get_byte (get_shrd (mt->adcclkp[0], 0x08)); + Regs[0x99] = get_byte (get_shrd (mt->adcclkp[0], 0x10)); + Regs[0x9a] = get_byte (get_shrd (mt->adcclkp[0], 0x18)); + Regs[0x9b] &= 0xf0; + Regs[0x9b] |= ((get_byte (get_shrd (mt->adcclkp[0], 0x20))) & 0x0f); + + Regs[0xc1] = get_byte (mt->adcclkp[1]); + Regs[0xc2] = get_byte (get_shrd (mt->adcclkp[1], 0x08)); + Regs[0xc3] = get_byte (get_shrd (mt->adcclkp[1], 0x10)); + Regs[0xc4] = get_byte (get_shrd (mt->adcclkp[1], 0x18)); + Regs[0xc5] &= 0xe0; + Regs[0xc5] |= ((get_byte (get_shrd (mt->adcclkp[1], 0x20))) & 0x0f); + + /* bit(4) = bit(0) */ + Regs[0xc5] |= ((mt->adcclkp2e & 1) << 4); + + Timing_SetLinearImageSensorClock (&Regs[0x48], &mt->cph[0]); + Timing_SetLinearImageSensorClock (&Regs[0x52], &mt->cph[1]); + Timing_SetLinearImageSensorClock (&Regs[0x5c], &mt->cph[2]); + Timing_SetLinearImageSensorClock (&Regs[0x66], &mt->cph[3]); + Timing_SetLinearImageSensorClock (&Regs[0x70], &mt->cph[4]); + Timing_SetLinearImageSensorClock (&Regs[0x7a], &mt->cph[5]); + } + } +} + +static SANE_Int +Motor_GetFromResolution (SANE_Int resolution) +{ + SANE_Int ret; + + ret = 3; + if (RTS_Debug->usbtype != USB11) + { + if (scan.scantype != ST_NORMAL) + { + /* scantype is ST_NEG or ST_TA */ + if (resolution >= 600) + ret = 0; + } + else if (resolution >= 1200) + ret = 0; + } + else if (resolution >= 600) + ret = 0; + + DBG (DBG_FNC, "> Motor_GetFromResolution(resolution=%i): %i\n", resolution, + ret); + + return ret; +} + +static SANE_Int +SetMultiExposure (struct st_device *dev, SANE_Byte * Regs) +{ + SANE_Int iValue, myctpc; + + DBG (DBG_FNC, "> SetMultiExposure:\n"); + + /* set motor has no curves */ + data_bitset (&Regs[0xdf], 0x10, 0); /*---0----*/ + + /* select case systemclock */ + switch (Regs[0x00] & 0x0f) + { + case 0x00: + iValue = 0x00895440; + break; /* 3 x 0x2DC6C0 */ + case 0x08: + case 0x01: + iValue = 0x00b71b00; + break; /* 4 x 0x2DC6C0 */ + case 0x02: + iValue = 0x0112a880; + break; /* 6 x 0x2DC6C0 */ + case 0x0a: + case 0x03: + iValue = 0x016e3600; + break; /* 8 x 0x2DC6C0 */ + case 0x04: + iValue = 0x02255100; + break; /* 12 x 0x2DC6C0 */ + case 0x0c: + iValue = 0x02dc6c00; + break; /* 16 x 0x2DC6C0 */ + case 0x05: + iValue = 0x044aa200; + break; /* 24 x 0x2DC6C0 */ + case 0x0d: + iValue = 0x05b8d800; + break; /* 32 x 0x2DC6C0 */ + + case 0x09: + iValue = 0x00f42400; + break; + case 0x0b: + iValue = 0x01e84800; + break; /* = case 9 * 2 */ + default: + iValue = 0x0478f7f8; + break; + } + + /* divide by timing.cnpp */ + iValue /= ((Regs[0x96] & 0x3f) + 1); + iValue /= dev->motorcfg->basespeedpps; + + /* get line exposure time */ + myctpc = data_lsb_get (&Regs[0x30], 3) + 1; + + DBG (DBG_FNC, "CTPC -- SetMultiExposure -- 1 =%i\n", myctpc); + + /* if last step of accurve.normalscan table is lower than iValue ... */ + if (data_lsb_get (&Regs[0xe1], 3) < iValue) + { + SANE_Int traget; + SANE_Int step_size = _B0 (Regs[0xe0]) + 1; + + /* set exposure time [RED] if zero */ + if (data_lsb_get (&Regs[0x36], 3) == 0) + data_lsb_set (&Regs[0x36], myctpc - 1, 3); + + /* set exposure time [GREEN] if zero */ + if (data_lsb_get (&Regs[0x3c], 3) == 0) + data_lsb_set (&Regs[0x3c], myctpc - 1, 3); + + /* set exposure time [BLUE] if zero */ + if (data_lsb_get (&Regs[0x42], 3) == 0) + data_lsb_set (&Regs[0x42], myctpc - 1, 3); + + iValue = (iValue + 1) * step_size; + + /* update line exposure time */ + traget = (((myctpc + iValue - 1) / myctpc) * myctpc); + data_lsb_set (&Regs[0x30], traget - 1, 3); + + traget = (traget / step_size) - 1; + data_lsb_set (&Regs[0x00e1], traget, 3); + } + + /* 8300 */ + return OK; +} + +static SANE_Int +data_lsb_get (SANE_Byte * address, SANE_Int size) +{ + SANE_Int ret = 0; + if ((address != NULL) && (size > 0) && (size < 5)) + { + SANE_Int a; + SANE_Byte b; + size--; + for (a = size; a >= 0; a--) + { + b = address[a]; + ret = (ret << 8) + b; + } + } + return ret; +} + +static SANE_Byte +data_bitget (SANE_Byte * address, SANE_Int mask) +{ + SANE_Int desp = 0; + + if (mask & 1); + else if (mask & 2) + desp = 1; + else if (mask & 4) + desp = 2; + else if (mask & 8) + desp = 3; + else if (mask & 16) + desp = 4; + else if (mask & 32) + desp = 5; + else if (mask & 64) + desp = 6; + else if (mask & 128) + desp = 7; + + return (*address & mask) >> desp; +} + +static void +data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data) +{ + /* This function fills mask bits of just a byte with bits given in data */ + if (mask & 1); + else if (mask & 2) + data <<= 1; + else if (mask & 4) + data <<= 2; + else if (mask & 8) + data <<= 3; + else if (mask & 16) + data <<= 4; + else if (mask & 32) + data <<= 5; + else if (mask & 64) + data <<= 6; + else if (mask & 128) + data <<= 7; + + *address = (*address & (0xff - mask)) | (data & mask); +} + +static void +data_wide_bitset (SANE_Byte * address, SANE_Int mask, SANE_Int data) +{ + /* Setting bytes bit per bit + mask is 4 bytes size + Example: + data = 0111010111 + mask = 00000000 11111111 11000000 00000000 + rst = 00000000 01110101 11000000 00000000 */ + + SANE_Int mymask, started = FALSE; + + if ((address != NULL) && (mask != 0)) + { + while (mask != 0) + { + mymask = _B0 (mask); + + if (started == FALSE) + { + if (mymask != 0) + { + SANE_Int a, myvalue; + + for (a = 0; a < 8; a++) + if ((mymask & (1 << a)) != 0) + break; + + myvalue = _B0 (data << a); + myvalue >>= a; + data_bitset (address, mymask, myvalue); + data >>= (8 - a); + started = TRUE; + } + } + else + { + data_bitset (address, mymask, _B0 (data)); + data >>= 8; + } + + address++; + mask >>= 8; + } + } +} + + +static void +data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size) +{ + if ((address != NULL) && (size > 0) && (size < 5)) + { + SANE_Int a; + for (a = 0; a < size; a++) + { + address[a] = _B0 (data); + data >>= 8; + } + } +} + +static void +data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size) +{ + if ((address != NULL) && (size > 0) && (size < 5)) + { + SANE_Int a; + + for (a = size - 1; a >= 0; a--) + { + address[a] = _B0 (data); + data >>= 8; + } + } +} + +static SANE_Int +data_swap_endianess (SANE_Int address, SANE_Int size) +{ + SANE_Int rst = 0; + + if ((size > 0) && (size < 5)) + { + SANE_Int a; + + for (a = 0; a < size; a++) + { + rst = (rst << 8) | _B0 (address); + address >>= 8; + } + } + + return rst; +} + +static void +Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs, + SANE_Int resolution, SANE_Byte gainmode) +{ + DBG (DBG_FNC, "> Lamp_SetGainMode(*Regs, resolution=%i, gainmode=%i):\n", + resolution, gainmode); + + if (dev->chipset->model == RTS8822L_02A) + { + /* hp4370 */ + SANE_Int data1, data2; + + data1 = data_lsb_get (&Regs[0x154], 2) & 0xfe7f; + data2 = data_lsb_get (&Regs[0x156], 2); + + switch (resolution) + { + case 4800: + data2 |= 0x40; + data1 &= 0xffbf; + break; + case 100: + case 150: + case 200: + case 300: + case 600: + case 1200: + case 2400: + data1 |= 0x40; + data2 &= 0xffbf; + break; + } + + data_lsb_set (&Regs[0x154], data1, 2); + data_lsb_set (&Regs[0x156], data2, 2); + } + else + { + /* hp3970 hp4070 ua4900 */ + SANE_Int data; + + data = data_lsb_get (&Regs[0x154], 2) & 0xfe7f; + data = (gainmode == FALSE) ? data | 0x0040 : data & 0xffbf; + + switch (resolution) + { + case 100: + case 200: + case 300: + case 600: + data |= 0x0100; + break; + case 2400: + data |= 0x0180; + break; + case 1200: + if (dev->sensorcfg->type == CIS_SENSOR) + data |= 0x80; + else if (dev->sensorcfg->type == CCD_SENSOR) + data |= 0x0180; + break; + } + + data_lsb_set (&Regs[0x0154], data, 2); + } +} + +static SANE_Int +RTS_Scanner_StartScan (struct st_device *dev) +{ + SANE_Int rst; + SANE_Int data; + + DBG (DBG_FNC, "+ RTS_Scanner_StartScan():\n"); + + v14b4 = 1; /* TEMPORAL */ + data = 0; + PWM_GetDutyCycle (dev, &data); + data = _B0 (data); + + DBG (DBG_FNC, "-> Pwm used = %i\n", data); + + /* + windows driver saves pwm used, in file usbfile + Section [SCAN_PARAM], field PwmUsed + */ + + rst = Scan_Start (dev); + if (rst == OK) + { + rst = Reading_Start (dev); + RTS_ScanCounter_Inc (dev); + } + + DBG (DBG_FNC, "- RTS_Scanner_StartScan: %i\n", rst); + + return rst; +} + +static SANE_Int +Reading_Start (struct st_device *dev) +{ + /* fn66d0 */ + + SANE_Int transferred; + + DBG (DBG_FNC, "+ Reading_Start():\n"); + + if (dev->scanning->imagebuffer != NULL) + { + free (dev->scanning->imagebuffer); + dev->scanning->imagebuffer = NULL; + } + + SetLock (dev->usb_handle, NULL, (scan2.depth == 16) ? FALSE : TRUE); + + /* Reservamos los buffers necesarios para leer la imagen */ + Reading_CreateBuffers (dev); + + if (dev->Resize->type != RSZ_NONE) + Resize_Start (dev, &transferred); /* 6729 */ + + DBG (DBG_FNC, "+ Reading_Start():\n"); + + return OK; +} + +static void +Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2, + SANE_Byte * buffer, SANE_Int channels_count) +{ + /* + pPointer1 = FAB8 + pPointer2 = FABC + buffer = FAC0 + channels_count = FAC4 + */ + + SANE_Int value; + SANE_Int channel_size; + + DBG (DBG_FNC, + "> Triplet_Gray(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n", + channels_count); + + channel_size = (scan2.depth > 8) ? 2 : 1; + channels_count = channels_count / 2; + + while (channels_count > 0) + { + value = data_lsb_get (pPointer1, channel_size); + data_lsb_set (buffer, value, channel_size); + + value = data_lsb_get (pPointer2, channel_size); + data_lsb_set (buffer + channel_size, value, channel_size); + + pPointer1 += 2 * channel_size; + pPointer2 += 2 * channel_size; + buffer += 2 * channel_size; + + channels_count--; + } +} + +static void +Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2, + SANE_Byte * buffer, SANE_Int channels_count) +{ + /* Composing colour in lineart mode */ + + SANE_Int dots_count = 0; + SANE_Int channel; + SANE_Byte mask; + SANE_Byte value; + SANE_Int C; + + DBG (DBG_FNC, + "> Triplet_Lineart(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n", + channels_count); + + if (channels_count > 0) + { + dots_count = (channels_count + 1) / 2; + while (dots_count > 0) + { + mask = 0x80; + channel = 2; + do + { + value = 0; + for (C = 4; C > 0; C--) + { + value = + (value << 2) + + (((*pPointer2 & mask) << 1) | (*pPointer1 & mask)); + mask = mask >> 1; + } + *buffer = value; + buffer++; + channel--; + } + while (channel > 0); + pPointer2 += 2; + pPointer1 += 2; + dots_count--; + } + } +} + +static SANE_Int +Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, SANE_Int * transferred) +{ + /* + buffer : fadc + buffer_size : fae0 + */ + + SANE_Int lines_count = 0; /* ebp */ + SANE_Int channels_count = 0; /* fadc pisa buffer */ + SANE_Int rst = ERROR; + struct st_scanning *scn; + + DBG (DBG_FNC, + "+ Arrange_NonColour(*buffer, buffer_size=%i, *transferred):\n", + buffer_size); + + /* this is just to make code more legible */ + scn = dev->scanning; + + if (scn->imagebuffer == NULL) + { + if ((scn->arrange_hres == TRUE) || (scan2.colormode == CM_LINEART)) + { + scn->bfsize = (scn->arrange_sensor_evenodd_dist + 1) * line_size; + scn->imagebuffer = + (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte)); + if (scn->imagebuffer != NULL) + { + if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) + == OK) + { + scn->channel_size = (scan2.depth == 8) ? 1 : 2; + scn->desp1[CL_RED] = 0; + scn->desp2[CL_RED] = + scn->channel_size + + (scn->arrange_sensor_evenodd_dist * line_size); + scn->pColour2[CL_RED] = + scn->imagebuffer + scn->desp2[CL_RED]; + scn->pColour1[CL_RED] = + scn->imagebuffer + scn->desp1[CL_RED]; + rst = OK; + } + } + } + } + else + rst = OK; + + /* b0f4 */ + if (rst == OK) + { + scn->imagepointer = scn->imagebuffer; + lines_count = buffer_size / line_size; + channels_count = line_size / scn->channel_size; + while (lines_count > 0) + { + if (scan2.colormode == CM_LINEART) + Triplet_Lineart (scn->pColour1[CL_RED], scn->pColour2[CL_RED], + buffer, channels_count); + else + Triplet_Gray (scn->pColour1[CL_RED], scn->pColour2[CL_RED], + buffer, channels_count); + + buffer += line_size; + scn->arrange_size -= bytesperline; + + lines_count--; + if (lines_count == 0) + { + if ((scn->arrange_size | v15bc) == 0) + break; + } + + rst = Read_Block (dev, line_size, scn->imagepointer, transferred); + if (rst != OK) + break; + + if (scn->arrange_hres == TRUE) + { + scn->desp2[CL_RED] = + (line_size + scn->desp2[CL_RED]) % scn->bfsize; + scn->desp1[CL_RED] = + (line_size + scn->desp1[CL_RED]) % scn->bfsize; + + scn->pColour2[CL_RED] = scn->imagebuffer + scn->desp2[CL_RED]; + scn->pColour1[CL_RED] = scn->imagebuffer + scn->desp1[CL_RED]; + } + + /* b21d */ + scn->imagepointer += line_size; + if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) + scn->imagepointer = scn->imagebuffer; + } + } + + /* 2246 */ + + DBG (DBG_FNC, "- Arrange_NonColour(*transferred=%i): %i\n", *transferred, + rst); + + return rst; +} + +static SANE_Int +Resize_Decrease (SANE_Byte * to_buffer, SANE_Int to_resolution, + SANE_Int to_width, SANE_Byte * from_buffer, + SANE_Int from_resolution, SANE_Int from_width, + SANE_Int myresize_mode) +{ + /* + to_buffer = FAC8 = 0x236200 + to_resolution = FACC = 0x4b + to_width = FAD0 = 0x352 + from_buffer = FAD4 = 0x235460 + from_resolution = FAD8 = 0x64 + from_width = FADC = 0x46d + myresize_mode = FAE0 = 1 + */ + + SANE_Int rst = ERROR; + SANE_Int channels = 0; /* fac8 */ + SANE_Int depth = 0; /* fae0 */ + SANE_Int color[3] = { 0, 0, 0 }; /* fab8 | fabc | fac0 */ + SANE_Int to_pos = 0; /* fad4 */ + SANE_Int rescont = 0; + SANE_Int from_pos = 0; /* fab4 */ + SANE_Int C; + SANE_Int smres = 0; /* fab0 */ + SANE_Int value; + SANE_Int channel_size; + + to_resolution = to_resolution & 0xffff; + from_resolution = from_resolution & 0xffff; + + DBG (DBG_FNC, + "+ Resize_Decrease(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n", + to_resolution, to_width, from_resolution, from_width, myresize_mode); + + if (myresize_mode != RSZ_LINEART) + { + switch (myresize_mode) + { + case RSZ_GRAYL: + channels = 1; + depth = 8; + break; + case RSZ_COLOURL: + channels = 3; + depth = 8; + break; + case RSZ_COLOURH: + channels = 3; + depth = 16; + break; + case RSZ_GRAYH: + channels = 1; + depth = 16; + break; + } + + channel_size = (depth > 8) ? 2 : 1; + to_pos = 0; + rescont = 0; + + while (to_pos < to_width) + { + from_pos++; + if (from_pos > from_width) + from_buffer -= (((depth + 7) / 8) * channels); + + rescont += to_resolution; + if (rescont < from_resolution) + { + /* Adds 3 color channel values */ + for (C = 0; C < channels; C++) + { + color[C] += + data_lsb_get (from_buffer, channel_size) * to_resolution; + from_buffer += channel_size; + } + } + else + { + /* fc3c */ + to_pos++; + smres = to_resolution - (rescont - from_resolution); + for (C = 0; C < channels; C++) + { + value = + ((data_lsb_get (from_buffer, channel_size) * smres) + + color[C]) / from_resolution; + data_lsb_set (to_buffer, value, channel_size); + color[C] = + data_lsb_get (from_buffer, + channel_size) * (rescont - from_resolution); + + to_buffer += channel_size; + from_buffer += channel_size; + } + rescont -= from_resolution; + } + } + + rst = OK; + } + else + { + /* fd60 */ + SANE_Int bit, pos, desp, rescont2; + + *to_buffer = 0; + bit = 0; + pos = 0; + desp = 0; + rescont = 0; + rescont2 = 0; + if (to_width > 0) + { + do + { + if (bit == 8) + { + /* fda6 */ + bit = 0; + to_buffer++; + *to_buffer = 0; + } + + rescont += to_resolution; + if (rescont < from_resolution) + { + if ((*from_buffer & (0x80 >> desp)) != 0) + rescont2 += to_resolution; + } + else + { + /*fdd5 */ + pos++; + rescont -= from_resolution; + if ((*from_buffer & (0x80 >> desp)) != 0) + /*fdee */ + rescont2 += (to_resolution - rescont); + if (rescont2 > (to_resolution / 2)) + /* fe00 */ + *to_buffer = _B0 (*to_buffer | (0x80 >> bit)); + rescont2 = + ((*from_buffer & (0x80 >> desp)) != 0) ? rescont : 0; + bit++; + } + + /* fe2f */ + desp++; + if (desp == 8) + { + desp = 0; + from_buffer++; + } + } + while (pos < to_width); + } + else + rst = OK; + } + + DBG (DBG_FNC, "- Resize_Decrease: %i\n", rst); + + return rst; +} + +static SANE_Int +Resize_Increase (SANE_Byte * to_buffer, SANE_Int to_resolution, + SANE_Int to_width, SANE_Byte * from_buffer, + SANE_Int from_resolution, SANE_Int from_width, + SANE_Int myresize_mode) +{ + /* + + to_buffer = FAC8 = 0x2353f0 + to_resolution = FACC = 0x4b + to_width = FAD0 = 0x352 + from_buffer = FAD4 = 0x234650 + from_resolution = FAD8 = 0x64 + from_width = FADC = 0x46d + myresize_mode = FAE0 = 1 + */ + + SANE_Int rst = ERROR; + SANE_Int desp; /* fac0 */ + SANE_Byte *myp2; /* faac */ + SANE_Int mywidth; /* fab4 fab8 */ + SANE_Int mychannels; /* fabc */ + SANE_Int channels = 0; /* faa4 */ + SANE_Int depth = 0; /* faa8 */ + SANE_Int pos = 0; /* fae0 */ + SANE_Int rescount; + SANE_Int val6 = 0; + SANE_Int val7 = 0; + SANE_Int value; + /**/ + DBG (DBG_FNC, + "+ Resize_Increase(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n", + to_resolution, to_width, from_resolution, from_width, myresize_mode); + + if (myresize_mode != RSZ_LINEART) + { + switch (myresize_mode) + { + case RSZ_GRAYL: + channels = 1; + depth = 8; + break; + case RSZ_COLOURL: + channels = 3; + depth = 8; + break; + case RSZ_COLOURH: + channels = 3; + depth = 16; + break; + case RSZ_GRAYH: + channels = 1; + depth = 16; + break; + } + + if (channels > 0) + { + SANE_Byte channel_size; + SANE_Byte *p_dst; /* fac8 */ + SANE_Byte *p_src; /* fad4 */ + + desp = to_buffer - from_buffer; + myp2 = from_buffer; + channel_size = (depth == 8) ? 1 : 2; + + for (mychannels = 0; mychannels < channels; mychannels++) + { + pos = 0; + rescount = (from_resolution / 2) + to_resolution; + + p_src = myp2; + p_dst = myp2 + desp; + + /* f938 */ + val7 = data_lsb_get (p_src, channel_size); + + if (to_width > 0) + { + for (mywidth = 0; mywidth < to_width; mywidth++) + { + if (rescount >= to_resolution) + { + rescount -= to_resolution; + val6 = val7; + pos++; + if (pos < from_width) + { + p_src += (channels * channel_size); + val7 = data_lsb_get (p_src, channel_size); + } + } + + /*f9a5 */ + data_lsb_set (p_dst, + ((((to_resolution - rescount) * val6) + + (val7 * rescount)) / to_resolution), + channel_size); + rescount += from_resolution; + p_dst += (channels * channel_size); + } + } + + myp2 += channel_size; + } + + rst = OK; + } + else + rst = OK; + } + else + { + /* RSZ_LINEART mode */ + /* fa02 */ + /* + to_buffer = FAC8 = 0x2353f0 + to_resolution = FACC = 0x4b + to_width = FAD0 = 0x352 + from_buffer = FAD4 = 0x234650 + from_resolution = FAD8 = 0x64 + from_width = FADC = 0x46d + myresize_mode = FAE0 = 1 + */ + SANE_Int myres2; /* fac8 */ + SANE_Int sres; + SANE_Int lfae0; + SANE_Int lfad8; + SANE_Int myres; + SANE_Int cont = 1; + SANE_Int someval; + SANE_Int bit; /*lfaa8 */ + + myres2 = from_resolution; + sres = (myres2 / 2) + to_resolution; + value = _B0 (*from_buffer); + bit = 0; + lfae0 = 0; + lfad8 = value >> 7; + someval = lfad8; + *to_buffer = 0; + + if (to_width > 0) + { + myres = to_resolution; + to_resolution = myres / 2; + do + { + if (sres >= myres) + { + sres -= myres; + lfae0++; + cont++; + lfad8 = someval; + if (lfae0 < from_width) + { + if (cont == 8) + { + cont = 0; + from_buffer++; + } + bit = (((0x80 >> cont) & *from_buffer) != 0) ? 1 : 0; + } + } + /*faa6 */ + if ((((myres - sres) * lfad8) + (bit * sres)) > to_resolution) + *to_buffer |= (0x80 >> bit); + + bit++; + if (bit == 8) + { + bit = 0; + to_buffer++; + *to_buffer = 0; + } + to_width--; + sres += myres2; + } + while (to_width > 0); + rst = OK; + } + } + + DBG (DBG_FNC, "- Resize_Increase: %i\n", rst); + + return rst; +} + +static SANE_Int +Resize_Start (struct st_device *dev, SANE_Int * transferred) +{ + SANE_Int rst = ERROR; + struct st_resize *rz = dev->Resize; + + DBG (DBG_FNC, "+ Resize_Start(*transferred):\n"); + + if (Resize_CreateBuffers + (dev, line_size, rz->bytesperline, rz->bytesperline) == ERROR) + return ERROR; + + if (arrangeline2 == FIX_BY_SOFT) + { + /* fee0 */ + if (scan2.colormode == CM_COLOR) + rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); + else + rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); + } + else + rst = Read_Block (dev, line_size, rz->v3624, transferred); /* ff03 */ + + /* Redimensionado */ + switch (rz->type) + { + case RSZ_DECREASE: + /* ff1b */ + Resize_Decrease (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624, + scan2.resolution_x, rz->fromwidth, rz->mode); + break; + case RSZ_INCREASE: + /* ff69 */ + rz->rescount = 0; + Resize_Increase (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624, + scan2.resolution_x, rz->fromwidth, rz->mode); + if (arrangeline2 == FIX_BY_SOFT) + { + /* ffb1 */ + if (scan2.colormode == CM_COLOR) + rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); + else + rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); + } + else + rst = Read_Block (dev, line_size, rz->v3624, transferred); /* ffe0 */ + + /* fff2 */ + Resize_Increase (rz->v362c, rz->resolution_x, rz->towidth, rz->v3624, + scan2.resolution_x, rz->fromwidth, rz->mode); + break; + } + + /* 002a */ + + DBG (DBG_FNC, "- Resize_Start(*transferred=%i): %i\n", *transferred, rst); + + return rst; +} + +static SANE_Int +Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, SANE_Int size2, + SANE_Int size3) +{ + SANE_Int rst = ERROR; + struct st_resize *rz = dev->Resize; + + rz->v3624 = (SANE_Byte *) malloc ((size1 + 0x40) * sizeof (SANE_Byte)); + rz->v3628 = (SANE_Byte *) malloc ((size2 + 0x40) * sizeof (SANE_Byte)); + rz->v362c = (SANE_Byte *) malloc ((size3 + 0x40) * sizeof (SANE_Byte)); + + if ((rz->v3624 == NULL) || (rz->v3628 == NULL) || (rz->v362c == NULL)) + Resize_DestroyBuffers (dev); + else + rst = OK; + + DBG (DBG_FNC, "> Resize_CreateBuffers(size1=%i, size2=%i, size3=%i): %i\n", + size1, size2, size3, rst); + + return rst; +} + +static SANE_Int +Resize_DestroyBuffers (struct st_device *dev) +{ + struct st_resize *rz = dev->Resize; + + if (rz->v3624 != NULL) + free (rz->v3624); + + if (rz->v3628 != NULL) + free (rz->v3628); + + if (rz->v362c != NULL) + free (rz->v362c); + + rz->v3624 = NULL; + rz->v3628 = NULL; + rz->v362c = NULL; + + return OK; +} + +static SANE_Int +Reading_DestroyBuffers (struct st_device *dev) +{ + DBG (DBG_FNC, "> Reading_DestroyBuffers():\n"); + + if (dev->Reading->DMABuffer != NULL) + free (dev->Reading->DMABuffer); + + if (dev->scanning->imagebuffer != NULL) + { + free (dev->scanning->imagebuffer); + dev->scanning->imagebuffer = NULL; + } + + bzero (dev->Reading, sizeof (struct st_readimage)); + + return OK; +} + +static SANE_Int +Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs, + SANE_Byte * gammatable, SANE_Int size) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ Gamma_SendTables(*Regs, *gammatable, size=%i):\n", size); + + if ((gammatable != NULL) && (size > 0)) + { + SANE_Int transferred; + SANE_Int first_table; + SANE_Int cont = 0; + SANE_Int retry = TRUE; + SANE_Byte *mybuffer; + + /* lock */ + SetLock (dev->usb_handle, Regs, TRUE); + + first_table = (data_lsb_get (&Regs[0x1b4], 2) & 0x3fff) >> 4; + + mybuffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * size); + if (mybuffer != NULL) + { + /* Try to send buffer during 10 seconds */ + long tick = GetTickCount () + 10000; + while ((retry == TRUE) && (tick > GetTickCount ())) + { + retry = FALSE; + + /* Operation type 0x14 */ + if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == OK) + { + /* Send size to write */ + if (RTS_DMA_Enable_Write (dev, 0x0000, size, first_table) == + OK) + { + /* Send data */ + if (Bulk_Operation + (dev, BLK_WRITE, size, gammatable, + &transferred) == OK) + { + /* Send size to read */ + if (RTS_DMA_Enable_Read + (dev, 0x0000, size, first_table) == OK) + { + /* Retrieve data */ + if (Bulk_Operation + (dev, BLK_READ, size, mybuffer, + &transferred) == OK) + { + /* Check data */ + while ((cont < size) && (retry == FALSE)) + { + if (mybuffer[cont] != gammatable[cont]) + retry = TRUE; + cont++; + } + + if (retry == FALSE) + rst = OK; + } + } + } + } + } + } + + free (mybuffer); + } + + /* unlock */ + SetLock (dev->usb_handle, Regs, FALSE); + } + + DBG (DBG_FNC, "- Gamma_SendTables: %i\n", rst); + + return rst; +} + +static SANE_Int +Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ Gamma_GetTables(SANE_Byte *Gamma_buffer):\n"); + + if (Gamma_buffer == NULL) + return ERROR; + + /* Operation type 0x14 */ + if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == 0x00) + { + SANE_Int size = 768; + + if (RTS_DMA_Enable_Read (dev, 0x0000, size, 0) == OK) + { + SANE_Int transferred = 0; + usleep (1000 * 500); + + /* Read buffer */ + rst = + Bulk_Operation (dev, BLK_READ, size, Gamma_buffer, &transferred); + } + } + + DBG (DBG_FNC, "- Gamma_GetTables: %i\n", rst); + + return rst; +} + +static void +Gamma_FreeTables () +{ + SANE_Int c; + + DBG (DBG_FNC, "> Gamma_FreeTables()\n"); + + for (c = 0; c < 3; c++) + { + if (hp_gamma->table[c] != NULL) + { + free (hp_gamma->table[c]); + hp_gamma->table[c] = NULL; + } + } + use_gamma_tables = FALSE; +} + +static void +RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait) +{ + SANE_Byte data; + + DBG (DBG_FNC, "+ RTS_Scanner_StopScan():\n"); + + data = 0; + + Reading_DestroyBuffers (dev); + Resize_DestroyBuffers (dev); + + RTS_DMA_Reset (dev); + + data_bitset (&dev->init_regs[0x60b], 0x10, 0); + data_bitset (&dev->init_regs[0x60a], 0x40, 0); + + if (Write_Buffer (dev->usb_handle, 0xee0a, &dev->init_regs[0x60a], 2) == OK) + Motor_Change (dev, dev->init_regs, 3); + + usleep (1000 * 200); + + if (wait == FALSE) + { + Read_Byte (dev->usb_handle, 0xe801, &data); + if ((data & 0x02) == 0) + { + if (Lamp_IsAtHome (dev, dev->init_regs) == FALSE) + { + /* clear execution bit */ + data_bitset (&dev->init_regs[0x00], 0x80, 0); + + Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]); + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + } + } + } + else + { + /*66a1 */ + /* clear execution bit */ + data_bitset (&dev->init_regs[0x00], 0x80, 0); + + Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]); + if (Lamp_IsAtHome (dev, dev->init_regs) == FALSE) + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + } + + /*66e0 */ + RTS_Enable_CCD (dev, dev->init_regs, 0); + + Lamp_SetTimer (dev, 13); + + DBG (DBG_FNC, "- RTS_Scanner_StopScan()\n"); +} + +static SANE_Int +Reading_CreateBuffers (struct st_device *dev) +{ + SANE_Byte data; + SANE_Int mybytesperline; + SANE_Int mybuffersize, a, b; + + DBG (DBG_FNC, "+ Reading_CreateBuffers():\n"); + + data = 0; + + /* Gets BinarythresholdH */ + if (Read_Byte (dev->usb_handle, 0xe9a1, &data) == OK) + binarythresholdh = data; + + mybytesperline = + (scan2.depth == 12) ? (bytesperline * 3) / 4 : bytesperline; + + dev->Reading->Max_Size = 0xfc00; + dev->Reading->DMAAmount = 0; + dev->Reading->Cancel = FALSE; + + a = (RTS_Debug->dmabuffersize / 63); + b = (((RTS_Debug->dmabuffersize - a) / 2) + a) >> 0x0f; + mybuffersize = ((b << 6) - b) << 10; + if (mybuffersize < 0x1f800) + mybuffersize = 0x1f800; + + dev->Reading->DMABufferSize = mybuffersize; /*3FFC00 4193280 */ + + do + { + dev->Reading->DMABuffer = + (SANE_Byte *) malloc (dev->Reading->DMABufferSize * + sizeof (SANE_Byte)); + if (dev->Reading->DMABuffer != NULL) + break; + dev->Reading->DMABufferSize -= dev->Reading->Max_Size; + } + while (dev->Reading->DMABufferSize >= dev->Reading->Max_Size); + + /* 6003 */ + dev->Reading->Starting = TRUE; + + dev->Reading->Size4Lines = (mybytesperline > dev->Reading->Max_Size) ? + mybytesperline : (dev->Reading->Max_Size / mybytesperline) * + mybytesperline; + + dev->Reading->ImageSize = imagesize; + read_v15b4 = v15b4; + + DBG (DBG_FNC, "- Reading_CreateBuffers():\n"); + + return OK; +} + +static SANE_Int +RTS_ScanCounter_Inc (struct st_device *dev) +{ + /* Keep a count of the number of scans done by this scanner */ + + SANE_Int idata; + + DBG (DBG_FNC, "+ RTS_ScanCounter_Inc():\n"); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + SANE_Byte cdata = 0; + SANE_Byte somebuffer[26]; + + switch (dev->chipset->model) + { + case RTS8822L_02A: + case RTS8822BL_03A: + /* value is 4 bytes size starting from address 0x21 in msb format */ + if (RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata) == OK) + { + idata = data_swap_endianess (idata, 4) + 1; + idata = data_swap_endianess (idata, 4); + RTS_EEPROM_WriteInteger (dev->usb_handle, 0x21, idata); + } + break; + default: + /* value is 4 bytes size starting from address 0x21 in lsb format */ + bzero (&somebuffer, sizeof (somebuffer)); + somebuffer[4] = 0x0c; + + RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata); + data_lsb_set (&somebuffer[0], idata + 1, 4); + + RTS_EEPROM_ReadByte (dev->usb_handle, 0x003a, &cdata); + somebuffer[25] = cdata; + RTS_EEPROM_WriteBuffer (dev->usb_handle, 0x21, somebuffer, 0x1a); + break; + } + } + + DBG (DBG_FNC, "- RTS_ScanCounter_Inc()\n"); + + return OK; +} + +static SANE_Int +RTS_ScanCounter_Get (struct st_device *dev) +{ + /* Returns the number of scans done by this scanner */ + + SANE_Int idata = 0; + + DBG (DBG_FNC, "+ RTS_ScanCounter_Get():\n"); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata); + + switch (dev->chipset->model) + { + case RTS8822L_02A: + case RTS8822BL_03A: + /* value is 4 bytes size starting from address 0x21 in msb format */ + idata = data_swap_endianess (idata, 4); + break; + default: /* RTS8822L_01H */ + /* value is 4 bytes size starting from address 0x21 in lsb format */ + idata &= 0xffffffff; + break; + } + } + + DBG (DBG_FNC, "- RTS_ScanCounter_Get(): %i\n", idata); + + return idata; +} + +static SANE_Int +Read_Image (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, + SANE_Int * transferred) +{ + SANE_Int rst; + SANE_Byte mycolormode; + + DBG (DBG_FNC, "+ Read_Image(buffer_size=%i, *buffer, *transferred):\n", + buffer_size); + + *transferred = 0; + mycolormode = scan2.colormode; + rst = ERROR; + if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3)) + mycolormode = 3; + + if (dev->Resize->type == RSZ_NONE) + { + if (arrangeline == FIX_BY_SOFT) + { + switch (mycolormode) + { + case CM_COLOR: + rst = Arrange_Colour (dev, buffer, buffer_size, transferred); + break; + case 3: + rst = Arrange_Compose (dev, buffer, buffer_size, transferred); + break; + default: + rst = Arrange_NonColour (dev, buffer, buffer_size, transferred); + break; + } + } + else + rst = Read_Block (dev, buffer_size, buffer, transferred); /*00fe */ + } + else + rst = Read_ResizeBlock (dev, buffer, buffer_size, transferred); /*010d */ + + DBG (DBG_FNC, "- Read_Image(*transferred=%i): %i\n", *transferred, rst); + + return rst; +} + +static SANE_Int +Arrange_Compose (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, SANE_Int * transferred) +{ + /* + fnb250 + + 0600FA7C 05E10048 buffer + 0600FA80 0000F906 buffer_size + */ + SANE_Byte *mybuffer = buffer; /* fa7c */ + SANE_Int mydistance; /*ebp */ + SANE_Int mydots; /*fa74 */ + SANE_Int channel_size; + SANE_Int c; + struct st_scanning *scn; + + /*mywidth = fa70 */ + + DBG (DBG_FNC, "+ Arrange_Compose(*buffer, buffer_size=%i, *transferred):\n", + buffer_size); + + channel_size = (scan2.depth == 8) ? 1 : 2; + + /* this is just to make code more legible */ + scn = dev->scanning; + + if (scn->imagebuffer == NULL) + { + if (dev->sensorcfg->type == CCD_SENSOR) + mydistance = + (dev->sensorcfg->line_distance * scan2.resolution_y) / + dev->sensorcfg->resolution; + else + mydistance = 0; + + if (mydistance != 0) + { + scn->bfsize = + (scn->arrange_hres == + TRUE) ? scn->arrange_sensor_evenodd_dist : 0; + scn->bfsize = line_size * (scn->bfsize + (mydistance * 2) + 1); + } + else + scn->bfsize = line_size * 2; + + /*b2f0 */ + scn->imagebuffer = + (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte)); + if (scn->imagebuffer == NULL) + return ERROR; + + scn->imagepointer = scn->imagebuffer; + if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) == + ERROR) + return ERROR; + + /* Calculate channel displacements */ + scn->arrange_orderchannel = FALSE; + for (c = CL_RED; c <= CL_BLUE; c++) + { + if (mydistance == 0) + { + /*b34e */ + if (scn->arrange_hres == FALSE) + { + if ((((dev->sensorcfg->line_distance * scan2.resolution_y) * + 2) / dev->sensorcfg->resolution) == 1) + scn->arrange_orderchannel = TRUE; + + if (scn->arrange_orderchannel == TRUE) + scn->desp[c] = + ((dev->sensorcfg->rgb_order[c] / 2) * line_size) + + (channel_size * c); + else + scn->desp[c] = channel_size * c; + } + } + else + { + /*b3e3 */ + scn->desp[c] = + (dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) + + (channel_size * c); + + if (scn->arrange_hres == TRUE) + { + /*b43b */ + scn->desp1[c] = scn->desp[c]; + scn->desp2[c] = + ((channel_size * 3) + scn->desp1[c]) + + (scn->arrange_sensor_evenodd_dist * line_size); + }; + } + } + + for (c = CL_RED; c <= CL_BLUE; c++) + { + if (scn->arrange_hres == TRUE) + { + scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; + scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; + } + else + scn->pColour[c] = scn->imagebuffer + scn->desp[c]; + } + } + + /*b545 */ + buffer_size /= line_size; + mydots = line_size / (channel_size * 3); + + while (buffer_size > 0) + { + if (scn->arrange_orderchannel == FALSE) + { + /*b5aa */ + if (scn->arrange_hres == TRUE) + Triplet_Compose_HRes (scn->pColour1[CL_RED], + scn->pColour1[CL_GREEN], + scn->pColour1[CL_BLUE], + scn->pColour2[CL_RED], + scn->pColour2[CL_GREEN], + scn->pColour2[CL_BLUE], mybuffer, mydots); + else + Triplet_Compose_LRes (scn->pColour[CL_RED], + scn->pColour[CL_GREEN], + scn->pColour[CL_BLUE], mybuffer, mydots); + } + else + Triplet_Compose_Order (dev, scn->pColour[CL_RED], + scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], + mybuffer, mydots); + + /*b5f8 */ + mybuffer += line_size; + scn->arrange_size -= bytesperline; + if (scn->arrange_size < 0) + v15bc--; + + buffer_size--; + if (buffer_size == 0) + { + if ((scn->arrange_size | v15bc) == 0) + return OK; + } + + /*b63f */ + if (Read_Block (dev, line_size, scn->imagepointer, transferred) == + ERROR) + return ERROR; + + for (c = CL_RED; c <= CL_BLUE; c++) + { + if (scn->arrange_hres == TRUE) + { + /*b663 */ + scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize; + scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize; + + scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; + scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; + } + else + { + /*b74a */ + scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize; + scn->pColour[c] = scn->imagebuffer + scn->desp[c]; + } + } + + /*b7be */ + scn->imagepointer += line_size; + if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) + scn->imagepointer = scn->imagebuffer; + } + + return OK; +} + +static void +Triplet_Compose_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, + SANE_Byte * pBlue1, SANE_Byte * pRed2, + SANE_Byte * pGreen2, SANE_Byte * pBlue2, + SANE_Byte * buffer, SANE_Int Width) +{ + SANE_Int Value; + SANE_Int Channel_size; + SANE_Int max_value; + + DBG (DBG_FNC, + "> Triplet_Compose_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2 *pGreen2, *pBlue2, *buffer, Width=%i):\n", + Width); + + Width /= 2; + Channel_size = (scan2.depth > 8) ? 2 : 1; + max_value = (1 << scan2.depth) - 1; + + while (Width > 0) + { + Value = + data_lsb_get (pRed1, Channel_size) + data_lsb_get (pGreen1, + Channel_size) + + data_lsb_get (pBlue1, Channel_size); + + Value = min (Value, max_value); + + if (v1600 != NULL) + { + if (scan2.depth > 8) + Value = *(v1600 + (Value >> 8)) | _B0 (Value); + else + Value = *(v1600 + Value); + } + + data_lsb_set (buffer, Value, Channel_size); + buffer += Channel_size; + + Value = + data_lsb_get (pRed2, Channel_size) + data_lsb_get (pGreen2, + Channel_size) + + data_lsb_get (pBlue2, Channel_size); + + Value = min (Value, max_value); + + if (v1600 != NULL) + { + if (scan2.depth > 8) + Value = *(v1600 + (Value >> 8)) | _B0 (Value); + else + Value = *(v1600 + Value); + } + + data_lsb_set (buffer, Value, Channel_size); + buffer += Channel_size; + + pRed1 += 6 * Channel_size; + pGreen1 += 6 * Channel_size; + pBlue1 += 6 * Channel_size; + + pRed2 += 6 * Channel_size; + pGreen2 += 6 * Channel_size; + pBlue2 += 6 * Channel_size; + + Width--; + } +} + +static void +Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed, + SANE_Byte * pGreen, SANE_Byte * pBlue, + SANE_Byte * buffer, SANE_Int dots) +{ + SANE_Int Value; + + DBG (DBG_FNC, + "> Triplet_Compose_Order(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n", + dots); + + if (scan2.depth > 8) + { + /* c0fe */ + dots = dots / 2; + while (dots > 0) + { + Value = + min (data_lsb_get (pRed, 2) + data_lsb_get (pGreen, 2) + + data_lsb_get (pBlue, 2), 0xffff); + + if (v1600 != NULL) + Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value); + + data_lsb_set (buffer, Value, 2); + + buffer += 2; + pRed += 6; + pGreen += 6; + pBlue += 6; + dots--; + } + } + else + { + SANE_Byte *myp1, *myp2, *myp3; + + if (dev->sensorcfg->rgb_order[CL_RED] == 1) + { + myp1 = pRed; + myp2 = pGreen; + myp3 = pBlue; + } + else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1) + { + myp1 = pGreen; + myp2 = pRed; + myp3 = pBlue; + } + else + { + myp1 = pBlue; + myp2 = pRed; + myp3 = pGreen; + } + + while (dots > 0) + { + Value = + min (((*myp1 + *(line_size + myp1)) / 2) + *myp2 + *myp3, 0xff); + + *buffer = (v1600 == NULL) ? _B0 (Value) : *(v1600 + Value); + + buffer++; + myp1 += 3; + myp2 += 3; + myp3 += 3; + dots--; + } + } +} + +static void +Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, + SANE_Byte * buffer, SANE_Int dots) +{ + SANE_Int Value; + SANE_Int Channel_size; + SANE_Int max_value; + + DBG (DBG_FNC, + "> Triplet_Compose_LRes(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n", + dots); + + Channel_size = (scan2.depth > 8) ? 2 : 1; + max_value = (1 << scan2.depth) - 1; + + /*bf59 */ + while (dots > 0) + { + Value = + data_lsb_get (pRed, Channel_size) + data_lsb_get (pGreen, + Channel_size) + + data_lsb_get (pBlue, Channel_size); + + Value = min (Value, max_value); + + if (v1600 != NULL) + { + if (scan2.depth > 8) + Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value); + else + Value = _B0 (*(v1600 + Value)); + } + + data_lsb_set (buffer, Value, Channel_size); + + buffer += Channel_size; + pRed += Channel_size * 3; + pGreen += Channel_size * 3; + pBlue += Channel_size * 3; + dots--; + } +} + +static void +Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed, + SANE_Byte * pGreen, SANE_Byte * pBlue, + SANE_Byte * buffer, SANE_Int Width) +{ + SANE_Int Value; + + DBG (DBG_FNC, + "> Triplet_Colour_Order(*pRed, *pGreen, *pBlue, *buffer, Width=%i):\n", + Width); + + if (scan2.depth > 8) + { + Width = Width / 2; + while (Width > 0) + { + Value = data_lsb_get (pRed, 2); + data_lsb_set (buffer, Value, 2); + + Value = data_lsb_get (pGreen, 2); + data_lsb_set (buffer + 2, Value, 2); + + Value = data_lsb_get (pBlue, 2); + data_lsb_set (buffer + 4, Value, 2); + + pRed += 6; + pGreen += 6; + pBlue += 6; + buffer += 6; + Width--; + } + } + else + { + SANE_Int Colour; + + if (dev->sensorcfg->rgb_order[CL_RED] == 1) + Colour = CL_RED; + else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1) + Colour = CL_GREEN; + else + Colour = CL_BLUE; + + while (Width > 0) + { + switch (Colour) + { + case CL_RED: + *buffer = (*pRed + *(pRed + line_size)) / 2; + *(buffer + 1) = *pGreen; + *(buffer + 2) = *pBlue; + break; + case CL_GREEN: + *buffer = *pRed; + *(buffer + 1) = ((*pGreen + *(pGreen + line_size)) / 2); + *(buffer + 2) = *pBlue; + break; + case CL_BLUE: + *buffer = *pRed; + *(buffer + 1) = *pGreen; + *(buffer + 2) = ((*pBlue + *(pBlue + line_size)) / 2); + break; + } + + pRed += 3; + pGreen += 3; + pBlue += 3; + buffer += 3; + + Width--; + } + } +} + +static void +Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, + SANE_Byte * pBlue1, SANE_Byte * pRed2, + SANE_Byte * pGreen2, SANE_Byte * pBlue2, + SANE_Byte * buffer, SANE_Int Width) +{ + SANE_Int Value; + SANE_Int channel_size; + SANE_Int c; + SANE_Byte *pPointers[6]; + + pPointers[0] = pRed1; + pPointers[1] = pGreen1; + pPointers[2] = pBlue1; + + pPointers[3] = pRed2; + pPointers[4] = pGreen2; + pPointers[5] = pBlue2; + + DBG (DBG_FNC, + "> Triplet_Colour_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2, *pGreen2, *pBlue2, *buffer, Width=%i):\n", + Width); + + channel_size = (scan2.depth > 8) ? 2 : 1; + + Width = Width / 2; + while (Width > 0) + { + for (c = 0; c < 6; c++) + { + Value = data_lsb_get (pPointers[c], channel_size); + data_lsb_set (buffer, Value, channel_size); + + pPointers[c] += (6 * channel_size); + buffer += (channel_size); + } + Width--; + } +} + +static void +Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer, + SANE_Byte * pChannel1, SANE_Byte * pChannel2, + SANE_Byte * pChannel3) +{ + /* + 05F0FA4C 04EBAE4A /CALL to Assumed StdFunc6 from hpgt3970.04EBAE45 + 05F0FA50 00234FF8 |Arg1 = 00234FF8 pChannel3 + 05F0FA54 002359EF |Arg2 = 002359EF pChannel2 + 05F0FA58 002363E6 |Arg3 = 002363E6 pChannel1 + 05F0FA5C 05D10048 |Arg4 = 05D10048 Buffer + 05F0FA60 00000352 |Arg5 = 00000352 Width + */ + + /* Esta funcion une los tres canales de color en un triplete + Inicialmente cada color está separado en 3 buffers apuntados + por pChannel1 ,2 y 3 + */ + SANE_Int Value; + SANE_Int channel_size; + SANE_Int c; + SANE_Byte *pChannels[3]; + + pChannels[0] = pChannel3; + pChannels[1] = pChannel2; + pChannels[2] = pChannel1; + + DBG (DBG_FNC, "> Triplet_Colour_LRes(Width=%i, *Buffer2, *p1, *p2, *p3):\n", + Width); + + channel_size = (scan2.depth > 8) ? 2 : 1; + while (Width > 0) + { + /* ba74 */ + for (c = 0; c < 3; c++) + { + Value = data_lsb_get (pChannels[c], channel_size); + data_lsb_set (Buffer, Value, channel_size); + + pChannels[c] += channel_size; + Buffer += channel_size; + } + Width--; + } +} + +static SANE_Int +Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, SANE_Int * transferred) +{ + /* + buffer = FA7C 05E30048 + buffer_size = FA80 0000F906 + */ + + SANE_Int rst = ERROR; /* fa68 */ + SANE_Int lfa54; + SANE_Int lfa58; + SANE_Byte *pP1; /* fa5c */ + SANE_Byte *pP2; /* fa60 */ + SANE_Int bOk; + struct st_resize *rz = dev->Resize; + + /* fa74 = Resize->resolution_y */ + /* fa70 = Resize->resolution_x */ + /* fa64 = scan2.resolution_y */ + /* fa6c = scan2.resolution_x */ + + DBG (DBG_FNC, + "+ Read_ResizeBlock(*buffer, buffer_size=%i, *transferred):\n", + buffer_size); + + if (rz->type == RSZ_DECREASE) + { + lfa58 = 0; + do + { + bOk = 1; + if (arrangeline2 == FIX_BY_SOFT) + { + if (scan2.colormode == CM_COLOR) + rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); + else + rst = + Arrange_NonColour (dev, rz->v3624, line_size, transferred); + } + else + rst = Read_Block (dev, line_size, rz->v3624, transferred); + + /*f2df */ + Resize_Decrease (rz->v362c, rz->resolution_x, rz->towidth, + rz->v3624, scan2.resolution_x, rz->fromwidth, + rz->mode); + rz->rescount += rz->resolution_y; + + if (rz->rescount > scan2.resolution_y) + { + /*f331 */ + rz->rescount -= scan2.resolution_y; + if (scan2.depth == 8) + { + /* f345 */ + pP1 = rz->v3628; + pP2 = rz->v362c; + if (rz->mode == RSZ_LINEART) + { + /* f36b */ + SANE_Int bit = 0; + SANE_Byte *pP3 = rz->v362c; + SANE_Int value; + + *buffer = 0; + lfa54 = 0; + while (lfa54 < rz->towidth) + { + if (bit == 8) + { + buffer++; + *buffer = 0; + pP1++; + bit = 0; + pP3++; + } + + value = + ((*pP1 & (0x80 >> bit)) != 0) ? rz->rescount : 0; + + if ((*pP3 & (0x80 >> bit)) != 0) + value += (scan2.resolution_y - rz->rescount); + + if (value > rz->resolution_y) + *buffer |= (0x80 >> bit); + + bit++; + lfa54++; + } + } + else + { + /* f414 */ + lfa54 = 0; + while (lfa54 < rz->bytesperline) + { + *buffer = + _B0 ((((scan2.resolution_y - + rz->rescount) * *pP2) + + (*pP1 * rz->rescount)) / + scan2.resolution_y); + pP1++; + pP2++; + buffer++; + lfa54++; + } + } + } + else + { + /* f47d */ + lfa54 = 0; + pP1 = rz->v3628; + pP2 = rz->v362c; + + if ((rz->bytesperline & 0xfffffffe) > 0) + { + SANE_Int value; + do + { + value = + (((scan2.resolution_y - + rz->rescount) * data_lsb_get (pP2, + 2)) + + (data_lsb_get (pP1, 2) * rz->rescount)) / + scan2.resolution_y; + data_lsb_set (buffer, value, 2); + + buffer += 2; + pP1 += 2; + pP2 += 2; + lfa54++; + } + while (lfa54 < (rz->bytesperline / 2)); + } + } + } + else + bOk = 0; + /* f4fd f502 */ + pP1 = rz->v3628; + /* swap pointers */ + rz->v3628 = rz->v362c; + rz->v362c = pP1; + } + while (bOk == 0); + } + else + { + /*f530 */ + SANE_Int lfa68; + SANE_Int transferred; + SANE_Int channel_size; + + rz->rescount += scan2.resolution_y; + lfa58 = 0; + if (rz->rescount > rz->resolution_y) + { + lfa68 = 1; + rz->rescount -= rz->resolution_y; + } + else + lfa68 = 0; + + pP1 = rz->v3628; + pP2 = rz->v362c; + + if (rz->mode == RSZ_LINEART) + { + /*f592 */ + *buffer = 0; + + if (rz->towidth > 0) + { + SANE_Int mask, mres; + /* lfa60 = rz->resolution_y */ + /* lfa7c = rz->resolution_y / 2 */ + + for (lfa54 = 0; lfa54 < rz->towidth; lfa54++) + { + mask = 0x80 >> lfa58; + + mres = ((mask & *pP1) != 0) ? rz->rescount : 0; + + if ((mask & *pP2) != 0) + mres += (rz->resolution_y - rz->rescount); + + if (mres > (rz->resolution_y / 2)) + *buffer = *buffer | mask; + + lfa58++; + if (lfa58 == 8) + { + lfa58 = 0; + buffer++; + pP1++; + pP2++; + *buffer = 0; + } + } + } + } + else + { + /*f633 */ + channel_size = (scan2.depth > 8) ? 2 : 1; + + if (rz->rescount < scan2.resolution_y) + { + if (rz->bytesperline != 0) + { + SANE_Int value; + + for (lfa54 = 0; lfa54 < rz->bytesperline; lfa54++) + { + value = + (((scan2.resolution_y - + rz->rescount) * data_lsb_get (pP2, + channel_size)) + + (rz->rescount * data_lsb_get (pP1, channel_size))) / + scan2.resolution_y; + data_lsb_set (buffer, value, channel_size); + + pP1 += channel_size; + pP2 += channel_size; + buffer += channel_size; + } + } + } + else + memcpy (buffer, rz->v3628, rz->bytesperline); /*f6a8 */ + } + + /*f736 */ + if (lfa68 != 0) + { + SANE_Byte *temp; + + if (arrangeline2 == FIX_BY_SOFT) + { + /*f74b */ + if (scan2.colormode == CM_COLOR) + rst = + Arrange_Colour (dev, rz->v3624, line_size, &transferred); + else + rst = + Arrange_NonColour (dev, rz->v3624, line_size, &transferred); + } + else + rst = Read_Block (dev, line_size, rz->v3624, &transferred); /*f77a */ + + /*f78c */ + /* swap buffers */ + temp = rz->v3628; + rz->v3628 = rz->v362c; + rz->v362c = temp; + + Resize_Increase (temp, rz->resolution_x, rz->towidth, rz->v3624, + scan2.resolution_x, rz->fromwidth, rz->mode); + } + else + rst = OK; + } + + DBG (DBG_FNC, "- Read_ResizeBlock(*transferred=%i): %i\n", *transferred, + rst); + + return rst; +} + +static void +Split_into_12bit_channels (SANE_Byte * destino, SANE_Byte * fuente, + SANE_Int size) +{ + /* + Each letter represents a bit + abcdefgh 12345678 lmnopqrs << before splitting + [efgh1234 0000abcd] [lmnopqrs 00005678] << after splitting, in memory + [0000abcd efgh1234] [00005678 lmnopqrs] << resulting channels + */ + + DBG (DBG_FNC, "> Split_into_12bit_channels(*destino, *fuente, size=%i\n", + size); + + if ((destino != NULL) && (fuente != NULL)) + { + if ((size - (size & 0x03)) != 0) + { + SANE_Int C; + + C = (size - (size & 0x03) + 3) / 4; + do + { + *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4)); + *(destino + 1) = _B0 (*fuente >> 4); + *(destino + 2) = _B0 (*(fuente + 2)); + *(destino + 3) = *(fuente + 1) & 0x0f; + destino += 4; + fuente += 3; + C--; + } + while (C > 0); + } + + /**/ if ((size & 0x03) != 0) + { + *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4)); + *(destino + 1) = _B0 (*fuente >> 4); + } + } +} + +static SANE_Int +Read_NonColor_Block (struct st_device *dev, SANE_Byte * buffer, + SANE_Int buffer_size, SANE_Byte ColorMode, + SANE_Int * transferred) +{ + /* FA50 05DA0048 buffer + FA54 0000F906 buffer_size + FA58 00 ColorMode + */ + + SANE_Int rst = OK; + SANE_Int lfa38 = 0; + SANE_Byte *gamma = v1600; + SANE_Int block_bytes_per_line; + SANE_Int mysize; + SANE_Byte *mybuffer; + char sdebug[20]; + + DBG (DBG_FNC, + "+ Read_NonColor_Block(*buffer, buffer_size=%i, ColorMode=%s):\n", + buffer_size, dbg_colour (sdebug, ColorMode)); + + if (ColorMode != CM_GRAY) + { + /* Lineart mode */ + if ((lineart_width & 7) != 0) + lfa38 = 8 - (lineart_width & 7); + block_bytes_per_line = (lineart_width + 7) / 8; + } + else + block_bytes_per_line = line_size; + /*61b2 */ + + mysize = (buffer_size / block_bytes_per_line) * bytesperline; + mybuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte)); /*fa40 */ + + if (mybuffer != NULL) + { + SANE_Int LinesCount; + SANE_Int mysize4lines; + SANE_Byte *pBuffer = buffer; + SANE_Byte *pImage = NULL; /* fa30 */ + SANE_Int puntero; + SANE_Int value; + + do + { + mysize4lines = + (mysize <= + dev->Reading->Size4Lines) ? mysize : dev->Reading->Size4Lines; + LinesCount = mysize4lines / bytesperline; + + if (ColorMode == CM_GRAY) + { + if (scan2.depth == 12) + { + /* 633b */ + /*GRAY Bit mode 12 */ + rst = + Scan_Read_BufferA (dev, (mysize4lines * 3) / 4, 0, + mybuffer, transferred); + if (rst == OK) + { + pImage = mybuffer; + pBuffer += LinesCount * block_bytes_per_line; + while (LinesCount > 0) + { + Split_into_12bit_channels (mybuffer, pImage, + line_size); + pImage += (bytesperline * 3) / 4; + LinesCount--; + } + } + else + break; + } + else + { + /* grayscale 8 and 16 bits */ + + SANE_Int channel_size; + + rst = + Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer, + transferred); + + if (rst == OK) + { + channel_size = (scan2.depth > 8) ? 2 : 1; + + pImage = mybuffer; + + /* No gamma tables */ + while (LinesCount > 0) + { + if (line_size > 0) + { + puntero = 0; + do + { + value = + data_lsb_get (pImage + puntero, + channel_size); + + if (gamma != NULL) + value += + *gamma << (8 * (channel_size - 1)); + + data_lsb_set (pBuffer, value, channel_size); + + pBuffer += channel_size; + puntero += channel_size; + } + while (puntero < line_size); + } + pImage += bytesperline; + LinesCount--; + } + } + else + break; + } + } + else + { + /*6429 */ + /* LINEART */ + SANE_Int desp; + rst = + Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer, + transferred); + if (rst == OK) + { + pImage = mybuffer; + while (LinesCount > 0) + { + if (lineart_width > 0) + { + desp = 0; + do + { + if ((desp % 7) == 0) + *pBuffer = 0; + + /* making a byte bit per bit */ + *pBuffer = *pBuffer << 1; + + /* bit 1 if data is under thresholdh value */ + if (*(pImage + desp) >= binarythresholdh) /* binarythresholdh = 0x0c */ + *pBuffer = *pBuffer | 1; + + desp++; + if ((desp % 7) == 0) + pBuffer++; + + } + while (desp < lineart_width); + } + + if (lfa38 != 0) + { + *pBuffer = (*pBuffer << lfa38); + pBuffer++; + } + /* 64b0 */ + pImage += bytesperline; + LinesCount--; + } + } + else + break; + } + /* 64c0 */ + mysize -= mysize4lines; + } + while ((mysize > 0) && (dev->Reading->Cancel == FALSE)); + + free (mybuffer); + } + else + rst = ERROR; + + DBG (DBG_FNC, "- Read_NonColor_Block(*transferred=%i): %i\n", *transferred, + rst); + + return rst; +} + +static SANE_Int +Read_Block (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, + SANE_Int * transferred) +{ + /* + SANE_Int buffer_size fa80 + SANE_Byte *buffer fa7c + */ +/* +scan2: +04F0155C 01 08 00 02 03 00 58 02 ..X +04F01564 58 02 58 02 C5 00 00 00 XXÅ... +04F0156C B4 07 00 00 8B 01 00 00 ´..‹.. +04F01574 10 06 00 00 EC 13 00 00 ..ì.. +04F0157C B2 07 00 00 B4 07 00 00 ²..´.. +04F01584 CF 08 00 00 Ï.. + +arrangeline2 = 1 +*/ + SANE_Int rst, LinesCount; + SANE_Int mysize; + SANE_Byte *readbuffer = NULL; + SANE_Byte *pImage = NULL; + + DBG (DBG_FNC, "+ Read_Block(buffer_size=%i, *buffer):\n", buffer_size); + + rst = ERROR; + *transferred = 0; + + if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3) + && (arrangeline2 != FIX_BY_SOFT)) + { + /*6510 */ + return Read_NonColor_Block (dev, buffer, buffer_size, scan2.colormode, + transferred); + } + + /*6544 */ + mysize = (buffer_size / line_size) * bytesperline; + readbuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte)); + pImage = buffer; + + if (readbuffer != NULL) + { + do + { + buffer_size = + (dev->Reading->Size4Lines < + mysize) ? dev->Reading->Size4Lines : mysize; + LinesCount = buffer_size / bytesperline; + + if (scan2.depth == 12) + { + rst = + Scan_Read_BufferA (dev, buffer_size, 0, readbuffer, + transferred); + if (rst == OK) + { + if (LinesCount > 0) + { + SANE_Byte *destino, *fuente; + destino = buffer; + fuente = readbuffer; + do + { + Split_into_12bit_channels (destino, fuente, + line_size); + destino += line_size; + fuente += (bytesperline * 3) / 4; + LinesCount--; + } + while (LinesCount > 0); + } + } + else + break; + } + else + { + /*65d9 */ + rst = + Scan_Read_BufferA (dev, buffer_size, 0, readbuffer, + transferred); + if (rst == OK) + { + memcpy (pImage, readbuffer, *transferred); + + /* apply white shading correction */ + if ((RTS_Debug->wshading == TRUE) + && (scan2.scantype == ST_NORMAL)) + WShading_Emulate (pImage, &wshading->ptr, *transferred, + scan2.depth); + + pImage += *transferred; + } + else + break; + } + /*6629 */ + mysize -= buffer_size; + } + while ((mysize > 0) && (dev->Reading->Cancel == FALSE)); + + free (readbuffer); + } + + DBG (DBG_FNC, "- Read_Block(*transferred=%i): %i\n", *transferred, rst); + + return rst; +} + +static SANE_Int +Scan_Read_BufferA (struct st_device *dev, SANE_Int buffer_size, SANE_Int arg2, + SANE_Byte * pBuffer, SANE_Int * bytes_transfered) +{ + SANE_Int rst = OK; + SANE_Byte *ptBuffer = NULL; + SANE_Byte *ptImg = NULL; + struct st_readimage *rd = dev->Reading; + + DBG (DBG_FNC, + "+ Scan_Read_BufferA(buffer_size=%i, arg2, *pBuffer, *bytes_transfered):\n", + buffer_size); + + arg2 = arg2; /* silence gcc */ + *bytes_transfered = 0; + + if (pBuffer != NULL) + { + ptBuffer = pBuffer; + + while ((buffer_size > 0) && (rst == OK) && (rd->Cancel == FALSE)) + { + /* Check if we've already started */ + if (rd->Starting == TRUE) + { + /* Get channels per dot and channel's size in bytes */ + SANE_Byte data; + + rd->Channels_per_dot = 1; + if (Read_Byte (dev->usb_handle, 0xe812, &data) == OK) + { + data = data >> 6; + if (data != 0) + rd->Channels_per_dot = data; + } + + rd->Channel_size = 1; + if (Read_Byte (dev->usb_handle, 0xee0b, &data) == OK) + if (((data & 0x40) != 0) && ((data & 0x08) == 0)) + rd->Channel_size = 2; + + rd->RDStart = rd->DMABuffer; + rd->RDSize = 0; + rd->DMAAmount = 0; + rd->Starting = FALSE; + } + + /* Is there any data to read from scanner? */ + if ((rd->ImageSize > 0) && (rd->RDSize == 0)) + { + /* Try to read from scanner all possible data to fill DMABuffer */ + if (rd->RDSize < rd->DMABufferSize) + { + SANE_Int iAmount, dofree; + + /* Check if we have already notify buffer size */ + if (rd->DMAAmount <= 0) + { + /* Initially I suppose that I can read all image */ + iAmount = min (rd->ImageSize, rd->Max_Size); + rd->DMAAmount = + ((RTS_Debug->dmasetlength * 2) / iAmount) * iAmount; + rd->DMAAmount = min (rd->DMAAmount, rd->ImageSize); + Reading_NotifySize (dev, 0, rd->DMAAmount); + iAmount = min (iAmount, rd->DMABufferSize - rd->RDSize); + } + else + { + iAmount = min (rd->DMAAmount, rd->ImageSize); + iAmount = min (iAmount, rd->Max_Size); + } + + /* Allocate buffer to read image if it's necessary */ + if ((rd->RDSize == 0) && (iAmount <= buffer_size)) + { + ptImg = ptBuffer; + dofree = FALSE; + } + else + { + ptImg = + (SANE_Byte *) malloc (iAmount * sizeof (SANE_Byte)); + dofree = TRUE; + } + + if (ptImg != NULL) + { + /* We must wait for scanner to get data */ + SANE_Int opStatus, sc; + + sc = (iAmount < rd->Max_Size) ? TRUE : FALSE; + opStatus = Reading_Wait (dev, rd->Channels_per_dot, + rd->Channel_size, + iAmount, + &rd->Bytes_Available, 90, sc); + + /* If something fails, perhaps we can read some bytes... */ + if (opStatus != OK) + { + if (rd->Bytes_Available > 0) + iAmount = rd->Bytes_Available; + else + rst = ERROR; + } + + if (rst == OK) + { + /* Try to read from scanner */ + SANE_Int transferred = 0; + opStatus = + Bulk_Operation (dev, BLK_READ, iAmount, ptImg, + &transferred); + + DBG (DBG_FNC, + "> Scan_Read_BufferA: Bulk read %i bytes\n", + transferred); + + /*if something fails may be we can read some bytes */ + iAmount = (SANE_Int) transferred; + if (iAmount != 0) + { + /* Lets copy data into DMABuffer if it's necessary */ + if (ptImg != ptBuffer) + { + SANE_Byte *ptDMABuffer; + + ptDMABuffer = rd->RDStart + rd->RDSize; + if ((ptDMABuffer - rd->DMABuffer) >= + rd->DMABufferSize) + ptDMABuffer -= rd->DMABufferSize; + + if ((ptDMABuffer + iAmount) >= + (rd->DMABuffer + rd->DMABufferSize)) + { + SANE_Int rest = + iAmount - (rd->DMABufferSize - + (ptDMABuffer - + rd->DMABuffer)); + memcpy (ptDMABuffer, ptImg, + iAmount - rest); + memcpy (rd->DMABuffer, + ptImg + (iAmount - rest), rest); + } + else + memcpy (ptDMABuffer, ptImg, iAmount); + rd->RDSize += iAmount; + } + else + { + *bytes_transfered += iAmount; + buffer_size -= iAmount; + } + + rd->DMAAmount -= iAmount; + rd->ImageSize -= iAmount; + } + else + rst = ERROR; + } + + /* Lets free buffer */ + if (dofree == TRUE) + { + free (ptImg); + ptImg = NULL; + } + } + else + rst = ERROR; + } + } + + /* is there any data read from scanner? */ + if (rd->RDSize > 0) + { + /* Add to the given buffer so many bytes as posible */ + SANE_Int iAmount; + + iAmount = min (buffer_size, rd->RDSize); + if ((rd->RDStart + iAmount) >= + (rd->DMABuffer + rd->DMABufferSize)) + { + SANE_Int rest = + rd->DMABufferSize - (rd->RDStart - rd->DMABuffer); + memcpy (ptBuffer, rd->RDStart, rest); + memcpy (ptBuffer + rest, rd->DMABuffer, iAmount - rest); + rd->RDStart = rd->DMABuffer + (iAmount - rest); + } + else + { + memcpy (ptBuffer, rd->RDStart, iAmount); + rd->RDStart += iAmount; + } + + ptBuffer += iAmount; + rd->RDSize -= iAmount; + buffer_size -= iAmount; + *bytes_transfered += iAmount; + + /* if there isn't any data in DMABuffer we can point RDStart + to the begining of DMABuffer */ + if (rd->RDSize == 0) + rd->RDStart = rd->DMABuffer; + } + + /* in case of all data is read we return OK with bytes_transfered = 0 */ + if ((*bytes_transfered == 0) + || ((rd->RDSize == 0) && (rd->ImageSize == 0))) + break; + } + + if (rst == ERROR) + RTS_DMA_Cancel (dev); + } + + DBG (DBG_FNC, "-> *bytes_transfered=%i\n", *bytes_transfered); + DBG (DBG_FNC, "-> Reading->ImageSize=%i\n", rd->ImageSize); + DBG (DBG_FNC, "-> Reading->DMAAmount=%i\n", rd->DMAAmount); + DBG (DBG_FNC, "-> Reading->RDSize =%i\n", rd->RDSize); + + DBG (DBG_FNC, "- Scan_Read_BufferA: %i\n", rst); + + return rst; +} + +static SANE_Int +Get_Scanner_Buffer_Size (struct st_device *dev, SANE_Byte channels_per_dot, + SANE_Int channel_size) +{ + SANE_Int rst; + SANE_Int myAmount; + + DBG (DBG_FNC, + "+ Get_Scanner_Buffer_Size(channels_per_dot=%i, channel_size=%i):\n", + channels_per_dot, channel_size); + + rst = 0; + + if (channels_per_dot < 1) + { + if (Read_Byte (dev->usb_handle, 0xe812, &channels_per_dot) == OK) + channels_per_dot = _B0 (channels_per_dot >> 6); + + if (channels_per_dot == 0) + channels_per_dot++; + } + + if (Read_Integer (dev->usb_handle, 0xef16, &myAmount) == OK) + { + if (channel_size > 0) + rst = ((channels_per_dot * 32) / channel_size) * myAmount; + } + + DBG (DBG_FNC, "- Get_Scanner_Buffer_Size: %i\n", rst); + + return rst; +} + +static SANE_Int +Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, SANE_Int lamp) +{ + SANE_Int rst = OK; + SANE_Byte flb_lamp, tma_lamp; + + DBG (DBG_FNC, "+ Lamp_Warmup(*Regs, lamp=%i)\n", lamp); + + if (Regs != NULL) + { + SANE_Int overdrivetime; + + Lamp_GetStatus (dev, &flb_lamp, &tma_lamp); + + if (lamp == FLB_LAMP) + { + overdrivetime = RTS_Debug->overdrive_flb; + + if (flb_lamp == 0) + { + /* FLB-Lamp is turned off, lets turn on */ + Lamp_SetStatus (dev, Regs, TRUE, FLB_LAMP); + waitforpwm = TRUE; + } + } + else + { + if (RTS_isTmaAttached (dev) == TRUE) + { + overdrivetime = RTS_Debug->overdrive_ta; + + if (tma_lamp == 0) + { + /* tma lamp is turned off */ + Lamp_SetStatus (dev, Regs, FALSE, TMA_LAMP); + waitforpwm = TRUE; + } + } + else + rst = ERROR; + } + + /**/ if (rst == OK) + { + if (waitforpwm == TRUE) + Lamp_OverDrive (dev, overdrivetime, lamp); + + Lamp_SetupPwm (dev, lamp); + } + + } + else + rst = ERROR; + + DBG (DBG_FNC, "- Lamp_Warmup: %i\n", rst); + + return rst; +} + +static SANE_Int +Scan_Start (struct st_device *dev) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ Scan_Start:\n"); + + rst = ERROR; + if (RTS_Enable_CCD (dev, dev->init_regs, 0x0f) == OK) + { + SANE_Byte Regs[RT_BUFFER_LEN], data, mlock; + SANE_Int findref; + SANE_Int cl, lfaa0, ypos, xpos, runb1, gainmode; + struct st_scanparams scancfg; + struct st_hwdconfig hwdcfg; + struct st_calibration myCalib; + long tick; + + memcpy (&Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (&scancfg, &scan, sizeof (struct st_scanparams)); + + dbg_ScanParams (&scancfg); + + /* reserva buffer 6 dwords en fa84-fa9f */ + bzero (&hwdcfg, sizeof (struct st_hwdconfig)); + + cl = (pixeldarklevel == 0xffff) ? 0 : 1; + + /* wait till lamp is at home (should use timeout + windows driver doesn't use it) + */ + tick = GetTickCount () + 10000; + while ((Lamp_IsAtHome (dev, Regs) == 0) && (tick > GetTickCount ())); + + lfaa0 = 0; + if (v14b4 != 0) + { + if (GainOffset_IncCount (dev, &lfaa0) != OK) + return 0x02; + } + + data = Refs_Counter_Load (dev); + tick = GetTickCount (); + +#ifdef STANDALONE + findref = TRUE; +#else + findref = ((data != 0) && (data < 15)) ? FALSE : TRUE; +#endif + + if (findref != FALSE) + { + /* Need Find Ref */ + SANE_Byte BL; + + DBG (DBG_FNC, "Need to find ref\n"); + + Lamp_Warmup (dev, Regs, FLB_LAMP); + + if (waitforpwm == TRUE) + { + Lamp_WaitForPWM (dev, scan.resolution_x, FLB_LAMP); + waitforpwm = FALSE; + } + + /*56e1 */ + BL = scan.scantype; /* save scantype */ + scan.scantype = ST_NORMAL; + Refs_Set (dev, Regs, &scancfg, TRUE); + Refs_Counter_Inc (dev); + scan.scantype = BL; /* restore scantype */ + + Load_StripCoords (ST_NORMAL, &ypos, &xpos); + if (ypos != 0) + Motor_Relocate (dev, dev->motorcfg->parkhomemotormove, + MTR_FORWARD, ypos); + + if (scan.scantype != ST_NORMAL) + { + if (Lamp_Warmup (dev, Regs, TMA_LAMP) == ERROR) + return ERROR; + + /*5794 */ + Load_StripCoords (ST_TA, &ypos, &xpos); + if (ypos != 0) + Motor_Relocate (dev, dev->motorcfg->parkhomemotormove, + MTR_FORWARD, ypos); + Lamp_WaitForPWM (dev, scan.resolution_x, TMA_LAMP); + } + } + else + { + DBG (DBG_FNC, "Don't Need to find ref\n"); + + /* No need find ref */ + /*57d9 */ + if (scan.scantype == ST_NORMAL) + { + Lamp_Warmup (dev, Regs, FLB_LAMP); + } + else + { + /*5836 */ + if (Lamp_Warmup (dev, Regs, TMA_LAMP) == ERROR) + return ERROR; + } + + /*5895 */ + Refs_Set (dev, Regs, &scancfg, FALSE); + Refs_Counter_Inc (dev); + + Load_StripCoords (scantype, &ypos, &xpos); + if (ypos != 0) + Motor_Relocate (dev, dev->motorcfg->parkhomemotormove, + MTR_FORWARD, ypos); + + if (waitforpwm != FALSE) + { + SANE_Int lamp; + + if (v14b4 == 0) + { + /*590a */ + if (scan.scantype == ST_NORMAL) + lamp = FLB_LAMP; + else + lamp = TMA_LAMP; + } + else + lamp = 0; /* preview */ + + Lamp_WaitForPWM (dev, scan.resolution_x, lamp); + waitforpwm = FALSE; + } + } + + /* Calibration process */ + + /*592c */ + if (Calib_CreateBuffers (dev, &myCalib, v14b4) != OK) + return ERROR; + + /*5947 */ + +/* +if (Calib_BlackShading_jkd(dev, Regs, &myCalib, &scancfg) == OK) + Motor_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove); +*/ + +/* +if (Calib_test(dev, Regs, &myCalib, &scancfg) == OK ) + Motor_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove); +*/ + +/* Calibrate White shading correction */ + if ((RTS_Debug->wshading == TRUE) && (scan.scantype == ST_NORMAL)) + if (WShading_Calibrate (dev, Regs, &myCalib, &scancfg) == OK) + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + + hwdcfg.calibrate = RTS_Debug->calibrate; + + if (RTS_Debug->calibrate != 0) + { + /* Let's calibrate */ + if ((scancfg.colormode != CM_COLOR) && (scancfg.channel == 3)) + scancfg.colormode = CM_COLOR; + + hwdcfg.arrangeline = 0; + + if (scan.scantype == ST_NORMAL) + { + /* Calibration for reflective type */ + + /*59e3 */ + memcpy (&Regs, dev->init_regs, + RT_BUFFER_LEN * sizeof (SANE_Byte)); + + if (Calibration (dev, Regs, &scancfg, &myCalib, 0) != OK) + { + if (v14b4 == 0) + Calib_FreeBuffers (&myCalib); + return ERROR; + } + } + else + { + /*59ed */ + /* Calibration for negative/slide type */ + + } + + /*5af1 */ + if (RTS_Debug->ScanWhiteBoard != FALSE) + { + Motor_ParkHome (dev, TRUE, dev->motorcfg->basespeedmotormove); + scan.ler = 1; + } + + scancfg.colormode = scan.colormode; + } + else + { + /*5b1e */ + /*Don't calibrate */ + if (scan.scantype == ST_NORMAL) + { + Lamp_SetStatus2 (dev, TRUE, FLB_LAMP); + } + else + { + if ((scan.scantype == ST_TA) || (scan.scantype == ST_NEG)) + { + /*SANE_Int ta_y_start; */ + Lamp_SetStatus2 (dev, FALSE, TMA_LAMP); + /*ta_y_start = + get_value(SCAN_PARAM, TA_Y_START, 0x2508, usbfile); + ta_y_start += (((((scan.coord.top * 3) * 5) * 5) * 32) / scancfg.resolution_x); + if (ta_y_start >= 500) + { + Motor_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, ta_y_start); + scancfg.coord.top = 1; + scan.ler = 1; + } else + { + / *5ba9* / + if (ta_y_start > 0) + { + Motor_Relocate(dev, dev->motorcfg->basespeedmotormove, MTR_FORWARD, ta_y_start); + scancfg.coord.top = 1; + scan.ler = 1; + } + } */ + } + } + } + /*5bd0 */ + usleep (1000 * 200); + + hwdcfg.scantype = scan.scantype; + hwdcfg.motor_direction = MTR_FORWARD; + + /* Set Origin */ + if ((scan.scantype >= ST_NORMAL) || (scan.scantype <= ST_NEG)) + { + SANE_Int myser; + if ((dpi100Lumping == 0) + && (scancfg.resolution_x == + Scanmode_minres (dev, scan.scantype, scan.colormode))) + myser = scan.ser / 2; + else + myser = scan.ser; + scancfg.coord.left += myser; + scancfg.coord.top += scan.ler; + } + + hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance; + hwdcfg.highresolution = (scancfg.resolution_x <= 1200) ? FALSE : TRUE; + + /*5c55 */ + /* + if (RTS_Debug->calibrate == FALSE) + { + SANE_Int mytop = (((scancfg.coord.top * 5) * 5) * 16) / scancfg.resolution_y; + if ((scancfg.resolution_y <= 150)&&(mytop < 300)) + { + scancfg.coord.top = scancfg.resolution_y / 4; + } else + { + if (mytop < 100) + scancfg.coord.top = scancfg.resolution_y / 12; + } + } + */ + + /*5cd9 */ + if (compression != FALSE) + hwdcfg.compression = TRUE; + + /* setting arrangeline option */ + hwdcfg.arrangeline = arrangeline; + if (scancfg.resolution_x == 2400) + { + /* 5cfa */ + if (scancfg.colormode != CM_COLOR) + { + if ((scancfg.colormode == CM_GRAY) && (scancfg.channel == 3)) + hwdcfg.arrangeline = FIX_BY_SOFT; + } + else + hwdcfg.arrangeline = FIX_BY_SOFT; + } + + /*5d12 */ + if (dev->sensorcfg->type == CCD_SENSOR) + { + if ((dpi100Lumping == 0) + && (scancfg.resolution_x == + Scanmode_minres (dev, scancfg.scantype, scancfg.colormode))) + scancfg.coord.left += 12; + else + { + /*5d3a */ + scancfg.coord.left += 24; + switch (scancfg.resolution_x) + { + case 1200: + scancfg.coord.left -= 63; + break; + case 2400: + scancfg.coord.left -= 127; + break; + } + } + } + else + { + /*5d5a */ + /* CIS sensor */ + if ((dpi100Lumping == 0) + && (scancfg.resolution_x == + Scanmode_minres (dev, scancfg.scantype, scancfg.colormode))) + scancfg.coord.left += 25; + else + { + /*5d6d */ + scancfg.coord.left += 50; + switch (scancfg.resolution_x) + { + case 1200: + scancfg.coord.left -= 63; + break; + case 2400: + scancfg.coord.left -= 127; + break; + } + } + } + + /* 5d92 */ + DBG (DBG_FNC, " ->Scan_Start xStart=%i, xExtent=%i\n", + scancfg.coord.left, scancfg.coord.width); + + runb1 = 1; + if (scan.scantype == ST_NORMAL) + { + /*5db7 */ + if ((scancfg.resolution_x == 1200) + || (scancfg.resolution_x == 2400)) + { + /*5e41 */ + if ((scancfg.resolution_y / 10) > scancfg.coord.top) + runb1 = 0; + } + else + { + if ((scancfg.resolution_x == 600) + && (RTS_Debug->usbtype == USB11) + && (scancfg.colormode == CM_COLOR)) + { + /*5ded */ + if ((scancfg.resolution_y / 10) > scancfg.coord.top) + runb1 = 0; + } + else + { + if ((scancfg.resolution_x == 600) + || (scancfg.resolution_x == 300)) + { + /*5e11 */ + if (scancfg.resolution_y > scancfg.coord.top) + runb1 = 0; + } + else + runb1 = 0; + } + } + } + else + { + /*5e7c *//* entra aquí */ + if ((scancfg.resolution_y / 10) > scancfg.coord.top) + runb1 = 0; + } + /*5eb1 */ + if (runb1 == 1) /*entra */ + { + SANE_Int val1 = scancfg.coord.top - (scancfg.resolution_y / 10); + scancfg.coord.top -= val1; + Motor_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, (dev->motorcfg->resolution / scancfg.resolution_y) * val1); /*x168 */ + } + + /*5efe */ + if (RTS_Debug->calibrate != FALSE) + { + if (use_gamma_tables != FALSE) + { + hwdcfg.use_gamma_tables = TRUE; + hp_gamma->depth = 0; + } + + /*5f24 */ + hwdcfg.white_shading = TRUE; + hwdcfg.black_shading = TRUE; + hwdcfg.unk3 = 0; + RTS_Setup (dev, Regs, &scancfg, &hwdcfg, &calibdata->gain_offset); + + myCalib.shading_type = 0; + myCalib.shadinglength = + min (myCalib.shadinglength, scan.shadinglength); + + if (scancfg.colormode != CM_COLOR) + { + if ((scancfg.channel > 0) && (scancfg.channel < 3)) + myCalib.WRef[0] = myCalib.WRef[scancfg.channel]; + } + + RTS_WriteRegs (dev->usb_handle, Regs); + + /* apply gamma if required */ + Gamma_Apply (dev, Regs, &scancfg, &hwdcfg, hp_gamma); + + Shading_apply (dev, Regs, &scancfg, &myCalib); + + /* Save to file? */ + if (RTS_Debug->DumpShadingData != FALSE) + dump_shading (&myCalib); /*5ff9 */ + } + else + RTS_Setup (dev, Regs, &scancfg, &hwdcfg, default_gain_offset); + + /*602a */ + RTS_Debug->calibrate = hwdcfg.calibrate; + binarythresholdh = bw_threshold; + binarythresholdl = bw_threshold; + DBG (DBG_FNC, "> bw threshold -- hi=%i, lo=%i\n", binarythresholdh, + binarythresholdl); + + /* set threshold high */ + data_lsb_set (&Regs[0x1a0], binarythresholdh, 2); + + /* set threshold low */ + data_lsb_set (&Regs[0x19e], binarythresholdl, 2); + + /* if has motorcurves... */ + if ((Regs[0xdf] & 0x10) != 0) + data_bitset (&Regs[0x01], 0x02, 1); + + /* Set MLOCK */ + mlock = get_value (SCAN_PARAM, MLOCK, 0, usbfile) & 1; + data_bitset (&Regs[0x00], 0x10, mlock); /*---x----*/ + + if (dev->motorcfg->changemotorcurrent != FALSE) + Motor_Change (dev, Regs, + Motor_GetFromResolution (scancfg.resolution_x)); + + /* set gain control mode */ + gainmode = Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype); + Lamp_SetGainMode (dev, Regs, scancfg.resolution_x, gainmode); + + RTS_WaitScanEnd (dev, 15000); + if (v14b4 == 0) + Calib_FreeBuffers (&myCalib); + + /* release motor */ + Motor_Release (dev); + + +#ifdef developing +/* prueba(Regs); + dbg_registers(Regs);*/ + /*WShading_Calibrate(dev, Regs, &myCalib, &scancfg); */ + /*shadingtest1(dev, Regs, &myCalib); */ +#endif + + if (RTS_Warm_Reset (dev) == 0) + { + RTS_WriteRegs (dev->usb_handle, Regs); + usleep (1000 * 500); + + if (RTS_Execute (dev) == OK) + { + Lamp_SetTimer (dev, 0); + + /* Let scanner some time to store some data */ + if ((dev->chipset->model == RTS8822L_02A) + && (scancfg.resolution_x > 2400)) + usleep (1000 * 5000); + + rst = OK; + } + } + } + + DBG (DBG_FNC, "- Scan_Start: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, SANE_Int somevalue) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_Setup_Motor(*Regs, *scancfg, somevalue=%i):\n", + somevalue); + dbg_ScanParams (scancfg); + + rst = ERROR; + + if ((Regs != NULL) && (scancfg != NULL)) + { + SANE_Int colormode, mymode, step_type, dummyline, myvalue, lf02c; + SANE_Int step_size; + SANE_Int mbs[2] = { 0 }; /* motor back steps */ + + struct st_scanmode *sm; + + colormode = scancfg->colormode; + if ((colormode != CM_COLOR) && (scancfg->channel == 3)) + colormode = 3; + + mymode = + RTS_GetScanmode (dev, scantype, colormode, scancfg->resolution_x); + if (mymode == -1) + return ERROR; + + sm = dev->scanmodes[mymode]; + + /* set motor step type */ + data_bitset (&Regs[0xd9], 0x70, sm->scanmotorsteptype); /*-xxx----*/ + + /* set motor direction (polarity) */ + data_bitset (&Regs[0xd9], 0x80, somevalue >> 3); /*e------- */ + + /* next value doesn't seem to have any effect */ + data_bitset (&Regs[0xd9], 0x0f, somevalue); /*----efgh*/ + + /* 0 enable/1 disable motor */ + data_bitset (&Regs[0xdd], 0x80, somevalue >> 4); /*d------- */ + + /* next value doesn't seem to have any effect */ + data_bitset (&Regs[0xdd], 0x40, somevalue >> 4); /*-d------*/ + + switch (sm->scanmotorsteptype) + { + case STT_OCT: + step_type = 8; + break; + case STT_QUART: + step_type = 4; + break; + case STT_HALF: + step_type = 2; + break; + default: + step_type = 1; + break; /* STT_FULL */ + } + + /* set dummy lines */ + dummyline = sm->dummyline; + if (dummyline == 0) + dummyline++; + + data_bitset (&Regs[0xd6], 0xf0, dummyline); /*xxxx---- */ + + /* Set if motor has curves */ + data_bitset (&Regs[0xdf], 0x10, ((sm->motorcurve != -1) ? 1 : 0)); /*---x----*/ + + /* set last step of deccurve.scanbufferfull table to 16 */ + data_lsb_set (&Regs[0xea], 0x10, 3); + + /* set last step of deccurve.normalscan table to 16 */ + data_lsb_set (&Regs[0xed], 0x10, 3); + + /* set last step of deccurve.smearing table to 16 */ + data_lsb_set (&Regs[0xf0], 0x10, 3); + + /* set last step of deccurve.parkhome table to 16 */ + data_lsb_set (&Regs[0xf3], 0x10, 3); + + /* set step size */ + step_size = + _B0 ((dev->motorcfg->resolution * step_type) / + (dummyline * scancfg->resolution_y)); + data_lsb_set (&Regs[0xe0], step_size - 1, 1); + + /* set line exposure time */ + myvalue = data_lsb_get (&Regs[0x30], 3); + myvalue += ((myvalue + 1) % step_size); + data_lsb_set (&Regs[0x30], myvalue, 3); + + /* set last step of accurve.normalscan table */ + myvalue = ((myvalue + 1) / step_size) - 1; + data_lsb_set (&Regs[0xe1], myvalue, 3); + + /* 42b30eb */ + lf02c = 0; + if (sm->motorcurve != -1) + { + if (sm->motorcurve < dev->mtrsetting_count) + { + struct st_motorcurve *ms = dev->mtrsetting[sm->motorcurve]; + ms->motorbackstep = sm->motorbackstep; + } + + DBG (DBG_FNC, " -> Setting up step motor using motorcurve %i\n", + sm->motorcurve); + lf02c = Motor_Setup_Steps (dev, Regs, sm->motorcurve); + + /* set motor back steps */ + mbs[1] = sm->motorbackstep; + if (mbs[1] >= (smeardeccurvecount + smearacccurvecount)) + mbs[0] = mbs[1] - (smeardeccurvecount + smearacccurvecount) + 2; + else + mbs[0] = 0; + + if (mbs[1] >= (deccurvecount + acccurvecount)) + mbs[1] -= (deccurvecount + acccurvecount) + 2; + else + mbs[1] = 0; + } + else + { + /* this scanner hasn't got any motorcurve */ + + /* set last step of accurve.smearing table (same as accurve.normalscan) */ + data_lsb_set (&Regs[0xe4], myvalue, 3); + + /* set last step of accurve.parkhome table (same as accurve.normalscan) */ + data_lsb_set (&Regs[0xe7], myvalue, 3); + + /* both motorbacksteps are equal */ + mbs[0] = sm->motorbackstep; + mbs[1] = sm->motorbackstep; + } + + /* show msi and motorbacksteps */ + DBG (DBG_FNC, " -> msi = %i\n", sm->msi); + DBG (DBG_FNC, " -> motorbackstep1 = %i\n", mbs[0]); + DBG (DBG_FNC, " -> motorbackstep2 = %i\n", mbs[1]); + + /* set msi */ + data_bitset (&Regs[0xda], 0xff, _B0 (sm->msi)); /*xxxxxxxx */ + data_bitset (&Regs[0xdd], 0x03, _B1 (sm->msi)); /*------xx*/ + + /* set motorbackstep (a) */ + data_bitset (&Regs[0xdb], 0xff, _B0 (mbs[0])); /*xxxxxxxx */ + data_bitset (&Regs[0xdd], 0x0c, _B1 (mbs[0])); /*----xx--*/ + + /* set motorbackstep (b) */ + data_bitset (&Regs[0xdc], 0xff, _B0 (mbs[1])); /*xxxxxxxx */ + data_bitset (&Regs[0xdd], 0x30, _B1 (mbs[1])); /*--xx----*/ + + /* 328b */ + + /* get dummy lines count */ + dummyline = data_bitget (&Regs[0xd6], 0xf0); + + myvalue = scancfg->coord.top * (dummyline * step_size); + + if (lf02c >= myvalue) + scancfg->coord.top = 1; + else + scancfg->coord.top -= (lf02c / (dummyline * step_size)) - 1; + + rst = lf02c; /* Result from Motor_Setup_Steps */ + } + + DBG (DBG_FNC, "- RTS_Setup_Motor: %i\n", rst); + + return rst; +} + +static void +RTS_Setup_Exposure_Times (SANE_Byte * Regs, struct st_scanparams *scancfg, + struct st_scanmode *sm) +{ + DBG (DBG_FNC, "> RTS_Setup_Exposure_Times\n"); + + if ((sm != NULL) && (Regs != NULL) && (scancfg != NULL)) + { + SANE_Int myexpt[3], linexpt, a; + + /* calculate line exposure time */ + linexpt = sm->ctpc + 1; + if (RTS_Debug->usbtype == USB11) + linexpt *= sm->multiexposureforfullspeed; + + if (scancfg->depth > 8) + linexpt *= sm->multiexposurefor16bitmode; + + linexpt--; + + /* generate exposure times for each channel color */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + if ((linexpt > sm->mexpt[a]) && (sm->expt[a] == 0)) + sm->expt[a] = sm->mexpt[a]; + + myexpt[a] = (sm->expt[a] == 0) ? sm->mexpt[a] : sm->expt[a]; + } + + /* save exposure times */ + DBG (DBG_FNC, "-> Exposure times : %04x, %04x, %04x\n", sm->expt[0], + sm->expt[1], sm->expt[2]); + data_lsb_set (&Regs[0x36], sm->expt[CL_RED], 3); + data_lsb_set (&Regs[0x3c], sm->expt[CL_GREEN], 3); + data_lsb_set (&Regs[0x42], sm->expt[CL_BLUE], 3); + + /* save maximum exposure times */ + DBG (DBG_FNC, "-> Maximum exposure times: %04x, %04x, %04x\n", + sm->mexpt[0], sm->mexpt[1], sm->mexpt[2]); + data_lsb_set (&Regs[0x33], sm->mexpt[CL_RED], 3); + data_lsb_set (&Regs[0x39], sm->mexpt[CL_GREEN], 3); + data_lsb_set (&Regs[0x3f], sm->mexpt[CL_BLUE], 3); + + /* save line exposure time */ + data_lsb_set (&Regs[0x30], linexpt, 3); + + /* scancfg->expt = lowest value */ + scancfg->expt = min (min (myexpt[1], myexpt[2]), myexpt[0]); + } +} + +static SANE_Int +RTS_Setup_Line_Distances (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_hwdconfig *hwdcfg, SANE_Int mycolormode, + SANE_Int arrangeline) +{ + SANE_Int iLineDistance = 0; + + if (arrangeline == FIX_BY_HARD) + { + /* we don't need to arrange retrieved line */ + SANE_Int mylinedistance, myevenodddist; + + mylinedistance = + (dev->sensorcfg->line_distance * scancfg->resolution_y) / + dev->sensorcfg->resolution; + + if (hwdcfg->highresolution == TRUE) + myevenodddist = + (hwdcfg->sensorevenodddistance * scancfg->resolution_y) / + dev->sensorcfg->resolution; + else + myevenodddist = 0; + + data_bitset (&Regs[0x149], 0x3f, myevenodddist); + data_bitset (&Regs[0x14a], 0x3f, mylinedistance); + data_bitset (&Regs[0x14b], 0x3f, mylinedistance + myevenodddist); + data_bitset (&Regs[0x14c], 0x3f, mylinedistance * 2); + data_bitset (&Regs[0x14d], 0x3f, (mylinedistance * 2) + myevenodddist); + } + else + { + /* arrange retrieved line */ + data_bitset (&Regs[0x149], 0x3f, 0); + data_bitset (&Regs[0x14a], 0x3f, 0); + data_bitset (&Regs[0x14b], 0x3f, 0); + data_bitset (&Regs[0x14c], 0x3f, 0); + data_bitset (&Regs[0x14d], 0x3f, 0); + + if (arrangeline == FIX_BY_SOFT) + { + if (hwdcfg->highresolution == FALSE) + { + if (mycolormode == CM_COLOR) + { + iLineDistance = + (dev->sensorcfg->line_distance * scan2.resolution_y) * 2; + iLineDistance = + (iLineDistance / dev->sensorcfg->resolution) + 1; + if (iLineDistance < 2) + iLineDistance = 2; + } + } + else + { + /* bcc */ + if (mycolormode == CM_COLOR) + iLineDistance = + ((dev->sensorcfg->line_distance * 2) + + hwdcfg->sensorevenodddistance) * scan2.resolution_y; + else + iLineDistance = + dev->sensorcfg->line_distance * scan2.resolution_y; + + iLineDistance = + (iLineDistance / dev->sensorcfg->resolution) + 1; + if (iLineDistance < 2) + iLineDistance = 2; + } + + /* c25 */ + iLineDistance &= 0xffff; + v15b4 = (iLineDistance > 0) ? 1 : 0; + imagesize += iLineDistance * bytesperline; + } + } + + DBG (DBG_FNC, + "> RTS_Setup_Line_Distances(*Regs, *scancfg, *hwdcfg, mycolormode=%i, arrangeline=%i): %i\n", + mycolormode, arrangeline, iLineDistance); + + return iLineDistance; +} + +static SANE_Int +RTS_Setup_Depth (SANE_Byte * Regs, struct st_scanparams *scancfg, + SANE_Int mycolormode) +{ + /* channels_per_line = channels_per_dot * scan.width + bytes_per_line = channels_per_line * bits_per_channel + */ + + SANE_Int bytes_per_line = 0; + + if ((scancfg != NULL) && (Regs != NULL)) + { + SANE_Int channels_per_line = + data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width; + + bytes_per_line = channels_per_line; + + /* set bits per channel in shading correction's register (0x1cf) */ + if (mycolormode == CM_LINEART) + { + /* lineart mode */ + bytes_per_line = (bytes_per_line + 7) / 8; + data_bitset (&Regs[0x1cf], 0x30, 3); /*--11----*/ + } + else + { + /*f0c */ + switch (scancfg->depth) + { + case 16: + /* 16 bits per channel */ + bytes_per_line *= 2; + data_bitset (&Regs[0x1cf], 0x30, 2); /*--10----*/ + break; + case 12: + /* 12 bits per channel */ + bytes_per_line *= 2; + data_bitset (&Regs[0x1cf], 0x30, 1); /*--01----*/ + break; + default: + /* 8 bits per channel */ + data_bitset (&Regs[0x1cf], 0x30, 0); /*--00----*/ + break; + } + } + } + + return bytes_per_line; +} + +static void +RTS_Setup_Shading (SANE_Byte * Regs, struct st_scanparams *scancfg, + struct st_hwdconfig *hwdcfg, SANE_Int bytes_per_line) +{ + DBG (DBG_FNC, + "> RTS_Setup_Shading(*Regs, *scancfg, *hwdcfg, bytes_per_line=%i)\n", + bytes_per_line); + + if ((Regs != NULL) && (hwdcfg != NULL)) + { + SANE_Int dots_count, myvalue, myvalue2, mydata, resolution_ratio, + sensor_line_distance; + SANE_Int table_size; + + resolution_ratio = Regs[0x0c0] & 0x1f; + + /* 50de */ + data_bitset (&Regs[0x1bf], 0x18, hwdcfg->unk3); /*---xx---*/ + + /* Enable black shading correction ? */ + data_bitset (&Regs[0x1cf], 0x08, hwdcfg->black_shading); /*----x---*/ + + /* Enable white shading correction ? */ + data_bitset (&Regs[0x1cf], 0x04, hwdcfg->white_shading); /*-----x--*/ + + if ((hwdcfg->white_shading != FALSE) && (hwdcfg->black_shading != FALSE) + && (hwdcfg->unk3 != 0)) + data_bitset (&Regs[0x1cf], 0x04, 0); /*-----x--*/ + + table_size = 0; + + /* if hwdcfg->black_shading */ + if ((Regs[0x1cf] & 8) != 0) + table_size = (resolution_ratio * scancfg->coord.width) * 2; /* black shading buffer size? */ + + /* if hwdcfg->white_shading */ + if ((Regs[0x1cf] & 4) != 0) + table_size += (resolution_ratio * scancfg->coord.width) * 2; /* white shading buffer size? */ + + /* Regs 0x1ba, 0x1bb, 0x1bd, 0x1c0 seem to be 4 pointers + to some buffer related to shading correction */ + + Regs[0x1ba] = 0x00; + table_size = (v160c + table_size - 1) / v160c; + table_size = ((table_size + 15) / 16) + 16; + + Regs[0x1bf] &= 0xfe; + Regs[0x1bb] = _B0 (table_size); + Regs[0x1bc] = _B1 (table_size); + Regs[0x1bf] |= _B2 (table_size) & 1; /*-------x*/ + + Regs[0x1bf] &= 0xf9; + Regs[0x1bd] = _B0 (table_size * 2); + Regs[0x1be] = _B1 (table_size * 2); + Regs[0x1bf] |= (_B2 (table_size * 2) & 3) << 1; /*-----xx-*/ + + data_wide_bitset (&Regs[0x1c0], 0xfffff, table_size * 3); + + mydata = v1610 - ((table_size * 3) * 16); + + dots_count = bytes_per_line; + + sensor_line_distance = Regs[0x14a] & 0x3f; + + /* select case channels_per_dot */ + switch ((data_lsb_get (&Regs[0x12], 1) >> 6)) + { + case 3: /* 3 channels per dot */ + /* 528d */ + dots_count = bytes_per_line / 3; /* 882 */ + myvalue = + (((sensor_line_distance + 1) * dots_count) + v160c - 1) / v160c; + myvalue2 = myvalue; + mydata = (mydata - (myvalue * 3) + 2) / 3; + + myvalue += (data_lsb_get (&Regs[0x1c0], 3) & 0x0fffff) * 8; + myvalue = (((myvalue * 2) + mydata) >> 4) + 1; + + data_bitset (&Regs[0x1c2], 0xf0, _B2 (myvalue)); /* 4 higher bits xxxx---- */ + data_wide_bitset (&Regs[0x1c3], 0xffff, myvalue); /* 16 lower bits */ + + myvalue = (((myvalue << 4) + myvalue2 + mydata) >> 4) + 1; + data_wide_bitset (&Regs[0x1c5], 0xfffff, myvalue); + break; + case 2: /* 2 channels per dot */ + dots_count = bytes_per_line / 2; + myvalue = + (((sensor_line_distance + 1) * dots_count) + v160c - 1) / v160c; + mydata = ((mydata - myvalue) + 1) / 2; + myvalue += + (((data_lsb_get (&Regs[0x1c0], 3) & 0x0fffff) + mydata) / 16) + 1; + + data_bitset (&Regs[0x1c2], 0xf0, _B2 (myvalue)); /* 4 higher bits xxxx---- */ + data_wide_bitset (&Regs[0x1c3], 0xffff, myvalue); /* 16 lower bits */ + break; + } + + Regs[0x01c7] &= 0x0f; + Regs[0x01c8] = _B0 ((v1610 - 1) / 16); + Regs[0x01c9] = _B1 ((v1610 - 1) / 16); + Regs[0x01c7] |= (_B2 ((v1610 - 1) / 16) & 0x0f) << 4; + + mydata -= (v160c + dots_count - 1) / v160c; + mydata /= 16; + Regs[0x0712] &= 0x0f; + Regs[0x0710] = _B0 (mydata); + Regs[0x0711] = _B1 (mydata); + Regs[0x0712] |= _B0 (_B2 (mydata) << 4); /*xxxx---- */ + + Regs[0x0713] = 0x00; + Regs[0x0714] = 0x10; + Regs[0x0715] &= 0xf0; + } +} + +static void +RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, SANE_Int mycolormode) +{ + DBG (DBG_FNC, "> RTS_Setup_Channels(colormode=%i)\n", mycolormode); + + if ((scancfg != NULL) && (Regs != NULL)) + { + if ((mycolormode != CM_COLOR) && (mycolormode != 3)) + { + /* CM_GRAY || CM_LINEART */ + if (scancfg->samplerate == LINE_RATE) + { + /* Setting channels_per_dot to 1 */ + data_bitset (&Regs[0x12], 0xc0, 1); /*01------ */ + + /* setting one rgb_channel_order */ + data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[scancfg->channel]); /*------xx*/ + + /* set sensor_channel_color_order */ + data_bitset (&Regs[0x60a], 0x3f, 6); /*--xxxxxx*/ + + /* set samplerate */ + data_bitset (&Regs[0x1cf], 0x40, PIXEL_RATE); /*-x------*/ + + /* set unknown data */ + data_bitset (&Regs[0x1cf], 0x80, 1); /*x------- */ + + if (scancfg->channel == dev->sensorcfg->rgb_order[1]) + { + /* mexpts[CL_RED] = mexpts[CL_GREEN] */ + data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x39], 3), + 3); + + /* expts[CL_RED] = expts[CL_GREEN] */ + data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x3c], 3), + 3); + } + else if (scancfg->channel == dev->sensorcfg->rgb_order[2]) + { + /* mexpts[CL_RED] = mexpts[CL_BLUE] */ + data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x3f], 3), + 3); + + /* expts[CL_RED] = expts[CL_BLUE] */ + data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x42], 3), + 3); + } + } + else + { + /* e01 */ + /* setting channels_per_dot to 2 */ + data_bitset (&Regs[0x12], 0xc0, 2); + + /* set two channel color order */ + data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->channel_gray[0]); /*------xx*/ + data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->channel_gray[1]); /*----xx--*/ + + /* set samplerate */ + data_bitset (&Regs[0x1cf], 0x40, LINE_RATE); + + /* set unknown data */ + data_bitset (&Regs[0x1cf], 0x80, 1); + } + } + else + { + /* CM_COLOR || 3 */ + /* e42 */ + + /* setting channels_per_dot to 3 */ + data_bitset (&Regs[0x12], 0xc0, 3); + + /* setting samplerate */ + data_bitset (&Regs[0x1cf], 0x40, scancfg->samplerate); + + /* set unknown data */ + data_bitset (&Regs[0x1cf], 0x80, 0); + + /* set sensor chanel_color_order */ + data_bitset (&Regs[0x60a], 0x03, dev->sensorcfg->channel_color[2]); /*------xx*/ + data_bitset (&Regs[0x60a], 0x0c, dev->sensorcfg->channel_color[1]); /*----xx--*/ + data_bitset (&Regs[0x60a], 0x30, dev->sensorcfg->channel_color[0]); /*--xx----*/ + + /* set rgb_channel_order */ + data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[0]); /*------xx*/ + data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->rgb_order[1]); /*----xx--*/ + data_bitset (&Regs[0x12], 0x30, dev->sensorcfg->rgb_order[2]); /*--xx----*/ + } + } +} + +static SANE_Int +RTS_Setup (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, + struct st_gain_offset *gain_offset) +{ + SANE_Int iLineDistance, lSMode, dummyline; + SANE_Int bytes_per_line, resolution_ratio; + SANE_Byte mycolormode; + struct st_scanmode *sm; + struct st_coords rts_coords; + + DBG (DBG_FNC, "+ RTS_Setup:\n"); + dbg_ScanParams (scancfg); + dbg_hwdcfg (hwdcfg); + + iLineDistance = 0; + + mycolormode = scancfg->colormode; + if (scancfg->colormode != CM_COLOR) + { + if (scancfg->colormode == CM_LINEART) + scancfg->depth = 8; + + if (scancfg->channel == 3) + { + if (scancfg->colormode == CM_GRAY) + mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR; + else + mycolormode = 3; + } + } + + /* 42b47d6 */ + memcpy (&scan2, scancfg, sizeof (struct st_scanparams)); + + scantype = hwdcfg->scantype; + lSMode = + RTS_GetScanmode (dev, scantype, mycolormode, scancfg->resolution_x); + if (lSMode < 0) + return ERROR; + + sm = dev->scanmodes[lSMode]; + + scancfg->timing = sm->timing; + scancfg->sensorresolution = dev->timings[scancfg->timing]->sensorresolution; + scancfg->shadinglength = + (((scancfg->sensorresolution * 17) / 2) + 3) & 0xfffffffc; + scancfg->samplerate = sm->samplerate; + + hwdcfg->motorplus = sm->motorplus; + + /* set systemclock */ + data_bitset (&Regs[0x00], 0x0f, sm->systemclock); + + /* setting exposure times */ + RTS_Setup_Exposure_Times (Regs, scancfg, sm); + + dev->scanning->arrange_compression = + (mycolormode == CM_LINEART) ? FALSE : hwdcfg->compression; + + if ((mycolormode == CM_LINEART) + || ((mycolormode == CM_GRAY) && (hwdcfg->highresolution == FALSE))) + arrangeline2 = 0; + else + arrangeline2 = hwdcfg->arrangeline; + + dev->scanning->arrange_hres = hwdcfg->highresolution; + dev->scanning->arrange_sensor_evenodd_dist = + (hwdcfg->highresolution == FALSE) ? 0 : hwdcfg->sensorevenodddistance; + + /* set up line distances */ + iLineDistance = + RTS_Setup_Line_Distances (dev, Regs, scancfg, hwdcfg, mycolormode, + arrangeline); + + /* 4c67 */ + + /* setup channel colors */ + RTS_Setup_Channels (dev, Regs, scancfg, mycolormode); + + /* setup depth */ + bytes_per_line = RTS_Setup_Depth (Regs, scancfg, mycolormode); + + /* f61 */ + + /* Set resolution ratio */ + resolution_ratio = + (scancfg->sensorresolution / scancfg->resolution_x) & 0x1f; + data_bitset (&Regs[0xc0], 0x1f, resolution_ratio); + + /* set sensor timing values */ + RTS_Setup_SensorTiming (dev, scancfg->timing, Regs); + + data_bitset (&Regs[0xd8], 0x40, ((scantype == ST_NORMAL) ? 0 : 1)); /*-x------*/ + + /* Use static head ? */ + data_bitset (&Regs[0xd8], 0x80, ((hwdcfg->static_head == FALSE) ? 1 : 0)); /*x------- */ + + /* Setting up gamma */ + RTS_Setup_Gamma (Regs, hwdcfg); + + /* setup shading correction */ + RTS_Setup_Shading (Regs, scancfg, hwdcfg, bytes_per_line); + + /* setup stepper motor */ + hwdcfg->startpos = + RTS_Setup_Motor (dev, Regs, scancfg, + hwdcfg->motor_direction | MTR_ENABLED); + + /* set coordinates */ + dummyline = data_bitget (&Regs[0xd6], 0xf0); + + if (scancfg->coord.left == 0) + scancfg->coord.left++; + if (scancfg->coord.top == 0) + scancfg->coord.top++; + + rts_coords.left = scancfg->coord.left * resolution_ratio; + rts_coords.width = scancfg->coord.width * resolution_ratio; + rts_coords.top = scancfg->coord.top * dummyline; + rts_coords.height = + ((Regs[0x14d] & 0x3f) + scancfg->coord.height + + iLineDistance) * dummyline; + + if ((rts_coords.left & 1) == 0) + rts_coords.left++; + + RTS_Setup_Coords (Regs, rts_coords.left, rts_coords.top, rts_coords.width, + rts_coords.height); + + data_bitset (&Regs[0x01], 0x06, 0); /*-----xx-*/ + + /* dummy_scan? */ + data_bitset (&Regs[0x01], 0x10, hwdcfg->dummy_scan); /*---x----*/ + + data_bitset (&Regs[0x163], 0xc0, 1); /*xx------ */ + + if (dev->scanning->arrange_compression != FALSE) + { + Regs[0x60b] &= 0x8f; + data_bitset (&Regs[0x60b], 0x10, 1); /*-001----*/ + } + else + data_bitset (&Regs[0x60b], 0x7f, 0); /*-0000000*/ + + if (mycolormode == 3) + { + SANE_Int channels_per_line; + + /* Set channels_per_line = channels_per_dot * scan_width */ + channels_per_line = + data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width; + data_wide_bitset (&Regs[0x060c], 0x3ffff, channels_per_line); + + /* Sets 16 bits per channel */ + data_bitset (&Regs[0x1cf], 0x30, 2); /*--10----*/ + + Regs[0x60b] |= 0x40; + if (v1619 == 0x21) + { + dev->scanning->arrange_compression = FALSE; + data_bitset (&Regs[0x60b], 0x10, 0); /*---0----*/ + } + + switch (scancfg->depth) + { + case 8: + case 16: + Regs[0x060b] &= 0xf3; + break; + case 12: + Regs[0x060b] = (Regs[0x060b] & 0xfb) | 0x08; + break; + } + + if (scancfg->colormode == CM_LINEART) + data_bitset (&Regs[0x60b], 0x0c, 0); + + /* disable gamma correction ¿? */ + data_bitset (&Regs[0x1d0], 0x40, 0); + } + + /* 5683 */ + /* Set calibration table */ + RTS_Setup_GainOffset (Regs, gain_offset); + + DBG (DBG_FNC, "- RTS_Setup:\n"); + + return OK; +} + +static void +RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop, + SANE_Int width, SANE_Int height) +{ + DBG (DBG_FNC, + "> RTS_Setup_Coords(*Regs, iLeft=%i, iTop=%i, width=%i, height=%i)\n", + iLeft, iTop, width, height); + + if (Regs != NULL) + { + /* Set Left coord */ + data_lsb_set (&Regs[0xb0], iLeft, 2); + + /* Set Right coord */ + data_lsb_set (&Regs[0xb2], iLeft + width, 2); + + /* Set Top coord */ + data_lsb_set (&Regs[0xd0], iTop, 2); + data_bitset (&Regs[0xd4], 0x0f, _B2 (iTop)); + + /* Set Down coord */ + data_lsb_set (&Regs[0xd2], iTop + height, 2); + data_bitset (&Regs[0xd4], 0xf0, _B2 (iTop + height)); + } +} + +static void +RTS_Setup_GainOffset (SANE_Byte * Regs, struct st_gain_offset *gain_offset) +{ + SANE_Byte fake[] = + { 0x19, 0x15, 0x19, 0x64, 0x64, 0x64, 0x74, 0xc0, 0x74, 0xc0, 0x6d, + 0xc0, 0x6d, 0xc0, 0x5f, 0xc0, 0x5f, 0xc0 + }; + + DBG (DBG_FNC, "> RTS_Setup_GainOffset(*Regs, *gain_offset)\n"); + dbg_calibtable (gain_offset); + + if ((Regs != NULL) && (gain_offset != NULL)) + { + if (RTS_Debug->calibrate == FALSE) + { + data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]); /*------xx*/ + data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]); /*----xx--*/ + data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]); /*--xx----*/ + + memcpy (&Regs[0x14], &fake, 18); + } + else + { + SANE_Int a; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + /* Offsets */ + Regs[0x1a + (a * 4)] = _B0 (gain_offset->edcg1[a]); + Regs[0x1b + (a * 4)] = + ((gain_offset->edcg1[a] >> 1) & 0x80) | (gain_offset-> + edcg2[a] & 0x7f); + Regs[0x1c + (a * 4)] = _B0 (gain_offset->odcg1[a]); + Regs[0x1d + (a * 4)] = + ((gain_offset->odcg1[a] >> 1) & 0x80) | (gain_offset-> + odcg2[a] & 0x7f); + + /* Variable Gain Amplifier */ + data_bitset (&Regs[0x14 + a], 0x1f, gain_offset->vgag1[a]); + data_bitset (&Regs[0x17 + a], 0x1f, gain_offset->vgag2[a]); + } + + data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]); /*------xx*/ + data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]); /*----xx--*/ + data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]); /*--xx----*/ + } + } +} + +static void +Calibrate_Free (struct st_cal2 *calbuffers) +{ + DBG (DBG_FNC, "> Calibrate_Free(*calbuffers)\n"); + + if (calbuffers != NULL) + { + SANE_Int c; + + if (calbuffers->table2 != NULL) + { + free (calbuffers->table2); + calbuffers->table2 = NULL; + } + + for (c = 0; c < 4; c++) + { + if (calbuffers->tables[c] != NULL) + { + free (calbuffers->tables[c]); + calbuffers->tables[c] = NULL; + } + } + + calbuffers->shadinglength1 = 0; + calbuffers->tables_size = 0; + calbuffers->shadinglength3 = 0; + } +} + +static SANE_Int +Calibrate_Malloc (struct st_cal2 *calbuffers, SANE_Byte * Regs, + struct st_calibration *myCalib, SANE_Int somelength) +{ + SANE_Int myshadinglength, pos; + SANE_Int rst; + + if ((calbuffers != NULL) && (Regs != NULL) && (myCalib != NULL)) + { + if ((Regs[0x1bf] & 0x18) == 0) + { + if ((((Regs[0x1cf] >> 1) & Regs[0x1cf]) & 0x04) != 0) + calbuffers->table_count = 2; + else + calbuffers->table_count = 4; + } + else + calbuffers->table_count = 4; + + /*365d */ + myshadinglength = myCalib->shadinglength * 2; + calbuffers->shadinglength1 = min (myshadinglength, somelength); + + if ((myshadinglength % somelength) != 0) + calbuffers->tables_size = + (myshadinglength >= somelength) ? somelength * 2 : somelength; + else + calbuffers->tables_size = somelength; + + if (myshadinglength >= somelength) + { + calbuffers->shadinglength1 = + (myshadinglength % calbuffers->shadinglength1) + + calbuffers->shadinglength1; + calbuffers->shadinglength3 = + ((myCalib->shadinglength * 2) / somelength) - 1; + } + else + calbuffers->shadinglength3 = 0; + + calbuffers->shadinglength3 = + (somelength / 16) * calbuffers->shadinglength3; + + rst = OK; + for (pos = 0; pos < calbuffers->table_count; pos++) + { + calbuffers->tables[pos] = + (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT)); + if (calbuffers->tables[pos] == NULL) + { + rst = ERROR; + break; + } + } + + if (rst == OK) + { + calbuffers->table2 = + (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT)); + if (calbuffers->table2 == NULL) + rst = ERROR; + } + + if (rst != OK) + Calibrate_Free (calbuffers); + } + else + rst = ERROR; + + DBG (DBG_FNC, + "> Calibrate_Malloc(*calbuffers, *Regs, *myCalib, somelength=%i): %i\n", + somelength, rst); + + return rst; +} + +static SANE_Int +fn3560 (USHORT * table, struct st_cal2 *calbuffers, SANE_Int * tablepos) +{ + /*05FEF974 001F99B0 |table = 001F99B0 + 05FEF978 05FEFA08 |calbuffers->tables[0] = 05FEFA08 + 05FEF97C 000000A0 |calbuffers->shadinglength3 = 000000A0 + 05FEF980 00000348 |calbuffers->shadinglength1 = 00000348 + 05FEF984 04F01502 |calbuffers->table_count = 04F01502 + 05FEF988 05FEF998 \Arg6 = 05FEF998 + */ + + if (table != NULL) + { + SANE_Int pos[4] = { 0, 0, 0, 0 }; /*f960 f964 f968 f96c */ + SANE_Int usetable = 0; + SANE_Int a; + + SANE_Int mylength3 = calbuffers->shadinglength1; /*f97c */ + SANE_Byte *pPointer = + (SANE_Byte *) (table + (calbuffers->shadinglength3 * 16)); + + DBG (DBG_FNC, "> fn3560(*table, *calbuffers, *tablepos)\n"); + + if (mylength3 > 0) + { + do + { + if (calbuffers->tables[usetable] != NULL) + { + if (mylength3 <= 16) + { + if (mylength3 > 0) + { + do + { + *(calbuffers->tables[usetable] + + pos[usetable]) = _B0 (*pPointer); + pPointer++; + pos[usetable]++; + mylength3--; + } + while (mylength3 > 0); + } + break; + } + + for (a = 0; a < 16; a++) + { + *(calbuffers->tables[usetable] + pos[usetable]) = + _B0 (*pPointer); + pPointer++; + pos[usetable]++; + } + } + + mylength3 -= 16; + usetable++; + if (usetable == calbuffers->table_count) + usetable = 0; + } + while (mylength3 > 0); + } + + /*35f8 */ + if (calbuffers->table_count > 0) + { + /* Return position of each table */ + memcpy (tablepos, pos, sizeof (SANE_Int) * 4); + } + } + + return OK; +} + +static SANE_Int +Calib_WriteTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, + SANE_Int data) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ Calib_WriteTable(*table, size=%i):\n", size); + + if ((table != NULL) && (size > 0)) + { + SANE_Int transferred; + + if (RTS_DMA_Reset (dev) == OK) + { + /* Send size to write */ + if (RTS_DMA_Enable_Write (dev, 0x0004, size, data) == OK) + /* Send data */ + rst = Bulk_Operation (dev, BLK_WRITE, size, table, &transferred); + } + } + + DBG (DBG_FNC, "- Calib_WriteTable: %i\n", rst); + + return rst; +} + +static SANE_Int +Calib_ReadTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, + SANE_Int data) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ Calib_ReadTable(*table, size=%i):\n", size); + + if ((table != NULL) && (size > 0)) + { + SANE_Int transferred; + + if (RTS_DMA_Reset (dev) == OK) + { + /* Send size to read */ + if (RTS_DMA_Enable_Read (dev, 0x0004, size, data) == OK) + /* Retrieve data */ + rst = Bulk_Operation (dev, BLK_READ, size, table, &transferred); + } + } + + DBG (DBG_FNC, "- Calib_ReadTable: %i\n", rst); + + return rst; +} + +static SANE_Int +fn3330 (struct st_device *dev, SANE_Byte * Regs, struct st_cal2 *calbuffers, + SANE_Int sensorchannelcolor, SANE_Int * tablepos, SANE_Int data) +{ + /*05EEF968 04F0F7F8 |Regs = 04F0F7F8 + 05EEF96C 02DEC838 |calbuffers->table2 = 02DEC838 + 05EEF970 05EEFA08 |calbuffers->tables[] = 05EEFA08 + 05EEF974 00000000 |sensorchannelcolor = 00000000 + 05EEF978 000000A0 |calbuffers->shadinglength3 = 000000A0 + 05EEF97C 00000400 |calbuffers->tables_size = 00000400 + 05EEF980 05EEF998 |&pos = 05EEF998 + 05EEF984 00221502 |calbuffers->table_count = 00221502 + 05EEF988 00000000 \data = 00000000 + */ + + SANE_Int table_count = calbuffers->table_count; /*f960 */ + SANE_Int schcolor = _B0 (sensorchannelcolor); + SANE_Int a = 0; + SANE_Int tablelength = calbuffers->shadinglength3 / table_count; /*f954 */ + SANE_Int val_color = 0; /*f974 */ + SANE_Int val_lineart = 0; /*f978 */ + SANE_Int val_gray = 0; /*ebx */ + SANE_Int value4 = 0; /*ebp */ + SANE_Int size; + SANE_Int rst = OK; + + DBG (DBG_FNC, + "+ fn3330(*Regs, *calbuffers, sensorchannelcolor=%i, *tablepos, data=%i):\n", + sensorchannelcolor, data); + + if (calbuffers->table_count > 0) + { + do + { + if (calbuffers->table_count == 2) + { + /*338c */ + if (a != 0) + { + /*3394 */ + if (_B0 (data) == 0) + { + val_color = 0x100000; + val_lineart = 0x100000; + val_gray = 0x200000; + } + else + { + /*343a */ + val_color = 0x300000; + val_lineart = 0x300000; + val_gray = 0; + } + } + else + { + /*33be */ + if (_B0 (data) == 0) + { + val_color = 0; + val_lineart = 0; + val_gray = 0x300000; + } + else + { + /*342a */ + val_color = 0x200000; + val_lineart = 0x200000; + val_gray = 0x100000; + } + } + } + else + { + /*33d5 */ + switch (a) + { + case 0: + val_color = 0; + val_lineart = 0; + val_gray = 0x300000; + break; + case 1: + val_color = 0x200000; + val_lineart = 0x200000; + val_gray = 0x100000; + break; + case 2: + val_color = 0x100000; + val_lineart = 0x100000; + val_gray = 0x200000; + break; + case 3: + val_color = 0x300000; + val_lineart = 0x300000; + val_gray = 0; + break; + } + } + + /*3449 */ + switch (schcolor) + { + case CM_LINEART: + size = + (((Regs[0x1bf] >> 1) & 3) << 0x10) | (Regs[0x1be] << 0x08) | + Regs[0x1bd]; + value4 = (tablelength + size) | val_lineart; + break; + case CM_GRAY: + size = + ((Regs[0x1bf] & 1) << 0x10) | (Regs[0x1bc] << 0x08) | + Regs[0x1bb]; + value4 = (tablelength + size) | val_gray; + break; + default: + size = _B0 (Regs[0x1ba]); + value4 = (tablelength + size) | val_color; + break; + } + + if (Calib_ReadTable + (dev, (SANE_Byte *) calbuffers->table2, calbuffers->tables_size, + value4) != OK) + { + rst = ERROR; + break; + } + + memcpy (calbuffers->tables[a], calbuffers->table2, tablepos[a]); + + if (tablepos[a + 1] == 0) + break; + + a++; + } + while (a < calbuffers->table_count); + } + + DBG (DBG_FNC, "- fn3330: %i\n", rst); + + return rst; +} + +static SANE_Int +fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, SANE_Byte * Regs, + USHORT * table, SANE_Int sensorchannelcolor, SANE_Int data) +{ + /*05FEF9AC |calbuffers = 05FEF9F8 + 05FEF9B0 |Regs = 04EFF7F8 + 05FEF9B4 |table = 001F99B0 + 05FEF9B8 |sensorchannelcolor = 00000000 + 05FEF9BC |data = 00000000 + */ + + SANE_Int pos[4] = { 0, 0, 0, 0 }; /*f998 f99c f9a0 f9a4 */ + SANE_Int rst; + + DBG (DBG_FNC, + "+ fn3730(*calbuffers, *Regs, *table, sensorchannelcolor=%i, data=%i):\n", + sensorchannelcolor, data); + + fn3560 (table, calbuffers, pos); + rst = fn3330 (dev, Regs, calbuffers, sensorchannelcolor, pos, data); + + DBG (DBG_FNC, "- fn3730: %i\n", rst); + + return rst; +} + +static SANE_Int +Shading_white_apply (struct st_device *dev, SANE_Byte * Regs, + SANE_Int channels, struct st_calibration *myCalib, + struct st_cal2 *calbuffers) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ Shading_white_apply(channels=%i)\n", channels); + + /*3e7f */ + Calibrate_Malloc (calbuffers, Regs, myCalib, + (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40); + + if (channels > 0) + { + /*int a; */ + SANE_Int chnl; + SANE_Int pos; /*fa2c */ + SANE_Int transferred; + + rst = ERROR; + + for (chnl = 0; chnl < channels; chnl++) + { + /*for (a = 0; a < myCalib->shadinglength; a++) + myCalib->black_shading[chnl][a] = 0x2000; */ + /* 11 tries */ + for (pos = 0; pos <= 10; pos++) + { + /* Send size to write */ + if (RTS_DMA_Enable_Write + (dev, dev->sensorcfg->channel_color[chnl] | 0x14, + myCalib->shadinglength, 0) == OK) + /* Send data */ + Bulk_Operation (dev, BLK_WRITE, + myCalib->shadinglength * sizeof (USHORT), + (SANE_Byte *) & myCalib-> + white_shading[chnl][myCalib->first_position - + 1], &transferred); + + /*3df7 */ + if (fn3730 + (dev, calbuffers, Regs, + &myCalib->white_shading[chnl][myCalib->first_position - 1], + dev->sensorcfg->channel_color[chnl], 1) == OK) + { + rst = OK; + break; + } + + RTS_DMA_Cancel (dev); + } + } + } + + Calibrate_Free (calbuffers); + + DBG (DBG_FNC, "- Shading_white_apply: %i\n", rst); + + return OK; +} + +static SANE_Int +Shading_black_apply (struct st_device *dev, SANE_Byte * Regs, + SANE_Int channels, struct st_calibration *myCalib, + struct st_cal2 *calbuffers) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ Shading_black_apply(channels=%i)\n", channels); + + /* 3d79 */ + Calibrate_Malloc (calbuffers, Regs, myCalib, + (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40); + + if (channels > 0) + { + /*int a; */ + SANE_Int chnl; + SANE_Int pos; /*fa2c */ + SANE_Int transferred; + + rst = ERROR; + + for (chnl = 0; chnl < channels; chnl++) + { + /* 11 tries */ + /*for (a = 0; a < myCalib->shadinglength; a++) + myCalib->black_shading[chnl][a] = 0x2000; */ + + for (pos = 0; pos <= 10; pos++) + { + /* Send size to write */ + if (RTS_DMA_Enable_Write + (dev, dev->sensorcfg->channel_color[chnl] | 0x10, + myCalib->shadinglength, 0) == OK) + /* Send data */ + Bulk_Operation (dev, BLK_WRITE, + myCalib->shadinglength * sizeof (USHORT), + (SANE_Byte *) & myCalib-> + black_shading[chnl][myCalib->first_position - + 1], &transferred); + + /*3df7 */ + if (fn3730 + (dev, calbuffers, Regs, + &myCalib->black_shading[chnl][myCalib->first_position - 1], + dev->sensorcfg->channel_color[chnl], 0) == OK) + { + rst = OK; + break; + } + + RTS_DMA_Cancel (dev); + } + } + } + + /*3e62 */ + Calibrate_Free (calbuffers); + + DBG (DBG_FNC, "- Shading_black_apply: %i\n", rst); + + return OK; +} + +static SANE_Int +Shading_apply (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *myvar, struct st_calibration *myCalib) +{ + /* + Regs f1bc + myvar f020 + hwdcfg e838 + arg4 e81c + myCalib e820 + */ + + SANE_Int rst; /* lf9e0 */ + SANE_Int myfact; /* e820 */ + SANE_Int shadata; + SANE_Byte channels; /* f9d4 */ + SANE_Int myShadingBase; /* e818 */ + + char lf9d1; + char lf9d0; + + DBG (DBG_FNC, "+ Shading_apply(*Regs, *myvar, *mygamma, *myCalib):\n"); + dbg_ScanParams (myvar); + + lf9d0 = (Regs[0x60b] >> 6) & 1; + lf9d1 = (Regs[0x60b] >> 4) & 1; + Regs[0x060b] &= 0xaf; + rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); + if (rst == OK) + { + SANE_Byte colormode = myvar->colormode; /*fa24 */ + SANE_Int le7cc, le7d8; + struct st_cal2 calbuffers; /* f9f8 */ + + if (colormode != CM_COLOR) + { + if (myvar->channel != 3) + { + if (colormode != 3) + channels = (myvar->samplerate == PIXEL_RATE) ? 2 : 1; + else + channels = 3; + } + else + { + colormode = 3; + channels = 3; + } + } + else + channels = 3; + + /* + White shading formula : 2000H x Target / (Wn-Dn) = White Gain data ----- for 8 times system + White shading formula : 4000H x Target / (Wn-Dn) = White Gain data ----- for 4 times system + For example : Target = 3FFFH Wn = 2FFFH Dn = 0040H and 8 times system operation + then White Gain = 2000H x 3FFFH / (2FFFH-0040H) = 2AE4H (1.34033 times) + */ + /* 3aad */ + if (colormode == 3) + { + /* + SANE_Int pos; + SANE_Int colour; + + myShadingBase = shadingbase; + + for (colour = 0; colour < channels; colour++) + { + if (myCalib->white_shading[colour] != NULL) + { + myfact = shadingfact[colour]; + if (myCalib->shadinglength > 0) + { + for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) + myCalib->white_shading[colour][pos] = (myCalib->white_shading[colour][pos] * myfact) / myShadingBase; + } + } else break; + } + */ + } + + /* 3b3b */ + if (myCalib->shading_enabled != FALSE) + { + /* 3b46 */ + SANE_Int colour, pos; + le7cc = shadingbase; + le7d8 = shadingbase; + + DBG (DBG_FNC, "-> Shading type: %i\n", myCalib->shading_type); + + for (colour = 0; colour < channels; colour++) + { + if (colormode == 3) + le7cc = shadingfact[colour]; + + myShadingBase = ((Regs[0x1cf] & 2) != 0) ? 0x2000 : 0x4000; + + myfact = myCalib->WRef[colour] * myShadingBase; + + if (myCalib->shading_type == 2) + { + /*3bd8 */ + if ((myCalib->black_shading[colour] != NULL) + && (myCalib->white_shading[colour] != NULL)) + { + for (pos = myCalib->first_position - 1; + pos < myCalib->shadinglength; pos++) + { + if (myCalib->white_shading[colour][pos] == 0) + shadata = myShadingBase; + else + shadata = + myfact / myCalib->white_shading[colour][pos]; + + shadata = min ((shadata * le7cc) / le7d8, 0xff00); + myCalib->black_shading[colour][pos] &= 0xff; + myCalib->black_shading[colour][pos] |= + shadata & 0xff00; + } + } + else + break; + } + else + { + /*3c63 */ + if (myCalib->shading_type == 3) + { + /*3c68 */ + if (myCalib->black_shading[colour] != NULL) + { + for (pos = myCalib->first_position - 1; + pos < myCalib->shadinglength; pos++) + { + if (myCalib->black_shading[colour][pos] == 0) + shadata = myShadingBase; + else + shadata = + myfact / + myCalib->black_shading[colour][pos]; + + shadata = + min ((shadata * le7cc) / le7d8, 0xffc0); + myCalib->black_shading[colour][pos] &= 0x3f; + myCalib->black_shading[colour][pos] |= + shadata & 0xffc0; + } + } + else + break; + } + else + { + /*3ce3 */ + if (myCalib->white_shading[colour] != NULL) + { + for (pos = 0; pos < myCalib->shadinglength; pos++) + { + if (myCalib->white_shading[colour][pos] == 0) + shadata = myShadingBase; + else + shadata = + myfact / + myCalib->white_shading[colour][pos]; + + shadata = + min ((shadata * le7cc) / le7d8, 0xffff); + myCalib->white_shading[colour][pos] = shadata; + } + } + else + break; + } + } + } + } + + /*3d4c */ + bzero (&calbuffers, sizeof (struct st_cal2)); + + /* If black shading correction is enabled ... */ + if ((Regs[0x1cf] & 8) != 0) + Shading_black_apply (dev, Regs, channels, myCalib, &calbuffers); + + /*3e6e */ + + /* If white shading correction is enabled ... */ + if ((Regs[0x1cf] & 4) != 0) + Shading_white_apply (dev, Regs, channels, myCalib, &calbuffers); + + /* 3f74 */ + if (rst == 0) + { + data_bitset (&Regs[0x60b], 0x40, lf9d0); /*-x------*/ + data_bitset (&Regs[0x60b], 0x10, lf9d1); /*---x----*/ + + rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); + } + } + /*3fb5 */ + + DBG (DBG_FNC, "- Shading_apply: %i\n", rst); + + return rst; +} + +static SANE_Int +Bulk_Operation (struct st_device *dev, SANE_Byte op, SANE_Int buffer_size, + SANE_Byte * buffer, SANE_Int * transfered) +{ + SANE_Int iTransferSize, iBytesToTransfer, iPos, rst, iBytesTransfered; + char sdebug[20]; + + if ((op & 0x01) != 0) + strcpy (sdebug, "READ"); + else + strcpy (sdebug, "WRITE"); + DBG (DBG_FNC, "+ Bulk_Operation(op=%s, buffer_size=%i, buffer):\n", sdebug, + buffer_size); + + iBytesToTransfer = buffer_size; + iPos = 0; + rst = OK; + iBytesTransfered = 0; + + if (transfered != NULL) + *transfered = 0; + + iTransferSize = min (buffer_size, RTS_Debug->dmatransfersize); + + if (op != 0) + { + /* Lectura */ + do + { + iTransferSize = min (iTransferSize, iBytesToTransfer); + + iBytesTransfered = + Read_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize); + if (iBytesTransfered < 0) + { + rst = ERROR; + break; + } + else + { + if (transfered != NULL) + *transfered += iBytesTransfered; + } + iPos += iTransferSize; + iBytesToTransfer -= iTransferSize; + } + while (iBytesToTransfer > 0); + } + else + { + /* Escritura */ + do + { + iTransferSize = min (iTransferSize, iBytesToTransfer); + + if (Write_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize) != + OK) + { + rst = ERROR; + break; + } + else + { + if (transfered != NULL) + *transfered += iTransferSize; + } + iPos += iTransferSize; + iBytesToTransfer -= iTransferSize; + } + while (iBytesToTransfer > 0); + } + + DBG (DBG_FNC, "- Bulk_Operation: %i\n", rst); + + return rst; +} + +static SANE_Int +Reading_NotifySize (struct st_device *dev, SANE_Int data, SANE_Int size) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ Reading_NotifySize(data=%i, size=%i):\n", data, size); + + rst = RTS_DMA_Enable_Read (dev, 0x0008, size, data); + + DBG (DBG_FNC, "- Reading_NotifySize: %i\n", rst); + + return rst; +} + +static SANE_Int +Reading_Wait (struct st_device *dev, SANE_Byte Channels_per_dot, + SANE_Byte Channel_size, SANE_Int size, SANE_Int * last_amount, + SANE_Int seconds, SANE_Byte op) +{ + SANE_Int rst; + SANE_Byte cTimeout, executing; + SANE_Int lastAmount, myAmount; + long tick; + + DBG (DBG_FNC, + "+ Reading_Wait(Channels_per_dot=%i, Channel_size=%i, size=%i, *last_amount, seconds=%i, op=%i):\n", + Channels_per_dot, Channel_size, size, seconds, op); + + rst = OK; + cTimeout = FALSE; + lastAmount = 0; + + myAmount = Get_Scanner_Buffer_Size (dev, Channels_per_dot, Channel_size); + if (myAmount < size) + { + /* Wait until scanner fills its buffer */ + if (seconds == 0) + seconds = 10; + tick = GetTickCount () + (seconds * 1000); + + while (cTimeout == FALSE) + { + myAmount = + Get_Scanner_Buffer_Size (dev, Channels_per_dot, Channel_size); + + /* check special case */ + if (op == TRUE) + { + if (((myAmount + 0x450) > size) + || (RTS_IsExecuting (dev, &executing) == FALSE)) + break; + } + + if (myAmount < size) + { + /* Check timeout */ + if (myAmount == lastAmount) + { + /* we are in timeout? */ + if (tick < GetTickCount ()) + { + /* TIMEOUT */ + rst = ERROR; + cTimeout = TRUE; + } + else + usleep (100 * 1000); + } + else + { + /* Amount increased, update tick */ + lastAmount = myAmount; + tick = GetTickCount () + (seconds * 1000); + } + } + else + { + lastAmount = myAmount; + break; /* buffer full */ + } + } + } + + if (last_amount != NULL) + *last_amount = myAmount; + + DBG (DBG_FNC, "- Reading_Wait: %i , last_amount=%i\n", rst, myAmount); + + return rst; +} + +static SANE_Int +RTS_GetImage_GetBuffer (struct st_device *dev, double dSize, + char unsigned *buffer, double *transferred) +{ + SANE_Int rst = ERROR; + SANE_Int itransferred; + double dtransferred = 0; + + DBG (DBG_FNC, "+ RTS_GetImage_GetBuffer(dSize=%f, buffer, transferred):\n", + dSize); + + rst = OK; + dSize /= 2; + + if (dSize > 0) + { + SANE_Int myLength; + SANE_Int iPos = 0; + + do + { + itransferred = 0; + myLength = + (dSize <= + RTS_Debug->dmasetlength) ? dSize : RTS_Debug->dmasetlength; + + if (myLength > 0x1ffe0) + myLength = 0x1ffe0; + + rst = ERROR; + if (Reading_Wait (dev, 0, 1, myLength * 2, NULL, 5, FALSE) == OK) + { + if (Reading_NotifySize (dev, 0, myLength * 2) == OK) + rst = + Bulk_Operation (dev, BLK_READ, myLength * 2, &buffer[iPos], + &itransferred); + } + + if (rst != OK) + break; + + iPos += itransferred; + dSize -= itransferred; + dtransferred += itransferred * 2; + } + while (dSize > 0); + } + + /* Return bytes transferred */ + if (transferred != NULL) + *transferred = dtransferred; + + if (rst != OK) + RTS_DMA_Cancel (dev); + + DBG (DBG_FNC, "- RTS_GetImage_GetBuffer: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer, + struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg) +{ + /*buffer f80c = esp+14 + scancfg f850 = esp+18 + hwdcfg faac = */ + + SANE_Int rst = ERROR; + + DBG (DBG_FNC, "+ RTS_GetImage_Read(buffer, scancfg, hwdcfg):\n"); + + if (buffer != NULL) + { + double dSize = scancfg->bytesperline * scancfg->coord.height; + SANE_Byte exfn; + + if (scancfg->depth == 12) + dSize = (dSize * 3) / 4; + + /*3ff6 */ + exfn = 1; + if (hwdcfg != NULL) + if (hwdcfg->compression != FALSE) + exfn = 0; + + if (exfn != 0) + { + double transferred; + rst = RTS_GetImage_GetBuffer (dev, dSize, buffer, &transferred); + } + + if (rst == OK) + RTS_WaitScanEnd (dev, 1500); + } + + DBG (DBG_FNC, "- RTS_GetImage_Read: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_GetImage (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, + struct st_gain_offset *gain_offset, SANE_Byte * buffer, + struct st_calibration *myCalib, SANE_Int options, + SANE_Int gainmode) +{ + /* 42b8e10 */ + + SANE_Int myvalue; + struct st_scanparams *myscancfg; + struct st_hwdconfig *hwdcfg; + + DBG (DBG_FNC, + "+ RTS_GetImage(*Regs, *scancfg, *gain_offset, *buffer, myCalib, options=0x%08x, gainmode=%i):\n", + options, gainmode); + dbg_ScanParams (scancfg); + + /* Validate arguments */ + if ((Regs == NULL) || (scancfg == NULL)) + return ERROR; + + if ((scancfg->coord.width != 0) && (scancfg->coord.height != 0)) + { + /* Let's make a copy of scan config */ + myscancfg = + (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + if (myscancfg != NULL) + memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); + else + return ERROR; + + /* Allocate space for low level config */ + hwdcfg = (struct st_hwdconfig *) malloc (sizeof (struct st_hwdconfig)); + if (hwdcfg == NULL) + { + free (myscancfg); + return ERROR; + } + else + bzero (hwdcfg, sizeof (struct st_hwdconfig)); + + if (((options & 2) != 0) || ((_B1 (options) & 1) != 0)) + { + /* switch off lamp */ + data_bitset (&Regs[0x146], 0x40, 0); + + Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]); + if (v14b4 == 0) + usleep (1000 * 500); + else + usleep (1000 * 300); + } + + hwdcfg->scantype = scan.scantype; + hwdcfg->use_gamma_tables = ((options & OP_USE_GAMMA) != 0) ? 1 : 0; + hwdcfg->white_shading = ((options & OP_WHITE_SHAD) != 0) ? 1 : 0; + hwdcfg->black_shading = ((options & OP_BLACK_SHAD) != 0) ? 1 : 0; + hwdcfg->motor_direction = + ((options & OP_BACKWARD) != 0) ? MTR_BACKWARD : MTR_FORWARD; + hwdcfg->compression = ((options & OP_COMPRESSION) != 0) ? 1 : 0; + hwdcfg->static_head = ((options & OP_STATIC_HEAD) != 0) ? 1 : 0; + hwdcfg->dummy_scan = (buffer == NULL) ? TRUE : FALSE; + hwdcfg->arrangeline = 0; + hwdcfg->highresolution = + (myscancfg->resolution_x > 1200) ? TRUE : FALSE; + hwdcfg->unk3 = 0; + + /* Set Left coord */ + myscancfg->coord.left += + ((dev->sensorcfg->type == CCD_SENSOR) ? 24 : 50); + + switch (myscancfg->resolution_x) + { + case 1200: + myscancfg->coord.left -= 63; + break; + case 2400: + myscancfg->coord.left -= 126; + break; + } + + if (myscancfg->coord.left < 0) + myscancfg->coord.left = 0; + + RTS_Setup (dev, Regs, myscancfg, hwdcfg, gain_offset); + + /* Setting exposure time */ + switch (scan.scantype) + { + case ST_NORMAL: + if (scan.resolution_x == 100) + { + SANE_Int iValue; + SANE_Byte *myRegs; + + myRegs = + (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (myRegs != NULL) + { + bzero (myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + RTS_Setup (dev, myRegs, &scan, hwdcfg, gain_offset); + + iValue = data_lsb_get (&myRegs[0x30], 3); + data_lsb_set (&Regs[0x30], iValue, 3); + + /*Copy myregisters mexpts to Regs mexpts */ + iValue = data_lsb_get (&myRegs[0x33], 3); + data_lsb_set (&Regs[0x33], iValue, 3); + + iValue = data_lsb_get (&myRegs[0x39], 3); + data_lsb_set (&Regs[0x39], iValue, 3); + + iValue = data_lsb_get (&myRegs[0x3f], 3); + data_lsb_set (&Regs[0x3f], iValue, 3); + + free (myRegs); + } + } + break; + case ST_NEG: + /* Setting exposure times for Negative scans */ + data_lsb_set (&Regs[0x30], myscancfg->expt, 3); + data_lsb_set (&Regs[0x33], myscancfg->expt, 3); + data_lsb_set (&Regs[0x39], myscancfg->expt, 3); + data_lsb_set (&Regs[0x3f], myscancfg->expt, 3); + + data_lsb_set (&Regs[0x36], 0, 3); + data_lsb_set (&Regs[0x3c], 0, 3); + data_lsb_set (&Regs[0x42], 0, 3); + + myvalue = + ((myscancfg->expt + 1) / (data_lsb_get (&Regs[0xe0], 1) + 1)) - 1; + data_lsb_set (&Regs[0xe1], myvalue, 3); + break; + } + + /* 91a0 */ + if (myscancfg->resolution_y > 600) + { + options |= 0x20000000; + if (options != 0) /* Always true ... */ + SetMultiExposure (dev, Regs); + else + myscancfg->coord.top += hwdcfg->startpos; + } + else + SetMultiExposure (dev, Regs); + + /* 91e2 */ + RTS_WriteRegs (dev->usb_handle, Regs); + if (myCalib != NULL) + Shading_apply (dev, Regs, myscancfg, myCalib); + + if (dev->motorcfg->changemotorcurrent != FALSE) + Motor_Change (dev, Regs, + Motor_GetFromResolution (myscancfg->resolution_x)); + + /* mlock = 0 */ + data_bitset (&Regs[0x00], 0x10, 0); + + data_wide_bitset (&Regs[0xde], 0xfff, 0); + + /* release motor */ + Motor_Release (dev); + + if (RTS_Warm_Reset (dev) != 0) + return ERROR; + + SetLock (dev->usb_handle, Regs, + (myscancfg->depth == 16) ? FALSE : TRUE); + + Lamp_SetGainMode (dev, Regs, myscancfg->resolution_x, gainmode); + + if (RTS_WriteRegs (dev->usb_handle, Regs) == OK) + { + if (RTS_Execute (dev) == OK) + RTS_GetImage_Read (dev, buffer, myscancfg, hwdcfg); /*92e7 */ + } + + /*92fc */ + SetLock (dev->usb_handle, Regs, FALSE); + + if ((options & 0x200) != 0) + { + /* switch on lamp */ + data_bitset (&Regs[0x146], 0x40, 1); + + Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]); + /* Wait 3 seconds */ + usleep (1000 * 3000); + } + + /*9351 */ + if (dev->motorcfg->changemotorcurrent == TRUE) + Motor_Change (dev, dev->init_regs, 3); + + free (myscancfg); + free (hwdcfg); + } + + DBG (DBG_FNC, "- RTS_GetImage\n"); + + return OK; +} + +static SANE_Int +Refs_Detect (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution_x, + SANE_Int resolution_y) +{ + struct st_scanparams scancfg; + struct st_gain_offset gain_offset; + SANE_Int rst, gainmode, pwmlamplevel_backup, C, ser1, ler1; + SANE_Byte *image; + + DBG (DBG_FNC, "+ Refs_Detect(*Regs, resolution_x=%i, resolution_y=%i):\n", + resolution_x, resolution_y); + + gainmode = 0; + if (RTS_Debug->use_fixed_pwm == FALSE) + { + /* 3877 */ + SANE_Int pwmdutycycle; + + gainmode = Lamp_GetGainMode (dev, resolution_x, scan.scantype); + pwmdutycycle = (gainmode == 0) ? 0x12 : 0x26; + pwmlamplevel = 0; + PWM_use (dev, 1); + PWM_SetDutyCycle (dev, pwmdutycycle); + + /* Enciende flb lamp */ + Lamp_SetStatus2 (dev, TRUE, FLB_LAMP); + usleep (1000 * 2000); + } + + /* 38d6 */ + pwmlamplevel_backup = pwmlamplevel; + pwmlamplevel = 0; + PWM_use (dev, 1); + + bzero (&gain_offset, sizeof (struct st_gain_offset)); + for (C = CL_RED; C <= CL_BLUE; C++) + { + gain_offset.pag[C] = 3; + gain_offset.vgag1[C] = 4; + gain_offset.vgag2[C] = 4; + } + + /* set configuration to scan a little area at the top-left corner */ + bzero (&scancfg, sizeof (struct st_scanparams)); + scancfg.depth = 8; + scancfg.colormode = CM_GRAY; + scancfg.channel = CL_RED; + scancfg.resolution_x = resolution_x; + scancfg.resolution_y = resolution_y; + scancfg.coord.left = 4; + scancfg.coord.width = (resolution_x * 3) / 10; + scancfg.coord.top = 1; + scancfg.coord.height = (resolution_y * 4) / 10; + scancfg.shadinglength = (resolution_x * 17) / 2; + scancfg.bytesperline = scancfg.coord.width; + + rst = ERROR; + + /* allocate space to store image */ + image = + (SANE_Byte *) malloc ((scancfg.coord.height * scancfg.coord.width) * + sizeof (SANE_Byte)); + if (image != NULL) + { + /* retrieve image from scanner */ + if (RTS_GetImage + (dev, Regs, &scancfg, &gain_offset, image, 0, 0x20000000, + gainmode) == OK) + { + /* same image to disk if required by user */ + if (RTS_Debug->SaveCalibFile != FALSE) + { + dbg_tiff_save ("pre-autoref.tiff", + scancfg.coord.width, + scancfg.coord.height, + scancfg.depth, + CM_GRAY, + scancfg.resolution_x, + scancfg.resolution_y, + image, + scancfg.coord.height * scancfg.coord.width); + } + + /* calculate reference position */ + if (Refs_Analyze_Pattern (&scancfg, image, &ler1, 1, &ser1, 0) == + OK) + { + scan.startpos = scancfg.coord.top + ler1; + scan.leftleading = scancfg.coord.left + ser1; + rst = OK; + } + } + free (image); + } + + pwmlamplevel = pwmlamplevel_backup; + + DBG (DBG_FNC, "- Refs_Detect: scan.startpos=%i, scan.leftleading=%i : %i\n", + scan.startpos, scan.leftleading, rst); + + return OK; +} + +static SANE_Int +Refs_Set (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *myscan, SANE_Int autoref) +{ + SANE_Int rst; + SANE_Int start_pos, left_leading; + struct st_autoref refcfg; + + DBG (DBG_FNC, "+ Refs_Set(*Regs, *myscan, autoref=%i):\n", autoref); + dbg_ScanParams (myscan); + + rst = OK; + + /* get fixed references for given resolution */ + cfg_vrefs_get (dev->sensorcfg->type, myscan->resolution_x, &scan.ler, + &scan.ser); + scan.leftleading = scan.ser; + + /* get auto reference configuration */ + cfg_autoref_get (&refcfg); + + if (refcfg.type != REF_NONE) + { + if (autoref == TRUE) + refcfg.type = REF_AUTODETECT; + + switch (refcfg.type) + { + case REF_AUTODETECT: + /* try to autodetect references scanning a little area */ + if (Refs_Detect (dev, Regs, refcfg.resolution, refcfg.resolution) == + OK) + Refs_Save (dev, scan.leftleading, scan.startpos); + else + rst = ERROR; + + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + break; + + case REF_TAKEFROMSCANNER: + /* Try to get values from scanner */ + if (Refs_Load (dev, &left_leading, &start_pos) == ERROR) + { + if (Refs_Detect + (dev, Regs, refcfg.resolution, refcfg.resolution) == OK) + Refs_Save (dev, left_leading, start_pos); + else + rst = ERROR; + + DBG (DBG_FNC, + " -> blacklinipos:ler=%i, leftBlackpos:ser = %i\n", + scan.startpos, scan.leftleading); + + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + } + else + { + scan.leftleading = left_leading; + scan.startpos = start_pos; + } + break; + } + + if (rst == OK) + { + scan.leftleading *= 4; + scan.startpos = (myscan->resolution_y < 1200) ? + (scan.startpos - 12) * 4 : (scan.startpos - 24) * 4; + + if ((dpi100Lumping == 0) + && (myscan->resolution_x == + Scanmode_minres (dev, myscan->scantype, myscan->colormode))) + scan.ser = ((scan.leftleading + refcfg.offset_x) * 200) / 2400; + else + scan.ser = + ((scan.leftleading + + refcfg.offset_x) * myscan->resolution_x) / 2400; + + scan.ler = + ((scan.startpos + refcfg.offset_y) * myscan->resolution_y) / 2400; + if (myscan->resolution_x <= 300) + scan.ler += 3; + + DBG (DBG_FNC, + " -> After SEROffset and LEROffset, xoffset = %i, yoffset =%i\n", + scan.ser, scan.ler); + } + } + + DBG (DBG_FNC, "- Refs_Set: %i\n", rst); + + return rst; +} + +static SANE_Int +Lamp_SetStatus (struct st_device *dev, SANE_Byte * Regs, SANE_Int turn_on, + SANE_Int lamp) +{ + char sdebug1[10], sdebug2[10]; + + if ((((lamp - 1) | turn_on) & 1) == 1) + strcpy (sdebug1, "Yes"); + else + strcpy (sdebug1, "No"); + + if (lamp == FLB_LAMP) + strcpy (sdebug2, "FLB_LAMP"); + else + strcpy (sdebug2, "TMA_LAMP"); + + DBG (DBG_FNC, "+ Lamp_SetStatus(*Regs, turn_on=%i->%s, lamp=%s)\n", turn_on, + sdebug1, sdebug2); + + RTS_ReadRegs (dev->usb_handle, Regs); + + /* next op depends on chipset */ + switch (dev->chipset->model) + { + case RTS8822BL_03A: + /* register 0xe946 has 2 bits and each one referres one lamp + 0x40: FLB_LAMP | 0x20 : TMA_LAMP + if both were enabled both lamps would be switched on */ + data_bitset (&Regs[0x146], 0x20, ((lamp == TMA_LAMP) && (turn_on == TRUE)) ? 1 : 0); /* TMA */ + data_bitset (&Regs[0x146], 0x40, ((lamp == FLB_LAMP) && (turn_on == TRUE)) ? 1 : 0); /* FLB */ + + data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0); + break; + default: + /* the other chipsets only use one bit to indicate when a lamp is + switched on or not being bit 0x10 in 0xe955 who decides which lamp + is affected */ + /* switch on lamp? yes if TMA_LAMP, else whatever turn_on says */ + data_bitset (&Regs[0x146], 0x40, ((lamp - 1) | turn_on)); + /* what lamp must be switched on? */ + if ((Regs[0x146] & 0x40) != 0) + data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0); + break; + } + + /*42b8cd1 */ + /* switch on/off lamp */ + /*dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0xbf) | (Regs[0x146] & 0x40); */ + dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0x9f) | (Regs[0x146] & 0x60); /*-xx-----*/ + + /* Which lamp */ + dev->init_regs[0x0155] = Regs[0x0155]; + Write_Byte (dev->usb_handle, 0xe946, Regs[0x0146]); + usleep (1000 * 200); + Write_Buffer (dev->usb_handle, 0xe954, &Regs[0x0154], 2); + + DBG (DBG_FNC, "- Lamp_SetStatus\n"); + + return OK; +} + +static void +Lamp_OverDrive (struct st_device *dev, SANE_Int itime, SANE_Int lamp) +{ + long ticks; + SANE_Int pwmdutycycle; + + DBG (DBG_FNC, "+ Lamp_OverDrive(itime=%i, lamp=%i):\n", itime, lamp); + + ticks = GetTickCount () + itime; + + switch (lamp) + { + case TMA_LAMP: + pwmdutycycle = 0x0e; + break; + default: + pwmdutycycle = 0x00; + break; + } + + PWM_SetDutyCycle (dev, pwmdutycycle); + + if (RTS_Debug->warmup == TRUE) + { + DBG (DBG_VRB, "- Lamp Warmup process. Please wait...\n"); + + while (GetTickCount () <= ticks) + usleep (1000 * 200); + } + else + DBG (DBG_FNC, " -> warmup disabled\n"); + + DBG (DBG_FNC, "- Lamp_OverDrive\n"); +} + +static SANE_Int +Get_PAG_Value (SANE_Byte scantype, SANE_Byte color) +{ + SANE_Int rst, iType, iColor; + char sdebug[20]; + + switch (scantype) + { + case ST_NEG: + iType = CALIBNEGATIVEFILM; + break; + case ST_TA: + iType = CALIBTRANSPARENT; + break; + case ST_NORMAL: + iType = CALIBREFLECTIVE; + break; + default: + iType = CALIBREFLECTIVE; + break; + } + + switch (color) + { + case CL_BLUE: + iColor = PAGB; + break; + case CL_GREEN: + iColor = PAGG; + break; + case CL_RED: + iColor = PAGR; + break; + default: + iColor = PAGR; + break; + } + + rst = get_value (iType, iColor, 1, FITCALIBRATE); + + DBG (DBG_FNC, "> Get_PAG_Value(scantype=%s, color=%i): %i\n", + dbg_scantype (sdebug, scantype), color, rst); + + return rst; +} + +static SANE_Byte +Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution, + SANE_Byte scantype) +{ + SANE_Byte ret; + SANE_Int mygain, iValue; + char sdebug[20]; + + switch (scantype) + { + case ST_TA: + ret = 0; + iValue = DPIGAINCONTROL_TA600; + break; + case ST_NEG: + ret = 1; + iValue = DPIGAINCONTROL_NEG600; + break; + default: /* Reflective */ + ret = 1; + iValue = DPIGAINCONTROL600; + break; + } + + mygain = get_value (SCAN_PARAM, iValue, ret, usbfile); + ret = 0; + +/* + +*/ + if (scantype == ST_NORMAL) + { + if (dev->chipset->model == RTS8822L_02A) + { + switch (resolution) + { + case 100: + case 150: + case 300: + case 600: + case 1200: + case 2400: + case 4800: + ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; + break; + } + } + else + { + switch (resolution) + { + case 100: + case 200: + case 300: + case 600: + if (RTS_Debug->usbtype != USB11) + ret = (mygain != 0) ? 1 : 0; + else + ret = (resolution == 100) ? 1 : 0; + break; + case 1200: + case 2400: + ret = 0; + break; + } + } + } + else if (scantype == ST_TA) + { + switch (resolution) + { + /*hp3970 */ + case 100: + case 200: + /*common */ + case 300: + case 600: + case 1200: + case 2400: + /*hp4370 */ + case 150: + case 4800: + ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; + break; + } + } + else + { + /* ST_NEG */ + switch (resolution) + { + case 100: + case 200: + case 300: + case 600: + ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; + break; + case 1200: + case 2400: + case 4800: /*hp4370 */ + ret = 0; + break; + } + } + + DBG (DBG_FNC, "> Lamp_GetGainMode(resolution=%i, scantype=%s): %i\n", + resolution, dbg_scantype (sdebug, scantype), ret); + + return ret; +} + +static SANE_Int +GetOneLineInfo (struct st_device *dev, SANE_Int resolution, + SANE_Int * maximus, SANE_Int * minimus, double *average) +{ + SANE_Int rst = ERROR; + + DBG (DBG_FNC, + "+ GetOneLineInfo(resolution=%i, *maximus, *minimus, *average):\n", + resolution); + + /* Check parameters */ + if ((maximus != NULL) && (minimus != NULL) && (average != NULL)) + { + SANE_Byte *Regs, *image; + SANE_Int a, gainmode; + struct st_gain_offset gain_offset; + struct st_scanparams scancfg; + + Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (Regs != NULL) + { + /* Copy scanner registers */ + memcpy (Regs, &dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + /* Setting some registers */ + for (a = 0x192; a <= 0x19d; a++) + Regs[a] = 0; + + /* Create calibration table */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + gain_offset.edcg1[a] = 256; + gain_offset.edcg2[a] = 0; + gain_offset.odcg1[a] = 256; + gain_offset.odcg2[a] = 0; + gain_offset.vgag1[a] = 4; + gain_offset.vgag2[a] = 4; + gain_offset.pag[a] = Get_PAG_Value (scan.scantype, a); + } + + RTS_GetScanmode (dev, scantype, 0, resolution); + + /* Setting scanning params */ + memset (&scancfg, 0, sizeof (struct st_scanparams)); + scancfg.colormode = CM_COLOR; + scancfg.resolution_x = resolution; + scancfg.resolution_y = resolution; + scancfg.coord.left = 100; + scancfg.coord.width = (resolution * 8.5) - 100; + scancfg.coord.top = 1; + scancfg.coord.height = 1; + scancfg.depth = 8; + scancfg.shadinglength = resolution * 8.5; + scancfg.v157c = scancfg.coord.width * 3; + scancfg.bytesperline = scancfg.v157c; + + /* Reserve buffer for line */ + image = + (SANE_Byte *) malloc (((scancfg.coord.width * 0x21) * 3) * + sizeof (SANE_Byte)); + if (image != NULL) + { + gainmode = + Lamp_GetGainMode (dev, resolution & 0xffff, scan.scantype); + if (RTS_GetImage + (dev, Regs, &scancfg, &gain_offset, image, 0, + OP_STATIC_HEAD, gainmode) != ERROR) + { + /* Read all image to take max min and average colours */ + SANE_Byte *pointer1 = image; + SANE_Byte *pointer2; + SANE_Byte *pointer3; + SANE_Int cmin[3]; /* min values */ + SANE_Int cmax[3]; /* max values */ + double cave[3]; /* average values */ + SANE_Int mysize; + + if (scancfg.colormode != CM_GRAY) + { + pointer2 = image; + pointer3 = image; + } + else + { + pointer2 = image + 1; + pointer3 = image + 2; + } + + for (a = CL_RED; a <= CL_BLUE; a++) + { + cmin[a] = 255; + cmax[a] = 0; + cave[a] = 0; + } + + if (scancfg.coord.height > 0) + { + SANE_Int y, x; + SANE_Byte *mypointer; + SANE_Byte color; + SANE_Int desp[3]; + + desp[CL_RED] = pointer1 - pointer3; + desp[CL_GREEN] = pointer2 - pointer3; + desp[CL_BLUE] = 0; + + for (y = 0; y < scancfg.coord.height; y++) + { + if (scancfg.coord.width > 0) + { + mypointer = pointer3; + + for (x = 0; x < scancfg.coord.width; x++) + { + for (a = CL_RED; a <= CL_BLUE; a++) + { + /* Take colour values */ + color = *(mypointer + desp[a]); + + /* Take max values for each color */ + cmax[a] = max (cmax[a], color); + + /* Take min values for each color */ + cmin[a] = min (cmin[a], color); + + /* Average */ + cave[a] += color; + } + + mypointer += 3; + } + } + + /* point to the pixel that is below */ + pointer1 += scancfg.coord.width * 3; + pointer2 += scancfg.coord.width * 3; + pointer3 += scancfg.coord.width * 3; + } + } + + mysize = scancfg.coord.height * scancfg.coord.width; + if (mysize < 1) + mysize = 1; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + maximus[a] = cmax[a]; + minimus[a] = cmin[a]; + average[a] = cave[a] / mysize; + } + + DBG (DBG_FNC, " -> GetOneLineInfo: max r=%3i g=%3i b=%3i\n", + maximus[CL_RED], maximus[CL_GREEN], maximus[CL_BLUE]); + DBG (DBG_FNC, " -> min r=%3i g=%3i b=%3i\n", + minimus[CL_RED], minimus[CL_GREEN], minimus[CL_BLUE]); + DBG (DBG_FNC, + " -> avg r=%3.0f g=%3.0f b=%3.0f\n", + average[CL_RED], average[CL_GREEN], average[CL_BLUE]); + + rst = OK; + } + + free (image); + } + + free (Regs); + } + } + + DBG (DBG_FNC, "- GetOneLineInfo: %i\n", rst); + + return OK; +} + +static SANE_Int +PWM_GetReady (struct st_device *dev, SANE_Int resolution, + SANE_Int * last_colour, double diff, long totaltime, + SANE_Int interval, SANE_Int value) +{ + /* This function detects when lamp is lightning in maximal intensity */ + + SANE_Int maximus[3] = { 0 }; + SANE_Int minimus[3] = { 0 }; + double average[3] = { 0 }; + SANE_Int maxbigger; + SANE_Int rst; + + DBG (DBG_FNC, + "+ PWM_GetReady(resolution=%i, *unknown, diff=%f, totaltime=%li, interval=%i, value=%i):\n", + resolution, diff, totaltime, interval, value); + + while (GetTickCount () <= totaltime) + { + rst = GetOneLineInfo (dev, resolution, maximus, minimus, average); + if (rst == OK) + { + /* Takes maximal colour value */ + maxbigger = + max (maximus[CL_GREEN], max (maximus[CL_BLUE], maximus[CL_RED])); + + /*breaks when colour intensity increases 'diff' or lower */ + if (abs (maxbigger - *last_colour) < diff) + { + DBG (DBG_FNC, " -> PWM is ready\n"); + break; + } + + *last_colour = maxbigger; + } + usleep (1000 * interval); + } + + DBG (DBG_FNC, "- PWM_GetReady\n"); + + return OK; +} + +static SANE_Int +Lamp_WaitForPWM (struct st_device *dev, SANE_Int resolution, SANE_Int lamp) +{ + struct st_checkstable check; + SANE_Int rst; + + DBG (DBG_FNC, "+ Lamp_WaitForPWM(resolution=%i, lamp=%i):\n", resolution, + lamp); + + rst = cfg_checkstable_get (lamp, &check); + + if (rst == OK) + { + SANE_Int last_colour = 0; + long tick = GetTickCount (); + + tick += check.tottime; + PWM_GetReady (dev, resolution, &last_colour, check.diff * 0.01, + tick, check.interval, -1); + } + + DBG (DBG_FNC, "- Lamp_WaitForPWM: %i\n", rst); + + return OK; +} + +static SANE_Byte +Refs_Counter_Load (struct st_device *dev) +{ + SANE_Byte data = 15; + + DBG (DBG_FNC, "+ Refs_Counter_Load:\n"); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x78, &data) != OK) + data = 15; + + DBG (DBG_FNC, "- Refs_Counter_Load: %i\n", _B0 (data)); + + return data; +} + +static SANE_Int +Refs_Counter_Save (struct st_device *dev, SANE_Byte data) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ Refs_Counter_Save(data=%i):\n", data); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + if (data > 15) + data = 15; + + rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x78, data); + } + + DBG (DBG_FNC, "- Refs_Counter_Save: %i\n", rst); + + return rst; +} + +static SANE_Int +Refs_Counter_Inc (struct st_device *dev) +{ + SANE_Byte data; + + DBG (DBG_FNC, "+ Refs_Counter_Inc:\n"); + + data = Refs_Counter_Load (dev) + 1; + + if (data >= 15) + data = 0; + + Refs_Counter_Save (dev, data); + + DBG (DBG_FNC, "- Refs_Counter_Inc() : Count=%i\n", data); + + return OK; +} + +static SANE_Int +Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, SANE_Int * xpos) +{ + SANE_Int iType; + char sdebug[20]; + + switch (scantype) + { + case 3: + iType = CALIBNEGATIVEFILM; + break; + case 2: + iType = CALIBTRANSPARENT; + break; + default: + iType = CALIBREFLECTIVE; + break; + } + + *xpos = get_value (iType, WSTRIPXPOS, 0, FITCALIBRATE); + *ypos = get_value (iType, WSTRIPYPOS, 0, FITCALIBRATE); + + DBG (DBG_FNC, "> Load_StripCoords(scantype=%s): ypos=%i, xpos=%i\n", + dbg_scantype (sdebug, scantype), *ypos, *xpos); + + return OK; +} + +static SANE_Int +Motor_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction, + SANE_Int ypos) +{ + SANE_Int rst; + SANE_Byte *Regs; + + DBG (DBG_FNC, "+ Motor_Relocate(speed=%i, direction=%i, ypos=%i):\n", speed, + direction, ypos); + + rst = ERROR; + + Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (Regs != NULL) + { + struct st_motormove mymotor; + struct st_motorpos mtrpos; + + bzero (&mymotor, sizeof (struct st_motormove)); + memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + if (speed < dev->motormove_count) + memcpy (&mymotor, dev->motormove[speed], + sizeof (struct st_motormove)); + + /*83fe */ + mtrpos.coord_y = ypos; + mtrpos.options = + MTR_ENABLED | ((direction == MTR_BACKWARD) ? MTR_BACKWARD : + MTR_FORWARD); + mtrpos.v12e448 = 0; + mtrpos.v12e44c = 1; + + Motor_Move (dev, Regs, &mymotor, &mtrpos); + + /* waits 15 seconds */ + RTS_WaitScanEnd (dev, 15000); + + free (Regs); + rst = OK; + } + + DBG (DBG_FNC, "- Motor_Relocate: %i\n", rst); + + return rst; +} + +static SANE_Int +Lamp_SetStatus2 (struct st_device *dev, SANE_Int turnon, SANE_Int lamp) +{ + SANE_Byte Regs[RT_BUFFER_LEN]; + + DBG (DBG_FNC, "> Lamp_SetStatus2(turnon=%i, lamp=%i)\n", turnon, lamp); + + return Lamp_SetStatus (dev, Regs, turnon, lamp); +} + +static SANE_Int +Calib_CreateFixedBuffers () +{ + SANE_Byte channel; + SANE_Int ret; + + DBG (DBG_FNC, "> Calib_CreateFixedBuffers()\n"); + + ret = OK; + channel = 0; + + while ((channel < 3) && (ret == OK)) + { + /* First table */ + if (fixed_black_shading[channel] == NULL) + fixed_black_shading[channel] = + (USHORT *) malloc (0x7f8 * sizeof (USHORT)); + + if (fixed_black_shading[channel] != NULL) + bzero (fixed_black_shading[channel], 0x7f8 * sizeof (USHORT)); + else + ret = ERROR; + + /* Second table */ + if (fixed_white_shading[channel] == NULL) + fixed_white_shading[channel] = + (USHORT *) malloc (0x7f8 * sizeof (USHORT)); + + if (fixed_white_shading[channel] != NULL) + bzero (fixed_white_shading[channel], 0x7f8 * sizeof (USHORT)); + else + ret = ERROR; + + channel++; + } + + return ret; +} + +static SANE_Int +Calib_CreateBuffers (struct st_device *dev, struct st_calibration *buffer, + SANE_Int my14b4) +{ + SANE_Int ebp, ret, channel; + + ret = ERROR; + + buffer->shadinglength = scan.coord.width; + ebp = 0x14; + if ((dpi100Lumping == 0) + && (scan.resolution_x == + Scanmode_minres (dev, scan.scantype, scan.colormode))) + { + buffer->shadinglength = scan.coord.width * 2; + ebp = 0x28; + } + + if (my14b4 != 0) + { + /* 673d */ + if (Calib_CreateFixedBuffers () == OK) + { + for (channel = 0; channel < 3; channel++) + { + buffer->white_shading[channel] = fixed_white_shading[channel]; + buffer->black_shading[channel] = fixed_black_shading[channel]; + } + ret = OK; + } + } + else + { + /* 677f */ + SANE_Int pos; + channel = 0; + while ((channel < 3) && (ret == OK)) + { + buffer->black_shading[channel] = + (USHORT *) malloc (ebp + + (buffer->shadinglength * sizeof (USHORT))); + buffer->white_shading[channel] = + (USHORT *) malloc (ebp + + (buffer->shadinglength * sizeof (USHORT))); + if ((buffer->black_shading[channel] != NULL) + && (buffer->white_shading[channel] != NULL)) + { + for (pos = 0; pos < buffer->shadinglength; pos++) + { + buffer->black_shading[channel][pos] = 0x00; + buffer->white_shading[channel][pos] = 0x4000; + } + ret = OK; + } + else + Calib_FreeBuffers (buffer); + + channel++; + } + } + + DBG (DBG_FNC, "> Calib_CreateBuffers: *buffer, my14b4=%i): %i\n", my14b4, + ret); + + return ret; +} + +static void +Calib_FreeBuffers (struct st_calibration *caltables) +{ + DBG (DBG_FNC, "> Calib_FreeBuffers(*caltables)\n"); + + if (caltables != NULL) + { + SANE_Int channel; + + for (channel = 0; channel < 3; channel++) + { + if (caltables->black_shading[channel] != NULL) + { + free (caltables->black_shading[channel]); + caltables->black_shading[channel] = NULL; + } + + if (caltables->white_shading[channel] != NULL) + { + free (caltables->white_shading[channel]); + caltables->white_shading[channel] = NULL; + } + } + } +} + +static SANE_Int +Calib_LoadConfig (struct st_device *dev, + struct st_calibration_config *calibcfg, SANE_Int scantype, + SANE_Int resolution, SANE_Int bitmode) +{ + SANE_Int section, a; + char sdebug[20]; + struct st_autoref refcfg; + + DBG (DBG_FNC, + "> Calib_LoadConfig(*calibcfg, scantype=%s, resolution=%i, bitmode=%i)\n", + dbg_scantype (sdebug, scantype), resolution, bitmode); + + switch (scantype) + { + case ST_NEG: + section = CALIBNEGATIVEFILM; + break; + case ST_TA: + section = CALIBTRANSPARENT; + break; + default: + section = CALIBREFLECTIVE; + break; + } + + calibcfg->WStripXPos = get_value (section, WSTRIPXPOS, 0, FITCALIBRATE); + calibcfg->WStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE); + calibcfg->BStripXPos = get_value (section, BSTRIPXPOS, 0, FITCALIBRATE); + calibcfg->BStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE); + + /* get calibration wrefs */ + cfg_wrefs_get (dev->sensorcfg->type, bitmode, resolution, scantype, + &calibcfg->WRef[CL_RED], &calibcfg->WRef[CL_GREEN], + &calibcfg->WRef[CL_BLUE]); + + /* 4913 */ + + for (a = CL_RED; a <= CL_BLUE; a++) + { + WRef[a] = _B0 (calibcfg->WRef[a]); + + calibcfg->BRef[a] = get_value (section, BREFR + a, 10, FITCALIBRATE); + calibcfg->OffsetEven1[a] = + get_value (section, OFFSETEVEN1R + a, 256, FITCALIBRATE); + calibcfg->OffsetEven2[a] = + get_value (section, OFFSETEVEN2R + a, 0, FITCALIBRATE); + calibcfg->OffsetOdd1[a] = + get_value (section, OFFSETODD1R + a, 256, FITCALIBRATE); + calibcfg->OffsetOdd2[a] = + get_value (section, OFFSETODD2R + a, 0, FITCALIBRATE); + } + + calibcfg->RefBitDepth = + _B0 (get_value (section, REFBITDEPTH, 8, FITCALIBRATE)); + calibcfg->CalibOffset10n = + _B0 (get_value (section, CALIBOFFSET10N, 3, FITCALIBRATE)); + calibcfg->CalibOffset20n = + _B0 (get_value (section, CALIBOFFSET20N, 0, FITCALIBRATE)); + calibcfg->OffsetHeight = + get_value (section, OFFSETHEIGHT, 10, FITCALIBRATE); + + /* 4ae9 */ + + /* get left coordinate and length to calibrate offset */ + cfg_offset_get (dev->sensorcfg->type, resolution, scantype, + &calibcfg->OffsetPixelStart, &calibcfg->OffsetNPixel); + + /*4c49 */ + calibcfg->OffsetNSigma = get_value (section, OFFSETNSIGMA, 2, FITCALIBRATE); + calibcfg->OffsetTargetMax = + get_value (section, OFFSETTARGETMAX, 0x32, FITCALIBRATE) * 0.01; + calibcfg->OffsetTargetMin = + get_value (section, OFFSETTARGETMIN, 2, FITCALIBRATE) * 0.01; + calibcfg->OffsetBoundaryRatio1 = + get_value (section, OFFSETBOUNDARYRATIO1, 0x64, FITCALIBRATE) * 0.01; + calibcfg->OffsetBoundaryRatio2 = + get_value (section, OFFSETBOUNDARYRATIO2, 0x64, FITCALIBRATE) * 0.01; + + calibcfg->OffsetAvgRatio1 = + get_value (section, OFFSETAVGRATIO1, 0x64, FITCALIBRATE) * 0.01; + calibcfg->OffsetAvgRatio2 = + get_value (section, OFFSETAVGRATIO2, 0x64, FITCALIBRATE) * 0.01; + calibcfg->AdcOffQuickWay = + get_value (section, ADCOFFQUICKWAY, 1, FITCALIBRATE); + calibcfg->AdcOffPredictStart = + get_value (section, ADCOFFPREDICTSTART, 0xc8, FITCALIBRATE); + calibcfg->AdcOffPredictEnd = + get_value (section, ADCOFFPREDICTEND, 0x1f4, FITCALIBRATE); + calibcfg->AdcOffEvenOdd = + get_value (section, ADCOFFEVENODD, 1, FITCALIBRATE); + calibcfg->OffsetTuneStep1 = + _B0 (get_value (section, OFFSETTUNESTEP1, 1, FITCALIBRATE)); + calibcfg->OffsetTuneStep2 = + _B0 (get_value (section, OFFSETTUNESTEP2, 1, FITCALIBRATE)); + calibcfg->CalibGain10n = get_value (section, CALIBGAIN10N, 1, FITCALIBRATE); + calibcfg->CalibGain20n = get_value (section, CALIBGAIN20N, 0, FITCALIBRATE); + calibcfg->CalibPAGOn = get_value (section, CALIBPAGON, 0, FITCALIBRATE); + + for (a = CL_RED; a <= CL_BLUE; a++) + { + calibcfg->OffsetAvgTarget[a] = + _B0 (get_value (section, OFFSETAVGTARGETR + a, 0x0d, FITCALIBRATE)); + calibcfg->PAG[a] = get_value (section, PAGR + a, 3, FITCALIBRATE); + calibcfg->Gain1[a] = get_value (section, GAIN1R + a, 4, FITCALIBRATE); + calibcfg->Gain2[a] = get_value (section, GAIN2R + a, 4, FITCALIBRATE); + calibcfg->WShadingPreDiff[a] = + get_value (section, WSHADINGPREDIFFR + a, -1, FITCALIBRATE); + calibcfg->BShadingPreDiff[a] = + get_value (section, BSHADINGPREDIFFR + a, 2, FITCALIBRATE); + } + + calibcfg->GainHeight = get_value (section, GAINHEIGHT, 0x1e, FITCALIBRATE); + calibcfg->GainTargetFactor = + get_value (section, GAINTARGETFACTOR, 0x5a, FITCALIBRATE) * 0.01; + calibcfg->TotShading = get_value (section, TOTSHADING, 0, FITCALIBRATE); + + /* White shading */ + calibcfg->WShadingOn = get_value (section, WSHADINGON, 3, FITCALIBRATE); + calibcfg->WShadingHeight = + get_value (section, WSHADINGHEIGHT, 0x18, FITCALIBRATE); + + /* Black shading */ + calibcfg->BShadingOn = get_value (section, BSHADINGON, 2, FITCALIBRATE); + calibcfg->BShadingHeight = + get_value (section, BSHADINGHEIGHT, 0x1e, FITCALIBRATE); + + calibcfg->BShadingDefCutOff = + get_value (section, BSHADINGDEFCUTOFF, 0, FITCALIBRATE); + + cfg_autoref_get (&refcfg); + calibcfg->ExternBoundary = refcfg.extern_boundary * 0.01; + + calibcfg->EffectivePixel = + cfg_effectivepixel_get (dev->sensorcfg->type, resolution); + + return OK; +} + +static SANE_Int +Calib_AdcGain (struct st_device *dev, struct st_calibration_config *calibcfg, + SANE_Int arg2, SANE_Int gainmode) +{ + /* + 0606F8E0 04F60738 |Arg1 = 04F60738 + 0606F8E4 0606F90C |Arg2 = 0606F90C calibcfg + 0606F8E8 00000001 |Arg3 = 00000001 arg2 + 0606F8EC 00000001 \Arg4 = 00000001 gainmode + */ + + SANE_Int a, rst; + SANE_Byte *myRegs; /*f1c0 */ + struct st_scanparams *scancfg; /*f17c */ + SANE_Int mywidth; /*lf134 */ + SANE_Int length; /*f13c */ + SANE_Int bytes_to_next_colour; /*f150 */ + SANE_Int bytes_per_pixel; /*f171 f174 */ + SANE_Byte *pgain; /*f144 */ + SANE_Byte *pcalgain; /*f140 */ + SANE_Byte *image; /*f16c */ + SANE_Int lf160, lf154, lf178, lf158; + SANE_Byte *pimage; /*f130 */ + SANE_Byte *ptrval, *ptrval2, *ptrval3 /*f170 */ ; + double dval[3] = { 0.0 }; /*f1a8 f1b0 f1b8 */ + SANE_Int lf138, lf148, lf14c, lf15c; + SANE_Int ival; + + DBG (DBG_FNC, "+ Calib_AdcGain(*calibcfg, arg2=%i, gainmode=%i)\n", arg2, + gainmode); + + myRegs = (SANE_Byte *) malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN); + if (myRegs == NULL) + { + DBG (DBG_FNC, "- Calib_AdcGain: -1\n"); + return ERROR; + } + else + memcpy (myRegs, &calibdata->Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); + + scancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + if (scancfg == NULL) + { + free (myRegs); + + DBG (DBG_FNC, "- Calib_AdcGain: -1\n"); + + return ERROR; + } + else + memcpy (scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); + + Lamp_SetGainMode (dev, myRegs, scancfg->resolution_x, gainmode); + + scancfg->depth = 8; + + /* set coordinates */ + if ((scan.scantype > 0) && (scan.scantype < 4)) + scancfg->coord.left += scan.ser; + + if ((scancfg->coord.width & 1) == 0) + scancfg->coord.width++; + + scancfg->coord.top = 1; + scancfg->coord.height = calibcfg->OffsetHeight; + + switch (scancfg->colormode) + { + case CM_GRAY: + case CM_LINEART: + bytes_to_next_colour = 0; + bytes_per_pixel = 1; + length = scancfg->coord.width; + break; + default: /* CM_COLOR */ + /* c027 */ + bytes_to_next_colour = 1; + length = scancfg->coord.width * 3; + if (scancfg->samplerate == LINE_RATE) + { + bytes_to_next_colour = scancfg->coord.width; + bytes_per_pixel = 1; + } + else + bytes_per_pixel = 3; + break; + } + + /*7fc7 */ + scancfg->v157c = length; + scancfg->bytesperline = length; + + mywidth = scancfg->coord.width; + + if (arg2 != 0) + { + pgain = &calibdata->gain_offset.vgag1[0]; + pcalgain = &calibcfg->Gain1[0]; + } + else + { + /*7ff2 */ + pgain = &calibdata->gain_offset.vgag2[0]; + pcalgain = &calibcfg->Gain2[0]; + } + + /*8002 */ + /* Allocate space for image | size = 132912 */ + image = + (SANE_Byte *) malloc (sizeof (SANE_Byte) * + ((scancfg->coord.height + 16) * length)); + if (image == NULL) + { + free (myRegs); + free (scancfg); + + DBG (DBG_FNC, "- Calib_AdcGain: -1\n"); + + return ERROR; + } + + /* Lets read image */ + if (RTS_GetImage + (dev, myRegs, scancfg, &calibdata->gain_offset, image, NULL, + OP_STATIC_HEAD, gainmode) != OK) + { + free (myRegs); + free (scancfg); + free (image); + + DBG (DBG_FNC, "- Calib_AdcGain: -1\n"); + + return ERROR; + } + + lf138 = 0xff; + lf160 = 0xff; + lf154 = 0xff; /*min value? */ + lf178 = 0; /*max value? */ + lf148 = 0; + lf14c = 0; + pimage = image; + ptrval3 = pimage + (bytes_to_next_colour * 2); + + for (a = CL_RED; a <= CL_BLUE; a++) + { + calibcfg->unk1[a] = 0; + calibcfg->unk2[a] = 0xff; + } + + if (mywidth > 0) + { + /*8104 */ + SANE_Int pos, myheight /*f164 */ ; + SANE_Int value; + + for (pos = mywidth; pos > 0; pos--) + { + lf158 = 0; + lf15c = 0; + value = 0; + ptrval2 = pimage + bytes_to_next_colour; + + if (scancfg->coord.height > 0) + { + ptrval = pimage; + for (myheight = 0; myheight < scancfg->coord.height; myheight++) + { + value += *ptrval; + lf15c += *ptrval2; + lf158 += *ptrval3; + + ptrval += length; + ptrval2 += length; + ptrval3 += length; + } + } + + /*816e */ + lf154 = min (lf154, value / scancfg->coord.height); + lf14c = max (lf14c, value / scancfg->coord.height); + + lf160 = min (lf160, lf15c / scancfg->coord.height); + lf148 = max (lf148, lf15c / scancfg->coord.height); + + lf138 = min (lf138, lf158 / scancfg->coord.height); + lf178 = max (lf178, lf158 / scancfg->coord.height); + + calibcfg->unk1[CL_RED] = max (calibcfg->unk1[CL_RED], lf14c); + calibcfg->unk1[CL_GREEN] = min (calibcfg->unk1[CL_GREEN], lf148); + calibcfg->unk1[CL_BLUE] = max (calibcfg->unk1[CL_BLUE], lf178); + + calibcfg->unk2[CL_RED] = min (calibcfg->unk1[CL_RED], lf154); + calibcfg->unk2[CL_GREEN] = min (calibcfg->unk1[CL_GREEN], lf160); + calibcfg->unk2[CL_BLUE] = min (calibcfg->unk1[CL_BLUE], lf138); + + pimage += bytes_per_pixel; + ptrval3 = pimage + (bytes_to_next_colour * 2); + dval[CL_RED] += lf14c & 0xffff; + dval[CL_GREEN] += lf148 & 0xffff; + dval[CL_BLUE] += lf178 & 0xffff; + } + } + + /*82b0 */ + dval[0] /= mywidth; + dval[1] /= mywidth; + dval[2] /= mywidth; + + DBG (DBG_FNC, + "> adcgain : r=%f, g=%f, b=%f - peak-R=%i, peak-G=%i, peak-B=%i\n", + dval[0], dval[1], dval[2], calibcfg->unk1[0], calibcfg->unk1[1], + calibcfg->unk1[2]); + + if (scancfg->colormode == CM_COLOR) + { + /*8353 */ + double *pdval; /*f138 */ + double dvalue; + SANE_Int *prefs; /*f134 */ + + pdval = &dval[0]; + prefs = &calibcfg->WRef[0]; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + dvalue = + ((((*prefs * (1 << scancfg->depth)) * + calibcfg->GainTargetFactor) * 0.00390625) / *pdval) * ((44 - + *pgain) + / 40); + if (dvalue > 0.9090909090909091) + { + /*83d7 */ + dvalue = min (44 - (40 / dvalue), 31); + ival = dvalue; + *pgain = _B0 (ival); + *pcalgain = _B0 (ival); + } + else + { + *pgain = 0; + *pcalgain = 0; + } + + /*840d */ + prefs++; + pdval++; + pgain++; + pcalgain++; + } + } + else + { + /*843c */ + /*falta codigo */ + double dvalue; + + dvalue = + ((44 - + *pgain) / 40) * ((((1 << scancfg->depth) * + calibcfg->WRef[scancfg->channel]) * 0.9) * + 0.00390625) / 17.08509389671362; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + if (dvalue > 0.9090909090909091) + { + dvalue = min (44 - (40 / dvalue), 31); + ival = dvalue; + *pgain = _B0 (ival); + *pcalgain = _B0 (ival); + } + else + { + /*84e3 */ + *pgain = 0; + *pcalgain = 0; + } + + pgain++; + pcalgain++; + } + } + + /*84fa */ + /* Save buffer */ + if (RTS_Debug->SaveCalibFile != FALSE) + { + dbg_tiff_save ("adcgain.tiff", + scancfg->coord.width, + scancfg->coord.height, + scancfg->depth, + CM_COLOR, + scancfg->resolution_x, + scancfg->resolution_y, + image, (scancfg->coord.height + 16) * length); + } + + /* free memory */ + free (image); + free (myRegs); + free (scancfg); + + rst = ERROR; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + if (calibcfg->unk1[a] >= calibcfg->OffsetAvgTarget[a] + 5) + { + rst = OK; + break; + } + } + + /* v14b8 = (rst == OK)? 0: 1; */ + DBG (DBG_FNC, "- Calib_AdcGain: %i\n", rst); + + return rst; +} + +static SANE_Int +GainOffset_Save (struct st_device *dev, SANE_Int * offset, SANE_Byte * gain) +{ + SANE_Int rst = OK; + + DBG (DBG_FNC, "+ GainOffset_Save(*offset, *gain):\n"); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + if ((offset != NULL) && (gain != NULL)) + { + SANE_Int a, crc, value; + + crc = 0x5B; + for (a = CL_RED; a <= CL_BLUE; a++) + { + value = (*gain << 9) | *offset; + crc = _B0 (abs (crc - _B0 (value))); + rst = + RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (a * 2), value); + } + + if (rst == OK) + rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, crc); + } + else + rst = ERROR; + } + + DBG (DBG_FNC, "- GainOffset_Save: %i\n", rst); + + return rst; +} + +static SANE_Int +Calib_PAGain (struct st_device *dev, struct st_calibration_config *calibcfg, + SANE_Int gainmode) +{ + SANE_Byte *Regs; + struct st_scanparams *scancfg; + SANE_Int channel_size; + SANE_Int bytes_to_next_colour = 0; + SANE_Int bytes_per_pixel = 0; + SANE_Int length = 0; + SANE_Byte *image; + double rst; + SANE_Int ret = ERROR; + + DBG (DBG_FNC, "+ Calib_PAGain(*calibcfg, gainmode=%i)\n", gainmode); + + Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + if (Regs != NULL) + { + scancfg = + (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + if (scancfg != NULL) + { + memcpy (Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (scancfg, &calibdata->scancfg, + sizeof (struct st_scanparams)); + + if (scan.scantype == ST_NORMAL) + { + /* bfa5 */ + scancfg->coord.left = scan.ser; + scancfg->coord.width = (scancfg->sensorresolution * 17) / 2; + } + else + { + scancfg->coord.left = scan.ser + v0750; + scancfg->coord.width = (scancfg->sensorresolution * 3) / 2; + } + + /* bfca */ + if ((scancfg->coord.width & 1) == 1) + scancfg->coord.width++; + + scancfg->coord.top = 1; + scancfg->coord.height = calibcfg->OffsetHeight; + + channel_size = (scancfg->depth > 8) ? 2 : 1; + + switch (scancfg->colormode) + { + case CM_GRAY: + case CM_LINEART: + bytes_to_next_colour = 0; + bytes_per_pixel = 1; + length = channel_size * scancfg->coord.width; + break; + default: /* CM_COLOR */ + /* c027 */ + bytes_to_next_colour = 1; + length = (channel_size * scancfg->coord.width) * 3; + if (scancfg->samplerate == LINE_RATE) + { + bytes_to_next_colour = scancfg->coord.width; + bytes_per_pixel = 1; + } + else + bytes_per_pixel = 3; + break; + } + + /* c070 */ + scancfg->v157c = length; + + image = + (SANE_Byte *) malloc ((scancfg->coord.height * length) * + sizeof (SANE_Byte)); + if (image != NULL) + { + ret = + RTS_GetImage (dev, Regs, scancfg, &calibdata->gain_offset, + image, 0, OP_STATIC_HEAD, gainmode); + if (ret == OK) + { + /* 429c105 */ + SANE_Int a; + SANE_Byte *ptr[3]; + SANE_Int vmin[3] = { 255, 255, 255 }; /* f16c|f16e|f170 */ + SANE_Int vmax[3] = { 0, 0, 0 }; /* f164|f166|f168 */ + SANE_Int total[3]; + + ptr[CL_RED] = image; + ptr[CL_GREEN] = image + bytes_to_next_colour; + ptr[CL_BLUE] = image + (bytes_to_next_colour * 2); + + if (scancfg->coord.width > 0) + { + SANE_Int pos, b; + + for (pos = 0; pos < scancfg->coord.width; pos++) + { + total[CL_BLUE] = 0; + total[CL_GREEN] = 0; + total[CL_RED] = 0; + + for (a = 0; a < scancfg->coord.height; a++) + { + for (b = CL_RED; b <= CL_BLUE; b++) + total[b] += + *(ptr[b] + + ((scancfg->coord.height - a) * length)); + } + + /* c1a5 */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + total[a] /= scancfg->coord.height; + vmin[a] = min (vmin[a], total[a]); + vmax[a] = max (vmax[a], total[a]); + + ptr[a] += bytes_per_pixel; + } + } + } + + /* 429c234 */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + rst = + (calibcfg->WRef[a] * calibcfg->GainTargetFactor) / + vmax[a]; + if (rst <= 1.5) + { + if (rst <= 1.286) + { + if (rst <= 1.125) + calibdata->gain_offset.pag[a] = 0; + else + calibdata->gain_offset.pag[a] = 1; + } + else + calibdata->gain_offset.pag[a] = 2; + } + else + calibdata->gain_offset.pag[a] = 3; + } + } + free (image); + } + free (scancfg); + } + free (Regs); + } + + DBG (DBG_FNC, "- Calib_PAGain: %i\n", ret); + + return ret; +} + +static SANE_Int +Chipset_ID (struct st_device *dev) +{ + SANE_Int ret; + + if (Read_Word (dev->usb_handle, 0xfe3c, &ret) == OK) + ret = _B0 (ret); + else + ret = 0; + + DBG (DBG_FNC, "> Chipset_ID(): %i\n", ret); + + return ret; +} + +static SANE_Int +Chipset_Name (struct st_device *dev, char *name, SANE_Int size) +{ + SANE_Int rst = ERROR; + + if (name != NULL) + { + strncpy (name, dev->chipset->name, size); + rst = OK; + } + + return rst; +} + +static SANE_Int +Refs_Load (struct st_device *dev, SANE_Int * left_leading, + SANE_Int * start_pos) +{ + SANE_Int ret = OK; + + DBG (DBG_FNC, "+ Refs_Load:\n"); + + *start_pos = 0; + *left_leading = 0; + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + SANE_Int data; + + ret = ERROR; + + if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6a, &data) == OK) + { + *left_leading = data; + if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6c, &data) == OK) + { + *start_pos = data; + if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6e, &data) == OK) + { + if ((_B0 (*start_pos + *left_leading + data)) == 0x5a) + ret = OK; + } + } + } + } + + DBG (DBG_FNC, "- Refs_Load(start_pos=%i, left_leading=%i) : %i\n", + *start_pos, *left_leading, ret); + + return ret; +} + +static SANE_Int +Refs_Save (struct st_device *dev, SANE_Int left_leading, SANE_Int start_pos) +{ + SANE_Int ret = OK; + + DBG (DBG_FNC, "+ Refs_Save(left_leading=%i, start_pos=%i)\n", left_leading, + start_pos); + + /* check if chipset supports accessing eeprom */ + if ((dev->chipset->capabilities & CAP_EEPROM) != 0) + { + ret = ERROR; + + if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6a, left_leading) == OK) + { + if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6c, start_pos) == OK) + { + SANE_Byte data = _B0 (0x5a - (start_pos + left_leading)); + ret = RTS_EEPROM_WriteByte (dev->usb_handle, 0x6e, data); + } + } + } + + DBG (DBG_FNC, "- Refs_Save: %i\n", ret); + + return ret; +} + +static SANE_Int +Calib_AdcOffsetRT (struct st_device *dev, + struct st_calibration_config *calibcfg, SANE_Int value) +{ +/* +05EFF8E4 04F10738 |Arg1 = 04F10738 +05EFF8E8 05EFF90C |Arg2 = 05EFF90C calibcfg +05EFF8EC 00000001 \Arg3 = 00000001 value +*/ + SANE_Byte Regs[RT_BUFFER_LEN]; /*f1c4 */ + SANE_Int channels_per_dot; /*f108 */ + struct st_scanparams scancfg; /*f18c */ + SANE_Int *pedcg; /*f114 */ + SANE_Int *podcg; /*f118 */ + SANE_Int *poffseteven; /*f130 */ + SANE_Int *poffsetodd; /*f128 */ + SANE_Int channel; + SANE_Int avgtarget[3]; /*f1b8 f1bc f1c0 */ + SANE_Byte *scanbuffer; /*f0f8 */ + SANE_Int scan_options; /*f12c */ + SANE_Int highresolution; /*f144 */ + double dbValues[3] = { 0, 0, 0 }; /*f148 f14c f150 */ + SANE_Int do_loop; /*f0ec */ + SANE_Int gainmode; + SANE_Byte *ptr; /*f0f4 */ + SANE_Byte *mvgag; /*f0e4 *//*f10c */ + USHORT wvalues[9]; /*0856 0858 085a 085c 085e 0860 0862 0864 0866 */ + SANE_Int imgcount = 0; + /* myoffsetnpixel = f120 */ + /* desp f0e8 & f140 */ + + DBG (DBG_FNC, "+ Calib_AdcOffsetRT(*calibcfg, value=%i)\n", value); + + memcpy (&Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); + + channels_per_dot = (calibdata->scancfg.colormode == CM_COLOR) ? 3 : 1; + + if (value != 0) + { + pedcg = &calibdata->gain_offset.edcg1[CL_RED]; + podcg = &calibdata->gain_offset.odcg1[CL_RED]; + poffseteven = &calibcfg->OffsetEven1[CL_RED]; + poffsetodd = &calibcfg->OffsetOdd1[CL_RED]; + } + else + { + /*c37c */ + pedcg = &calibdata->gain_offset.edcg2[CL_RED]; + podcg = &calibdata->gain_offset.odcg2[CL_RED]; + poffseteven = &calibcfg->OffsetEven2[CL_RED]; + poffsetodd = &calibcfg->OffsetOdd2[CL_RED]; + } + + /*c3a4 */ + scancfg.coord.left = calibcfg->OffsetPixelStart; + + if (channels_per_dot > 0) + { + for (channel = 0; channel < channels_per_dot; channel++) + { + avgtarget[channel] = calibcfg->OffsetAvgTarget[channel] << 8; + if (avgtarget[channel] == 0) + avgtarget[channel] = 0x80; + } + } + + /* set image coordinates to scan */ + scancfg.coord.width = calibcfg->OffsetNPixel; + if ((scancfg.coord.width & 1) == 0) + scancfg.coord.width++; + + scancfg.bytesperline = channels_per_dot * scancfg.coord.width; + scancfg.coord.top = 1; + scancfg.coord.height = calibcfg->OffsetHeight; + scancfg.depth = 8; + + /* allocate memory to store image */ + scanbuffer = + (SANE_Byte *) malloc ((scancfg.bytesperline * calibcfg->OffsetHeight) * + sizeof (SANE_Byte)); + if (scanbuffer == NULL) + return ERROR; + + /*42ac477 */ + scan_options = (linedarlampoff == 1) ? 1 : 0x101; + highresolution = (scancfg.sensorresolution >= 1200) ? TRUE : FALSE; + + do + { + if (channels_per_dot > 0) + { + for (channel = 0; channel < channels_per_dot; channel++) + dbValues[channel] = + (40 / (44 - calibdata->gain_offset.vgag2[channel])) * (40 / + (44 - + calibdata-> + gain_offset. + vgag1 + [channel])); + } + + /*429c50f */ + /* Get Image */ + gainmode = Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype); + if (RTS_GetImage + (dev, Regs, &scancfg, &calibdata->gain_offset, scanbuffer, 0, + scan_options, gainmode) != OK) + { + free (scanbuffer); + return ERROR; + } + + /*429c55f */ + /* Save retrieved image */ + if (RTS_Debug->SaveCalibFile != FALSE) + { + char fname[30]; + + imgcount++; + if (snprintf (fname, 30, "adcoffset_rt%i.tiff", imgcount) > 0) + dbg_tiff_save (fname, + scancfg.coord.width, + scancfg.coord.height, + scancfg.depth, + CM_COLOR, + scancfg.resolution_x, + scancfg.resolution_y, + scanbuffer, + scancfg.bytesperline * calibcfg->OffsetHeight); + } + + /*429c5a5 */ + do_loop = FALSE; + + if (highresolution == TRUE) + { + /* f0fc = f0e4 = channel */ + SANE_Int lf104; + SANE_Int *mydcg; /*f0f4 */ + USHORT *mywvalue; /*ebp */ + + SANE_Byte is_ready[6]; /*f174 f178 f17c f180 f184 f18c */ + SANE_Byte *ptr_ready; /*f11c */ + SANE_Int colour; + + for (channel = 0; channel < 6; channel++) + is_ready[channel] = FALSE; + + if (channels_per_dot <= 0) + break; + + ptr = scanbuffer; + mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1; + + for (channel = 0; channel < channels_per_dot; channel++) + { + for (lf104 = 0; lf104 < 2; lf104++) + { + if (lf104 == 0) + { + mywvalue = &wvalues[channel]; + mydcg = pedcg; + ptr_ready = &is_ready[0]; + } + else + { + /*1645 */ + mywvalue = &wvalues[3]; + mydcg = podcg; + ptr_ready = &is_ready[3]; + } + + /*1658 */ + if (ptr_ready[channel] == FALSE) + { + colour = 0; + if (lf104 < calibcfg->OffsetNPixel) + { + SANE_Int dot; + + for (dot = 0; + dot < (calibcfg->OffsetNPixel - lf104 + 1) / 2; + dot++) + colour += + scanbuffer[mvgag[(lf104 * channels_per_dot)] + + (dot * (channels_per_dot * 2))]; + } + + /*c6b2 */ + colour = colour << 8; + if (colour == 0) + { + /*c6b9 */ + if (mydcg[channel] != 0x1ff) + { + /*c6d5 */ + mydcg[channel] = 0x1ff; + do_loop = TRUE; + } + else + ptr_ready[channel] = TRUE; + } + else + { + SANE_Int myesi; + SANE_Int d; + + /*c6e8 */ + if (*mywvalue == 0) + mywvalue += 2; + + colour /= (calibcfg->OffsetNPixel / 2); + if (colour >= avgtarget[channel]) + { + colour -= avgtarget[channel]; + myesi = 0; + } + else + { + colour = avgtarget[channel] - colour; + myesi = 1; + } + + d = mydcg[channel]; + if (d < 0x100) + d = 0xff - d; + + if (myesi != 0) + { + /*c76e */ + if ((d + colour) > 0x1ff) + { + if (*mvgag > 0) + { + *mvgag = *mvgag - 1; + do_loop = TRUE; + } + else + ptr_ready[channel] = TRUE; /*c7a0 */ + } + else + d += colour; + } + else + { + /*c7ad */ + if (colour > d) + { + if (*mvgag > 0) + { + *mvgag = *mvgag - 1; + do_loop = TRUE; + } + else + ptr_ready[channel] = TRUE; + } + else + d -= colour; + } + + /*c7dd */ + mydcg[channel] = (d < 0x100) ? 0x100 - d : d; + } + + dbg_calibtable (&calibdata->gain_offset); + } + } + + /*c804 */ + mvgag++; + } + } + else + { + /* Low resolution */ + + SANE_Byte is_ready[3]; + SANE_Int colour; + + /*429c845 */ + for (channel = 0; channel < channels_per_dot; channel++) + is_ready[channel] = FALSE; + + if (channels_per_dot <= 0) + break; + + ptr = scanbuffer; + mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1; + + for (channel = 0; channel < channels_per_dot; channel++) + { + if (is_ready[channel] == FALSE) + { + colour = 0; + if (calibcfg->OffsetNPixel > 0) + { + SANE_Int dot; + + /* Take one channel colour values from offsetnpixel pixels */ + for (dot = 0; dot < calibcfg->OffsetNPixel; dot++) + colour += *(ptr + (dot * channels_per_dot)); + } + + colour <<= 8; + if (colour == 0) + { + if (pedcg[channel] != 0x1ff) + { + do_loop = TRUE; + podcg[channel] = 0x1ff; + pedcg[channel] = 0x1ff; + } + else + is_ready[channel] = TRUE; + } + else + { + /*c8f7 */ + SANE_Int myesi; + SANE_Int op1, op2, op3; + + /* Get colour average */ + colour /= calibcfg->OffsetNPixel; + + /* get absolute difference with avgtarget */ + myesi = (colour > avgtarget[channel]) ? 0 : 1; + colour = abs (avgtarget[channel] - colour); + + if (scancfg.resolution_x > 600) + { + /*c923 */ + if (wvalues[channel + 3] == 0) + wvalues[channel + 3]++; + + if (wvalues[channel] == 0) + wvalues[channel]++; + + op3 = max (wvalues[channel], wvalues[channel + 3]); + } + else + { + if (wvalues[channel + 6] == 0) + wvalues[channel + 6]++; + + op3 = wvalues[channel + 6]; + } + + /*c9d3 */ + op1 = (SANE_Int) (colour / (dbValues[channel] * op3)); + op2 = + (pedcg[channel] < + 0x100) ? pedcg[channel] - 0xff : pedcg[channel]; + + if (myesi != 0) + { + /*c9f5 */ + if (((op2 + op1) & 0xffff) > 0x1ff) + { + if (*mvgag != 0) + { + do_loop = TRUE; + *mvgag = *mvgag - 1; + } + else + is_ready[channel] = TRUE; + } + else + op2 += op1; + } + else + { + /*ca31 */ + if (op1 > op2) + { + if (*mvgag > 0) + { + do_loop = TRUE; + *mvgag = *mvgag - 1; + } + else + is_ready[channel] = TRUE; + } + else + op2 -= op1; + } + + /*ca54 */ + if (op2 < 0x100) + op2 = 0x100 - op2; + + pedcg[channel] = op2; + podcg[channel] = op2; + } + } + /*ca6f */ + ptr++; + mvgag++; + dbg_calibtable (&calibdata->gain_offset); + } + } + } + while (do_loop != FALSE); + + /*429cad1 */ + for (channel = 0; channel < 3; channel++) + { + poffseteven[channel] = + (pedcg[channel] < 0x100) ? 0xff - pedcg[channel] : pedcg[channel]; + poffsetodd[channel] = + (podcg[channel] < 0x100) ? 0xff - podcg[channel] : podcg[channel]; + } + + free (scanbuffer); + + return OK; +} + +static void +Calib_LoadCut (struct st_device *dev, struct st_scanparams *scancfg, + SANE_Int scantype, struct st_calibration_config *calibcfg) +{ + double mylong; /*ee78 */ + double mylong2; + /**/ SANE_Int channel[3]; + SANE_Int a; + + cfg_shading_cut_get (dev->sensorcfg->type, scancfg->depth, + scancfg->resolution_x, scantype, &channel[0], + &channel[1], &channel[2]); + + mylong = 1 << scancfg->depth; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + mylong2 = channel[a]; + calibcfg->ShadingCut[a] = (mylong * mylong2) * 0.000390625; + } +} + +static SANE_Int +Calib_BWShading (struct st_calibration_config *calibcfg, + struct st_calibration *myCalib, SANE_Int gainmode) +{ + /* + 0603F8E4 0603F90C |Arg1 = 0603F90C calibcfg + 0603F8E8 0603FAAC |Arg2 = 0603FAAC myCalib + 0603F8EC 00000001 \Arg3 = 00000001 gainmode + */ + + /*falta codigo */ + + /*silence gcc */ + calibcfg = calibcfg; + myCalib = myCalib; + gainmode = gainmode; + + return OK; +} + +static SANE_Int +Calib_WhiteShading_3 (struct st_device *dev, + struct st_calibration_config *calibcfg, + struct st_calibration *myCalib, SANE_Int gainmode) +{ +/* +05EDF8E0 04F00738 |Arg1 = 04F00738 +05EDF8E4 05EDF90C |Arg2 = 05EDF90C calibcfg +05EDF8E8 05EDFAAC |Arg3 = 05EDFAAC myCalib +05EDF8EC 00000001 \Arg4 = 00000001 gainmode +*/ + SANE_Byte *myRegs; /*f1bc */ + struct st_scanparams scancfg; /*f170 */ + SANE_Int myWidth; /*f14c */ + SANE_Int lf168, bytes_per_pixel; + SANE_Int bytes_per_line; + /**/ SANE_Int a; + double lf1a4[3]; + SANE_Int otherheight; /*f150 */ + SANE_Int otherheight2; + SANE_Int lf12c; + SANE_Int lf130; + double *buffer1; /*f138 */ + double *buffer2; /*f144 */ + SANE_Byte *scanbuffer; /*f164 */ + SANE_Byte *ptr; /*f148 */ + SANE_Int position; /*f140 */ + SANE_Int lf13c, myHeight; + SANE_Int myESI, myEDI; + SANE_Int channel; /*f134 */ + double myst; + double sumatorio; + SANE_Int rst; + + DBG (DBG_FNC, "> Calib_WhiteShading3(*calibcfg, *myCalib, gainmode=%i)\n", + gainmode); + + myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); + + Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode); + + rst = OK; + scancfg.resolution_y = 200; + switch (scan.scantype) + { + case ST_NORMAL: + /*a184 */ + scancfg.coord.left += scan.ser; + scancfg.coord.width &= 0xffff; + break; + case ST_TA: + case ST_NEG: + scancfg.coord.left += scan.ser; + break; + } + + /*a0e5 */ + /* Set resolution */ + if ((dpi100Lumping == 0) + && (scancfg.resolution_x == + Scanmode_minres (dev, scancfg.scantype, scancfg.colormode))) + { + scancfg.resolution_y = 200; + scancfg.resolution_x = 200; + scancfg.coord.width = + min (scancfg.coord.width * 2, scancfg.shadinglength); + } + + /*a11b */ + if ((scancfg.coord.width & 1) != 0) + scancfg.coord.width++; + + scancfg.coord.top = 1; + scancfg.coord.height = calibcfg->WShadingHeight; + + switch (scancfg.colormode) + { + case CM_GRAY: + case CM_LINEART: + myWidth = scancfg.coord.width; + lf168 = 0; + bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth; + bytes_per_pixel = 1; + break; + default: /* CM_COLOR */ + myWidth = scancfg.coord.width * 3; + bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth; + lf168 = (scancfg.samplerate == LINE_RATE) ? scancfg.coord.width : 1; + bytes_per_pixel = (scancfg.samplerate == PIXEL_RATE) ? 3 : 1; + break; + } + + /*a1e8 */ + scancfg.v157c = bytes_per_line; + scancfg.bytesperline = bytes_per_line; + + for (a = 0; a < 3; a++) + lf1a4[a] = (calibcfg->WRef[a] * (1 << scancfg.depth)) >> 8; + + /* debug this code because if it's correct, lf130 and lf12c are always 2 */ + otherheight = calibcfg->WShadingHeight - 3; + otherheight -= (otherheight - 4); + otherheight2 = otherheight / 2; + otherheight -= otherheight2; + lf130 = otherheight2; + lf12c = otherheight; + + buffer1 = (double *) malloc (otherheight * sizeof (double)); + if (buffer1 == NULL) + return ERROR; + + buffer2 = (double *) malloc (otherheight * sizeof (double)); + if (buffer2 == NULL) + { + free (buffer1); + return ERROR; + } + + scanbuffer = + (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) * + sizeof (SANE_Byte)); + if (scanbuffer == NULL) + { + free (buffer1); + free (buffer2); + return ERROR; + } + + /* Scan image */ + myCalib->shading_enabled = FALSE; + rst = + RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, scanbuffer, + myCalib, 0x20000080, gainmode); + + for (a = 0; a < 3; a++) + myCalib->WRef[a] *= ((1 << scancfg.depth) >> 8); + + if (rst == ERROR) + { + free (buffer1); + free (buffer2); + free (scanbuffer); + return ERROR; + } + + if (scancfg.depth > 8) + { + /*a6d9 */ + position = 0; + sumatorio = 0; + if (myWidth > 0) + { + do + { + switch (scancfg.colormode) + { + case CM_GRAY: + case CM_LINEART: + channel = 0; + lf13c = position; + break; + default: /*CM_COLOR */ + if (scancfg.samplerate == PIXEL_RATE) + { + /* pixel rate */ + channel = position % bytes_per_pixel; + lf13c = position / bytes_per_pixel; + } + else + { + /* line rate */ + channel = position / lf168; + lf13c = position % lf168; + } + break; + } + + /*a743 */ + if (lf130 > 0) + bzero (buffer1, lf130 * sizeof (double)); + + /*a761 */ + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + buffer2[a] = (1 << scancfg.depth) - 1.0; + } + + /*a78f */ + myESI = 0; + myEDI = 0; + ptr = scanbuffer + (position * 2); + myHeight = 0; + + if (otherheight > 0) + { + do + { + myst = 0; + for (a = 0; a < 4; a++) + myst += data_lsb_get (ptr + (a * (myWidth * 2)), 2); + + myEDI = 0; + myst = myst * 0.25; + if (myHeight < (otherheight - 4)) + { + if (myst < buffer2[myESI]) + { + buffer2[myESI] = myst; + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + if (buffer2[myESI] < buffer2[a]) + myESI = a; + } + } + + /*a820 */ + if (myst >= buffer1[myEDI]) + { + buffer1[myEDI] = myst; + if (lf130 > 0) + { + for (a = 0; a < lf130; a++) + if (buffer1[myEDI] >= buffer1[a]) + myEDI = a; + } + } + sumatorio += myst; + } + else + { + /*a853 */ + if (myHeight == (otherheight - 4)) + { + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + if (buffer2[myESI] >= buffer2[a]) + myESI = a; + } + + if (lf130 > 0) + { + for (a = 0; a < lf130; a++) + if (buffer1[myEDI] < buffer1[a]) + myEDI = a; + } + } + + /*a895 */ + if (myst >= buffer2[myESI]) + { + /*a89c */ + sumatorio -= buffer2[myESI]; + sumatorio += myst; + buffer2[myESI] = myst; + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + if (buffer2[myESI] >= buffer2[a]) + myESI = a; + } + } + else + { + if (myst < buffer1[myEDI]) + { + sumatorio -= buffer1[myEDI]; + sumatorio += myst; + buffer1[myEDI] = myst; + + if (lf130 > 0) + { + for (a = 0; a < lf130; a++) + if (buffer1[myEDI] < buffer1[a]) + myEDI = a; + } + } + } + } + + /*a901 */ + ptr += (myWidth * 2); + myHeight++; + } + while (myHeight < otherheight); + } + + /*a924 */ + scancfg.ser = 0; + scancfg.startpos = otherheight - 4; + + sumatorio = sumatorio / scancfg.startpos; + if (myCalib->shading_enabled != FALSE) + { + /*a94a */ + myCalib->white_shading[channel][lf13c] = + (unsigned short) sumatorio; + } + else + { + /*a967 */ + if ((scancfg.colormode != CM_GRAY) + && (scancfg.colormode != CM_LINEART)) + sumatorio /= lf1a4[channel]; + else + sumatorio /= lf1a4[scancfg.channel]; + + sumatorio = min (sumatorio * 0x4000, 65535); + + if (myRegs[0x1bf] != 0x18) + myCalib->black_shading[channel][lf13c] |= + (0x140 - + ((((myRegs[0x1bf] >> 3) & 3) * + 3) << 6)) & ((int) sumatorio); + else + myCalib->white_shading[channel][lf13c] = + (unsigned short) sumatorio; + } + + /*a9fd */ + position++; + } + while (position < myWidth); + } + } + else + { + /*a6d9 */ + position = 0; + sumatorio = 0; + if (myWidth > 0) + { + do + { + switch (scancfg.colormode) + { + case CM_GRAY: + case CM_LINEART: + channel = 0; + lf13c = position; + break; + default: /*CM_COLOR */ + if (scancfg.samplerate == PIXEL_RATE) + { + channel = position % bytes_per_pixel; + lf13c = position / bytes_per_pixel; + } + else + { + channel = position / lf168; + lf13c = position % lf168; + } + break; + } + + /*a743 */ + if (lf130 > 0) + bzero (buffer1, lf130 * sizeof (double)); + + /*a761 */ + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + buffer2[a] = (1 << scancfg.depth) - 1.0; + } + + /*a78f */ + myESI = 0; + myEDI = 0; + ptr = scanbuffer + position; + myHeight = 0; + + if (otherheight > 0) + { + do + { + myst = 0; + for (a = 0; a < 4; a++) + myst += *(ptr + (a * myWidth)); + + myEDI = 0; + myst *= 0.25; + if (myHeight < (otherheight - 4)) + { + if (myst < buffer2[myESI]) + { + buffer2[myESI] = myst; + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + if (buffer2[myESI] < buffer2[a]) + myESI = a; + } + } + /*a820 */ + if (myst >= buffer1[myEDI]) + { + buffer1[myEDI] = myst; + if (lf130 > 0) + { + for (a = 0; a < lf130; a++) + if (buffer1[myEDI] >= buffer1[a]) + myEDI = a; + } + } + sumatorio += myst; + } + else + { + /*a853 */ + if (myHeight == (otherheight - 4)) + { + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + if (buffer2[myESI] >= buffer2[a]) + myESI = a; + } + + if (lf130 > 0) + { + for (a = 0; a < lf130; a++) + if (buffer1[myEDI] < buffer1[a]) + myEDI = a; + } + } + + /*a895 */ + if (myst >= buffer2[myESI]) + { + /*a89c */ + sumatorio -= buffer2[myESI]; + sumatorio += myst; + buffer2[myESI] = myst; + if (lf12c > 0) + { + for (a = 0; a < lf12c; a++) + if (buffer2[myESI] >= buffer2[a]) + myESI = a; + } + } + else + { + if (myst < buffer1[myEDI]) + { + sumatorio -= buffer1[myEDI]; + sumatorio += myst; + buffer1[myEDI] = myst; + + if (lf130 > 0) + { + for (a = 0; a < lf130; a++) + if (buffer1[myEDI] < buffer1[a]) + myEDI = a; + } + } + } + } + /*a901 */ + ptr += myWidth; + myHeight++; + } + while (myHeight < otherheight); + } + /*a924 */ + scancfg.ser = 0; + scancfg.startpos = otherheight - 4; + + sumatorio /= scancfg.startpos; + if (myCalib->shading_enabled != FALSE) + { + /*a94a */ + myCalib->white_shading[channel][lf13c] = + (unsigned short) sumatorio; + } + else + { + /*a967 */ + if ((scancfg.colormode != CM_GRAY) + && (scancfg.colormode != CM_LINEART)) + sumatorio /= lf1a4[channel]; + else + sumatorio /= lf1a4[scancfg.channel]; + + sumatorio = min (sumatorio * 0x4000, 65535); + + if (myRegs[0x1bf] != 0x18) + myCalib->black_shading[channel][lf13c] |= + (0x140 - + ((((myRegs[0x1bf] >> 3) & 0x03) * + 3) << 6)) & ((int) sumatorio); + else + myCalib->white_shading[channel][lf13c] = + (unsigned short) sumatorio; + } + /*a9fd */ + position++; + } + while (position < myWidth); + } + } + + /*aa12 */ + if (RTS_Debug->SaveCalibFile != FALSE) + { + dbg_tiff_save ("whiteshading3.tiff", + scancfg.coord.width, + scancfg.coord.height, + scancfg.depth, + CM_COLOR, + scancfg.resolution_x, + scancfg.resolution_y, + scanbuffer, + (scancfg.coord.height + 16) * bytes_per_line); + } + + free (buffer1); + free (buffer2); + free (scanbuffer); + + return OK; +} + +static SANE_Int +Calib_BlackShading (struct st_device *dev, + struct st_calibration_config *calibcfg, + struct st_calibration *myCalib, SANE_Int gainmode) +{ + /* + gainmode f8ec + myCalib f8e8 + calibcfg f8e4 + */ + SANE_Byte *myRegs; /*f1bc */ + struct st_scanparams scancfg; /*f020 */ + long ltime; + double shadingprediff[6]; /*f08c f094 f09c f0a4 f0ac f0b4 */ + double mylong; /*f018 */ + double maxvalue; /*eff8 */ + double sumatorio = 0.0; + double myst; + SANE_Int rst; + SANE_Int a; + SANE_Int mheight; /*efe0 */ + SANE_Int current_line; /*efe4 */ + SANE_Int bytes_per_line; /*efd8 */ + SANE_Int position; /*lefcc */ + SANE_Int leff0, lf010, lefd0; + SANE_Byte *buffer; /*efd4 */ + SANE_Byte buff2[256]; /*F0BC */ + SANE_Int buff3[0x8000]; + SANE_Byte *ptr; /*f008 */ + SANE_Int my14b4; /*f008 pisa ptr */ + SANE_Int biggest; /*bx */ + SANE_Int lowest; /*dx */ + SANE_Int lefdc; + SANE_Int channel; + SANE_Int smvalues[3]; /*f04c f04e f050 */ + double dbvalue[6]; /*lf05c lf060, lf064 lf068, lf06c lf070, + lf074 lf078, lf07c lf080, lf084 lf088 */ + + DBG (DBG_FNC, "> Calib_BlackShading(*calibcfg, *myCalib, gainmode=%i)\n", + gainmode); + + rst = OK; + ltime = GetTickCount (); + myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); + + Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode); + + for (a = CL_RED; a <= CL_BLUE; a++) + shadingprediff[a + 3] = calibcfg->BShadingPreDiff[a]; + + if ((scan.scantype >= ST_NORMAL) && (scan.scantype <= ST_NEG)) + scancfg.coord.left += scan.ser; + + if ((dpi100Lumping == 0) + && (scancfg.resolution_x == + Scanmode_minres (dev, scancfg.scantype, scancfg.colormode))) + { + scancfg.resolution_x = 200; + scancfg.resolution_y = 200; + scancfg.coord.width = + min (scancfg.coord.width * 2, scancfg.shadinglength); + } + + if ((scancfg.coord.width & 1) != 0) + scancfg.coord.width++; + + scancfg.coord.top = 1; + scancfg.depth = 8; + scancfg.coord.height = calibcfg->BShadingHeight; + + if (scancfg.colormode != CM_COLOR) + { + bytes_per_line = scancfg.coord.width; + leff0 = 0; + lf010 = 1; + } + else + { + /*876c */ + bytes_per_line = scancfg.coord.width * 3; + if (scancfg.samplerate == LINE_RATE) + { + leff0 = scancfg.coord.width; + lf010 = 1; + } + else + { + leff0 = 1; + lf010 = 3; + } + } + + scancfg.v157c = bytes_per_line; + scancfg.bytesperline = bytes_per_line; + + mylong = 1 << (16 - scancfg.depth); + if ((myRegs[0x1bf] & 0x18) != 0) + mylong /= 1 << (((myRegs[0x1bf] >> 5) & 3) + 4); + + lefd0 = + ((((myRegs[0x1bf] >> 3) & 2) << 8) - + ((((myRegs[0x1bf] >> 3) & 1) * 3) << 6)) - 1; + + if (scancfg.depth >= 8) + maxvalue = ((1 << (scancfg.depth - 8)) << 8) - 1; + else + maxvalue = (256 / (1 << (8 - scancfg.depth))) - 1; + + Calib_LoadCut (dev, &scancfg, scan.scantype, calibcfg); + for (a = CL_RED; a <= CL_BLUE; a++) + shadingprediff[a] = calibcfg->ShadingCut[a]; + + if (calibcfg->BShadingOn == -1) + { + SANE_Int b, d; + double e; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + myst = max (shadingprediff[a], 0); + myst = (maxvalue >= myst) ? shadingprediff[a] : maxvalue; + shadingprediff[a] = max (myst, 0); + } + + b = 0; + + while (b < bytes_per_line) + { + if (scancfg.colormode != CM_COLOR) + { + channel = 0; + d = b; + } + else + { + if (scancfg.samplerate == PIXEL_RATE) + { + channel = (b % lf010) & 0xffff; + d = (b / lf010) & 0xffff; + } + else + { + channel = (b / leff0) & 0xffff; + d = (b % leff0) & 0xffff; + } + } + /*89d0 */ + e = min (lefd0, mylong * shadingprediff[channel]); + myCalib->black_shading[channel][d] |= (unsigned short) e & 0xffff; + b++; + } + + return OK; + } + + /* Allocate buffer to read image */ + mheight = scancfg.coord.height; + buffer = + (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) * + sizeof (SANE_Byte)); + if (buffer == NULL) + return ERROR; + + /* Turn off lamp */ + Lamp_SetStatus2 (dev, FALSE, FLB_LAMP); + usleep (200 * 1000); + + /* Scan image */ + myCalib->shading_enabled = FALSE; + rst = + RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, buffer, + myCalib, 0x101, gainmode); + if (rst == ERROR) + { + /*8ac2 */ + free (buffer); + memcpy (&calibdata->Regs, myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + free (myRegs); + return ERROR; + } + + /* myRegs isn't going to be used anymore */ + free (myRegs); + myRegs = NULL; + + /* Turn on lamp again */ + if (scan.scantype != ST_NORMAL) + { + Lamp_SetStatus2 (dev, FALSE, TMA_LAMP); + usleep (1000 * 1000); + } + else + Lamp_SetStatus2 (dev, TRUE, FLB_LAMP); + + /* Save buffer */ + if (RTS_Debug->SaveCalibFile != FALSE) + { + dbg_tiff_save ("blackshading.tiff", + scancfg.coord.width, + scancfg.coord.height, + scancfg.depth, + CM_COLOR, + scancfg.resolution_x, + scancfg.resolution_y, + buffer, (scancfg.coord.height + 16) * bytes_per_line); + } + + if (scancfg.depth > 8) + { + /*8bb2 */ + bzero (&dbvalue, 6 * sizeof (double)); + position = 0; + + if (bytes_per_line > 0) + { + do + { + bzero (&buff3, 0x8000 * sizeof (SANE_Int)); + sumatorio = 0; + ptr = buffer + position; + current_line = 0; + biggest = 0; + lowest = (int) maxvalue; + /* Toma los valores de una columna */ + if (mheight > 0) + { + SANE_Int value; + do + { + value = data_lsb_get (ptr, 2); + biggest = max (biggest, value); + if (current_line < mheight) + { + sumatorio += value; + lowest = min (lowest, value); + biggest = max (biggest, value); + + buff3[value]++; + } + else + { + /*8cab */ + if (value > lowest) + { + buff3[lowest]--; + buff3[value]++; + sumatorio += value; + sumatorio -= lowest; + + if (buff3[lowest] != 0) + { + do + { + lowest++; + } + while (buff3[lowest] == 0); + } + } + } + /*8d0b */ + ptr += (bytes_per_line * 2); + current_line++; + } + while (current_line < mheight); + } + /*8d27 */ + sumatorio /= mheight; + + if (scancfg.colormode != CM_COLOR) + { + channel = 0; + lefdc = position; + } + else + { + /*8d5f */ + if (scancfg.samplerate == PIXEL_RATE) + { + channel = position % lf010; + lefdc = (position / lf010) & 0xffff; + } + else + { + channel = position / leff0; + lefdc = position % leff0; + } + } + + dbvalue[channel] += sumatorio; + if ((scancfg.colormode == CM_GRAY) + || (scancfg.colormode == CM_LINEART)) + sumatorio += shadingprediff[scancfg.channel]; + else + sumatorio += shadingprediff[channel]; + + myst = min (max (0, sumatorio), maxvalue); + + dbvalue[channel + 3] = myst; + + if ((calibcfg->BShadingOn == 1) || (calibcfg->BShadingOn == 2)) + { + if (calibcfg->BShadingOn == 2) + { + myst -= + calibcfg->BRef[channel] * (1 << (scancfg.depth - 8)); + myst = max (myst, 0); + } + /*8e6d */ + myst *= mylong; + myCalib->black_shading[channel][lefdc] = min (myst, lefd0); + } + + position++; + } + while (position < bytes_per_line); + } + } + else + { + /*8eb6 */ + bzero (&dbvalue, 6 * sizeof (double)); + position = 0; + + if (bytes_per_line > 0) + { + do + { + bzero (&buff2, 256 * sizeof (SANE_Byte)); + sumatorio = 0; + /* ptr points to the next position of the first line */ + ptr = buffer + position; + biggest = 0; + lowest = (int) maxvalue; + current_line = 0; + /* Toma los valores de una columna */ + if (mheight > 0) + { + my14b4 = v14b4; + do + { + biggest = max (biggest, *ptr); + + if (my14b4 == 0) + { + /*8fd7 */ + if (current_line < mheight) + { + sumatorio += *ptr; + + lowest = min (lowest, *ptr); + biggest = max (biggest, *ptr); + + buff2[*ptr]++; + } + else + { + /*9011 */ + if (*ptr > lowest) + { + buff2[lowest]--; + buff2[*ptr]++; + sumatorio += *ptr; + sumatorio -= lowest; + + if (buff2[lowest] != 0) + { + do + { + lowest++; + } + while (buff2[lowest] == 0); + } + } + } + } + else + sumatorio += *ptr; + /*9067 */ + /* Point to the next pixel under current line */ + ptr += bytes_per_line; + current_line++; + } + while (current_line < mheight); + } + + /*908a */ + /* Calculates average of each column */ + sumatorio = sumatorio / mheight; + + if (scancfg.colormode != CM_COLOR) + { + channel = 0; + lefdc = position; + } + else + { + /*90c5 */ + if (scancfg.samplerate == PIXEL_RATE) + { + channel = position % lf010; + lefdc = (position / lf010) & 0xffff; + } + else + { + /*90fb */ + channel = position / leff0; + lefdc = position % leff0; + } + } + + /*911f */ + dbvalue[channel] += sumatorio; + if ((scancfg.colormode == CM_GRAY) + || (scancfg.colormode == CM_LINEART)) + sumatorio += shadingprediff[scancfg.channel]; + else + sumatorio += shadingprediff[channel]; + + /*9151 */ + myst = min (max (0, sumatorio), maxvalue); + + /*9198 */ + if (position >= 3) + { + double myst2; + + myst -= dbvalue[channel + 3]; + myst2 = myst; + myst = min (myst, shadingprediff[channel + 3]); + + my14b4 = -shadingprediff[channel + 3]; + if (myst >= my14b4) + myst = min (myst2, shadingprediff[channel + 3]); + else + myst = my14b4; + + myst += dbvalue[channel + 3]; + } + + /*9203 */ + dbvalue[channel + 3] = myst; + + switch (calibcfg->BShadingOn) + { + case 1: + myCalib->black_shading[channel][lefdc] |= + (unsigned short) (((int) myst & 0xff) << 8) & 0xffff; + break; + case 2: + /*9268 */ + my14b4 = + calibcfg->BRef[channel] / (1 << (8 - scancfg.depth)); + myst -= my14b4; + myst = max (myst, 0); + myst *= mylong; + myCalib->black_shading[channel][lefdc] = min (myst, lefd0); + break; + } + + /*92d8 */ + position++; + } + while (position < bytes_per_line); + } + } + + /*9306 */ + if (calibcfg->BShadingOn == -2) + { + for (a = 0; a < 3; a++) + { + dbvalue[a] = + (dbvalue[a] / scancfg.coord.width) + calibcfg->ShadingCut[a]; + if (dbvalue[a] < 0) + dbvalue[a] = 0; + smvalues[a] = min ((int) (dbvalue[a] + 0.5) & 0xffff, maxvalue); + } + + if (scancfg.coord.width > 0) + { + SANE_Int b, c; + + for (c = 0; c < scancfg.coord.width; c++) + for (b = 0; b < 3; b++) + myCalib->black_shading[b][c] |= + (unsigned short) min (smvalues[b] * mylong, lefd0); + } + } + /*9425 */ + free (buffer); + + return OK; +} + +static SANE_Int +Calibration (struct st_device *dev, SANE_Byte * Regs, + struct st_scanparams *scancfg, struct st_calibration *myCalib, + SANE_Int value) +{ + /*//SANE_Int Calibration([fa20]char *Regs, [fa24]struct st_scanparams *scancfg, [fa28]struct st_calibration myCalib, [fa2c]SANE_Int value) + */ + + struct st_calibration_config calibcfg; /* f90c */ + SANE_Int a; + SANE_Byte gainmode; + SANE_Int lf900; + SANE_Int myleftleading; /* [3ec0] */ + SANE_Int myler; /* [3ec4] */ + + DBG (DBG_FNC, "> Calibration\n"); + dbg_ScanParams (scancfg); + + value = value; /*silence gcc */ + + memcpy (&calibdata->Regs, Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); + + /*4213be8 */ + memset (&calibcfg, 0x30, sizeof (struct st_calibration_config)); + Calib_LoadConfig (dev, &calibcfg, scan.scantype, scancfg->resolution_x, + scancfg->depth); + + bzero (&calibdata->gain_offset, sizeof (struct st_gain_offset)); /*[42b3654] */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + myCalib->WRef[a] = calibcfg.WRef[a]; + + calibdata->gain_offset.edcg1[a] = 256; + calibdata->gain_offset.odcg1[a] = 256; + calibdata->gain_offset.vgag1[a] = 4; + calibdata->gain_offset.vgag2[a] = 4; + + /*3654|3656|3658 + 365a|365c|365e + 3660|3662|3664 + 3666|3668|366a + 366c|366d|366e + 366f|3670|3671 + 3672|3673|3674 */ + } + + memcpy (&calibdata->scancfg, scancfg, sizeof (struct st_scanparams)); + gainmode = Lamp_GetGainMode (dev, scancfg->resolution_x, scan.scantype); /* [lf904] = 1 */ + + if ((dpi100Lumping == 0) + && (scancfg->resolution_x == + Scanmode_minres (dev, scancfg->scantype, scancfg->colormode))) + { + /* duplicate resolution, so duplicate coords */ + calibdata->scancfg.resolution_x = 200; + calibdata->scancfg.resolution_y = 200; + calibdata->scancfg.coord.width *= 2; + calibdata->scancfg.coord.height *= 2; + calibdata->scancfg.coord.top *= 2; + calibdata->scancfg.coord.left *= 2; + calibdata->scancfg.v157c *= 2; + calibdata->scancfg.bytesperline *= 2; + } + + /* 3cf3 */ + myCalib->first_position = 1; + myCalib->shading_type = 0; + if (calibdata->scancfg.colormode == CM_LINEART) + { + calibdata->scancfg.colormode = CM_GRAY; + calibcfg.GainTargetFactor = 1.3; + } + + lf900 = OK; + /*OK*/ myleftleading = scan.leftleading; + myler = scan.ler; + + if (calibcfg.CalibPAGOn != 0) + { + if (Calib_PAGain (dev, &calibcfg, gainmode) != 0) + lf900 = ERROR; + /*ERROR*/} + else + { + /*3da7 */ + if ((calibdata->scancfg.colormode != CM_GRAY) + && (calibdata->scancfg.colormode != CM_LINEART)) + { + for (a = CL_RED; a <= CL_BLUE; a++) + calibdata->gain_offset.pag[a] = calibcfg.PAG[a]; + } + else + { + /* 3dd3 */ + /* Default PAGain */ + if (calibdata->scancfg.channel > 2) + calibdata->scancfg.channel = 0; + + for (a = CL_RED; a <= CL_BLUE; a++) + calibdata->gain_offset.pag[a] = + calibcfg.PAG[calibdata->scancfg.channel]; + } + } + + /* 3e01 */ + if (calibcfg.CalibOffset10n != 0) /*==2*/ + { + /*v14b4=1 offset[CL_RED]=0x174 offset[CL_GREEN]=0x16d offset[CL_BLUE]=0x160 */ + if ((v14b4 != 0) && (offset[CL_RED] != 0) && (offset[CL_GREEN] != 0) + && (offset[CL_BLUE] != 0)) + { + for (a = CL_RED; a <= CL_BLUE; a++) + { + calibdata->gain_offset.edcg1[a] = offset[a]; + calibdata->gain_offset.odcg1[a] = offset[a]; + } + } + else + { + /* 3e84 */ + if ((calibcfg.CalibOffset10n > 0) && (calibcfg.CalibOffset10n < 4)) + { + /*if (calibcfg.CalibOffset10n != 0) */ + if (calibcfg.CalibOffset10n == 3) + { + lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 1); + } + else + { + /* 3eb2 */ + /*falta codigo */ + } + } + } + } + else + { + /* 3faf */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + calibdata->gain_offset.edcg1[a] = + abs (calibcfg.OffsetEven1[a] - 0x100); + calibdata->gain_offset.odcg1[a] = + abs (calibcfg.OffsetOdd1[a] - 0x100); + } + } + + /* 3f13 3f0b */ + if ((gainmode != 0) && (calibcfg.CalibGain10n != 0)) + { + /*gain[CL_RED]=0x17 gain[CL_GREEN]=0x12 gain[CL_BLUE]=0x17 */ + if ((v14b4 != 0) && (gain[CL_RED] != 0) && (gain[CL_GREEN] != 0) + && (gain[CL_BLUE] != 0)) + { + for (a = CL_RED; a <= CL_BLUE; a++) + calibdata->gain_offset.vgag1[a] = gain[a]; + } + else + { + /*4025 */ + lf900 = Calib_AdcGain (dev, &calibcfg, 1, gainmode); + + if ((v14b4 != 0) && (lf900 == OK)) + GainOffset_Save (dev, &calibdata->gain_offset.edcg1[0], + &calibdata->gain_offset.vgag1[0]); + } + } + else + { + /*4089 */ + for (a = CL_RED; a <= CL_BLUE; a++) + calibdata->gain_offset.vgag1[a] = calibcfg.Gain1[a]; + } + + /*40a5 */ + if ((gainmode != 0) && (calibcfg.CalibOffset20n != 0)) + { + switch (calibcfg.CalibOffset20n) + { + case 3: + lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 2); + break; + } + /*4140 */ + /*falta codigo */ + } + else + { + /*4162 */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + calibdata->gain_offset.edcg2[a] = + abs (calibcfg.OffsetEven2[a] - 0x40); + calibdata->gain_offset.odcg2[a] = + abs (calibcfg.OffsetOdd2[a] - 0x40); + } + } + + /*41d6 */ + if ((gainmode != 0) && (calibcfg.CalibGain20n != 0)) + { + lf900 = Calib_AdcGain (dev, &calibcfg, 0, gainmode); + } + else + { + /*423c */ + for (a = CL_RED; a <= CL_BLUE; a++) + calibdata->gain_offset.vgag2[a] = calibcfg.Gain2[a]; + } + + /*4258 */ + if (calibcfg.TotShading != 0) + { + lf900 = Calib_BWShading (&calibcfg, myCalib, gainmode); + /*falta codigo */ + } + else + { + /*428f */ + if (gainmode != 0) + { + if (calibcfg.BShadingOn != 0) + lf900 = Calib_BlackShading (dev, &calibcfg, myCalib, gainmode); + + /*42fd */ + if ((lf900 != ERROR) && (calibcfg.WShadingOn != 0)) + { + switch (calibcfg.WShadingOn) + { + default: + break; + case 3: + lf900 = + Calib_WhiteShading_3 (dev, &calibcfg, myCalib, gainmode); + break; + case 2: + break; + } + } + else + myCalib->shading_enabled = FALSE; + } + else + myCalib->shading_enabled = FALSE; + } + + /*43ca */ + memcpy (&myCalib->gain_offset, &calibdata->gain_offset, + sizeof (struct st_gain_offset)); + memcpy (&mitabla2, &calibdata->gain_offset, sizeof (struct st_gain_offset)); + + /*4424 */ + /* Park home after calibration */ + if (get_value (SCANINFO, PARKHOMEAFTERCALIB, TRUE, FITCALIBRATE) == FALSE) + scan.ler -= + calibcfg.WShadingHeight * + (((dpi100Lumping == 0) + && (scancfg->resolution_x == + Scanmode_minres (dev, scancfg->scantype, + scancfg->colormode))) ? 2 : 1); + else + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + + return OK; +} + +/*static void show_diff(struct st_device *dev, SANE_Byte *original) +{ + SANE_Byte *buffer = (SANE_Byte *)malloc(RT_BUFFER_LEN * sizeof(SANE_Byte)); + SANE_Int a; + + if ((buffer == NULL)||(original == NULL)) + return; + + if (RTS_ReadRegs(dev->usb_handle, buffer) != OK) + { + free(buffer); + return; + } + + for (a = 0; a < RT_BUFFER_LEN; a++) + { + if ((original[a] & 0xff) != (buffer[a] & 0xff)) + { + printf("%5i: %i -> %i\n", a, original[a] & 0xff, buffer[a] & 0xff); + original[a] = buffer[a] & 0xff; + } + } + + free(buffer); +} */ + +static SANE_Int +Load_Constrains (struct st_device *dev) +{ + SANE_Int rst = ERROR; + + if (dev->constrains != NULL) + Free_Constrains (dev); + + DBG (DBG_FNC, "> Load_Constrains\n"); + + dev->constrains = + (struct st_constrains *) malloc (sizeof (struct st_constrains)); + if (dev->constrains != NULL) + { + cfg_constrains_get (dev->constrains); + rst = OK; + } + + return rst; +} + +static SANE_Int +Constrains_Check (struct st_device *dev, SANE_Int Resolution, + SANE_Int scantype, struct st_coords *mycoords) +{ + /* + Constrains: + 100 dpi 850 x 1170 | 164 x 327 + 300 dpi 2550 x 3510 + 600 dpi 5100 x 7020 + 1200 dpi 10200 x 14040 + */ + + SANE_Int rst = ERROR; + char sdebug[20]; + + if (dev->constrains != NULL) + { + struct st_coords coords; + struct st_coords *mc; + + if ((scantype < ST_NORMAL) || (scantype > ST_NEG)) + scantype = ST_NORMAL; + + switch (scantype) + { + case ST_TA: + mc = &dev->constrains->slide; + break; + case ST_NEG: + mc = &dev->constrains->negative; + break; + default: + mc = &dev->constrains->reflective; + break; + } + + coords.left = MM_TO_PIXEL (mc->left, Resolution); + coords.width = MM_TO_PIXEL (mc->width, Resolution); + coords.top = MM_TO_PIXEL (mc->top, Resolution); + coords.height = MM_TO_PIXEL (mc->height, Resolution); + + /* Check left and top */ + if (mycoords->left < 0) + mycoords->left = 0; + + mycoords->left += coords.left; + + if (mycoords->top < 0) + mycoords->top = 0; + + mycoords->top += coords.top; + + /* Check width and height */ + if ((mycoords->width < 0) || (mycoords->width > coords.width)) + mycoords->width = coords.width; + + if ((mycoords->height < 0) || (mycoords->height > coords.height)) + mycoords->height = coords.height; + + rst = OK; + } + + DBG (DBG_FNC, + "> Constrains_Check: Source=%s, Res=%i, LW=(%i,%i), TH=(%i,%i): %i\n", + dbg_scantype (sdebug, scantype), Resolution, mycoords->left, + mycoords->width, mycoords->top, mycoords->height, rst); + + return rst; +} + +static struct st_coords * +Constrains_Get (struct st_device *dev, SANE_Byte scantype) +{ + static struct st_coords *rst = NULL; + + if (dev->constrains != NULL) + { + switch (scantype) + { + case ST_TA: + rst = &dev->constrains->slide; + break; + case ST_NEG: + rst = &dev->constrains->negative; + break; + default: + rst = &dev->constrains->reflective; + break; + } + } + + return rst; +} + +static void +Free_Constrains (struct st_device *dev) +{ + DBG (DBG_FNC, "> Free_Constrains\n"); + + if (dev->constrains != NULL) + { + free (dev->constrains); + dev->constrains = NULL; + } +} + +static void +RTS_DebugInit () +{ + /* Default vaules */ + RTS_Debug->dev_model = HP3970; + + RTS_Debug->DumpShadingData = FALSE; + RTS_Debug->SaveCalibFile = FALSE; + RTS_Debug->ScanWhiteBoard = FALSE; + RTS_Debug->EnableGamma = TRUE; + RTS_Debug->use_fixed_pwm = TRUE; + RTS_Debug->dmatransfersize = 0x80000; + RTS_Debug->dmasetlength = 0x7c0000; + RTS_Debug->dmabuffersize = 0x400000; + RTS_Debug->usbtype = -1; + + /* Lamp settings */ + RTS_Debug->overdrive_flb = 10000; /* msecs */ + RTS_Debug->overdrive_ta = 10000; /* msecs */ + + RTS_Debug->warmup = TRUE; + + /* Calibration settings */ + RTS_Debug->calibrate = FALSE; + RTS_Debug->wshading = TRUE; +} + +static void +RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *hwdcfg) +{ + DBG (DBG_FNC, "> RTS_Setup_Gamma(*Regs, *hwdcfg)\n"); + + if ((hwdcfg != NULL) && (Regs != NULL)) + { + if (hwdcfg->use_gamma_tables != FALSE) + { + SANE_Int table_size; + + /* set set table size */ + data_bitset (&Regs[0x1d0], 0x0f, hwdcfg->gamma_tablesize); + + /* enable gamma correction */ + data_bitset (&Regs[0x1d0], 0x40, 1); + + + switch (Regs[0x1d0] & 0x0c) + { + case 0: + table_size = (Regs[0x1d0] & 1) | 0x0100; + break; + case 4: + table_size = (Regs[0x1d0] & 1) | 0x0400; + break; + case 8: + table_size = (Regs[0x1d0] & 1) | 0x1000; + break; + default: + table_size = hwdcfg->startpos & 0xffff; + break; + } + + /* 5073 */ + /* points to red gamma table */ + data_wide_bitset (&Regs[0x1b4], 0x3fff, 0); + + /* points to green gamma table */ + data_wide_bitset (&Regs[0x1b6], 0x3fff, table_size); + + /* points to blue gamma table */ + data_wide_bitset (&Regs[0x1b8], 0x3fff, table_size * 2); + + v15f8 = (((table_size * 3) + 15) / 16) & 0xffff; + } + else + { + /* disable gamma correction */ + data_bitset (&Regs[0x1d0], 0x40, 0); + v15f8 = 0; + } + } +} + +static SANE_Int +RTS_USBType (struct st_device *dev) +{ + /* Gets USB type of this scanner */ + + SANE_Int rst = ERROR; + SANE_Byte data; + char sUSB[7]; + + DBG (DBG_FNC, "+ RTS_USBType\n"); + + if (Read_Byte (dev->usb_handle, 0xfe11, &data) == OK) + rst = (data & 1); + + if (rst == USB11) + strcpy (sUSB, "USB1.1"); + else + strcpy (sUSB, "USB2.0"); + + DBG (DBG_FNC, "- RTS_USBType(void): %s\n", sUSB); + + return rst; +} + +static void +RTS_Free (struct st_device *dev) +{ + /* this function frees space of devices's variable */ + + if (dev != NULL) + { + /* next function shouldn't be necessary but I can NOT assure that other + programmers will call Free_Config before this function */ + Free_Config (dev); + + if (dev->init_regs != NULL) + free (dev->init_regs); + + if (dev->Resize != NULL) + free (dev->Resize); + + if (dev->Reading != NULL) + free (dev->Reading); + + if (dev->scanning != NULL) + free (dev->scanning); + + free (dev); + } +} + +static struct st_device * +RTS_Alloc () +{ + /* this function allocates space for device's variable */ + + struct st_device *dev = NULL; + + dev = malloc (sizeof (struct st_device)); + if (dev != NULL) + { + SANE_Int rst = OK; + + bzero (dev, sizeof (struct st_device)); + + /* initial registers */ + dev->init_regs = malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN); + if (dev->init_regs != NULL) + bzero (dev->init_regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); + else + rst = ERROR; + + if (rst == OK) + { + dev->scanning = malloc (sizeof (struct st_scanning)); + if (dev->scanning != NULL) + bzero (dev->scanning, sizeof (struct st_scanning)); + else + rst = ERROR; + } + + if (rst == OK) + { + dev->Reading = malloc (sizeof (struct st_readimage)); + if (dev->Reading != NULL) + bzero (dev->Reading, sizeof (struct st_readimage)); + else + rst = ERROR; + } + + if (rst == OK) + { + dev->Resize = malloc (sizeof (struct st_resize)); + if (dev->Resize != NULL) + bzero (dev->Resize, sizeof (struct st_resize)); + else + rst = ERROR; + } + + /* if something fails, free space */ + if (rst != OK) + { + RTS_Free (dev); + dev = NULL; + } + } + + return dev; +} + +static SANE_Int +Init_Vars (void) +{ + SANE_Int rst = OK; + + hp_gamma = malloc (sizeof (struct st_gammatables)); + if (hp_gamma != NULL) + bzero (hp_gamma, sizeof (struct st_gammatables)); + else + rst = ERROR; + + if (rst == OK) + { + RTS_Debug = malloc (sizeof (struct st_debug_opts)); + if (RTS_Debug != NULL) + bzero (RTS_Debug, sizeof (struct st_debug_opts)); + else + rst = ERROR; + } + + if (rst == OK) + { + default_gain_offset = malloc (sizeof (struct st_gain_offset)); + if (default_gain_offset != NULL) + bzero (default_gain_offset, sizeof (struct st_gain_offset)); + else + rst = ERROR; + } + + if (rst == OK) + { + calibdata = malloc (sizeof (struct st_calibration_data)); + if (calibdata != NULL) + bzero (calibdata, sizeof (struct st_calibration_data)); + else + rst = ERROR; + } + + if (rst == OK) + { + wshading = malloc (sizeof (struct st_shading)); + if (wshading != NULL) + bzero (wshading, sizeof (struct st_shading)); + else + rst = ERROR; + } + + waitforpwm = TRUE; + + use_gamma_tables = TRUE; + + if (rst == OK) + RTS_DebugInit (); + else + Free_Vars (); + + return rst; +} + +static void +Free_Vars (void) +{ + if (RTS_Debug != NULL) + { + free (RTS_Debug); + RTS_Debug = NULL; + } + + if (hp_gamma != NULL) + { + free (hp_gamma); + hp_gamma = NULL; + } + + if (calibdata != NULL) + { + free (calibdata); + calibdata = NULL; + } + + if (wshading != NULL) + { + if (wshading->rates != NULL) + free (wshading->rates); + + free (wshading); + wshading = NULL; + } + + if (default_gain_offset != NULL) + { + free (default_gain_offset); + default_gain_offset = NULL; + } + +} + +static SANE_Int +Chipset_Reset (struct st_device *dev) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ Chipset_Reset:\n"); + + /* I've found two ways to reset chipset. Next one will stay commented + rst = ERROR; + if (Read_Byte(dev->usb_handle, 0xe800, &data) == OK) + { + data |= 0x20; + if (Write_Byte(dev->usb_handle, 0xe800, data) == OK) + { + data &= 0xdf; + rst = Write_Byte(dev->usb_handle, 0xe800, data); + } + } + */ + + rst = IWrite_Buffer (dev->usb_handle, 0x0000, NULL, 0, 0x0801); + + DBG (DBG_FNC, "- Chipset_Reset: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int size, + SANE_Int options) +{ + SANE_Int rst = ERROR; + SANE_Byte buffer[6]; + + DBG (DBG_FNC, + "+ RTS_DMA_Enable_Read(dmacs=0x%04x, size=%i, options=0x%06x)\n", + dmacs, size, options); + + data_msb_set (&buffer[0], options, 3); + + /* buffer size divided by 2 (words count) */ + data_lsb_set (&buffer[3], size / 2, 3); + + rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0400); + + DBG (DBG_FNC, "- RTS_DMA_Enable_Read: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int size, + SANE_Int options) +{ + SANE_Int rst = ERROR; + SANE_Byte buffer[6]; + + DBG (DBG_FNC, + "+ RTS_DMA_Enable_Write(dmacs=0x%04x, size=%i, options=0x%06x)\n", + dmacs, size, options); + + data_msb_set (&buffer[0], options, 3); + + /* buffer size divided by 2 (words count) */ + data_lsb_set (&buffer[3], size / 2, 3); + + rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0401); + + DBG (DBG_FNC, "- RTS_DMA_Enable_Write: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_Cancel (struct st_device *dev) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_DMA_Cancel:\n"); + + rst = IWrite_Word (dev->usb_handle, 0x0000, 0, 0x0600); + + DBG (DBG_FNC, "- RTS_DMA_Cancel: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_DMA_Reset (struct st_device *dev) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_DMA_Reset:\n"); + + rst = IWrite_Word (dev->usb_handle, 0x0000, 0x0000, 0x0800); + + DBG (DBG_FNC, "- RTS_DMA_Reset: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_WriteByte(address=%04x, data=%i):\n", address, + data); + + rst = IWrite_Byte (usb_handle, address, data, 0x200, 0x200); + + DBG (DBG_FNC, "- RTS_EEPROM_WriteByte: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_ReadWord(address=%04x, data):\n", address); + + rst = IRead_Word (usb_handle, address, data, 0x200); + + DBG (DBG_FNC, "- RTS_EEPROM_ReadWord: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * data) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_ReadByte(address=%04x, data):\n", address); + + rst = IRead_Byte (usb_handle, address, data, 0x200); + + DBG (DBG_FNC, "- RTS_EEPROM_ReadByte: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, SANE_Int data) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_WriteWord(address=%04x, data=%i):\n", address, + data); + + rst = IWrite_Word (usb_handle, address, data, 0x0200); + + DBG (DBG_FNC, "- RTS_EEPROM_WriteWord: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_ReadInteger (USB_Handle usb_handle, SANE_Int address, + SANE_Int * data) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_ReadInteger(address=%04x, data):\n", address); + + rst = IRead_Integer (usb_handle, address, data, 0x200); + + DBG (DBG_FNC, "- RTS_EEPROM_ReadInteger: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_WriteInteger (USB_Handle usb_handle, SANE_Int address, + SANE_Int data) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_WriteInteger(address=%04x, data):\n", address); + + rst = IWrite_Integer (usb_handle, address, data, 0x200); + + DBG (DBG_FNC, "- RTS_EEPROM_WriteInteger: %i\n", rst); + + return rst; +} + +static SANE_Int +RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * data, SANE_Int size) +{ + SANE_Int rst; + + DBG (DBG_FNC, "+ RTS_EEPROM_WriteBuffer(address=%04x, data, size=%i):\n", + address, size); + + rst = IWrite_Buffer (usb_handle, address, data, size, 0x200); + + DBG (DBG_FNC, "- RTS_EEPROM_WriteBuffer: %i\n", rst); + + return rst; +} + +static void +WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, SANE_Int size, + SANE_Int depth) +{ + if ((wshading->rates != NULL) && (chnptr != NULL)) + { + if (*chnptr < wshading->count) + { + double maxvalue, chncolor; + SANE_Int chnsize; + SANE_Int pos; + SANE_Int icolor; + + maxvalue = (1 << depth) - 1; + chnsize = (depth > 8) ? 2 : 1; + + pos = 0; + while (pos < size) + { + /* get channel color */ + chncolor = data_lsb_get (buffer + pos, chnsize); + + /* apply shading coeficient */ + chncolor *= wshading->rates[*chnptr]; + + /* care about limits */ + chncolor = min (chncolor, maxvalue); + + /* save color */ + icolor = chncolor; + data_lsb_set (buffer + pos, icolor, chnsize); + + *chnptr = *chnptr + 1; + if (*chnptr >= wshading->count) + *chnptr = 0; + + pos += chnsize; + } + } + } +} + +static SANE_Int +WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib, + struct st_scanparams *scancfg) +{ + struct st_calibration_config *calibcfg; + struct st_gain_offset myCalibTable; + struct st_scanparams *myscancfg; + SANE_Byte *myRegs; /*f1bc */ + SANE_Int bytes_per_line; + /**/ SANE_Int x, y, a, C; + SANE_Byte *pattern; /*f164 */ + double sumatorio; + SANE_Int gainmode; + SANE_Int rst; + SANE_Byte *avg_colors; + + DBG (DBG_FNC, "> WShading_Calibrate(*myCalib)\n"); + + bzero (&myCalibTable, sizeof (struct st_gain_offset)); + for (C = CL_RED; C <= CL_BLUE; C++) + { + myCalibTable.pag[C] = 3; + myCalibTable.vgag1[C] = 4; + myCalibTable.vgag2[C] = 4; + } + + calibcfg = + (struct st_calibration_config *) + malloc (sizeof (struct st_calibration_config)); + memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); + + myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); + + myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, + myscancfg->depth); + gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); + + Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); + + rst = OK; + + switch (scan.scantype) + { + case ST_NORMAL: + /*a184 */ + myscancfg->coord.left += scan.ser; + myscancfg->coord.width &= 0xffff; + break; + case ST_TA: + case ST_NEG: + myscancfg->coord.left += scan.ser; + break; + } + + /*a11b */ + if ((myscancfg->coord.width & 1) != 0) + myscancfg->coord.width++; + + myscancfg->coord.top = 1; + myscancfg->coord.height = calibcfg->WShadingHeight; + + myscancfg->sensorresolution = 0; + + bytes_per_line = + myscancfg->coord.width * (((myscancfg->colormode == CM_COLOR) ? 3 : 1) * + ((myscancfg->depth > 8) ? 2 : 1)); + + /*a1e8 */ + myscancfg->v157c = bytes_per_line; + myscancfg->bytesperline = bytes_per_line; + + /* allocate space for pattern */ + pattern = + (SANE_Byte *) malloc (((myscancfg->coord.height) * bytes_per_line) * + sizeof (SANE_Byte)); + if (pattern == NULL) + return ERROR; + + /* Scan image */ + myCalib->shading_enabled = FALSE; + rst = + RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, pattern, myCalib, + 0x20000000, gainmode); + + if (rst != ERROR) + { + SANE_Int chn; + double colors[3] = { 0, 0, 0 }; + double prueba; + SANE_Int data; + SANE_Int bytes_per_channel; + + bytes_per_channel = (myscancfg->depth > 8) ? 2 : 1; + + avg_colors = (SANE_Byte *) malloc (sizeof (SANE_Byte) * bytes_per_line); + + if (avg_colors != NULL) + { + wshading->ptr = 0; + wshading->count = bytes_per_line / bytes_per_channel; + + if (wshading->rates != NULL) + { + free (wshading->rates); + wshading->rates = NULL; + } + wshading->rates = + (double *) malloc (sizeof (double) * wshading->count); + + chn = 0; + for (x = 0; x < wshading->count; x++) + { + sumatorio = 0; + + for (y = 0; y < myscancfg->coord.height; y++) + { + data = + data_lsb_get (pattern + + ((x * bytes_per_channel) + + (bytes_per_line * y)), bytes_per_channel); + sumatorio += data; + } + + sumatorio /= myscancfg->coord.height; + a = sumatorio; + colors[chn] = max (colors[chn], sumatorio); + chn++; + if (chn > 2) + chn = 0; + + data_lsb_set (avg_colors + (x * bytes_per_channel), a, + bytes_per_channel); + } + + DBG (DBG_FNC, " -> max colors RGB= %f %f %f\n", colors[0], + colors[1], colors[2]); + + chn = 0; + for (x = 0; x < wshading->count; x++) + { + data = + data_lsb_get (avg_colors + (x * bytes_per_channel), + bytes_per_channel); + prueba = data; + *(wshading->rates + x) = colors[chn] / prueba; + chn++; + if (chn > 2) + chn = 0; + } + } + + if (RTS_Debug->SaveCalibFile != FALSE) + { + dbg_tiff_save ("whiteshading_jkd.tiff", + myscancfg->coord.width, + myscancfg->coord.height, + myscancfg->depth, + CM_COLOR, + scancfg->resolution_x, + scancfg->resolution_y, + pattern, (myscancfg->coord.height) * bytes_per_line); + } + +#ifdef developing + { + FILE *archivo; + char texto[1024]; + + /* apply correction to the pattern to see the result */ + chn = 0; + for (x = 0; x < myscancfg->coord.height * wshading->count; x++) + { + data = + data_lsb_get (pattern + (x * bytes_per_channel), + bytes_per_channel); + sumatorio = data; + sumatorio *= wshading->rates[chn]; + if (sumatorio > ((1 << myscancfg->depth) - 1)) + sumatorio = (1 << myscancfg->depth) - 1; + + a = sumatorio; + data_lsb_set (pattern + (x * bytes_per_channel), a, + bytes_per_channel); + + chn++; + if (chn == wshading->count) + chn = 0; + } + + /* save corrected pattern */ + dbg_tiff_save ("onwhiteshading_jkd.tiff", + myscancfg->coord.width, + myscancfg->coord.height, + myscancfg->depth, + CM_COLOR, + scancfg->resolution_x, + scancfg->resolution_y, + pattern, (myscancfg->coord.height) * bytes_per_line); + + /* export coefficients */ + archivo = fopen ("wShading.txt", "w"); + for (x = 0; x < wshading->count; x++) + { + snprintf (texto, 1024, "%f", wshading->rates[x]); + fprintf (archivo, "%s\n", texto); + } + + fclose (archivo); + } +#endif + } + + free (pattern); + + return OK; +} + +#ifdef developing +static SANE_Int +motor_pos (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib, struct st_scanparams *scancfg) +{ + struct st_calibration_config *calibcfg; + struct st_gain_offset myCalibTable; + struct st_scanparams *myscancfg; + SANE_Byte *myRegs; /*f1bc */ + SANE_Int bytes_per_line; + /**/ SANE_Int a, C; + SANE_Byte *scanbuffer; /*f164 */ + SANE_Int gainmode; + SANE_Int rst; + + DBG (DBG_FNC, "> Calib_test(*myCalib)\n"); + + bzero (&myCalibTable, sizeof (struct st_gain_offset)); + + calibcfg = + (struct st_calibration_config *) + malloc (sizeof (struct st_calibration_config)); + memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); + + myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); + + myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, + myscancfg->depth); + gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); + + Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); + + rst = OK; + + switch (scan.scantype) + { + case ST_NORMAL: + /*a184 */ + myscancfg->coord.left += scan.ser; + myscancfg->coord.width &= 0xffff; + break; + case ST_TA: + case ST_NEG: + myscancfg->coord.left += scan.ser; + break; + } + + /*a11b */ + if ((myscancfg->coord.width & 1) != 0) + myscancfg->coord.width++; + + myscancfg->coord.top = 100; + myscancfg->coord.height = 30; + + bytes_per_line = myscancfg->coord.width * 3; + + /*a1e8 */ + myscancfg->v157c = bytes_per_line; + myscancfg->bytesperline = bytes_per_line; + + scanbuffer = + (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * + sizeof (SANE_Byte)); + if (scanbuffer == NULL) + return ERROR; + + /* Scan image */ + myCalib->shading_enabled = FALSE; + /*Motor_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */ + + for (a = 0; a < 10; a++) + { + for (C = CL_RED; C <= CL_BLUE; C++) + { + myCalibTable.pag[C] = 3; + myCalibTable.vgag1[C] = 4; + myCalibTable.vgag2[C] = 4; + myCalibTable.edcg1[C] = a * 20; + } + + dbg_ScanParams (myscancfg); + + Motor_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, + 5000); + rst = + RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, + myCalib, 0x20000000, gainmode); + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + + if (rst != ERROR) + { + char name[30]; + snprintf (name, 30, "calibtest-%i.tiff", a); + dbg_tiff_save (name, + myscancfg->coord.width, + myscancfg->coord.height, + myscancfg->depth, + CM_COLOR, + myscancfg->resolution_x, + myscancfg->resolution_y, + scanbuffer, + (myscancfg->coord.height + 16) * bytes_per_line); + } + } + + free (scanbuffer); + + exit (0); + return OK; +} + +static SANE_Int +hp4370_prueba (struct st_device *dev) +{ + SANE_Int rst; + SANE_Int data = 0x0530, a; + SANE_Int transferred; + SANE_Byte buffer[512]; + + for (a = 0; a < 256; a++) + data_lsb_set (buffer + (a * 2), 0x9d7, 2); + + rst = IWrite_Word (dev->usb_handle, 0x0000, data, 0x0800); + RTS_DMA_Enable_Write (dev, 0x4, 512, 0); + Bulk_Operation (dev, BLK_WRITE, 512, buffer, &transferred); + + return rst; +} + +static SANE_Int +Calib_BlackShading_jkd (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib, + struct st_scanparams *scancfg) +{ + struct st_calibration_config *calibcfg; + struct st_gain_offset myCalibTable; + struct st_scanparams *myscancfg; + SANE_Byte *myRegs; /*f1bc */ + SANE_Int bytes_per_line; + /**/ SANE_Int x, y, a, C; + SANE_Byte *scanbuffer; /*f164 */ + double sumatorio; + SANE_Int gainmode; + SANE_Int rst; + + DBG (DBG_FNC, "> Calib_BlackShading_jkd(*myCalib)\n"); + + bzero (&myCalibTable, sizeof (struct st_gain_offset)); + for (C = CL_RED; C <= CL_BLUE; C++) + { + myCalibTable.pag[C] = 3; + myCalibTable.vgag1[C] = 4; + myCalibTable.vgag2[C] = 4; + } + + calibcfg = + (struct st_calibration_config *) + malloc (sizeof (struct st_calibration_config)); + memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); + + myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); + + myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, + myscancfg->depth); + gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); + + Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); + + rst = OK; + + switch (scan.scantype) + { + case ST_NORMAL: + /*a184 */ + myscancfg->coord.left += scan.ser; + myscancfg->coord.width &= 0xffff; + break; + case ST_TA: + case ST_NEG: + myscancfg->coord.left += scan.ser; + break; + } + + /*a11b */ + if ((myscancfg->coord.width & 1) != 0) + myscancfg->coord.width++; + + myscancfg->coord.top = 1; + myscancfg->coord.height = calibcfg->BShadingHeight; + + bytes_per_line = myscancfg->coord.width * 3; + + /*a1e8 */ + myscancfg->v157c = bytes_per_line; + myscancfg->bytesperline = bytes_per_line; + + scanbuffer = + (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * + sizeof (SANE_Byte)); + if (scanbuffer == NULL) + return ERROR; + + /* Turn off lamp */ + Lamp_SetStatus2 (dev, FALSE, FLB_LAMP); + usleep (200 * 1000); + + /* Scan image */ + myCalib->shading_enabled = FALSE; + rst = + RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, + 0x101, gainmode); + + /* Turn on lamp again */ + if (scan.scantype != ST_NORMAL) + { + Lamp_SetStatus2 (dev, FALSE, TMA_LAMP); + usleep (1000 * 1000); + } + else + Lamp_SetStatus2 (dev, TRUE, FLB_LAMP); + + if (rst != ERROR) + { + jkd_black = (SANE_Byte *) malloc (bytes_per_line); + + if (jkd_black != NULL) + { + jkd_blackbpl = bytes_per_line; + + for (x = 0; x < bytes_per_line; x++) + { + sumatorio = 0; + + for (y = 0; y < myscancfg->coord.height + 16; y++) + sumatorio += scanbuffer[x + (bytes_per_line * y)]; + + sumatorio /= myscancfg->coord.height + 16; + a = sumatorio; + *(jkd_black + x) = _B0 (a); + } + } + + /*if (RTS_Debug->SaveCalibFile != FALSE) */ + { + dbg_tiff_save ("blackshading_jkd.tiff", + myscancfg->coord.width, + myscancfg->coord.height, + myscancfg->depth, + CM_COLOR, + myscancfg->resolution_x, + myscancfg->resolution_y, + scanbuffer, + (myscancfg->coord.height + 16) * bytes_per_line); + } + } + + free (scanbuffer); + + return OK; +} + +static SANE_Int +Calib_test (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib, struct st_scanparams *scancfg) +{ + struct st_calibration_config *calibcfg; + struct st_gain_offset myCalibTable; + struct st_scanparams *myscancfg; + SANE_Byte *myRegs; /*f1bc */ + SANE_Int bytes_per_line; + /**/ SANE_Int a, C; + SANE_Byte *scanbuffer; /*f164 */ + SANE_Int gainmode; + SANE_Int rst; + + DBG (DBG_FNC, "> Calib_test(*myCalib)\n"); + + bzero (&myCalibTable, sizeof (struct st_gain_offset)); + + calibcfg = + (struct st_calibration_config *) + malloc (sizeof (struct st_calibration_config)); + memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); + + myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); + memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); + + myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); + memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); + + Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, + myscancfg->depth); + gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); + + Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); + + rst = OK; + + switch (scan.scantype) + { + case ST_NORMAL: + /*a184 */ + myscancfg->coord.left += scan.ser; + myscancfg->coord.width &= 0xffff; + break; + case ST_TA: + case ST_NEG: + myscancfg->coord.left += scan.ser; + break; + } + + /*a11b */ + if ((myscancfg->coord.width & 1) != 0) + myscancfg->coord.width++; + + myscancfg->coord.top = 100; + myscancfg->coord.height = 30; + + bytes_per_line = myscancfg->coord.width * 3; + + /*a1e8 */ + myscancfg->v157c = bytes_per_line; + myscancfg->bytesperline = bytes_per_line; + + scanbuffer = + (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * + sizeof (SANE_Byte)); + if (scanbuffer == NULL) + return ERROR; + + /* Scan image */ + myCalib->shading_enabled = FALSE; + /*Motor_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */ + + for (a = 0; a < 10; a++) + { + for (C = CL_RED; C <= CL_BLUE; C++) + { + myCalibTable.pag[C] = 3; + myCalibTable.vgag1[C] = 4; + myCalibTable.vgag2[C] = 4; + myCalibTable.edcg1[C] = a * 20; + } + + Motor_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, + 5000); + rst = + RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, + myCalib, 0x20000000, gainmode); + Motor_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); + + if (rst != ERROR) + { + char name[30]; + snprintf (name, 30, "calibtest-%i.tiff", a); + dbg_tiff_save (name, + myscancfg->coord.width, + myscancfg->coord.height, + myscancfg->depth, + CM_COLOR, + myscancfg->resolution_x, + myscancfg->resolution_y, + scanbuffer, + (myscancfg->coord.height + 16) * bytes_per_line); + } + } + + free (scanbuffer); + + exit (0); + return OK; +} + +static void +prueba (SANE_Byte * a) +{ + /* SANE_Byte p[] = {}; */ + /*int z = 69; */ + + /*(a + 11) = 0x0; */ + /*a[1] = a[1] | 0x40; */ + + /*memcpy(a, &p, sizeof(p)); */ + + /*memcpy(a + 0x12, p, 10); */ + /*a[0x146] &= 0xdf; */ + +} + +void +shadingtest1 (struct st_device *dev, SANE_Byte * Regs, + struct st_calibration *myCalib) +{ + USHORT *buffer; + int a; + int bit[2]; + + DBG (DBG_FNC, "+ shadingtest1(*Regs, *myCalib):\n"); + + if ((Regs == NULL) || (myCalib == NULL)) + return; + + RTS_DMA_Reset (dev); + + bit[0] = (Regs[0x60b] >> 6) & 1; + bit[1] = (Regs[0x60b] >> 4) & 1; + Regs[0x060b] &= 0xaf; + + Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); + + Regs[0x1cf] = 0; /* reset config. By default black shading disabled and pixel-rate */ + /*Regs[0x1cf] |= 2; shadingbase 0x2000 */ + Regs[0x1cf] |= 4; /* White shading enabled */ + Regs[0x1cf] |= 0x20; /* 16 bits per channel */ + + Write_Byte (dev->usb_handle, 0xe9cf, Regs[0x01cf]); + + buffer = (USHORT *) malloc (sizeof (USHORT) * myCalib->shadinglength); + + DBG (DBG_FNC, " -> shading length = %i\n", myCalib->shadinglength); + + /* fill buffer */ + for (a = 0; a < myCalib->shadinglength; a++) + buffer[a] = RTS_Debug->shd + (a * 500); + + for (a = 0; a < 3; a++) + { + RTS_DMA_Write (dev, a | 0x14, 0, + sizeof (USHORT) * myCalib->shadinglength, + (SANE_Byte *) buffer); + } + + data_bitset (&Regs[0x60b], 0x40, bit[0]); /*-x------*/ + data_bitset (&Regs[0x60b], 0x10, bit[1]); /*---x----*/ + + Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); + + DBG (DBG_FNC, "- shadingtest1\n"); +} + +#endif + +#endif /* RTS8822_CORE */ diff --git a/backend/hp3900_sane.c b/backend/hp3900_sane.c new file mode 100644 index 000000000..b572e029e --- /dev/null +++ b/backend/hp3900_sane.c @@ -0,0 +1,2700 @@ +/* HP Scanjet 3900 series - SANE Backend controller + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +/* Backend Code for SANE*/ +#define HP3900_CONFIG_FILE "hp3900.conf" +#define GAMMA_DEFAULT 1.0 + +#include "../include/sane/config.h" +#include "../include/sane/sane.h" +#include "../include/sane/sanei.h" +#include "../include/sane/sanei_backend.h" +#include "../include/sane/sanei_config.h" +#include "../include/sane/saneopts.h" +#include "../include/sane/sanei_usb.h" +#include "../include/sane/sanei_debug.h" + +#include "hp3900_rts8822.c" + +struct st_convert +{ + SANE_Int colormode; + SANE_Int depth; + SANE_Int threshold; + SANE_Int negative; + SANE_Int real_depth; +}; + +/* options enumerator */ +typedef enum +{ + opt_begin = 0, + + grp_geometry, + opt_tlx, opt_tly, opt_brx, opt_bry, + opt_resolution, + + /* gamma tables */ + opt_gamma_red, + opt_gamma_green, + opt_gamma_blue, + + opt_scantype, + opt_colormode, + opt_depth, + opt_threshold, + + /* debugging options */ + grp_debug, + opt_model, + opt_negative, + opt_nogamma, + opt_nowshading, + opt_realdepth, + opt_emulategray, + opt_nowarmup, + opt_dbgimages, + opt_reset, + + /* device information */ + grp_info, + opt_chipname, + opt_chipid, + opt_scancount, + opt_infoupdate, + + /* supported buttons. RTS8822 supports up to 6 buttons */ + grp_buttons, + opt_button_0, + opt_button_1, + opt_button_2, + opt_button_3, + opt_button_4, + opt_button_5, + + opt_count +} EOptionIndex; + +/* linked list of SANE_Device structures */ +typedef struct TDevListEntry +{ + struct TDevListEntry *pNext; + SANE_Device dev; + char *devname; +} TDevListEntry; + +typedef struct +{ + char *pszVendor; + char *pszName; +} TScannerModel; + +typedef union +{ + SANE_Word w; + SANE_Word *wa; /* word array */ + SANE_String s; +} TOptionValue; + +typedef struct +{ + SANE_Int model; + SANE_Option_Descriptor aOptions[opt_count]; + TOptionValue aValues[opt_count]; + struct params ScanParams; + + /* lists */ + SANE_String_Const *list_colormodes; + SANE_Int *list_depths; + SANE_String_Const *list_models; + SANE_Int *list_resolutions; + SANE_String_Const *list_sources; + + SANE_Word *aGammaTable[3]; /* a 16-to-16 bit color lookup table */ + SANE_Range rng_gamma; + + /* reading image */ + SANE_Byte *image; + SANE_Byte *rest; + SANE_Int rest_amount; + SANE_Int mylin; + + /* convertion settings */ + struct st_convert cnv; + + /* ranges */ + SANE_Range rng_threshold; + SANE_Range rng_horizontal; + SANE_Range rng_vertical; + + SANE_Int scan_count; + SANE_Int fScanning; /* TRUE if actively scanning */ + SANE_Int fCanceled; +} TScanner; + +/* functions to manage backend's options */ +static void options_init (TScanner * scanner); +static void options_free (TScanner * scanner); + +/* devices listing */ +static SANE_Int _ReportDevice (TScannerModel * pModel, + const char *pszDeviceName); +static SANE_Status attach_one_device (SANE_String_Const devname); + +/* capabilities */ +static SANE_Status bknd_colormodes (TScanner * scanner, SANE_Int model); +static void bknd_constrains (TScanner * scanner, SANE_Int source, + SANE_Int type); +static SANE_Status bknd_depths (TScanner * scanner, SANE_Int model); +static SANE_Status bknd_info (TScanner * scanner); +static SANE_Status bknd_models (TScanner * scanner); +static SANE_Status bknd_resolutions (TScanner * scanner, SANE_Int model); +static SANE_Status bknd_sources (TScanner * scanner, SANE_Int model); + +/* convertions */ +static SANE_Int Color_Negative (SANE_Byte * buffer, SANE_Int size, + SANE_Int depth); +static SANE_Int Color_to_Gray (SANE_Byte * buffer, SANE_Int size, + SANE_Int depth); +static void Gray_to_Lineart (SANE_Byte * buffer, SANE_Int size, + SANE_Int threshold); +static SANE_Int Depth_16_to_8 (SANE_Byte * from_buffer, SANE_Int size, + SANE_Byte * to_buffer); + +static SANE_Int dot_size (SANE_Handle h, SANE_Int depth); + +/* gamma functions */ +static void gamma_apply (TScanner * s, SANE_Byte * buffer, SANE_Int size, + SANE_Int depth); +static SANE_Int gamma_create (TScanner * s, double gamma); +static void gamma_free (TScanner * s); + +static SANE_Int Get_Colormode (SANE_String colormode); +static SANE_Int Get_Model (SANE_String model); +static SANE_Int Get_Source (SANE_String source); +static SANE_Int GetUSB_device_model (SANE_String_Const name); +static size_t max_string_size (const SANE_String_Const strings[]); + +static SANE_Status get_button_status (TScanner * s); + +/* reading buffers */ +static SANE_Status img_buffers_alloc (TScanner * scanner, SANE_Int size); +static SANE_Status img_buffers_free (TScanner * scanner); + +static SANE_Status option_get (TScanner * scanner, SANE_Int optid, + void *result); +static SANE_Status option_set (TScanner * scanner, SANE_Int optid, + void *value, SANE_Int * pInfo); + +static void Set_Coordinates (SANE_Int scantype, SANE_Int resolution, + struct st_coords *coords); +static SANE_Int set_ScannerModel (SANE_Int proposed, SANE_Int product, + SANE_Int vendor); +static void Silent_Compile (void); +static SANE_Status Translate_coords (struct st_coords *coords); + +/* SANE functions */ +void sane_cancel (SANE_Handle h); +void sane_close (SANE_Handle h); +SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, + SANE_Action Action, void *pVal, + SANE_Int * pInfo); +void sane_exit (void); +SANE_Status sane_get_devices (const SANE_Device *** device_list, + SANE_Bool local_only); +const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h, + SANE_Int n); +SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p); +SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd); +SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); +SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h); +SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, + SANE_Int * len); +SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking); +SANE_Status sane_start (SANE_Handle h); + +/* variables */ +static struct st_device *device = NULL; +static TDevListEntry *_pFirstSaneDev = 0; +static SANE_Int iNumSaneDev = 0; +static const SANE_Device **_pSaneDevList = 0; + +/* Own functions */ + +static SANE_Status +bknd_resolutions (TScanner * scanner, SANE_Int model) +{ + SANE_Status rst = SANE_STATUS_INVAL; + + DBG (DBG_FNC, "> bknd_resolutions(*scanner, model=%i\n", model); + + if (scanner != NULL) + { + SANE_Int *res = NULL; + + switch (model) + { + case BQ5550: + case UA4900: + { + SANE_Int myres[] = { 8, 50, 75, 100, 150, 200, 300, 600, 1200 }; + + res = (SANE_Int *) malloc (sizeof (myres)); + if (res != NULL) + memcpy (res, &myres, sizeof (myres)); + } + break; + + case HP3800: + { + /* 1200 and 2400 dpi are disabled until problems are solved */ + SANE_Int myres[] = { 7, 50, 75, 100, 150, 200, 300, 600 }; + + res = (SANE_Int *) malloc (sizeof (myres)); + if (res != NULL) + memcpy (res, &myres, sizeof (myres)); + } + break; + + case HP4370: + case HPG3010: + { + SANE_Int myres[] = + { 10, 50, 75, 100, 150, 200, 300, 600, 1200, 2400, 4800 }; + + res = (SANE_Int *) malloc (sizeof (myres)); + if (res != NULL) + memcpy (res, &myres, sizeof (myres)); + } + break; + + default: /* HP3970 & HP4070 & UA4900 */ + { + SANE_Int myres[] = + { 9, 50, 75, 100, 150, 200, 300, 600, 1200, 2400 }; + + res = (SANE_Int *) malloc (sizeof (myres)); + if (res != NULL) + memcpy (res, &myres, sizeof (myres)); + } + break; + } + + if (res != NULL) + { + if (scanner->list_resolutions != NULL) + free (scanner->list_resolutions); + + scanner->list_resolutions = res; + rst = SANE_STATUS_GOOD; + } + } + + return rst; +} + +static SANE_Status +bknd_models (TScanner * scanner) +{ + SANE_Status rst = SANE_STATUS_INVAL; + + DBG (DBG_FNC, "> bknd_models:\n"); + + if (scanner != NULL) + { + SANE_String_Const *model = NULL; + + /* at this moment all devices use the same list */ + SANE_String_Const mymodel[] = + { "HP3800", "HP3970", "HP4070", "HP4370", "UA4900", "HPG3010", +"BQ5550", 0 }; + + /* allocate space to save list */ + model = (SANE_String_Const *) malloc (sizeof (mymodel)); + if (model != NULL) + memcpy (model, &mymodel, sizeof (mymodel)); + + if (model != NULL) + { + /* free previous list */ + if (scanner->list_models != NULL) + free (scanner->list_models); + + /* set new list */ + scanner->list_models = model; + rst = SANE_STATUS_GOOD; + } + } + + return rst; +} + +static SANE_Status +bknd_colormodes (TScanner * scanner, SANE_Int model) +{ + SANE_Status rst = SANE_STATUS_INVAL; + + DBG (DBG_FNC, "> bknd_colormodes(*scanner, model=%i)\n", model); + + if (scanner != NULL) + { + SANE_String_Const *colormode = NULL; + + /* at this moment all devices use the same list */ + SANE_String_Const mycolormode[] = + { SANE_I18N ("Color"), SANE_I18N ("Gray"), SANE_I18N ("Lineart"), 0 }; + + /* silence gcc */ + model = model; + + colormode = (SANE_String_Const *) malloc (sizeof (mycolormode)); + if (colormode != NULL) + memcpy (colormode, &mycolormode, sizeof (mycolormode)); + + if (colormode != NULL) + { + if (scanner->list_colormodes != NULL) + free (scanner->list_colormodes); + + scanner->list_colormodes = colormode; + rst = SANE_STATUS_GOOD; + } + } + + return rst; +} + +static SANE_Status +bknd_sources (TScanner * scanner, SANE_Int model) +{ + SANE_Status rst = SANE_STATUS_INVAL; + + DBG (DBG_FNC, "> bknd_sources(*scanner, model=%i\n", model); + + if (scanner != NULL) + { + SANE_String_Const *source = NULL; + + switch (model) + { + case UA4900: + { + SANE_String_Const mysource[] = { SANE_I18N ("Flatbed"), 0 }; + source = (SANE_String_Const *) malloc (sizeof (mysource)); + if (source != NULL) + memcpy (source, &mysource, sizeof (mysource)); + } + break; + default: /* hp3970, hp4070, hp4370 and others */ + { + SANE_String_Const mysource[] = + { SANE_I18N ("Flatbed"), SANE_I18N ("Slide"), +SANE_I18N ("Negative"), 0 }; + source = (SANE_String_Const *) malloc (sizeof (mysource)); + if (source != NULL) + memcpy (source, &mysource, sizeof (mysource)); + } + break; + } + + if (source != NULL) + { + if (scanner->list_sources != NULL) + free (scanner->list_sources); + + scanner->list_sources = source; + rst = SANE_STATUS_GOOD; + } + } + + return rst; +} + +static SANE_Status +bknd_depths (TScanner * scanner, SANE_Int model) +{ + SANE_Status rst = SANE_STATUS_INVAL; + + DBG (DBG_FNC, "> bknd_depths(*scanner, model=%i\n", model); + + if (scanner != NULL) + { + SANE_Int *depth = NULL; + + /* at this moment all devices use the same list */ + SANE_Int mydepth[] = { 2, 8, 16 }; /*{3, 8, 12, 16}; */ + + /* silence gcc */ + model = model; + + depth = (SANE_Int *) malloc (sizeof (mydepth)); + if (depth != NULL) + memcpy (depth, &mydepth, sizeof (mydepth)); + + if (depth != NULL) + { + if (scanner->list_depths != NULL) + free (scanner->list_depths); + + scanner->list_depths = depth; + rst = SANE_STATUS_GOOD; + } + } + + return rst; +} + +static SANE_Status +bknd_info (TScanner * scanner) +{ + SANE_Status rst = SANE_STATUS_INVAL; + + DBG (DBG_FNC, "> bknd_info(*scanner)"); + + if (scanner != NULL) + { + char data[256]; + + /* update chipset name */ + Chipset_Name (device, data, 255); + if (scanner->aValues[opt_chipname].s != NULL) + { + free (scanner->aValues[opt_chipname].s); + scanner->aValues[opt_chipname].s = NULL; + } + + scanner->aValues[opt_chipname].s = strdup (data); + scanner->aOptions[opt_chipname].size = strlen (data) + 1; + + /* update chipset id */ + scanner->aValues[opt_chipid].w = Chipset_ID (device); + + /* update scans counter */ + scanner->aValues[opt_scancount].w = RTS_ScanCounter_Get (device); + + rst = SANE_STATUS_GOOD; + } + + return rst; +} + +static SANE_Int +GetUSB_device_model (SANE_String_Const name) +{ + SANE_Int usbid, model; + + /* default model is unknown */ + model = -1; + + /* open usb device */ + if (sanei_usb_open (name, &usbid) == SANE_STATUS_GOOD) + { + SANE_Int vendor, product; + + if (sanei_usb_get_vendor_product (usbid, &vendor, &product) == + SANE_STATUS_GOOD) + model = Device_get (product, vendor); + + sanei_usb_close (usbid); + } + + return model; +} + +static void +Silent_Compile (void) +{ + /* + There are some functions in hp3900_rts8822.c that aren't used yet. + To avoid compilation warnings we will use them here + */ + + SANE_Byte a = 1; + + if (a == 0) + { + Buttons_Status (device); + Calib_WriteTable (device, NULL, 0, 0); + Gamma_GetTables (device, NULL); + } +} + +static void +bknd_constrains (TScanner * scanner, SANE_Int source, SANE_Int type) +{ + struct st_coords *coords = Constrains_Get (device, source); + + if ((coords != NULL) && (scanner != NULL)) + { + switch (type) + { + case 1: /* Y */ + scanner->rng_vertical.max = coords->height; + break; + default: /* X */ + scanner->rng_horizontal.max = coords->width; + break; + } + } +} + +static SANE_Status +img_buffers_free (TScanner * scanner) +{ + if (scanner != NULL) + { + if (scanner->image != NULL) + { + free (scanner->image); + scanner->image = NULL; + } + + if (scanner->rest != NULL) + { + free (scanner->rest); + scanner->rest = NULL; + } + + scanner->rest_amount = 0; + } + + return SANE_STATUS_GOOD; +} + +static SANE_Status +img_buffers_alloc (TScanner * scanner, SANE_Int size) +{ + SANE_Status rst; + + /* default result at this point */ + rst = SANE_STATUS_INVAL; + + if (scanner != NULL) + { + /* default result at this point */ + rst = SANE_STATUS_NO_MEM; + + /* free previous allocs */ + img_buffers_free (scanner); + + scanner->image = (SANE_Byte *) malloc (size * sizeof (SANE_Byte)); + if (scanner->image != NULL) + { + scanner->rest = (SANE_Byte *) malloc (size * sizeof (SANE_Byte)); + if (scanner->rest != NULL) + rst = SANE_STATUS_GOOD; /* ok !! */ + } + + if (rst != SANE_STATUS_GOOD) + img_buffers_free (scanner); + } + + return rst; +} + +static SANE_Int +set_ScannerModel (SANE_Int proposed, SANE_Int product, SANE_Int vendor) +{ + /* This function will set the device behaviour */ + + SANE_Int current = Device_get (product, vendor); + char *sdevname[8] = + { "Unknown", "HP3970", "HP4070", "HP4370", "UA4900", "HP3800", "HPG3010", +"BQ5550" }; + + DBG (DBG_FNC, + "> set_ScannerModel(proposed=%i, product=%04x, vendor=%04x)\n", + proposed, product, vendor); + + if (proposed < 0) + { + if ((current < 0) || (current >= DEVSCOUNT)) + { + DBG (DBG_VRB, " -> Unknown device. Defaulting to HP3970...\n"); + RTS_Debug->dev_model = HP3970; + } + else + { + RTS_Debug->dev_model = current; + DBG (DBG_VRB, " -> Device model is %s\n", sdevname[current + 1]); + } + } + else + { + if (proposed < DEVSCOUNT) + { + RTS_Debug->dev_model = proposed; + DBG (DBG_VRB, " -> Device %s , treating as %s ...\n", + sdevname[current + 1], sdevname[proposed + 1]); + } + else + { + if ((current >= 0) && (current < DEVSCOUNT)) + { + RTS_Debug->dev_model = current; + DBG (DBG_VRB, + " -> Device not supported. Defaulting to %s ...\n", + sdevname[current + 1]); + } + else + { + RTS_Debug->dev_model = HP3970; + DBG (DBG_VRB, + "-> Device not supported. Defaulting to HP3970...\n"); + } + } + } + + return OK; +} + +static void +Set_Coordinates (SANE_Int scantype, SANE_Int resolution, + struct st_coords *coords) +{ + struct st_coords *limits = Constrains_Get (device, scantype); + + if (coords->left == -1) + coords->left = 0; + + if (coords->width == -1) + coords->width = limits->width; + + if (coords->top == -1) + coords->top = 0; + + if (coords->height == -1) + coords->height = limits->height; + + coords->left = MM_TO_PIXEL (coords->left, resolution); + coords->width = MM_TO_PIXEL (coords->width, resolution); + coords->top = MM_TO_PIXEL (coords->top, resolution); + coords->height = MM_TO_PIXEL (coords->height, resolution); + + Constrains_Check (device, resolution, scantype, coords); +} + +static SANE_Int +Color_Negative (SANE_Byte * buffer, SANE_Int size, SANE_Int depth) +{ + if (buffer != NULL) + { + SANE_Int a; + SANE_Int max_value = (1 << depth) - 1; + + if (depth > 8) + { + USHORT *sColor = (void *) buffer; + for (a = 0; a < size / 2; a++) + { + *sColor = max_value - *sColor; + sColor++; + } + } + else + { + for (a = 0; a < size; a++) + *(buffer + a) = max_value - *(buffer + a); + } + } + + return OK; +} + +static SANE_Status +get_button_status (TScanner * s) +{ + if (s != NULL) + { + SANE_Int a, b, status, btn; + + b = 1; + status = Buttons_Released (device) & 63; + for (a = 0; a < 6; a++) + { + if ((status & b) != 0) + { + btn = Buttons_Order (device, b); + if (btn != -1) + s->aValues[opt_button_0 + btn].w = SANE_TRUE; + } + + b <<= 1; + } + } + + return SANE_STATUS_GOOD; +} + +static SANE_Int +Depth_16_to_8 (SANE_Byte * from_buffer, SANE_Int size, SANE_Byte * to_buffer) +{ + if ((from_buffer != NULL) && (to_buffer != NULL)) + { + SANE_Int a, b; + + a = 1; + b = 0; + + while (a < size) + { + *(to_buffer + b) = *(from_buffer + a); + a += 2; + b++; + } + } + + return OK; +} + +static void +Gray_to_Lineart (SANE_Byte * buffer, SANE_Int size, SANE_Int threshold) +{ + /* code provided by tobias leutwein */ + + if (buffer != NULL) + { + SANE_Byte toBufferByte; + SANE_Int fromBufferPos_i = 0; + SANE_Int toBufferPos_i = 0; + SANE_Int bitPos_i; + + while (fromBufferPos_i < size) + { + toBufferByte = 0; + + for (bitPos_i = 7; bitPos_i != (-1); bitPos_i--) + { + if ((fromBufferPos_i < size) + && (buffer[fromBufferPos_i] < threshold)) + toBufferByte |= (1u << bitPos_i); + + fromBufferPos_i++; + } + + buffer[toBufferPos_i] = toBufferByte; + toBufferPos_i++; + } + } +} + +static SANE_Int +Color_to_Gray (SANE_Byte * buffer, SANE_Int size, SANE_Int depth) +{ + if (buffer != NULL) + { + SANE_Int c; + SANE_Int dot_size = 3 * ((depth > 8) ? 2 : 1); + SANE_Int colour; + SANE_Byte *pColor = buffer; + USHORT *sColor = (void *) buffer; + + for (c = 0; c < size / dot_size; c++) + { + if (depth > 8) + { + colour = + ((*sColor + *(sColor + 1) + *(sColor + 2)) / 3) & 0xffff; + *sColor = colour; + *(sColor + 1) = colour; + *(sColor + 2) = colour; + sColor += 3; + } + else + { + colour = ((*pColor + *(pColor + 1) + *(pColor + 2)) / 3) & 0xff; + *pColor = colour; + *(pColor + 1) = colour; + *(pColor + 2) = colour; + pColor += 3; + } + } + } + + return OK; +} + +static void +gamma_free (TScanner * s) +{ + DBG (DBG_FNC, "> gamma_free()\n"); + + if (s != NULL) + { + /* Destroy gamma tables */ + SANE_Int a; + + for (a = CL_RED; a <= CL_BLUE; a++) + { + if (s->aGammaTable[a] != NULL) + { + free (s->aGammaTable[a]); + s->aGammaTable[a] = NULL; + } + } + } +} + +static SANE_Int +gamma_create (TScanner * s, double gamma) +{ + SANE_Int rst = ERROR; /* by default */ + + DBG (DBG_FNC, "> gamma_create(*s)\n"); + + if (s != NULL) + { + SANE_Int a; + double value, c; + + /* default result */ + rst = OK; + + /* destroy previus gamma tables */ + gamma_free (s); + + /* check gamma value */ + if (gamma < 0) + gamma = GAMMA_DEFAULT; + + /* allocate space for 16 bit gamma tables */ + for (a = CL_RED; a <= CL_BLUE; a++) + { + s->aGammaTable[a] = malloc (65536 * sizeof (SANE_Word)); + if (s->aGammaTable[a] == NULL) + { + rst = ERROR; + break; + } + } + + if (rst == OK) + { + /* fill tables */ + for (a = 0; a < 65536; a++) + { + value = (a / (65536. - 1)); + value = pow (value, (1. / gamma)); + value = value * (65536. - 1); + + c = (SANE_Int) value; + if (c > (65536. - 1)) + c = (65536. - 1); + else if (c < 0) + c = 0; + + s->aGammaTable[CL_RED][a] = c; + s->aGammaTable[CL_GREEN][a] = c; + s->aGammaTable[CL_BLUE][a] = c; + } + } + else + gamma_free (s); + } + + return rst; +} + +static void +gamma_apply (TScanner * s, SANE_Byte * buffer, SANE_Int size, SANE_Int depth) +{ + if ((s != NULL) && (buffer != NULL)) + { + SANE_Int c; + SANE_Int dot_size = 3 * ((depth > 8) ? 2 : 1); + SANE_Byte *pColor = buffer; + USHORT *sColor = (void *) buffer; + + if ((s->aGammaTable[CL_RED] != NULL) + && (s->aGammaTable[CL_GREEN] != NULL) + && (s->aGammaTable[CL_BLUE] != NULL)) + { + for (c = 0; c < size / dot_size; c++) + { + if (depth > 8) + { + *sColor = s->aGammaTable[CL_RED][*sColor]; + *(sColor + 1) = s->aGammaTable[CL_GREEN][*(sColor + 1)]; + *(sColor + 2) = s->aGammaTable[CL_BLUE][*(sColor + 2)]; + sColor += 3; + } + else + { + /* 8 bits gamma */ + *pColor = + (s->aGammaTable[CL_RED][*pColor * 256] >> 8) & 0xff; + *(pColor + 1) = + (s-> + aGammaTable[CL_GREEN][*(pColor + 1) * 256] >> 8) & 0xff; + *(pColor + 2) = + (s-> + aGammaTable[CL_BLUE][*(pColor + 2) * 256] >> 8) & 0xff; + pColor += 3; + } + } + } + } +} + +static SANE_Int +Get_Model (SANE_String model) +{ + SANE_Int rst; + + if (strcmp (model, "HP3800") == 0) + rst = HP3800; + else if (strcmp (model, "HP3970") == 0) + rst = HP3970; + else if (strcmp (model, "HP4070") == 0) + rst = HP4070; + else if (strcmp (model, "HP4370") == 0) + rst = HP4370; + else if (strcmp (model, "HPG3010") == 0) + rst = HPG3010; + else if (strcmp (model, "UA4900") == 0) + rst = UA4900; + else if (strcmp (model, "BQ5550") == 0) + rst = BQ5550; + else + rst = HP3970; /* default */ + + return rst; +} + +static SANE_Int +Get_Source (SANE_String source) +{ + SANE_Int rst; + + if (strcmp (source, SANE_I18N ("Flatbed")) == 0) + rst = ST_NORMAL; + else if (strcmp (source, SANE_I18N ("Slide")) == 0) + rst = ST_TA; + else if (strcmp (source, SANE_I18N ("Negative")) == 0) + rst = ST_NEG; + else + rst = ST_NORMAL; /* default */ + + return rst; +} + +static SANE_Int +Get_Colormode (SANE_String colormode) +{ + SANE_Int rst; + + if (strcmp (colormode, SANE_I18N ("Color")) == 0) + rst = CM_COLOR; + else if (strcmp (colormode, SANE_I18N ("Gray")) == 0) + rst = CM_GRAY; + else if (strcmp (colormode, SANE_I18N ("Lineart")) == 0) + rst = CM_LINEART; + else + rst = CM_COLOR; /* default */ + + return rst; +} + +static SANE_Status +Translate_coords (struct st_coords *coords) +{ + SANE_Int data; + + DBG (DBG_FNC, "> translate_coords(*coords)\n"); + + if ((coords->left < 0) || (coords->top < 0) || + (coords->width < 0) || (coords->height < 0)) + return SANE_STATUS_INVAL; + + if (coords->width < coords->left) + { + data = coords->left; + coords->left = coords->width; + coords->width = data; + } + + if (coords->height < coords->top) + { + data = coords->top; + coords->top = coords->height; + coords->height = data; + } + + coords->width -= coords->left; + coords->height -= coords->top; + + if (coords->width == 0) + coords->width++; + + if (coords->height == 0) + coords->height++; + + return SANE_STATUS_GOOD; +} + +static SANE_Int +dot_size (SANE_Handle h, SANE_Int depth) +{ + /* returns size in bytes of a dot */ + + TScanner *scanner = (TScanner *) h; + SANE_Int rst = 0; + + if (scanner != NULL) + { + SANE_Int channels = (scanner->ScanParams.colormode != CM_COLOR) ? 1 : 3; + rst = channels * ((depth > 8) ? 2 : 1); + } + + return rst; +} + +static size_t +max_string_size (const SANE_String_Const strings[]) +{ + size_t size, max_size = 0; + SANE_Int i; + + DBG (DBG_FNC, "> max_string_size:\n"); + + for (i = 0; strings[i]; ++i) + { + size = strlen (strings[i]) + 1; + if (size > max_size) + max_size = size; + } + + return max_size; +} + +static void +options_free (TScanner * scanner) +{ + /* frees all information contained in controls */ + + DBG (DBG_FNC, "> options_free\n"); + + if (scanner != NULL) + { + SANE_Int i; + SANE_Option_Descriptor *pDesc; + TOptionValue *pVal; + + /* free gamma tables */ + gamma_free (scanner); + + /* free lists */ + if (scanner->list_resolutions != NULL) + free (scanner->list_resolutions); + + if (scanner->list_depths != NULL) + free (scanner->list_depths); + + if (scanner->list_sources != NULL) + free (scanner->list_sources); + + if (scanner->list_colormodes != NULL) + free (scanner->list_colormodes); + + if (scanner->list_models != NULL) + free (scanner->list_models); + + /* free values in certain controls */ + for (i = opt_begin; i < opt_count; i++) + { + pDesc = &scanner->aOptions[i]; + pVal = &scanner->aValues[i]; + + if (pDesc->type == SANE_TYPE_STRING) + { + if (pVal->s != NULL) + free (pVal->s); + } + } + } +} + +static void +options_init (TScanner * scanner) +{ + /* initializes all controls */ + + DBG (DBG_FNC, "> options_init\n"); + + if (scanner != NULL) + { + SANE_Int i; + SANE_Option_Descriptor *pDesc; + TOptionValue *pVal; + + /* set gamma */ + gamma_create (scanner, 2.2); + + /* color convertion */ + scanner->cnv.colormode = -1; + scanner->cnv.negative = FALSE; + scanner->cnv.threshold = 40; + scanner->cnv.real_depth = FALSE; + scanner->cnv.depth = -1; + + /* setting threshold */ + scanner->rng_threshold.min = 0; + scanner->rng_threshold.max = 255; + scanner->rng_threshold.quant = 0; + + /* setting gamma range (16 bits depth) */ + scanner->rng_gamma.min = 0; + scanner->rng_gamma.max = 65535; + scanner->rng_gamma.quant = 0; + + /* setting default horizontal constrain in milimeters */ + scanner->rng_horizontal.min = 0; + scanner->rng_horizontal.max = 220; + scanner->rng_horizontal.quant = 1; + + /* setting default vertical constrain in milimeters */ + scanner->rng_vertical.min = 0; + scanner->rng_vertical.max = 300; + scanner->rng_vertical.quant = 1; + + /* allocate option lists */ + bknd_colormodes (scanner, RTS_Debug->dev_model); + bknd_depths (scanner, RTS_Debug->dev_model); + bknd_models (scanner); + bknd_resolutions (scanner, RTS_Debug->dev_model); + bknd_sources (scanner, RTS_Debug->dev_model); + + /* By default preview scan */ + scanner->ScanParams.scantype = ST_NORMAL; + scanner->ScanParams.colormode = CM_COLOR; + scanner->ScanParams.resolution_x = 75; + scanner->ScanParams.resolution_y = 75; + scanner->ScanParams.coords.left = 0; + scanner->ScanParams.coords.top = 0; + scanner->ScanParams.coords.width = 220; + scanner->ScanParams.coords.height = 300; + scanner->ScanParams.depth = 8; + scanner->ScanParams.channel = 0; + + for (i = opt_begin; i < opt_count; i++) + { + pDesc = &scanner->aOptions[i]; + pVal = &scanner->aValues[i]; + + /* defaults */ + pDesc->name = ""; + pDesc->title = ""; + pDesc->desc = ""; + pDesc->type = SANE_TYPE_INT; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->cap = 0; + + switch (i) + { + case opt_begin: + pDesc->title = SANE_TITLE_NUM_OPTIONS; + pDesc->desc = SANE_DESC_NUM_OPTIONS; + pDesc->cap = SANE_CAP_SOFT_DETECT; + pVal->w = (SANE_Word) opt_count; + break; + + case grp_geometry: + pDesc->name = "grp_geometry"; + pDesc->title = SANE_I18N ("Geometry"); + pDesc->desc = ""; + pDesc->type = SANE_TYPE_GROUP; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = 0; + pDesc->cap = 0; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pVal->w = 0; + break; + + case opt_tlx: + pDesc->name = SANE_NAME_SCAN_TL_X; + pDesc->title = SANE_TITLE_SCAN_TL_X; + pDesc->desc = SANE_DESC_SCAN_TL_X; + pDesc->unit = SANE_UNIT_MM; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_horizontal; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = scanner->rng_horizontal.max; + break; + + case opt_tly: + pDesc->name = SANE_NAME_SCAN_TL_Y; + pDesc->title = SANE_TITLE_SCAN_TL_Y; + pDesc->desc = SANE_DESC_SCAN_TL_Y; + pDesc->unit = SANE_UNIT_MM; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_vertical; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = scanner->rng_vertical.max; + break; + + case opt_brx: + pDesc->name = SANE_NAME_SCAN_BR_X; + pDesc->title = SANE_TITLE_SCAN_BR_X; + pDesc->desc = SANE_DESC_SCAN_BR_X; + pDesc->unit = SANE_UNIT_MM; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_horizontal; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = scanner->rng_horizontal.max; + break; + + case opt_bry: + pDesc->name = SANE_NAME_SCAN_BR_Y; + pDesc->title = SANE_TITLE_SCAN_BR_Y; + pDesc->desc = SANE_DESC_SCAN_BR_Y; + pDesc->unit = SANE_UNIT_MM; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_vertical; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = scanner->rng_vertical.max; + break; + + case opt_resolution: + pDesc->name = SANE_NAME_SCAN_RESOLUTION; + pDesc->title = SANE_TITLE_SCAN_RESOLUTION; + pDesc->desc = SANE_DESC_SCAN_RESOLUTION; + pDesc->unit = SANE_UNIT_DPI; + pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; + pDesc->constraint.word_list = scanner->list_resolutions; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = scanner->list_resolutions[1]; + break; + + case opt_gamma_red: + pDesc->name = SANE_NAME_GAMMA_VECTOR_R; + pDesc->title = SANE_TITLE_GAMMA_VECTOR_R; + pDesc->desc = SANE_DESC_GAMMA_VECTOR_R; + pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_gamma; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->wa = scanner->aGammaTable[CL_RED]; + break; + + case opt_gamma_green: + pDesc->name = SANE_NAME_GAMMA_VECTOR_G; + pDesc->title = SANE_TITLE_GAMMA_VECTOR_G; + pDesc->desc = SANE_DESC_GAMMA_VECTOR_G; + pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_gamma; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->wa = scanner->aGammaTable[CL_GREEN]; + break; + + case opt_gamma_blue: + pDesc->name = SANE_NAME_GAMMA_VECTOR_B; + pDesc->title = SANE_TITLE_GAMMA_VECTOR_B; + pDesc->desc = SANE_DESC_GAMMA_VECTOR_B; + pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_gamma; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->wa = scanner->aGammaTable[CL_BLUE]; + break; + + case opt_scantype: + pDesc->name = SANE_NAME_SCAN_SOURCE; + pDesc->title = SANE_TITLE_SCAN_SOURCE; + pDesc->desc = SANE_DESC_SCAN_SOURCE; + pDesc->type = SANE_TYPE_STRING; + pDesc->size = max_string_size (scanner->list_sources); + pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; + pDesc->constraint.string_list = scanner->list_sources; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->s = strdup (scanner->list_sources[0]); + break; + + case opt_colormode: + pDesc->name = SANE_NAME_SCAN_MODE; + pDesc->title = SANE_TITLE_SCAN_MODE; + pDesc->desc = SANE_DESC_SCAN_MODE; + pDesc->type = SANE_TYPE_STRING; + pDesc->size = max_string_size (scanner->list_colormodes); + pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; + pDesc->constraint.string_list = scanner->list_colormodes; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->s = strdup (scanner->list_colormodes[0]); + break; + + case opt_depth: + pDesc->name = SANE_NAME_BIT_DEPTH; + pDesc->title = SANE_TITLE_BIT_DEPTH; + pDesc->desc = SANE_DESC_BIT_DEPTH; + pDesc->type = SANE_TYPE_INT; + pDesc->unit = SANE_UNIT_BIT; + pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; + pDesc->constraint.word_list = scanner->list_depths; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = scanner->list_depths[1]; + break; + + case opt_threshold: + pDesc->name = SANE_NAME_THRESHOLD; + pDesc->title = SANE_TITLE_THRESHOLD; + pDesc->desc = SANE_DESC_THRESHOLD; + pDesc->type = SANE_TYPE_INT; + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &scanner->rng_threshold; + pDesc->cap |= + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | + SANE_CAP_INACTIVE; + pVal->w = 0x80; + break; + + /* debugging options */ + case grp_debug: + pDesc->name = "grp_debug"; + pDesc->title = SANE_I18N ("Debugging Options"); + pDesc->desc = ""; + pDesc->type = SANE_TYPE_GROUP; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = 0; + pDesc->cap = SANE_CAP_ADVANCED; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pVal->w = 0; + break; + + case opt_model: + pDesc->name = "opt_model"; + pDesc->title = SANE_I18N ("Scanner model"); + pDesc->desc = + SANE_I18N + ("Lets to test device behaviour with other supported models"); + pDesc->type = SANE_TYPE_STRING; + pDesc->size = max_string_size (scanner->list_models); + pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; + pDesc->constraint.string_list = scanner->list_models; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT | + SANE_CAP_SOFT_DETECT; + pVal->s = strdup (scanner->list_models[0]); + break; + + case opt_negative: + pDesc->name = "opt_negative"; + pDesc->title = SANE_I18N ("Negative"); + pDesc->desc = SANE_I18N ("Image colours will be inverted"); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_nogamma: + pDesc->name = "opt_nogamma"; + pDesc->title = SANE_I18N ("Disable gamma correction"); + pDesc->desc = SANE_I18N ("Gamma correction will be disabled"); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_nowshading: + pDesc->name = "opt_nowshading"; + pDesc->title = SANE_I18N ("Disable white shading correction"); + pDesc->desc = + SANE_I18N ("White shading correction will be disabled"); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_nowarmup: + pDesc->name = "opt_nowarmup"; + pDesc->title = SANE_I18N ("Skip warmup process"); + pDesc->desc = SANE_I18N ("Warmup process will be disabled"); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_realdepth: + pDesc->name = "opt_realdepth"; + pDesc->title = SANE_I18N ("Force real depth"); + pDesc->desc = + SANE_I18N + ("If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation."); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_emulategray: + pDesc->name = "opt_emulategray"; + pDesc->title = SANE_I18N ("Emulate Grayscale"); + pDesc->desc = + SANE_I18N + ("If enabled, image will be scanned in color mode and then converted to grayscale by software. This uses to improve image quality in some circunstances."); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_dbgimages: + pDesc->name = "opt_dbgimages"; + pDesc->title = SANE_I18N ("Save debugging images"); + pDesc->desc = + SANE_I18N + ("If enabled, some images involved in scanner processing are saved to analyze them."); + pDesc->type = SANE_TYPE_BOOL; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | + SANE_CAP_SOFT_SELECT; + pVal->w = SANE_FALSE; + break; + + case opt_reset: + pDesc->name = "opt_reset"; + pDesc->title = SANE_I18N ("Reset chipset"); + pDesc->desc = SANE_I18N ("Resets chipset data"); + pDesc->type = SANE_TYPE_BUTTON; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = 0; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.string_list = 0; + pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT; + pVal->w = 0; + break; + + /* device information */ + case grp_info: + pDesc->name = "grp_info"; + pDesc->title = SANE_I18N ("Information"); + pDesc->desc = ""; + pDesc->type = SANE_TYPE_GROUP; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = 0; + pDesc->cap = 0; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pVal->w = 0; + break; + + case opt_chipname: + pDesc->name = "opt_chipname"; + pDesc->title = SANE_I18N ("Chipset name"); + pDesc->desc = SANE_I18N ("Shows chipset name used in device."); + pDesc->type = SANE_TYPE_STRING; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_HARD_SELECT | + SANE_CAP_SOFT_DETECT; + pVal->s = strdup (SANE_I18N ("Unknown")); + break; + + case opt_chipid: + pDesc->name = "opt_chipid"; + pDesc->title = SANE_I18N ("Chipset ID"); + pDesc->desc = SANE_I18N ("Shows the chipset ide"); + pDesc->type = SANE_TYPE_INT; + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_HARD_SELECT | + SANE_CAP_SOFT_DETECT; + pVal->w = -1; + break; + + case opt_scancount: + pDesc->name = "opt_scancount"; + pDesc->title = SANE_I18N ("Scans counter"); + pDesc->desc = + SANE_I18N ("Shows the number of scans made by scanner"); + pDesc->type = SANE_TYPE_INT; + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->cap = + SANE_CAP_ADVANCED | SANE_CAP_HARD_SELECT | + SANE_CAP_SOFT_DETECT; + pVal->w = -1; + break; + + case opt_infoupdate: + pDesc->name = "opt_infoupdate"; + pDesc->title = SANE_I18N ("Update information"); + pDesc->desc = SANE_I18N ("Updates information about device"); + pDesc->type = SANE_TYPE_BUTTON; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = 0; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.string_list = 0; + pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT; + pVal->w = 0; + break; + + /* buttons support */ + case grp_buttons: + pDesc->name = "grp_buttons"; + pDesc->title = SANE_I18N ("Buttons"); + pDesc->desc = ""; + pDesc->type = SANE_TYPE_GROUP; + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = 0; + pDesc->cap = 0; + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pDesc->constraint.range = 0; + pVal->w = 0; + break; + + case opt_button_0: + case opt_button_1: + case opt_button_2: + case opt_button_3: + case opt_button_4: + case opt_button_5: + { + char name[12]; + char title[128]; + + sprintf (name, "button %d", i - opt_button_0); + sprintf (title, "Scanner button %d", i - opt_button_0); + pDesc->name = strdup (name); + pDesc->title = strdup (title); + pDesc->desc = + SANE_I18N + ("This options reflects a front pannel scanner button"); + pDesc->type = SANE_TYPE_BOOL; + pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; + + if (i - opt_button_0 >= Buttons_Count (device)) + pDesc->cap |= SANE_CAP_INACTIVE; + + pDesc->unit = SANE_UNIT_NONE; + pDesc->size = sizeof (SANE_Word); + pDesc->constraint_type = SANE_CONSTRAINT_NONE; + pVal->w = SANE_FALSE; + } + break; + } + } + } +} + +static SANE_Int +_ReportDevice (TScannerModel * pModel, const char *pszDeviceName) +{ + SANE_Int rst = ERROR; + TDevListEntry *pNew, *pDev; + + DBG (DBG_FNC, "> _ReportDevice:\n"); + + pNew = malloc (sizeof (TDevListEntry)); + if (pNew != NULL) + { + rst = OK; + + /* add new element to the end of the list */ + if (_pFirstSaneDev != NULL) + { + /* Add at the end of existing list */ + for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext); + + pDev->pNext = pNew; + } + else + _pFirstSaneDev = pNew; + + /* fill in new element */ + pNew->pNext = NULL; + pNew->devname = (char *) strdup (pszDeviceName); + pNew->dev.name = pNew->devname; + pNew->dev.vendor = pModel->pszVendor; + pNew->dev.model = pModel->pszName; + pNew->dev.type = SANE_I18N ("flatbed scanner"); + + iNumSaneDev++; + } + + return rst; +} + +static SANE_Status +attach_one_device (SANE_String_Const devname) +{ + static TScannerModel sModel; + + DBG (DBG_FNC, "> attach_one_device(devname=%s)\n", devname); + + switch (GetUSB_device_model (devname)) + { + case HP3800: + sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); + sModel.pszName = (char *) strdup ("Scanjet 3800"); + break; + case HP3970: + sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); + sModel.pszName = (char *) strdup ("Scanjet 3970"); + break; + case HP4070: + sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); + sModel.pszName = (char *) strdup ("Scanjet 4070 Photosmart"); + break; + case HP4370: + sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); + sModel.pszName = (char *) strdup ("Scanjet 4370"); + break; + case HPG3010: + sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); + sModel.pszName = (char *) strdup ("Scanjet G3010"); + break; + case UA4900: + sModel.pszVendor = (char *) strdup ("UMAX"); + sModel.pszName = (char *) strdup ("Astra 4900"); + break; + case BQ5550: + sModel.pszVendor = (char *) strdup ("BenQ"); + sModel.pszName = (char *) strdup ("5550"); + break; + default: + sModel.pszVendor = (char *) strdup ("Unknown"); + sModel.pszName = (char *) strdup ("RTS8822 chipset based"); + break; + } + + _ReportDevice (&sModel, devname); + + return SANE_STATUS_GOOD; +} + +/* Sane default functions */ + +SANE_Status +sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) +{ + FILE *conf_fp; /* Config file stream */ + SANE_Char line[PATH_MAX]; + SANE_Char *str = NULL; + SANE_String_Const proper_str; + SANE_Int nline = 0; + + /* Initialize debug */ + DBG_INIT (); + + DBG (DBG_FNC, "> sane_init\n"); + + /* silence gcc */ + authorize = authorize; + + /* Initialize usb */ + sanei_usb_init (); + + /* Parse config file */ + conf_fp = sanei_config_open (HP3900_CONFIG_FILE); + if (conf_fp) + { + while (sanei_config_read (line, sizeof (line), conf_fp)) + { + nline++; + if (str) + free (str); + + proper_str = sanei_config_get_string (line, &str); + + /* Discards white lines and comments */ + if ((str != NULL) && (proper_str != line) && (str[0] != '#')) + { + /* If line's not blank or a comment, then it's the device + * filename or a usb directive. */ + sanei_usb_attach_matching_devices (line, attach_one_device); + } + } + fclose (conf_fp); + } + else + { + /* By default */ + sanei_usb_attach_matching_devices ("usb 0x03f0 0x2605", attach_one_device); /* HP3800 */ + sanei_usb_attach_matching_devices ("usb 0x03f0 0x2305", attach_one_device); /* HP3970 */ + sanei_usb_attach_matching_devices ("usb 0x03f0 0x2405", attach_one_device); /* HP4070 */ + sanei_usb_attach_matching_devices ("usb 0x03f0 0x4105", attach_one_device); /* HP4370 */ + sanei_usb_attach_matching_devices ("usb 0x03f0 0x4205", attach_one_device); /* HPG3010 */ + sanei_usb_attach_matching_devices ("usb 0x06dc 0x0020", attach_one_device); /* UA4900 */ + sanei_usb_attach_matching_devices ("usb 0x04a5 0x2211", attach_one_device); /* BQ5550 */ + } + + /* Return backend version */ + if (version_code != NULL) + *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0); + + return SANE_STATUS_GOOD; +} + +SANE_Status +sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) +{ + SANE_Status rst = SANE_STATUS_GOOD; + + local_only = local_only; + + if (_pSaneDevList) + free (_pSaneDevList); + + _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1)); + if (_pSaneDevList != NULL) + { + TDevListEntry *pDev; + SANE_Int i = 0; + + for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext) + _pSaneDevList[i++] = &pDev->dev; + + _pSaneDevList[i++] = 0; /* last entry is 0 */ + *device_list = _pSaneDevList; + } + else + rst = SANE_STATUS_NO_MEM; + + DBG (DBG_FNC, "> sane_get_devices: %i\n", rst); + + return rst; +} + +SANE_Status +sane_open (SANE_String_Const name, SANE_Handle * h) +{ + TScanner *s; + SANE_Status rst; + + /* check the name */ + if (strlen (name) == 0) + /* default to first available device */ + name = _pFirstSaneDev->dev.name; + + /* allocate space for RTS environment */ + device = RTS_Alloc (); + if (device != NULL) + { + /* Open device */ + rst = sanei_usb_open (name, &device->usb_handle); + if (rst == SANE_STATUS_GOOD) + { + /* Allocating memory for device */ + s = malloc (sizeof (TScanner)); + if (s != NULL) + { + memset (s, 0, sizeof (TScanner)); + + /* Initializing RTS */ + if (Init_Vars () == OK) + { + SANE_Int vendor, product; + + /* Setting device model */ + if (sanei_usb_get_vendor_product + (device->usb_handle, &vendor, + &product) == SANE_STATUS_GOOD) + s->model = Device_get (product, vendor); + else + s->model = HP3970; + + set_ScannerModel (s->model, product, vendor); + + /* Initialize device */ + if (RTS_Scanner_Init (device) == OK) + { + /* silencing unused functions */ + Silent_Compile (); + + /* initialize backend options */ + options_init (s); + *h = s; + + /* everything went ok */ + rst = SANE_STATUS_GOOD; + } + else + { + free ((void *) s); + rst = SANE_STATUS_INVAL; + } + } + else + rst = SANE_STATUS_NO_MEM; + } + else + rst = SANE_STATUS_NO_MEM; + } + } + else + rst = SANE_STATUS_NO_MEM; + + DBG (DBG_FNC, "> sane_open(name=%s): %i\n", name, rst); + + return rst; +} + +const SANE_Option_Descriptor * +sane_get_option_descriptor (SANE_Handle h, SANE_Int n) +{ + SANE_Option_Descriptor *rst = NULL; + + if ((n >= opt_begin) && (n < opt_count)) + { + TScanner *s = (TScanner *) h; + rst = &s->aOptions[n]; + } + + DBG (DBG_FNC, "> SANE_Option_Descriptor(handle, n=%i): %i\n", n, + (rst == NULL) ? -1 : 0); + + return rst; +} + +static SANE_Status +option_get (TScanner * scanner, SANE_Int optid, void *result) +{ + /* This function returns value contained in selected option */ + + DBG (DBG_FNC, "> option_get(optid=%i)\n", optid); + + if ((scanner != NULL) && (result != NULL)) + { + switch (optid) + { + /* SANE_Word */ + case opt_begin: /* null */ + case opt_reset: /* null */ + case opt_negative: + case opt_nogamma: + case opt_nowshading: + case opt_emulategray: + case opt_dbgimages: + case opt_nowarmup: + case opt_realdepth: + case opt_depth: + case opt_resolution: + case opt_threshold: + case opt_brx: + case opt_tlx: + case opt_bry: + case opt_tly: + *(SANE_Word *) result = scanner->aValues[optid].w; + break; + + /* SANE_Int */ + case opt_chipid: + case opt_scancount: + *(SANE_Int *) result = scanner->aValues[optid].w; + break; + + /* SANE_Word array */ + case opt_gamma_red: + case opt_gamma_green: + case opt_gamma_blue: + memcpy (result, scanner->aValues[optid].wa, + scanner->aOptions[optid].size); + break; + + /* String */ + case opt_colormode: + case opt_scantype: + case opt_model: + case opt_chipname: + strcpy (result, scanner->aValues[optid].s); + break; + + /* scanner buttons */ + case opt_button_0: + get_button_status (scanner); + case opt_button_1: + case opt_button_2: + case opt_button_3: + case opt_button_4: + case opt_button_5: + /* copy the button state */ + *(SANE_Word *) result = scanner->aValues[optid].w; + /* clear the button state */ + scanner->aValues[optid].w = SANE_FALSE; + break; + } + } + + return SANE_STATUS_GOOD; +} + +static SANE_Status +option_set (TScanner * scanner, SANE_Int optid, void *value, SANE_Int * pInfo) +{ + SANE_Status rst; + + DBG (DBG_FNC, "> option_set(optid=%i)\n", optid); + + rst = SANE_STATUS_INVAL; + + if (scanner != NULL) + { + if (scanner->fScanning == FALSE) + { + SANE_Int info = 0; + + rst = SANE_STATUS_GOOD; + + switch (optid) + { + case opt_brx: + case opt_tlx: + case opt_bry: + case opt_tly: + case opt_depth: + case opt_nogamma: + case opt_nowshading: + case opt_nowarmup: + case opt_negative: + case opt_emulategray: + case opt_dbgimages: + case opt_threshold: + case opt_resolution: + info |= SANE_INFO_RELOAD_PARAMS; + scanner->aValues[optid].w = *(SANE_Word *) value; + break; + + case opt_gamma_red: + case opt_gamma_green: + case opt_gamma_blue: + memcpy (scanner->aValues[optid].wa, value, + scanner->aOptions[optid].size); + break; + + case opt_scantype: + if (strcmp (scanner->aValues[optid].s, value) != 0) + { + struct st_coords *coords; + SANE_Int source; + + if (scanner->aValues[optid].s) + free (scanner->aValues[optid].s); + + scanner->aValues[optid].s = strdup (value); + + source = Get_Source (scanner->aValues[opt_scantype].s); + coords = Constrains_Get (device, source); + if (coords != NULL) + { + bknd_constrains (scanner, source, 0); + bknd_constrains (scanner, source, 1); + scanner->aValues[opt_tlx].w = 0; + scanner->aValues[opt_tly].w = 0; + scanner->aValues[opt_brx].w = coords->width; + scanner->aValues[opt_bry].w = coords->height; + } + + info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; + } + break; + + case opt_colormode: + if (strcmp (scanner->aValues[optid].s, value) != 0) + { + if (scanner->aValues[optid].s) + free (scanner->aValues[optid].s); + scanner->aValues[optid].s = strdup (value); + if (Get_Colormode (scanner->aValues[optid].s) == CM_LINEART) + scanner->aOptions[opt_threshold].cap &= + ~SANE_CAP_INACTIVE; + else + scanner->aOptions[opt_threshold].cap |= SANE_CAP_INACTIVE; + info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; + } + break; + + case opt_model: + if (strcmp (scanner->aValues[optid].s, value) != 0) + { + SANE_Int model; + + if (scanner->aValues[optid].s) + free (scanner->aValues[optid].s); + scanner->aValues[optid].s = strdup (value); + + model = Get_Model (scanner->aValues[optid].s); + if (model != RTS_Debug->dev_model) + { + SANE_Int source; + struct st_coords *coords; + + /* free configuration of last model */ + Free_Config (device); + + /* set new model */ + RTS_Debug->dev_model = model; + + /* and load configuration of current model */ + Load_Config (device); + + /* update options according to selected device */ + bknd_colormodes (scanner, model); + bknd_depths (scanner, model); + bknd_resolutions (scanner, model); + bknd_sources (scanner, model); + + /* updating lists */ + scanner->aOptions[opt_colormode].size = + max_string_size (scanner->list_colormodes); + scanner->aOptions[opt_colormode].constraint. + string_list = scanner->list_colormodes; + scanner->aOptions[opt_depth].constraint.word_list = + scanner->list_depths; + scanner->aOptions[opt_resolution].constraint.word_list = + scanner->list_resolutions; + scanner->aOptions[opt_scantype].size = + max_string_size (scanner->list_sources); + scanner->aOptions[opt_scantype].constraint.string_list = + scanner->list_sources; + + /* default values */ + if (scanner->aValues[opt_colormode].s != NULL) + free (scanner->aValues[opt_colormode].s); + + if (scanner->aValues[opt_scantype].s != NULL) + free (scanner->aValues[opt_scantype].s); + + scanner->aValues[opt_colormode].s = + strdup (scanner->list_colormodes[0]); + scanner->aValues[opt_scantype].s = + strdup (scanner->list_sources[0]); + scanner->aValues[opt_resolution].w = + scanner->list_resolutions[1]; + scanner->aValues[opt_depth].w = scanner->list_depths[1]; + + source = Get_Source (scanner->aValues[opt_scantype].s); + coords = Constrains_Get (device, source); + if (coords != NULL) + { + bknd_constrains (scanner, source, 0); + bknd_constrains (scanner, source, 1); + scanner->aValues[opt_tlx].w = 0; + scanner->aValues[opt_tly].w = 0; + scanner->aValues[opt_brx].w = coords->width; + scanner->aValues[opt_bry].w = coords->height; + } + } + + info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; + } + break; + + case opt_reset: + Chipset_Reset (device); + break; + + case opt_realdepth: + scanner->aValues[optid].w = + (scanner->cnv.real_depth == TRUE) ? SANE_TRUE : SANE_FALSE; + break; + + case opt_infoupdate: + if (bknd_info (scanner) == SANE_STATUS_GOOD) + info |= SANE_INFO_RELOAD_OPTIONS; + break; + default: + rst = SANE_STATUS_INVAL; + break; + } + + if (pInfo != NULL) + *pInfo = info; + } + } + + return rst; +} + +SANE_Status +sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, + void *pVal, SANE_Int * pInfo) +{ + TScanner *scanner; + SANE_Status rst; + + DBG (DBG_FNC, "> sane_control_option\n"); + + scanner = (TScanner *) h; + + switch (Action) + { + case SANE_ACTION_GET_VALUE: + rst = option_get (scanner, n, pVal); + break; + + case SANE_ACTION_SET_VALUE: + rst = option_set (scanner, n, pVal, pInfo); + break; + + case SANE_ACTION_SET_AUTO: + rst = SANE_STATUS_UNSUPPORTED; + break; + + default: + rst = SANE_STATUS_INVAL; + break; + } + + return rst; +} + +SANE_Status +sane_get_parameters (SANE_Handle h, SANE_Parameters * p) +{ + SANE_Status rst = SANE_STATUS_INVAL; + TScanner *s = (TScanner *) h; + + if (s != NULL) + { + struct st_coords coords; + SANE_Int res, source, depth, colormode, frameformat, bpl; + + /* first do some checks */ + + /* Get depth */ + depth = s->aValues[opt_depth].w; + + /* colormode */ + colormode = Get_Colormode (s->aValues[opt_colormode].s); + + frameformat = + (colormode == CM_COLOR) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; + + if (colormode == CM_LINEART) + depth = 1; + + /* Get Scan type */ + source = Get_Source (s->aValues[opt_scantype].s); + + /* Get resolution */ + res = s->aValues[opt_resolution].w; + + /* Get image coordinates in milimeters */ + coords.left = s->aValues[opt_tlx].w; + coords.top = s->aValues[opt_tly].w; + coords.width = s->aValues[opt_brx].w; + coords.height = s->aValues[opt_bry].w; + + /* validate coords */ + if (Translate_coords (&coords) == SANE_STATUS_GOOD) + { + Set_Coordinates (source, res, &coords); + + bpl = + (colormode != CM_LINEART) ? coords.width * dot_size (h, + depth) + : (coords.width + 7) / 8; + + /* return the data */ + p->format = frameformat; + p->last_frame = SANE_TRUE; + p->depth = depth; + p->lines = coords.height; + p->pixels_per_line = coords.width; + p->bytes_per_line = bpl; + + rst = SANE_STATUS_GOOD; + } + } + + DBG (DBG_FNC, "> sane_get_parameters: %i\n", rst); + + return rst; +} + +SANE_Status +sane_start (SANE_Handle h) +{ + SANE_Status rst = SANE_STATUS_INVAL; + TScanner *s; + + DBG (DBG_FNC, "+ sane_start\n"); + + s = (TScanner *) h; + if (s != NULL) + { + struct st_coords coords; + SANE_Int res, source, colormode, depth, channel; + + /* first do some checks */ + /* Get Scan type */ + source = Get_Source (s->aValues[opt_scantype].s); + + /* Check if scanner supports slides and negatives in case selected source is tma */ + if (!((source != ST_NORMAL) && (RTS_isTmaAttached (device) == FALSE))) + { + /* Get depth */ + depth = s->aValues[opt_depth].w; + + /* Get color mode */ + colormode = Get_Colormode (s->aValues[opt_colormode].s); + + /* Emulating certain color modes */ + if (colormode == CM_LINEART) + { + /* emulate lineart */ + s->cnv.colormode = CM_LINEART; + colormode = CM_GRAY; + depth = 8; + } + else if ((colormode == CM_GRAY) + && (s->aValues[opt_emulategray].w == SANE_TRUE)) + { + /* emulate grayscale */ + s->cnv.colormode = CM_GRAY; + colormode = CM_COLOR; + } + else + s->cnv.colormode = -1; + + /* setting channel for colormodes different than CM_COLOR */ + if (colormode != CM_COLOR) + channel = 1; + else + channel = 0; + + /* negative colors */ + s->cnv.negative = + (s->aValues[opt_negative].w == SANE_TRUE) ? TRUE : FALSE; + + /* Get threshold */ + s->cnv.threshold = s->aValues[opt_threshold].w; + + /* Get resolution */ + res = s->aValues[opt_resolution].w; + + /* set depth emulation */ + if (s->cnv.colormode == CM_LINEART) + s->cnv.real_depth = TRUE; + else + s->cnv.real_depth = + (s->aValues[opt_realdepth].w == SANE_TRUE) ? TRUE : FALSE; + + /* use gamma? */ + RTS_Debug->EnableGamma = + (s->aValues[opt_nogamma].w == SANE_TRUE) ? FALSE : TRUE; + + /* disable white shading correction? */ + RTS_Debug->wshading = + (s->aValues[opt_nowshading].w == SANE_TRUE) ? FALSE : TRUE; + + /* skip warmup process? */ + RTS_Debug->warmup = + (s->aValues[opt_nowarmup].w == SANE_TRUE) ? FALSE : TRUE; + + /* save debugging images? */ + RTS_Debug->SaveCalibFile = + (s->aValues[opt_dbgimages].w == SANE_TRUE) ? TRUE : FALSE; + + /* Get image coordinates in milimeters */ + coords.left = s->aValues[opt_tlx].w; + coords.top = s->aValues[opt_tly].w; + coords.width = s->aValues[opt_brx].w; + coords.height = s->aValues[opt_bry].w; + + /* Validate coords */ + if (Translate_coords (&coords) == SANE_STATUS_GOOD) + { + /* Stop previusly started scan */ + RTS_Scanner_StopScan (device, TRUE); + + s->ScanParams.scantype = source; + s->ScanParams.colormode = colormode; + s->ScanParams.resolution_x = res; + s->ScanParams.resolution_y = res; + s->ScanParams.channel = channel; + + memcpy (&s->ScanParams.coords, &coords, + sizeof (struct st_coords)); + Set_Coordinates (source, res, &s->ScanParams.coords); + + /* emulating depth? */ + if ((s->cnv.real_depth == FALSE) && (depth < 16) + && (RTS_Debug->EnableGamma == TRUE)) + { + /* In order to improve image quality, we will scan at 16bits if + we are using gamma correction */ + s->cnv.depth = depth; + s->ScanParams.depth = 16; + } + else + { + s->ScanParams.depth = depth; + s->cnv.depth = -1; + } + + /* set scanning parameters */ + if (RTS_Scanner_SetParams (device, &s->ScanParams) == OK) + { + /* Start scanning process */ + if (RTS_Scanner_StartScan (device) == OK) + { + /* Allocate buffer to read one line */ + s->mylin = 0; + rst = img_buffers_alloc (s, bytesperline); + } + } + } + } + else + rst = SANE_STATUS_COVER_OPEN; + } + + DBG (DBG_FNC, "- sane_start: %i\n", rst); + + return rst; +} + +SANE_Status +sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) +{ + SANE_Status rst = SANE_STATUS_GOOD; + TScanner *s = (TScanner *) h; + + DBG (DBG_FNC, "> sane_read\n"); + + if ((s != NULL) && (buf != NULL) && (len != NULL)) + { + /* nothing has been read at the moment */ + *len = 0; + + /* if we read all the lines return EOF */ + if ((s->mylin == s->ScanParams.coords.height) + || (device->Reading->Cancel == TRUE)) + { + RTS_Scanner_StopScan (device, FALSE); + img_buffers_free (s); + + DBG (DBG_FNC, "> sane_read: All lines read\n"); + rst = SANE_STATUS_EOF; + } + else + { + SANE_Int emul_len, emul_maxlen; + SANE_Int thwidth, transferred, bufflength; + SANE_Byte *buffer, *pbuffer; + + emul_len = 0; + if (s->cnv.depth != -1) + emul_maxlen = maxlen * (s->ScanParams.depth / s->cnv.depth); + else + emul_maxlen = maxlen; + + /* this is important to keep lines alignment */ + if (s->cnv.colormode == CM_LINEART) + emul_maxlen = s->ScanParams.coords.width; + + /* if we are emulating depth, we scan at 16bit when frontend waits + for 8bit data. Next buffer will be used to retrieve data from + scanner prior to convert to 8 bits depth */ + buffer = (SANE_Byte *) malloc (emul_maxlen * sizeof (SANE_Byte)); + + if (buffer != NULL) + { + pbuffer = buffer; + /* read as many lines the buffer may contain and while there are lines to be read */ + thwidth = + (s->ScanParams.colormode != + CM_LINEART) ? s->ScanParams.coords.width * dot_size (h, + s-> + ScanParams. + depth) + : (s->ScanParams.coords.width + 7) / 8; + /*thwidth = s->ScanParams.coords.width * dot_size(h, s->ScanParams.depth); */ + + while ((emul_len < emul_maxlen) + && (s->mylin < s->ScanParams.coords.height)) + { + /* Is there any data waiting for being passed ? */ + if (s->rest_amount != 0) + { + /* copy to buffer as many bytes as we can */ + bufflength = + min (emul_maxlen - emul_len, s->rest_amount); + memcpy (pbuffer, s->rest, bufflength); + emul_len += bufflength; + pbuffer += bufflength; + s->rest_amount -= bufflength; + if (s->rest_amount == 0) + s->mylin++; + } + else + { + /* read from scanner up to one line */ + if (Read_Image + (device, bytesperline, s->image, + &transferred) != OK) + { + /* error, exit function */ + DBG (DBG_FNC, + "> sane_read: Read_Image returned ERROR\n"); + rst = SANE_STATUS_EOF; + break; + } + + /* is there any data? */ + if (transferred != 0) + { + /* copy to buffer as many bytes as we can */ + bufflength = min (emul_maxlen - emul_len, thwidth); + + memcpy (pbuffer, s->image, bufflength); + emul_len += bufflength; + pbuffer += bufflength; + + /* the rest will be copied to s->rest buffer */ + if (bufflength < thwidth) + { + s->rest_amount = thwidth - bufflength; + memcpy (s->rest, s->image + bufflength, + s->rest_amount); + } + else + s->mylin++; + } + else + break; + } + } /* while */ + + /* process buffer before sending to frontend */ + if ((emul_len > 0) && (rst != SANE_STATUS_EOF)) + { + /* at this point ... + buffer : contains retrieved image + emul_len: contains size in bytes of retrieved image + + after this code ... + buf : will contain postprocessed image + len : will contain postprocessed image */ + + /* apply gamma if neccesary */ + if (RTS_Debug->EnableGamma == TRUE) + gamma_apply (s, buffer, emul_len, s->ScanParams.depth); + + /* if we are scanning negatives, let's invert colors */ + if (s->ScanParams.scantype == ST_NEG) + { + if (s->cnv.negative == FALSE) + Color_Negative (buffer, emul_len, + s->ScanParams.depth); + } + else if (s->cnv.negative != FALSE) + Color_Negative (buffer, emul_len, s->ScanParams.depth); + + /* emulating depth */ + if (s->cnv.depth != -1) + { + switch (s->cnv.depth) + { + /* case 1: treated separately as lineart */ + /*case 12: in the future */ + case 8: + Depth_16_to_8 (buffer, emul_len, buffer); + emul_len /= 2; + break; + } + } + + /* Lets do neccesary convertions */ + switch (s->cnv.colormode) + { + case CM_GRAY: + Color_to_Gray (buffer, emul_len, s->ScanParams.depth); + break; + case CM_LINEART: + { + SANE_Int rest = emul_len % 8; + + Gray_to_Lineart (buffer, emul_len, s->cnv.threshold); + emul_len /= 8; + if (rest > 0) + emul_len++; + } + break; + } + + /* copy postprocessed image */ + *len = emul_len; + memcpy (buf, buffer, *len); + } + + free (buffer); + } + } + } + else + rst = SANE_STATUS_EOF; + + return rst; +} + +void +sane_cancel (SANE_Handle h) +{ + DBG (DBG_FNC, "> sane_cancel\n"); + + /* silence gcc */ + h = h; + + device->Reading->Cancel = TRUE; +} + +SANE_Status +sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) +{ + DBG (DBG_FNC, "> sane_set_io_mode\n"); + + /* silence gcc */ + handle = handle; + non_blocking = non_blocking; + + return SANE_STATUS_UNSUPPORTED; +} + +SANE_Status +sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) +{ + DBG (DBG_FNC, "> sane_get_select_fd\n"); + + /* silence gcc */ + handle = handle; + fd = fd; + + return SANE_STATUS_UNSUPPORTED; +} + +void +sane_close (SANE_Handle h) +{ + TScanner *scanner = (TScanner *) h; + + DBG (DBG_FNC, "- sane_close...\n"); + + /* stop previus scans */ + RTS_Scanner_StopScan (device, TRUE); + + /* close usb */ + sanei_usb_close (device->usb_handle); + + /* free scanner internal variables */ + RTS_Scanner_End (device); + + /* free RTS enviroment */ + RTS_Free (device); + + /* free backend variables */ + if (scanner != NULL) + { + options_free (scanner); + + img_buffers_free (scanner); + } +} + +void +sane_exit (void) +{ + /* free device list memory */ + if (_pSaneDevList) + { + TDevListEntry *pDev, *pNext; + + for (pDev = _pFirstSaneDev; pDev; pDev = pNext) + { + pNext = pDev->pNext; + /* pDev->dev.name is the same pointer that pDev->devname */ + free (pDev->devname); + free (pDev); + } + + _pFirstSaneDev = NULL; + free (_pSaneDevList); + _pSaneDevList = NULL; + } +} diff --git a/backend/hp3900_types.c b/backend/hp3900_types.c new file mode 100644 index 000000000..2632b3fc6 --- /dev/null +++ b/backend/hp3900_types.c @@ -0,0 +1,773 @@ +/* HP Scanjet 3900 series - Structures and global variables + + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +/* devices */ +#define DEVSCOUNT 0x07 /* Number of scanners supported by this backend */ + +#define HP3970 0x00 /* rts8822l-01H HP Scanjet 3970 */ +#define HP4070 0x01 /* rts8822l-01H HP Scanjet 4070 */ +#define HP4370 0x02 /* rts8822l-02A HP Scanjet 4370 */ +#define UA4900 0x03 /* rts8822l-01H UMAX Astra 4900 */ +#define HP3800 0x04 /* rts8822bl-03A HP Scanjet 3800 */ +#define HPG3010 0x05 /* rts8822l-02A HP Scanjet G3010 */ +#define BQ5550 0x06 /* rts8823l-01E BenQ 5550 */ + +/* chipset models */ +#define RTS8822L_01H 0x00 +#define RTS8822L_02A 0x01 +#define RTS8822BL_03A 0x02 +#define RTS8823L_01E 0x03 + +/* chipset capabilities */ +#define CAP_EEPROM 0x01 + +/* acceleration types */ +#define ACC_CURVE 0x00 +#define DEC_CURVE 0x01 + +/* curve types */ +#define CRV_NORMALSCAN 0x00 +#define CRV_PARKHOME 0x01 +#define CRV_SMEARING 0x02 +#define CRV_BUFFERFULL 0x03 + +/* Sample rates */ +#define PIXEL_RATE 0x00 +#define LINE_RATE 0x01 + +/* motor types */ +#define MT_OUTPUTSTATE 0x00 +#define MT_ONCHIP_PWM 0x01 + +/* motor step types */ +#define STT_FULL 0x00 /* 90 degrees */ +#define STT_HALF 0x01 /* 45 degrees */ +#define STT_QUART 0x02 /* 22.5 degrees */ +#define STT_OCT 0x03 /* 11.25 degrees */ + +/* motor options */ +#define MTR_BACKWARD 0x00 +#define MTR_FORWARD 0x08 +#define MTR_ENABLED 0x00 +#define MTR_DISABLED 0x10 + +/* sensors */ +#define CCD_SENSOR 0x01 +#define CIS_SENSOR 0x00 + +/* sony sensor models */ +#define SNYS575 0x00 + +/* toshiba sensor models */ +#define TCD2952 0x01 +#define TCD2958 0x02 +#define TCD2905 0x03 + +/* usb types */ +#define USB20 0x01 +#define USB11 0x00 + +/* scan types */ +#define ST_NEG 0x03 +#define ST_TA 0x02 +#define ST_NORMAL 0x01 + +/* colour modes */ +#define CM_COLOR 0x00 +#define CM_GRAY 0x01 +#define CM_LINEART 0x02 + +/* colour channels */ +#define CL_RED 0x00 +#define CL_GREEN 0x01 +#define CL_BLUE 0x02 + +/* lamp types */ +#define FLB_LAMP 0x01 +#define TMA_LAMP 0x02 + +#define IST_NORMAL 0x00 +#define IST_TA 0x01 +#define IST_NEG 0x02 + +#define ICM_GRAY 0x00 +#define ICM_LINEART 0x01 +#define ICM_COLOR 0x02 + +#define TRUE 0x01 +#define FALSE 0x00 + +/* function results */ +#define OK 0x00 +#define ERROR -1 + +#define RT_BUFFER_LEN 0x71a + +#define FIX_BY_HARD 0x01 +#define FIX_BY_SOFT 0x02 + +#define REF_AUTODETECT 0x02 +#define REF_TAKEFROMSCANNER 0x01 +#define REF_NONE 0x00 + +/* bulk operations */ +#define BLK_WRITE 0x00 +#define BLK_READ 0x01 + +/* constants for resizing functions */ +#define RSZ_NONE 0x00 +#define RSZ_DECREASE 0x01 +#define RSZ_INCREASE 0x02 + +#define RSZ_GRAYL 0x00 +#define RSZ_COLOURL 0x01 +#define RSZ_COLOURH 0x02 +#define RSZ_LINEART 0x03 +#define RSZ_GRAYH 0x04 + +/* Macros for managing data */ +#define _B0(x) ((SANE_Byte)((x) & 0xFF)) +#define _B1(x) ((SANE_Byte)((x) >> 0x08)) +#define _B2(x) ((SANE_Byte)((x) >> 0x10)) +#define _B3(x) ((SANE_Byte)((x) >> 0x18)) + +/* operation constants used in RTS_GetImage */ +#define OP_STATIC_HEAD 0x00000001 +#define OP_COMPRESSION 0x00000004 +#define OP_BACKWARD 0x00000010 +#define OP_WHITE_SHAD 0x00000020 +#define OP_USE_GAMMA 0x00000040 +#define OP_BLACK_SHAD 0x00000080 +#define OP_LAMP_ON 0x00000200 + +/* data types */ + +typedef unsigned short USHORT; + +#ifdef STANDALONE +/* Stand-alone*/ +#define SANE_STATUS_GOOD 0x00 + +typedef unsigned char SANE_Byte; +typedef int SANE_Int; +typedef usb_dev_handle *USB_Handle; + +#else + +/* SANE backend */ +typedef SANE_Int USB_Handle; + +#endif + +/* structures */ + +struct st_debug_opts +{ + /* device capabilities */ + SANE_Int dev_model; + + SANE_Byte SaveCalibFile; + SANE_Byte DumpShadingData; + SANE_Byte ScanWhiteBoard; + SANE_Byte EnableGamma; + SANE_Byte use_fixed_pwm; + SANE_Int dmabuffersize; + SANE_Int dmatransfersize; + SANE_Int dmasetlength; + SANE_Int usbtype; + + SANE_Int calibrate; + SANE_Int wshading; + + SANE_Int overdrive_flb; + SANE_Int overdrive_ta; + SANE_Byte warmup; + + SANE_Int shd; +}; + +struct st_chip +{ + SANE_Int model; + SANE_Int capabilities; + char *name; +}; + +struct st_shading +{ + double *rates; + SANE_Int count; + SANE_Int ptr; +}; + +struct st_scanning +{ + SANE_Byte *imagebuffer; + SANE_Byte *imagepointer; + SANE_Int bfsize; + SANE_Int channel_size; + + /* arrange line related variables */ + SANE_Int arrange_hres; + SANE_Int arrange_compression; + SANE_Int arrange_sensor_evenodd_dist; + SANE_Int arrange_orderchannel; + SANE_Int arrange_size; + + /* Pointers to each channel colour */ + SANE_Byte *pColour[3]; + SANE_Byte *pColour1[3]; + SANE_Byte *pColour2[3]; + + /* Channel displacements */ + SANE_Int desp[3]; + SANE_Int desp1[3]; + SANE_Int desp2[3]; +}; + +struct st_resize +{ + SANE_Byte mode; + SANE_Int type; + SANE_Int fromwidth; + SANE_Int towidth; + SANE_Int bytesperline; + SANE_Int rescount; + SANE_Int resolution_x; + SANE_Int resolution_y; + + SANE_Byte *v3624; + SANE_Byte *v3628; + SANE_Byte *v362c; +}; + +struct st_gammatables +{ + SANE_Int depth; /*0=0x100| 4=0x400 |8=0x1000 */ + SANE_Byte *table[3]; +}; + +struct st_readimage +{ + SANE_Int Size4Lines; + + SANE_Byte Starting; + SANE_Byte *DMABuffer; + SANE_Int DMABufferSize; + SANE_Byte *RDStart; + SANE_Int RDSize; + SANE_Int DMAAmount; + SANE_Int Channel_size; + SANE_Byte Channels_per_dot; + SANE_Int ImageSize; + SANE_Int Bytes_Available; + SANE_Int Max_Size; + SANE_Byte Cancel; +}; + +struct st_gain_offset +{ + /* 32 bytes 08be|08e0|3654 + red green blue */ + SANE_Int edcg1[3]; /* 08e0|08e2|08e4 *//*Even offset 1 */ + SANE_Int edcg2[3]; /* 08e6|08e8|08ea *//*Even offset 2 */ + SANE_Int odcg1[3]; /* 08ec|08ee|08f0 *//*Odd offset 1 */ + SANE_Int odcg2[3]; /* 08f2|08f4|08f6 *//*Odd offset 2 */ + SANE_Byte pag[3]; /* 08f8|08f9|08fa */ + SANE_Byte vgag1[3]; /* 08fb|08fc|08fd */ + SANE_Byte vgag2[3]; /* 08fe|08ff|0900 */ +}; + +struct st_calibration_config +{ + SANE_Int WStripXPos; + SANE_Int WStripYPos; + SANE_Int BStripXPos; + SANE_Int BStripYPos; + SANE_Int WRef[3]; + SANE_Int BRef[3]; + SANE_Byte RefBitDepth; + double OffsetTargetMax; + double OffsetTargetMin; + double OffsetBoundaryRatio1; + double OffsetBoundaryRatio2; + double OffsetAvgRatio1; + double OffsetAvgRatio2; + SANE_Int CalibOffset10n; + SANE_Int CalibOffset20n; + SANE_Int AdcOffEvenOdd; + SANE_Int AdcOffQuickWay; + SANE_Int OffsetEven1[3]; + SANE_Int OffsetOdd1[3]; + SANE_Int OffsetEven2[3]; + SANE_Int OffsetOdd2[3]; + SANE_Byte OffsetHeight; + SANE_Int OffsetPixelStart; + SANE_Int OffsetNPixel; + SANE_Byte OffsetNSigma; + SANE_Int AdcOffPredictStart; + SANE_Int AdcOffPredictEnd; + SANE_Byte OffsetAvgTarget[3]; + SANE_Byte OffsetTuneStep1; + SANE_Byte OffsetTuneStep2; + double GainTargetFactor; + SANE_Int CalibGain10n; + SANE_Int CalibGain20n; + SANE_Int CalibPAGOn; + SANE_Int GainHeight; + SANE_Int unk1[3]; + SANE_Int unk2[3]; + SANE_Byte PAG[3]; + SANE_Byte Gain1[3]; + SANE_Byte Gain2[3]; + /* White Shading */ + SANE_Int WShadingOn; + SANE_Int WShadingHeight; + SANE_Int WShadingPreDiff[3]; + SANE_Int unknown; /*?? */ + double ShadingCut[3]; + /* Black Shading */ + SANE_Int BShadingOn; + SANE_Int BShadingHeight; + SANE_Int BShadingDefCutOff; + SANE_Int BShadingPreDiff[3]; + double ExternBoundary; + SANE_Int EffectivePixel; + SANE_Byte TotShading; +}; + +struct st_calibration +{ + /* faac */ + struct st_gain_offset gain_offset; /* 0..35 */ + USHORT *white_shading[3]; /* +36 +40 +44 */ + USHORT *black_shading[3]; /* +48 +52 +56 */ + SANE_Int WRef[3]; /* +60 +62 +64 */ + SANE_Byte shading_type; /* +66 */ + SANE_Byte shading_enabled; /* +67 */ + SANE_Int first_position; /* +68 */ + SANE_Int shadinglength; /* +72 */ +}; + +struct st_cal2 +{ + /* f9f8 35 bytes */ + SANE_Int table_count; /* +0 f9f8 */ + SANE_Int shadinglength1; /* +4 f9fc */ + SANE_Int tables_size; /* +8 fa00 */ + SANE_Int shadinglength3; /* +12 fa04 */ + USHORT *tables[4]; /* +16+20+24+28 fa08 fa0c fa10 fa14 */ + USHORT *table2; /* +32 fa18 */ +}; + +struct st_coords +{ + SANE_Int left; + SANE_Int width; + SANE_Int top; + SANE_Int height; +}; + +struct params +{ + SANE_Int scantype; + SANE_Int colormode; + SANE_Int resolution_x; + SANE_Int resolution_y; + struct st_coords coords; + SANE_Int depth; + SANE_Int channel; +}; + +struct st_constrains +{ + struct st_coords reflective; + struct st_coords negative; + struct st_coords slide; +}; + +struct st_scanparams /* 44 bytes size */ +{ + /* 760-78b|155c-1587|fa58-fa83|f0c4 */ + SANE_Byte colormode; /* [+00] 760 */ + SANE_Byte depth; /* [+01] 761 */ + SANE_Byte samplerate; /* [+02] 762 */ + SANE_Byte timing; /* [+03] 763 */ + SANE_Int channel; /* [+04] 764 */ + SANE_Int sensorresolution; /* [+06] 766 */ + SANE_Int resolution_x; /* [+08] 768 */ + SANE_Int resolution_y; /* [+10] 76a */ + struct st_coords coord; /* [+12] left */ + /* [+16] width */ + /* [+20] top */ + /* [+24] height */ + SANE_Int shadinglength; /* [+28] 77c */ + SANE_Int v157c; /* [+32] 780 */ + SANE_Int bytesperline; /* [+36] 784 */ + SANE_Int expt; /* [+40] 788 */ + + SANE_Int startpos; /* [+44] 78c */ + SANE_Int leftleading; /* [+46] 78e */ + SANE_Int ser; /* [+48] 790 */ + SANE_Int ler; /* [+52] 794 */ + SANE_Int scantype; /* [+58] 79a */ +}; + +struct st_hwdconfig /* 28 bytes size */ +{ + /* fa84-fa9f|f0ac-f0c7|e838-e853|f3a4-f3bf */ + SANE_Int startpos; /* +0 */ + /* +1..7 */ + SANE_Byte arrangeline; /* +8 */ + SANE_Byte scantype; /* +9 */ + SANE_Byte compression; /* +10 */ + SANE_Byte use_gamma_tables; /* +11 */ + SANE_Byte gamma_tablesize; /* +12 */ + SANE_Byte white_shading; /* +13 */ + SANE_Byte black_shading; /* +14 */ + SANE_Byte unk3; /* +15 */ + SANE_Byte motorplus; /* +16 */ + SANE_Byte static_head; /* +17 */ + SANE_Byte motor_direction; /* +18 */ + SANE_Byte dummy_scan; /* +19 */ + SANE_Byte highresolution; /* +20 */ + SANE_Byte sensorevenodddistance; /* +21 */ + /* +22..23 */ + SANE_Int calibrate; /* +24 */ +}; + +struct st_calibration_data +{ + SANE_Byte Regs[RT_BUFFER_LEN]; + struct st_scanparams scancfg; + struct st_gain_offset gain_offset; +}; + +struct st_cph +{ + double p1; + double p2; + SANE_Byte ps; + SANE_Byte ge; + SANE_Byte go; +}; + +struct st_timing +{ + SANE_Int sensorresolution; + SANE_Byte cnpp; + SANE_Byte cvtrp[3]; /* 3 transfer gates */ + SANE_Byte cvtrw; + SANE_Byte cvtrfpw; + SANE_Byte cvtrbpw; + struct st_cph cph[6]; /* Linear Image Sensor Clocks */ + SANE_Int cphbp2s; + SANE_Int cphbp2e; + SANE_Int clamps; + SANE_Int clampe; + SANE_Byte cdss[2]; + SANE_Byte cdsc[2]; + SANE_Byte cdscs[2]; /* Toshiba T958 ccd from hp4370 */ + double adcclkp[2]; + SANE_Int adcclkp2e; +}; + +struct st_scanmode +{ + SANE_Int scantype; + SANE_Int colormode; + SANE_Int resolution; + + SANE_Byte timing; + SANE_Int motorcurve; + SANE_Byte samplerate; + SANE_Byte systemclock; + SANE_Int ctpc; + SANE_Int motorbackstep; + SANE_Byte scanmotorsteptype; + + SANE_Byte dummyline; + SANE_Int expt[3]; + SANE_Int mexpt[3]; + SANE_Int motorplus; + SANE_Int multiexposurefor16bitmode; + SANE_Int multiexposureforfullspeed; + SANE_Int multiexposure; + SANE_Int mri; + SANE_Int msi; + SANE_Int mmtir; + SANE_Int mmtirh; + SANE_Int skiplinecount; +}; + +struct st_motormove +{ + SANE_Byte systemclock; + SANE_Int ctpc; + SANE_Byte scanmotorsteptype; + SANE_Int motorcurve; +}; + +struct st_motorpos +{ + SANE_Int coord_y; + SANE_Byte options; + SANE_Int v12e448; + SANE_Int v12e44c; +}; + +struct st_find_edge +{ + SANE_Int exposuretime; + SANE_Int scanystart; + SANE_Int scanylines; + SANE_Int findlermethod; + SANE_Int findlerstart; + SANE_Int findlerend; + SANE_Int checkoffsetser; + SANE_Int findserchecklines; + SANE_Int findserstart; + SANE_Int findserend; + SANE_Int findsermethod; + SANE_Int offsettoser; + SANE_Int offsettoler; +}; + +struct st_curve +{ + SANE_Int crv_speed; /* acceleration or deceleration */ + SANE_Int crv_type; + SANE_Int step_count; + SANE_Int *step; +}; + +struct st_motorcurve +{ + SANE_Int mri; + SANE_Int msi; + SANE_Int skiplinecount; + SANE_Int motorbackstep; + SANE_Int curve_count; + struct st_curve **curve; +}; + +struct st_checkstable +{ + double diff; + SANE_Int interval; + long tottime; +}; + +struct st_sensorcfg +{ + SANE_Int type; + SANE_Int name; + SANE_Int resolution; + + SANE_Int channel_color[3]; + SANE_Int channel_gray[2]; + SANE_Int rgb_order[3]; + + SANE_Int line_distance; + SANE_Int evenodd_distance; +}; + +struct st_autoref +{ + SANE_Byte type; + SANE_Int offset_x; + SANE_Int offset_y; + SANE_Int resolution; + SANE_Int extern_boundary; +}; + +struct st_motorcfg +{ + SANE_Byte type; + SANE_Int resolution; + SANE_Byte pwmfrequency; + SANE_Int basespeedpps; + SANE_Int basespeedmotormove; + SANE_Int highspeedmotormove; + SANE_Int parkhomemotormove; + SANE_Byte changemotorcurrent; +}; + +struct st_buttons +{ + SANE_Int count; + SANE_Int mask[6]; /* up to 6 buttons */ +}; + +struct st_device +{ + /* next var handles usb device, used for every usb operations */ + USB_Handle usb_handle; + + /* next buffer will contain initial state registers of the chipset */ + SANE_Byte *init_regs; + + /* next structure will contain information and capabilities about chipset */ + struct st_chip *chipset; + + /* next structure will contain general configuration of stepper motor */ + struct st_motorcfg *motorcfg; + + /* next structure will contain general configuration of ccd sensor */ + struct st_sensorcfg *sensorcfg; + + /* next structure will contain all ccd timing values */ + SANE_Int timings_count; + struct st_timing **timings; + + /* next structure will contain all possible motor movements */ + SANE_Int motormove_count; + struct st_motormove **motormove; + + /* next structure will contain all motorcurve values */ + SANE_Int mtrsetting_count; + struct st_motorcurve **mtrsetting; + + /* next structure will contain all possible scanning modes for one scanner */ + SANE_Int scanmodes_count; + struct st_scanmode **scanmodes; + + /* next structure contains constrain values for one scanner */ + struct st_constrains *constrains; + + /* next structure contains supported buttons and their order */ + struct st_buttons *buttons; + + /* next structure will be used to resize scanned image */ + struct st_resize *Resize; + + /* next structure will be used while reading image from device */ + struct st_readimage *Reading; + + /* next structure will be used to arrange color channels while scanning */ + struct st_scanning *scanning; +}; + +/* Unknown vars */ +SANE_Int v14b4 = 0; +SANE_Byte *v1600 = NULL; /* tabla */ +SANE_Byte *v1604 = NULL; /* tabla */ +SANE_Byte *v1608 = NULL; /* tabla */ +SANE_Byte v160c; +SANE_Int v1610; +SANE_Byte v1619; +SANE_Int v15f8; + +SANE_Int acccurvecount; /* counter used y MotorSetup */ +SANE_Int deccurvecount; /* counter used y MotorSetup */ +SANE_Int smearacccurvecount; /* counter used y MotorSetup */ +SANE_Int smeardeccurvecount; /* counter used y MotorSetup */ + +/* Known vars */ +SANE_Int offset[3]; +SANE_Byte gain[3]; + +static SANE_Int usbfile = -1; +SANE_Int scantype; + +SANE_Byte pwmlampenabled; +SANE_Byte pwmlamplevel; + +SANE_Byte dpi100Lumping; +SANE_Byte arrangeline; +SANE_Byte binarythresholdh; +SANE_Byte binarythresholdl; + +SANE_Byte shadingbase; +SANE_Byte shadingfact[3]; +SANE_Byte arrangeline; +SANE_Int compression; + +SANE_Byte linedarlampoff; +SANE_Int pixeldarklevel; + +SANE_Int bw_threshold = 0x00; + +/* SetScanParams */ +struct st_scanparams scan; +struct st_scanparams scan2; + +SANE_Int bytesperline; /* width * (3 colors [RGB]) */ +SANE_Int imagewidth3; +SANE_Int lineart_width; +SANE_Int imagesize; /* bytesperline * coords.height */ +SANE_Int imageheight; +SANE_Int line_size; +SANE_Int v15b4; +SANE_Int v15bc; +SANE_Int waitforpwm; + +SANE_Byte WRef[3]; + +USHORT *fixed_black_shading[3] = { NULL, NULL, NULL }; +USHORT *fixed_white_shading[3] = { NULL, NULL, NULL }; + +/* Calibration */ +struct st_gain_offset mitabla2; /* calibration table */ +SANE_Int v0750; + +static SANE_Byte use_gamma_tables; + +SANE_Int read_v15b4 = 0; + +SANE_Int v35b8 = 0; +SANE_Int arrangeline2; + +SANE_Int v07c0 = 0; + +/* next structure contains coefficients for white shading correction */ +struct st_shading *wshading; + +struct st_gammatables *hp_gamma; +struct st_gain_offset *default_gain_offset; +struct st_calibration_data *calibdata; + +struct st_debug_opts *RTS_Debug; + +/* testing */ +SANE_Byte *jkd_black = NULL; +SANE_Int jkd_blackbpl; diff --git a/backend/hp3900_usb.c b/backend/hp3900_usb.c new file mode 100644 index 000000000..4576d3a2a --- /dev/null +++ b/backend/hp3900_usb.c @@ -0,0 +1,503 @@ +/* HP Scanjet 3900 series - USB layer + + Copyright (C) 2005-2008 Jonathan Bravo Lopez + + 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. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +#define TIMEOUT 1000 +#define BLK_READ_EP 0x81 +#define BLK_WRITE_EP 0x02 + +SANE_Int dataline_count = 0; + +/* USB layer commands */ +static SANE_Int usb_ctl_write (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * buffer, SANE_Int size, + SANE_Int index); +static SANE_Int usb_ctl_read (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * buffer, SANE_Int size, + SANE_Int index); + +/* Higher level commands*/ + +static SANE_Int IRead_Byte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * data, SANE_Int index); +static SANE_Int IRead_Word (USB_Handle usb_handle, SANE_Int address, + SANE_Int * data, SANE_Int index); +static SANE_Int IRead_Integer (USB_Handle usb_handle, SANE_Int address, + SANE_Int * data, SANE_Int index); +static SANE_Int IRead_Buffer (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * buffer, SANE_Int size, + SANE_Int index); +static SANE_Int IWrite_Byte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte data, SANE_Int index1, + SANE_Int index2); +static SANE_Int IWrite_Word (USB_Handle usb_handle, SANE_Int address, + SANE_Int data, SANE_Int index); +static SANE_Int IWrite_Integer (USB_Handle usb_handle, SANE_Int address, + SANE_Int data, SANE_Int index); +static SANE_Int IWrite_Buffer (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * buffer, SANE_Int size, + SANE_Int index); + +static SANE_Int Read_Byte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * data); +static SANE_Int Read_Word (USB_Handle usb_handle, SANE_Int address, + SANE_Int * data); +static SANE_Int Read_Integer (USB_Handle usb_handle, SANE_Int address, + SANE_Int * data); +static SANE_Int Read_Buffer (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * buffer, SANE_Int size); +static SANE_Int Read_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, + size_t size); +static SANE_Int Write_Byte (USB_Handle usb_handle, SANE_Int address, + SANE_Byte data); +static SANE_Int Write_Word (USB_Handle usb_handle, SANE_Int address, + SANE_Int data); +/*static SANE_Int Write_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data);*/ +static SANE_Int Write_Buffer (USB_Handle usb_handle, SANE_Int address, + SANE_Byte * buffer, SANE_Int size); +static SANE_Int Write_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, + SANE_Int size); + +static SANE_Int show_buffer (SANE_Int level, SANE_Byte * buffer, + SANE_Int size); + +/* Implementation */ + +static SANE_Int +IWrite_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data, + SANE_Int index1, SANE_Int index2) +{ + SANE_Int rst = ERROR; + SANE_Byte buffer[2] = { 0x00, 0x00 }; + + if (usb_ctl_read (usb_handle, address + 1, buffer, 0x02, index1) == 2) + { + buffer[1] = (buffer[0] & 0xff); + buffer[0] = (data & 0xff); + + if (usb_ctl_write (usb_handle, address, buffer, 0x02, index2) == 2) + rst = OK; + } + + return rst; +} + +static SANE_Int +IWrite_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data, + SANE_Int index) +{ + SANE_Int rst = ERROR; + SANE_Byte buffer[2]; + + buffer[0] = (data & 0xff); + buffer[1] = ((data >> 8) & 0xff); + + if (usb_ctl_write (usb_handle, address, buffer, 0x02, index) == 2) + rst = OK; + + return rst; +} + +static SANE_Int +IWrite_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data, + SANE_Int index) +{ + SANE_Int rst = ERROR; + SANE_Byte buffer[4]; + + buffer[0] = (data & 0xff); + buffer[1] = ((data >> 8) & 0xff); + buffer[2] = ((data >> 16) & 0xff); + buffer[3] = ((data >> 24) & 0xff); + + if (usb_ctl_write (usb_handle, address, buffer, 0x04, index) == 4) + rst = OK; + + return rst; +} + +static SANE_Int +IWrite_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, + SANE_Int size, SANE_Int index) +{ + SANE_Int ret = ERROR; + + if (!((buffer == NULL) && (size > 0))) + if (usb_ctl_write (usb_handle, address, buffer, size, index) == size) + ret = OK; + + return ret; +} + +static SANE_Int +IRead_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, + SANE_Int index) +{ + SANE_Byte buffer[2] = { 0x00, 0x00 }; + SANE_Int ret = ERROR; + + if (data != NULL) + if (usb_ctl_read (usb_handle, address, buffer, 0x02, index) == 2) + { + *data = (SANE_Byte) (buffer[0] & 0xff); + ret = OK; + } + + return ret; +} + +static SANE_Int +IRead_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data, + SANE_Int index) +{ + SANE_Byte buffer[2] = { 0x00, 0x00 }; + SANE_Int ret = ERROR; + + if (data != NULL) + if (usb_ctl_read (usb_handle, address, buffer, 0x02, index) == 2) + { + *data = ((buffer[1] << 8) & 0xffff) + (buffer[0] & 0xff); + ret = OK; + } + + return ret; +} + +static SANE_Int +IRead_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data, + SANE_Int index) +{ + SANE_Byte buffer[4] = { 0x00, 0x00, 0x00, 0x00 }; + SANE_Int ret = ERROR; + + if (data != NULL) + { + *data = 0; + if (usb_ctl_read (usb_handle, address, buffer, 0x04, index) == 4) + { + SANE_Int C; + for (C = 3; C >= 0; C--) + *data = ((*data << 8) + (buffer[C] & 0xff)) & 0xffffffff; + ret = OK; + } + } + + return ret; +} + +static SANE_Int +IRead_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, + SANE_Int size, SANE_Int index) +{ + SANE_Int ret = ERROR; + + if (buffer != NULL) + if (usb_ctl_read (usb_handle, address, buffer, size, index) == size) + ret = OK; + + return ret; +} + +static SANE_Int +Write_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data) +{ + return IWrite_Byte (usb_handle, address, data, 0x100, 0); +} + +static SANE_Int +Write_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data) +{ + return IWrite_Word (usb_handle, address, data, 0); +} + +/*static SANE_Int Write_Integer(USB_Handle usb_handle, SANE_Int address, SANE_Int data) +{ + return IWrite_Integer(usb_handle, address, data, 0); +}*/ + +static SANE_Int +Write_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, + SANE_Int size) +{ + return IWrite_Buffer (usb_handle, address, buffer, size, 0); +} + +static SANE_Int +Read_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data) +{ + return IRead_Byte (usb_handle, address, data, 0x100); +} + +static SANE_Int +Read_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) +{ + return IRead_Word (usb_handle, address, data, 0x100); +} + +static SANE_Int +Read_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) +{ + return IRead_Integer (usb_handle, address, data, 0x100); +} + +static SANE_Int +Read_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, + SANE_Int size) +{ + return IRead_Buffer (usb_handle, address, buffer, size, 0x100); +} + +static SANE_Int +Write_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, SANE_Int size) +{ + SANE_Int rst = ERROR; + + if (buffer != NULL) + { + dataline_count++; + DBG (DBG_CTL, "%06i BLK DO: %i. bytes\n", dataline_count, size); + show_buffer (4, buffer, size); + +#ifdef STANDALONE + if (usb_handle != NULL) + if (usb_bulk_write (usb_handle, + BLK_WRITE_EP, + (char *) buffer, size, TIMEOUT) == size) + rst = OK; +#else + if (usb_handle != -1) + { + size_t mysize = size; + if (sanei_usb_write_bulk (usb_handle, + buffer, &mysize) == SANE_STATUS_GOOD) + rst = OK; + } +#endif + } + + if (rst != OK) + DBG (DBG_CTL, " : Write_Bulk error\n"); + + return rst; +} + +static SANE_Int +Read_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, size_t size) +{ + SANE_Int rst = ERROR; + + if (buffer != NULL) + { + dataline_count++; + DBG (DBG_CTL, "%06i BLK DI: Buffer length = %i. bytes\n", + dataline_count, size); + +#ifdef STANDALONE + if (usb_handle != NULL) + rst = usb_bulk_read (usb_handle, + BLK_READ_EP, (char *) buffer, size, TIMEOUT); +#else + if (usb_handle != -1) + if (sanei_usb_read_bulk (usb_handle, + buffer, &size) == SANE_STATUS_GOOD) + rst = size; +#endif + } + + if (rst < 0) + DBG (DBG_CTL, " : Read_Bulk error\n"); + else + show_buffer (4, buffer, rst); + + return rst; +} + +static SANE_Int +usb_ctl_write (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, + SANE_Int size, SANE_Int index) +{ + SANE_Int rst = ERROR; + + dataline_count++; + DBG (DBG_CTL, "%06i CTL DO: 40 04 %04x %04x %04x\n", + dataline_count, address & 0xffff, index, size); + show_buffer (DBG_CTL, buffer, size); + +#ifdef STANDALONE + if (usb_handle != NULL) + rst = usb_control_msg (usb_handle, 0x40, /* Request type */ + 0x04, /* Request */ + address, /* Value */ + index, /* Index */ + (char *) buffer, /* Buffer */ + size, /* Size */ + TIMEOUT); +#else + if (usb_handle != -1) + { + if (sanei_usb_control_msg (usb_handle, 0x40, /* Request type */ + 0x04, /* Request */ + address, /* Value */ + index, /* Index */ + size, /* Size */ + buffer) /* Buffer */ + == SANE_STATUS_GOOD) + rst = size; + else + rst = -1; + } +#endif + + if (rst < 0) + DBG (DBG_CTL, " : Error, returned %i\n", rst); + + return rst; +} + +static SANE_Int +usb_ctl_read (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, + SANE_Int size, SANE_Int index) +{ + SANE_Int rst; + + rst = ERROR; + + dataline_count++; + DBG (DBG_CTL, "%06i CTL DI: c0 04 %04x %04x %04x\n", + dataline_count, address & 0xffff, index, size); + +#ifdef STANDALONE + if (usb_handle != NULL) + rst = usb_control_msg (usb_handle, 0xc0, /* Request type */ + 0x04, /* Request */ + address, /* Value */ + index, /* Index */ + (char *) buffer, /* Buffer */ + size, /* Size */ + TIMEOUT); +#else + if (usb_handle != -1) + { + if (sanei_usb_control_msg (usb_handle, 0xc0, /* Request type */ + 0x04, /* Request */ + address, /* Value */ + index, /* Index */ + size, /* Size */ + buffer) /* Buffer */ + == SANE_STATUS_GOOD) + rst = size; + else + rst = -1; + } +#endif + + if (rst < 0) + DBG (DBG_CTL, " : Error, returned %i\n", rst); + else + show_buffer (DBG_CTL, buffer, rst); + + return rst; +} + +static SANE_Int +show_buffer (SANE_Int level, SANE_Byte * buffer, SANE_Int size) +{ + if (DBG_LEVEL >= level) + { + char *sline = NULL; + char *sdata = NULL; + SANE_Int cont, data, offset = 0, col = 0; + + if ((size > 0) && (buffer != NULL)) + { + sline = (char *) malloc (256); + if (sline != NULL) + { + sdata = (char *) malloc (256); + if (sdata != NULL) + { + bzero (sline, 256); + for (cont = 0; cont < size; cont++) + { + if (col == 0) + { + if (cont == 0) + snprintf (sline, 255, " BF: "); + else + snprintf (sline, 255, " "); + } + data = (buffer[cont] & 0xff); + snprintf (sdata, 255, "%02x ", data); + sline = strcat (sline, sdata); + col++; + offset++; + if (col == 8) + { + col = 0; + snprintf (sdata, 255, " : %i\n", offset - 8); + sline = strcat (sline, sdata); + DBG (level, "%s", sline); + bzero (sline, 256); + } + } + if (col > 0) + { + for (cont = col; cont < 8; cont++) + { + snprintf (sdata, 255, "-- "); + sline = strcat (sline, sdata); + offset++; + } + snprintf (sdata, 255, " : %i\n", offset - 8); + sline = strcat (sline, sdata); + DBG (level, "%s", sline); + bzero (sline, 256); + } + free (sdata); + } + free (sline); + } + } + else + DBG (level, " BF: Empty buffer\n"); + } + return OK; +}