diff -urN sane-backends-1.0.15.orig/backend/Makefile.in sane-backends-1.0.15/backend/Makefile.in --- sane-backends-1.0.15.orig/backend/Makefile.in 2005-07-26 13:24:29.985094160 -0500 +++ sane-backends-1.0.15/backend/Makefile.in 2005-07-26 13:25:11.194829328 -0500 @@ -61,7 +61,7 @@ @SET_MAKE@ -PRELOADABLE_BACKENDS = @BACKENDS@ +PRELOADABLE_BACKENDS = hp_rts88xx @BACKENDS@ ALL_BACKENDS = $(PRELOADABLE_BACKENDS) dll @@ -79,7 +79,7 @@ LIBOBJS = $(addprefix ../lib/,$(addsuffix .lo,$(LIBLIB_FUNCS))) -DISTFILES = abaton.c abaton.conf abaton.h agfafocus.c agfafocus.conf \ +DISTFILES = hp_rts88xx.c hp_rts88xx.h abaton.c abaton.conf abaton.h agfafocus.c agfafocus.conf \ agfafocus.h apple.c apple.conf apple.h artec.c artec.conf artec.h \ artec_eplus48u.c artec_eplus48u.h artec_eplus48u.conf as6e.c \ as6e.h avision.c avision.conf avision.h bh.c bh.conf bh.h canon.c \ @@ -266,7 +266,10 @@ libsane-abaton.la: ../sanei/sanei_config2.lo libsane-abaton.la: ../sanei/sanei_constrain_value.lo -libsane-abaton.la: ../sanei/sanei_scsi.lo +libsane-abaton.la: ../sanei/sanei_scsi.lo +libsane-hp_rts88xx.la: ../sanei/sanei_config2.lo +libsane-hp_rts88xx.la: ../sanei/sanei_constrain_value.lo +libsane-hp_rts88xx.la: ../sanei/sanei_usb.lo libsane-agfafocus.la: ../sanei/sanei_config2.lo libsane-agfafocus.la: ../sanei/sanei_constrain_value.lo libsane-agfafocus.la: ../sanei/sanei_scsi.lo diff -urN sane-backends-1.0.15.orig/backend/dll.conf sane-backends-1.0.15/backend/dll.conf --- sane-backends-1.0.15.orig/backend/dll.conf 2005-07-26 13:24:29.959098112 -0500 +++ sane-backends-1.0.15/backend/dll.conf 2005-07-26 13:25:11.200828416 -0500 @@ -67,3 +67,4 @@ # HP OfficeJet backend homepage: http://hpoj.sf.net/ # Uncomment the following line if hpoj is installed: #hpoj +hp_rts88xx diff -urN sane-backends-1.0.15.orig/backend/hp_rts88xx.c sane-backends-1.0.15/backend/hp_rts88xx.c --- sane-backends-1.0.15.orig/backend/hp_rts88xx.c 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts88xx.c 2005-07-26 13:25:11.152835712 -0500 @@ -0,0 +1,1594 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP4400C, HP4470C, HP3500C, 3530C, and HP ScanJet 3570C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + enable DEDUG output: + use a nomal shell (konsole) and type + export SANE_DEBUG_HP_RTS88XX=32 + xsane +*/ + +#ifndef BACKEND_NAME +#define BACKEND_NAME hp_rts88xx +#endif +#ifndef BUILD +#define BUILD 18 +#endif + +/*#define STANDALONE*/ +/*#define ENABLE_VI8920*/ + +/* definitions for debug */ +#define DEBUG /* debug output */ +/*#define DEBUG_HP3500 * debug switch to test the 3500 code under hp4470c */ +/*#define STOP_HP3500_1*/ + +/*#define DEBUG_SCAN * debug output about getting the immage datas */ +/*#define DEBUG_L * don't wait for lamp warm up */ +/*#define USBDEBUG * debug output about the USB in/out */ +/*#define DEBUG_FILE * additional write into a pnm file (not allowed as driver)*/ + +#include /* malloc, free */ +#include /* memcpy */ +#include +#include "../include/sane/sane.h" +#include "../include/sane/config.h" +#include "../include/sane/sanei.h" +#include "../include/sane/sanei_config.h" +#include "../include/sane/saneopts.h" + +#ifdef STANDALONE + #define V_MAJOR 1 + #define V_MINOR 15 + #define PATH_MAX 128 + #define DBG fprintf + #define DBG_MSG stdout + #define DBG_USB stdout + #define DBG_OPT stdout + #define DBG_SCAN stdout + #define DBG_ASSERT stdout + #define DBG_ERR stdout +#else +#include "../include/sane/sanei_backend.h" + #define DBG_ASSERT 1 + #define DBG_ERR 2 + #define DBG_MSG 16 + #define DBG_SCAN 32 + #define DBG_OPT 64 + #define DBG_USB 128 +#endif + +#define HP_RTS_CONFIG_FILE "hp_rts88xx.conf" + +#include "hp_rts88xx.h" +#include "hp_rts_44x0c.h" +#include "hp_rts_35x0c.h" + +/* (source) includes for data transfer methods */ +#include "hp_rts_xfer.c" +/* (source) includes for special scanner code */ +#include "hp_rts_44x0c.c" +#include "hp_rts_35x0c.c" + + +/****************************************************************************/ +SANE_Bool _InitScan(TScanParams *pParams, THWParams *pHWParams, TDataPipe *pDataPipe) +/****************************************************************************/ +{ + SANE_Int iHandle; + SANE_Bool result; + iHandle = pHWParams->iXferHandle; + + result = SANE_FALSE; + /* check validity of scanparameters */ + switch (pParams->iDpi) { + case 150: + case 200: + case 300: + case 600: + break; + default: + DBG(DBG_ERR, "InitScan: Invalid dpi (%d)\n", pParams->iDpi); + return SANE_FALSE; + } + switch (pParams->iLpi) { + case 150: + case 200: + case 300: + case 600: + break; + default: + DBG(DBG_ERR, "InitScan: Invalid lpi (%d)\n", pParams->iLpi); + return SANE_FALSE; + } + /* *** Done checking scan parameters validity *** */ + switch (pHWParams->ScannerModel) { + case eHp3500c: case eHp3530c: +#ifdef ENABLE_VI8920 + case eVi8920: +#endif + result = Hp35x0c_init_scan(pHWParams,pParams,pDataPipe); + if (result) + DBG(DBG_ERR, "InitScan: OK\n"); + else + DBG(DBG_ERR, "InitScan: ERROR from Hp35x0_init_scan\n"); + break; + case eHp4400c: case eHp4470c: + if (Hp44x0_cal_scanner(pHWParams,pParams) == SANE_TRUE){ + result = Hp44x0_init_scan(pHWParams,pParams,pDataPipe); + if (result) + DBG(DBG_ERR, "InitScan: OK\n"); + else + DBG(DBG_ERR, "InitScan: ERROR from Hp44x0_init_scan\n"); + } + break; + case eUnknownModel: + default: + DBG(DBG_ERR, "InitScan: ERROR: unknown model! (%d)\n", + (SANE_Int)pHWParams->ScannerModel); + result = SANE_FALSE; + break; + } + return result; +} + +/**************************************************************************** + _FinishScan + ================= + Finishes the scan. Makes the scanner head move back to the home position. +****************************************************************************/ +SANE_Bool _FinishScan( SANE_Handle h ) +{ + TScanner *s; + THWParams *pHWParams; + TScanParams *pParams; + SANE_Int iHandle; + SANE_Word size; + + s = (TScanner *)h; + + iHandle = s->HWParams.iXferHandle; + pHWParams = &s->HWParams; + pParams = &s->ScanParams; + + DBG(DBG_MSG,"Finish scan:\n"); + /* check, if the scanner moving */ + if (Hp_rts_is_moving(iHandle)){ + DBG(DBG_MSG,"Finish scan, scanner is moving, stop it!!!\n"); + Hp_rts_stop_moving(iHandle); + }; + usleep(100); + + /* clean the Scanner Buffer */ + do{ + /*if ( !*/(Hp_rts_data_ready(iHandle,&size));/*) return SANE_FALSE;*/ + if ( size > 0) + if ( !(Hp_rts_read_data(iHandle,size,s->DataPipe.pabXferBuf))) return SANE_FALSE; + } while (size != 0); + + DBG(DBG_MSG,"Finish scan, park to home\n"); + switch (pHWParams->ScannerModel) { + case eHp3500c: case eHp3530c: case eHp3570c: +#ifdef ENABLE_VI8920 + case eVi8920: +#endif + Hp35x0c_rewind(pHWParams); + break; + case eHp4400c: case eHp4470c: + Hp44x0_park_to_home(pHWParams,pParams); + break; + default: + DBG(DBG_ERR, "FinishScan: ERROR: unknown model! (%d) %s\n", + (SANE_Int)pHWParams->ScannerModel, ScannerModels[(SANE_Int)pHWParams->ScannerModel].pszName); + return SANE_FALSE; + } + return SANE_TRUE; +} + + +/****************************************************************************/ +static SANE_Int +_max_string_size (const SANE_String_Const strings[]) +/****************************************************************************/ +{ + SANE_Int size, max_size = 0; + SANE_Int i; + + for (i = 0; strings[i]; ++i) { + size = strlen (strings[i]) + 1; + if (size > max_size) + max_size = size; + } + return max_size; +} + + +/****************************************************************************/ +SANE_Status _Init_Interface(THWParams *pHWParams, TScanParams *pParams) +/****************************************************************************/ +{ + + DBG(DBG_SCAN, "Init_Interface....\n"); + /* autodetect some hardware properties */ + if (Hp_rts_ProbeRegisters(pHWParams) != SANE_STATUS_GOOD) { + DBG(DBG_ERR, "Init_Interface: Hp_rts_ProbeRegisters failed!\n"); + return SANE_STATUS_IO_ERROR; + } + /* default HW params */ + pHWParams->iTopLeftX = 0; + pHWParams->iTopLeftY = 3; + pHWParams->iReversedHead = SANE_FALSE; + DBG(DBG_MSG, "Init_Interface: Use scanner (%d) %s\n", + (SANE_Int)pHWParams->ScannerModel,ScannerModels[pHWParams->ScannerModel].pszName); + switch (pHWParams->ScannerModel) { + + case eHp3500c: case eHp3530c: +#ifdef ENABLE_VI8920 + case eVi8920: +#endif + pHWParams->iTopLeftX = 7; +#ifndef DEBUG_HP3500 + Hp35x0c_init_power_on(pHWParams); +#else + if ( !(Hp44x0_Wakeup(pHWParams, pParams))) return SANE_STATUS_IO_ERROR; + if ( !(Hp44x0_cal_scanner(pHWParams, pParams))) return SANE_STATUS_IO_ERROR; +#endif + break; + case eHp4400c: case eHp4470c: + pHWParams->iTopLeftX = 7; + if ( !(Hp44x0_Wakeup(pHWParams, pParams))) return SANE_STATUS_IO_ERROR; + if ( !(Hp44x0_cal_scanner(pHWParams, pParams))) return SANE_STATUS_IO_ERROR; + if ( !(Hp44x0_park_to_home(pHWParams, pParams))) return SANE_STATUS_IO_ERROR; + break; + case eUnknownModel: + default: + DBG(DBG_ERR, "Init_Interface: ERROR: internal error! (%d)\n", + (SANE_Int)pHWParams->ScannerModel); + return SANE_STATUS_UNSUPPORTED; + } + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +void _Close_Interface(THWParams *pHWParams) +/****************************************************************************/ +{ + DBG(DBG_MSG, "Close_Interface: ..\n"); + switch (pHWParams->ScannerModel) { + case eHp3500c: case eHp3530c: +#ifdef ENABLE_VI8920 + case eVi8920: +#endif + Hp35x0c_turn_off_lamp(pHWParams->iXferHandle); + Hp35x0c_set_powersave_mode(pHWParams->iXferHandle,1); + break; + case eHp4400c: case eHp4470c: + /* turn of scanner lamp */ + Hp44x0_SetLamp(pHWParams->iXferHandle, SANE_FALSE); + Hp44x0_Down(pHWParams->iXferHandle); + break; + case eUnknownModel: + default: + DBG(DBG_ERR, "Close_Interface: ERROR: internal error! (%d)\n", (SANE_Int)pHWParams->ScannerModel); + return; + } + Hp_rts_XferExit(pHWParams->iXferHandle); + pHWParams->iXferHandle = 0; +} + +/****************************************************************************/ +static void SANE_InitOptions(TScanner *s) +/****************************************************************************/ +{ + SANE_Int i, Model; + SANE_Option_Descriptor *pDesc; + TOptionValue *pVal; + + Model = s->HWParams.ScannerModel; + DBG(DBG_SCAN, "SANE_InitOptions: Use model # %d\n", Model); + /* set a neutral gamma */ + if( s->aGammaTableR == NULL ) /* Not yet allocated */ + { + s->aGammaTableR = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) ); + s->aGammaTableG = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) ); + s->aGammaTableB = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) ); + + for (i = 0; i < NUM_GAMMA_ENTRIES; i++) { + s->aGammaTableR[i] = i; + s->aGammaTableG[i] = i; + s->aGammaTableB[i] = i; + } + } + + if ( (Model==eHp4400c) || (Model==eHp4470c) ){ + DBG(DBG_MSG,"SANE_InitOptions: use HP4x00 mode\n"); +/* mode_list[0]="B/W";*/ + mode_list[0]="Gray"; + mode_list[1]=NULL; + if (OPT_COLOR){ + mode_list[1]="Color"; + mode_list[2]=NULL; + } + }else + { /* hp35x0 */ + DBG(DBG_MSG,"SANE_InitOptions: use HP35x0 mode\n"); + /* mode_list[0]="B/W";*/ + mode_list[0]="Gray"; /**/ + mode_list[1]=NULL; + if (OPT_COLOR){ + mode_list[1]="Color"; + mode_list[2]=NULL; + } + } + + ccd_list[0]="CCDType 0"; + ccd_list[1]="CCDType 1"; + ccd_list[2]=NULL; + + scan_option_list[0]="bed light"; + scan_option_list[1]="XPA"; + scan_option_list[2]=NULL; + + for (i = optCount; i < optLast; i++) { + + pDesc = &s->aOptions[i]; + pVal = &s->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 optCount: + pDesc->title = SANE_TITLE_NUM_OPTIONS; + pDesc->desc = SANE_DESC_NUM_OPTIONS; + pDesc->cap = SANE_CAP_SOFT_DETECT; + pVal->w = (SANE_Word)optLast; + break; + + case optGroupGeometry: + pDesc->title = "Geometry"; + pDesc->type = SANE_TYPE_GROUP; + pDesc->size = 0; + break; + + case optTLX: + 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->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pDesc->constraint.range = &rangeXmm; + pVal->w = rangeXmm.min; + break; + + case optTLY: + 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 = &rangeYmm; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = rangeYmm.min; + break; + + case optBRX: + 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 = &rangeXmm; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = rangeXmm.max; + break; + + case optBRY: + 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 = &rangeYmm; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = rangeYmm.max; + break; + + case optDPI: + 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->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + if ((Model==eHp4400c) || (Model==eHp4470c) ){ + if (OPT_T_RES) { + DBG(DBG_MSG,"SANE_InitOptions: use HP4x00 TEST mode \n"); + pDesc->constraint.word_list = Hp44x0c_setResolutions_t; + pVal->w = Hp44x0c_setResolutions_t[1]; + } else { + DBG(DBG_MSG,"SANE_InitOptions: use HP4x00 normal mode \n"); + pDesc->constraint.word_list = Hp44x0c_setResolutions; + pVal->w = Hp44x0c_setResolutions[1]; + } + }else{ /* it's a HP35xx */ + if (OPT_T_RES) { + DBG(DBG_MSG,"SANE_InitOptions: use HP35x0 TEST mode \n"); + pDesc->constraint.word_list = Hp35x0c_setResolutions_t; + pVal->w = Hp35x0c_setResolutions_t[1]; + } else { + DBG(DBG_MSG,"SANE_InitOptions: use HP35x0 normal mode \n"); + pDesc->constraint.word_list = Hp35x0c_setResolutions; + pVal->w = Hp35x0c_setResolutions[1]; + } + } + break; + + case optGroupImage: + pDesc->title = SANE_I18N("Image"); + pDesc->type = SANE_TYPE_GROUP; + pDesc->size = 0; + break; + + case optGammaTableRed: + pDesc->name = SANE_NAME_GAMMA_VECTOR_R; + pDesc->title = SANE_TITLE_GAMMA_VECTOR_R; + pDesc->desc = SANE_DESC_GAMMA_VECTOR_R; + pDesc->size = NUM_GAMMA_ENTRIES * sizeof( SANE_Int ); + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeGammaTable; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->wa = s->aGammaTableR; + break; + + case optGammaTableGreen: + pDesc->name = SANE_NAME_GAMMA_VECTOR_G; + pDesc->title = SANE_TITLE_GAMMA_VECTOR_G; + pDesc->desc = SANE_DESC_GAMMA_VECTOR_G; + pDesc->size = NUM_GAMMA_ENTRIES * sizeof( SANE_Int ); + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeGammaTable; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->wa = s->aGammaTableG; + break; + + case optGammaTableBlue: + pDesc->name = SANE_NAME_GAMMA_VECTOR_B; + pDesc->title = SANE_TITLE_GAMMA_VECTOR_B; + pDesc->desc = SANE_DESC_GAMMA_VECTOR_B; + pDesc->size = NUM_GAMMA_ENTRIES * sizeof( SANE_Int ); + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeGammaTable; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->wa = s->aGammaTableB; + break; + + case optGroupMisc: + pDesc->title = SANE_I18N ("Miscellaneous"); + pDesc->type = SANE_TYPE_GROUP; + pDesc->size = 0; + break; + + case optBrightness: + pDesc->name = SANE_NAME_BRIGHTNESS; + pDesc->title = SANE_TITLE_BRIGHTNESS; + pDesc->desc = SANE_DESC_BRIGHTNESS; + pDesc->type = SANE_TYPE_INT; + pDesc->size = sizeof(SANE_Int); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeBrightness; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = 10; + break; + + case OPT_MODE: + pDesc->name = SANE_NAME_SCAN_MODE; + pDesc->title = SANE_TITLE_SCAN_MODE; + pDesc->desc = SANE_DESC_SCAN_MODE; + pDesc->type = SANE_TYPE_STRING; + pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; + pDesc->size = _max_string_size (mode_list); + pDesc->constraint.string_list = mode_list; + pVal->s = strdup (mode_list[0]); + pDesc->cap = ~SANE_CAP_INACTIVE; + break; + + case optXPDA: + pDesc->name = SANE_NAME_SCAN_SOURCE; + pDesc->title = SANE_TITLE_SCAN_SOURCE; + pDesc->desc = SANE_I18N("Switches the scaner source mode (normal/xPDA)."); + pDesc->type = SANE_TYPE_STRING; + pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; + pDesc->size = _max_string_size (scan_option_list); + pDesc->constraint.string_list = scan_option_list; + pVal->s = strdup (scan_option_list[0]); + if (Model == eHp4470c) + pDesc->cap = ~SANE_CAP_INACTIVE; + else + pDesc->cap = SANE_CAP_INACTIVE; + s->ScanParams.optXPA = SANE_FALSE; + break; + + case optCCD: + pDesc->name = SANE_NAME_SCAN_SOURCE; + pDesc->title = "CCD_Type"; + pDesc->desc = SANE_I18N("Switches the scaner CCD mode (0/1)."); + pDesc->type = SANE_TYPE_STRING; + pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; + pDesc->size = _max_string_size (ccd_list); + pDesc->constraint.string_list = ccd_list; + pVal->s = strdup (ccd_list[0]); + if ((Model==eHp4400c) || (Model==eHp4470c) ){ + if (OPT_CCD){ + pDesc->cap = ~SANE_CAP_INACTIVE; + s->ScanParams.oCCD_Type = 0; + } else + pDesc->cap = SANE_CAP_INACTIVE; + }else + pDesc->cap = SANE_CAP_INACTIVE; + break; + + case optGainR: + pDesc->name = "optGainR"; + pDesc->title = "optGainR"; + pDesc->desc = SANE_I18N("optGainR"); + pDesc->type = SANE_TYPE_INT; + pDesc->size = sizeof(SANE_Int); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeBrightness; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = 0x0a; + break; + case optGainG: + pDesc->name = "optGainG"; + pDesc->title = "optGainG"; + pDesc->desc = SANE_I18N("optGainG"); + pDesc->type = SANE_TYPE_INT; + pDesc->size = sizeof(SANE_Int); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeBrightness; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = 0x0a; + break; + case optGainB: + pDesc->name = "optGainB"; + pDesc->title = "optGainB"; + pDesc->desc = SANE_I18N("optGainB"); + pDesc->type = SANE_TYPE_INT; + pDesc->size = sizeof(SANE_Int); + pDesc->unit = SANE_UNIT_NONE; + pDesc->constraint_type = SANE_CONSTRAINT_RANGE; + pDesc->constraint.range = &rangeBrightness; + pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + pVal->w = 0x0a; + break; + + default: + DBG(DBG_ERR, "InitOptions: Uninitialised option %d\n", i); + break; + } + } +} + +/****************************************************************************/ +SANE_Status +sane_init(SANE_Int *piVersion, SANE_Auth_Callback pfnAuth) +/****************************************************************************/ +{ + SANE_Char line[PATH_MAX]; + SANE_Char *word; + SANE_String_Const cp; + SANE_Int linenumber; + FILE *conf_fp; + TScanner *s; + +/* prevent compiler from complaing about unused parameters */ + pfnAuth = pfnAuth; + s = malloc (sizeof (TScanner)); + if (!s) + { + DBG (DBG_MSG,"sane_init : malloc failed\n"); + return SANE_STATUS_NO_MEM; + } + +#ifndef STANDALONE + DBG_INIT(); + DBG (DBG_MSG, "SANE HP_RTS88XX USB backend version %d.%d build %d from %s\n", V_MAJOR, + V_MINOR, BUILD, PACKAGE_STRING); +#else + DBG (DBG_MSG, "SANE HP_RTS88XX USB backend version %d.%d build %d from \n", V_MAJOR, + V_MINOR, BUILD); +#endif + + iNumSaneDev = 0; + _pFirstSaneDev = 0; + + /* initialise scanner object */ + DBG(DBG_OPT, "Init_Interface: call Hp_rts_XferInit\n"); + if ( Hp_rts_XferInit() != SANE_TRUE) { + DBG(DBG_ERR, "Init_Interface: Hp_rts_XferInit failed\n"); + /* free scanner object memory */ + free ((void *) s); + return SANE_STATUS_IO_ERROR; + } + /* free scanner object memory */ + free ((void *) s); + DBG(DBG_OPT, "sane_init: call sanei_config_open\n"); + conf_fp = sanei_config_open (HP_RTS_CONFIG_FILE); + if (conf_fp) { + linenumber = 0; + DBG (DBG_OPT, "sane_init: reading config file '%s'\n",HP_RTS_CONFIG_FILE); + while (sanei_config_read (line, sizeof (line), conf_fp)) { + word = 0; + linenumber++; + cp = sanei_config_get_string (line, &word); + /* Discards white lines and comments*/ + if (!word || cp == line) { + if (word) + free (word); + continue; + } + + if (word[0] == '#') { + free (word); + continue; + } + if (strcmp (word, "option") == 0) { + free (word); + word = 0; + cp = sanei_config_get_string (cp, &word); + if (!word) { + DBG (DBG_ERR, + "sane_init: config file line %d: missing quotation mark?\n", + linenumber); + continue; + } + if (strcmp (word, "CCD0") == 0) { + DBG(DBG_OPT,"sane_init: Find option '%s'\n",line); + free (word); + word = 0; + OPT_CCD = SANE_FALSE; + s->ScanParams.oCCD_Type = 0; + continue; + } + if (strcmp (word, "CCD1") == 0) { + DBG(DBG_OPT,"sane_init: Find option '%s'\n",line); + free (word); + word = 0; + OPT_CCD = SANE_FALSE; + s->ScanParams.oCCD_Type = 1; + continue; + } + if (strcmp (word, "ENABLE_COLOR") == 0) { + DBG(DBG_OPT,"sane_init: Find option '%s'\n",line); + free (word); + word = 0; + OPT_COLOR = SANE_TRUE; + continue; + } + if (strcmp (word, "ENABLE_T_RES") == 0) { + DBG(DBG_OPT,"sane_init: Find option '%s'\n",line); + free (word); + word = 0; + OPT_T_RES = SANE_TRUE; + continue; + } + } + } /*while*/ + fclose(conf_fp); + } + else { + DBG (DBG_ERR, "sane_init: Unable to read config file \"%s\": %s\n", + HP_RTS_CONFIG_FILE,strerror(errno)); + DBG (DBG_OPT, "sane_init: Using default built-in values\n"); + } + if (piVersion != NULL) { + *piVersion = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD); + } + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +void +sane_exit(void) +/****************************************************************************/ +{ + TDevListEntry *pDev, *pNext; + + DBG(DBG_MSG, "sane_exit\n"); + + /* free device list memory */ + if (_pSaneDevList) + { + for (pDev = _pFirstSaneDev; pDev; pDev = pNext) + { + pNext = pDev->pNext; + free ((void *) pDev->dev.name); + free (pDev); + } + _pFirstSaneDev = 0; + free (_pSaneDevList); + _pSaneDevList = 0; + } +} + +/****************************************************************************/ +SANE_Status +sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) +/****************************************************************************/ +{ + TDevListEntry *pDev; + SANE_Int i; +#if 0 + DBG (DBG_MSG, "sane_get_devices\n"); +#endif + local_only = local_only; + + if (_pSaneDevList) + { + free (_pSaneDevList); + } + + _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1)); + if (!_pSaneDevList) + { + DBG (DBG_MSG, "sane_get_devices : no mem\n"); + return SANE_STATUS_NO_MEM; + } + i = 0; + for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext) + { + _pSaneDevList[i++] = &pDev->dev; + DBG (DBG_MSG, "sane_get_devices: name %s\n",pDev->dev.name); + } + _pSaneDevList[i++] = 0; /* last entry is 0 */ + + *device_list = _pSaneDevList; + + return SANE_STATUS_GOOD; +} + +/****************************************************************************/ +SANE_Status +sane_open(SANE_String_Const name, SANE_Handle *h) +/****************************************************************************/ +{ + TScanner *s; + + DBG(DBG_MSG, "sane_open: %s\n", name); + + s = malloc (sizeof (TScanner)); + if (!s) + { + DBG (DBG_MSG,"sane_open : malloc failed\n"); + return SANE_STATUS_NO_MEM; + } + *h = s; + + s->HWParams.iXferHandle = Hp_rts_XferOpen (name,(EScannerModel *) &s->HWParams.ScannerModel); +#if 0 + DBG (DBG_MSG, "sane_open: s->HWParams.ScannerModel = %d\n",s->HWParams.ScannerModel); +#endif + if (s->HWParams.iXferHandle < 0) + { + DBG (DBG_ERR, "sane_open: Hp_rts_XferOpen failed for '%s'\n", name); + return SANE_STATUS_DEVICE_BUSY; + } + + /* initialise scanner object */ +#if 1 /* only for test, normaly 1 */ + s->HWParams.lamp_warm = SANE_FALSE; +#else + s->HWParams.lamp_warm = SANE_TRUE; /*only for test */ +#endif + s->fScanning = SANE_FALSE; + s->fCanceled = SANE_FALSE; + + s->aGammaTableR = NULL; + s->aGammaTableG = NULL; + s->aGammaTableB = NULL; + + if (_Init_Interface(&s->HWParams,&s->ScanParams) == SANE_STATUS_GOOD) { + SANE_InitOptions((TScanner *)s); + } + else{ + DBG (DBG_ERR, "sane_open: _Init_Interface failed\n"); + s->HWParams.iXferHandle = -1; + return SANE_STATUS_IO_ERROR; + } + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +void +sane_close(SANE_Handle h) +/****************************************************************************/ +{ + TScanner *s; + + DBG(DBG_MSG, "sane_close\n"); + s = (TScanner *)h; + /* close scanner */ + _Close_Interface(&s->HWParams); + #ifdef DEBUG_FILE + if ( s->ScanParams.DebugOpen ){ + fclose(s->ScanParams.FD_r); + s->ScanParams.DebugOpen = SANE_FALSE; + } + #endif + if ( s->aGammaTableR != NULL ){ + free(s->aGammaTableR); + s->aGammaTableR = NULL;} + if ( s->aGammaTableG != NULL ){ + free(s->aGammaTableG); + s->aGammaTableG = NULL;} + if ( s->aGammaTableB != NULL ){ + free(s->aGammaTableB); + s->aGammaTableB = NULL;} + + /* free scanner object memory */ + free ((void *) s); +} + + +/****************************************************************************/ +const SANE_Option_Descriptor * +sane_get_option_descriptor(SANE_Handle h, SANE_Int n) +/****************************************************************************/ +{ + TScanner *s; + + DBG(DBG_OPT, "sane_get_option_descriptor %d\n", n); + if ((n < optCount) || (n >= optLast)) { + return NULL; + } + s = (TScanner *)h; + return &s->aOptions[n]; +} + + +/****************************************************************************/ +SANE_Status +sane_control_option(SANE_Handle h, SANE_Int option, SANE_Action Action, void *pVal, + SANE_Int *pInfo) +/****************************************************************************/ +{ + TScanner *s; + SANE_Int info; + SANE_Status status; + + DBG(DBG_OPT,"sane_control_option: option %d, action %d\n", option, Action); + s = (TScanner *)h; + info = 0; + + if (option < 0 || option >= optLast) + return SANE_STATUS_INVAL; + + if (pInfo != NULL) + *pInfo = 0; + + /*************************************************/ + switch (Action) { + /*************************************************/ + case SANE_ACTION_GET_VALUE: + switch (option) { + + /* Get options of type SANE_Word */ + case optCount: case optDPI: + case optTLX: case optTLY: case optBRX: case optBRY: + case optBrightness: case optGainR: case optGainG: case optGainB: + DBG(DBG_OPT,"sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", option, + (SANE_Int)s->aValues[option].w); + *(SANE_Word*)pVal = s->aValues[option].w; + break; + + /* Get options of type SANE_Word array */ + case optGammaTableRed: case optGammaTableGreen: case optGammaTableBlue: + DBG(DBG_OPT, "Reading gamma table\n"); + memcpy (pVal, s->aValues[option].wa, s->aOptions[option].size); + break; + + /* Get options of type SANE_TYPE STRING */ + case OPT_MODE: case optXPDA: case optCCD: + DBG(DBG_OPT,"sane_control_option: SANE_ACTION_GET_VALUE %s\n",s->aValues[option].s); + status = sanei_constrain_value (s->aOptions + option, s->aValues[option].s, + (SANE_Int *)info); + strcpy ((char *)pVal, s->aValues[option].s); + return SANE_STATUS_GOOD; + break; + + default: ; + DBG(DBG_ERR,"SANE_ACTION_GET_VALUE: Invalid option (%d)\n", option); + break; + } + break; + case SANE_ACTION_SET_VALUE: + /* no changes while in mid-pass! */ + if (s->fScanning){ + DBG(DBG_ERR,"sane_control_option: SANE_ACTION_SET_VALUE not allowed during scan\n"); + return SANE_STATUS_DEVICE_BUSY; + } + status = sanei_constrain_value (s->aOptions + option, pVal, pInfo); + if (status != SANE_STATUS_GOOD) + return status; + switch (option) { + + /* Set options of type SANE_Word */ + case optCount: + return SANE_STATUS_INVAL; + break; + + case optDPI: case optTLX: case optTLY: case optBRX: case optBRY: + case optBrightness: case optGainR: case optGainG: case optGainB: + DBG(DBG_OPT,"sane_control_option: SANE_ACTION_SET_VALUE %d to %d\n", + option,*(SANE_Word *) pVal); + info |= SANE_INFO_RELOAD_PARAMS; + s->aValues[option].w = *(SANE_Word *) pVal; + break; + + /* Get options of type SANE_Word array */ + case optGammaTableRed: case optGammaTableGreen: case optGammaTableBlue: + DBG(DBG_OPT, "Writing gamma table\n"); + memcpy (s->aValues[option].wa, pVal, s->aOptions[option].size); + break; + + /* Set options of type SANE_TYPE_STRING */ + case OPT_MODE: case optXPDA: case optCCD: + DBG(DBG_OPT,"sane_control_option: SANE_ACTION_SET_String %d to %s\n", + option,(char *)pVal); + if (s->aValues[option].s) + free (s->aValues[option].s); + s->aValues[option].s = strdup (pVal); + if (info) + info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; + break; + + default: ; + DBG(DBG_ERR,"SANE_ACTION_SET_VALUE: Invalid option (%d)\n", option); + return SANE_STATUS_INVAL; + } /* switch option */ + if (pInfo != NULL) { + *pInfo = info; + } + break; /*case SANE_ACTION_SET_VALUE*/ + case SANE_ACTION_SET_AUTO: + return SANE_STATUS_UNSUPPORTED; + default: ; + DBG(DBG_ERR,"sane_control_option: Invalid action (%d)\n", Action); + return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +SANE_Status +sane_get_parameters(SANE_Handle h, SANE_Parameters *p) +/****************************************************************************/ +{ + TScanner *s; + SANE_String val; + + s = (TScanner *)h; + val = s->aValues[OPT_MODE].s; + + /* first do some checks */ + if (s->aValues[optTLX].w >= s->aValues[optBRX].w) { + DBG(DBG_ERR,"sane_get_parameters: TLX should be smaller than BRX\n"); + s->aValues[optTLX].w = s->aValues[optBRX].w; /* new 17.06.03 JoHu */ + /* return SANE_STATUS_INVAL; / proper error code? */ + } + if (s->aValues[optTLY].w >= s->aValues[optBRY].w) { + DBG(DBG_ERR,"sane_get_parameters: TLY should be smaller than BRY\n"); + s->aValues[optTLY].w = s->aValues[optBRY].w; /* new 17.06.03 JoHu */ + /* return SANE_STATUS_INVAL; / proper error code? */ + } + + /* return the data */ + p->last_frame = SANE_TRUE; + s->ScanParams.brightness = s->aValues[optBrightness].w; + s->ScanParams.GainR = s->aValues[optGainR].w; + s->ScanParams.GainG = s->aValues[optGainG].w; + s->ScanParams.GainB = s->aValues[optGainB].w; + p->depth = 8; + + if (!strcmp (s->aValues[optXPDA].s, "XPA")){ + s->ScanParams.optXPA = SANE_TRUE; + DBG(DBG_MSG,"sane_get_parameters: set XPA to TRUE\n"); + }else{ + s->ScanParams.optXPA = SANE_FALSE; + DBG(DBG_MSG,"sane_get_parameters: set XPA to FALSE\n"); + } + + if (s->aOptions[optCCD].cap != SANE_CAP_INACTIVE){ + if (!strcmp (s->aValues[optCCD].s, "CCDType 0")){ + s->ScanParams.oCCD_Type = 0; + DBG(DBG_MSG,"sane_get_parameters: set CCD to 0\n"); + } + if (!strcmp (s->aValues[optCCD].s, "CCDType 1")){ + s->ScanParams.oCCD_Type = 1; + DBG(DBG_MSG,"sane_get_parameters: set CCD to 1\n"); + } + } + + if (!strcmp (val, "Color")){ + s->ScanParams.mode = COLOR; + DBG(DBG_MSG,"sane_get_parameters: switch to color 24 bit!\n"); + p->format = SANE_FRAME_RGB; + }else{ + if (!strcmp (val, "B/W")){ + DBG(DBG_MSG,"sane_get_parameters: switch to B/W 8 bit\n"); + s->ScanParams.mode = BLACK_WHITE; + p->format = SANE_FRAME_GRAY; + p->depth = 1; + } else { + DBG(DBG_MSG,"sane_get_parameters: switch to gray 8 bit\n"); + s->ScanParams.mode = GRAY; + p->format = SANE_FRAME_GRAY; + } + } + p->lines = MM_TO_PIXEL(s->aValues[optBRY].w - s->aValues[optTLY].w, + s->aValues[optDPI].w); + p->pixels_per_line = MM_TO_PIXEL(s->aValues[optBRX].w - s->aValues[optTLX].w, + s->aValues[optDPI].w); + p->bytes_per_line = p->pixels_per_line; + /* fill in the scanparams using the option values */ + s->ScanParams.iLinesLeft = p->lines; + s->ScanParams.iDpi = s->aValues[optDPI].w; + s->ScanParams.iLpi = s->aValues[optDPI].w; + s->ScanParams.iWidth = p->pixels_per_line; + s->ScanParams.iLenght = p->lines; + s->ScanParams.fCalib = SANE_FALSE; + + switch (s->ScanParams.iDpi) { + case 150: + s->ScanParams.iY = + MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, 150); + s->ScanParams.iX = + MM_TO_PIXEL(s->aValues[optTLX].w + s->HWParams.iTopLeftX, 150); + break; + case 300: + s->ScanParams.iY = + MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, 300); + s->ScanParams.iX = + MM_TO_PIXEL(s->aValues[optTLX].w + s->HWParams.iTopLeftX, 300); + break; + case 600: + s->ScanParams.iY = + MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, 600); + s->ScanParams.iX = + MM_TO_PIXEL(s->aValues[optTLX].w + (s->HWParams.iTopLeftX / 2), 600); + break; + default: + DBG(DBG_MSG,"sane_get_parameters: invalid resolution !"); + return SANE_STATUS_INVAL; + } + if (s->ScanParams.mode == COLOR) + p->bytes_per_line = p->bytes_per_line * 3; + + /* init data pipe */ + s->DataPipe.iBytesLeft = 0; + s->DataPipe.iScanned = 0; + s->DataPipe.iLinesLeft = p->lines; + s->DataPipe.iLinesInCircBuf = 1; + DBG(DBG_MSG, + "sane_get_parameters: lpi %3d; dpi %3d; p->lines %3d; p->pixels_per_line %3d; p->bytes_per_line %3d; Mode %x\n", + s->ScanParams.iLpi,s->ScanParams.iDpi,p->lines, + p->pixels_per_line,p->bytes_per_line, + s->ScanParams.mode); + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +SANE_Status +sane_start(SANE_Handle h) +/****************************************************************************/ +{ + TScanner *s; + SANE_Parameters par; + SANE_Int pabLineBufSize; + SANE_Status State; + + DBG(DBG_MSG,"sane_start\n"); + s = (TScanner *)h; + + if (sane_get_parameters(h, &par) != SANE_STATUS_GOOD) { + DBG(DBG_MSG," sane_get_parameters,invalid scan parameters\n"); + return SANE_STATUS_INVAL; + } + #ifdef DEBUG_FILE + s->ScanParams.DebugOpen = SANE_FALSE; + s->ScanParams.DebugSeek0 = SANE_FALSE; + #endif + + DBG(DBG_MSG,"sane_start: optDPI=%d optTLY=%dmm, optTLX=%dmm, optBRX=%dmm, optBRY=%dmm.\n", + s->aValues[optDPI].w, + s->aValues[optTLY].w, + s->aValues[optTLX].w, + s->aValues[optBRX].w, + s->aValues[optBRY].w); + + DBG(DBG_MSG,"sane_start: iDpi=%d iLpi=%d iY=%dpix. iX=%dpix. iWidth=%dpix iLenght=%dpix. mode=0x%x brightness=0x%x\n", + s->ScanParams.iDpi, /* horizontal resolution */ + s->ScanParams.iLpi, /* vertical resolution */ + s->ScanParams.iY, /* in HW coordsane_readinates */ + s->ScanParams.iX, /* in HW coordinates */ + s->ScanParams.iWidth, /* pixels per line*/ + s->ScanParams.iLenght, /* Pixel lines */ + s->ScanParams.mode, + s->ScanParams.brightness); + + /* hack */ + pabLineBufSize = par.bytes_per_line * 3; + DBG(DBG_MSG,"sane_start: pabLineBufSize=%d\n",pabLineBufSize); + s->DataPipe.pabLineBuf = (SANE_Byte *)malloc(pabLineBufSize); + + s->DataPipe.iZeroLines = 0; + + /* copy gamma table */ + Hp_rts_WriteGammaCalibTable (s->HWParams.iXferHandle, s->aGammaTableR, + s->aGammaTableG, s->aGammaTableB); + + /* prepare and start the actual scan */ + State = Hp_rts_CircBufferInit( h, &s->DataPipe, par.bytes_per_line, + s->ScanParams.iWidth, s->ScanParams.mode); + if ( State == SANE_STATUS_GOOD ){ + State = _InitScan(&s->ScanParams, &s->HWParams, &s->DataPipe); + if ( !State ) { +/* if ( State != SANE_STATUS_GOOD ) {*/ + DBG(DBG_MSG,"sane_start: InitScan, invalid scan parameters\n"); + return SANE_STATUS_IO_ERROR; + } + s->fScanning = SANE_TRUE; + return SANE_STATUS_GOOD; + } + s->fScanning = SANE_FALSE; + return State; +} + + +/****************************************************************************/ +SANE_Status +sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len) +/* buf have the lenght maxlen; len returns the lenght of the retuned bytes */ +/****************************************************************************/ +{ + TScanner *s; + TDataPipe *p; + + s = (TScanner *)h; + + DBG(DBG_SCAN,"sane_read: starts here\n"); + /* sane_read only allowed after sane_start */ + if (!s->fScanning) { + DBG(DBG_ERR," sane_read: sane_read only allowed after sane_start\n"); + return SANE_STATUS_EOF; + } + + p = &s->DataPipe; + + /* anything left to read? */ + if ((s->ScanParams.iLinesLeft == 0) && (p->iBytesLeft == 0)) { + DBG(DBG_SCAN," sane_read: end of scan\n"); + _FinishScan(s); + *len = 0; + s->fScanning = SANE_FALSE; + Hp_rts_CircBufferExit( h ); + if (p->pabLineBuf != NULL){ + free(p->pabLineBuf); + p->pabLineBuf = NULL; + } + #ifdef DEBUG_FILE + if ( s->ScanParams.DebugOpen ){ + fclose(s->ScanParams.FD_r); + s->ScanParams.DebugOpen = SANE_FALSE; + } + #endif + return SANE_STATUS_EOF; + } + + /* time to read the next line? */ + *len = 0; + if (p->iBytesLeft == 0) { + if (Hp_rts_CircBufferGetLine(h, p, p->pabLineBuf,s->ScanParams.mode)){ + p->iBytesLeft = p->iBytesPerLine; + s->ScanParams.iLinesLeft--; + DBG(DBG_SCAN," sane_read: p->iBytesLeft=%3d s->ScanParams.iLinesLeft=%3d\n", + p->iBytesLeft,s->ScanParams.iLinesLeft); + }else + { /* no data read from the pipe ! */ + s->DataPipe.iZeroLines = s->DataPipe.iZeroLines +1; + DBG(DBG_SCAN," sane_read: no bytes read from CircBuffer\n"); + if (s->DataPipe.iZeroLines <10){ + *len = 0; + return SANE_STATUS_GOOD; + }else /* time over */ + { + *len = 0; + return SANE_STATUS_IO_ERROR; + } + } + /* copy (part of) a line */ + *len = MIN(maxlen, p->iBytesLeft); + memcpy(buf, &p->pabLineBuf[p->iBytesPerLine - p->iBytesLeft], *len); + p->iBytesLeft -= *len; + } + + DBG(DBG_SCAN," sane_read: read %d bytes; maxlen = %d\n", *len,maxlen); + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +void +sane_cancel(SANE_Handle h) +/****************************************************************************/ +{ + TScanner *s; + + DBG(DBG_MSG,"sane_cancel\n"); + s = (TScanner *)h; + + /* Make sure the scanner head returns home */ + _FinishScan(s); + Hp_rts_CircBufferExit( h ); + if (s->DataPipe.pabLineBuf != NULL){ + free(s->DataPipe.pabLineBuf); + s->DataPipe.pabLineBuf = NULL; + } + #ifdef DEBUG_FILE + if ( s->ScanParams.DebugOpen ){ + fclose(s->ScanParams.FD_r); + s->ScanParams.DebugOpen = SANE_FALSE; + } + #endif + s->fCanceled = SANE_TRUE; + s->fScanning = SANE_FALSE; +} + + +/****************************************************************************/ +SANE_Status +sane_set_io_mode(SANE_Handle h, SANE_Bool m) +/****************************************************************************/ +{ + DBG(DBG_MSG, "sane_set_io_mode: %s\n", m ? "non-blocking" : "blocking"); + /* prevent compiler from complaining about unused parameters */ + h = h; + + if (m) { + return SANE_STATUS_UNSUPPORTED; + } + return SANE_STATUS_GOOD; +} + + +/****************************************************************************/ +SANE_Status +sane_get_select_fd(SANE_Handle h, SANE_Int *fd) +/****************************************************************************/ +{ + DBG(DBG_MSG, "sane_select_fd\n"); + /* prevent compiler from complaining about unused parameters */ + h = h; + fd = fd; + return SANE_STATUS_UNSUPPORTED; +} + + +#ifdef STANDALONE +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +typedef void (*rts8801_callback)( void *param, + unsigned bytes, + void *data); + +/****************************************************************************/ +void +main_UsageError() +/****************************************************************************/ +{ + fprintf(stderr, "SANE HP_RTS88XX x y width height resolution filename\n" + " x, y, width, height: in pixels\n" + " resolution: 1200/600/300/200/150/75\n"); + exit(1); +} + + +/****************************************************************************/ +int +main (int argc, char *argv[]) +/****************************************************************************/ +{ + TScanner *s; + /*SANE_String_Const name;*/ + SANE_Int piVersion; + unsigned x, y, w, h; + SANE_Word resolution; + char const * filename; + FILE *fp; + int result = 1; + int multiplier; + /*int depth; + SANE_Int i;*/ + SANE_Auth_Callback pfnAuth; + const SANE_Device **device_list; + SANE_Bool local; + SANE_Handle device; + SANE_Status status; + SANE_Int num_dev_options; + SANE_Int info; + SANE_Byte *buf; + /*SANE_Int maxlen;*/ + SANE_Int len; + + DBG (DBG_MSG, "SANE HP_RTS88XX USB test version\n"); + + if (argc != 7) + main_UsageError(); + + x = atoi(argv[1]); + y = atoi(argv[2]); + w = atoi(argv[3]); + h = atoi(argv[4]); + resolution = atoi(argv[5]); + filename = argv[6]; + + switch (resolution) + { + case 1200: + case 600: + case 400: + case 300: + case 200: + case 150: + case 100: + case 75: + case 50: + case 25: + break; + + default: + fprintf(stderr, "Invalid resolution: %s\n", argv[5]); + return 1; + } + + multiplier = 1200 / resolution; + if ((y + h) * multiplier > 16800) + { + fprintf(stderr, "Scan parameters take the image past the bottom of the scanner\n"); + return 1; + } + if ((x + w) * multiplier > 10451) + { + fprintf(stderr, "Scan parameters take the image past the right hand side of the scanner\n"); + return 1; + } + if (!x || !y || !w || !h) + { + fprintf(stderr, "None of the co-ordinates may be zero\n"); + return 1; + } + if (y * multiplier < 600) + { + fprintf(stderr, "Warning: at this resolution 'y' values under %d are in the pre-scan area\n", + 599 / multiplier + 1); + } + if (x * multiplier < 251) + { + fprintf(stderr, "Warning: at this resolution, 'x' values under %d are left of the scan area\n", + 250 / multiplier + 1); + } + + s = malloc (sizeof (TScanner)); + if (!s) + { + DBG (DBG_MSG,"main : malloc for s failed\n"); + return SANE_STATUS_NO_MEM; + } + buf = malloc (5000); + if (!buf) + { + DBG (DBG_MSG,"main : malloc buf failed\n"); + return SANE_STATUS_NO_MEM; + } + + if (sane_init(&piVersion,pfnAuth) != SANE_STATUS_GOOD) + { + fprintf(stderr, "Could not initialise scanner\n"); + /* free scanner object memory */ + free ((void *) s); + exit(1); + } + local = SANE_TRUE; + if (sane_get_devices (&device_list, local) != SANE_STATUS_GOOD) + { + fprintf(stderr, "Could not sane_get_devices\n"); + /* free scanner object memory */ + free ((void *) s); + exit(1); + } + + status = sane_open ("libusb:001:002", &device); + if (status != SANE_STATUS_GOOD) + { + fprintf(stderr, "Could not sane_open\n"); + /* free scanner object memory */ + free ((void *) s); + exit(1); + } + + /* Get the number of options. */ + status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE, &num_dev_options, 0); + if (status != SANE_STATUS_GOOD) + { + fprintf(stderr, "Could not read sane_control_option\n"); + /* free scanner object memory */ + free ((void *) s); + exit(1); + } + +/*SANE_Word: + case optDPI: case optTLX: case optTLY: case optBRX: case optBRY: + case optBrightness: case optGainR: case optGainG: case optGainB: +SANE_TYPE_STRING + case OPT_MODE: case optXPDA: case optCCD: +*/ + status = sane_control_option (device,optDPI, SANE_ACTION_SET_VALUE, + &resolution, &info); + status = sane_control_option (device,optTLX, SANE_ACTION_SET_VALUE, + &x, &info); + status = sane_control_option (device,optBRX, SANE_ACTION_SET_VALUE, + &w, &info); + status = sane_control_option (device,optTLY, SANE_ACTION_SET_VALUE, + &y, &info); + status = sane_control_option (device,optBRY, SANE_ACTION_SET_VALUE, + &h, &info); +#if 0 + free ((void *) s); + exit(1); +#endif + s = (TScanner *)device; + + /* TScanParams */ + s->ScanParams.brightness = 10; + s->ScanParams.mode = 1; /* B/W = 0; grayscale = 1 color = 2 */ + s->ScanParams.optXPA = 0; /* 0=normal; 1 = XPA */ + s->ScanParams.oCCD_Type = 0; /* 0/1 */ + + fprintf(stdout, "Will open file %s\n",filename); + fp = fopen(filename, "w"); + + if (fp) + { + fprintf(fp, "P6\n%d %d\n255\n", w, h); + + switch (s->HWParams.ScannerModel) + { + case eHp3500c: case eHp3530c: case eHp3570c: + if (Hp35x0c_init_scan(&s->HWParams, &s->ScanParams, &s->DataPipe)) + ; + else result = 1; + break; + + case eHp4400c: case eHp4470c: + if (Hp44x0_init_scan(&s->HWParams, &s->ScanParams, &s->DataPipe)) + { + if (Hp44x0_start_scan(&s->HWParams, &s->ScanParams, &s->DataPipe)) + { + s->fScanning = SANE_TRUE; + } + } /* if */ + + break; + default: + fprintf(stderr, "Wrong scanner model\n"); + result = 1; + } + } + else + { + perror(filename); + } + + if (s->fScanning == SANE_TRUE) + { + while ( s->fScanning == SANE_FALSE ) + { + status = sane_read(device, (SANE_Byte *)buf, 5000, &len); +/* status = sane_read(device, &buf, 5000, &len);*/ + /* buf have the lenght maxlen; len returns the lenght of the retuned bytes */ + } + } + /* free scanner object memory */ + free ((void *) s); + return result; +} + +#endif + + diff -urN sane-backends-1.0.15.orig/backend/hp_rts88xx.conf sane-backends-1.0.15/backend/hp_rts88xx.conf --- sane-backends-1.0.15.orig/backend/hp_rts88xx.conf 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts88xx.conf 2005-07-26 13:25:11.166833584 -0500 @@ -0,0 +1,20 @@ +# hp_rts88xx.conf: Configuration file for HP35x00C and HP44x0 USB scanners +# Read man sane-hp_rts88xx.man for documentation + +# ALL: +# If autodetection doesn't work uncomment or add your device file +#/dev/usbscanner + +# HP44x0C option_CCD +# CCD0 or CCD1 allowed +# if you receive a black image, change it to CCD1 +#option CCD0 + +# HP44x0C option_color +# none or ENABLE_COLOR allowed +# allow the color mode +#option ENABLE_COLOR + +# HP35x00C/HP44x0C enable all resolutions +# !!!!! only for test and development !!!!! +#option ENABLE_T_RES diff -urN sane-backends-1.0.15.orig/backend/hp_rts88xx.h sane-backends-1.0.15/backend/hp_rts88xx.h --- sane-backends-1.0.15.orig/backend/hp_rts88xx.h 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts88xx.h 2005-07-26 13:25:11.153835560 -0500 @@ -0,0 +1,242 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP4400C, HP4470C, HP3500C, 3530C, and HP ScanJet 3570C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Provides a simple interface to read and write data from the scanner, + without any knowledge whether it's a parallel or USB scanner + + enable DEDUG output: + use a nomal shell (konsole) and type + export SANE_DEBUG_HP_RTS88XX=32 + export XSANE_DEBUG=100 + xsane +*/ + +#ifndef _HP_RTS88xx_H_ +#define _HP_RTS88xx_H_ + + +#define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4) +#define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_)) +#define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE +#define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE +#define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) +#define NUM_GAMMA_ENTRIES 65536 + +#define RTS8801_GREYSCALE 1 +#define RTS8801_COLOUR 2 +#define RTS8801_BW 0 + +typedef enum + { + BLACK_WHITE = 0, + GRAY, /*1*/ + COLOR /*2*/ + } +BACKEND_MODE; + +/* options enumerator */ +typedef enum { + optCount = 0, + + optGroupGeometry, + optTLX, optTLY, optBRX, optBRY, + optDPI, + optGroupImage, + optGammaTableRed, /* Gamma Tables */ + optGammaTableGreen, + optGammaTableBlue, + optGroupMisc, + OPT_MODE, + optXPDA, + optCCD, + optBrightness, + optGainR, + optGainG, + optGainB, + optLast +} EOptionIndex; + + +typedef union { + SANE_Word w; + SANE_Word *wa; /* word array */ + SANE_String s; +} TOptionValue; + + +typedef struct { + SANE_Int iDpi; /* horizontal resolution */ + SANE_Int iLpi; /* vertical resolution */ + SANE_Int iY; /* iTop in HW coordinates */ + SANE_Int iX; /* iLeft in HW coordinates */ + SANE_Int iWidth; /* pixels per line */ + SANE_Int iLenght; /* iHeight pixel lines */ + SANE_Int iSkipLines; /* Steps to pos. for scann */ + SANE_Int iLinesLeft; /* Lines witch left over to scan */ + SANE_Int fCalib; /* if TRUE, disable backtracking? */ + SANE_Int brightness; + SANE_Int mode; /* B/W = 0; grayscale = 1 color = 2 */ + SANE_Int optXPA; /* 0=normal; 1 = XPA */ + SANE_Int oCCD_Type; /* 0/1 */ + SANE_Int GainR; + SANE_Int GainG; + SANE_Int GainB; + #ifdef DEBUG_FILE + FILE *FD_r; /* rgb test pnm file*/ + SANE_Int DebugOpen; + SANE_Int DebugSeek0; + #endif +} TScanParams; + + +typedef struct { + /* transfer buffer */ + SANE_Byte *pabXferBuf; + SANE_Int iCurLine, iBytesPerLine, iLinesPerXferBuf; + SANE_Int iLastLine; + SANE_Int iScanned; /* Lines witch have scanned */ + SANE_Int iLinesLeft; /* Lines witch left over to scan */ + /* circular buffer */ + SANE_Byte *pabCircBuf; + SANE_Int iLinesPerCircBuf; + SANE_Int iLinesInCircBuf; + SANE_Int iMisAlignment; + SANE_Int iRedLine, iGrnLine, iBluLine; + /* current line buffer */ + SANE_Byte *pabLineBuf; + SANE_Int iBytesLeft; + + SANE_Int iZeroLines; +} TDataPipe; + + +typedef struct { +/* EScannerModel ScannerModel;*/ + SANE_Int ScannerModel; + SANE_Int iXferHandle; /* handle used for data transfer to HW */ + SANE_Int iTopLeftX; /* in mm */ + SANE_Int iTopLeftY; /* in mm */ + SANE_Int iMainBoardID; /* */ + SANE_Bool iReversedHead; /* Head is reversed */ + SANE_Bool lamp_warm; /* TRUE = the lamp is warm */ + SANE_Byte regs[0xff]; +} THWParams; + + +typedef struct { + SANE_Option_Descriptor aOptions[optLast]; + TOptionValue aValues[optLast]; + + TScanParams ScanParams; + THWParams HWParams; + TDataPipe DataPipe; + + SANE_Int *aGammaTableR; /* a 16-to-16 bit color lookup table */ + SANE_Int *aGammaTableG; /* a 16-to-16 bit color lookup table */ + SANE_Int *aGammaTableB; /* a 16-to-16 bit color lookup table */ + + SANE_Bool fScanning; /* TRUE if actively scanning */ + SANE_Bool fCanceled; +} TScanner; + + +/* option constraints */ +static SANE_Bool OPT_CCD = SANE_TRUE; +static SANE_Bool OPT_COLOR = SANE_FALSE; +static SANE_Bool OPT_T_RES = SANE_FALSE; +static const SANE_Range rangeGammaTable = {0,65535,1}; +static const SANE_Int Hp44x0c_setResolutions[] = {1,300}; +static const SANE_Int Hp44x0c_setResolutions_t[] = {2,300,600}; +static const SANE_Int Hp35x0c_setResolutions[] = {1,150}; +static const SANE_Int Hp35x0c_setResolutions_t[] = {3,150,300,600}; + +#ifndef WITH_TSTBACKEND +static const SANE_Range rangeXmm = {0, 220, 1}; /* max. mm */ +static const SANE_Range rangeYmm = {0, 295, 1}; /* max. mm */ +#endif +#ifdef WITH_TSTBACKEND +static const SANE_Range rangeXmm = {0, 70, 1}; /* max. mm */ +static const SANE_Range rangeYmm = {0, 70, 1}; /* max. mm */ +#endif +static const SANE_Range rangeBrightness = {0, 20, 1}; +/*static const SANE_Range rangeBrightness = {0, 0x40, 1};*/ +#if 0 +static const SANE_Range rangeLampBrightness = {0xa1, 0xaf, 1}; +#endif + +static SANE_String_Const mode_list[5]; +static SANE_String_Const scan_option_list[3]; +static SANE_String_Const ccd_list[3]; + +/* Device filename for USB access */ +SANE_Char * usb_devfile = "/dev/usb/scanner0"; + +SANE_Status _Init_Interface(THWParams *pHWParams, TScanParams *pParams); +void _Close_Interface(THWParams *pHWParams); +SANE_Bool _InitScan (TScanParams *pParams,THWParams *pHWParams, TDataPipe *pDataPipe); +SANE_Bool _FinishScan (SANE_Handle h); +#endif diff -urN sane-backends-1.0.15.orig/backend/hp_rts_35x0c.c sane-backends-1.0.15/backend/hp_rts_35x0c.c --- sane-backends-1.0.15.orig/backend/hp_rts_35x0c.c 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts_35x0c.c 2005-07-26 13:25:11.157834952 -0500 @@ -0,0 +1,1421 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP3500C, 3530C, and HP ScanJet 3570C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Core HP35x0c functions. +*/ + +#include /* fopen, fread, fwrite, fclose etc */ +#include /* va_list for vfprintf */ +#include /* memcpy, memset */ +#include /* unlink */ +#include /* malloc, free */ +#include /* exp, pow */ +#include + +#include "hp_rts_xfer.h" +#include "hp_rts_44x0c.h" +#include "hp_rts_35x0c.h" + +static SANE_Byte sram_access_method = 0; +static SANE_Word sram_size = 0; + +/****************************************************************************/ +SANE_Int +Hp35x0c_queue_read_register( SANE_Int iHandle, SANE_Byte reg, SANE_Int bytes, SANE_Byte *data) +/****************************************************************************/ +{ + if (bytes == 1) + return ( Hp_rts_RegRead(iHandle,reg, data)); + else + return ( Hp_rts_BulkRead( iHandle, reg, data, bytes, SANE_TRUE) ); + } + +/****************************************************************************/ +SANE_Int +Hp35x0c_read_register_immediate( SANE_Int iHandle, SANE_Int reg, SANE_Int bytes, SANE_Byte *data) +/****************************************************************************/ +{ + if (bytes == 1) + return ( Hp_rts_RegRead(iHandle,reg, data) ); + else + return ( Hp_rts_BulkRead( iHandle, reg, data, bytes, SANE_TRUE) ); +} + +/**************************************************************************** +SANE_Int +Hp35x0c_queue_set_register( SANE_Int iHandle, SANE_Int reg, SANE_Int bytes, void *data) +**************************************************************************** +{ + if (bytes == 1) + return( Hp_rts_RegWrite (iHandle, reg, data)); + else + return( Hp_rts_BulkWrite(iHandle, reg, data, bytes, SANE_TRUE)); +}*/ + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_register_immediate( SANE_Int iHandle, SANE_Int reg, SANE_Int bytes, SANE_Byte *data) +/****************************************************************************/ +{ + if (reg < 0xb3 && reg + bytes > 0xb3) + { + SANE_Int bytes_in_first_block = 0xb3 - reg; + + if (Hp35x0c_set_register_immediate(iHandle, reg, bytes_in_first_block, data) < 0 || + Hp35x0c_set_register_immediate(iHandle, 0xb4, bytes - bytes_in_first_block - 1, + data + bytes_in_first_block + 1) < 0) + return -1; + return 0; + } + if (bytes == 1){ + return( Hp_rts_RegWrite (iHandle, reg, *data)); + }else + return( Hp_rts_BulkWrite(iHandle, reg, (SANE_Byte *)data, bytes, SANE_TRUE)); +} + + +/****************************************************************************/ +SANE_Int +Hp35x0c_send_command_immediate( SANE_Int iHandle, SANE_Int command, +/****************************************************************************/ + SANE_Byte reg, + SANE_Int count, + SANE_Int bytes, + SANE_Byte *data, + SANE_Int readbytes, + SANE_Byte *readdata) +{ + callibration_buffer[0] = command; + callibration_buffer[1] = reg; + callibration_buffer[2] = count >> 8; + callibration_buffer[3] = count; + memcpy(callibration_buffer + 4, data, bytes); + Hp_rts_BulkWrite(iHandle, 0,callibration_buffer, bytes+4, SANE_FALSE); + if (readbytes) + { + return(Hp_rts_BulkRead(iHandle, 0,readdata,readbytes,SANE_FALSE)); + } + return( 0 ); +} + + +/****************************************************************************/ +SANE_Int +Hp35x0c_write_sram( SANE_Int iHandle, SANE_Word bytes, SANE_Byte *data) +/****************************************************************************/ +{ + callibration_buffer[0] = RTCMD_WRITESRAM; + callibration_buffer[1] = 0x00; + callibration_buffer[2] = bytes >> 8; + callibration_buffer[3] = bytes; + memcpy(callibration_buffer + 4, data, bytes); + return( Hp_rts_BulkWrite(iHandle, 0, + callibration_buffer, bytes+4, SANE_FALSE)); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_read_sram( SANE_Int iHandle, SANE_Int bytes, SANE_Byte *data) +/****************************************************************************/ +{ + return Hp35x0c_send_command_immediate(iHandle,RTCMD_READSRAM, 0, bytes, 0, 0, bytes, data); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_sram_page( SANE_Int iHandle, SANE_Byte page) +/****************************************************************************/ +{ + return(Hp_rts_Set_double_reg(iHandle,0x91, page, page >> 8)); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_detect_sram( SANE_Int iHandle, SANE_Word *totalbytes, SANE_Byte *r93setting) +/****************************************************************************/ +{ + SANE_Byte data[0x818]; + SANE_Byte testbuf[0x818]; + SANE_Int i; + SANE_Int test_values[] = { 6, 2, 1, -1 }; + + for (i = 0; i < (SANE_Int)sizeof(data); ++i) + data[i] = i % 0x61; + + + for (i = 0; test_values[i] != -1; ++i) + { + if (Hp_rts_RegWrite(iHandle,0x93, test_values[i]) || + Hp35x0c_set_sram_page(iHandle,0x81) || + Hp35x0c_write_sram(iHandle,0x818, data) || + Hp35x0c_set_sram_page(iHandle,0x81) || + Hp_rts_Read_Sram (iHandle, testbuf,0x818) ) + return -1; + if (!memcmp(testbuf, data, 0x818)) + { + sram_access_method = test_values[i]; + if (r93setting) + *r93setting = sram_access_method; + break; + } + } + if (!sram_access_method) + return -1; + + for (i = 0; i < 16; ++i) + { + SANE_Int j; + SANE_Byte write_data[32]; + SANE_Byte read_data[32]; + SANE_Int pagesetting; + + for (j = 0; j < 16; j++) + { + write_data[j * 2] = j * 2; + write_data[j * 2 + 1] = i; + } + + pagesetting = i * 4096; + + if (Hp35x0c_set_sram_page(iHandle,pagesetting) < 0|| + Hp35x0c_write_sram(iHandle,32, write_data) < 0) + return -1; + if (i) + { + if (Hp35x0c_set_sram_page(iHandle,0) < 0 || + Hp35x0c_read_sram(iHandle,32, read_data) < 0) + return -1; + if (!memcmp(read_data, write_data, 32)) + { + sram_size = i * 0x20000; + if (totalbytes) + *totalbytes = sram_size; + return 0; + } + } + return -1; + } + return -1; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_is_rewound( SANE_Int iHandle ) +/****************************************************************************/ +{ + SANE_Byte r; + + if (Hp35x0c_read_register_immediate( iHandle, 0x1d, 1, &r) < 0) + return -1; + if (r & 0x02) + return 1; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_direction_forwards(SANE_Byte *regs) +/****************************************************************************/ +{ + regs[0xc6] |= 0x08; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_direction_rewind(SANE_Byte *regs) +/****************************************************************************/ +{ + regs[0xc6] &= 0xf7; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_stop_when_rewound( SANE_Byte *regs, SANE_Int stop) +/****************************************************************************/ +{ + if (stop) + regs[0xb2] |= 0x10; + else + regs[0xb2] &= 0xef; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_distances( SANE_Int iHandle,SANE_Int location1, + SANE_Int location2) +/****************************************************************************/ +{ + SANE_Byte regbuffer[4]; + + regbuffer[0] = location1; + regbuffer[1] = location1 >> 8; + regbuffer[2] = location2; + regbuffer[3] = location2 >> 8; + return Hp35x0c_set_register_immediate(iHandle,REG_DESTINATION_POSITION, 4, regbuffer); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_powersave_mode( SANE_Int iHandle,SANE_Int enable) +/****************************************************************************/ +{ + SANE_Byte r; + + if (Hp35x0c_read_register_immediate(iHandle,REG_MOVE_CONTROL_TEST, 1, &r) < 0) + return -1; + if (r & 0x04) + { + if (enable == 1) + return 0; + r &= ~0x04; + } + else + { + if (enable == 0) + return 0; + r |= 0x04; + } + if (Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, r) < 0 || + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, r) < 0) + return -1; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_lamp_ready( SANE_Int iHandle ) +/****************************************************************************/ +{ + SANE_Byte r; + + if (Hp35x0c_read_register_immediate(iHandle,0xd1, 1, &r) < 0) + return -1; + if (r & 0x40) + return 0; + return 1; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_turn_off_lamp( SANE_Int iHandle ) +/****************************************************************************/ +{ + return Hp_rts_RegWrite(iHandle,0x3a, 0); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_turn_on_lamp( SANE_Int iHandle ) +/****************************************************************************/ +{ + SANE_Byte r3a; + SANE_Byte r10; + SANE_Byte r58; + + if (Hp35x0c_read_register_immediate(iHandle,0x3a, 1, &r3a) < 0 || + Hp35x0c_read_register_immediate(iHandle,0x10, 1, &r10) < 0 || + Hp35x0c_read_register_immediate(iHandle,0x58, 1, &r58) < 0) + return -1; + r3a |= 0x80; + r10 |= 0x01; + r58 &= 0x0f; + if (Hp_rts_RegWrite(iHandle,0x3a, r3a) < 0 || + Hp_rts_RegWrite(iHandle,0x10, r10) < 0 || + Hp_rts_RegWrite(iHandle,0x58, r58) < 0) + return -1; + return 0; +} + +/****************************************************************************/ +/****************************************************************************/ +#if 0 +static SANE_Int +Hp35x0c_set_value_msbfirst( SANE_Byte *regs, + SANE_Int firstreg, + SANE_Int totalregs, + SANE_Word value) +/****************************************************************************/ +{ + while (totalregs--) + { + regs[firstreg + totalregs] = value & 0xff; + value >>= 8; + } + return 0; +} +#endif +/****************************************************************************/ +SANE_Int +Hp35x0c_set_ccd_shift_clock_multiplier( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0xf0, 3, value); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_ccd_sample_clock_multiplier( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0xf6, 3, value); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_ccd_clock_reset_interval( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0xf9, 3, value); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_ccd_clamp_clock_multiplier( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0xfc, 3, value); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_movement_pattern( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0xc0, 3, value); +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_motor_movement_clock_multiplier( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + regs[0x40] = (regs[0x40] & ~0xc0) | (value << 6); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_motor_type( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + regs[0xc9] = (regs[0xc9] & 0xf8) | (value & 0x7); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_basic_calibration( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int redoffset1, + SANE_Int redoffset2, + SANE_Int redgain, + SANE_Int greenoffset1, + SANE_Int greenoffset2, + SANE_Int greengain, + SANE_Int blueoffset1, + SANE_Int blueoffset2, + SANE_Int bluegain) +{ + regs[0x05] = redoffset1; + regs[0x02] = redoffset2; + regs[0x08] = redgain; + regs[0x06] = greenoffset1; + regs[0x03] = greenoffset2; + regs[0x09] = greengain; + regs[0x07] = blueoffset1; + regs[0x04] = blueoffset2; + regs[0x0a] = bluegain; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_calibration_addresses( SANE_Byte *regs, +/****************************************************************************/ + SANE_Word redaddr, + SANE_Word blueaddr, + SANE_Word greenaddr) +{ + regs[0x84] = redaddr; + regs[0x8e] = (regs[0x8e] * 0x0f) | ((redaddr >> 4) & 0xf0); + Hp_rts_set_value_lsbfirst(regs, 0x85, 2, blueaddr); + Hp_rts_set_value_lsbfirst(regs, 0x87, 2, greenaddr); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_lamp_duty_cycle( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int enable, + SANE_Int frequency, + SANE_Int offduty) +{ + if (enable) + regs[0x3b] |= 0x80; + else + regs[0x3b] &= 0x7f; + + regs[0x3b] = (regs[0x3b] & 0x80) | ((frequency & 0x7) << 4) | (offduty & 0x0f); + regs[0x3d] = (regs[0x3d] & 0x7f) | ((frequency & 0x8) << 4); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_data_feed_on( SANE_Byte *regs) +/****************************************************************************/ +{ + regs[0xb2] &= ~0x04; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_data_feed_off( SANE_Byte *regs) +/****************************************************************************/ +{ + regs[0xb2] |= 0x04; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_enable_ccd( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int enable) +{ + if (enable) + regs[0x00] &= ~0x10; + else + regs[0x00] |= 0x10; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_cdss( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int val1, + SANE_Int val2) +{ + regs[0x28] = (regs[0x28] & 0xe0) | (val1 & 0x1f); + regs[0x2a] = (regs[0x2a] & 0xe0) | (val2 & 0x1f); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_cdsc( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int val1, + SANE_Int val2) +{ + regs[0x29] = (regs[0x29] & 0xe0) | (val1 & 0x1f); + regs[0x2b] = (regs[0x2b] & 0xe0) | (val2 & 0x1f); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_update_after_setting_cdss2( SANE_Byte *regs) +/****************************************************************************/ +{ + SANE_Int fullcolour = (!(regs[0x2f] & 0xc0) && (regs[0x2f] & 0x04)); + SANE_Int value = regs[0x2a] & 0x1f; + + regs[0x2a] = (regs[0x2a] & 0xe0) | (value & 0x1f); + + if (fullcolour) + value *= 3; + if ((regs[0x40] & 0xc0) == 0x40) + value += 17; + else + value += 16; + + regs[0x2c] = (regs[0x2c] & 0xe0) | (value % 24); + regs[0x2d] = (regs[0x2d] & 0xe0) | ((value + 2) % 24); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_cph0s( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int on) +{ + if (on) + regs[0x2d] |= 0x20; /* 1200dpi horizontal coordinate space */ + else + regs[0x2d] &= ~0x20; /* 600dpi horizontal coordinate space */ + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_cvtr_lm( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int val1, + SANE_Int val2, + SANE_Int val3) +{ + regs[0x28] = (regs[0x28] & ~0xe0) | (val1 << 5); + regs[0x29] = (regs[0x29] & ~0xe0) | (val2 << 5); + regs[0x2a] = (regs[0x2a] & ~0xe0) | (val3 << 5); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_cvtr_mpt( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int val1, + SANE_Int val2, + SANE_Int val3) +{ + regs[0x3c] = (val1 & 0x0f) | (val2 << 4); + regs[0x3d] = (regs[0x3d] & 0xf0) | (val3 & 0x0f); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_cvtr_wparams( SANE_Byte *regs, +/****************************************************************************/ + SANE_Word fpw, + SANE_Word bpw, + SANE_Word w) +{ + regs[0x31] = (w & 0x0f) | ((bpw << 4) & 0x30) | (fpw << 6); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_enable_movement( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int enable) +{ + if (enable) + regs[0xc3] |= 0x80; + else + regs[0xc3] &= ~0x80; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_scan_frequency( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int frequency) +{ + regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_merge_channels( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int on) +{ + DBG( DBG_MSG , "start_scan: Hp35x0c_set_merge_channels\n"); + regs[0x2f] &= ~0x14; + regs[0x2f] |= on ? 0x04 : 0x10; +#ifdef DEBUG + Hp_rts_DumpBits(0x2f, regs[0x2f]); +#endif + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_channel( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int channel) +{ + DBG( DBG_MSG , "start_scan: Hp35x0c_set_channel %d\n",channel); + regs[0x2f] = (regs[0x2f] & ~0xc0) | (channel << 6); +#ifdef DEBUG + Hp_rts_DumpBits(0x2f, regs[0x2f]); +#endif + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_single_channel_scanning( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int on) +{ + if (on){ + regs[0x2f] |= 0x20; + DBG( DBG_MSG , "start_scan: Hp35x0c_set_single_channel_scanning on\n"); + }else{ + regs[0x2f] &= ~0x20; + DBG( DBG_MSG , "start_scan: Hp35x0c_set_single_channel_scanning off\n"); + } +#ifdef DEBUG + Hp_rts_DumpBits(0x2f, regs[0x2f]); +#endif + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_colour_mode( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int on) +{ + if (on){ + DBG( DBG_MSG , "start_scan: Set register to color mode\n"); + regs[0x2f] |= 0x02; + }else{ + DBG( DBG_MSG , "start_scan: Set register to gray mode\n"); + regs[0x2f] &= ~0x02; + } +#ifdef DEBUG + Hp_rts_DumpBits(0x2f, regs[0x2f]); +#endif + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_horizontal_resolution( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int resolution) +{ + if (regs[0x2d] & 0x20) + regs[0x7a] = 1200 / resolution; + else + regs[0x7a] = 600 / resolution; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_last_sram_page( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int pagenum) +{ + Hp_rts_set_value_lsbfirst(regs, 0x8b, 2, pagenum); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_step_size( SANE_Byte *regs, +/****************************************************************************/ + SANE_Int stepsize) +{ + Hp_rts_set_value_lsbfirst(regs, 0xe2, 2, stepsize); + Hp_rts_set_value_lsbfirst(regs, 0xe0, 2, 0); + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_set_all_registers( SANE_Int iHandle, void const *regs_) +/****************************************************************************/ +{ + SANE_Byte regs[255]; + + memcpy(regs, regs_, 255); + regs[32] &= ~0x40; + + if (Hp_rts_RegWrite(iHandle,0x32, regs[0x32]) < 0 || + Hp35x0c_set_register_immediate(iHandle,0, 255, regs) < 0 || + Hp_rts_RegWrite(iHandle,0x32, regs[0x32] | 0x40) < 0) + return -1; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_adjust_misc_registers(SANE_Byte *regs) +/****************************************************************************/ +{ + /* Mostly unknown purposes - probably no need to adjust */ + regs[0xc6] = (regs[0xc6] & 0x0f) | 0x20; /* Purpose unknown - appears to do nothing */ + regs[0x2e] = 0x86; /* ???? - Always has this value */ + regs[0x30] = 2; /* CCPL = 1 */ + regs[0xc9] |= 0x38; /* Doesn't have any obvious effect, but the Windows driver does this */ + return 0; +} + + +#define NVR_MAX_ADDRESS_SIZE 11 +#define NVR_MAX_OPCODE_SIZE 3 +#define NVR_DATA_SIZE 8 +#define NVR_MAX_COMMAND_SIZE ((NVR_MAX_ADDRESS_SIZE + \ + NVR_MAX_OPCODE_SIZE + \ + NVR_DATA_SIZE) * 2 + 1) + +/****************************************************************************/ +static SANE_Int +Hp35x0c_nvram_enable_controller(SANE_Int iHandle,SANE_Int enable) +/****************************************************************************/ +{ + SANE_Byte r; + + if (Hp35x0c_read_register_immediate(iHandle,0x1d, 1, &r) < 0) + return -1; + if (enable) + r |= 1; + else + r &= ~1; + return Hp_rts_RegWrite(iHandle,0x1d, r); + +} + +/****************************************************************************/ +static SANE_Int +Hp35x0c_nvram_init_command(SANE_Int iHandle) +/****************************************************************************/ +{ + SANE_Byte regs[13]; + + if (Hp35x0c_read_register_immediate(iHandle,0x10, 13, regs) < 0) + return -1; + regs[2] |= 0xf0; + regs[4] = regs[4] & 0x1f | 0x60; + return Hp35x0c_set_register_immediate(iHandle,0x10, 13, regs); +} + +/****************************************************************************/ +static SANE_Int +Hp35x0c_nvram_init_stdvars(SANE_Int iHandle,SANE_Int block, +/****************************************************************************/ + SANE_Int *addrbits, + SANE_Byte *basereg) +{ + SANE_Int bitsneeded; + SANE_Int capacity; + + switch (block) + { + case 0: + bitsneeded = 7; + break; + + case 1: + bitsneeded = 9; + break; + + case 2: + bitsneeded = 11; + break; + + default: + bitsneeded = 0; + capacity = 1; + while (capacity < block) + capacity <<= 1, ++bitsneeded; + break; + } + + *addrbits = bitsneeded; + + if (Hp35x0c_read_register_immediate(iHandle,0x10, 1, basereg) < 0) + return -1; + + *basereg &= ~0x60; + return 0; +} + +/****************************************************************************/ +static void +Hp35x0c_nvram_set_half_bit( SANE_Byte *buffer, +/****************************************************************************/ + SANE_Int value, + SANE_Byte stdbits, + SANE_Int whichhalf) +{ + *buffer = stdbits | (value ? 0x40 : 0) | (whichhalf ? 0x20 : 0); +} + +/****************************************************************************/ +static void +Hp35x0c_nvram_set_command_bit(SANE_Byte *buffer, +/****************************************************************************/ + SANE_Int value, + SANE_Byte stdbits) +{ + Hp35x0c_nvram_set_half_bit(buffer, value, stdbits, 0); + Hp35x0c_nvram_set_half_bit(buffer + 1, value, stdbits, 1); +} + +/****************************************************************************/ +void +Hp35x0c_nvram_set_addressing_bits( SANE_Byte *buffer, +/****************************************************************************/ + SANE_Int location, + SANE_Int addressingbits, + SANE_Byte stdbits) +{ + SANE_Int currentbit = 1 << (addressingbits - 1); + + while (addressingbits--) + { + Hp35x0c_nvram_set_command_bit(buffer, + (location & currentbit) ? 1 : 0, + stdbits); + buffer += 2; + currentbit >>= 1; + } +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_nvram_enable_write(SANE_Int iHandle,SANE_Int addressingbits, +/****************************************************************************/ + SANE_Int enable, + SANE_Byte stdbits) +{ + SANE_Byte cmdbuffer[NVR_MAX_COMMAND_SIZE]; + SANE_Byte cmdsize = 6 + addressingbits * 2; + + Hp35x0c_nvram_set_command_bit(cmdbuffer, 1, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 2, 0, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 4, 0, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 6, enable, stdbits); + if (addressingbits > 1) + Hp35x0c_nvram_set_addressing_bits(cmdbuffer + 8, 0, addressingbits - 1, stdbits); + + if (Hp35x0c_nvram_enable_controller(iHandle,1) < 0 || + Hp35x0c_send_command_immediate(iHandle,RTCMD_NVRAMCONTROL, 0, cmdsize, cmdsize, cmdbuffer, 0, 0) < 0 || + Hp35x0c_nvram_enable_controller(iHandle,0) < 0) + { + return -1; + } + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_nvram_write(SANE_Int iHandle, SANE_Int block, +/****************************************************************************/ + SANE_Int location, + SANE_Char const *data, + SANE_Int bytes) +{ + SANE_Int addressingbits; + SANE_Byte stdbits; + SANE_Byte cmdbuffer[NVR_MAX_COMMAND_SIZE]; + SANE_Byte *address_bits; + SANE_Byte *data_bits; + SANE_Int i; + SANE_Int cmdsize; + SANE_Byte r; + SANE_Byte cmd; + + /* This routine doesn't appear to work, but I can't see anything wrong with it */ + if (Hp35x0c_nvram_init_stdvars(iHandle,block, &addressingbits, &stdbits) < 0) + return -1; + + cmdsize = (addressingbits + 8) * 2 + 6; + address_bits = cmdbuffer + 6; + data_bits = address_bits + (addressingbits * 2); + + Hp35x0c_nvram_set_command_bit(cmdbuffer, 1, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 2, 0, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 4, 1, stdbits); + + if (Hp35x0c_nvram_init_command(iHandle) < 0 || + Hp35x0c_nvram_enable_write(iHandle,addressingbits, 1, stdbits) < 0) + return -1; + + while (bytes--) + { + Hp35x0c_nvram_set_addressing_bits(address_bits, location, addressingbits, stdbits); + Hp35x0c_nvram_set_addressing_bits(data_bits, *data++, 8, stdbits); + + if (Hp35x0c_nvram_enable_controller(iHandle,1) < 0 || + Hp35x0c_send_command_immediate(iHandle,RTCMD_NVRAMCONTROL, 0, cmdsize, cmdsize, cmdbuffer, 0, 0) < 0 || + Hp35x0c_nvram_enable_controller(iHandle,0) < 0) + return -1; + + if (Hp35x0c_nvram_enable_controller(iHandle,1) < 0) + return -1; + for (i = 0; i < cmdsize; ++i) + { + Hp35x0c_nvram_set_half_bit(&cmd, 0, stdbits, i & 1); + if (Hp35x0c_send_command_immediate(iHandle,RTCMD_NVRAMCONTROL, 0, 1, 1, &cmd, 0, 0) < 0 || + Hp35x0c_read_register_immediate(iHandle,0x10, 1, &r) < 0) + { + return -1; + } + else if (r & 0x80) + { + break; + } + } + if (Hp35x0c_nvram_enable_controller(iHandle,0) < 0) + return -1; + + ++location; + } + + if (Hp35x0c_nvram_enable_write(iHandle,addressingbits, 0, stdbits) < 0) + return -1; + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp35x0c_nvram_read(SANE_Int iHandle,SANE_Int block, +/****************************************************************************/ + SANE_Int location, + SANE_Byte *data, + SANE_Int bytes) +{ + SANE_Int addressingbits; + SANE_Byte stdbits; + SANE_Byte cmdbuffer[NVR_MAX_COMMAND_SIZE]; + SANE_Byte *address_bits; + SANE_Byte readbit_command[2]; + SANE_Int cmdsize; + SANE_Byte r; + SANE_Int i; + SANE_Char c = 0; + + if (Hp35x0c_nvram_init_stdvars(iHandle,block, &addressingbits, &stdbits) < 0) + return -1; + + cmdsize = addressingbits * 2 + 7; + address_bits = cmdbuffer + 6; + + Hp35x0c_nvram_set_command_bit(cmdbuffer, 1, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 2, 1, stdbits); + Hp35x0c_nvram_set_command_bit(cmdbuffer + 4, 0, stdbits); + Hp35x0c_nvram_set_half_bit(cmdbuffer + cmdsize - 1, 0, stdbits, 0); + + Hp35x0c_nvram_set_half_bit(readbit_command, 0, stdbits, 1); + Hp35x0c_nvram_set_half_bit(readbit_command + 1, 0, stdbits, 0); + + if (Hp35x0c_nvram_init_command(iHandle) < 0) + return -1; + + while (bytes--) + { + Hp35x0c_nvram_set_addressing_bits(address_bits, location, addressingbits, stdbits); + + if (Hp35x0c_nvram_enable_controller(iHandle,1) < 0 || + Hp35x0c_send_command_immediate(iHandle,RTCMD_NVRAMCONTROL, 0x1d, cmdsize, cmdsize, cmdbuffer, 0, 0) < 0) + return -1; + + for (i = 0; i < 8; ++i) + { + c <<= 1; + + if (Hp35x0c_send_command_immediate(iHandle,RTCMD_NVRAMCONTROL, 0x1d, 2, 2, readbit_command, 0, 0) < 0 || + Hp35x0c_read_register_immediate(iHandle,0x10, 1, &r) < 0) + return -1; + if (r & 0x80) + c |= 1; + } + if (Hp35x0c_nvram_enable_controller(iHandle,0) < 0) + return -1; + + *data++ = c; + ++location; + } + return 0; +} + + +/****************************************************************************/ +SANE_Int +Hp35x0c_rewind(THWParams *pHWParams) +/* Moves scanner to home position */ +/****************************************************************************/ +{ + SANE_Byte regs[255]; + SANE_Int iHandle; + + regs[1] = 0; /* only for the compiler */ + iHandle = pHWParams->iXferHandle; + DBG(DBG_MSG,"Hp35x0c_rewind : park to home..."); +#ifdef DEBUG_HP3500 + return 0; +#endif + if (Hp35x0c_is_rewound(iHandle )){ + DBG(DBG_MSG,"Hp35x0c_rewind : i'm home\n"); + return 0; + } + DBG(DBG_MSG,"Hp35x0c_rewind : i must moving\n"); +#if 0 + /* read all registers */ + Hp35x0c_read_register_immediate(iHandle,0, 255, regs); + + /* set registes 60/1 and 62/3 */ + Hp_rts_set_noscan_distance(regs, 59998); + Hp_rts_set_total_distance(regs, 59999); + + /* clear Bit 4 from register b2 */ + Hp35x0c_set_stop_when_rewound(regs, 0); + + DBG(DBG_MSG,"Hp35x0c_rewind : Hp_rts_RegWrite 0xc6\n"); + Hp_rts_RegWrite(iHandle,0xc6, 0); + DBG(DBG_MSG,"Hp35x0c_rewind : Hp_rts_RegWrite 0xc6\n"); + Hp_rts_RegWrite(iHandle,0xc6, 0); + + /* set register e2 to stepsize, e0 to 0 */ + Hp35x0c_set_step_size(regs, 0x0abd); + + /* set Bit 3 from register c6 to 0 */ + Hp35x0c_set_direction_rewind(regs); + + /* fast move */ + regs[0x39] = 15; + /* Motor enable: It set bit 7. clear bit 0-2 and set bit 0 + regs[0xc3] = (regs[0xc3] & 0xf8) | 1; */ + regs[0xc3] |= 0x80; + + /* setzt in Register c6 step size auf 3 */ + regs[0xc6] = (regs[0xc6] & 0xf8) | 3; + + DBG(DBG_MSG,"Hp35x0c_rewind : Hp35x0c_set_all_registers\n"); + Hp35x0c_set_all_registers(iHandle,regs); +#else + memcpy(pHWParams->regs,Hp35x0c_rewind_regs,255); + /*-- motor resolution divisor*/ + pHWParams->regs[0x39] =0x0f; + + /*-- motor movement clock multiplier*/ + pHWParams->regs[0x40] =0xa0; + + /*-- noscan distance*/ + pHWParams->regs[0x60] =0x70; + pHWParams->regs[0x61] =0xe7; + + /*-- total distance =noscan distance+1*/ + pHWParams->regs[0x62] =0x71; + pHWParams->regs[0x63] =0xe7; + + /*-- no image data, stop when home*/ + /* (careful, value becomes 0x12 after write)*/ + pHWParams->regs[0xb2] =0x14; + + /*-- coordinate space denominator=3D1, motor enable*/ + pHWParams->regs[0xc3] =0x81; + + /*-- backward direction, step size 0.5 (0x01) or 1 (0x03)*/ + /* pHWParams->regs[0xc6] =0x21;*/ + pHWParams->regs[0xc6] =0x23; + + /*-- bounds movement range 1*/ + pHWParams->regs[0xe0] =0xf4; + pHWParams->regs[0xe1] =0x07; + + /*-- Step size movement range 1*/ + pHWParams->regs[0xe2] =0xd0; + pHWParams->regs[0xe3] =0x00; + + Hp35x0c_set_all_registers(iHandle,pHWParams->regs); + +#endif + Hp_rts_start_moving(iHandle); + DBG(DBG_MSG,"Hp35x0c_rewind : Test, if the scanner is moving\n"); + while (!Hp35x0c_is_rewound(iHandle) /*&& + (Hp_rts_data_ready(iHandle,&n) || + Hp_rts_is_moving(iHandle) > 0)*/) + { + /*if (n) + { + SANE_Byte buffer[0xffc0]; + + if (n > (SANE_Int)sizeof(buffer)) + n = (SANE_Int)sizeof(buffer); + Hp_rts_read_data(iHandle,n, buffer); + DBG(DBG_MSG,"====> has read data\n"); + } + else + {*/ + DBG(DBG_MSG,"w"); + usleep(10000); +#if 0 /* short fix, because the scanner doesn't move */ + break; +#endif + /*}*/ + } + DBG(DBG_MSG," moving done\n"); + return(Hp_rts_stop_moving(iHandle)); +} + + +/****************************************************************************/ +SANE_Bool Hp35x0c_init_scan(THWParams *pHWParams, TScanParams *pParams, + TDataPipe *pDataPipe) +/* code comes from rts8801_scan */ +/****************************************************************************/ +{ + SANE_Int iHandle; + SANE_Byte offdutytime; + SANE_Int ires; + SANE_Byte r93setting; + SANE_Int tg_setting; + SANE_Word x1,x2,y,h; + + iHandle = pHWParams->iXferHandle; + r93setting = r93setting; + + for (ires = 0; Hp35x0c_resparms[ires].resolution && + Hp35x0c_resparms[ires].resolution != pParams->iDpi; ++ires); + if (Hp35x0c_resparms[ires].resolution == 0){ + DBG(DBG_MSG,"Hp35x0c_init_scan: did not found this resolution %d\n",pParams->iDpi); + return SANE_FALSE; + } + + DBG(DBG_MSG,"Hp35x0c_init_scan: Use ires entry %d (%ddpi) for the resolution %d dpi\n",ires, + Hp35x0c_resparms[ires].resolution, pParams->iDpi); + +#ifdef ENABLE_VI8920 + DBG(DBG_MSG,"Vi8920 is enabled and will be run us a HP3500c\n"); +#endif + + /* Initialise and power up */ +#ifdef DEBUG_HP3500 + Hp35x0c_set_all_registers(iHandle,Hp44x0_switch_on_regs); +#else + Hp35x0c_set_all_registers(iHandle,Hp35x0c_initial_regs); + Hp35x0c_set_powersave_mode(iHandle,0); + + Hp35x0c_rewind(pHWParams); + /* Warm up the lamp */ + Hp35x0c_detect_sram(iHandle,&sram_size, &r93setting); + Hp35x0c_turn_on_lamp(iHandle); + sleep(20); +#endif + + /* Set scan parameters */ + Hp35x0c_read_register_immediate(iHandle,0, 255, pHWParams->regs); + pHWParams->regs[255] = 0; + + Hp35x0c_enable_ccd(pHWParams->regs, 1); + Hp35x0c_enable_movement(pHWParams->regs, 1); + Hp35x0c_set_scan_frequency(pHWParams->regs, 1); + + Hp35x0c_adjust_misc_registers(pHWParams->regs); + Hp35x0c_set_cvtr_wparams(pHWParams->regs, 3, 0, 6); + Hp35x0c_set_cvtr_mpt(pHWParams->regs, 15, 15, 15); + Hp35x0c_set_cvtr_lm(pHWParams->regs, 7, 7, 7); + Hp35x0c_set_motor_type(pHWParams->regs, 2); + + offdutytime = 0; + if (Hp35x0c_nvram_read(iHandle,0, 0x7b, &offdutytime, 1) < 0 || + offdutytime >= 15) + { + offdutytime = 6; + } + Hp35x0c_set_lamp_duty_cycle(pHWParams->regs, + 1, /* On */ + 10, /* Frequency */ + offdutytime); /* Off duty time */ + + Hp35x0c_set_movement_pattern(pHWParams->regs, 0x800000); + + tg_setting = Hp35x0c_resparms[ires].tg; + Hp35x0c_set_ccd_shift_clock_multiplier(pHWParams->regs, + tg_info[tg_setting].tg_cph0p); + Hp35x0c_set_ccd_clock_reset_interval(pHWParams->regs, + tg_info[tg_setting].tg_crsp); + Hp35x0c_set_ccd_clamp_clock_multiplier(pHWParams->regs, + tg_info[tg_setting].tg_cclpp); + + Hp_rts_RegWrite(iHandle,0xc6, 0); + Hp_rts_RegWrite(iHandle,0xc6, 0); + + Hp35x0c_set_step_size(pHWParams->regs, Hp35x0c_resparms[ires].step_size); + Hp35x0c_set_direction_forwards(pHWParams->regs); + + Hp35x0c_set_stop_when_rewound(pHWParams->regs, 0); + Hp35x0c_set_data_feed_on(pHWParams->regs); + + Hp35x0c_set_calibration_addresses(pHWParams->regs, 0, 0, 0); + + Hp35x0c_set_basic_calibration(pHWParams->regs, + 0xc8, 0xc8, 0x0a, + 0xc6, 0xc6, 0x0c, + 0xc6, 0xc6, 0x0b); + pHWParams->regs[0x0b] = 0x70;/* If set to 0x71, the alternative, all values are low*/ + + switch (pParams->mode) { + case GRAY: + DBG(DBG_ERR, "Hp35x0c_init_scan: Use gray parameter\n"); + Hp35x0c_set_channel(pHWParams->regs, RT_CHANNEL_RED); + Hp35x0c_set_single_channel_scanning(pHWParams->regs, 1); /* 0x20 on / 0ff*/ + Hp35x0c_set_merge_channels(pHWParams->regs, 1); /* 0x14 on / off */ + Hp35x0c_set_colour_mode(pHWParams->regs, 0); /* 0x02 on / off */ + break; + case COLOR: + DBG(DBG_ERR, "Hp35x0c_init_scan: use color parameter\n"); + Hp35x0c_set_channel(pHWParams->regs, RT_CHANNEL_ALL); + Hp35x0c_set_single_channel_scanning(pHWParams->regs, 0); /* 0x20 on / 0ff*/ + Hp35x0c_set_merge_channels(pHWParams->regs, 1); /* 0x14 on / off */ + /* Hp35x0c_set_merge_channels(pHWParams->regs, 0); * 0x14 on / off */ + Hp35x0c_set_colour_mode(pHWParams->regs, 1); /* 0x02 on / off */ + break; + + default: + DBG(DBG_ERR, "Hp35x0c_init_scan: Invalid parameter\n"); + return SANE_FALSE; + }/* switch */ + + Hp35x0c_set_motor_movement_clock_multiplier(pHWParams->regs, + Hp35x0c_resparms[ires].motor_movement_clock_multiplier); + + Hp35x0c_set_cdss(pHWParams->regs, tg_info[tg_setting].tg_cdss1, + tg_info[tg_setting].tg_cdss2); + Hp35x0c_set_cdsc(pHWParams->regs, tg_info[tg_setting].tg_cdsc1, + tg_info[tg_setting].tg_cdsc2); + + Hp35x0c_update_after_setting_cdss2(pHWParams->regs); + + Hp35x0c_set_last_sram_page(pHWParams->regs, (sram_size - 1) >> 5); + + pHWParams->regs[0x39] = Hp35x0c_resparms[ires].reg_39_value; + pHWParams->regs[0xc3] = (pHWParams->regs[0xc3] & 0xf8) | + Hp35x0c_resparms[ires].reg_c3_value; + pHWParams->regs[0xc6] = (pHWParams->regs[0xc6] & 0xf8) | + Hp35x0c_resparms[ires].reg_c6_value; + Hp35x0c_set_scan_frequency(pHWParams->regs, Hp35x0c_resparms[ires].scan_frequency); + Hp35x0c_set_cph0s(pHWParams->regs, Hp35x0c_resparms[ires].cph0s); + + x1 = pParams->iX; + x2 = pParams->iWidth + pParams->iX; + y = pParams->iY; + h = pParams->iLenght;/* * 2;*/ + DBG(DBG_MSG,"Hp35x0c_init_scan: calculate scandata x1 = %d; x2 = %d; lenght = %d\n",x1,x2,h); + pDataPipe->iScanned = h; + DBG(DBG_MSG,"Hp35x0c_init_scan: Hp35x0c_set_horizontal_resolution %d.\n",pParams->iDpi); + Hp35x0c_set_horizontal_resolution(pHWParams->regs, pParams->iDpi); + + /* modify reg 60 + 61 */ +/* Hp_rts_set_noscan_distance(pHWParams->regs, y * + Hp35x0c_resparms[ires].scan_frequency - 1);*/ + Hp_rts_set_noscan_distance(pHWParams->regs, 0x01 ); + + /* modify reg 62 + 63 */ +/* Hp_rts_set_total_distance(pHWParams->regs, Hp35x0c_resparms[ires].scan_frequency * + (y + h + ((pParams->mode == COLOR) ? (Hp35x0c_resparms[ires].red_green_offset + + Hp35x0c_resparms[ires].green_blue_offset) : 0) + + Hp35x0c_resparms[ires].intra_channel_offset));*/ + Hp_rts_set_total_distance(pHWParams->regs, h ); + + /* modify reg 66 + 67 */ +/* Hp_rts_set_scanline_start(pHWParams->regs, x1 * (1200 / pParams->iDpi) / (Hp35x0c_resparms[ires].cph0s ? 1 : 2));*/ + Hp_rts_set_scanline_start(pHWParams->regs, x1 ); + + /* modify reg 6C + 6D */ +/* Hp_rts_set_scanline_end(pHWParams->regs, (x1 + x2) * (1200 / pParams->iDpi) / (Hp35x0c_resparms[ires].cph0s ? 1 : 2));*/ + Hp_rts_set_scanline_end(pHWParams->regs, x2 ); + +#if 1 + DBG(DBG_MSG,"Hp35x0c_init_scan: Hp35x0c_set_all_registers\n"); + Hp_rts_DumpHex(pHWParams->regs,255,16,SANE_TRUE); + Hp_rts_DumpBits(0x2f, pHWParams->regs[0x2f]); +#endif +#ifdef DEBUG_HP3500 + return SANE_FALSE; +#endif + Hp35x0c_set_all_registers(iHandle, pHWParams->regs); + + Hp_rts_RegWrite(iHandle, 0x2c, pHWParams->regs[0x2c]); + + Hp_rts_start_moving(iHandle); + usleep(10000); + /* wait for moving and check it */ + return(Hp_rts_Check_Moving (iHandle)); +} + +/****************************************************************************/ +SANE_Bool Hp35x0c_init_power_on(THWParams *pHWParams) +/****************************************************************************/ +{ + SANE_Int iHandle; + + iHandle = pHWParams->iXferHandle; + Hp35x0c_set_all_registers(iHandle,Hp35x0c_initial_regs); + Hp35x0c_set_powersave_mode(iHandle,0); +#ifndef DEBUG_HP3500 + return(Hp35x0c_rewind(pHWParams)); +#else + return 0; +#endif +} diff -urN sane-backends-1.0.15.orig/backend/hp_rts_35x0c.h sane-backends-1.0.15/backend/hp_rts_35x0c.h --- sane-backends-1.0.15.orig/backend/hp_rts_35x0c.h 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts_35x0c.h 2005-07-26 13:25:11.155835256 -0500 @@ -0,0 +1,445 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP3500C, 3530C, and HP ScanJet 3570C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Core HP35x0c functions. +*/ + + +#ifndef _HP_RTS_HP35x0C_H_ +#define _HP_RTS_HP35x0C_H_ + +#include + +SANE_Byte Hp35x0c_initial_regs[] = +{ + 0xf5,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, + 0xe1,0xfc,0xff,0xff,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x19, + 0xd0,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x37,0xff,0x0f,0x00,0x00, + 0x80,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x20,0xbc,0x03,0x00,0x00,0x00,0x00,0x00,0x1d,0x1f,0x00,0x1f,0x00,0x00,0x00,0x00, + 0x5e,0xea,0x5f,0xea,0x00,0x80,0x64,0x00,0x00,0x00,0x00,0x00,0x84,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0x02,0x4b,0x02,0x00,0xec,0x19,0xd8,0x2d,0x87,0x02,0xff,0x3f,0x78,0x60,0x00, + 0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0c,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x08,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xbf,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +SANE_Byte Hp35x0c_rewind_regs[] = +{ + 0xe5,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xeb,0xed,0xe0,0x01,0x00,0x20,0x86,0x0b, + 0x02,0xa6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0xff,0x8f,0x00,0x00, + 0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x10,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x64,0x00, + 0x00,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x0f,0x18,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x00,0x10,0x0a,0x00,0x00,0x00,0x3a,0x0a,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1f,0x4c,0x00,0x0c,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf8,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe0,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x30,0x00 +}; + +struct Hp35x0c_tg_info__ +{ + SANE_Word tg_cph0p; + SANE_Word tg_crsp; + SANE_Word tg_cclpp; + SANE_Word tg_cdss1; + SANE_Word tg_cdsc1; + SANE_Word tg_cdss2; + SANE_Word tg_cdsc2; +} tg_info[] = +{ + /* CPH0P CRSP CCLPP CDSS1 CDSC1 CDSS2 CDSC2 */ + { 0x01FFE0, 0x3c0000, 0x003000, 0xb, 0xd, 0x00, 0x01 }, /* NORMAL*/ + { 0x7ff800, 0xf00000, 0x01c000, 0xb, 0xc, 0x14, 0x15 } /* DOUBLE*/ +}; + +struct Hp35x0c_resolution_parameters +{ + SANE_Int resolution; + SANE_Byte reg_39_value; + SANE_Byte reg_c3_value; + SANE_Byte reg_c6_value; + SANE_Byte scan_frequency; + SANE_Byte cph0s; + SANE_Byte red_green_offset; + SANE_Byte green_blue_offset; + SANE_Byte intra_channel_offset; + SANE_Byte motor_movement_clock_multiplier; + SANE_Byte tg; + SANE_Word step_size; +}; + +static struct Hp35x0c_resolution_parameters Hp35x0c_resparms[] = +{ + /* My values - all work */ + /*res.,39, c3, c6, freq.chp,gre blu itr mm tg steps. */ + { 1200, 3, 6, 4, 2, 1, 22, 22, 4, 2, 0, 0x157b }, + { 600, 3, 3, 1, 1, 0, 9, 10, 0, 2, 0, 0x157b }, + { 400, 1, 1, 1, 1, 1, 6, 6, 1, 2, 0, 0x157b }, + { 300, 3, 3, 3, 1, 0, 5, 4, 0, 2, 1, 0x157b }, + { 200, 3, 1, 1, 1, 0, 3, 3, 0, 2, 1, 0x157b }, + { 150, 3, 3, 3, 2, 0, 2, 2, 0, 2, 1, 0x157b }, + { 100, 3, 1, 3, 1, 0, 1, 1, 0, 2, 1, 0x157b }, + { 75, 3, 3, 3, 4, 0, 1, 1, 0, 2, 1, 0x157b }, + { 50, 3, 1, 3, 2, 0, 0, 0, 0, 2, 1, 0x157b }, + { 25, 3, 1, 3, 4, 0, 0, 0, 0, 2, 1, 0x157b }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x157b } +}; + +#define REG_DESTINATION_POSITION 0x60 + +#define RTCMD_GETREG 0x80 +#define RTCMD_READSRAM 0x81 + +#define RTCMD_SETREG 0x88 +#define RTCMD_WRITESRAM 0x89 + +#define RTCMD_NVRAMCONTROL 0x8a + +#define RTCMD_BYTESAVAIL 0x90 +#define RTCMD_READBYTES 0x91 + +#define RT_CHANNEL_ALL 0 +#define RT_CHANNEL_RED 1 +#define RT_CHANNEL_GREEN 2 +#define RT_CHANNEL_BLUE 3 + +#if 0 +static SANE_Int +Hp35x0c_set_value_msbfirst( SANE_Byte *regs, + SANE_Int firstreg, + SANE_Int totalregs, + SANE_Word value); +#endif +SANE_Int +Hp35x0c_queue_read_register( SANE_Int iHandle, SANE_Byte reg, SANE_Int bytes, SANE_Byte *data); + +SANE_Int +Hp35x0c_read_register_immediate( SANE_Int iHandle, SANE_Int reg, SANE_Int bytes, SANE_Byte *data); + +SANE_Int +Hp35x0c_set_register_immediate( SANE_Int iHandle, SANE_Int reg, SANE_Int bytes, SANE_Byte *data); + +SANE_Int +Hp35x0c_send_command_immediate( SANE_Int iHandle, SANE_Int command, + SANE_Byte reg, + SANE_Int count, + SANE_Int bytes, + SANE_Byte *data, + SANE_Int readbytes, + SANE_Byte *readdata); + +SANE_Int +Hp35x0c_write_sram( SANE_Int iHandle, SANE_Word bytes, SANE_Byte *data); + +SANE_Int +Hp35x0c_read_sram( SANE_Int iHandle, SANE_Int bytes, SANE_Byte *data); + +SANE_Int +Hp35x0c_set_sram_page( SANE_Int iHandle, SANE_Byte page); + +SANE_Int +Hp35x0c_detect_sram( SANE_Int iHandle, SANE_Word *totalbytes, SANE_Byte *r93setting); + +SANE_Int +Hp35x0c_is_rewound( SANE_Int iHandle ); + +SANE_Int +Hp35x0c_set_direction_forwards(SANE_Byte *regs); + +SANE_Int +Hp35x0c_set_direction_rewind(SANE_Byte *regs); + +SANE_Int +Hp35x0c_set_stop_when_rewound( SANE_Byte *regs, SANE_Int stop); + +SANE_Int +Hp35x0c_set_distances( SANE_Int iHandle,SANE_Int location1, + SANE_Int location2); + +SANE_Int +Hp35x0c_set_powersave_mode(SANE_Int iHandle,SANE_Int enable); + +SANE_Int +Hp35x0c_lamp_ready( SANE_Int iHandle ); + +SANE_Int +Hp35x0c_turn_off_lamp( SANE_Int iHandle ); + +SANE_Int +Hp35x0c_turn_on_lamp( SANE_Int iHandle ); +#if 0 +static SANE_Int +Hp35x0c_set_value_msbfirst( SANE_Byte *regs,SANE_Int firstreg, + SANE_Int totalregs,SANE_Word value); +#endif +SANE_Int +Hp35x0c_set_ccd_shift_clock_multiplier( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_ccd_sample_clock_multiplier( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_ccd_clock_reset_interval( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_ccd_clamp_clock_multiplier( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_movement_pattern( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_motor_movement_clock_multiplier( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_motor_type( SANE_Byte *regs, + SANE_Word value); + +SANE_Int +Hp35x0c_set_basic_calibration( SANE_Byte *regs, + SANE_Int redoffset1, + SANE_Int redoffset2, + SANE_Int redgain, + SANE_Int greenoffset1, + SANE_Int greenoffset2, + SANE_Int greengain, + SANE_Int blueoffset1, + SANE_Int blueoffset2, + SANE_Int bluegain); + +SANE_Int +Hp35x0c_set_calibration_addresses( SANE_Byte *regs, + SANE_Word redaddr, + SANE_Word blueaddr, + SANE_Word greenaddr); + +SANE_Int +Hp35x0c_set_lamp_duty_cycle( SANE_Byte *regs, + SANE_Int enable, + SANE_Int frequency, + SANE_Int offduty); + +SANE_Int +Hp35x0c_set_data_feed_on( SANE_Byte *regs); + +SANE_Int +Hp35x0c_set_data_feed_off( SANE_Byte *regs); + +SANE_Int +Hp35x0c_enable_ccd( SANE_Byte *regs, + SANE_Int enable); + +SANE_Int +Hp35x0c_set_cdss( SANE_Byte *regs, + SANE_Int val1, + SANE_Int val2); + +SANE_Int +Hp35x0c_set_cdsc( SANE_Byte *regs, + SANE_Int val1, + SANE_Int val2); + +SANE_Int +Hp35x0c_update_after_setting_cdss2( SANE_Byte *regs); + +SANE_Int +Hp35x0c_set_cph0s( SANE_Byte *regs, + SANE_Int on); + +SANE_Int +Hp35x0c_set_cvtr_lm( SANE_Byte *regs, + SANE_Int val1, + SANE_Int val2, + SANE_Int val3); + +SANE_Int +Hp35x0c_set_cvtr_mpt( SANE_Byte *regs, + SANE_Int val1, + SANE_Int val2, + SANE_Int val3); + +SANE_Int +Hp35x0c_set_cvtr_wparams( SANE_Byte *regs, + SANE_Word fpw, + SANE_Word bpw, + SANE_Word w); + +SANE_Int +Hp35x0c_enable_movement( SANE_Byte *regs, + SANE_Int enable); + +SANE_Int +Hp35x0c_set_scan_frequency( SANE_Byte *regs, + SANE_Int frequency); + +SANE_Int +Hp35x0c_set_merge_channels( SANE_Byte *regs, + SANE_Int on); + +SANE_Int +Hp35x0c_set_channel( SANE_Byte *regs, + SANE_Int channel); + +SANE_Int +Hp35x0c_set_single_channel_scanning( SANE_Byte *regs, + SANE_Int on); + +SANE_Int +Hp35x0c_set_colour_mode( SANE_Byte *regs, + SANE_Int on); + +SANE_Int +Hp35x0c_set_horizontal_resolution( SANE_Byte *regs, + SANE_Int resolution); + +SANE_Int +Hp35x0c_set_last_sram_page( SANE_Byte *regs, + SANE_Int pagenum); + +SANE_Int +Hp35x0c_set_step_size( SANE_Byte *regs, + SANE_Int stepsize); + +SANE_Int +Hp35x0c_set_all_registers( SANE_Int iHandle, void const *regs_); + +SANE_Int +Hp35x0c_adjust_misc_registers(SANE_Byte *regs); + +static SANE_Int +Hp35x0c_nvram_enable_controller(SANE_Int iHandle,SANE_Int enable); + +static SANE_Int +Hp35x0c_nvram_init_command(SANE_Int iHandle); + +static SANE_Int +Hp35x0c_nvram_init_stdvars(SANE_Int iHandle,SANE_Int block, + SANE_Int *addrbits, + SANE_Byte *basereg); + +static void +Hp35x0c_nvram_set_half_bit( SANE_Byte *buffer, + SANE_Int value, + SANE_Byte stdbits, + SANE_Int whichhalf); + +static void +Hp35x0c_nvram_set_command_bit(SANE_Byte *buffer, + SANE_Int value, + SANE_Byte stdbits); + +void +Hp35x0c_nvram_set_addressing_bits( SANE_Byte *buffer, + SANE_Int location, + SANE_Int addressingbits, + SANE_Byte stdbits); + +SANE_Int +Hp35x0c_nvram_enable_write(SANE_Int iHandle,SANE_Int addressingbits, + SANE_Int enable, + SANE_Byte stdbits); + +SANE_Int +Hp35x0c_nvram_write(SANE_Int iHandle,SANE_Int block, + SANE_Int location, + SANE_Char const *data, + SANE_Int bytes); + +SANE_Int +Hp35x0c_nvram_read(SANE_Int iHandle,SANE_Int block, + SANE_Int location, + SANE_Byte *data, + SANE_Int bytes); + +SANE_Int Hp35x0c_rewind(THWParams *pHWParams); + +SANE_Bool Hp35x0c_init_scan(THWParams *pHWParams, TScanParams *pParams, + TDataPipe *pDataPipe); + +SANE_Bool Hp35x0c_init_power_on(THWParams *pHWParams); + +#endif /* NO _HP_RTS_HP35x0C_H_ */ + diff -urN sane-backends-1.0.15.orig/backend/hp_rts_44x0c.c sane-backends-1.0.15/backend/hp_rts_44x0c.c --- sane-backends-1.0.15.orig/backend/hp_rts_44x0c.c 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts_44x0c.c 2005-07-26 13:25:11.160834496 -0500 @@ -0,0 +1,949 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP4400C, HP4470C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Core HP44x0c functions. +*/ + +#include /* fopen, fread, fwrite, fclose etc */ +#include /* va_list for vfprintf */ +#include /* memcpy, memset */ +#include /* unlink */ +#include /* malloc, free */ +#include /* exp, pow */ + +#include "hp_rts_xfer.h" +#include "hp_rts_44x0c.h" + + +/****************************************************************************/ +SANE_Bool Hp44x0_Wakeup(THWParams *pHWParams,TScanParams *pParams) +/****************************************************************************/ +{ + SANE_Byte Reg_10, Reg_11; + SANE_Int iHandle; + + DBG(DBG_SCAN, "Hp44x0_Wakeup....\n"); + /* prevent compiler from complaining about unused parameters */ + pParams->mode = pParams->mode; + iHandle = pHWParams->iXferHandle; + + if (iHandle < 0) { + DBG(DBG_SCAN, "Hp44x0_Wakeup, wrong iHandle\n"); + return SANE_FALSE; + } + /* write magic startup sequence */ + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + /* test_reg( 0xb2,0x00,20 );*/ + if ( !(Hp_rts_RegWrite(iHandle,0xb2,0x02))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb1,0x00))) return SANE_FALSE; + if (pParams->optXPA) + Reg_11 = 0x08; + else + Reg_11 = 0x28; + Reg_10 = 0x28; + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, Reg_10, Reg_11 ))) return SANE_FALSE; + usleep(1000); + /* test_double_reg( 0x20,0x3a,0xf2,21 );*/ + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x01))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x01))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle,0x12,0xff,0x20))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle,0x14,0xf8,0x28))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, Reg_10, Reg_11 ))) return SANE_FALSE; + usleep(1000); + if ( !(Hp_rts_RegWrite(iHandle,0xd9,0x80))) return SANE_FALSE; + memcpy(pHWParams->regs,Hp44x0_switch_on_regs,254); + pHWParams->regs[0x10] = Reg_10; + pHWParams->regs[0x11] = Reg_11; + if ( !(Hp_rts_BulkWrite (iHandle, 0x00,pHWParams->regs, 0xb3,SANE_TRUE))) return SANE_FALSE; + return (Hp_rts_BulkWrite (iHandle, 0xb4,pHWParams->regs+0xb3, 0x3f,SANE_TRUE)); + + /* need we a new callibriation ? */ +} + + +/****************************************************************************/ +SANE_Bool Hp44x0_Down(SANE_Int iHandle) +/****************************************************************************/ +{ + DBG(DBG_SCAN, "Hp44x0_Down....\n"); + if (iHandle <= 0) { + return SANE_FALSE; + } + /* switch off the little green LEDs for color selector */ + if ( !(Hp_rts_Set_double_reg(iHandle,LEDSTATUS,0x08,0x28))) return SANE_FALSE; + usleep(10000); + /*test_reg( 0xb2, 0x02,13 ); */ + /* switch off the green power LED */ + if ( !(Hp_rts_RegWrite(iHandle,0xb2,0x00))) return SANE_FALSE; + /* ?? */ + if ( !(Hp_rts_RegWrite(iHandle,0xb1,0x00))) return SANE_FALSE; + /* switch off lamp, LCD and power LED */ + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x04))) return SANE_FALSE; + return (Hp_rts_RegWrite(iHandle,0xb3,0x04)); +} + +/****************************************************************************/ +SANE_Bool Hp44x0_patch_and_send_values(SANE_Int iHandle, SANE_Byte *my_values){ +/****************************************************************************/ + /* read registers, patch and write out them */ + SANE_Byte v1,v2; + + DBG(DBG_SCAN, "Hp44x0_patch_and_send_values....\n"); + Hp_rts_BulkReadall(iHandle,registers); + v1 = *my_values++; + v2 = *my_values++; + registers[v1] = v2; + while(*my_values){ + v1 = *my_values++; + v2 = *my_values++; + registers[v1] = v2; + } + if ( !(Hp_rts_BulkWrite(iHandle,0x00,registers,0xb3,SANE_TRUE))) return SANE_FALSE; + return (Hp_rts_BulkWrite(iHandle,0xb4,registers+0xb3,0x3f,SANE_TRUE)); +} + +/****************************************************************************/ +void Hp44x0_patch_regs(THWParams *pHWParams,SANE_Byte *my_values){ +/****************************************************************************/ + /* read registers, patch and write out them */ + SANE_Byte v1,v2; + + DBG(DBG_SCAN, "Hp44x0_patch_regs....\n"); + v1 = *my_values++; + v2 = *my_values++; + pHWParams->regs[v1] = v2; + while(*my_values){ + v1 = *my_values++; + v2 = *my_values++; + pHWParams->regs[v1] = v2; + } +} + +/****************************************************************************/ +SANE_Bool Hp44x0_set_display( SANE_Int iHandle, SANE_Byte val ) +/****************************************************************************/ +{ + static SANE_Word LcdValues_h []= + /* left char 0, 1, 2, 3 */ + { 0xa18f2,0x0890,0x10b3,0x18b1}; + static SANE_Word LcdValues_l []= + /* right char 0, 1, 2, 3 4 */ + { 0xa68c,0x2280,0xe484,0x6684,0x6288, + /* 5, 6, 7, 8 9 */ + 0x468c,0xc68c,0x2284,0xe68c,0x668c}; + SANE_Byte reg_20,reg_21; + + DBG(DBG_SCAN, "Hp44x0_set_display.to %d\n",val); + if (val < 40){ + reg_20 = (LcdValues_l [val%10] >> 8) & 0x00ff; + reg_21 = LcdValues_l [val%10] & 0x00ff; + reg_20 = reg_20 | (LcdValues_h [val/10] >> 8) & 0x00ff; + reg_21 = reg_21 | LcdValues_h [val/10] & 0x00ff; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + return (Hp_rts_Set_double_reg(iHandle, LCD_CONTROL1, reg_20, reg_21 )); + }; + return SANE_TRUE; +} + +/****************************************************************************/ +SANE_Bool Hp44x0_write_cal_bytes( THWParams *pHWParams, SANE_Byte b ) { +/****************************************************************************/ + SANE_Word i,n; + SANE_Int iHandle; + + DBG(DBG_SCAN, "Hp44x0_write_cal_bytes....\n"); + iHandle = pHWParams->iXferHandle; + callibration_buffer[0]=0x89; + callibration_buffer[1]=0x00; + callibration_buffer[2]=0x00; + callibration_buffer[3]=0x20; + callibration_buffer[4]=0; + n = 2; + for(i=5;i<36;i++) { + callibration_buffer[i] = b; + callibration_buffer[i+1] = n; + i++; + n = n + 2; + } + return (Hp_rts_BulkWrite(iHandle,0x00,callibration_buffer,36,SANE_FALSE)); +} + + +/****************************************************************************/ +SANE_Bool Hp44x0_cal_scanner(THWParams *pHWParams, TScanParams *pParams) { +/****************************************************************************/ + SANE_Word i,n; + SANE_Int iHandle; + SANE_Byte Reg_10, Reg_11; + + DBG(DBG_SCAN, "Hp44x0_cal_scanner....\n"); + iHandle = pHWParams->iXferHandle; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + memcpy(registers,Hp44x0_init_1,0xf4); + if (pParams->mode == COLOR){ + Reg_10 = 0x28; + } else { + Reg_10 = 0x18;} + if (pParams->optXPA){ + Reg_11 = 0x1b; + } else { + Reg_11 = 0x3b;} + registers[0x10] = Reg_10; + registers[0x11] = Reg_11; + if ( !(Hp_rts_BulkWrite(iHandle,0x00,registers,0xb3,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_BulkWrite(iHandle,0xb4,registers+0xb3,0x3f,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp44x0_patch_and_send_values(iHandle,Hp44x0_patch_2))) return SANE_FALSE; + if ( !(Hp44x0_patch_and_send_values(iHandle,Hp44x0_patch_3))) return SANE_FALSE; + +/* if (pParams->mode == COLOR){*/ + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, 0x20, 0x28))) return SANE_FALSE; +/* usleep(10000);*/ + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, 0x28, 0x28))) return SANE_FALSE; +/* + } else { + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, 0x10, 0x28))) return SANE_FALSE; + usleep(10000); + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, 0x18, 0x28))) return SANE_FALSE; + } +*/ + usleep(10000); + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x02))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x02))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + if ( !(Hp44x0_patch_and_send_values(iHandle,Hp44x0_patch_4))) return SANE_FALSE; + + for (n=0;n<3;n++){ + switch (n){ + case 0: if ( !(Hp_rts_RegWrite(iHandle,0x93,0x06))) return SANE_FALSE; break; + case 1: if ( !(Hp_rts_RegWrite(iHandle,0x93,0x02))) return SANE_FALSE; break; + case 2: if ( !(Hp_rts_RegWrite(iHandle,0x93,0x01))) return SANE_FALSE; break; + default:; + } + if ( !(Hp_rts_Set_double_reg(iHandle,0x91, 0x81, 0x00))) return SANE_FALSE; + callibration_buffer[0]=0x89; + callibration_buffer[1]=0x00; + callibration_buffer[2]=0x08; + callibration_buffer[3]=0x18; + callibration_buffer[4]=0; + for(i=5;i<0x818;i++) { + callibration_buffer[i]=callibration_buffer[i-1]+1; + if(callibration_buffer[i]==0x61) callibration_buffer[i]=0; + }; + if ( !(Hp_rts_BulkWrite(iHandle,0x00,callibration_buffer,0x818+4,SANE_FALSE))) return SANE_FALSE; + if ( !(Hp35x0c_set_sram_page(iHandle,0x81))) return SANE_FALSE; +/* Hp_rts_Set_double_reg(iHandle,0x91, 0x81, 0x00);*/ + if ( !(Hp_rts_Read_Sram (iHandle, callibration_buffer,0x0818))) return SANE_FALSE; +#if 0 + read_bulk_callibriation_data(callibration_buffer,0x0818); +/* read_bulk_callibriation_data(buffer2,0x0818); and verify it*/ +#endif + }; + memcpy(registers,Hp44x0_init_5,0xf4); +/* + if (pParams->mode == COLOR){ + registers[LEDSTATUS] = 0x28; + } else { + registers[LEDSTATUS] = 0x18; + }*/ + if ( !(Hp_rts_BulkWrite(iHandle,0x00,registers,0xb3,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_BulkWrite(iHandle,0xb4,registers+0xb3,0x3f,SANE_TRUE))) return SANE_FALSE; + + for(i=0;i<5;i++) { + if ( !(Hp44x0_write_cal_bytes( pHWParams, i ))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle, 0x91, 0x00, 0x10 ))) return SANE_FALSE; +/* read_bulk_callibriation_data(buffer2,0x20); and verify it*/ + }; + if ( !(Hp_rts_RegWrite(iHandle,LAMPREG,0x80))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMPREG,0xad))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle, 0x14, 0x78, 0x28 ))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa0))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa7))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMPREG,0x8d))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMPREG,0xad))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,BUTTON_1,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,BUTTON_2,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,BUTTON_1,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,BUTTON_2,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa0))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa7))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,MOVE_START_STOP,0x00))) return SANE_FALSE; + + if (pParams->mode == COLOR){ + if ( !(Hp_rts_Set_double_reg(iHandle, 0x10, 0x28, 0x3f))) return SANE_FALSE; + } else { + if ( !(Hp_rts_Set_double_reg(iHandle, 0x10, 0x18, 0x3f))) return SANE_FALSE; + } + usleep(10000); + if ( !(Hp_rts_RegWrite(iHandle,LAMPREG,0xad))) return SANE_FALSE; + usleep(10000); +/* if (pParams->mode == COLOR){*/ + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, 0x20, 0x3f))) return SANE_FALSE; +/* } else { + if ( !(Hp_rts_Set_double_reg(iHandle, LEDSTATUS, 0x10, 0x3f))) return SANE_FALSE; + }*/ + usleep(10000); + return(SANE_TRUE); +} + + +/****************************************************************************/ +SANE_Int Hp44x0_park_to_home(THWParams *pHWParams,TScanParams *pParams){ +/* Moves scanner to home position */ +/****************************************************************************/ + SANE_Int n,iHandle; + SANE_Byte buffer[0xffc0]; + + iHandle = pHWParams->iXferHandle; + + DBG(DBG_SCAN, "Hp44x0_park_to_home...."); + /* make shure the scaner is stoped */ + if ( !(Hp_rts_stop_moving(iHandle))) return SANE_FALSE; + + if (Hp35x0c_is_rewound(iHandle )){ + DBG(DBG_SCAN,"i'm home\n"); +/* if(read_reg(iHandle,MICROSWITCH) & 0x02) { + DBG(DBG_MSG,"i'm home\n");*/ + return(SANE_TRUE); + } else { + DBG(DBG_SCAN,"i must moving\n"); + memcpy(pHWParams->regs,Hp44x0_move_back,255); +/* + pHWParams->regs[0x32] = 0x80; + pHWParams->regs[0x33] = 0x81; + pHWParams->regs[0x34] = 0x10; + pHWParams->regs[0x35] = 0x10; + pHWParams->regs[0x36] = 0x21; *0x24;* + pHWParams->regs[0x39] = 0x02; * ??* + pHWParams->regs[0x3A] = 0x0e; + pHWParams->regs[0x60] = 0x40; + pHWParams->regs[0x61] = 0x1f; + pHWParams->regs[0x62] = 0x41; + pHWParams->regs[0x63] = 0x1f; + pHWParams->regs[0xb2] = 0x16; + pHWParams->regs[0xe2-1] = 0x17; * StepSize */ + #if 1 + if (pParams->optXPA) + pHWParams->regs[0x11] = pHWParams->regs[0x11] & 0xdf; + else + pHWParams->regs[0x11] = pHWParams->regs[0x11] | 0x02; + #endif + if ( !(Hp_rts_BulkWrite(iHandle,0x00,pHWParams->regs,0xb3,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_BulkWrite(iHandle,0xb4,pHWParams->regs+0xb3,0x3f,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xd3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_start_moving(iHandle))) return SANE_FALSE; + usleep(1000); + while (!Hp35x0c_is_rewound(iHandle) && +/* (Hp_rts_data_ready(iHandle,&n) ||*/ + Hp_rts_is_moving(iHandle) > 0) + { + /*if ( !(*/Hp_rts_data_ready(iHandle,&n);/*)) return SANE_FALSE;*/ + if (n) + { + if (n > (SANE_Word)sizeof(buffer)) + n = sizeof(buffer); + /*if ( !(*/Hp_rts_read_data(iHandle, n, buffer);/*)) return SANE_FALSE;*/ + } + else + { + usleep(10000); + } + } + return(Hp_rts_stop_moving(iHandle)); + } +} + +/****************************************************************************/ +SANE_Int Hp44x0_move_to_pos(THWParams *pHWParams, TScanParams *pParams){ +/* Moves scanner to position */ +/****************************************************************************/ + SANE_Int iHandle; + SANE_Word pos; + SANE_Int ypos; + SANE_Byte r; + + iHandle = pHWParams->iXferHandle; + + ypos = MM_TO_PIXEL(pHWParams->iTopLeftY,pParams->iDpi); + DBG(DBG_MSG,"Hp44x0_move_to_pos: %d dpi pParams->iY = %d pHWParams->iTopLeftY = %d ypos=%d \n", + pParams->iDpi,(SANE_Int)pParams->iY,pHWParams->iTopLeftY,ypos); + + if (pParams->iDpi == 600) + pos = ((pParams->iY) / 2 )+ ypos; + else + pos = (pParams->iY) + ypos; + pos = pos / 2; + +/* DBG(DBG_MSG,"Hp44x0_move_to_pos: move to pos %d (pixel) %x (hex)\n",pos,pos-1);*/ + + pHWParams->regs[0x33] = 0x81; /* 81 move fast, 82 lower */ + pHWParams->regs[0x36] = 0x29; /*29 fast; * 2C slow forward, 24 reverse */ + pHWParams->regs[0x3A] = 0x1b; /* 1b scan, 0e quick move */ + pHWParams->regs[0x60] = 0x01; + pHWParams->regs[0x61] = 0x00; + pHWParams->regs[0x62] = (pos+1) & 0xff; + pHWParams->regs[0x63] = ((pos+1) >> 8) & 0xff; + pHWParams->regs[0x65] = 0x00; /* switch to move only (no scan)*/ + pHWParams->regs[0xE2-1] = 0x07 ; /* Stepsize */ + if (pParams->optXPA) + pHWParams->regs[0x11] = pHWParams->regs[0x11] & 0xdf; + else + pHWParams->regs[0x11] = pHWParams->regs[0x11] | 0x02; + + usleep(10000); +#if 0 + printf("start_scan: start the moving!\n"); + Hp_rts_DumpHex(pHWParams->regs,252,16,SANE_TRUE); +#endif + if ( !(Hp_rts_BulkWrite(iHandle,0x00,pHWParams->regs,0xb3,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_BulkWrite(iHandle,0xb4,pHWParams->regs+0xb3,0x3f,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xd3,0x03))) return SANE_FALSE; + + if ( !(Hp_rts_start_moving(iHandle))) return SANE_FALSE; + usleep(1000); + + /*DBG(DBG_MSG,"move_to_pos: check moving\n");*/ + r = 0x08; + if ( Hp_rts_Check_Moving (iHandle)){ + while( r == 0x08){ + usleep(10000); + usleep(10000); + Hp_rts_RegRead(iHandle,MOVE_START_STOP, &r); + } + /*DBG(DBG_MSG,"move_to_pos: move finish\n");*/ + }else + { + DBG(DBG_ERR,"start_scan: Error, stop the moving!\n"); + Hp_rts_stop_moving(iHandle); + return(SANE_FALSE); + } + return(SANE_TRUE); +} + + +/****************************************************************************/ +SANE_Int Hp44x0_wait_for_WarmUp(SANE_Int iHandle,THWParams *pHWParams){ +/****************************************************************************/ + /* Reads 11 bytes and check the last one */ +SANE_Char i; +#ifdef DEBUG_L +SANE_Char c; +#endif + DBG(DBG_SCAN, "Hp44x0_wait_for_WarmUp....\n"); + /* we must here implement a wait loop for the lamp */ + if ( !(Hp_rts_BulkRead(iHandle,0x84,read_buffer,0x0b,SANE_TRUE))) return SANE_FALSE; +#ifdef DEBUG_L + c = read_buffer[0xa]; + DBG(DBG_MSG,"wait_for_WarmUp: read %x\n",c); + i = 1; +#else + i = 15; +#endif + if ( pHWParams->lamp_warm == SANE_FALSE ){ + while (i--){ + if ( !(Hp44x0_set_display( iHandle, i ))) return SANE_FALSE; + sleep(1); + } + pHWParams->lamp_warm = SANE_TRUE; + } + return( /*(read_buffer[0xa] & 0x60) == 0x60*/ SANE_TRUE ); +} + +/****************************************************************************/ +SANE_Bool Hp44x0_start_scan(THWParams *pHWParams, TScanParams *pParams, + TDataPipe *pDataPipe){ +/****************************************************************************/ +#ifdef DEBUG + SANE_Word lengtha1,lengtha2; +#endif + SANE_Int brightness, iHandle; + SANE_Int ires/*,result*/; + SANE_Word x1,x2,length; + + iHandle = pHWParams->iXferHandle; + brightness = 0; + + DBG(DBG_SCAN, "Hp44x0_start_scan....\n"); + DBG(DBG_MSG,"Hp44x0_start_scan: check resolution %d\n",pParams->iDpi); + for (ires = 0; Hp44x0c_resparms[ires].resolution && + Hp44x0c_resparms[ires].resolution != pParams->iDpi; ++ires); + if (Hp44x0c_resparms[ires].resolution == 0){ + DBG(DBG_MSG,"start_scan: did not found this resolution %d\n",pParams->iDpi); + return SANE_FALSE; + } + + DBG(DBG_MSG,"start_scan: Use ires entry %d (%ddpi) for the resolution %d dpi\n",ires, + Hp44x0c_resparms[ires].resolution, pParams->iDpi); + + memcpy(pHWParams->regs,Hp44x0_myinit33,254); /* CCD_Type 0*/ + + if ( !(Hp44x0_move_to_pos(pHWParams,pParams))) return SANE_FALSE; + x1 = pParams->iX; + x2 = pParams->iWidth + pParams->iX; + length = pParams->iLenght * 2; + pDataPipe->iScanned = pParams->iLenght; + DBG(DBG_MSG,"start_scan: calculate scandata x1 = %d; x2 = %d; lenght = %d\n",x1,x2,length); + + switch (pParams->mode) { + + case BLACK_WHITE: + DBG(DBG_MSG,"Copy 300 DPI BW Regs\n"); + if (pParams->oCCD_Type){ + DBG(DBG_MSG,"Use CCD_Type 1 Regs\n"); + memcpy(pHWParams->regs,Hp44x0_300_BW_1,254); /* CCD_Type 1*/ + }else{ + DBG(DBG_MSG,"Use CCD_Type 0 Regs\n"); + memcpy(pHWParams->regs,Hp44x0_myinit33,254); /* CCD_Type 0*/ + } + pHWParams->regs[0xD2 ]= 0x03; + pHWParams->regs[0xD3 ]= 0x05; + pHWParams->regs[0xE4 ]= 0x1c; + pHWParams->regs[0xE5 ]= 0x10; + pHWParams->regs[0xd5 ]= 0xab;/* ab gray */ + break; + + case GRAY: + DBG(DBG_MSG,"Copy 300 DPI Regs\n"); + brightness = 0; + if (pParams->oCCD_Type){ + DBG(DBG_MSG,"Use CCD_Type 1 Regs\n"); + memcpy(pHWParams->regs,Hp44x0_300_true_1_3,254); /* CCD_Type 1*/ + }else{ + DBG(DBG_MSG,"Use CCD_Type 0 Regs\n"); + memcpy(pHWParams->regs,Hp44x0_myinit33,254); /* CCD_Type 0*/ + } + if (pParams->iDpi == 600){ + DBG(DBG_MSG,"Patch to 600 DPI\n"); + Hp44x0_patch_regs(pHWParams,Hp44x0_patch_600); + brightness = 43; + } + pHWParams->regs[0xd5 ]= 0xab;/* ab gray */ +#if 1 + pHWParams->regs[0x08] = brightness + pParams->brightness; + pHWParams->regs[0x09] = brightness + pParams->brightness; + pHWParams->regs[0x0a] = brightness + pParams->brightness; +#endif + #if 1 + if (pParams->optXPA) + pHWParams->regs[0x11] = pHWParams->regs[0x11] & 0xdf; + else + pHWParams->regs[0x11] = pHWParams->regs[0x11] | 0x02; + #endif + break; + + case COLOR: + DBG(DBG_MSG,"Copy 300 DPI Regs\n"); + if (pParams->oCCD_Type) + memcpy(pHWParams->regs,Hp44x0_300_true_1_3,254); /* CCD_Type 1*/ + else + memcpy(pHWParams->regs,Hp44x0_myinit33,254); /* CCD_Type 0*/ + + if (pParams->iDpi == 200){ + DBG(DBG_MSG,"Patch to 200 DPI\n"); + memcpy(pHWParams->regs,Hp44x0_200_TRUE_1,254); /* CCD_Type 0*/ +/* Hp44x0_patch_regs(pHWParams,Hp44x0_200_TRUE_1);*/ + } + + if (pParams->iDpi == 300){ + DBG(DBG_MSG,"Patch to 300 DPI\n"); +/* memcpy(pHWParams->regs,Hp44x0_300_TRUE_1,254); * CCD_Type 1*/ + Hp44x0_patch_regs(pHWParams,Hp44x0_patch_600); + } + + if (pParams->iDpi == 600){ + DBG(DBG_MSG,"Patch to 600 DPI\n"); + Hp44x0_patch_regs(pHWParams,Hp44x0_patch_600); + } + pHWParams->regs[0xd5 ]= 0x0f;/* 0f color*/ + #if 1 + if (pParams->optXPA) + pHWParams->regs[0x11] = pHWParams->regs[0x11] & 0xdf; + else + pHWParams->regs[0x11] = pHWParams->regs[0x11] | 0x02; + #endif +#if 1 + pHWParams->regs[0x32 ]= Hp44x0c_resparms[ires].reg_32_value; + pHWParams->regs[0x33 ]= Hp44x0c_resparms[ires].reg_33_value; +#endif +#if DEBUG_L +/* pHWParams->regs[0xd5 ]= 0x1B;* 0f color*/ + /* horizon resolution */ + pHWParams->regs[0x10 ]= Hp44x0c_resparms[ires].reg_10_value; + pHWParams->regs[0x32 ]= Hp44x0c_resparms[ires].reg_32_value; + pHWParams->regs[0x33 ]= Hp44x0c_resparms[ires].reg_33_value; + pHWParams->regs[0x36 ]= Hp44x0c_resparms[ires].reg_36_value; + printf("pHWParams->regs[0xE1]= 0x%x to 0x%x\n",pHWParams->regs[0xE1],Hp44x0c_resparms[ires].step_size); + pHWParams->regs[0xE1]= Hp44x0c_resparms[ires].step_size; + #if 1 + printf("pHWParams->regs[0xE4]= 0x%x to 0x%x\n",pHWParams->regs[0xE4],Hp44x0c_resparms[ires].reg_E4_value); + pHWParams->regs[0xE4]= Hp44x0c_resparms[ires].reg_E4_value; + printf("pHWParams->regs[0xE5]= 0x%x to 0x%x\n",pHWParams->regs[0xE5],Hp44x0c_resparms[ires].reg_E5_value); + pHWParams->regs[0xE5]= Hp44x0c_resparms[ires].reg_E5_value; + #endif + #if 1 + /* color releated */ + pHWParams->regs[0x72 ]= Hp44x0c_resparms[ires].reg_72_value; + pHWParams->regs[0x73 ]= Hp44x0c_resparms[ires].reg_73_value; + pHWParams->regs[0x74 ]= Hp44x0c_resparms[ires].reg_74_value; + #endif + #if 1 + pHWParams->regs[0x11 ]= Hp44x0c_resparms[ires].reg_11_value; + pHWParams->regs[0x3a ]= 0x0e;/* for test*/ + /* pHWParams->regs[0xCC ]= Hp44x0c_resparms[ires].reg_CC_value; + pHWParams->regs[0xCD ]= Hp44x0c_resparms[ires].reg_CD_value; + pHWParams->regs[0xCE ]= Hp44x0c_resparms[ires].reg_CE_value; + pHWParams->regs[0xCF ]= Hp44x0c_resparms[ires].reg_CF_value; + pHWParams->regs[0xd0 ]= Hp44x0c_resparms[ires].reg_D0_value;*/ + /* pHWParams->regs[0xd7 ]= Hp44x0c_resparms[ires].reg_D7_value; + pHWParams->regs[0xC4 ]= Hp44x0c_resparms[ires].reg_C4_value; * colors ? * + pHWParams->regs[0xC5 ]= Hp44x0c_resparms[ires].reg_C5_value; * colors ? * + pHWParams->regs[0xd5 ]= Hp44x0c_resparms[ires].reg_D5_value; + + pHWParams->regs[0x35 ]= Hp44x0c_resparms[ires].reg_35_value; + pHWParams->regs[0x3A ]= Hp44x0c_resparms[ires].reg_3A_value; */ + #endif + /* vertical resolution */ + #if 0 + pHWParams->regs[0x3A ]= Hp44x0c_resparms[ires].reg_3A_value; + #endif +/* pHWParams->regs[0x02 ]= 0xbb; + pHWParams->regs[0x03 ]= 0x7d; + pHWParams->regs[0x04 ]= 0x3e; + pHWParams->regs[0x05 ]= 0xbb; + pHWParams->regs[0x06 ]= 0x7d; + pHWParams->regs[0x07 ]= 0x3e; + + pHWParams->regs[0x08 ]= 0x00; + pHWParams->regs[0x09 ]= 0x00; + pHWParams->regs[0x0a ]= 0x00;*/ + + pHWParams->regs[0xBF ]= Hp44x0c_resparms[ires].reg_BF_value; + pHWParams->regs[0xC0 ]= Hp44x0c_resparms[ires].reg_C0_value; + pHWParams->regs[0xC1 ]= Hp44x0c_resparms[ires].reg_C1_value; + pHWParams->regs[0xc2 ]= 0xff;/* for test*/ + pHWParams->regs[0xc3 ]= 0x00;/* for test*/ + pHWParams->regs[0xc4 ]= 0xf0;/* for test*/ + pHWParams->regs[0xc5 ]= 0x00;/* for test*/ + pHWParams->regs[0xc6 ]= 0x7f;/* for test*/ + pHWParams->regs[0xc7 ]= 0x0f;/* for test*/ +/* pHWParams->regs[0xc9 ]= 0xff;* for test*/ + pHWParams->regs[0xca ]= 0xf1;/* for test*/ + pHWParams->regs[0xcb ]= 0xff;/* for test*/ + pHWParams->regs[0xcc ]= 0x00;/* for test*/ + pHWParams->regs[0xcd ]= 0xf0;/* for test*/ + pHWParams->regs[0xce ]= 0xed;/* for test*/ + pHWParams->regs[0xcf ]= 0xef;/* for test*/ + pHWParams->regs[0xd0 ]= 0xe2;/* for test*/ +/* pHWParams->regs[0xd1 ]= Hp44x0c_resparms[ires].reg_D1_value; + pHWParams->regs[0xd2 ]= Hp44x0c_resparms[ires].reg_D2_value; + pHWParams->regs[0xd3 ]= Hp44x0c_resparms[ires].reg_D3_value;*/ + pHWParams->regs[0xd1 ]= 0x03;/* for test*/ + pHWParams->regs[0xd2 ]= 0x17;/* for test*/ + pHWParams->regs[0xd3 ]= 0x01;/* for test*/ + pHWParams->regs[0xd6 ]= 0x10;/* for test*/ + + pHWParams->regs[0x80 ]= 0x2b;/* for test*/ + pHWParams->regs[0x81 ]= 0x02;/* for test*/ + pHWParams->regs[0x82 ]= 0x2C;/* for test*/ + pHWParams->regs[0x83 ]= 0x02;/* for test*/ + pHWParams->regs[0x85 ]= 0x18;/* for test*/ + pHWParams->regs[0x86 ]= 0x1b;/* for test*/ + pHWParams->regs[0x87 ]= 0x30;/* for test*/ + pHWParams->regs[0x88 ]= 0x30;/* for test*/ + pHWParams->regs[0x89 ]= 0x2d;/* for test*/ + pHWParams->regs[0x8a ]= 0x02;/* for test*/ + pHWParams->regs[0x8d ]= 0x21;/* for test*/ + pHWParams->regs[0x8e ]= 0x60;/* for test*/ +#endif + break; + + default: + DBG(DBG_ERR, "Hp44x0_init_scan: Invalid parameter\n"); + return SANE_FALSE; + }/* switch */ + + + + +#if 0 + if (pParams->optXPA) + pHWParams->regs[0x11] = pHWParams->regs[0x11] & 0xdf; + else + pHWParams->regs[0x11] = pHWParams->regs[0x11] | 0x02; +#endif + +#if 0 + if (pParams->mode == COLOR) + pHWParams->regs[0xd5 ]= 0x0f;/* 0f color*/ + else + pHWParams->regs[0xd5 ]= 0xab;/* ab gray */ +#endif + + /* modify reg 60 + 61 */ + Hp_rts_set_noscan_distance(pHWParams->regs, 0x01 ); + /* modify reg 62 + 63 */ +#if 1 + Hp_rts_set_total_distance(pHWParams->regs, length+1 ); +#endif +#if 0 + Hp_rts_set_total_distance(pHWParams->regs, 0x02 ); +#endif + + pHWParams->regs[0x65]= 0x20; /* Schan mode on */ + + /* modify reg 66 + 67 */ + Hp_rts_set_scanline_start(pHWParams->regs, x1 ); + /* modify reg 6C + 6D */ + Hp_rts_set_scanline_end(pHWParams->regs, x2 ); + + #ifdef DEBUG + lengtha1 = 0; + lengtha2 = 0; + lengtha1 = pHWParams->regs[0x60]; + lengtha1 = lengtha1 + ((pHWParams->regs[0x61] <<8) & 0xFF00); + lengtha2 = pHWParams->regs[0x62]; + lengtha2 = lengtha2 + ((pHWParams->regs[0x63] <<8) & 0xFF00); + DBG(DBG_MSG,"start_scan: Init scan_region: dpi=%d iLenght=%d, iScanned=%d lenght=%d mode=%x xPDA=%x\n", + pParams->iDpi,pParams->iLenght,pDataPipe->iScanned,length,pParams->mode,pParams->optXPA); + #endif + +#if 0 + pHWParams->regs[0xDA-1]= pParams->intensity2; /* Lamp density */ +#endif + + +#if 0 /* do not use by graymode ! */ + pHWParams->regs[0x05] = 0x20 - pParams->GainR; + pHWParams->regs[0x06] = 0x20 - pParams->GainG; + pHWParams->regs[0x07] = 0x20 - pParams->GainB; +#endif + +#if 0 + pHWParams->regs[0x08] = 0x20 - pParams->GainR; + pHWParams->regs[0x09] = 0x20 - pParams->GainG; + pHWParams->regs[0x0a] = 0x20 - pParams->GainB; +#endif + +#if 0 /* moved to graymode */ + pHWParams->regs[0x08] = /*0x20 -*/ pParams->brightness; + pHWParams->regs[0x09] = /*0x20 -*/ pParams->brightness; + pHWParams->regs[0x0a] = /*0x20 -*/ pParams->brightness; +#endif +#if 0 + printf("start_scan: start the scanner!\n"); + Hp_rts_DumpHex(pHWParams->regs,255,16,SANE_TRUE); +#endif + + if ( !(Hp_rts_Set_double_reg(iHandle,0x10,pHWParams->regs[0x10],pHWParams->regs[0x11]))) return SANE_FALSE; + usleep(10000); + + if ( !(Hp_rts_BulkWrite(iHandle,0x00,pHWParams->regs,0xb3,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_BulkWrite(iHandle,0xb4,pHWParams->regs+0xb3,0x3f,SANE_TRUE))) return SANE_FALSE; +#if 0 + if (pParams->mode == BLACK_WHITE) + Hp_rts_RegWrite(iHandle,0xd3,0x17); + else + Hp_rts_RegWrite(iHandle,0xd3,0x03); +#endif +#if 0 + DBG(DBG_MSG,"pHWParams->regs[0xd3]= 0x%x to 0x%x\n", + pHWParams->regs[0xd3-1],pHWParams->regs[0xd3-1]); +#endif + if ( !(Hp_rts_RegWrite(iHandle,0xd3,pHWParams->regs[0xd3-1]))) return SANE_FALSE; + + if ( !(Hp_rts_start_moving(iHandle))) return SANE_FALSE; + usleep(10000); + /* wait for moving and check it */ + return(Hp_rts_Check_Moving (iHandle)); +} + + +/****************************************************************************/ +SANE_Bool Hp44x0_init_scan(THWParams *pHWParams, TScanParams *pParams, + TDataPipe *pDataPipe){ +/****************************************************************************/ + + SANE_Int iHandle; + SANE_Int ires; + + iHandle = pHWParams->iXferHandle; + DBG(DBG_MSG,"Hp44x0_init_scan: check resolution %d\n",pParams->iDpi); + for (ires = 0; Hp44x0c_resparms[ires].resolution && + Hp44x0c_resparms[ires].resolution != pParams->iDpi; ++ires); + if (Hp44x0c_resparms[ires].resolution == 0){ + DBG(DBG_MSG,"Hp44x0_init_scan: this resolution %d not found\n",pParams->iDpi); + return SANE_FALSE; + } + + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa7))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa0))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa7))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x01))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x01))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle, 0x12, 0xff, 0x20 ))) return SANE_FALSE; + if ( !(Hp_rts_Set_double_reg(iHandle, 0x14, 0xf8, 0x28 ))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + + memcpy(pHWParams->regs,Hp44x0_init_1,0xf4); + pHWParams->regs[0x10 ]= Hp44x0c_resparms[ires].reg_10_value; + pHWParams->regs[0x11 ]= Hp44x0c_resparms[ires].reg_11_value; + + if (pParams->optXPA) + pHWParams->regs[0x11] = pHWParams->regs[0x11] & 0xdf; + else + pHWParams->regs[0x11] = pHWParams->regs[0x11] | 0x02; + + if ( !(Hp_rts_Set_double_reg(iHandle,0x10,pHWParams->regs[0x10], + pHWParams->regs[0x11]))) return SANE_FALSE; + usleep(10000); + if ( !(Hp_rts_RegWrite(iHandle,0xd9,0x80))) return SANE_FALSE; + + #ifndef WITH_TSTBACKEND + if ( !(Hp44x0_wait_for_WarmUp(iHandle,pHWParams))) return SANE_FALSE; + #endif + + if ( !(Hp_rts_BulkWrite(iHandle,0x00,pHWParams->regs,0xb3,SANE_TRUE))) return SANE_FALSE; + if ( !(Hp_rts_BulkWrite(iHandle,0xb4,pHWParams->regs+0xb3,0x3f,SANE_TRUE))) return SANE_FALSE; + + if ( !(Hp_rts_RegWrite(iHandle,LAMP_INTENSITY,0xa7))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xd9,0x8d))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xd9,0xad))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + if ( !(Hp_rts_RegWrite(iHandle,0xb3,0x00))) return SANE_FALSE; + /* test_double_reg( LEDSTATUS, 0x28, 0x3f, 7 ); */ + usleep(10000); + if ( !(Hp_rts_Set_double_reg(iHandle,0x10,pHWParams->regs[0x10], + pHWParams->regs[0x11]))) return SANE_FALSE; + /* if ( !(test_double_reg( LEDSTATUS, 0x28, 0x3f, 8 ); */ + if ( !(Hp_rts_RegWrite(iHandle,0xd9,0xad))) return SANE_FALSE; + + return(Hp44x0_start_scan(pHWParams,pParams,pDataPipe)); +} + + + +/****************************************************************************/ +/* Lamp control functions */ +SANE_Bool Hp44x0_GetLamp(SANE_Int iHandle, SANE_Bool *pfLampIsOn) +/****************************************************************************/ +{ + SANE_Byte bData; + + DBG(DBG_SCAN, "Hp44x0_GetLamp....\n"); + if ( !(Hp_rts_RegRead(iHandle, LAMPREG, &bData))) return SANE_FALSE; + *pfLampIsOn = ((bData & 0x80) != 0); + return SANE_TRUE; +} + + +/****************************************************************************/ +SANE_Bool Hp44x0_SetLamp(SANE_Int iHandle, SANE_Bool fLampOn) +/****************************************************************************/ +{ + SANE_Byte bData; + + DBG(DBG_SCAN, "Hp44x0_SetLamp....\n"); + if ( !(Hp_rts_RegRead(iHandle, LAMPREG, &bData))) return SANE_FALSE; + if (fLampOn) { + if ( !(Hp_rts_RegWrite(iHandle, LAMPREG, bData | 0x80))) return SANE_FALSE; + } + else { + if ( !(Hp_rts_RegWrite(iHandle, LAMPREG, bData & ~0x80))) return SANE_FALSE; + } + return SANE_TRUE; +} + + +/****************************************************************************/ +SANE_Int +Hp44x0c_nvram_enable_controller(SANE_Int iHandle,SANE_Int enable) +/****************************************************************************/ +{ + SANE_Byte r; + + DBG(DBG_SCAN, "Hp44x0c_nvram_enable_controller....\n"); + if ( !(Hp_rts_RegRead(iHandle, 0x1d, &r))) return SANE_FALSE; + if (enable) + r |= 1; + else + r &= ~1; + return Hp_rts_RegWrite(iHandle,0x1d, r); + +} + diff -urN sane-backends-1.0.15.orig/backend/hp_rts_44x0c.h sane-backends-1.0.15/backend/hp_rts_44x0c.h --- sane-backends-1.0.15.orig/backend/hp_rts_44x0c.h 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts_44x0c.h 2005-07-26 13:25:11.159834648 -0500 @@ -0,0 +1,485 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP4400C, HP4470C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Core HP44x0c functions. +*/ + + +#ifndef _HP_RTS_HP44x0C_H_ +#define _HP_RTS_HP44x0C_H_ + +#include + +#define XFER_BUF_SIZE 0xFF00 + + +#define HW_PIXELS 2000 /* number of pixels supported by hardware */ +#define HW_DPI 300 /* horizontal resolution of hardware */ +#define HW_LPI 300 /* vertical resolution of hardware */ + +/* thise rts8891 registers are known */ +#define LEDSTATUS 0x10 +#define LIGHT_SOURCE 0x11 +#define TAP 0x14 +#define LCD_CONTROL1 0x20 +#define LCD_CONTROL2 0x21 +#define LCD_CONTROL3 0x22 +#define BUTTON_1 0x25 +#define BUTTON_2 0x1a +#define MICROSWITCH 0x1d +#define MOVEMENT_DIRECTION 0x36 +#define SCAN_OR_QUICK_MOVE 0x3a +#define CHECK_SCANNER_LINKED 0xb0 +#define MAINBOARD_ID 0xb1 +#define MOVEMENT_REG_1 0xb2 +#define MOVE_START_STOP 0xb3 +#define LAMPREG 0xd9 +#define LAMP_INTENSITY 0xda +#define STEP_SIZE 0xe1 + +struct Hp44x0c_resolution_parameters +{ + SANE_Int resolution; + SANE_Byte reg_10_value; + SANE_Byte reg_11_value; + SANE_Byte reg_32_value; + SANE_Byte reg_33_value; + SANE_Byte reg_35_value; + SANE_Byte reg_36_value; + SANE_Byte reg_3A_value; + SANE_Byte reg_72_value; + SANE_Byte reg_73_value; + SANE_Byte reg_74_value; + SANE_Byte reg_BF_value; + SANE_Byte reg_C0_value; + SANE_Byte reg_C1_value; + SANE_Byte reg_C4_value; + SANE_Byte reg_C5_value; + SANE_Byte reg_CC_value; + SANE_Byte reg_CD_value; + SANE_Byte reg_CE_value; + SANE_Byte reg_CF_value; + SANE_Byte reg_D0_value; + SANE_Byte reg_D1_value; + SANE_Byte reg_D2_value; + SANE_Byte reg_D3_value; + SANE_Byte reg_D5_value; + SANE_Byte reg_D7_value; + SANE_Byte step_size; + SANE_Byte reg_E4_value; + SANE_Byte reg_E5_value; +}; + +static struct Hp44x0c_resolution_parameters Hp44x0c_resparms[] = +{ +/*res. 10 11 32 33 35 36 3a 72 73 74 bf c0 c1 c5 cb cc cd ce cf d0 d1 d2 d3 d5 d7 Step e4 e5*/ +/* 0x00,0x03,0x45, 0x43 */ +{600,0x28,0x3b,0x80,0x82,0x1b,0x2C,0x1b,0x3a,0x15,0x62,0x00,0xff,0x0f,0xf8,0x07,0x80,0xff,0xf2,0xf4,0xe7,0x08,0x0e,0x10,0x0f,0x52,0x01,0x56,0x01}, +{300,0x20,0x3b,0x80,0x82,0x0e,0x22,0x0e,0xe1,0x14,0x18,0xff,0x0f,0xf0,0x00,0x00,0xf0,0xff,0xf5,0xf7,0xea,0x0b,0x03,0x05,0xab,0xf6,0x01,0x56,0x01}, +{200,0x20,0x3b,0x00,0x03,0x0e,0x22,0x0e,0xe1,0x14,0x18,0xff,0x0f,0xf0,0x00,0x00,0xf0,0xff,0xf5,0xf7,0xea,0x0b,0x03,0x05,0xab,0xf6,0x01,0xbd,0x0a}, +{150,0x20,0x3f,0x80,0x81,0x1b,0x29,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01}, +{0, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + + + +SANE_Byte Hp44x0_switch_on_regs[] = { +/*0 1 2 3 4 5 6 7 8 9 a b c d e f*/ +0xe5,0x41,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x0a,0x0a,0x0a,0x70,0x00,0x00,0x00,0x00, +/*10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f*/ +0x28,0x28,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +/*20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f*/ +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f*/ +0x00,0x00,0x00,0x00,0x10,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f*/ +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f*/ +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x3f,0x80,0x68,0x00, +/*90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f*/ +0x00,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af*/ +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf*/ +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +/*c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf*/ +0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x0e,0x00,0x00,0xf0,0xff,0xf5,0xf7, +/*d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df*/ +0xea,0x0b,0x03,0x05,0x86,0x1b,0x30,0xf6,0xad,0x27,0x00,0x00,0x00,0x00,0x00,0x00, +/*e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef*/ +0x00,0x01,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*f0 f1 f2*/ +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_move_back[] = { +0xf5,0x41,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x10,0x10,0x10,0x70,0x00,0x00,0x00,0x00, +0x20,0x28,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x80,0x81,0x10,0x10,0x24,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x40,0x1f,0x41,0x1f,0x01,0x20,0x64,0x00,0x00,0x00,0x00,0x00,0xc8,0x00,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +0x32,0x00,0x33,0x00,0x00,0x00,0x06,0x00,0x06,0x34,0x00,0xff,0x3f,0x80,0x68,0x00, +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x86,0x6b,0x00,0x00,0x80,0x27,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x17,0x0d,0x06,0xf9,0x00,0x53,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_init_1[] = { +0xe5,0x41,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x0a,0x0a,0x0a,0x70,0x00,0x00,0x00,0x00, +0x60,0x3b,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +0x3a,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x68,0x00, +0x00,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x86,0x1b,0x00,0xff,0x00,0x27,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_init_5[] = { +0xe5,0x41,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x0a,0x0a,0x0a,0x70,0x00,0x00,0x00,0x00, +0x28,0x28,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x68,0x00, +0x00,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x0e,0x00,0x00,0xf0,0xff,0xf5,0xf7, +0xea,0x0b,0x03,0x05,0x86,0x1b,0x30,0xf6,0x80,0x27,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_myinit33[] = { +/*0 1 2 3 4 5 6 7 8 9 a b c d e f*/ +0xe5,0x41,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x10,0x10,0x10,0x70,0x00,0x00,0x00,0x00, +/*10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f*/ +0x20,0x3f,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +/*20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f*/ +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f*/ +0x00,0x00,0x80,0x81,0x10,0x1b,0x29,0x00,0x00,0x02,0x1b,0x00,0x00,0x00,0x00,0x00, +/*40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f*/ +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f*/ +0x12,0x00,0xc6,0x00,0x01,0x20,0x2c,0x01,0x00,0x00,0x00,0x00,0xdc,0x05,0x00,0x00, +/*70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f*/ +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +/*80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f*/ +0x32,0x00,0x33,0x00,0x00,0x00,0x06,0x00,0x06,0x34,0x00,0xff,0x3f,0x80,0x68,0x00, +/*90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f*/ +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af*/ +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf*/ +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +/*c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf*/ +0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x0e,0x00,0x00,0xf0,0xff,0xf5,0xf7, +/*d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df*/ +0xea,0x0b,0x03,0x05,0x86,0xab,0x30,0xf6,0xad,0xa7,0x00,0x00,0x00,0x00,0x00,0x00, +/*e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef*/ +0x00,0x01,0x00,0x00,0x1c,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*f0 f1 f2*/ +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_300_true_1_3[] = { +0xe5,0x41,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x10,0x10,0x10,0x70,0x00,0x00,0x00,0x00, +0x20,0x3b,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x80,0x81,0x10,0x1b,0x29,0x00,0x00,0x02,0x1b,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x12,0x00,0xc6,0x00,0x01,0x20,0x2c,0x01,0x00,0x00,0x00,0x00,0xdc,0x05,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +0x2b,0x02,0x2c,0x02,0x00,0x18,0x1b,0x30,0x30,0x2d,0x02,0xff,0x3f,0x21,0x60,0x00, +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +0x0f,0x00,0x00,0xf0,0xff,0xff,0x0f,0x00,0xff,0xf1,0xff,0x00,0xf0,0xff,0xf5,0xf7, +0xea,0x0b,0x03,0x05,0x86,0xab,0x10,0xf6,0xad,0xa7,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x00,0x1c,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_300_BW_1[] = { +/*0 1 2 3 4 5 6 7 8 9 a b c d e f*/ +0xe5,0x41,0x82,0x86,0x81,0x82,0x86,0x81,0x07,0x05,0x0f,0x70,0x00,0x00,0x00,0x00, +/*10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f*/ +0x20,0x3f,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +/*20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f*/ +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f*/ +0x00,0x00,0x80,0x81,0x10,0x1b,0x29,0x00,0x00,0x02,0x1b,0x00,0x00,0x00,0x00,0x00, +/*0x00,0x00,0x20,0x83,0x10,0x0e,0x2c,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00,*/ +/*40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f*/ +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f*/ +0x01,0x00,0x43,0x00,0x01,0x20,0x5e,0x00,0x00,0x00,0x00,0x00,0x54,0x0a,0x00,0x00, +/*70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f*/ +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +/*80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f*/ +0x32,0x00,0x33,0x00,0x00,0x00,0x06,0x00,0x06,0x34,0x00,0xff,0x3f,0x00,0x60,0x00, +/*90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f*/ +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af*/ +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf*/ +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +/*c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf*/ +0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x0e,0x00,0x00,0xf0,0xff,0xf5,0xf7, +/*d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df*/ +0xea,0x0b,0x17,0x01,0x86,0x0f,0x30,0x52,0xad,0xa7,0x00,0x00,0x00,0x00,0x00,0x00, +/*e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef*/ +0x00,0x05,0x00,0x00,0xc9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*f0 f1 f2*/ +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_200_BW_1[] = { +0xe5,0x41,0x82,0x86,0x81,0x82,0x86,0x81,0x07,0x05,0x0f,0x70,0x00,0x00,0x00,0x00, +0x20,0x3f,0xff,0x20,0xf8,0x28,0x01,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +0x3a,0xf2,0x00,0x80,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x20,0x83,0x10,0x0e,0x2c,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00, +0x2c,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x2d,0x00,0xef,0x0d,0x01,0x20,0x5e,0x00,0x00,0x00,0x00,0x00,0x54,0x0a,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +0x2b,0x02,0x2c,0x02,0x00,0x18,0x1b,0x30,0x30,0x2d,0x02,0xff,0x3f,0xef,0x60,0x00, +0x18,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x0e,0x00,0x00,0xf0,0xff,0xf5,0xf7, +0xea,0x0b,0x17,0x01,0x86,0x0f,0x30,0x52,0xad,0xa7,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x56,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00}; + +SANE_Byte Hp44x0_200_BW_2[] = { +0xe5,0x41,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, +0x20,0x3f,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x03,0x10,0x0e,0x22,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x00,0x02,0x00,0x01,0x20,0x0d,0x00,0x00,0x00,0x00,0x00,0xfb,0x02,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +0x32,0x00,0x33,0x00,0x00,0x00,0x06,0x00,0x06,0x34,0x00,0xff,0x3f,0x00,0x60,0x00, +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, +0x0f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x0e,0x00,0x00,0xf0,0xff,0xf5,0xf7, +0xea,0x0b,0x17,0x01,0x86,0x0f,0x30,0x52,0xad,0xa7,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x56,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + +SANE_Byte Hp44x0_200_TRUE_1[] = { +/*0 1 2 3 4 5 6 7 8 9 a b c d e f*/ +0xe5,0x41,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, +/*10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f*/ +0x20,0x3b,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +/*20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f*/ +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f*/ +0x00,0x00,0x00,0x03,0x10,0x0e,0x22,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x00,0x02,0x00,0x01,0x20,0x15,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +0x2b,0x02,0x2c,0x02,0x00,0x18,0x1b,0x30,0x30,0x2d,0x02,0xff,0x3f,0x21,0x60,0x00, +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0x0f,0xff,0x00,0xf0,0x00,0xff,0x0f,0xff,0xff,0xf1,0xff,0x00,0xf0,0xed,0xef, +0xe2,0x03,0x17,0x01,0x86,0x0f,0x10,0x52,0xad,0xa7,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x07,0x00,0x00,0x56,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + +SANE_Byte Hp44x0_300_TRUE_1[] = { +/*0 1 2 3 4 5 6 7 8 9 a b c d e f*/ +0xe5,0x41,0xbb,0x7d,0x3e,0xbb,0x7d,0x3e,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00, +/*10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f*/ +0x20,0x3b,0xff,0x20,0xf8,0x28,0x07,0x00,0xff,0x00,0x00,0x00,0x00,0x20,0x00,0x00, +/*20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f*/ +0x3a,0xf2,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f*/ +0x00,0x00,0x00,0x03,0x10,0x0e,0x22,0x00,0x00,0x02,0x0e,0x00,0x00,0x00,0x00,0x00, +0x20,0x00,0x00,0x00,0x8c,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x00,0x02,0x00,0x01,0x20,0x15,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00, +0x00,0x00,0xe1,0x14,0x18,0x15,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00, +0x2b,0x02,0x2c,0x02,0x00,0x18,0x1b,0x30,0x30,0x2d,0x02,0xff,0x3f,0x21,0x60,0x00, +0x1c,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xcc,0x27,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf*/ +0x00,0x00,0x02, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf*/ +0x00,0xff,0x0f,0xff,0x00,0xf0,0x00,0xff,0x0f,0xff,0xff,0xf1,0xff,0x00,0xf0,0xed, +/*d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df*/ +0xef,0xe2,0x03,0x17,0x01,0x86,0x0f,0x10,0x52,0xad,0xa7,0x00,0x00,0x00,0x00,0x00, +/*e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef*/ +0x00,0x00,0x07,0x00,0x00,0x56,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*f0 f1 f2*/ +0x00,0x00,0x00}; + +/* CCD CHANGES to CCD1 80,81,82,83,85,86,87,88,89,8a,8d,8e,c2,c3,c6,c7,c8,c9,ca,d6 */ + + +SANE_Byte Hp44x0_patch_2[] = { +0x12,0x8,0x16,0x8,0x1d,0x20,0xb0,0x0,0xce,0xe0,0xd4,0x86, +0xd5,0x1b,0xd6,0x0,0xd7,0xff,0xd8,0x0,0xd9,0x27,0xda,0x0, +0xe1,0x1,0xe2,0x0,0xe4,0x14,0xe5,0x0,0xf4,0x0,0xf5,0x0, +0xf6,0x0,0xf7,0x0,0xf8,0x0,0xf9,0x0,0xfa,0x0,0xfb,0x0, +0xfc,0x0,0xfd,0x0,0xfe,0x0,0x0,0x0}; + +SANE_Byte Hp44x0_patch_3[] = { +0x1d,0x20,0xb0,0x0,0xd4,0x86,0xd5,0x1b,0xd6,0x0,0xd7,0xff, +0xd8,0x0,0xd9,0x27,0xda,0x0,0xe1,0x1,0xe2,0x0,0xe4,0x14, +0xe5,0x0,0xf4,0x0,0xf7,0x0,0xf8,0x0,0xf9,0x0,0xfa,0x0, +0xfb,0x0,0xfc,0x0,0xfd,0x0,0xfe,0x0,0x0,0x0}; + +SANE_Byte Hp44x0_patch_4[] = { +0x10,0x28,0x11,0x28,0x12,0xff,0x14,0xf8,0x15,0x28,0x16,0x7, +0x18,0xff,0x1a,0x0,0x1d,0x20,0x23,0xff,0x24,0xff,0x72,0xe1, +0x73,0x14,0x74,0x18,0x75,0x15,0xb0,0x0,0xbf,0xff,0xc0,0xf, +0xc2,0xff,0xc3,0xff,0xc4,0xff,0xc5,0xff,0xc6,0xff,0xc7,0xff, +0xc9,0xe,0xcc,0xf0,0xcd,0xff,0xce,0xf5,0xcf,0xf7,0xd0,0xea, +0xd1,0xb,0xd2,0x3,0xd3,0x5,0xd4,0x86,0xd5,0x1b,0xd6,0x30, +0xd7,0xf6,0xd8,0x80,0xd9,0x27,0xda,0x0,0xe1,0x1,0xe2,0x0, +0xe4,0x14,0xe5,0x0,0xf7,0x0,0xf8,0x0,0xf9,0x0,0xfa,0x0, +0xfb,0x0,0xfc,0x0,0xfd,0x0,0xfe,0x0,0x0,0x0}; + +SANE_Byte Hp44x0_patch_600[] = { +0x10,0x28, 0x11,0x3b, 0x36,0x2c, +0xe4,0xbd, 0xe5,0x0a, + +0x72,0x3a, 0x73,0x15, 0x74,0x62, +0xbf,0xf8, 0xc0,0x7f, +0xc4,0x00, 0xc5,0xf8, +0xcb,0x07, 0xcc,0x80, 0xce,0xf2, +0xcf,0xf4, 0xd0,0xe7, 0xd1,0x08, 0xd2,0x0e, 0xd3,0x10, +0xd5,0x0f, 0xd7,0x52, +0x60,0x01, 0x62,0x02, 0x66,0x2b, 0x67,0x00, 0x6c,0x19, 0x6d,0x03 +}; + +SANE_Byte callibration_buffer[0x818+4]; +SANE_Byte registers[0xff]; +SANE_Byte read_buffer[0xff]; + +SANE_Bool Hp44x0_Wakeup(THWParams *pHWParams,TScanParams *pParams); +SANE_Bool Hp44x0_Down(SANE_Int iHandle); + +SANE_Bool Hp44x0_patch_and_send_values (SANE_Int iHandle, SANE_Byte *my_values); +void Hp44x0_patch_regs (THWParams *pHWParams,SANE_Byte *my_values); +SANE_Bool Hp44x0_set_display ( SANE_Int iHandle, SANE_Byte val ); + +SANE_Bool Hp44x0_write_cal_bytes (THWParams *pHWParams, SANE_Byte b ); +SANE_Bool Hp44x0_cal_scanner (THWParams *pHWParams, TScanParams *pParams); +SANE_Int Hp44x0_park_to_home (THWParams *pHWParams,TScanParams *pParams); + +SANE_Int Hp44x0_move_to_pos (THWParams *pHWParams, TScanParams *pParams); +SANE_Int Hp44x0_wait_for_WarmUp (SANE_Int iHandle, THWParams *pHWParams); +SANE_Bool Hp44x0_start_scan (THWParams *pHWParams,TScanParams *pParams, + TDataPipe *pDataPipe); +SANE_Bool Hp44x0_init_scan (THWParams *pHWParams, TScanParams *pParams, + TDataPipe *pDataPipe); +SANE_Bool Hp44x0_GetLamp (SANE_Int iHandle, SANE_Bool *pfLampIsOn); +SANE_Bool Hp44x0_SetLamp (SANE_Int iHandle, SANE_Bool fLampOn); + +SANE_Int Hp44x0c_nvram_enable_controller(SANE_Int iHandle,SANE_Int enable); + + +#if 0 +void _UnscrambleLine (SANE_Handle h,SANE_Byte *pabLine, + SANE_Byte *pabRed, SANE_Byte *pabGrn, SANE_Byte *pabBlu, + SANE_Int iWidth, SANE_Bool iReversedHead); + +#endif + +#endif /* NO _HP_RTS__H_ */ + diff -urN sane-backends-1.0.15.orig/backend/hp_rts_xfer.c sane-backends-1.0.15/backend/hp_rts_xfer.c --- sane-backends-1.0.15.orig/backend/hp_rts_xfer.c 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts_xfer.c 2005-07-26 13:25:11.162834192 -0500 @@ -0,0 +1,1177 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP4400C, HP4470C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Provides a simple interface to read and write data from the scanner, + without any knowledge whether it's a parallel or USB scanner + + enable DEDUG output: + use a nomal shell (konsole) and type + export SANE_DEBUG_HP_RTS88XX=32 + export XSANE_DEBUG=100 + xsane +*/ + + +#include /* read, open, write */ +#include /* open */ +#include /* printf */ +#include /* better error reports */ +#include /* better error reports */ +#include /* malloc(), free() on FreeBSD */ +#include "../include/sane/sanei_usb.h" + +#include "hp_rts_xfer.h" + +#ifdef STANDALONE + #include "../include/sane/config.h" + #include "hp_rts_35x0c.h" + #include "hp_rts_44x0c.h" +#endif + + +static SANE_Int _fDeviceFound; +static TScannerModel *_pModel; +static TDevListEntry *_pFirstSaneDev = 0; +static SANE_Int iNumSaneDev = 0; +static const SANE_Device **_pSaneDevList = 0; + +/* list of supported models */ +TScannerModel ScannerModels[] = { + {"Hewlett-Packard", "UnknownModel", 0x3F0, 0x0000, eUnknownModel}, + {"Hewlett-Packard", "ScanJet 3500C", 0x3F0, 0x2205, eHp3500c}, /*RTS8801C2*/ +#ifdef DEBUG_HP3500 + {"Hewlett-Packard", "ScanJet 3530C", 0x3F0, 0x0805, eHp3530c}, /*RTS8801C2*/ +#else + {"Hewlett-Packard", "ScanJet 3530C", 0x3F0, 0x2005, eHp3530c}, /*RTS8801C2*/ +#endif + {"Hewlett-Packard", "ScanJet 3570C", 0x3F0, 0x2005, eHp3570c}, /*RTS8801C2 is the same as 3500 */ + {"Hewlett-Packard", "ScanJet 4400C", 0x3F0, 0x0705, eHp4400c}, /*RTS8891*/ + {"Hewlett-Packard", "ScanJet 4470C", 0x3F0, 0x0805, eHp4470c}, /*RTS8891*/ +#ifdef ENABLE_VI8920 + {"Visioneer", "Onetouch 8920 USB", 0x0461, 0x0371, eVi8920}, /*RTS8801C2-004*/ +#endif +#if 0 + {"Visioneer", "Onetouch 8900 USB", 0x0461, 0x0371, eVi8900}, /*RTS8801C2-004*/ + {"Visioneer", "Onetouch 8700 USB", 0x0461, 0x0371, eVi8700}, /*RTS8801C2-004*/ + {"Visioneer", "OneTouch 5800 USB", 0x04a7, 0x0226, eVi5800}, /*RTS8801C2-004*/ + {"Visioneer", "OneTouch 5300 USB", 0x04a7, 0x0226, eVi5300}, /*RTS8801C2-004*/ + {"Visioneer", "OneTouch 4800 USB", 0x04a7, 0x0224, eVi4800}, /*RTS8801B-0001*/ + {"Vantas", "3000", 0x04a7, 0x0224, eVa3000}, /*RTS8801B-0001*/ + {"Microtek", "Scanport 3000", 0x04a7, 0x0224, eMi3000}, /*RTS8801B-0001*/ + {"Plustek", "OpticPro S6", 0x0???, 0x????, ePlS6}, /*RTS8801D*/ + {"Prolink", "Winscan Pro 2448U", 0x06dc, 0x0014, ePrlS6}, /*RTS8801C2-006*/ +#endif +/* last entry all zeros */ + {0, 0, 0, 0, 0} +}; + + +/****************************************************************************/ +/* utility function to show a hexdump of a buffer */ +void Hp_rts_DumpHex(SANE_Byte *pabData, SANE_Int iLen, SANE_Int iWidth, SANE_Int withLf) +/****************************************************************************/ +{ + SANE_Int i; + + printf(" "); + for (i = 0; i < iWidth ; i++) { + printf(" %02X", i); + } + for (i = 0; i < iLen; i++) { + if ((i % iWidth) == 0) { + if (withLf) printf("\n"); + printf("%04X", i); + } + printf(" %02X", pabData[i]); + } + if (withLf) printf("\n"); +} + +/****************************************************************************/ +/* utility function to show a bit dump of a byte */ +void Hp_rts_DumpBits(SANE_Byte reg, SANE_Byte pabData) +/****************************************************************************/ +{ + SANE_Int i = 0; + + printf("RegisterDump : Register %x will be set to the bits ", reg); + for (i = 0; i < 8; i++) { + if (pabData & 0x80) + printf("1"); + else + printf("0"); + if (i==3) printf(" "); + pabData = pabData << 1; + } + printf("\n"); +} + +/**************************************************************************** + Hp_rts_MatchUsbDevice + ============== + Matches a given USB vendor and product id against a list of + supported scanners. + + IN iVendor USB vendor ID + iProduct USB product ID + OUT *ppModel Pointer to TScannerModel structure + + Returns SANE_TRUE if a matching USB scanner was found +*/ +SANE_Bool Hp_rts_MatchUsbDevice(SANE_Int iVendor, SANE_Int iProduct, TScannerModel **ppModel) +/****************************************************************************/ +{ + TScannerModel *pModels = ScannerModels; + + DBG(DBG_MSG,"Hp_rts_MatchUsbDevice :Matching USB device 0x%04X-0x%04X ... \n", iVendor, iProduct); + while (pModels->pszName != NULL) + { + if ((pModels->iVendor == iVendor) && (pModels->iProduct == iProduct)) + { + DBG(DBG_MSG,"Hp_rts_MatchUsbDevice : found %s %s\n", pModels->pszVendor, pModels->pszName); + *ppModel = pModels; + return SANE_TRUE; + } + /* next model to match */ + pModels++; + } + DBG(DBG_MSG,"Hp_rts_MatchUsbDevice : nothing found\n"); + return SANE_FALSE; +} + + + +/************************************************************************ + Public functions +************************************************************************/ + + +/*static TFnReportDevice *_pfnReportDevice;*/ +static TScannerModel *_pModel; + +/****************************************************************************/ +static int +_ReportDevice (TScannerModel * pModel, SANE_Char *pszDeviceName) +/****************************************************************************/ +{ + TDevListEntry *pNew, *pDev; +#if 0 + DBG (DBG_MSG, "_ReportDevice '%s'", pszDeviceName); +#endif + pNew = malloc (sizeof (TDevListEntry)); + if (!pNew) + { + DBG (DBG_ERR, "_ReportDevice: no mem\n"); + return -1; + } + + /* add new element to the end of the list */ + if (_pFirstSaneDev == 0) + { + _pFirstSaneDev = pNew; + } + else + { + for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext) + { + ; + } + pDev->pNext = pNew; + } + + /* fill in new element */ + pNew->pNext = 0; + pNew->dev.name = strdup (pszDeviceName); + pNew->dev.vendor = pModel->pszVendor; + pNew->dev.model = pModel->pszName; + pNew->dev.type = "flatbed scanner"; + + iNumSaneDev++; + + return 0; +} + +/* callback for sanei_usb_attach_matching_devices */ +/****************************************************************************/ +static SANE_Status +_AttachUsb (SANE_String_Const devname) +/****************************************************************************/ +{ + DBG (DBG_MSG, "_AttachUsb: found %s", devname); + + _fDeviceFound ++; + _ReportDevice (_pModel, (SANE_Char *) devname); +/* _pfnReportDevice (_pModel, (SANE_Char *) devname);*/ + + return SANE_STATUS_GOOD; +} + +/**************************************************************************** + Hp_rts_XferInit + =============== + Probes all registered modules to see if it can be used to access a + compatible scanner. The first module that supports the scanner is + used. + + Returns the handle to a TXferDev structure which was used to find the + scanner, returns 0 or negative otherwise. +*/ +SANE_Int Hp_rts_XferInit(/*EScannerModel *peModel*/void) +/****************************************************************************/ +{ + TScannerModel *pModels = ScannerModels; + + DBG (DBG_MSG,"Hp_rts_XferInit ....\n"); + + sanei_usb_init (); + _fDeviceFound = 0; +/* _pfnReportDevice = _ReportDevice;*/ + + /* loop over all scanner models */ + while (pModels->pszName != NULL) + { + DBG (DBG_MSG, "Looking for %s...", pModels->pszName); + _pModel = pModels; + if (sanei_usb_find_devices ((SANE_Int) pModels->iVendor, + (SANE_Int) pModels->iProduct, + _AttachUsb) != SANE_STATUS_GOOD) + { + DBG (DBG_ERR, "Error invoking sanei_usb_find_devices\n"); + return SANE_FALSE; + } +#if 0 + DBG(DBG_MSG, "Hp_rts_XferInit: found device "); + if (pModels->eModel != eUnknownModel){ + _AttachUsb("libusb:001:002*"); + } +#endif + DBG (DBG_MSG, "\n"); + pModels++; + } + + if (_fDeviceFound) + return SANE_TRUE; + else + return SANE_FALSE; +} + + +/****************************************************************************/ +SANE_Int Hp_rts_XferOpen (SANE_String_Const devname,EScannerModel *peModel) +/****************************************************************************/ +{ + SANE_Status status; + SANE_Word vendor, product; + int fd; + TScannerModel *pModel; + + DBG (DBG_MSG, "Hp_rts_XferOpen, trying to open %s...\n", devname); + + status = sanei_usb_open (devname, &fd); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_ERR, "Hp_rts_XferOpen: sanei_usb_open failed %s\n", devname); + return -1; + } +#if 0 + DBG (DBG_MSG, "Hp_rts_XferOpen, trying to get sanei_usb_get_vendor_product for fd %d\n", (int) fd); +#endif + status = sanei_usb_get_vendor_product (fd, &vendor, &product); + if (status == SANE_STATUS_GOOD) + { +#if 0 + DBG (DBG_MSG, "Hp_rts_XferOpen, trying Hp_rts_MatchUsbDevice\n"); +#endif + if (Hp_rts_MatchUsbDevice (vendor, product, &pModel)== SANE_TRUE) + { +#if 0 + DBG (DBG_MSG, "pModel->eModel = %d\n",pModel->eModel); +#endif + *peModel = pModel->eModel; + }else + { + DBG (DBG_ERR, "Hp_rts_XferOpen: Hp_rts_MatchUsbDevice failed %s\n", devname); + sanei_usb_close (fd); + return -1; + } + }else + { + DBG (DBG_ERR, "Hp_rts_XferOpen: sanei_usb_get_vendor_product failed %s\n", devname); + sanei_usb_close (fd); + return -1; + } +#if 0 + DBG (DBG_MSG, "handle = %d\n", (int) fd); +#endif + return fd; +} + +/****************************************************************************/ +SANE_Int Hp_rts_XferExit(SANE_Int iHandle) +/****************************************************************************/ +{ + + if (iHandle < 0) { + return(-1); + } + /* close usb device */ + sanei_usb_close (iHandle); + return SANE_TRUE; +} + + +/****************************************************************************/ +SANE_Int Hp_rts_BulkWrite (SANE_Int iHandle, SANE_Byte reg, SANE_Byte *pabBuf, + SANE_Int iSize, SANE_Int wHeader) +/****************************************************************************/ +{ + static SANE_Byte init[]={0x88,0,0x00,0x01}; + SANE_Char *request; /* Compose a request string. */ + SANE_Int size; + +#ifdef USBDEBUG + DBG(DBG_USB,"UsbWriteBulk ...\n"); +#endif + if (iHandle == -1) { + return(SANE_FALSE); + } + + if (wHeader){ + request=malloc(iSize + 4); /* Compose a request string. */ + init[1]=(SANE_Byte)reg; + init[2]=(SANE_Byte)(iSize>>8); /* split count over these bytes.*/ + init[3]=(SANE_Byte)iSize; + memcpy(request,init,4); /* stick them together */ + memcpy(request+4,pabBuf,iSize); + size = iSize + 4; +#ifdef USBDEBUG + SANE_Byte *tmpw=request; + SANE_Int tmp_size=size; + fprintf(stderr,"WB1 transfer type=bulk size=%d dir=OUT\n",tmp_size); + while(tmp_size--) fprintf(stderr,"%02hhx ",*tmpw++); + fprintf(stderr,"\n"); +#endif + if (sanei_usb_write_bulk(iHandle, request,&size) != SANE_STATUS_GOOD) { + DBG(DBG_ERR, "UsbWriteBulk: ERROR: Bulk write failed\n"); + return SANE_FALSE; + } + free(request); /* clean up */ + }else + { +#ifdef USBDEBUG + SANE_Byte *tmpw=pabBuf; + SANE_Int tmp_size=iSize; + fprintf(stderr,"WB2 transfer type=bulk size=%d dir=OUT\n",tmp_size); + while(tmp_size--) fprintf(stderr,"%02hhx ",*tmpw++); + fprintf(stderr,"\n"); +#endif + if (sanei_usb_write_bulk(iHandle,pabBuf,&iSize) != SANE_STATUS_GOOD) { + DBG(DBG_ERR, "UsbWriteBulk: ERROR: Bulk write failed\n"); + return SANE_FALSE; + } + } + return SANE_TRUE; +} + + +/****************************************************************************/ +SANE_Int Hp_rts_BulkRead(SANE_Int iHandle, SANE_Byte reg, SANE_Byte *pabBuf, + SANE_Int iSize, SANE_Int wWrite) +/****************************************************************************/ +{ + static SANE_Byte init[]={0x80,0,0x00,0x01}; + size_t size; + +#ifdef USBDEBUG + DBG(DBG_USB,"UsbReadBulk ...\n"); +#endif + if (iHandle == -1) { + return SANE_FALSE; + } + + if (wWrite){ +#ifdef USBDEBUG + DBG(DBG_USB,"UsbReadBulk with write\n"); +#endif + init[1] = reg; + init[2] = (iSize>>8) & 0xFF; /*split count over these bytes.*/ + init[3] = (iSize) & 0xFF; + size = 4; +#ifdef USBDEBUG + SANE_Byte *tmpw=init; + SANE_Int tmp_size=size; + fprintf(stderr,"RR transfer type=bulk size=%d dir=OUT\n",tmp_size); + while(tmp_size--) fprintf(stderr,"%02hhx ",*tmpw++); + fprintf(stderr,"\n"); +#endif + if (sanei_usb_write_bulk(iHandle,(unsigned char *) init,&size) != SANE_STATUS_GOOD) { + DBG(DBG_ERR,"UsbReadBulk: ERROR: Bulk write failed\n"); + return SANE_FALSE; + } + } +#ifdef USBDEBUG + DBG(DBG_USB,"UsbReadBulk, now read ...\n"); +#endif + size = iSize; + if (sanei_usb_read_bulk(iHandle, pabBuf,&size) != SANE_STATUS_GOOD) { + DBG(DBG_ERR,"UsbReadBulk: ERROR: Bulk read failed\n"); + return SANE_FALSE; + } +#ifdef USBDEBUG + SANE_Byte *tmpr=pabBuf; + SANE_Int tmp_size=size; + fprintf(stderr,"RR transfer type=bulk size=%d dir=IN\n",tmp_size); + while(tmp_size--) fprintf(stderr,"%02hhx ",*tmpr++); + fprintf(stderr,"\n"); +#endif + return SANE_TRUE; +} + + +/****************************************************************************/ +SANE_Int Hp_rts_RegWrite(SANE_Int iHandle, SANE_Byte bReg, SANE_Byte bData) +/****************************************************************************/ +{ +#ifdef USBDEBUG + DBG(DBG_USB, "SaneiUsbWriteReg...\n"); +#endif + if (Hp_rts_BulkWrite(iHandle,bReg,&bData,1, SANE_TRUE)) + return(SANE_TRUE); + else + return(SANE_FALSE); +} + + +/****************************************************************************/ +SANE_Int Hp_rts_RegRead(SANE_Int iHandle, SANE_Byte bReg, SANE_Byte *pbData) +/****************************************************************************/ +{ +#ifdef USBDEBUG + DBG(DBG_USB, "SaneiUsbReadReg...\n"); +#endif + if (Hp_rts_BulkRead(iHandle,bReg,pbData,1,SANE_TRUE)) + return(SANE_TRUE); + else + return(SANE_FALSE); +} + + +/****************************************************************************/ +SANE_Int Hp_rts_BulkReadall(SANE_Int iHandle, SANE_Byte *pabData) +/****************************************************************************/ +{ + SANE_Byte init[]={0x80,0,0x00,0xf4}; + +#ifdef USBDEBUG + DBG(DBG_USB, "SaneiUsbReadBulk_all_regs...\n"); +#endif + if (iHandle < 0) { + return -1; + } + + if (Hp_rts_BulkWrite(iHandle,1,(char *)init,4, SANE_FALSE)) + { + if (Hp_rts_BulkRead(iHandle,0x81,pabData,192,SANE_FALSE)) + { + if (Hp_rts_BulkRead(iHandle,0x81,pabData+192,52,SANE_FALSE)) + return(SANE_TRUE); + + } else return(SANE_FALSE); + } else return(SANE_FALSE); + return SANE_TRUE; +} + +/************************************************************************* + Returns SANE_TRUE if a known chipset was found. */ +SANE_Bool Hp_rts_ProbeRegisters(THWParams *pHWParams) +/*************************************************************************/ +{ + SANE_Byte bData1,r; + SANE_Int iHandle; + + iHandle = pHWParams->iXferHandle; + bData1 = 0; + DBG(DBG_MSG, "Hp_rts_ProbeRegisters: iHandle = %d, Probing scanner...\n",(SANE_Int)iHandle); + Hp_rts_RegRead( iHandle, 0x00, &bData1); /* read register 0x00 */ + if ((bData1 == 0xE5) || (bData1 == 0xF5)) { + switch (pHWParams->ScannerModel) { + case eHp3500c: case eHp3530c: case eHp3570c: +#ifdef ENABLE_VI8920 + case eVi8920: +#endif + return SANE_STATUS_GOOD; + break; + case eHp4400c: case eHp4470c: + Hp_rts_RegRead(iHandle,MAINBOARD_ID, &r); + if (r == 0) + return SANE_STATUS_GOOD; + DBG(DBG_ERR, "Hp_rts_ProbeRegisters: Wrong MainBoardID = %d\n",r); + DBG(DBG_ERR, "Hp_rts_ProbeRegisters: No valid scanner with RTS88xx chipset found!\n"); + Hp_rts_XferExit(iHandle); + return SANE_STATUS_IO_ERROR ; + break; + default: + DBG(DBG_ERR, "Hp_rts_ProbeRegisters: ERROR: unknown model! (%d) %s\n", + (SANE_Int)pHWParams->ScannerModel, ScannerModels[(SANE_Int)pHWParams->ScannerModel].pszName); + return SANE_STATUS_IO_ERROR; + } + } + else + { + DBG(DBG_ERR, "Hp_rts_ProbeRegisters: No valid scanner with RTS88xx chipset found!\n"); + Hp_rts_XferExit(iHandle); + return SANE_STATUS_IO_ERROR ; + } +} + +/****************************************************************************/ +SANE_Int Hp_rts_Set_double_reg(SANE_Int iHandle, SANE_Byte reg, + SANE_Byte c1, SANE_Byte c2 ) +/****************************************************************************/ +{ + SANE_Byte regs[5]; + +#ifdef USBDEBUG + DBG(DBG_SCAN, "Hp_rts_Set_double_reg....\n"); +#endif + regs[0] = c1; + regs[1] = c2; + return(Hp_rts_BulkWrite (iHandle, reg, regs, 2,SANE_TRUE)); +} + +/****************************************************************************/ +SANE_Int Hp_rts_Read_double_reg(SANE_Int iHandle, SANE_Byte reg, SANE_Byte *pbData ) +/****************************************************************************/ +{ +#ifdef USBDEBUG + DBG(DBG_SCAN, "Hp_rts_Read_double_reg....\n"); +#endif + return(Hp_rts_BulkRead(iHandle,reg,pbData,2,SANE_TRUE)); +} + +/****************************************************************************/ +/*Return the number of bytes ready for collection */ +SANE_Word Hp_rts_data_ready(SANE_Int iHandle, SANE_Word *size){ +/****************************************************************************/ + static SANE_Byte command[]={0x90,0x00,0x00,0x03}; + SANE_Byte data[5]; + +#if 0 + DBG(DBG_SCAN, "Hp_rts_data_ready....\n"); +#endif + /* check if the scanner is moving*/ + if (SANE_TRUE /*read_reg(iHandle,MOVE_START_STOP) & 0x08*/) + { + Hp_rts_BulkWrite(iHandle,0x00,command,4,SANE_FALSE); + Hp_rts_BulkRead(iHandle,0x00,data,3,SANE_FALSE); + *size = data[0]; + *size = *size + (data[1]<<8); + *size = *size + (data[2]<<16); + if(*size > 0xe500) *size=0xe500; + DBG(DBG_SCAN, " Hp_rts_data_ready....data %x\n",*size); + if (*size > 0){ + return(SANE_TRUE); } + else + return(SANE_FALSE); + }else return(SANE_FALSE); +} + + +/****************************************************************************/ +SANE_Int Hp_rts_read_data(SANE_Int iHandle, SANE_Word size,SANE_Byte *data) { +/****************************************************************************/ + static SANE_Byte write_command[]={0x91,0x00,0x00,0x00}; + + write_command[3]=size & 0xff; + write_command[2]=(size>>8) & 0xff; + write_command[1]=(size>>16) & 0xff; + +#ifdef USBDEBUG + DBG(DBG_SCAN, "Hp_rts_read_data..%x\n",size); +#endif + Hp_rts_BulkWrite(iHandle,0x00,write_command,4,SANE_FALSE); + Hp_rts_BulkRead(iHandle,0x00,data,size,SANE_FALSE); + return(SANE_TRUE); +} + +/****************************************************************************/ +SANE_Bool +Hp_rts_is_moving( SANE_Int iHandle ) +/****************************************************************************/ +{ + SANE_Byte r; + + Hp_rts_RegRead(iHandle,REG_MOVE_CONTROL_TEST, &r); +/* if ( Hp_rts_RegRead(iHandle,REG_MOVE_CONTROL_TEST, &r) < 0) + return -1;*/ + if (r == 0x08) + return SANE_TRUE; + return SANE_FALSE; +} + +/****************************************************************************/ +SANE_Int +Hp_rts_start_moving( SANE_Int iHandle ) +/****************************************************************************/ +{ + DBG(DBG_MSG,"Hp_rts_start_moving..."); + if (Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 2) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 2) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 0) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 0) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 8) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 8)) + { + DBG(DBG_MSG,"Hp_rts_start_moving..TRUE\n"); + return SANE_TRUE; + } + else + { + DBG(DBG_MSG,"Hp_rts_start_moving..FALSE\n"); + return SANE_FALSE; + } +} + +/****************************************************************************/ +SANE_Int +Hp_rts_stop_moving( SANE_Int iHandle ) +/****************************************************************************/ +{ + DBG(DBG_MSG,"Hp_rts_stop_moving..."); + if (Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 2) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 2) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 0) && + Hp_rts_RegWrite(iHandle,REG_MOVE_CONTROL_TEST, 0)) + { + DBG(DBG_MSG,"Hp_rts_stop_moving..TRUE\n"); + return SANE_TRUE; + } + else + { + DBG(DBG_MSG,"Hp_rts_stop_moving..FALSE\n"); + return SANE_FALSE; + } +} + + +/****************************************************************************/ +/* Write a gamma table */ +void +Hp_rts_WriteGammaCalibTable (SANE_Int iHandle, + const SANE_Int *pabGammaR, const SANE_Int *pabGammaG, const SANE_Int *pabGammaB) +/****************************************************************************/ +{ + SANE_Byte cmd[3]; + SANE_Byte *buffer; + SANE_Int i, j; + + iHandle = iHandle; + + /* Setup dummy gamma correction table */ + buffer = malloc (2 * 65536); + + cmd[0] = 2; + cmd[1] = 0; + cmd[2] = 0; + + for (i = 0; i < 3; i++) + { + const SANE_Int *ptr = (i == 0) ? pabGammaR : + (i == 1) ? pabGammaG : pabGammaB; + + for (j = 0; j < 65536; j++) /* Truncate integers to shorts */ + buffer[j] = ptr[j]; + +/* hp5400_bulk_command_write (iHandle, 0x2A01 + i, cmd, 3, 2 * 65536, + 65536, (void *) buffer);*/ + } + free (buffer); + + return; +} + +/**************************************************************************** +void +Hp_rts_SetDefaultGamma (SANE_Int iHandle) +**************************************************************************** +{ + SANE_Int *buffer = malloc (sizeof (SANE_Int) * 65536); + SANE_Int i; + + for (i = 0; i < 65336; i++) + buffer[i] = i; + + Hp_rts_WriteGammaCalibTable (iHandle, buffer, buffer, buffer); +}*/ + +/****************************************************************************/ +SANE_Bool +Hp_rts_Check_Moving (SANE_Int iHandle) +/****************************************************************************/ +{ + SANE_Int i; +#if 0 + SANE_Word size; +#endif + + DBG(DBG_MSG,"Hp_rts_Check_Moving: wait for moving ...\n"); + i = 0; + while( !(Hp_rts_is_moving(iHandle)) && ( i < 25 )){ + usleep(10000); + i++; + }; + if ( i >= 25 ){ + DBG(DBG_MSG,"Hp_rts_Check_Moving: Time over, no move : %d!, will stop the movement\n",i); + /*stop it and make sure it stopped!!! */ + Hp_rts_stop_moving(iHandle); + return(SANE_FALSE); + } +#if 0 + /* the scanner is now moving. Check it */ + DBG(DBG_MSG,"Hp_rts_Check_Moving: the scanner is now scanning. Check it\n"); + i = 0; + while( (Hp_rts_data_ready(iHandle,&size) == SANE_FALSE) && ( i < 25 )){ + usleep(10000); + i++; + } + if ( i >= 25 ){ + DBG(DBG_MSG,"Hp_rts_Check_Scanning: Time over, scanner no data : %d, will stop the scanner!\n",i); + /*stop it and make sure it stopped!!! */ + Hp_rts_stop_moving(iHandle); + return(SANE_FALSE); + } +#endif + return(SANE_TRUE); +} + +/****************************************************************************/ +SANE_Int +Hp_rts_Read_Sram (SANE_Int iHandle, SANE_Byte *pabData, + SANE_Int iSize) +/****************************************************************************/ +{ + SANE_Byte init[]={0x81,0x00,0x08,0x18}; + + if (iHandle < 0) { + return(-1); + } +#ifdef USBDEBUG + DBG(DBG_MSG,"Hp_rts_Read_Sram...\n"); +#endif + init[2]=(SANE_Byte)(iSize>>8); /*split count over these bytes.*/ + init[3]=(SANE_Byte)iSize; + + if (Hp_rts_BulkWrite(iHandle,0x00,/*(SANE_Byte *)*/init,4,SANE_FALSE)){ +#if 0 + DBG(DBG_MSG,"Read SRAM, READ NOW %d bytes\n",iSize); + if (iSize >= 0x800){ + DBG(DBG_MSG,"Read SRAM, READ the first %d bytes\n",2048); + if (Hp_rts_BulkRead(iHandle,0x00,(SANE_Byte *)pabData, 2048,SANE_FALSE) == 0){ + DBG(DBG_MSG,"Read SRAM, READ the left %d bytes\n",iSize-2048); + return (Hp_rts_BulkRead(iHandle,0x00,(SANE_Byte *)pabData, iSize-2048,SANE_FALSE)); + } + } + else{ +#endif + return (Hp_rts_BulkRead(iHandle,0x00,(SANE_Byte *)pabData, iSize,SANE_FALSE)); +#if 0 + } +#endif + } + return(SANE_FALSE); +} + +/****************************************************************************/ +SANE_Int +Hp_rts_set_value_lsbfirst( SANE_Byte *regs, + SANE_Int firstreg, + SANE_Int totalregs, + SANE_Word value) +/****************************************************************************/ +{ + while (totalregs--) + { + regs[firstreg++] = value & 0xff; + value >>= 8; + } + return 0; +} + +/****************************************************************************/ +SANE_Int +Hp_rts_set_noscan_distance( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0x60, 2, value); +} + +/****************************************************************************/ +SANE_Int +Hp_rts_set_total_distance( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0x62, 2, value); +} + +/****************************************************************************/ +SANE_Int +Hp_rts_set_scanline_end( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst(regs, 0x6c, 2, value); +} + +/****************************************************************************/ +SANE_Int +Hp_rts_set_scanline_start( SANE_Byte *regs, + SANE_Word value) +/****************************************************************************/ +{ + return Hp_rts_set_value_lsbfirst (regs, 0x66, 2, value); +} + + +/****************************************************************************/ +SANE_Status Hp_rts_CircBufferInit(SANE_Handle h, TDataPipe *p, SANE_Int iBytesPerLine, + SANE_Int iMisAlignment, SANE_Bool mode) +/****************************************************************************/ +{ + TScanner *s; + SANE_Int iHandle; + SANE_Int bufsize; + + /* prevent compiler from complaining about unused parameters */ + mode = mode; + + s = (TScanner *)h; + iHandle = s->HWParams.iXferHandle; + p->iBytesPerLine = iBytesPerLine; + bufsize = p->iBytesPerLine * 3; + p->iLinesPerCircBuf = 1; + p->iMisAlignment = iMisAlignment; + + DBG(DBG_SCAN, "Hp_rts_CircBufferInit: _iBytesPerLine = %d\n", p->iBytesPerLine); + DBG(DBG_SCAN, "Hp_rts_CircBufferInit: _iLinesPerCircBuf = %d\n", p->iLinesPerCircBuf); + + p->pabCircBuf = (SANE_Byte *)malloc(bufsize+(3*p->iBytesPerLine)); + if (p->pabCircBuf == NULL) { + DBG(DBG_ERR, "Hp_rts_CircBufferInit: Unable to allocate %d bytes for circular buffer (%x - %x)\n", + (SANE_Int)bufsize,(unsigned int)p->pabCircBuf,(unsigned int)p->pabCircBuf+bufsize); + return SANE_STATUS_NO_MEM; + } + DBG(DBG_SCAN,"Hp_rts_CircBufferInit: Allocate %d bytes for circular buffer (%x - %x)\n", + (SANE_Int)bufsize,(unsigned int)p->pabCircBuf,(unsigned int)p->pabCircBuf+bufsize); + /* init transfer buffer */ + return Hp_rts_XferBufferInit(h, p); +} + + +/****************************************************************************/ +void Hp_rts_CircBufferExit(SANE_Handle h) +/****************************************************************************/ +{ + TScanner *s; + + s = (TScanner *)h; + if (s->DataPipe.pabCircBuf != NULL) { + free(s->DataPipe.pabCircBuf); + s->DataPipe.pabCircBuf = NULL; + } + Hp_rts_XferBufferExit( h ); + DBG(DBG_SCAN,"Hp_rts_CircBufferExit\n"); +} + + +/****************************************************************************/ +/* gets an line from the circular buffer. */ +SANE_Bool Hp_rts_CircBufferGetLine(SANE_Handle h, TDataPipe *p, SANE_Byte *pabLine, + SANE_Bool mode){ +/****************************************************************************/ + + SANE_Int line_lenght,copy_lines; + #ifdef DEBUG_FILE + SANE_Word size_t,data_count; + #endif + + TScanner *s; + + s = (TScanner *)h; + + DBG(DBG_SCAN," Hp_rts_CircBufferGetLine starts here\n"); + mode = mode; + line_lenght = p->iBytesPerLine; + copy_lines = 0; + + if (pabLine != NULL) { + if (Hp_rts_XferBufferGetLine(h, p, &p->pabCircBuf[0])){ + memcpy(pabLine, &p->pabCircBuf[0], p->iBytesPerLine); + #ifdef DEBUG_FILE + data_count = 0; + size_t = p->iBytesPerLine; + while(size_t--) fprintf(s->ScanParams.FD_r,"%c",p->pabCircBuf[data_count++]); + #endif + return SANE_TRUE; + } + } + return SANE_FALSE; +} + + +/****************************************************************************/ +SANE_Bool Hp_rts_XferBufferGetLine(SANE_Handle h, TDataPipe *p, SANE_Byte *pabLine) +/****************************************************************************/ +{ + TScanner *s; + SANE_Word size; + SANE_Word size_t; + SANE_Word Lines, Skip, lBytes; + SANE_Int iHandle,i,wt; + SANE_Byte *buf; + + s = (TScanner *)h; + iHandle = s->HWParams.iXferHandle; + + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine in: = iBytesPerLine=%3d iLinesLeft=%3d\n", + (SANE_Int)p->iBytesPerLine,(SANE_Int)s->ScanParams.iLinesLeft); + + switch (s->ScanParams.iDpi) { + case 150: + case 200: + case 300: + case 600: + if (s->ScanParams.mode == COLOR) + Skip = 1; + else + Skip = 2; + break; + default: + Skip = 1; + break; + } + lBytes = p->iBytesPerLine; + + /* Step 1, check if we have to receive more data from the scanner */ + if (p->iCurLine == 0){ + i = 0; + while( i < 10 ){ + Hp_rts_data_ready(iHandle,&size); + if (size > lBytes) + i = 9; + usleep(10); + i++; + } + #if 0 + DBG(DBG_SCAN,"size %d ",(SANE_Int) size); + #endif + Hp_rts_data_ready(iHandle,&size); + Lines = (size / lBytes) / Skip; /* make shure we can div. it */ + size_t = (Lines * lBytes) * Skip; + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: size %d lBytes %d size_t %d\n",size,lBytes,size_t); + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: write to buffer at 0x%x %d Lines\n", + (unsigned int) p->pabXferBuf,Lines); + #endif + p->iLastLine = Lines * Skip; + if ( size_t > 0 ){ + Hp_rts_read_data(iHandle,size_t,p->pabXferBuf); + }else + { /* fix: the scanner is stoped. + we have to read all bytes to + restart him */ + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: restart %d\n",size_t); + #endif + if ( size > 0 ){ + Hp_rts_read_data(iHandle,size,p->pabXferBuf); + size_t = lBytes - size; + i = 0; + while( (Hp_rts_data_ready(iHandle,&size) == SANE_FALSE) && ( i < 3 )){ + sleep(1); + i++; + } + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: restart read %d\n",size_t); + #endif + Hp_rts_read_data(iHandle,size,p->pabXferBuf); + } + else{ /* no more data aviable */ + p->iLastLine = 0; + return(SANE_FALSE); + } + } + wt = (10 * (XFER_BUF_SIZE - size))/2; + if (wt < 1) wt = 1; + if (wt > 65000) wt = 65000; + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Wait %d s, size %d, iLastLine %d\n",wt, size,(SANE_Int)p->iLastLine); + #endif + usleep(wt); + } + + /* Step 2, copy one line */ + if (pabLine != NULL) { + buf = p->pabXferBuf + (p->iCurLine * lBytes); + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: read from buffer at 0x%x (%d), iLinesLeft %d, iScanned %d\n", + (unsigned int) buf,p->iCurLine,(SANE_Int)s->ScanParams.iLinesLeft,(SANE_Int)p->iScanned); + #endif + memcpy(pabLine, buf, lBytes); + } + + /* Step 3, set the advance pointer */ + p->iCurLine = p->iCurLine + Skip; + p->iScanned = p->iScanned + 1; + + if ( p->iCurLine >= p->iLastLine ){ + p->iCurLine = 0; + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: set p->iCurLine = 0\n"); + #endif + } + #ifdef DEBUG_SCAN + DBG(DBG_SCAN," Hp_rts_XferBufferGetLine: exit\n"); + #endif + return(SANE_TRUE); +} + + +/****************************************************************************/ +SANE_Status Hp_rts_XferBufferInit(SANE_Handle h, TDataPipe *p) +/****************************************************************************/ +{ + TScanner *s; + #ifdef DEBUG_FILE + SANE_Word x1,x2,length ; + #endif + + SANE_Int bufsize; + + s = (TScanner *)h; + bufsize = XFER_BUF_SIZE/**10*/; + + p->iLinesPerXferBuf = bufsize / (p->iBytesPerLine); + p->iLastLine = 0; + DBG(DBG_SCAN,"Hp_rts_XferBufferInit: iLinesPerXferBuf = %d\n", p->iLinesPerXferBuf); + DBG(DBG_SCAN,"Hp_rts_XferBufferInit: Xfer block size = 0x%x\n", p->iLinesPerXferBuf * + p->iBytesPerLine); + + #ifdef DEBUG_FILE + /* Opening the testfile for debuging */ + if ( !s->ScanParams.DebugOpen ){ + s->ScanParams.DebugOpen = SANE_TRUE; + s->ScanParams.FD_r = fopen("view_r.pnm","w"); + x1 = s->ScanParams.iX; + x2 = s->ScanParams.iWidth ; + length = s->ScanParams.iLenght - 1; + DBG(DBG_SCAN,"TempFile, length:%d, x1:%d, x2:%d \n",length,x1,x2); + switch (s->ScanParams.mode) { + case BLACK_WHITE: + case GRAY: + fprintf(s->ScanParams.FD_r,"P5\n%d %d\n255\n",x2,length+100); + break; + case COLOR: + fprintf(s->ScanParams.FD_r,"P6\n%d %d\n255\n",x2,length+100); + break; + } + } + #endif + p->iCurLine = 0; + + p->pabXferBuf = (SANE_Byte *)malloc(bufsize); + if (p->pabXferBuf == 0){ + DBG(DBG_ERR,"Hp_rts_XferBufferInit: MEM alloc is not not possible !\n"); + return SANE_STATUS_NO_MEM; + } else{ + DBG(DBG_SCAN,"Hp_rts_XferBufferInit alloc: p->pabXferBuf = 0x%x bytes at 0x%x\n", + bufsize,(unsigned int) p->pabXferBuf); + return SANE_STATUS_GOOD; + } +} + + +/****************************************************************************/ +void Hp_rts_XferBufferExit( SANE_Handle h ) +/****************************************************************************/ +{ + TScanner *s; + + s = (TScanner *)h; + if (s->DataPipe.pabXferBuf != NULL) { + DBG(DBG_SCAN,"Hp_rts_XferBufferExit free: p->pabXferBuf at 0x%x\n", + (unsigned int) s->DataPipe.pabXferBuf); + free(s->DataPipe.pabXferBuf); + s->DataPipe.pabXferBuf = NULL; + } + else { ; + DBG(DBG_ERR, "Hp_rts_XferBufExit: Xfer buffer not initialised!\n"); + } +} + + diff -urN sane-backends-1.0.15.orig/backend/hp_rts_xfer.h sane-backends-1.0.15/backend/hp_rts_xfer.h --- sane-backends-1.0.15.orig/backend/hp_rts_xfer.h 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/backend/hp_rts_xfer.h 2005-07-26 13:25:11.164833888 -0500 @@ -0,0 +1,214 @@ + /* sane - Scanner Access Now Easy. + Copyright (C) 2003 Johannes Hub (JohannesHub@t-online.de) + + This file was initially copied from the hp3300 backend. + 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 exutable, 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. +*/ + +/* + Concept for a backend for scanners based on the RTS88xx chipset, + such as HP4400C, HP4470C. + Parts of this source were inspired by other backends. + + History: + + Version 0.18 21.11.04 13.alpha, + - source sorted, + - now only SANEI_USB_SUPPORT for a better overview(xfermodules removed) + - read and verify the MainBoardID + Version 0.17p 02.11.04 12.alpha, source sorted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17p 02.11.04 12.alpha, source sourted, little fixes, SANEI_USB_SUPPORT implemented + Version 0.17b 30.03.04 10.alpha, little fixes and libusb implemented + Version 0.17 09.03.04 9. alpha, HP3500 included + Version 0.16 06.02.04 8. alpha, wait counting on LCD + Version 0.15a 29.01.04 7. alpha, CCD switch moved to config file + Version 0.15 11.01.04 6. alpha, a second CCD implemented + Version 0.13a 21.11.04 4. alpha, an little fix included + Version 0.12 22.10.03 third alpha, Backend name changed to HP_RTS88xx + Version 0.11 30.08.03 second alpha + Version 0.10 19.07.03 first alpha +*/ + +/* + Provides a simple interface to read and write data from the scanner, + without any knowledge whether it's a parallel or USB scanner +*/ + +#ifndef _HP_RTS_XFER_H_ +#define _HP_RTS_XFER_H_ + +#include /* for FILE * */ + +#ifdef STANDALONE + + #include + #include "../include/sane/config.h" + #include "../include/sane/sane.h" + + #include "hp_rts88xx.h" + #undef DBG + #undef DBG_MSG + #undef DBG_USB + #undef DBG_OPT + #undef DBG_SCAN + #undef DBG_ASSERT + #undef DBG_ERR + + #define DBG fprintf + #define DBG_MSG stdout + #define DBG_USB stdout + #define DBG_OPT stdout + #define DBG_SCAN stdout + #define DBG_ASSERT stdout + #define DBG_ERR stdout + +#endif + + +#define MAINBOARD_ID 0xb1 +#define REG_MOVE_CONTROL_TEST 0xb3 + +#define MAX_READ_WRITE 0x3fff /* 4096 */ +#define TIMEOUT 10000 +#define XFER_BUF_SIZE 0xFF00 + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + + +typedef enum { + eUnknownModel = 0, + eHp3500c, + eHp3530c, + eHp3570c, + eHp4400c, + eHp4470c, + eVi8920, + eVi8900, + eVi8700, + eVi5800, + eVi5300, + eVi4800, + eVa3000, + eMi3000, + ePlS6, + ePrlS6 +} EScannerModel; + + +typedef struct { + SANE_Char *pszVendor; + SANE_Char *pszName; + SANE_Int iVendor; + SANE_Int iProduct; + EScannerModel eModel; +} TScannerModel; + + +/* linked list of SANE_Device structures */ +typedef struct TDevListEntry +{ + struct TDevListEntry *pNext; + SANE_Device dev; +} +TDevListEntry; + + +typedef SANE_Int (TFnReportDevice)(TScannerModel *pModel, SANE_Char *pszDeviceName); + +/* USB device file name */ +extern SANE_Char * usb_devfile; + +/* list of supported models, the actual list is in hp_rts_xfer.c */ +extern TScannerModel ScannerModels[]; + +/* The number returned by Hp_rts_XferInit is a handle. This handle needs to + be passed to all other transfer functions. + Internally it is a pointer to structure containg function pointers +*/ +void Hp_rts_DumpHex(SANE_Byte *pabData, SANE_Int iLen, SANE_Int iWidth, SANE_Int withLf); +void Hp_rts_DumpBits(SANE_Byte reg, SANE_Byte pabData); + +SANE_Int Hp_rts_XferInit(/*EScannerModel *peModel*/void); +/*SANE_Int Hp_rts_XferInit (EScannerModel *peModel);*/ +SANE_Int Hp_rts_XferExit (SANE_Int iXferHandle); +SANE_Int Hp_rts_RegWrite (SANE_Int iXferHandle, SANE_Byte reg, SANE_Byte bData); +SANE_Int Hp_rts_RegRead (SANE_Int iXferHandle, SANE_Byte reg, SANE_Byte *pbData); +SANE_Int Hp_rts_BulkWrite (SANE_Int iXferHandle, SANE_Byte reg, SANE_Byte *pabBuf, SANE_Int iSize, SANE_Int wHeader); +SANE_Int Hp_rts_BulkRead (SANE_Int iXferHandle, SANE_Byte reg, SANE_Byte *pabBuf, SANE_Int iSize, SANE_Int wWrite); +SANE_Int Hp_rts_BulkReadall (SANE_Int iHandle, SANE_Byte *pabData); +SANE_Bool Hp_rts_MatchUsbDevice (SANE_Int iVendor, SANE_Int iProduct, TScannerModel **ppeModel); +SANE_Bool Hp_rts_ProbeRegisters (THWParams *pHWParams); +SANE_Int Hp_rts_Set_double_reg (SANE_Int iHandle, SANE_Byte reg, SANE_Byte c1, SANE_Byte c2 ); +SANE_Int Hp_rts_Read_double_reg (SANE_Int iHandle, SANE_Byte reg, SANE_Byte *pbData ); +SANE_Int Hp_rts_data_ready (SANE_Int iHandle, SANE_Int *size); +SANE_Int Hp_rts_read_data (SANE_Int iHandle, SANE_Int size,SANE_Byte *data); +SANE_Int Hp_rts_set_value_lsbfirst( SANE_Byte *regs,SANE_Int firstreg,SANE_Int totalregs, SANE_Word value); + +SANE_Bool Hp_rts_is_moving (SANE_Int iHandle); +SANE_Int Hp_rts_start_moving (SANE_Int iHandle); +SANE_Int Hp_rts_stop_moving (SANE_Int iHandle); +void Hp_rts_WriteGammaCalibTable (SANE_Int iHandle, + const SANE_Int *pabGammaR, const SANE_Int *pabGammaG,const SANE_Int *pabGammaB); +/*void Hp_rts_SetDefaultGamma (SANE_Int iHandle);*/ +SANE_Bool Hp_rts_Check_Moving (SANE_Int iHandle); +SANE_Int Hp_rts_Read_Sram (SANE_Int iHandle, SANE_Byte *pabData, + SANE_Int iSize); +SANE_Int Hp_rts_set_noscan_distance(SANE_Byte *regs,SANE_Word value); +SANE_Int Hp_rts_set_total_distance(SANE_Byte *regs,SANE_Word value); +SANE_Int Hp_rts_set_scanline_end(SANE_Byte *regs,SANE_Word value); +SANE_Int Hp_rts_set_scanline_start(SANE_Byte *regs,SANE_Word value); + +SANE_Status Hp_rts_CircBufferInit (SANE_Handle h, TDataPipe *p, SANE_Int iBytesPerLine, + SANE_Int iMisAlignment, SANE_Bool mode); + +SANE_Bool Hp_rts_CircBufferGetLine (SANE_Handle h, TDataPipe *p, SANE_Byte *pabLine, + SANE_Bool mode); + +void Hp_rts_CircBufferExit (SANE_Handle h); + +SANE_Bool Hp_rts_XferBufferGetLine(SANE_Handle h, TDataPipe *p, SANE_Byte *pabLine); + +void Hp_rts_XferBufferExit (SANE_Handle h); +SANE_Status Hp_rts_XferBufferInit (SANE_Handle h, TDataPipe *p); + +#endif /* _HP_RTS_XFER_H_ */ diff -urN sane-backends-1.0.15.orig/doc/Makefile.in sane-backends-1.0.15/doc/Makefile.in --- sane-backends-1.0.15.orig/doc/Makefile.in 2005-07-26 13:24:30.190063000 -0500 +++ sane-backends-1.0.15/doc/Makefile.in 2005-07-26 13:25:11.175832216 -0500 @@ -38,7 +38,7 @@ @SET_MAKE@ SECT1 = scanimage.1 sane-config.1 sane-find-scanner.1 gamma4scanimage.1 -SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 \ +SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 sane-hp_rts88xx.5 \ sane-dc25.5 sane-dmc.5 sane-epson.5 sane-hp.5 sane-gphoto2.5 \ sane-leo.5 sane-matsushita.5 sane-microtek.5 \ sane-microtek2.5 sane-mustek.5 sane-nec.5 sane-net.5 sane-pie.5 \ @@ -89,7 +89,7 @@ sane-artec.man sane-as6e.man sane-avision.man sane-bh.man \ sane-canon.man sane-canon630u.man sane-config.man sane-coolscan.man \ sane-coolscan2.man sane-dc210.man sane-dc240.man \ - sane-dc25.man sane-dll.man sane-dmc.man sane-epson.man \ + sane-dc25.man sane-dll.man sane-hp_rts88xx.man sane-dmc.man sane-epson.man \ sane-find-scanner.man sane-fujitsu.man sane-gphoto2.man sane-hp.man \ sane-logo.png sane-logo2.jpg sane-matsushita.man sane-microtek.man \ sane-leo.man sane-microtek2.man \ diff -urN sane-backends-1.0.15.orig/doc/descriptions/hp_rts88xx.desc sane-backends-1.0.15/doc/descriptions/hp_rts88xx.desc --- sane-backends-1.0.15.orig/doc/descriptions/hp_rts88xx.desc 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/doc/descriptions/hp_rts88xx.desc 2005-07-26 13:25:11.168833280 -0500 @@ -0,0 +1,37 @@ +; +; SANE Backend specification file +; +:backend "hp_rts88xx" ; name of backend +;:version "(0.18)" ; version of backend +;:manpage "sane-hp_rts88xx" ; name of manpage (if it exists) +:url "http://hp44x0backend.sourceforge.net" ; backend's web page + +:devicetype :scanner ; start of a list of devices.... + +:mfg "Hewlett-Packard" ; name a manufacturer +:url "http://www.hp.com/" + +:model "HP4400C" ; name models for above-specified mfg. +:interface "USB" +:status :basic +:comment "grayscale 300/600 DPI" + +:model "HP4470C" +:interface "USB" +:status :basic +:comment "grayscale 300/600 DPI, XPA/bed mode" + +:model "HP3500C" +:interface "USB" +:status :basic +:comment "not tested" + +:model "HP3530C" +:interface "USB" +:status :basic +:comment "not tested" + +:model "HP3570C" +:interface "USB" +:status :basic +:comment "not tested" diff -urN sane-backends-1.0.15.orig/doc/sane-hp_rts88xx.man sane-backends-1.0.15/doc/sane-hp_rts88xx.man --- sane-backends-1.0.15.orig/doc/sane-hp_rts88xx.man 1969-12-31 18:00:00.000000000 -0600 +++ sane-backends-1.0.15/doc/sane-hp_rts88xx.man 2005-07-26 13:25:11.167833432 -0500 @@ -0,0 +1,108 @@ +.\" $Id: sane-hp_rts88xx.man,v 1.2 2004/22/10 10:35:31 jh Exp $ +.TH sane-hp_rts88xx 5 "22 Oct 2004" +.IX sane-hp_rts88xx + +.SH NAME +sane-hp_rts88xx - SANE backend for scanners based on the RTS8891 chipset. + +.SH DESCRIPTION +The +.B sane-hp_rts88xx +implements a SANE (Scanner Access Now Easy) backend that +provides access to RTS8891 chipset based scanners. This backend will try to support +the following models: + +MANUFACTURER: MODEL: USB ID: +.br +--------------- -------------- --------- +.br +Hewlett-Packard Scanjet 4400c 03F0-0705 +.br +Hewlett-Packard Scanjet 4470c 03F0-0805 +.br +Hewlett-Packard Scanjet 3500C 03F0-2205 +.br +Hewlett-Packard Scanjet 3530c 03F0-2005 +.br +Hewlett-Packard Scanjet 3570c 03F0-2005 +.br +.PP +.br + +.SH "DEVICE NAMES" +This backend expects device names of the form: +.PP +.RS +.I special +.RE +.PP +Where +.I special +is a path-name for the special device that corresponds to a USB scanner. +With GNU/Linux systems, such a device name could be +.I /dev/usb/scanner0 +or +.IR /dev/usbscanner1 , +for example. + + +.SH CONFIGURATION +The +.I hp_rts88xx.conf +file contains the device name that correspond to the hp44x0c +scanner. Empty lines and lines starting with a hash mark (#) are +ignored. +.PP +A sample configuration file is shown below: +.PP +.RS +# Comment +.br +/dev/usbscanner +# option_CCD +# CCD0 or CCD1 allowed +# if you receive a black image, change it to CCD1 +option CCD0 +.RE +.PP +The first line is ignored. The second line is the device filename to use +in order to access the hp44x0c Scanner. If no device is given, the +backend will use libUSB. + +.SH FILES +.TP +.I @CONFIGDIR@/hp_rts88xx.conf +The backend configuration file (see also description of SANE_CONFIG_DIR below). + +.TP +.I @LIBDIR@/libsane-hp_rts88xx.a +The static library implementing this backend. + +.TP +.I @LIBDIR@/libsane-hp_rts88xx.so +The shared library implementing this backend (present on systems that +support dynamic loading). +.SH ENVIRONMENT + +.TP +.B SANE_CONFIG_DIR +This environment variable specifies the list of directories that may +contain the configuration file. Under UNIX, the directories are +separated by a colon (`:'), under OS/2, they are separated by a +semi-colon (`;'). If this variable is not set, the configuration file +is searched in two default directories: first, the current working +directory (".") and then in @CONFIGDIR@. If the value of the +environment variable ends with the directory separator character, then +the default directories are searched after the explicitly specified +directories. For example, setting +.B SANE_CONFIG_DIR +to "/tmp/config:" would result in directories "tmp/config", ".", and +"@CONFIGDIR@" being searched (in this order). +.TP + +.SH "SEE ALSO" +sane(7), sane\-usb(5) +.br +http://hp44x0backend.sourceforge.net +.SH AUTHOR +Johannes Hub