Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 13543 Details for
Bug 18479
add HP ScanJet 3300c support to sane-backends-1.0.12
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
hp3300c.patch
hp3300c.patch (text/plain), 97.61 KB, created by
Brian Jackson (RETIRED)
on 2003-06-19 09:09:46 UTC
(
hide
)
Description:
hp3300c.patch
Filename:
MIME Type:
Creator:
Brian Jackson (RETIRED)
Created:
2003-06-19 09:09:46 UTC
Size:
97.61 KB
patch
obsolete
>diff -ruN sane-backends-1.0.12/backend/Makefile.in sane-backends-1.0.12-patched/backend/Makefile.in >--- sane-backends-1.0.12/backend/Makefile.in 2003-05-13 04:39:50.000000000 -0500 >+++ sane-backends-1.0.12-patched/backend/Makefile.in 2003-06-19 11:02:15.000000000 -0500 >@@ -62,7 +62,7 @@ > > @SET_MAKE@ > >-PRELOADABLE_BACKENDS = abaton agfafocus apple artec as6e avision bh canon \ >+PRELOADABLE_BACKENDS = niash abaton agfafocus apple artec as6e avision bh canon \ > canon630u @CANON_PP@ coolscan coolscan2 dc25 @DC210@ @DC240@ dmc \ > epson fujitsu @GPHOTO2@ gt68xx hp @HPSJ5S@ leo matsushita microtek \ > microtek2 mustek mustek_pp mustek_usb nec @NET@ pie @PINT@ plustek \ >@@ -70,7 +70,7 @@ > sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \ > @V4L@ artec_eplus48u ma1509 ibm hp5400 > ifneq (@SELECTED_BACKENDS@,) >-PRELOADABLE_BACKENDS = @SELECTED_BACKENDS@ >+PRELOADABLE_BACKENDS = niash @SELECTED_BACKENDS@ > endif > > ALL_BACKENDS = $(PRELOADABLE_BACKENDS) dll >@@ -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-niash.la: ../sanei/sanei_config2.lo >+libsane-niash.la: ../sanei/sanei_constrain_value.lo >+libsane-niash.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 -ruN sane-backends-1.0.12/backend/dll.conf sane-backends-1.0.12-patched/backend/dll.conf >--- sane-backends-1.0.12/backend/dll.conf 2003-04-17 04:19:42.000000000 -0500 >+++ sane-backends-1.0.12-patched/backend/dll.conf 2003-06-19 11:02:15.000000000 -0500 >@@ -64,3 +64,4 @@ > # HP OfficeJet backend homepage: http://hpoj.sf.net/ > # Uncomment the following line if hpoj is installed: > #hpoj >+niash >diff -ruN sane-backends-1.0.12/backend/hp3300c.c sane-backends-1.0.12-patched/backend/hp3300c.c >--- sane-backends-1.0.12/backend/hp3300c.c 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c.c 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,1077 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c.c,v 1.52 2003/03/24 19:14:46 bertrik Exp $ >+*/ >+ >+/* >+ Core HP3300c functions. >+*/ >+ >+#include <stdio.h> /* fopen, fread, fwrite, fclose etc */ >+#include <stdarg.h> /* va_list for vfprintf */ >+#include <string.h> /* memcpy, memset */ >+#include <unistd.h> /* unlink */ >+#include <stdlib.h> /* malloc, free */ >+#include <math.h> /* exp, pow */ >+ >+#include "mytypes.h" >+#include "hp3300c_xfer.h" >+ >+#include "hp3300c.h" >+ >+ >+#ifndef MIN >+#define MIN(a,b) (((a) < (b)) ? (a) : (b)) >+#endif >+ >+#ifndef MAX >+#define MAX(a,b) (((a) > (b)) ? (a) : (b)) >+#endif >+ >+ >+#define XFER_BUF_SIZE 0xF000 >+ >+ >+/* HP3400 firmware data */ >+static byte abData0000[] = { >+ 0xfe, 0x9f, 0x58, 0x1b, 0x00, 0x03, 0xa4, 0x02, 0x63, 0x02, 0x33, 0x02, 0x0d, 0x02, 0xf0, 0x01, >+ 0xd8, 0x01, 0xc5, 0x01, 0xb5, 0x01, 0xa8, 0x01, 0x9d, 0x01, 0x93, 0x01, 0x8b, 0x01, 0x84, 0x01, >+ 0x7e, 0x01, 0x79, 0x01, 0x74, 0x01, 0x70, 0x01, 0x6d, 0x01, 0x69, 0x01, 0x67, 0x01, 0x64, 0x01, >+ 0x62, 0x01, 0x60, 0x01, 0x5f, 0x01, 0x5d, 0x01, 0x5c, 0x01, 0x5b, 0x01, 0x5a, 0x01, 0x59, 0x01, >+ 0x58, 0x01, 0x57, 0x01, 0x57, 0x01, 0x56, 0x01, 0x56, 0x01, 0x55, 0x01, 0x55, 0x01, 0x54, 0x01, >+ 0x54, 0x01, 0x54, 0x01, 0x54, 0x01, 0x53, 0x01, 0x53, 0x01, 0x53, 0x01, 0x53, 0x01, 0x52, 0x81 }; >+/* 1st word : 0x9ffe = 40958, strip 15th bit: 0x1ffe = 8190 >+ 2nd word : 0x1b58 = 7000 -> coincidence ? >+ other words: formula: y = 676 / (2 - exp(0.113 * (1-x)) ), where x = 0 for first entry >+*/ >+ >+/* more HP3400 firmware data */ >+static byte abData0400[] = { >+ 0xa4, 0x82, 0x00, 0x80, 0xa4, 0x82, 0xaa, 0x02, 0xc0, 0x02, 0xe8, 0x02, 0x3e, 0x03, 0xc8, 0x03, >+ 0x58, 0x1b, 0xfe, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00 }; >+ >+ >+ >+/* utility function to show a hexdump of a buffer */ >+void DumpHex(byte *pabData, int iLen, int iWidth) >+{ >+ int i; >+ for (i = 0; i < iLen; i++) { >+ if ((i % iWidth) == 0) { >+ printf("\n%04X", i); >+ } >+ printf(" %02X", pabData[i]); >+ } >+ printf("\n"); >+} >+ >+ >+static void _ConvertMotorTable(byte *pabOld, byte *pabNew, int iSize, int iLpi) >+{ >+ int iData, i, iBit15; >+ >+ for (i = 0; i < (iSize / 2); i++) { >+ iData = pabOld[2*i + 0] + (pabOld[2*i + 1] << 8); >+ iBit15 = (iData & 0x8000); >+ iData = (iData & 0x7FFF); >+ if (iData <= 0x400) { >+ iData = iData * iLpi / 300; >+ } >+ if (iBit15 != 0) { >+ iData |= 0x8000; >+ } >+ pabNew[2*i + 0] = iData & 255; >+ pabNew[2*i + 1] = (iData >> 8) & 255; >+ } >+} >+ >+ >+/************************************************************************* >+ _ProbeRegisters >+ =============== >+ Tries to determine certain hardware properties. >+ >+ This is done by checking the writeability of some scanner registers. >+ We cannot rely simply on the scanner model to contain a specific >+ chip. The HP3300c for example uses one of at least three slightly >+ different scanner ASICs (NIASH00012, NIASH00013 and NIASH00014). >+ >+ OUT pHWParams Hardware parameters, updated fields: >+ fGamma16 TRUE if 16 bit gamma tables can be used >+ fReg07 TRUE if reg07 is writeable >+ iBufferSize Size of scanner's internal buffer >+ >+ Returns TRUE if a NIASH chipset was found. >+*************************************************************************/ >+static bool _ProbeRegisters(THWParams *pHWParams) >+{ >+ byte bData1, bData2; >+ int iHandle; >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ DBG(DBG_MSG, "Probing scanner...\n"); >+ >+ /* check register 0x04 */ >+ Hp3300cRegWrite (iHandle, 0x04, 0x55); >+ Hp3300cRegRead (iHandle, 0x04, &bData1); >+ Hp3300cRegWrite (iHandle, 0x04, 0xAA); >+ Hp3300cRegRead (iHandle, 0x04, &bData2); >+ Hp3300cRegWrite (iHandle, 0x04, 0x07); >+ if ((bData1 != 0x55) || (bData2 != 0xAA)) { >+ DBG(DBG_ERR, " No NIASH chipset found!\n"); >+ return FALSE; >+ } >+ >+ /* check writeability of register 3 bit 1 */ >+ Hp3300cRegRead (iHandle, 0x03, &bData1); >+ Hp3300cRegWrite (iHandle, 0x03, bData1 | 0x02); >+ Hp3300cRegRead (iHandle, 0x03, &bData2); >+ Hp3300cRegWrite (iHandle, 0x03, bData1); >+ pHWParams->fGamma16 = ((bData2 & 0x02) != 0); >+ DBG(DBG_MSG, " Gamma table entries are %d bit\n", pHWParams->fGamma16 ? 16 : 8); >+ >+ /* check register 0x07 */ >+ Hp3300cRegRead (iHandle, 0x07, &bData1); >+ Hp3300cRegWrite (iHandle, 0x07, 0x1C); >+ Hp3300cRegRead (iHandle, 0x07, &bData2); >+ Hp3300cRegWrite (iHandle, 0x07, bData1); >+ pHWParams->fReg07 = (bData2 == 0x1C); >+ >+ if (!pHWParams->fGamma16) { >+ /* internal scan buffer size is an educated guess, but seems to correlate >+ well with the size calculated from several windows driver log files >+ size = 128kB - 44088 bytes (space required for gamma/calibration table) >+ */ >+ pHWParams->iBufferSize = 86984L; >+ DBG(DBG_MSG, " NIASH version < 00014\n"); >+ } >+ else { >+ pHWParams->iBufferSize = 0x60000L; >+ if (!pHWParams->fReg07) { >+ DBG(DBG_MSG, " NIASH version = 00014\n"); >+ } >+ else { >+ DBG(DBG_MSG, " NIASH version > 00014\n"); >+ } >+ } >+ >+ return TRUE; >+} >+ >+ >+/* returns 0 on success, < 0 otherwise */ >+int Hp3300cOpen(THWParams *pHWParams, char *pszName) >+{ >+ int iXferHandle; >+ >+ iXferHandle = Hp3300cXferOpen(pszName, &pHWParams->eModel); >+ if (iXferHandle < 0) { >+ DBG(DBG_ERR, "Hp3300cXferOpen failed for '%s'\n", pszName); >+ return -1; >+ } >+ >+ pHWParams->iXferHandle = iXferHandle; >+ >+ Hp3300cWakeup(pHWParams->iXferHandle); >+ >+ /* default HW params */ >+ pHWParams->iSensorSkew = 8; >+ pHWParams->iTopLeftX = 0; >+ pHWParams->iTopLeftY = 3; >+ pHWParams->fReg07 = FALSE; >+ pHWParams->iSkipLines = 0; >+ pHWParams->iExpTime = 5408; >+ pHWParams->iReversedHead = TRUE; >+ >+ switch (pHWParams->eModel) { >+ >+ case eHp3300c: >+ DBG(DBG_MSG, "Setting params for Hp3300\n"); >+ pHWParams->iTopLeftX = 4; >+ pHWParams->iTopLeftY = 11; >+ pHWParams->iSkipLines = 14; >+ break; >+ >+ case eHp3400c: case eHp4300c: >+ DBG(DBG_MSG, "Setting params for Hp3400c/Hp4300c\n"); >+ pHWParams->iTopLeftX = 2; >+ pHWParams->iTopLeftY = 13; >+ pHWParams->fReg07 = TRUE; >+ break; >+ >+ case eAgfaTouch: >+ DBG(DBG_MSG, "Setting params for AgfaTouch\n"); >+ pHWParams->iReversedHead = FALSE; /* head not reversed on Agfa Touch */ >+ pHWParams->iTopLeftX = 3; >+ pHWParams->iTopLeftY = 10; >+ pHWParams->iSkipLines = 7; >+ break; >+ >+ case eUnknownModel: >+ DBG(DBG_MSG, "Setting params for UnknownModel\n"); >+ break; >+ >+ default: >+ DBG(DBG_ERR, "ERROR: internal error! (%d)\n", (int)pHWParams->eModel); >+ return -1; >+ } >+ >+ /* autodetect some hardware properties */ >+ if (!_ProbeRegisters(pHWParams)) { >+ DBG(DBG_ERR, "_ProbeRegisters failed!\n"); >+ return -1; >+ } >+ >+ return 0; >+} >+ >+ >+void Hp3300cClose(THWParams *pHWPar) >+{ >+ Hp3300cXferClose(pHWPar->iXferHandle); >+ pHWPar->iXferHandle = 0; >+} >+ >+ >+static void WriteRegWord(int iHandle, byte bReg, word wData) >+{ >+ Hp3300cRegWrite(iHandle, bReg, wData & 0xFF); >+ Hp3300cRegWrite(iHandle, bReg + 1, (wData >> 8) & 0xFF); >+} >+ >+ >+/* calculate a 4096 byte gamma table */ >+void CalcGamma(byte *pabTable, double Gamma) >+{ >+ int i, iData; >+ >+ /* fill gamma table */ >+ for (i = 0; i < 4096; i++) { >+ iData = floor(256.0 * pow(((double)i / 4096.0), 1.0 / Gamma)); >+ pabTable[i] = iData; >+ } >+} >+ >+ >+/* >+ Hp3400WriteFw >+ ============= >+ Writes data to scanners with a NIASH00019 chipset, e.g. >+ gamma, calibration and motor control data. >+ >+ IN pabData pointer to firmware data >+ iLen Size of firmware date (bytes) >+ iAddr Scanner address to write to >+*/ >+static void Hp3400cWriteFW(int iXferHandle, byte *pabData, int iLen, int iAddr) >+{ >+ iAddr--; >+ Hp3300cRegWrite(iXferHandle, 0x21, iAddr & 0xFF); >+ Hp3300cRegWrite(iXferHandle, 0x22, (iAddr >> 8) & 0xFF); >+ Hp3300cRegWrite(iXferHandle, 0x23, (iAddr >> 16) & 0xFF); >+ Hp3300cBulkWrite(iXferHandle, pabData, iLen); >+} >+ >+ >+/* Writes the gamma and offset/gain tables to the scanner. >+ In case a calibration file exist, it will be used for offset/gain */ >+void WriteGammaCalibTable(byte *pabGammaR, byte *pabGammaG, byte *pabGammaB, >+ byte *pabCalibTable, int iGain, int iOffset, THWParams *pHWPar) >+{ >+ int i, j, k; >+ static byte abGamma[60000]; >+ int iData; >+ int iHandle; >+ >+ iHandle = pHWPar->iXferHandle; >+ >+ j = 0; >+ /* fill gamma table for red component */ >+ /* pad entries with 0 for 16-bit gamma table */ >+ for (i = 0; i < 4096; i++) { >+ if (pHWPar->fGamma16) { >+ abGamma[j++] = 0; >+ } >+ abGamma[j++] = pabGammaR[i]; >+ } >+ /* fill gamma table for green component */ >+ for (i = 0; i < 4096; i++) { >+ if (pHWPar->fGamma16) { >+ abGamma[j++] = 0; >+ } >+ abGamma[j++] = pabGammaG[i]; >+ } >+ /* fill gamma table for blue component */ >+ for (i = 0; i < 4096; i++) { >+ if (pHWPar->fGamma16) { >+ abGamma[j++] = 0; >+ } >+ abGamma[j++] = pabGammaB[i]; >+ } >+ >+ if (pabCalibTable == NULL) { >+ iData = (iGain << 6) + iOffset; >+ for (i = 0; i < HW_PIXELS; i++) { >+ for (k = 0; k < 3; k++) { >+ abGamma[j++] = (iData) & 255; >+ abGamma[j++] = (iData >> 8) & 255; >+ } >+ } >+ } >+ else { >+ memcpy(&abGamma[j], pabCalibTable, HW_PIXELS * 6); >+ j += HW_PIXELS * 6; >+ } >+ >+ Hp3300cRegWrite(iHandle, 0x02, 0x80); >+ Hp3300cRegWrite(iHandle, 0x03, 0x01); >+ Hp3300cRegWrite(iHandle, 0x03, 0x11); >+ Hp3300cRegWrite(iHandle, 0x02, 0x84); >+ >+ if (pHWPar->fReg07) { >+ Hp3400cWriteFW(iHandle, abGamma, j, 0x2000); >+ } >+ else { >+ Hp3300cBulkWrite(iHandle, abGamma, j); >+ } >+ >+ Hp3300cRegWrite(iHandle, 0x02, 0x80); >+} >+ >+ >+static void WriteAFEReg(int iHandle, int iReg, int iData) >+{ >+ Hp3300cRegWrite(iHandle, 0x25, iReg); >+ Hp3300cRegWrite(iHandle, 0x26, iData); >+} >+ >+ >+/* setup the analog front-end -> coarse calibration */ >+static void WriteAFE(int iHandle) >+{ >+ /* see WM8143 datasheet */ >+ >+ WriteAFEReg(iHandle, 0x04, 0x00); >+ WriteAFEReg(iHandle, 0x03, 0x12); >+ WriteAFEReg(iHandle, 0x02, 0x04); >+ WriteAFEReg(iHandle, 0x05, 0x10); >+ WriteAFEReg(iHandle, 0x01, 0x03); >+ >+ WriteAFEReg(iHandle, 0x20, 0xc0);/*c8*/ /* red offset */ >+ WriteAFEReg(iHandle, 0x21, 0xc0);/*c8*/ /* green offset */ >+ WriteAFEReg(iHandle, 0x22, 0xc0);/*d0*/ /* blue offset */ >+ >+ WriteAFEReg(iHandle, 0x28, 0x05);/*5*/ /* red gain */ >+ WriteAFEReg(iHandle, 0x29, 0x03);/*3*/ /* green gain */ >+ WriteAFEReg(iHandle, 0x2A, 0x04);/*4*/ /* blue gain */ >+} >+ >+ >+/* wait for the carriage to return */ >+static void WaitReadyBit(int iHandle) >+{ >+ byte bData; >+ >+ do { >+ Hp3300cRegRead(iHandle, 0x03, &bData); >+ } while ((bData & 8) == 0); >+} >+ >+ >+/* >+ Initialisation specific for NIASH00014 and lower chips >+*/ >+static void InitNiash00014(TScanParams *pParams, THWParams *pHWParams) >+{ >+ int iHandle, iLpiCode; >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ /* exposure time (in units 24/Fcrystal)? */ >+ WriteRegWord(iHandle, 0x08, pHWParams->iExpTime - 1); >+ >+ /* width in pixels */ >+ WriteRegWord(iHandle, 0x12, pParams->iWidth - 1); >+ >+ /* top */ >+ WriteRegWord (iHandle, 0x17, pParams->iTop); >+ WriteRegWord (iHandle, 0x19, pParams->iTop); >+ >+ /* time between stepper motor steps (in units of 24/Fcrystal)? */ >+ iLpiCode = pParams->iLpi * pHWParams->iExpTime / 1200L; >+ >+ if (!pHWParams->fGamma16) { >+ /* NIASH 00012 / 00013 init */ >+ >+ /* LPI specific settings */ >+ if (pParams->iLpi < 600) { >+ /* set halfres bit */ >+ Hp3300cRegWrite(iHandle, 0x06, 0x01); >+ /* double lpi code because of halfres bit */ >+ iLpiCode *= 2; >+ } >+ else { >+ /* clear halfres bit */ >+ Hp3300cRegWrite(iHandle, 0x06, 0x00); >+ /* add exptime to make it scan slower */ >+ iLpiCode += pHWParams->iExpTime; >+ } >+ >+ /* unknown setting */ >+ WriteRegWord (iHandle, 0x27, 0x7FD2); >+ WriteRegWord (iHandle, 0x29, 0x6421); >+ >+ } >+ else { >+ /* NIASH 00014 init */ >+ >+ /* halfres bit always cleared */ >+ Hp3300cRegWrite(iHandle, 0x06, 0x00); >+ >+ /* LPI specific settings */ >+ if (pParams->iLpi >= 600) { >+ /* add exptime to make it scan slower */ >+ iLpiCode += pHWParams->iExpTime; >+ } >+ >+ /* unknown setting */ >+ WriteRegWord (iHandle, 0x27, 0xc862);/*c862 */ >+ WriteRegWord (iHandle, 0x29, 0xb853);/*b853 */ >+ } >+ >+ /* LPI code */ >+ WriteRegWord(iHandle, 0x0A, iLpiCode - 1); >+ >+ /* backtrack reversing speed */ >+ Hp3300cRegWrite(iHandle, 0x1E, (iLpiCode - 1) / 32); >+} >+ >+ >+/* >+ Initialisation specific for NIASH00019 chips >+*/ >+static void InitNiash00019(TScanParams *pParams, THWParams *pHWParams) >+{ >+ int iHandle, iLpiCode; >+ static byte abMotor[512]; >+ >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ /* exposure time (in units 24/Fcrystal)? */ >+ WriteRegWord (iHandle, 0x08, pHWParams->iExpTime); >+ >+ /* width in pixels */ >+ WriteRegWord (iHandle, 0x12, pParams->iWidth); >+ >+ /* ? */ >+ WriteRegWord (iHandle, 0x27, 0xc862);/*c862 */ >+ WriteRegWord (iHandle, 0x29, 0xb853);/*b853 */ >+ >+ /* specific handling of 150 dpi resolution */ >+ if (pParams->iLpi == 150) { >+ /* use 300 LPI but skip every other line */ >+ pParams->iLpi = 300; >+ Hp3300cRegWrite(iHandle, 0x06, 0x01); >+ } >+ else { >+ Hp3300cRegWrite(iHandle, 0x06, 0x00); >+ } >+ >+ /* DPI and position table */ >+ Hp3300cRegWrite (iHandle, 0x07, 0x02); >+ _ConvertMotorTable(abData0000, abMotor, sizeof(abData0000), pParams->iLpi); >+ Hp3400cWriteFW(iHandle, abMotor, sizeof(abData0000), 0x000); >+ _ConvertMotorTable(abData0400, abMotor, sizeof(abData0400), pParams->iLpi); >+ Hp3400cWriteFW(iHandle, abMotor, sizeof(abData0400), 0x400); >+ >+ /* backtrack reversing speed */ >+ iLpiCode = pParams->iLpi * pHWParams->iExpTime / 1200L; >+ Hp3300cRegWrite(iHandle, 0x1E, (iLpiCode - 1) / 32); >+} >+ >+ >+/* >+ Scanner initialisation common to all NIASH chips >+*/ >+static void InitNiashCommon(TScanParams *pParams, THWParams *pHWParams) >+{ >+ int iWidthHW, iHandle, iMaxLevel; >+ >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ Hp3300cRegWrite (iHandle, 0x02, 0x80); >+ Hp3300cRegWrite (iHandle, 0x03, 0x11); >+ Hp3300cRegWrite (iHandle, 0x01, 0x8B); >+ Hp3300cRegWrite (iHandle, 0x05, 0x01); >+ >+ /* dpi */ >+ WriteRegWord (iHandle, 0x0C, pParams->iDpi); >+ >+ /* calculate width in units of HW resolution */ >+ iWidthHW = pParams->iWidth * (HW_DPI / pParams->iDpi); >+ >+ /* set left and right limits */ >+ if ( pHWParams->iReversedHead ) { >+ /* head is reversed */ >+ /* right */ >+ WriteRegWord (iHandle, 0x0E, 3 * (HW_PIXELS - (pParams->iLeft + iWidthHW)) ); >+ >+ /* left */ >+ WriteRegWord (iHandle, 0x10, 3 * (HW_PIXELS - pParams->iLeft) - 1); >+ } else { >+ /* head is not reversed */ >+ /*left */ >+ WriteRegWord (iHandle, 0x0E, 3 * pParams->iLeft); >+ >+ /* right */ >+ WriteRegWord (iHandle, 0x10, 3 * (pParams->iLeft + iWidthHW) - 1); >+ } >+ >+ /* bottom */ >+ WriteRegWord (iHandle, 0x1B, pParams->iBottom); /* 0x393C); */ >+ >+ /* forward jogging speed */ >+ Hp3300cRegWrite (iHandle, 0x1D, 0x60); >+ >+ /* backtrack reversing speed? */ >+ Hp3300cRegWrite (iHandle, 0x2B, 0x15); >+ >+ /* backtrack distance */ >+ if (pParams->iLpi < 600) { >+ Hp3300cRegWrite(iHandle, 0x1F, 0x30); >+ } >+ else { >+ Hp3300cRegWrite(iHandle, 0x1F, 0x18); >+ } >+ >+ /* max buffer level before backtrace */ >+ iMaxLevel = MIN(pHWParams->iBufferSize / pParams->iWidth, 250); >+ Hp3300cRegWrite (iHandle, 0x14, iMaxLevel - 1); >+ >+ /* lamp PWM, max = 0x1ff? */ >+ WriteRegWord (iHandle, 0x2C, 0x01FF); >+ >+ /* not needed? */ >+ Hp3300cRegWrite (iHandle, 0x15, 0x90);/* 90 */ >+ Hp3300cRegWrite (iHandle, 0x16, 0x70);/* 70 */ >+ >+ WriteAFE(iHandle); >+ >+ WaitReadyBit(iHandle); >+ >+ Hp3300cRegWrite (iHandle, 0x03, 0x05); >+ >+ Hp3300cRegWrite(iHandle, 0x02, pParams->fCalib ? 0x88 : 0xA8); >+} >+ >+ >+/* write registers */ >+bool InitScan(TScanParams *pParams, THWParams *pHWParams) >+{ >+ int iHeight; >+ int iExpTime; >+ TScanParams Params; >+ int iHandle; >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ /* check validity of scanparameters */ >+ switch (pParams->iDpi) { >+ case 150: case 300: case 600: >+ break; >+ default: >+ DBG(DBG_ERR, "Invalid dpi (%d)\n", pParams->iDpi); >+ return FALSE; >+ } >+ >+ iHeight = (pParams->iBottom - pParams->iTop + 1); >+ if (iHeight <= 0) { >+ DBG(DBG_ERR, "Invalid height (%d)\n", iHeight); >+ return FALSE; >+ } >+ >+ if (pParams->iWidth <= 0) { >+ DBG(DBG_ERR, "Invalid width (%d)\n", pParams->iWidth); >+ return FALSE; >+ } >+ >+ switch (pParams->iLpi) { >+ case 150: case 300: case 600: >+ break; >+ default: >+ DBG(DBG_ERR, "Invalid lpi (%d)\n", pParams->iLpi); >+ return FALSE; >+ } >+ >+ /* exposure time (in units of 24/Fcrystal?), must be divisible by 8 !!! */ >+ iExpTime = 5408; >+ if ((iExpTime % 8) != 0) { >+ DBG(DBG_ERR, "Invalid exposure time (%d)\n", iExpTime); >+ return FALSE; >+ } >+ >+ /* >+ *** Done checking scan parameters validity *** >+ */ >+ >+ /* >+ copy the parameters locally and make pParams point to the local copy >+ */ >+ memcpy(&Params, pParams, sizeof(Params)); >+ pParams = &Params; >+ >+ if (!pHWParams->fReg07) { >+ /* init NIASH00014 and lower */ >+ InitNiash00014(pParams, pHWParams); >+ } >+ else { >+ /* init NIASH00019 */ >+ InitNiash00019(pParams, pHWParams); >+ } >+ >+ /* common NIASH init */ >+ InitNiashCommon(pParams, pHWParams); >+ >+ return TRUE; >+} >+ >+ >+/************************************************************************/ >+ >+static void XferBufferGetLine(int iHandle, TDataPipe *p, byte *pabLine) >+{ >+ byte bData; >+ >+ /* time for a fresh read? */ >+ if (p->iCurLine == 0) { >+ /* DBG(DBG_MSG, "Reading buffer %d bytes\n", _iLinesPerXferBuf >+ * _iBytesPerLine); */ >+ Hp3300cRegRead(iHandle, 0x20, &bData); >+ DBG(DBG_MSG, "buffer level = %3d, <reading %5d bytes>, ", >+ (int)bData, p->iLinesPerXferBuf * p->iBytesPerLine); >+ Hp3300cBulkRead(iHandle, p->pabXferBuf, p->iLinesPerXferBuf * p->iBytesPerLine); >+ Hp3300cRegRead(iHandle, 0x20, &bData); >+ DBG(DBG_MSG, "buffer level = %3d\r", bData); >+ fflush(stdout); >+ } >+ /* copy one line */ >+ if (pabLine != NULL) { >+ memcpy(pabLine, &p->pabXferBuf[p->iCurLine * p->iBytesPerLine], p->iBytesPerLine); >+ } >+ /* advance pointer */ >+ p->iCurLine = (p->iCurLine + 1) % p->iLinesPerXferBuf; >+} >+ >+ >+static void XferBufferInit(int iHandle, TDataPipe *p) >+{ >+ int i; >+ >+ p->pabXferBuf = (byte *)malloc(XFER_BUF_SIZE); >+ p->iCurLine = 0; >+ >+ /* skip garbage lines */ >+ for (i = 0; i < p->iSkipLines; i++) { >+ XferBufferGetLine(iHandle, p, NULL); >+ } >+} >+ >+ >+static void XferBufferExit(TDataPipe *p) >+{ >+ if (p->pabXferBuf != NULL) { >+ free(p->pabXferBuf); >+ p->pabXferBuf = NULL; >+ } >+ else { >+ DBG(DBG_ERR, "XferBufExit: Xfer buffer not initialised!\n"); >+ } >+} >+ >+ >+/* unscrambles a line: >+ - combining the proper R, G and B lines and converting them to interpixel RGB >+ - mirroring left to right >+*/ >+static void _UnscrambleLine(byte *pabLine, >+ byte *pabRed, byte *pabGrn, byte *pabBlu, int iWidth, bool iReversedHead) >+{ >+ int i, j; >+ if (iReversedHead) { >+ /* reversed */ >+ for (i = 0; i < iWidth; i++) { >+ j = (iWidth - i) * 3; >+ pabLine[j - 3] = pabRed[i]; >+ pabLine[j - 2] = pabGrn[i + iWidth]; >+ pabLine[j - 1] = pabBlu[i + iWidth * 2]; >+ } >+ } else { >+ /* not reversed */ >+ for (i = 0; i < iWidth; i++) { >+ pabLine[3 * i] = pabRed[i]; >+ pabLine[3 * i + 1] = pabGrn[i + iWidth]; >+ pabLine[3 * i + 2] = pabBlu[i + iWidth * 2]; >+ } >+ } >+} >+ >+ >+/* gets an unscrambled line from the circular buffer. the first couple of lines contain garbage */ >+void CircBufferGetLine(int iHandle, TDataPipe *p, byte *pabLine, bool iReversedHead) >+{ >+ if (iReversedHead) { >+ XferBufferGetLine(iHandle, p, &p->pabCircBuf[p->iRedLine * p->iBytesPerLine]); >+ } else { >+ XferBufferGetLine(iHandle, p, &p->pabCircBuf[p->iBluLine * p->iBytesPerLine]); >+ } >+ >+ if (pabLine != NULL) { >+ _UnscrambleLine(pabLine, >+ &p->pabCircBuf[p->iRedLine * p->iBytesPerLine], >+ &p->pabCircBuf[p->iGrnLine * p->iBytesPerLine], >+ &p->pabCircBuf[p->iBluLine * p->iBytesPerLine], >+ p->iBytesPerLine / 3, >+ iReversedHead); >+ } >+ >+ /* advance pointers */ >+ p->iRedLine = (p->iRedLine + 1) % p->iLinesPerCircBuf; >+ p->iGrnLine = (p->iGrnLine + 1) % p->iLinesPerCircBuf; >+ p->iBluLine = (p->iBluLine + 1) % p->iLinesPerCircBuf; >+} >+ >+ >+void CircBufferInit(int iHandle, TDataPipe *p, int iBytesPerLine, int iMisAlignment, bool iReversedHead) >+{ >+ int i; >+ >+ p->iBytesPerLine = iBytesPerLine; >+ if (iMisAlignment == 0) { >+ p->iLinesPerCircBuf = 1; >+ } >+ else { >+ p->iLinesPerCircBuf = 3 * iMisAlignment; >+ } >+ >+ DBG(DBG_MSG, "_iBytesPerLine = %d\n", p->iBytesPerLine); >+ DBG(DBG_MSG, "_iLinesPerCircBuf = %d\n", p->iLinesPerCircBuf); >+ p->pabCircBuf = (byte *)malloc(iBytesPerLine * p->iLinesPerCircBuf); >+ if (p->pabCircBuf == NULL) { >+ DBG(DBG_ERR, "Unable to allocate %d bytes for circular buffer\n", (int)(iBytesPerLine * p->iLinesPerCircBuf)); >+ return; >+ } >+ DBG(DBG_MSG, "Allocated %d bytes for circular buffer\n", iBytesPerLine * p->iLinesPerCircBuf); >+ >+ if (iReversedHead) { >+ p->iBluLine = 0; >+ p->iGrnLine = iMisAlignment; >+ p->iRedLine = iMisAlignment * 2; >+ } else { >+ p->iRedLine = 0; >+ p->iGrnLine = iMisAlignment; >+ p->iBluLine = iMisAlignment * 2; >+ } >+ >+ p->iLinesPerXferBuf = XFER_BUF_SIZE / iBytesPerLine; >+ DBG(DBG_MSG, "_iLinesPerXferBuf = %d\n", p->iLinesPerXferBuf); >+ DBG(DBG_MSG, "Xfer block size = %d\n", p->iLinesPerXferBuf * p->iBytesPerLine); >+ >+ /* init transfer buffer */ >+ XferBufferInit(iHandle, p); >+ >+ /* fill circular buffer */ >+ for (i = 0; i < p->iLinesPerCircBuf; i++) { >+ CircBufferGetLine(iHandle, p, NULL, iReversedHead); >+ } >+} >+ >+ >+void CircBufferExit(TDataPipe *p) >+{ >+ XferBufferExit(p); >+ if (p->pabCircBuf != NULL) { >+ DBG(DBG_MSG, "\n"); >+ free(p->pabCircBuf); >+ p->pabCircBuf = NULL; >+ } >+ else { >+ DBG(DBG_ERR, "CircBufferExit: Circular buffer not initialised!\n"); >+ } >+} >+ >+ >+/************************************************************************/ >+ >+/************************************************************************* >+ ScanLines >+ ========= >+ Helper function to scan in an image and output the result to a file. >+ >+ IN pFile File to write image data to >+ pParams User-defineable settings describing the image to be scanned >+ pHWParams Scanner hardware settings >+ >+*************************************************************************/ >+void ScanLines(FILE *pFile, TScanParams *pParams, THWParams *pHWParams) >+{ >+ static byte abBuf[HW_PIXELS * 3]; >+ int iBytesPerLine; >+ int iHeight; >+ int iHandle; >+ bool iReversedHead; >+ TDataPipe DataPipe; >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ iHeight = pParams->iHeight; >+ iBytesPerLine = pParams->iWidth * 3; >+ DataPipe.iSkipLines = 0; >+ iReversedHead = pHWParams->iReversedHead; >+ >+ if (InitScan(pParams, pHWParams)) { >+ CircBufferInit(iHandle, &DataPipe, iBytesPerLine, pHWParams->iSensorSkew * pParams->iLpi / HW_LPI, iReversedHead); >+ while (iHeight-- > 0) { >+ CircBufferGetLine(iHandle, &DataPipe, abBuf, iReversedHead); >+ fwrite(abBuf, 1, iBytesPerLine, pFile); >+ } >+ CircBufferExit(&DataPipe); >+ } >+ FinishScan(pHWParams); >+} >+ >+ >+static int _CalcAvg(byte *pabBuf, int n, int iStep) >+{ >+ int i, j, x; >+ >+ for (i = j = x = 0; i < n; i++) { >+ x += pabBuf[j]; >+ j += iStep; >+ } >+ return (x / n); >+} >+ >+ >+/* converts white line data and black point data into a calibration table */ >+static void CreateCalibTable(byte *abWhite, byte bBlackR, byte bBlackG, >+ byte bBlackB, int iReversedHead, byte *pabCalibTable) >+{ >+ int i, j, iGain, iOffset, iData; >+ byte *pabPixel; >+ >+ j = 0; >+ for (i = 0; i < HW_PIXELS; i++) { >+ if (iReversedHead) { >+ pabPixel = &abWhite[(HW_PIXELS - i - 1) * 3]; >+ } >+ else { >+ pabPixel = &abWhite[i * 3]; >+ } >+ /* red */ >+ if (bBlackR > 16) bBlackR = 16 ; >+ iGain = 65536 / MAX(1, pabPixel[0] - bBlackR); >+ iOffset = bBlackR * 4; >+ if (iOffset > 63) iOffset = 63 ; >+ iData = (iGain << 6) + iOffset; >+ pabCalibTable[j++] = (iData) & 255; >+ pabCalibTable[j++] = (iData >> 8) & 255; >+ /* green */ >+ if (bBlackG > 16) bBlackG = 16 ; >+ iGain = 65536 / MAX(1, pabPixel[1] - bBlackG); >+ iOffset = bBlackG * 4; >+ if (iOffset > 63) iOffset = 63 ; >+ iData = (iGain << 6) + iOffset; >+ pabCalibTable[j++] = (iData) & 255; >+ pabCalibTable[j++] = (iData >> 8) & 255; >+ /* blue */ >+ if (bBlackB > 16) bBlackB = 16 ; >+ iGain = 65536 / MAX(1, pabPixel[2] - bBlackB); >+ iOffset = bBlackB * 4; >+ if (iOffset > 63) iOffset = 63 ; >+ iData = (iGain << 6) + iOffset; >+ pabCalibTable[j++] = (iData) & 255; >+ pabCalibTable[j++] = (iData >> 8) & 255; >+ } >+} >+ >+ >+/************************************************************************* >+ Lamp control functions >+*************************************************************************/ >+bool GetLamp(THWParams *pHWParams, bool *pfLampIsOn) >+{ >+ byte bData; >+ >+ Hp3300cRegRead(pHWParams->iXferHandle, 0x03, &bData); >+ *pfLampIsOn = ((bData & 0x01) != 0); >+ return TRUE; >+} >+ >+ >+bool SetLamp(THWParams *pHWParams, bool fLampOn) >+{ >+ byte bData; >+ int iHandle; >+ >+ iHandle = pHWParams->iXferHandle; >+ >+ Hp3300cRegRead(iHandle, 0x03, &bData); >+ if (fLampOn) { >+ Hp3300cRegWrite(iHandle, 0x03, bData | 0x01); >+ } >+ else { >+ Hp3300cRegWrite(iHandle, 0x03, bData & ~0x01); >+ } >+ return TRUE; >+} >+ >+ >+/************************************************************************* >+ Experimental simple calibration >+ >+ Basic idea: >+ * a strip starting at position 0 is scanned in >+ * per-pixel white level is determined by average of first 4 lines >+ * global black level is determined by minimum value of all lines >+*************************************************************************/ >+bool SimpleCalib(THWParams *pHWPar, byte *pabCalibTable) >+{ >+ byte bMinR, bMinG, bMinB; >+ TDataPipe DataPipe; >+ TScanParams Params; >+ byte abGamma[4096]; >+ int i, j; >+ static byte abBuf[HW_PIXELS * 3 * 71]; /* Carefull : see startWhite and endWhite below */ >+ static byte abLine[HW_PIXELS * 3]; >+ static byte abWhite[HW_PIXELS * 3]; >+ byte *pabWhite; >+ int iWhiteR, iWhiteG, iWhiteB; >+ int iHandle; >+ bool iReversedHead; >+ int startWhiteY, endWhiteY ; >+ int startBlackY, endBlackY ; >+ int startBlackX, endBlackX ; >+ >+ iHandle = pHWPar->iXferHandle; >+ iReversedHead = pHWPar->iReversedHead; >+ >+ DataPipe.iSkipLines = pHWPar->iSkipLines; >+ >+ Params.iDpi = HW_DPI; >+ Params.iLpi = HW_DPI; >+ if (iReversedHead) /* hp scanners */ >+ Params.iTop = 60; >+ else /* agfa scanners */ >+ Params.iTop = 30 ; >+ Params.iBottom = HP3300C_BOTTOM; >+ Params.iLeft = 0; >+ Params.iWidth = HW_PIXELS; >+ Params.iHeight = 54; >+ Params.fCalib = TRUE; >+ >+ /* write gamma table with neutral gain / offset */ >+ CalcGamma(abGamma, 1.0); >+ WriteGammaCalibTable(abGamma, abGamma, abGamma, NULL, 256, 0, pHWPar); >+ >+ if (!InitScan(&Params, pHWPar)) { >+ return FALSE; >+ } >+ >+ /* Definition of white and black areas */ >+ if (iReversedHead) { /* hp scanners */ >+ startWhiteY = 0 ; >+ endWhiteY = 15 ; >+ startBlackY = 16 ; >+ endBlackY = 135 ; >+ startBlackX = 0 ; >+ endBlackX = HW_PIXELS ; >+ } else { /* agfa scanners */ >+ startWhiteY = 0 ; >+ endWhiteY = 70 ; >+ startBlackY = 86 ; >+ endBlackY = 135 ; >+ startBlackX = 1666 ; >+ endBlackX = 3374 ; >+ } >+ >+ CircBufferInit(iHandle, &DataPipe, HW_PIXELS * 3, Params.iLpi / 150, iReversedHead); >+ /* white level */ >+ /* skip some lines */ >+ for (i = 0; i < startWhiteY; i++) { >+ CircBufferGetLine(iHandle, &DataPipe, abLine, iReversedHead); >+ } >+ /* Get white lines */ >+ for (i = 0; i < endWhiteY - startWhiteY + 1; i++) { >+ CircBufferGetLine(iHandle, &DataPipe, &abBuf[i * HW_PIXELS * 3], iReversedHead); >+ } >+ /* black level */ >+ bMinR = 255; bMinG = 255; bMinB = 255; >+ /* Skip some lines */ >+ for (i = 0; i < startBlackY; i++) { >+ CircBufferGetLine(iHandle, &DataPipe, abLine, iReversedHead); >+ } >+ for (i = 0; i < endBlackY - startBlackY + 1; i++) { >+ CircBufferGetLine(iHandle, &DataPipe, abLine, iReversedHead); >+ for (j = 0; j < endBlackX; j++) { >+ bMinR = MIN(abLine[j * 3 + 0], bMinR); >+ bMinG = MIN(abLine[j * 3 + 1], bMinG); >+ bMinB = MIN(abLine[j * 3 + 2], bMinB); >+ } >+ } >+ CircBufferExit(&DataPipe); >+ FinishScan(pHWPar); >+ >+ /* calc average white level */ >+ pabWhite = abBuf; >+ for (i = 0; i < HW_PIXELS; i++) { >+ abWhite[i * 3 + 0] = _CalcAvg(&pabWhite[i * 3 + 0], endWhiteY - startWhiteY + 1, HW_PIXELS * 3); >+ abWhite[i * 3 + 1] = _CalcAvg(&pabWhite[i * 3 + 1], endWhiteY - startWhiteY + 1, HW_PIXELS * 3); >+ abWhite[i * 3 + 2] = _CalcAvg(&pabWhite[i * 3 + 2], endWhiteY - startWhiteY + 1, HW_PIXELS * 3); >+ } >+ iWhiteR = _CalcAvg(&abWhite[0], HW_PIXELS, 3); >+ iWhiteG = _CalcAvg(&abWhite[1], HW_PIXELS, 3); >+ iWhiteB = _CalcAvg(&abWhite[2], HW_PIXELS, 3); >+ >+ DBG(DBG_MSG, "Black level (%d,%d,%d), White level (%d,%d,%d)\n", >+ (int)bMinR, (int)bMinG, (int)bMinB, iWhiteR, iWhiteG, iWhiteB); >+ >+ /* convert the white line and black point into a calibration table */ >+ CreateCalibTable(abWhite, bMinR, bMinG, bMinB, iReversedHead, >+ pabCalibTable); >+ >+ return TRUE; >+} >+ >+ >+/************************************************************************* >+ FinishScan >+ ========== >+ Finishes the scan. Makes the scanner head move back to the home position. >+ >+*************************************************************************/ >+void FinishScan(THWParams *pHWParams) >+{ >+ Hp3300cRegWrite(pHWParams->iXferHandle, 0x02, 0x80); >+} >+ >+ >+ >diff -ruN sane-backends-1.0.12/backend/hp3300c.h sane-backends-1.0.12-patched/backend/hp3300c.h >--- sane-backends-1.0.12/backend/hp3300c.h 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c.h 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,113 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c.h,v 1.24 2002/11/04 23:48:32 bertrik Exp $ >+*/ >+ >+/* >+ Core HP3300c functions. >+*/ >+ >+ >+#ifndef _HP3300C_H_ >+#define _HP3300C_H_ >+ >+#include <unistd.h> >+ >+#include "mytypes.h" >+#include "hp3300c_xfer.h" /* for EScannerModel */ >+ >+#define HP3300C_RIGHT 330 >+#define HP3300C_TOP 452 >+#define HP3300C_BOTTOM (HP3300C_TOP + 14200UL) >+ >+#define HW_PIXELS 5300 /* number of pixels supported by hardware */ >+#define HW_DPI 600 /* horizontal resolution of hardware */ >+#define HW_LPI 1200 /* vertical resolution of hardware */ >+ >+ >+typedef struct { >+ int iXferHandle; /* handle used for data transfer to HW */ >+ int iTopLeftX; /* in mm */ >+ int iTopLeftY; /* in mm */ >+ int iSensorSkew; /* in units of 1/1200 inch */ >+ int iSkipLines; /* lines of garbage to skip */ >+ bool fReg07; /* NIASH00019 */ >+ bool fGamma16; /* if TRUE, gamma entries are 16 bit */ >+ int iExpTime; >+ bool iReversedHead; /* Head is reversed */ >+ int iBufferSize; /* Size of internal scan buffer */ >+ EScannerModel eModel; >+} THWParams; >+ >+ >+typedef struct { >+ int iDpi; /* horizontal resolution */ >+ int iLpi; /* vertical resolution */ >+ int iTop; /* in HW coordinates */ >+ int iLeft; /* in HW coordinates */ >+ int iWidth; /* pixels */ >+ int iHeight; /* lines */ >+ int iBottom; >+ >+ int fCalib; /* if TRUE, disable backtracking? */ >+} TScanParams; >+ >+ >+typedef struct { >+ /* transfer buffer */ >+ byte *pabXferBuf; >+ int iCurLine, iBytesPerLine, iLinesPerXferBuf; >+ int iSkipLines; >+ /* circular buffer */ >+ byte *pabCircBuf; >+ int iLinesPerCircBuf; >+ int iRedLine, iGrnLine, iBluLine; >+ /* current line buffer */ >+ byte *pabLineBuf; >+ int iBytesLeft; >+} TDataPipe; >+ >+ >+int Hp3300cOpen(THWParams *pHWParams, char *pszName); >+void Hp3300cClose(THWParams *pHWParams); >+ >+void DumpHex(byte *pabData, int iLen, int iWidth); >+ >+void ScanLines(FILE *pFile, TScanParams *pParams, THWParams *pHWParams); >+bool SimpleCalib(THWParams *pHWPar, byte *pabCalibTable); >+ >+bool GetLamp(THWParams *pHWParams, bool *pfLampIsOn); >+bool SetLamp(THWParams *pHWParams, bool fLampOn); >+ >+bool InitScan(TScanParams *pParams, THWParams *pHWParams); >+void FinishScan(THWParams *pHWParams); >+ >+void CalcGamma(byte *pabTable, double Gamma); >+void WriteGammaCalibTable( byte *pabGammaR, byte *pabGammaG, byte *pabGammaB, >+ byte *pabCalibTable, int iGain, int iOffset, >+ THWParams *pHWPar); >+ >+void CircBufferInit(int iHandle, TDataPipe *p, int iBytesPerLine, >+ int iMisAlignment, bool iReversedHead); >+void CircBufferGetLine(int iHandle, TDataPipe *p, byte *pabLine, >+ bool iReversedHead); >+void CircBufferExit(TDataPipe *p); >+ >+ >+#endif /* NO _HP3300C_H_ */ >+ >diff -ruN sane-backends-1.0.12/backend/hp3300c_ieee1284.c sane-backends-1.0.12-patched/backend/hp3300c_ieee1284.c >--- sane-backends-1.0.12/backend/hp3300c_ieee1284.c 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c_ieee1284.c 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,229 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c_ieee1284.c,v 1.8 2002/11/19 22:58:31 bertrik Exp $ >+*/ >+ >+/* >+ Provides a simple interface to read and write data from the scanner, >+ without any knowledge whether it's a parallel or USB scanner >+*/ >+ >+#ifdef LIBIEEE1284_SUPPORT >+ >+#include "mytypes.h" >+#include "hp3300c_xfer.h" >+ >+#include "ieee1284.h" >+ >+ >+void >+ParInit(TFnReportDevice *pfnReportDevice) >+{ >+ int i; >+ static char abDeviceId[256]; >+ struct parport *pMyPort; >+ struct parport_list mylist; >+ TScannerModel *pModel; >+ >+ pMyPort = (struct parport *)-1; >+ >+ ieee1284_find_ports(&mylist, 0); >+ DBG(DBG_MSG, "Found %d parallel ports:\n", mylist.portc); >+ >+ for (i = 0; i < mylist.portc; i++) { >+ pMyPort = mylist.portv[i]; >+ DBG(DBG_MSG, "Port %3d : %s\n", i, pMyPort->name); >+ >+ /* try to get a device id, no daisy chain assumed */ >+ memset(abDeviceId, 0, sizeof(abDeviceId)); >+ if (ieee1284_get_deviceid(pMyPort, -1, 0, abDeviceId, sizeof(abDeviceId) - 1) >= 0) { >+ DBG(DBG_MSG, "Device ID: %s\n", abDeviceId + 2); >+ } >+ >+ /* hack: for now just let pModel to the first entry of ScannerModels */ >+ pModel = ScannerModels; >+ >+ pfnReportDevice(pModel, (char *)pMyPort->name); >+ } >+ ieee1284_free_ports(&mylist); >+} >+ >+ >+static int >+ParOpen(char *pszName, EScannerModel *peModel) >+{ >+ struct parport *pMyPort; >+ struct parport_list mylist; >+ int i, iCaps, iResult; >+ >+ iResult = -1; >+ ieee1284_find_ports(&mylist, 0); >+ for (i = 0; i < mylist.portc; i++) { >+ pMyPort = mylist.portv[i]; >+ if (strcmp(pMyPort->name, pszName) == 0) { >+ /* open port non-exclusively (exclusive won't work?) */ >+ if (ieee1284_open(pMyPort, 0, &iCaps) != E1284_OK) { >+ DBG(DBG_MSG, "Failed to open %s\n", pMyPort->name); >+ break; >+ } >+ >+ /* claim the port. We're abusing a bit here because a claim should be >+ reasonably short, while we keep the port claimed continuously. >+ */ >+ if (ieee1284_claim(pMyPort) != E1284_OK) { >+ DBG(DBG_MSG, "Failed to claim %s\n", pMyPort->name); >+ ieee1284_close(pMyPort); >+ break; >+ } >+ >+ DBG(DBG_MSG, "Successfully claimed %s, capabilities %04X\n", pMyPort->name, >+ iCaps); >+ iResult = (int)pMyPort; >+ break; >+ } >+ } >+ ieee1284_free_ports(&mylist); >+ return iResult; >+} >+ >+ >+static void >+ParClose(int iHandle) >+{ >+ struct parport *pMyPort; >+ >+ if (iHandle < 0) { >+ DBG(DBG_ERR, "ParExit: nothing to close\n"); >+ return; >+ } >+ >+ pMyPort = (struct parport *)iHandle; >+ >+ ieee1284_release(pMyPort); >+ ieee1284_close(pMyPort); >+} >+ >+ >+static void ParWriteReg(int iHandle, byte bReg, byte bData) >+{ >+ int iRet; >+ struct parport *pMyPort; >+ >+ pMyPort = (struct parport *)iHandle; >+ >+ switch (bReg) { >+ case EPP_ADDR: >+ iRet = ieee1284_epp_write_addr(pMyPort, 0, &bData, 1); >+ if (iRet < 0) { >+ DBG(DBG_ERR, "ieee1284_epp_write_addr failed (%d)\n", iRet); >+ } >+ break; >+ case EPP_DATA_WRITE: >+ iRet = ieee1284_epp_write_data(pMyPort, 0, &bData, 1); >+ if (iRet < 0) { >+ DBG(DBG_ERR, "ieee1284_epp_write_data failed (%d)\n", iRet); >+ } >+ break; >+ case SPP_CONTROL: >+ /* TODO: check direction bit and explicitly set direction */ >+ ieee1284_write_control(pMyPort, bData); >+ break; >+ case SPP_DATA: >+ ieee1284_write_data(pMyPort, bData); >+ break; >+ default: >+ DBG(DBG_ERR, "Invalid write function requested (%d)\n", bReg); >+ break; >+ } >+} >+ >+ >+static void >+ParReadReg(int iHandle, byte bReg, byte *pbData) >+{ >+ int iRet; >+ struct parport *pMyPort; >+ >+ pMyPort = (struct parport *)iHandle; >+ >+ switch (bReg) { >+ case EPP_ADDR: >+ iRet = ieee1284_epp_read_addr(pMyPort, 0, pbData, 1); >+ if (iRet < 0) { >+ DBG(DBG_ERR, "ieee1284_epp_read_addr failed (%d)\n", iRet); >+ } >+ break; >+ case EPP_DATA_READ: >+ iRet = ieee1284_epp_read_data(pMyPort, 0, pbData, 1); >+ if (iRet < 0) { >+ DBG(DBG_ERR, "ieee1284_epp_read_data failed (%d)\n", iRet); >+ } >+ break; >+ case SPP_CONTROL: >+ *pbData = ieee1284_read_control(pMyPort); >+ break; >+ case SPP_DATA: >+ *pbData = ieee1284_read_data(pMyPort); >+ break; >+ default: >+ DBG(DBG_ERR, "Invalid read function requested (%d)\n", bReg); >+ break; >+ } >+} >+ >+ >+static void >+ParWriteBulk(int iHandle, byte *pabData, int iSize) >+{ >+ int iRet; >+ struct parport *pMyPort; >+ >+ pMyPort = (struct parport *)iHandle; >+ iRet = ieee1284_epp_write_data(pMyPort, 0, pabData, iSize); >+ if (iRet < 0) { >+ DBG(DBG_ERR, "ieee1284_epp_write_data failed (%d)\n", iRet); >+ } >+} >+ >+ >+static void >+ParReadBulk(int iHandle, byte *pabData, int iSize) >+{ >+ int iRet; >+ struct parport *pMyPort; >+ >+ pMyPort = (struct parport *)iHandle; >+ iRet = ieee1284_epp_read_data(pMyPort, 0, pabData, iSize); >+ if (iRet < 0) { >+ DBG(DBG_ERR, "ieee1284_epp_write_data failed (%d)\n", iRet); >+ } >+} >+ >+ >+XferModule IEEE1284Dev = { >+ "LibIEEE1284 parallel port", >+ ParInit, >+ ParOpen, >+ ParClose, >+ ParWriteReg, >+ ParReadReg, >+ ParWriteBulk, >+ ParReadBulk >+}; >+ >+#endif /* LIBIEEE1284_SUPPORT */ >diff -ruN sane-backends-1.0.12/backend/hp3300c_saneiusb.c sane-backends-1.0.12-patched/backend/hp3300c_saneiusb.c >--- sane-backends-1.0.12/backend/hp3300c_saneiusb.c 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c_saneiusb.c 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,191 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c_saneiusb.c,v 1.9 2002/11/12 21:24:43 bertrik Exp $ >+*/ >+ >+/* >+ This is the sanei_usb transfer method >+*/ >+ >+#include "mytypes.h" >+ >+#include <stdio.h> /* printf */ >+#include <sane/sanei_usb.h> >+ >+#include "hp3300c_xfer.h" >+ >+ >+static TFnReportDevice *_pfnReportDevice; >+static TScannerModel *_pModel; >+ >+ >+static void _SaneiUsbWriteControl(int fd, byte bValue, byte *pabData, int iSize) >+{ >+ sanei_usb_control_msg(fd, >+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, >+ (iSize > 1) ? 0x04 : 0x0C, >+ bValue, >+ 0, >+ iSize, >+ pabData); >+} >+ >+ >+static void _SaneiUsbReadControl(int fd, byte bValue, byte *pabData, int iSize) >+{ >+ sanei_usb_control_msg(fd, >+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, >+ (iSize > 1) ? 0x04 : 0x0C, >+ bValue, >+ 0, >+ iSize, >+ pabData); >+} >+ >+ >+/* callback for sanei_usb_attach_matching_devices */ >+static SANE_Status _AttachUsb(SANE_String_Const devname) >+{ >+ DBG(DBG_MSG, "_AttachUsb: found %s\n", devname); >+ >+ _pfnReportDevice(_pModel, (char *)devname); >+ >+ return SANE_STATUS_GOOD; >+} >+ >+ >+static void UsbInit(TFnReportDevice *pfnReportDevice) >+{ >+ TScannerModel *pModels = ScannerModels; >+ >+ sanei_usb_init(); >+ _pfnReportDevice = pfnReportDevice; >+ >+ /* loop over all scanner models */ >+ while (pModels->pszName != NULL) { >+ DBG(DBG_MSG, "Looking for %s...\n", 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"); >+ break; >+ } >+ pModels++; >+ } >+} >+ >+ >+static int UsbOpen(char *pszName, EScannerModel *peModel) >+{ >+ SANE_Status status; >+ SANE_Word vendor, product; >+ int fd; >+ TScannerModel *pModel; >+ >+ DBG(DBG_MSG, "Trying to open %s...\n", pszName); >+ >+ status = sanei_usb_open(pszName, &fd); >+ if (status != SANE_STATUS_GOOD) { >+ return -1; >+ } >+ >+ status = sanei_usb_get_vendor_product(fd, &vendor, &product); >+ if (status == SANE_STATUS_GOOD) { >+ MatchUsbDevice(vendor, product, &pModel); >+ *peModel = pModel->eModel; >+ } >+ >+ return fd; >+} >+ >+ >+static void UsbClose(int fd) >+{ >+ /* close usb device */ >+ if (fd != -1) { >+ sanei_usb_close(fd); >+ } >+} >+ >+ >+static void UsbWriteReg(int fd, byte bReg, byte bData) >+{ >+ _SaneiUsbWriteControl(fd, bReg, &bData, 1); >+} >+ >+ >+static void UsbReadReg(int fd, byte bReg, byte *pbData) >+{ >+ _SaneiUsbReadControl(fd, bReg, pbData, 1); >+} >+ >+ >+static void UsbWriteBulk(int fd, byte *pabData, int iSize) >+{ >+ /* byte abSetup[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; >+ HP3400 probably needs 0x01, 0x01 */ >+ byte abSetup[8] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; >+ size_t size; >+ >+ if (fd == -1) { >+ return; >+ } >+ >+ abSetup[4] = (iSize) & 0xFF; >+ abSetup[5] = (iSize >> 8) & 0xFF; >+ _SaneiUsbWriteControl(fd, USB_SETUP, abSetup, 8); >+ >+ size = iSize; >+ if (sanei_usb_write_bulk(fd, pabData, &size) != SANE_STATUS_GOOD) { >+ DBG(DBG_ERR, "ERROR: Bulk write failed\n"); >+ } >+} >+ >+ >+static void UsbReadBulk(int fd, byte *pabData, int iSize) >+{ >+ byte abSetup[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; >+ size_t size; >+ >+ if (fd == -1) { >+ return; >+ } >+ >+ abSetup[4] = (iSize) & 0xFF; >+ abSetup[5] = (iSize >> 8) & 0xFF; >+ _SaneiUsbWriteControl(fd, USB_SETUP, abSetup, 8); >+ >+ size = iSize; >+ if (sanei_usb_read_bulk(fd, pabData, &size) != SANE_STATUS_GOOD) { >+ DBG(DBG_ERR, "ERROR: Bulk read failed\n"); >+ } >+} >+ >+ >+XferModule SaneiUsbDev = { >+ "Sanei_USB", >+ UsbInit, >+ UsbOpen, >+ UsbClose, >+ UsbWriteReg, >+ UsbReadReg, >+ UsbWriteBulk, >+ UsbReadBulk >+}; >+ >diff -ruN sane-backends-1.0.12/backend/hp3300c_uscanner.c sane-backends-1.0.12-patched/backend/hp3300c_uscanner.c >--- sane-backends-1.0.12/backend/hp3300c_uscanner.c 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c_uscanner.c 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,234 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c_uscanner.c,v 1.4 2002/11/27 23:24:10 saperski Exp $ >+*/ >+ >+/* >+ Provides a simple interface to read and write data from the scanner, >+ without any knowledge whether it's a parallel or USB scanner >+*/ >+ >+#ifdef USCANNER_SUPPORT >+ >+#include "hp3300c_xfer.h" >+ >+#include "mytypes.h" >+ >+#include <unistd.h> /* read, open, write */ >+#include <fcntl.h> /* open */ >+#include <stdio.h> /* printf */ >+#include <errno.h> /* better error reports */ >+#include <string.h> /* better error reports */ >+#include <sys/ioctl.h> >+#include <sys/stat.h> >+#include <limits.h> >+ >+#include <dev/usb/usb.h> >+ >+ >+/************************************************************************ >+ USB transfer routines implemented with uscanner calls >+************************************************************************/ >+ >+#define MAX_DEV_TRY 16 >+ >+static void >+uscannerInit(TFnReportDevice *pfnReportDevice) >+{ >+ struct usb_device_info usb_info; >+ TScannerModel *pModel; >+ struct stat fs; >+ char devname[PATH_MAX]; >+ int i, fd, rc; >+ >+ /* open scanner's device file */ >+ for (rc = -1, i = 0; rc < 0 && i < MAX_DEV_TRY; i++) { >+ snprintf(devname, PATH_MAX, "/dev/uscanner%d", i); >+ rc = stat(devname, &fs); >+ if (rc == 0) { >+ if ((fs.st_mode & S_IFCHR) == 0 ) { >+ DBG(DBG_ERR, "Not a characted device: %s\n", devname); >+ rc = -1; >+ } >+ } else >+ if (errno != ENOENT) >+ DBG(DBG_ERR, "Error accessing %s: %s\n", devname, strerror(errno)); >+ >+ } >+ if (rc < 0) { >+ DBG(DBG_ERR, "Cannot open any scanner device (/dev/uscanner*).\n"); >+ return; >+ } >+ if ((fd = open(devname, O_RDWR)) >= 0) { >+ if (ioctl(fd, USB_GET_DEVICEINFO, &usb_info) >= 0) { >+ DBG(DBG_MSG, "VendorId %s (0x%04X), ProductId %s (0x%04X)\n", >+ usb_info.udi_vendor, usb_info.udi_vendorNo, >+ usb_info.udi_product, usb_info.udi_productNo); >+ if (MatchUsbDevice(usb_info.udi_vendorNo, >+ usb_info.udi_productNo, &pModel)) >+ pfnReportDevice(pModel, devname); >+ } else >+ DBG(DBG_ERR, "USB_GET_DEVICEINFO not supported, check version of the uscanner driver"); >+ } else >+ DBG(DBG_ERR, "Cannot open %s: %s", devname, strerror(errno)); >+ close(fd); >+} >+ >+static int >+uscannerOpen(char *devname, EScannerModel *peModel) >+{ >+ int fd, rc = -1; >+ struct usb_device_info usb_info; >+ TScannerModel *pModel; >+ >+ fd = open(devname, O_RDWR); >+ if (fd > 0) >+ if (ioctl(fd, USB_GET_DEVICEINFO, &usb_info) >= 0) >+ if (MatchUsbDevice(usb_info.udi_vendorNo, >+ usb_info.udi_productNo, &pModel)) { >+ *peModel = pModel->eModel; >+ rc = fd; >+ } else >+ DBG(DBG_ERR, "Cannot match device at %s\n", devname); >+ else >+ DBG(DBG_ERR, "USB_GET_INFO failed on %s: %s\n", devname, strerror(errno)); >+ else >+ DBG(DBG_ERR, "Cannot open %s: %s\n", devname, strerror(errno)); >+ >+ return fd; >+} >+ >+static void >+uscannerExit(int fd) >+{ >+ /* close usb device */ >+ if (fd != -1) { >+ close(fd); >+ } >+} >+ >+static void >+_uscannerReadControl(int fd, byte bValue, byte *pabData, int iSize) >+{ >+ struct usb_ctl_request req; >+ >+ if (fd < 0) { >+ return; >+ } >+ >+ req.ucr_addr = 0; >+ req.ucr_data = pabData; >+ req.ucr_flags = 0; >+ req.ucr_actlen = 0; >+ req.ucr_request.bmRequestType = UT_READ_VENDOR_DEVICE; >+ req.ucr_request.bRequest = (iSize > 1) ? 0x04 : 0x0C; >+ USETW(req.ucr_request.wValue, bValue); >+ USETW(req.ucr_request.wIndex, 0); >+ USETW(req.ucr_request.wLength, iSize); >+ >+ if (fd != -1) { >+ ioctl(fd, USB_DO_REQUEST, &req); >+ } >+} >+ >+ >+static void >+_uscannerWriteControl(int fd, byte bValue, byte *pabData, int iSize) >+{ >+ struct usb_ctl_request req; >+ >+ if (fd < 0) { >+ return; >+ } >+ >+ req.ucr_addr = 0; >+ req.ucr_data = pabData; >+ req.ucr_flags = 0; >+ req.ucr_actlen = 0; >+ req.ucr_request.bmRequestType = UT_WRITE_VENDOR_DEVICE; >+ req.ucr_request.bRequest = (iSize > 1) ? 0x04 : 0x0C; >+ USETW(req.ucr_request.wValue, bValue); >+ USETW(req.ucr_request.wIndex, 0); >+ USETW(req.ucr_request.wLength, iSize); >+ >+ if (fd != -1) { >+ ioctl(fd, USB_DO_REQUEST, &req); >+ } >+} >+ >+static void >+uscannerWriteReg(int fd, byte bReg, byte bData) >+{ >+ _uscannerWriteControl(fd, bReg, &bData, 1); >+} >+ >+ >+static void >+uscannerReadReg(int fd, byte bReg, byte *pbData) >+{ >+ _uscannerReadControl(fd, bReg, pbData, 1); >+} >+ >+ >+static void >+uscannerWriteBulk(int fd, byte *pabData, int iSize) >+{ >+ byte abSetup[8] = {0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; >+ >+ if (fd < 0) { >+ return; >+ } >+ >+ abSetup[4] = (iSize) & 0xFF; >+ abSetup[5] = (iSize >> 8) & 0xFF; >+ _uscannerWriteControl(fd, USB_SETUP, abSetup, 8); >+ if (write(fd, pabData, iSize) != iSize) { >+ DBG(DBG_ERR, "ERROR: Bulk Write failed\n"); >+ } >+} >+ >+ >+static void >+uscannerReadBulk(int fd, byte *pabData, int iSize) >+{ >+ byte abSetup[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; >+ >+ if (fd < 0) { >+ return; >+ } >+ >+ abSetup[4] = (iSize) & 0xFF; >+ abSetup[5] = (iSize >> 8) & 0xFF; >+ _uscannerWriteControl(fd, USB_SETUP, abSetup, 8); >+ if (read(fd, pabData, iSize) != iSize) { >+ DBG(DBG_ERR, "ERROR: Bulk read failed\n"); >+ } >+} >+ >+XferModule uscannerDev = { >+ "BSD uscanner kernel module", >+ uscannerInit, >+ uscannerOpen, >+ uscannerExit, >+ uscannerWriteReg, >+ uscannerReadReg, >+ uscannerWriteBulk, >+ uscannerReadBulk >+}; >+ >+#endif /* USCANNER_SUPPORT */ >diff -ruN sane-backends-1.0.12/backend/hp3300c_xfer.c sane-backends-1.0.12-patched/backend/hp3300c_xfer.c >--- sane-backends-1.0.12/backend/hp3300c_xfer.c 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c_xfer.c 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,275 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c_xfer.c,v 1.31 2003/01/11 13:35:18 bertrik Exp $ >+*/ >+ >+/* >+ Provides a simple interface to read and write data from the scanner, >+ without any knowledge whether it's a parallel or USB scanner >+*/ >+ >+#include "mytypes.h" >+ >+#include <unistd.h> /* read, open, write */ >+#include <fcntl.h> /* open */ >+#include <stdio.h> /* printf */ >+#include <errno.h> /* better error reports */ >+#include <string.h> /* better error reports */ >+#include <stdlib.h> /* malloc(), free() on FreeBSD */ >+ >+#include "hp3300c_xfer.h" >+ >+#define MAX_XFER_MODULES 5 >+ >+static XferModule *_aXferModules[MAX_XFER_MODULES]; >+static int _iNrXferModules; >+ >+/* list of supported models */ >+TScannerModel ScannerModels[] = { >+ {"Hewlett-Packard", "ScanJet 3300C", 0x3F0, 0x205, eHp3300c}, >+ {"Hewlett-Packard", "ScanJet 3400C", 0x3F0, 0x405, eHp3400c}, >+ {"Hewlett-Packard", "ScanJet 4300C", 0x3F0, 0x305, eHp4300c}, >+ {"Agfa", "Snapscan Touch", 0x6BD, 0x100, eAgfaTouch}, >+/* last entry all zeros */ >+ {0, 0, 0, 0, 0} >+}; >+ >+ >+/* >+ 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 TRUE if a matching USB scanner was found >+*/ >+bool MatchUsbDevice(int iVendor, int iProduct, TScannerModel **ppModel) >+{ >+ TScannerModel *pModels = ScannerModels; >+ >+ DBG(DBG_MSG, "Matching USB device 0x%04X-0x%04X ... ", iVendor, iProduct); >+ while (pModels->pszName != NULL) { >+ if ((pModels->iVendor == iVendor) && (pModels->iProduct == iProduct)) { >+ DBG(DBG_MSG, "found %s %s\n", pModels->pszVendor, pModels->pszName); >+ *ppModel = pModels; >+ return TRUE; >+ } >+ /* next model to match */ >+ pModels++; >+ } >+ DBG(DBG_MSG, "nothing found\n"); >+ return FALSE; >+} >+ >+/************************************************************************ >+ Public functions >+************************************************************************/ >+ >+ >+/* >+ Hp3300cXferRegisterModule >+ ========================= >+ installs a transfer method >+ >+ IN pXferModule Module to registers >+ >+ Returns a negative number when an error occurred. >+*/ >+int Hp3300cXferRegisterModule(XferModule *pXferModule) >+{ >+ DBG(DBG_MSG, "Registering transfer method %d: %s\n", _iNrXferModules, pXferModule->pszName); >+ >+ if (_iNrXferModules >= MAX_XFER_MODULES) { >+ DBG(DBG_ERR, "Max. number of installed transfer methods reached\n"); >+ return -1; >+ } >+ _aXferModules[_iNrXferModules++] = pXferModule; >+ >+ return 0; >+} >+ >+ >+/* >+ Hp3300cXferInit >+ =============== >+ Initialises all registered data transfer modules, which causes >+ them to report any devices found through the pfnReport callback. >+ >+ IN pfnReport Function to call to report a transfer device >+*/ >+void Hp3300cXferInit(TFnReportDevice *pfnReport) >+{ >+ int i; >+ >+ for (i = 0; i < _iNrXferModules; i++) { >+ _aXferModules[i]->mfnInit(pfnReport); >+ } >+} >+ >+ >+int Hp3300cXferOpen (char *pszName, EScannerModel *peModel) >+{ >+ TXferDev *pDev; >+ XferModule *pMod; >+ int i, iHandle; >+ >+ DBG(DBG_MSG, "Hp3300cXferOpen '%s'\n", pszName); >+ >+ /* try each method */ >+ for (i = 0; i < _iNrXferModules; i++) { >+ pMod = _aXferModules[i]; >+ DBG(DBG_MSG, "probing %s\n", pMod->pszName); >+ *peModel = eUnknownModel; >+ iHandle = pMod->mfnOpen(pszName, peModel); >+ if (iHandle >= 0) { >+ pDev = malloc(sizeof(TXferDev)); >+ pDev->iXferDev = pMod; >+ pDev->iHandle = iHandle; >+ return (int)pDev; >+ } >+ } >+ return -1; >+} >+ >+ >+void Hp3300cXferClose(int iHandle) >+{ >+ TXferDev *pDev; >+ >+ if (iHandle <= 0) { >+ return; >+ } >+ pDev = (TXferDev *)iHandle; >+ >+ /* deinit the driver */ >+ if (pDev->iHandle >= 0) { >+ pDev->iXferDev->mfnExit(pDev->iHandle); >+ free((void *)iHandle); >+ } >+} >+ >+ >+void Hp3300cRegWrite(int iHandle, byte bReg, byte bData) >+{ >+ TXferDev *pDev; >+ >+ if (iHandle <= 0) { >+ return; >+ } >+ pDev = (TXferDev *)iHandle; >+ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR, bReg); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_DATA_WRITE, bData); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+} >+ >+ >+void Hp3300cRegRead(int iHandle, byte bReg, byte *pbData) >+{ >+ TXferDev *pDev; >+ >+ if (iHandle <= 0) { >+ return; >+ } >+ pDev = (TXferDev *)iHandle; >+ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR, bReg); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x34); >+ pDev->iXferDev->mfnReadReg (pDev->iHandle, EPP_DATA_READ, pbData); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+} >+ >+ >+void Hp3300cBulkWrite(int iHandle, byte *pabBuf, int iSize) >+{ >+ TXferDev *pDev; >+ >+ if (iHandle <= 0) { >+ return; >+ } >+ pDev = (TXferDev *)iHandle; >+ >+ /* select scanner register 0x24 */ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR, 0x24); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ /* do the bulk write */ >+ pDev->iXferDev->mfnWriteBulk(pDev->iHandle, pabBuf, iSize); >+} >+ >+ >+void Hp3300cBulkRead(int iHandle, byte *pabBuf, int iSize) >+{ >+ TXferDev *pDev; >+ >+ if (iHandle <= 0) { >+ return; >+ } >+ pDev = (TXferDev *)iHandle; >+ >+ /* select scanner register 0x24 */ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, EPP_ADDR, 0x24); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ /* do the bulk read */ >+ pDev->iXferDev->mfnReadBulk(pDev->iHandle, pabBuf, iSize); >+} >+ >+ >+void Hp3300cWakeup(int iHandle) >+{ >+ TXferDev *pDev; >+ byte abMagic[] = { 0xA0, 0xA8, 0x50, 0x58, 0x90, 0x98, 0xC0, 0xC8, >+ 0x90, 0x98, 0xE0, 0xE8}; >+ int i; >+ >+ if (iHandle <= 0) { >+ return; >+ } >+ pDev = (TXferDev *)iHandle; >+ >+ /* write magic startup sequence */ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ for (i = 0; i < (int)sizeof(abMagic); i++) { >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_DATA, abMagic[i]); >+ } >+ >+ /* write 0x04 to scanner register 0x00 the hard way */ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_DATA, 0x00); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x1D); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_DATA, 0x04); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x17); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x15); >+ pDev->iXferDev->mfnWriteReg(pDev->iHandle, SPP_CONTROL, 0x14); >+} >+ >+ >diff -ruN sane-backends-1.0.12/backend/hp3300c_xfer.h sane-backends-1.0.12-patched/backend/hp3300c_xfer.h >--- sane-backends-1.0.12/backend/hp3300c_xfer.h 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c_xfer.h 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,132 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c_xfer.h,v 1.16 2002/11/04 23:48:33 bertrik Exp $ >+*/ >+ >+/* >+ Provides a simple interface to read and write data from the scanner, >+ without any knowledge whether it's a parallel or USB scanner >+*/ >+ >+#ifndef _HP3300C_XFER_H_ >+#define _HP3300C_XFER_H_ >+ >+#include "mytypes.h" >+#include <stdio.h> /* for FILE * */ >+ >+ >+/* register codes for the USB - IEEE1284 bridge */ >+#define USB_SETUP 0x82 >+#define EPP_ADDR 0x83 >+#define EPP_DATA_READ 0x84 >+#define EPP_DATA_WRITE 0x85 >+#define SPP_STATUS 0x86 >+#define SPP_CONTROL 0x87 >+#define SPP_DATA 0x88 >+ >+ >+typedef enum { >+ eUnknownModel = 0, >+ eHp3300c, >+ eHp3400c, >+ eHp4300c, >+ eAgfaTouch >+} EScannerModel; >+ >+ >+typedef struct { >+ char *pszVendor; >+ char *pszName; >+ int iVendor; >+ int iProduct; >+ EScannerModel eModel; >+} TScannerModel; >+ >+ >+typedef int (TFnReportDevice)(TScannerModel *pModel, char *pszDeviceName); >+ >+/* function pointer definitions */ >+/* >+ The TFnInit function get passed a TFnReportDevice function pointer which is >+ called for each scanner device. >+ The TFnOpen function can then be called with one of the names as an argument >+ and returns a handle > 0 if the open was successful. >+*/ >+typedef void (TFnInit)(TFnReportDevice *pfnReportDevice); >+typedef int (TFnOpen)(char *pszDeviceName, EScannerModel *peModel); >+typedef void (TFnWriteReg)(int iHandle, byte bReg, byte bData); >+typedef void (TFnReadReg)(int iHandle, byte bReg, byte *pbData); >+typedef void (TFnWriteBulk)(int iHandle, byte *pabBuf, int iSize); >+typedef void (TFnReadBulk)(int iHandle, byte *pabBuf, int iSize); >+typedef void (TFnExit)(int iHandle); >+ >+ >+typedef struct { >+ char *pszName; >+ TFnInit *mfnInit; >+ TFnOpen *mfnOpen; >+ TFnExit *mfnExit; >+ TFnWriteReg *mfnWriteReg; >+ TFnReadReg *mfnReadReg; >+ TFnWriteBulk *mfnWriteBulk; >+ TFnReadBulk *mfnReadBulk; >+} XferModule; >+ >+ >+typedef struct { >+ int iHandle; >+ XferModule *iXferDev; >+} TXferDev; >+ >+ >+/* Creates our own DBG definitions, externs are define in main.c*/ >+#ifndef WITH_NIASH >+#define DBG fprintf >+extern FILE * DBG_MSG; >+extern FILE * DBG_ERR; >+extern FILE * BG_ASSERT; >+#endif /* NO WITH_NIASH */ >+ >+ >+/* USB device file name */ >+extern char * usb_devfile; >+ >+ >+/* list of supported models, the actual list is in hp3300c_xfer.c */ >+extern TScannerModel ScannerModels[]; >+ >+ >+/* The number returned by Hp3300cXferInit is a handle. This handle needs to >+ be passed to all other transfer functions. >+ Internally it is a pointer to structure containg function pointers >+ */ >+int Hp3300cXferRegisterModule(XferModule *pXferModule); >+ >+void Hp3300cXferInit (TFnReportDevice *pfnReport); >+int Hp3300cXferOpen (char *pszName, EScannerModel *peModel); >+void Hp3300cXferClose (int iXferHandle); >+ >+void Hp3300cRegWrite (int iXferHandle, byte bReg, byte bData); >+void Hp3300cRegRead (int iXferHandle, byte bReg, byte *pbData); >+void Hp3300cBulkWrite (int iXferHandle, byte *pabBuf, int iSize); >+void Hp3300cBulkRead (int iXferHandle, byte *pabBuf, int iSize); >+void Hp3300cWakeup (int iXferHandle); >+ >+bool MatchUsbDevice(int iVendor, int iProduct, TScannerModel **ppeModel); >+ >+#endif /* _HP3300C_XFER_H_ */ >diff -ruN sane-backends-1.0.12/backend/hp3300c_xfer_cfg.h sane-backends-1.0.12-patched/backend/hp3300c_xfer_cfg.h >--- sane-backends-1.0.12/backend/hp3300c_xfer_cfg.h 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/hp3300c_xfer_cfg.h 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,75 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: hp3300c_xfer_cfg.h,v 1.5 2002/11/03 17:58:59 bertrik Exp $ >+*/ >+ >+/* >+ This file defines which transfer methods are compiled into the SANE backend >+ (Linux scanner kernel module, BSD uscanner kernel module, libusb, ieee1284, >+ dummy for scanner emulation, etc.) >+ >+ To disable a transfer method, comment out the corresponding #define >+ >+ #define SANEI_USB_SUPPORT >+ USB support using the SANE builtin functions from sanei_usb.h >+ sanei_usb.h version 1.0.7 supports Linux only (in fact it uses >+ the scanner kernel module internally). >+ >+ #define LINUX_USB_SUPPORT >+ USB support using the 'scanner' kernel module for Linux. >+ You need at least Linux kernel version 2.4.12 to use this. >+ >+ #define USCANNER_SUPPORT >+ USB support using the 'uscanner' kernel module for BSD. >+ This is obviously mutually exclusive with LINUX_USB_SUPPORT >+ >+ #define LIBUSB_SUPPORT >+ USB support using libusb (should be platform independent) >+ You need at least version 0.1.5 of libusb (+ devel package) to use this. >+ >+ #define LIBIEEE1284_SUPPORT >+ Parallel port support using libieee1284 (should be platform independent). >+ You need at least version ... of libieee1284 (+ devel package) to use this. >+ *** This transfer method has not been tested yet *** >+ >+ #define DUMMY_SCAN_SUPPORT >+ Dummy transfer method used for testing. >+ This method very simply emulates a specific type of scanner. >+ >+ Any changes in this file will have no effect until you recompile & install: >+ (in the sane-backends package, backend directory) >+ touch niash.c >+ make >+ make install >+*/ >+ >+ >+#define SANEI_USB_SUPPORT >+ >+/* #define LINUX_USB_SUPPORT */ >+ >+/* #define USCANNER_SUPPORT */ >+ >+/* #define LIBUSB_SUPPORT */ >+ >+/* not tested yet */ >+/* #define LIBIEEE1284_SUPPORT */ >+ >+/* not implemented yet */ >+/* #define DUMMY_SCAN_SUPPORT */ >+ >diff -ruN sane-backends-1.0.12/backend/mytypes.h sane-backends-1.0.12-patched/backend/mytypes.h >--- sane-backends-1.0.12/backend/mytypes.h 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/mytypes.h 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,33 @@ >+/* >+ Defines my types >+ >+ $Id: mytypes.h,v 1.3 2001/12/18 03:10:41 aggression Exp $ >+*/ >+ >+ >+#ifndef _MYTYPES_H_ >+#define _MYTYPES_H_ >+ >+#ifndef byte >+typedef unsigned char byte; >+#endif >+ >+#ifndef word >+typedef int word; >+#endif >+ >+#ifndef bool >+typedef int bool; >+#endif >+ >+#ifndef FALSE >+#define FALSE 0 >+#endif >+ >+#ifndef TRUE >+#define TRUE 1 >+#endif >+ >+#endif >+ >+ >diff -ruN sane-backends-1.0.12/backend/niash.c sane-backends-1.0.12-patched/backend/niash.c >--- sane-backends-1.0.12/backend/niash.c 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/niash.c 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,869 @@ >+/* >+ Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) >+ >+ This program is free software; you can redistribute it and/or >+ modify it under the terms of the GNU General Public License >+ as published by the Free Software Foundation; either version 2 >+ of the License, or (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. >+ >+ $Id: niash.c,v 1.36 2003/03/24 19:14:47 bertrik Exp $ >+*/ >+ >+/* >+ Concept for a backend for scanners based on the NIASH chipset, >+ such as HP3300C, HP3400C, HP4300C, Agfa Touch. >+ Parts of this source were inspired by other backends. >+*/ >+ >+#include "sane/sane.h" >+#include "sane/config.h" >+#include "sane/sanei.h" >+#include "sane/sanei_backend.h" >+#include "sane/sanei_config.h" >+#include "sane/saneopts.h" >+ >+#include <stdlib.h> /* malloc, free */ >+#include <string.h> /* memcpy */ >+#include <stdio.h> >+ >+/* definitions for debug */ >+#define BACKEND_NAME niash >+#define BUILD 1 >+ >+#define DBG_ASSERT 1 >+#define DBG_ERR 16 >+#define DBG_MSG 32 >+ >+#define NIASH_CONFIG_FILE "niash.conf" >+ >+/* Just to avoid conflicts between niash backend and testtool */ >+#define WITH_NIASH 1 >+ >+ >+#include "hp3300c_xfer_cfg.h" >+ >+/* (source) includes for data transfer methods */ >+#include "hp3300c.c" >+#include "hp3300c_xfer.c" >+#include "hp3300c_saneiusb.c" >+#if defined(LINUX_USB_SUPPORT) >+ #include "hp3300c_linux.c" >+#endif >+#if defined(USCANNER_SUPPORT) >+ #include "hp3300c_uscanner.c" >+#endif >+#if defined(LIBUSB_SUPPORT) >+ #include "hp3300c_libusb.c" >+#endif >+#if defined(LIBIEEE1284_SUPPORT) >+ #include "hp3300c_ieee1284.c" >+#endif >+ >+ >+#define ASSERT(cond) (!(cond) ? DBG(DBG_ASSERT, "!!! ASSERT(%S) FAILED!!!\n",STRINGIFY(cond));) >+ >+/* other definitions */ >+#define TRUE 1 >+#define FALSE 0 >+ >+#define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4) >+#define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_)) >+ >+/* Device filename for USB access */ >+char * usb_devfile = "/dev/usb/scanner0"; >+ >+/* options enumerator */ >+typedef enum { >+ optCount = 0, >+ >+ optGroupGeometry, >+ optTLX, optTLY, optBRX, optBRY, >+ optDPI, >+ >+ optGroupImage, >+ optGammaTable, /* gamma table */ >+ >+ optGroupMisc, >+ optLamp, >+ >+ optLast, >+/* put temporarily disabled options here after optLast */ >+ optCalibrate, >+ optGamma /* analog gamma = single number */ >+ >+} EOptionIndex; >+ >+ >+typedef union { >+ SANE_Word w; >+ SANE_Word *wa; /* word array */ >+ SANE_String s; >+} TOptionValue; >+ >+ >+typedef struct { >+ SANE_Option_Descriptor aOptions[optLast]; >+ TOptionValue aValues[optLast]; >+ >+ TScanParams ScanParams; >+ THWParams HWParams; >+ >+ TDataPipe DataPipe; >+ int iLinesLeft; >+ >+ SANE_Int aGammaTable[4096]; /* a 12-to-8 bit color lookup table */ >+ >+ int fScanning; /* TRUE if actively scanning */ >+ int fCanceled; >+} TScanner; >+ >+ >+/* linked list of SANE_Device structures */ >+typedef struct TDevListEntry { >+ struct TDevListEntry *pNext; >+ SANE_Device dev; >+} TDevListEntry; >+ >+ >+static TDevListEntry *_pFirstSaneDev = 0; >+static int iNumSaneDev = 0; >+static const SANE_Device **_pSaneDevList = 0; >+ >+ >+/* option constraints */ >+static const SANE_Range rangeGammaTable = {0, 255, 1}; >+static const SANE_Int setResolutions[] = {3, 150, 300, 600}; >+static const SANE_Range rangeGamma = {SANE_FIX(0.25), SANE_FIX(4.0), >+ SANE_FIX(0.0)}; >+static const SANE_Range rangeXmm = {0, 220, 1}; >+static const SANE_Range rangeYmm = {0, 290, 1}; >+ >+ >+static void _InitOptions(TScanner *s) >+{ >+ int i, j; >+ SANE_Option_Descriptor *pDesc; >+ TOptionValue *pVal; >+ >+ 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->constraint.range = &rangeXmm; >+ pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; >+ 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->constraint.word_list = setResolutions; >+ pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; >+ pVal->w = setResolutions[1]; >+ break; >+ >+ case optGroupImage: >+ pDesc->title = SANE_I18N("Image"); >+ pDesc->type = SANE_TYPE_GROUP; >+ pDesc->size = 0; >+ break; >+ >+ case optGamma: >+ pDesc->name = SANE_NAME_ANALOG_GAMMA; >+ pDesc->title = SANE_TITLE_ANALOG_GAMMA; >+ pDesc->desc = SANE_DESC_ANALOG_GAMMA; >+ pDesc->type = SANE_TYPE_FIXED; >+ pDesc->constraint_type = SANE_CONSTRAINT_RANGE; >+ pDesc->constraint.range = &rangeGamma; >+ pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; >+ pVal->w = SANE_FIX(1.0); >+ break; >+ >+ case optGammaTable: >+ pDesc->name = SANE_NAME_GAMMA_VECTOR; >+ pDesc->title = SANE_TITLE_GAMMA_VECTOR; >+ pDesc->desc = SANE_DESC_GAMMA_VECTOR; >+ pDesc->size = sizeof(s->aGammaTable); >+ pDesc->constraint_type = SANE_CONSTRAINT_RANGE; >+ pDesc->constraint.range = &rangeGammaTable; >+ pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; >+ /* set a neutral gamma */ >+ for (j = 0; j < 4096; j++) { >+ s->aGammaTable[j] = j / 16; >+ } >+ pVal->wa = s->aGammaTable; >+ break; >+ >+ case optGroupMisc: >+ pDesc->title = SANE_I18N("Miscellaneous"); >+ pDesc->type = SANE_TYPE_GROUP; >+ pDesc->size = 0; >+ break; >+ >+ case optLamp: >+ pDesc->name = "lamp"; >+ pDesc->title = SANE_I18N("Lamp status"); >+ pDesc->desc = SANE_I18N("Switches the lamp on or off."); >+ pDesc->type = SANE_TYPE_BOOL; >+ pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; >+ /* switch the lamp on when starting for first the time */ >+ pVal->w = SANE_TRUE; >+ break; >+ >+ case optCalibrate: >+ pDesc->name = "calibrate"; >+ pDesc->title = SANE_I18N("Calibrate"); >+ pDesc->desc = SANE_I18N("Calibrates for black and white level."); >+ pDesc->type = SANE_TYPE_BUTTON; >+ pDesc->cap = SANE_CAP_SOFT_SELECT; >+ pDesc->size = 0; >+ break; >+ >+ default: >+ DBG(DBG_ERR, "Uninitialised option %d\n", i); >+ break; >+ } >+ } >+} >+ >+ >+static int _ReportDevice(TScannerModel *pModel, char *pszDeviceName) >+{ >+ TDevListEntry *pNew, *pDev; >+ >+ DBG(DBG_MSG, "niash: _ReportDevice '%s'\n", pszDeviceName); >+ >+ pNew = malloc(sizeof(TDevListEntry)); >+ if (!pNew) { >+ DBG(DBG_ERR, "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; >+} >+ >+/*****************************************************************************/ >+ >+SANE_Status >+sane_init(SANE_Int *piVersion, SANE_Auth_Callback pfnAuth) >+{ >+ FILE * conf_fp; /* Config file stream */ >+ SANE_Char line[PATH_MAX]; >+ SANE_Char * str = NULL; >+ SANE_String_Const proper_str; >+ int nline = 0; >+ >+ /* prevent compiler from complaing about unused parameters */ >+ pfnAuth = pfnAuth; >+ >+ DBG_INIT(); >+ DBG(DBG_MSG, "sane_init\n"); >+ >+ /* install transfer methods */ >+#if defined(SANEI_USB_SUPPORT) >+ Hp3300cXferRegisterModule(&SaneiUsbDev); >+#endif >+#if defined(LINUX_USB_SUPPORT) >+ Hp3300cXferRegisterModule(&LnxUsbDev); >+#endif >+#if defined(USCANNER_SUPPORT) >+ Hp3300cXferRegisterModule(&uscannerDev); >+#endif >+#if defined(LIBUSB_SUPPORT) >+ Hp3300cXferRegisterModule(&LibUsbDev); >+#endif >+#if defined(LIBIEEE1284_SUPPORT) >+ Hp3300cXferRegisterModule(&IEEE1284Dev); >+#endif >+ >+ conf_fp = sanei_config_open (NIASH_CONFIG_FILE); >+ >+ if (conf_fp) { >+ DBG(DBG_MSG, "Reading config file\n"); >+ >+ while (sanei_config_read (line, sizeof (line), conf_fp)) { >+ ++nline; >+ >+ if (str) { >+ free(str); >+ } >+ >+ proper_str = sanei_config_get_string (line, &str); >+ >+ /* Discards white lines and comments */ >+ if (!str || proper_str == line || str[0] == '#' ) { >+ DBG(DBG_MSG, "Discarding line %d\n", nline); >+ } >+ else { >+ /* If line's not blank or a comment, then it's the device >+ * filename. usb_devfile is resized to hold the device filename string */ >+ usb_devfile = malloc ( sizeof (line) * sizeof(SANE_Char) ); >+ if (usb_devfile == NULL) { >+ DBG(DBG_ERR, "Unable to allocate memory for device filename string\n"); >+ DBG(DBG_MSG, "Using default built-in values\n"); >+ break; >+ } >+ strcpy (usb_devfile, line); >+ DBG(DBG_MSG, "Using %s as device file\n", usb_devfile); >+ } >+ } /* while */ >+ fclose(conf_fp); >+ } >+ else { >+ DBG (DBG_ERR, "Unable to read config file \"%s\": %s\n", NIASH_CONFIG_FILE, >+ strerror(errno)); >+ DBG (DBG_MSG, "Using default built-in values\n"); >+ } >+ >+ if (piVersion != NULL) { >+ *piVersion = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD); >+ } >+ >+ /* initialise transfer methods */ >+ iNumSaneDev = 0; >+ Hp3300cXferInit(_ReportDevice); >+ >+ 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; >+ int i; >+ >+ DBG(DBG_MSG, "sane_get_devices\n"); >+ >+ local_only = local_only; >+ >+ if (_pSaneDevList) { >+ free(_pSaneDevList); >+ } >+ >+ _pSaneDevList = malloc(sizeof(*_pSaneDevList) * (iNumSaneDev + 1)); >+ if (!_pSaneDevList) { >+ DBG(DBG_MSG, "no mem\n"); >+ return SANE_STATUS_NO_MEM; >+ } >+ i = 0; >+ for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext) { >+ _pSaneDevList[i++] = &pDev->dev; >+ } >+ _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); >+ >+ /* check the name */ >+ if (strlen(name) == 0) { >+ /* default to first available device */ >+ name = _pFirstSaneDev->dev.name; >+ } >+ >+ s = malloc(sizeof(TScanner)); >+ if (!s) { >+ DBG(DBG_MSG, "malloc failed\n"); >+ return SANE_STATUS_NO_MEM; >+ } >+ >+ if (Hp3300cOpen(&s->HWParams, (char *)name) < 0) { >+ /* is this OK ? */ >+ DBG(DBG_ERR, "Hp3300cOpen failed\n"); >+ free((void *)s); >+ return SANE_STATUS_DEVICE_BUSY; >+ } >+ _InitOptions(s); >+ *h = s; >+ >+ /* Turn on lamp by default at startup */ >+ SetLamp(&s->HWParams, TRUE); >+ >+ return SANE_STATUS_GOOD; >+} >+ >+ >+void >+sane_close(SANE_Handle h) >+{ >+ TScanner *s; >+ >+ DBG(DBG_MSG, "sane_close\n"); >+ >+ s = (TScanner *)h; >+ >+ /* turn off scanner lamp */ >+ SetLamp(&s->HWParams, FALSE); >+ >+ /* close scanner */ >+ Hp3300cClose(&s->HWParams); >+ >+ /* 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_MSG, "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 n, SANE_Action Action, void *pVal, >+ SANE_Int *pInfo) >+{ >+ TScanner *s; >+ int fVal; >+ static char szTable[15000]; >+ char szTemp[16]; >+ int *pi; >+ int i; >+ SANE_Int info; >+ bool fLampIsOn; >+ >+ DBG(DBG_MSG, "sane_control_option: option %d, action %d\n", n, Action); >+ >+ s = (TScanner *)h; >+ info = 0; >+ >+ switch (Action) { >+ case SANE_ACTION_GET_VALUE: >+ switch (n) { >+ >+ /* Get options of type SANE_Word */ >+ case optCount: >+ case optDPI: >+ case optGamma: >+ case optTLX: case optTLY: case optBRX: case optBRY: >+ DBG(DBG_MSG, "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n, >+ (int)s->aValues[n].w); >+ *(SANE_Word*)pVal = s->aValues[n].w; >+ break; >+ >+ /* Get options of type SANE_Word array */ >+ case optGammaTable: >+ DBG(DBG_MSG, "Reading gamma table\n"); >+ memcpy(pVal, s->aValues[n].wa, s->aOptions[n].size); >+ break; >+ >+ /* Get options of type SANE_Bool */ >+ case optLamp: >+ GetLamp(&s->HWParams, &fLampIsOn); >+ *(SANE_Bool *)pVal = fLampIsOn; >+ break; >+ >+ case optCalibrate: >+ /* although this option has nothing to read, >+ it's added here to avoid a warning when running scanimage --help */ >+ break; >+ >+ default: >+ DBG(DBG_MSG, "SANE_ACTION_GET_VALUE: Invalid option (%d)\n", n); >+ } >+ break; >+ >+ >+ case SANE_ACTION_SET_VALUE: >+ if (s->fScanning) { >+ DBG(DBG_ERR, "sane_control_option: SANE_ACTION_SET_VALUE not allowed during scan\n"); >+ return SANE_STATUS_INVAL; >+ } >+ switch (n) { >+ >+ case optCount: >+ return SANE_STATUS_INVAL; >+ >+ case optDPI: case optTLX: case optTLY: case optBRX: case optBRY: >+ info |= SANE_INFO_RELOAD_PARAMS; >+ /* fall through */ >+ >+ case optGamma: >+ DBG(DBG_MSG, "sane_control_option: SANE_ACTION_SET_VALUE %d = %d\n", n, >+ (int)s->aValues[n].w); >+ s->aValues[n].w = *(SANE_Word *)pVal; >+ break; >+ >+ case optGammaTable: >+ DBG(DBG_MSG, "Writing gamma table\n"); >+ pi = (SANE_Int *)pVal; >+ strcpy(szTable, ""); >+ for (i = 0; i < 4096; i++) { >+ if ((i % 32) == 0) { >+ sprintf(szTemp, " %04X", pi[i]); >+ strcat(szTable, szTemp); >+ } >+ } >+ memcpy(s->aValues[n].wa, pVal, s->aOptions[n].size); >+ DBG(DBG_MSG, "Gamma table summary:\n%s\n", szTable); >+ break; >+ >+ case optLamp: >+ fVal = *(SANE_Bool *)pVal; >+ DBG(DBG_MSG, "lamp %s\n", fVal ? "on" : "off"); >+ SetLamp(&s->HWParams, fVal); >+ break; >+ >+ case optCalibrate: >+/* SimpleCalib(&s->HWParams); */ >+ break; >+ >+ default: >+ DBG(DBG_ERR, "SANE_ACTION_SET_VALUE: Invalid option (%d)\n", n); >+ } >+ if (pInfo != NULL) { >+ *pInfo = info; >+ } >+ break; >+ >+ >+ case SANE_ACTION_SET_AUTO: >+ return SANE_STATUS_UNSUPPORTED; >+ >+ >+ default: >+ DBG(DBG_ERR, "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; >+ DBG(DBG_MSG, "sane_get_parameters\n"); >+ >+ s = (TScanner *)h; >+ >+ /* first do some checks */ >+ if (s->aValues[optTLX].w >= s->aValues[optBRX].w) { >+ DBG(DBG_ERR, "TLX should be smaller than BRX\n"); >+ return SANE_STATUS_INVAL; /* proper error code? */ >+ } >+ if (s->aValues[optTLY].w >= s->aValues[optBRY].w) { >+ DBG(DBG_ERR, "TLY should be smaller than BRY\n"); >+ return SANE_STATUS_INVAL; /* proper error code? */ >+ } >+ >+ /* return the data */ >+ p->format = SANE_FRAME_RGB; >+ p->last_frame = SANE_TRUE; >+ >+ p->lines = MM_TO_PIXEL(s->aValues[optBRY].w - s->aValues[optTLY].w, >+ s->aValues[optDPI].w); >+ p->depth = 8; >+ 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 * 3; >+ >+ return SANE_STATUS_GOOD; >+} >+ >+ >+SANE_Status >+sane_start(SANE_Handle h) >+{ >+ TScanner *s; >+ SANE_Parameters par; >+ int i, iLineCorr; >+ static byte abGamma[4096]; >+ static byte abCalibTable[HW_PIXELS * 6]; >+ >+ DBG(DBG_MSG, "sane_start\n"); >+ >+ s = (TScanner *)h; >+ >+ if (sane_get_parameters(h, &par) != SANE_STATUS_GOOD) { >+ DBG(DBG_MSG, "Invalid scan parameters\n"); >+ return SANE_STATUS_INVAL; >+ } >+ s->iLinesLeft = par.lines; >+ >+ /* fill in the scanparams using the option values */ >+ s->ScanParams.iDpi = s->aValues[optDPI].w; >+ s->ScanParams.iLpi = s->aValues[optDPI].w; >+ >+ /* calculate correction for filling of circular buffer */ >+ iLineCorr = 3 * s->HWParams.iSensorSkew; /* usually 16 motor steps */ >+ /* calculate correction for garbage lines */ >+ iLineCorr += s->HWParams.iSkipLines * (HW_LPI / s->ScanParams.iLpi); >+ >+ s->ScanParams.iTop = >+ MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, HW_LPI) - iLineCorr; >+ s->ScanParams.iLeft = >+ MM_TO_PIXEL(s->aValues[optTLX].w + s->HWParams.iTopLeftX, HW_DPI); >+ >+ s->ScanParams.iWidth = par.pixels_per_line; >+ s->ScanParams.iHeight = par.lines; >+ s->ScanParams.iBottom = 14200UL; >+ s->ScanParams.fCalib = FALSE; >+ >+ /* perform a simple calibration just before scanning */ >+ SimpleCalib(&s->HWParams, abCalibTable); >+ >+ /* copy gamma table */ >+ for (i = 0; i < 4096; i++) { >+ abGamma[i] = s->aValues[optGammaTable].wa[i]; >+ } >+ >+ WriteGammaCalibTable(abGamma, abGamma, abGamma, abCalibTable, 0, 0, &s->HWParams); >+ >+ /* prepare the actual scan */ >+ if (!InitScan(&s->ScanParams, &s->HWParams)) { >+ DBG(DBG_MSG, "Invalid scan parameters\n"); >+ return SANE_STATUS_INVAL; >+ } >+ >+ /* init data pipe */ >+ s->DataPipe.iSkipLines = s->HWParams.iSkipLines; >+ /* on the hp3400 and hp4300 we cannot set the top of the scan area (yet), >+ so instead we just scan and throw away the data until the top */ >+ if ((s->HWParams.eModel == eHp4300c) || (s->HWParams.eModel == eHp3400c)) { >+ s->DataPipe.iSkipLines += MM_TO_PIXEL(s->aValues[optTLY].w + s->HWParams.iTopLeftY, s->aValues[optDPI].w); >+ } >+ s->DataPipe.iBytesLeft = 0; >+ /* hack */ >+ s->DataPipe.pabLineBuf = (byte *)malloc(HW_PIXELS * 3); >+ CircBufferInit( s->HWParams.iXferHandle, &s->DataPipe, par.bytes_per_line, >+ s->ScanParams.iLpi * s->HWParams.iSensorSkew / HW_LPI, s->HWParams.iReversedHead); >+ >+ s->fScanning = TRUE; >+ return SANE_STATUS_GOOD; >+} >+ >+ >+SANE_Status >+sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len) >+{ >+ TScanner *s; >+ TDataPipe *p; >+ >+ DBG(DBG_MSG, "sane_read: buf=%p, maxlen=%d, ", buf, maxlen); >+ >+ s = (TScanner *)h; >+ >+ /* 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_INVAL; >+ } >+ >+ p = &s->DataPipe; >+ >+ /* anything left to read? */ >+ if ((s->iLinesLeft == 0) && (p->iBytesLeft == 0)) { >+ CircBufferExit(&s->DataPipe); >+ free(p->pabLineBuf); >+ FinishScan(&s->HWParams); >+ *len = 0; >+ DBG(DBG_MSG, "sane_read: end of scan\n"); >+ s->fScanning = FALSE; >+ return SANE_STATUS_EOF; >+ } >+ >+ /* time to read the next line? */ >+ if (p->iBytesLeft == 0) { >+ CircBufferGetLine(s->HWParams.iXferHandle, p, p->pabLineBuf, s->HWParams.iReversedHead); >+ p->iBytesLeft = p->iBytesPerLine; >+ s->iLinesLeft--; >+ } >+ >+ /* copy (part of) a line */ >+ *len = MIN(maxlen, p->iBytesLeft); >+ memcpy(buf, &p->pabLineBuf[p->iBytesPerLine - p->iBytesLeft], *len); >+ p->iBytesLeft -= *len; >+ >+ DBG(DBG_MSG, " read=%d\n", *len); >+ >+ return SANE_STATUS_GOOD; >+} >+ >+ >+void >+sane_cancel(SANE_Handle h) >+{ >+ TScanner *s; >+ >+ DBG(DBG_MSG, "sane_cancel\n"); >+ >+ s = (TScanner *)h; >+ >+ /* to be implemented more thoroughly */ >+ >+ /* Make sure the scanner head returns home */ >+ FinishScan(&s->HWParams); >+ >+ s->fCanceled = TRUE; >+ s->fScanning = 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; >+} >+ >diff -ruN sane-backends-1.0.12/backend/niash.conf sane-backends-1.0.12-patched/backend/niash.conf >--- sane-backends-1.0.12/backend/niash.conf 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/backend/niash.conf 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,9 @@ >+# Device filename to use for scanner access >+# Uncomment the following line if you are using the SANE backend >+# and want to use the kernel scanner module instead of libusb: >+# >+#Linux: >+#/dev/usbscanner >+# >+#FreeBSD/NetBSD: >+#/dev/uscanner0 >diff -ruN sane-backends-1.0.12/doc/Makefile.in sane-backends-1.0.12-patched/doc/Makefile.in >--- sane-backends-1.0.12/doc/Makefile.in 2003-04-30 18:12:55.000000000 -0500 >+++ sane-backends-1.0.12-patched/doc/Makefile.in 2003-06-19 11:02:15.000000000 -0500 >@@ -38,7 +38,7 @@ > @SET_MAKE@ > > SECT1 = saned.1 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-niash.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 \ >@@ -88,7 +88,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-niash.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 -ruN sane-backends-1.0.12/doc/sane-niash.man sane-backends-1.0.12-patched/doc/sane-niash.man >--- sane-backends-1.0.12/doc/sane-niash.man 1969-12-31 18:00:00.000000000 -0600 >+++ sane-backends-1.0.12-patched/doc/sane-niash.man 2003-06-19 11:02:15.000000000 -0500 >@@ -0,0 +1,113 @@ >+.\" $Id: sane-niash.man,v 1.7 2002/02/07 03:28:53 aggression Exp $ >+.TH sane-niash 5 "17 Dec 2001" >+.IX sane-niash >+ >+.SH NAME >+sane-niash - SANE backend for scanners based on the NIASH chipset. >+ >+.SH DESCRIPTION >+The >+.B sane-niash >+implements a SANE (Scanner Access Now Easy) backend that >+provides access to NIASH chipset based scanners. This backend will try to support >+the following models: >+ >+MANUFACTURER: MODEL: USB ID: >+.br >+--------------- -------------- --------- >+.br >+Agfa Snapscan Touch 06BD-0100 (1)(a) >+.br >+Hewlett-Packard Scanjet 3300c 03F0-0205 (1)(a)(b) >+.br >+Hewlett-Packard Scanjet 3400c 03F0-0405 (2)(b) >+.br >+Hewlett-Packard Scanjet 4300c 03F0-0305 (2)(a) >+.PP >+.br >+ASIC: (1) - NIASH00014 / (2) - NIASH00019 >+.br >+ANALOG FRONT-END: (a) - ESIC ES8100QA / (b) - WM8143-12 >+.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 niash.conf >+file contains the device name that correspond to the NIASH >+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 >+.RE >+.PP >+The first line is ignored. The second line is the device filename to use >+in order to access the NIASH Scanner. If no device is given, the >+backend will use libUSB. >+ >+.SH FILES >+.TP >+.I @CONFIGDIR@/niash.conf >+The backend configuration file (see also description of SANE_CONFIG_DIR below). >+ >+.TP >+.I @LIBDIR@/libsane-niash.a >+The static library implementing this backend. >+ >+.TP >+.I @LIBDIR@/libsane-niash.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 >+ >+.B SANE_DEBUG_NIASH >+If the library was compiled with debug support enabled, this >+environment variable controls the debug level for this backend. Higher >+debug levels increase the verbosity of the output. >+ >+Example: >+export SANE_DEBUG_NIASH=255 >+ >+.SH "SEE ALSO" >+sane(7), sane\-usb(5) >+.br >+http://www.sourceforge.net/projects/hp3300backend >+.SH AUTHOR >+Bertrik Sikken <bertrik@zonnet.nl>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 18479
: 13543