1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci Copyright (C) 2020 Ralph Little <skelband@gmail.com> 3141cc406Sopenharmony_ci Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org> 4141cc406Sopenharmony_ci Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net> 5141cc406Sopenharmony_ci Copyright (c) 2003 Henning Meier-Geinitz, <henning@meier-geinitz.de> 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci Originally copied from HP3300 testtools. Original notice follows: 8141cc406Sopenharmony_ci 9141cc406Sopenharmony_ci Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci This file is part of the SANE package. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 14141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License 15141cc406Sopenharmony_ci as published by the Free Software Foundation; either version 2 16141cc406Sopenharmony_ci of the License, or (at your option) any later version. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, 19141cc406Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 20141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21141cc406Sopenharmony_ci GNU General Public License for more details. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 24141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 27141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 30141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 31141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 32141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 33141cc406Sopenharmony_ci account of linking the SANE library code into it. 34141cc406Sopenharmony_ci 35141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 36141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 37141cc406Sopenharmony_ci License. 38141cc406Sopenharmony_ci 39141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 40141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 41141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 44141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 45141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci HP5400/5470 Test util. 48141cc406Sopenharmony_ci Currently is only able to read back the scanner version string, 49141cc406Sopenharmony_ci but this basically demonstrates ability to communicate with the scanner. 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci Massively expanded. Can do calibration scan, upload gamma and calibration 52141cc406Sopenharmony_ci tables and stores the results of a scan. - 19/02/2003 Martijn 53141cc406Sopenharmony_ci*/ 54141cc406Sopenharmony_ci 55141cc406Sopenharmony_ci#include <stdio.h> /* for printf */ 56141cc406Sopenharmony_ci#include <stdlib.h> /* for exit */ 57141cc406Sopenharmony_ci#include <assert.h> 58141cc406Sopenharmony_ci#include <errno.h> 59141cc406Sopenharmony_ci#include <string.h> 60141cc406Sopenharmony_ci#include <unistd.h> 61141cc406Sopenharmony_ci#include <math.h> 62141cc406Sopenharmony_ci#include <netinet/in.h> /* for htons */ 63141cc406Sopenharmony_ci#include <string.h> 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci#include "hp5400.h" 67141cc406Sopenharmony_ci#include "hp5400_xfer.h" 68141cc406Sopenharmony_ci#include "hp5400_internal.h" 69141cc406Sopenharmony_ci#include "hp5400_debug.h" /* debug functions */ 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci#ifndef min 73141cc406Sopenharmony_ci#define min(A,B) (((A)<(B)) ? (A) : (B)) 74141cc406Sopenharmony_ci#endif 75141cc406Sopenharmony_ci#ifndef max 76141cc406Sopenharmony_ci#define max(A,B) (((A)>(B)) ? (A) : (B)) 77141cc406Sopenharmony_ci#endif 78141cc406Sopenharmony_ci 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci#ifndef STRING_VERSION_MATCH 81141cc406Sopenharmony_ci#define NO_STRING_VERSION_MATCH 1 82141cc406Sopenharmony_ci#endif 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#ifdef __GNUC__ 85141cc406Sopenharmony_ci#define PACKED __attribute__ ((packed)) 86141cc406Sopenharmony_ci#else 87141cc406Sopenharmony_ci#define PACKED 88141cc406Sopenharmony_ci#endif 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci/* If this is enabled, a copy of the raw data from the scanner will be saved to 91141cc406Sopenharmony_ci imagedebug.dat and the attempted conversion to imagedebug.ppm */ 92141cc406Sopenharmony_ci/* #define IMAGE_DEBUG */ 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_ci/* If this is defined you get extra info on the calibration */ 95141cc406Sopenharmony_ci/* #define CALIB_DEBUG */ 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_citypedef struct versionString { 99141cc406Sopenharmony_ci char strVersion[128]; 100141cc406Sopenharmony_ci} versionString; 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ciconst int numVersions = 3; 103141cc406Sopenharmony_civersionString *MatchVersions; 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_cistatic TScannerModel Model_HP54xx = 107141cc406Sopenharmony_ci { "Hewlett-Packard", "HP54xx Flatbed Scanner" }; 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ciHP5400_SANE_STATIC 111141cc406Sopenharmony_ciint 112141cc406Sopenharmony_ciInitHp5400_internal() { 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci MatchVersions = malloc( sizeof(versionString) * numVersions ); 115141cc406Sopenharmony_ci strcpy( MatchVersions[0].strVersion, "SilitekIBlizd C3 ScannerV0.84"); 116141cc406Sopenharmony_ci strcpy( MatchVersions[1].strVersion, "SilitekIBlizd C3 ScannerV0.86"); 117141cc406Sopenharmony_ci strcpy( MatchVersions[2].strVersion, "SilitekIBlizd C3 ScannerV0.87"); 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_ci return 1; 120141cc406Sopenharmony_ci} 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ciHP5400_SANE_STATIC 123141cc406Sopenharmony_ciint 124141cc406Sopenharmony_ciFreeHp5400_internal() { 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci free(MatchVersions); 127141cc406Sopenharmony_ci MatchVersions = NULL; 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_ci return 1; 130141cc406Sopenharmony_ci} 131141cc406Sopenharmony_ci 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ciHP5400_SANE_STATIC 134141cc406Sopenharmony_ciint 135141cc406Sopenharmony_ciWriteByte (int iHandle, int cmd, char data) 136141cc406Sopenharmony_ci{ 137141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, cmd, 1, &data) < 0) 138141cc406Sopenharmony_ci { 139141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to send byte (cmd=%04X)\n", cmd); 140141cc406Sopenharmony_ci return -1; 141141cc406Sopenharmony_ci } 142141cc406Sopenharmony_ci return 0; 143141cc406Sopenharmony_ci} 144141cc406Sopenharmony_ci 145141cc406Sopenharmony_ciHP5400_SANE_STATIC 146141cc406Sopenharmony_ciint 147141cc406Sopenharmony_ciSetLamp (THWParams * pHWParams, int fLampOn) 148141cc406Sopenharmony_ci{ 149141cc406Sopenharmony_ci if (fLampOn) 150141cc406Sopenharmony_ci { 151141cc406Sopenharmony_ci if (WriteByte (pHWParams->iXferHandle, 0x0000, 0x01) == 0) 152141cc406Sopenharmony_ci return 0; 153141cc406Sopenharmony_ci } 154141cc406Sopenharmony_ci return -1; 155141cc406Sopenharmony_ci} 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ciHP5400_SANE_STATIC 159141cc406Sopenharmony_ciint 160141cc406Sopenharmony_ciGetSensors(THWParams * pHWParams, uint16_t *sensorMap) 161141cc406Sopenharmony_ci{ 162141cc406Sopenharmony_ci /* 163141cc406Sopenharmony_ci * Read until we get 0. 164141cc406Sopenharmony_ci * Max 10 iterations for safety. 165141cc406Sopenharmony_ci * 166141cc406Sopenharmony_ci */ 167141cc406Sopenharmony_ci *sensorMap = 0; 168141cc406Sopenharmony_ci uint16_t thisSensorMap = 0; 169141cc406Sopenharmony_ci size_t iterCount = 10; 170141cc406Sopenharmony_ci do 171141cc406Sopenharmony_ci { 172141cc406Sopenharmony_ci if (hp5400_command_read 173141cc406Sopenharmony_ci (pHWParams->iXferHandle, CMD_GETSENSORS, sizeof (uint16_t), &thisSensorMap) < 0) 174141cc406Sopenharmony_ci { 175141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to read sensors\n"); 176141cc406Sopenharmony_ci return -1; 177141cc406Sopenharmony_ci } 178141cc406Sopenharmony_ci *sensorMap |= thisSensorMap; 179141cc406Sopenharmony_ci } while (iterCount-- && (thisSensorMap > 0)); 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci return 0; 182141cc406Sopenharmony_ci} 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ciHP5400_SANE_STATIC 185141cc406Sopenharmony_ciint 186141cc406Sopenharmony_ciGetPanelInfo (THWParams * pHWParams, TPanelInfo *panelInfo) 187141cc406Sopenharmony_ci{ 188141cc406Sopenharmony_ci struct PanelInfo info; 189141cc406Sopenharmony_ci if (hp5400_command_read (pHWParams->iXferHandle, CMD_READPANEL, 190141cc406Sopenharmony_ci sizeof(info), &info) < 0) 191141cc406Sopenharmony_ci { 192141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to read panel info\n"); 193141cc406Sopenharmony_ci return -1; 194141cc406Sopenharmony_ci } 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci panelInfo->copycount = (SANE_Word)info.copycount; 197141cc406Sopenharmony_ci panelInfo->bwcolour = (SANE_Word)info.bwcolour; 198141cc406Sopenharmony_ci 199141cc406Sopenharmony_ci return 0; 200141cc406Sopenharmony_ci} 201141cc406Sopenharmony_ci 202141cc406Sopenharmony_ciHP5400_SANE_STATIC 203141cc406Sopenharmony_ciint 204141cc406Sopenharmony_ciSetCopyCount(THWParams * pHWParams, SANE_Word copyCount) 205141cc406Sopenharmony_ci{ 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci /* 208141cc406Sopenharmony_ci * I don't know what most of these things are but it is 209141cc406Sopenharmony_ci * necessary to send something sane otherwise we get an error from the scanner. 210141cc406Sopenharmony_ci * I got these settings from a USB trace. 211141cc406Sopenharmony_ci * Hopefully, we will learn what it is all about at some point 212141cc406Sopenharmony_ci * and hopefully it doesn't screw with other settings. 213141cc406Sopenharmony_ci * 214141cc406Sopenharmony_ci */ 215141cc406Sopenharmony_ci uint8_t packetImage[] = {0x02, 0x06, 0x32, 0x01, 216141cc406Sopenharmony_ci 0xf2, 0x40, 0x16, 0x01, 217141cc406Sopenharmony_ci 0x7b, 0x41, 0x16, 0x01, 218141cc406Sopenharmony_ci 0xdc, 0x06, 0x32, 0x01, 219141cc406Sopenharmony_ci 0xd7, 0x5b, 0x16, 0x01, 220141cc406Sopenharmony_ci 0xac, 0x06, 0x32, 0x01, 221141cc406Sopenharmony_ci 0xf8, 0xd7, 0x18, 0x01, 222141cc406Sopenharmony_ci 0xd8, 0x06, 0x32, 0x01, 223141cc406Sopenharmony_ci 0x2c, 0xf3, 0x12, 0x00, 224141cc406Sopenharmony_ci 0x70, 0x8d, 0x18, 0x01, 225141cc406Sopenharmony_ci 0x7b, 0x00, 0x00, 0x00}; 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci struct PanelInfo workingInfo; 228141cc406Sopenharmony_ci (void)memcpy(&workingInfo, packetImage, sizeof(workingInfo)); 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci workingInfo.copycount = (uint8_t)copyCount; 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci if (hp5400_command_write (pHWParams->iXferHandle, CMD_WRITEPANEL, 233141cc406Sopenharmony_ci sizeof(workingInfo), &workingInfo) < 0) 234141cc406Sopenharmony_ci { 235141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to write panel info\n"); 236141cc406Sopenharmony_ci return -1; 237141cc406Sopenharmony_ci } 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci return 0; 240141cc406Sopenharmony_ci} 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ciHP5400_SANE_STATIC 243141cc406Sopenharmony_ciint 244141cc406Sopenharmony_ciSetColourBW(THWParams * pHWParams, SANE_Word colourBW) 245141cc406Sopenharmony_ci{ 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci /* 248141cc406Sopenharmony_ci * I don't know what most of these things are but it is 249141cc406Sopenharmony_ci * necessary to send something sane otherwise we get an error from the scanner. 250141cc406Sopenharmony_ci * I got these settings from a USB trace. 251141cc406Sopenharmony_ci * Hopefully, we will learn what it is all about at some point 252141cc406Sopenharmony_ci * and hopefully it doesn't screw with other settings. 253141cc406Sopenharmony_ci * 254141cc406Sopenharmony_ci */ 255141cc406Sopenharmony_ci uint8_t packetImage[] = {0x03, 0x06, 0x32, 0x01, 256141cc406Sopenharmony_ci 0xf2, 0x40, 0x16, 0x01, 257141cc406Sopenharmony_ci 0x7b, 0x41, 0x16, 0x01, 258141cc406Sopenharmony_ci 0xdc, 0x06, 0x32, 0x01, 259141cc406Sopenharmony_ci 0xd7, 0x5b, 0x16, 0x01, 260141cc406Sopenharmony_ci 0xac, 0x06, 0x32, 0x01, 261141cc406Sopenharmony_ci 0xf8, 0xd7, 0x18, 0x01, 262141cc406Sopenharmony_ci 0xd8, 0x06, 0x32, 0x01, 263141cc406Sopenharmony_ci 0x68, 0xf5, 0x12, 0x00, 264141cc406Sopenharmony_ci 0x70, 0x8d, 0x18, 0x01, 265141cc406Sopenharmony_ci 0x7b, 0x00, 0x00, 0x00}; 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci struct PanelInfo workingInfo; 268141cc406Sopenharmony_ci (void)memcpy(&workingInfo, packetImage, sizeof(workingInfo)); 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci workingInfo.bwcolour = (uint8_t)colourBW; 271141cc406Sopenharmony_ci 272141cc406Sopenharmony_ci if (hp5400_command_write (pHWParams->iXferHandle, CMD_WRITEPANEL, 273141cc406Sopenharmony_ci sizeof(workingInfo), &workingInfo) < 0) 274141cc406Sopenharmony_ci { 275141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to write panel info\n"); 276141cc406Sopenharmony_ci return -1; 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_ci return 0; 280141cc406Sopenharmony_ci} 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ciHP5400_SANE_STATIC 285141cc406Sopenharmony_ciint 286141cc406Sopenharmony_ciWarmupLamp (int iHandle) 287141cc406Sopenharmony_ci{ 288141cc406Sopenharmony_ci int i = 30; /* Max 30 seconds, 15 is typical for cold start? */ 289141cc406Sopenharmony_ci int couldRead; 290141cc406Sopenharmony_ci unsigned char dataVerify[0x02]; 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci /* Keep writing 01 to 0000 until no error... */ 293141cc406Sopenharmony_ci unsigned char data0000[] = { 294141cc406Sopenharmony_ci 0x01 295141cc406Sopenharmony_ci }; 296141cc406Sopenharmony_ci unsigned char data0300[3]; 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci hp5400_command_write_noverify (iHandle, 0x0000, data0000, 1); 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci do 302141cc406Sopenharmony_ci { 303141cc406Sopenharmony_ci hp5400_command_read_noverify (iHandle, 0x0300, 3, data0300); 304141cc406Sopenharmony_ci 305141cc406Sopenharmony_ci hp5400_command_write_noverify (iHandle, 0x0000, data0000, 1); 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci couldRead = 308141cc406Sopenharmony_ci hp5400_command_read_noverify (iHandle, 0xc500, 0x02, dataVerify); 309141cc406Sopenharmony_ci if ((dataVerify[0] != 0) || (dataVerify[1] != 0)) 310141cc406Sopenharmony_ci sleep (1); 311141cc406Sopenharmony_ci } 312141cc406Sopenharmony_ci while ((i-- > 0) && (couldRead >= 0) 313141cc406Sopenharmony_ci && ((dataVerify[0] != 0) || (dataVerify[1] != 0))); 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci if (i > 0) 316141cc406Sopenharmony_ci return 0; 317141cc406Sopenharmony_ci 318141cc406Sopenharmony_ci /* 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_ci while( i > 0 ) 321141cc406Sopenharmony_ci { 322141cc406Sopenharmony_ci if( WriteByte( iHandle, 0x0000, 0x01 ) == 0 ) 323141cc406Sopenharmony_ci return 0; 324141cc406Sopenharmony_ci sleep(1); 325141cc406Sopenharmony_ci i--; 326141cc406Sopenharmony_ci } 327141cc406Sopenharmony_ci */ 328141cc406Sopenharmony_ci 329141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "***WARNING*** Warmup lamp failed...\n"); 330141cc406Sopenharmony_ci return -1; 331141cc406Sopenharmony_ci} 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci#define CALPIXBYBLOCK 42 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ciHP5400_SANE_STATIC 336141cc406Sopenharmony_ciint 337141cc406Sopenharmony_ciSetCalibration (int iHandle, int numPixels, unsigned int *low_vals[3], 338141cc406Sopenharmony_ci unsigned int *high_vals[3], int dpi) 339141cc406Sopenharmony_ci{ 340141cc406Sopenharmony_ci char cmd[8]; 341141cc406Sopenharmony_ci /* unsigned char cmd[8]; */ /* should fix the compilation warning 342141cc406Sopenharmony_ci but I don't have a scanner right now 343141cc406Sopenharmony_ci to check that the fix does not break 344141cc406Sopenharmony_ci calibration */ 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci int i, j, k; 347141cc406Sopenharmony_ci struct CalPixel 348141cc406Sopenharmony_ci { 349141cc406Sopenharmony_ci char highr[2], highg[2], highb[2]; 350141cc406Sopenharmony_ci char lowr[2], lowg[2], lowb[2]; 351141cc406Sopenharmony_ci }; 352141cc406Sopenharmony_ci struct CalBlock 353141cc406Sopenharmony_ci { 354141cc406Sopenharmony_ci struct CalPixel pixels[CALPIXBYBLOCK]; 355141cc406Sopenharmony_ci char pad[8]; 356141cc406Sopenharmony_ci } 357141cc406Sopenharmony_ci PACKED; 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci struct CalBlock *calinfo; 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci /** 362141cc406Sopenharmony_ci we did scan test at 300 dpi, so we don't have all the needed pixels. 363141cc406Sopenharmony_ci To fill the gap, we loop 364141cc406Sopenharmony_ci */ 365141cc406Sopenharmony_ci int numLoop = max (1, dpi / 300); 366141cc406Sopenharmony_ci int calBlockSize = CALPIXBYBLOCK * (6 * sizeof (short)) + 8 * sizeof (char); /* = sizeof(calBlock) */ 367141cc406Sopenharmony_ci int numCalBlock = 368141cc406Sopenharmony_ci ((numPixels / CALPIXBYBLOCK) + 369141cc406Sopenharmony_ci ((numPixels % CALPIXBYBLOCK != 0) ? 1 : 0)); 370141cc406Sopenharmony_ci int calSize = numLoop * calBlockSize * numCalBlock; 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci calinfo = malloc (calSize); 373141cc406Sopenharmony_ci memset (calinfo, 0, calSize); 374141cc406Sopenharmony_ci 375141cc406Sopenharmony_ci for (j = 0; j < numLoop * numCalBlock * CALPIXBYBLOCK; j++) 376141cc406Sopenharmony_ci { 377141cc406Sopenharmony_ci struct CalPixel *pixel = 378141cc406Sopenharmony_ci &calinfo[j / CALPIXBYBLOCK].pixels[j % CALPIXBYBLOCK]; 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci /* 381141cc406Sopenharmony_ci i = ( j % (int)( 0.80 * numPixels ) ) + (int)(0.10 * numPixels ); 382141cc406Sopenharmony_ci */ 383141cc406Sopenharmony_ci /* better solution : stretch the actual scan size to the calibration size */ 384141cc406Sopenharmony_ci i = j / numLoop; 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci /* This is obviously not quite right. The values on 387141cc406Sopenharmony_ci * the right are approximately what windows sends */ 388141cc406Sopenharmony_ci k = (high_vals[0][i] > 0x4000) ? 1000000000 / high_vals[0][i] : 0; /* 0x6700 */ 389141cc406Sopenharmony_ci pixel->highr[0] = k; 390141cc406Sopenharmony_ci pixel->highr[1] = k >> 8; 391141cc406Sopenharmony_ci k = (high_vals[1][i] > 0x4000) ? 1000000000 / high_vals[1][i] : 0; /* 0x5e00 */ 392141cc406Sopenharmony_ci pixel->highg[0] = k; 393141cc406Sopenharmony_ci pixel->highg[1] = k >> 8; 394141cc406Sopenharmony_ci k = (high_vals[2][i] > 0x4000) ? 1000000000 / high_vals[2][i] : 0; /* 0x6000 */ 395141cc406Sopenharmony_ci pixel->highb[0] = k; 396141cc406Sopenharmony_ci pixel->highb[1] = k >> 8; 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci pixel->lowr[0] = low_vals[0][i]; /* 0x0530 */ 399141cc406Sopenharmony_ci pixel->lowr[1] = low_vals[0][i] >> 8; 400141cc406Sopenharmony_ci pixel->lowg[0] = low_vals[1][i]; /* 0x0530 */ 401141cc406Sopenharmony_ci pixel->lowg[1] = low_vals[1][i] >> 8; 402141cc406Sopenharmony_ci pixel->lowb[0] = low_vals[2][i]; /* 0x0530 */ 403141cc406Sopenharmony_ci pixel->lowb[1] = low_vals[2][i] >> 8; 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci cmd[0] = 0xff & (calSize >> 16); 407141cc406Sopenharmony_ci cmd[1] = 0xff & (calSize >> 8); 408141cc406Sopenharmony_ci cmd[2] = 0xff & (calSize >> 0); 409141cc406Sopenharmony_ci cmd[3] = 0x00; 410141cc406Sopenharmony_ci cmd[4] = 0x54; 411141cc406Sopenharmony_ci cmd[5] = 0x02; 412141cc406Sopenharmony_ci cmd[6] = -128; // 0x80; fixes compiler warning (for 413141cc406Sopenharmony_ci // signed char implementations), see 414141cc406Sopenharmony_ci // also comment above 415141cc406Sopenharmony_ci cmd[7] = 0x00; 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci hp5400_bulk_command_write (iHandle, 0xE603, cmd, 8, calSize, calSize, 418141cc406Sopenharmony_ci (void *) calinfo); 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci free (calinfo); 421141cc406Sopenharmony_ci return 0; 422141cc406Sopenharmony_ci} 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ci/* Write a gamma table */ 425141cc406Sopenharmony_ciHP5400_SANE_STATIC 426141cc406Sopenharmony_civoid 427141cc406Sopenharmony_ciWriteGammaCalibTable (int iHandle, const int *pabGammaR, const int *pabGammaG, 428141cc406Sopenharmony_ci const int *pabGammaB) 429141cc406Sopenharmony_ci{ 430141cc406Sopenharmony_ci char cmd[3]; 431141cc406Sopenharmony_ci char *buffer; 432141cc406Sopenharmony_ci int i, j; 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci /* Setup dummy gamma correction table */ 435141cc406Sopenharmony_ci buffer = malloc (2 * 65536); 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci cmd[0] = 2; 438141cc406Sopenharmony_ci cmd[1] = 0; 439141cc406Sopenharmony_ci cmd[2] = 0; 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci for (i = 0; i < 3; i++) 442141cc406Sopenharmony_ci { 443141cc406Sopenharmony_ci const int *ptr = (i == 0) ? pabGammaR : 444141cc406Sopenharmony_ci (i == 1) ? pabGammaG : pabGammaB; 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ci for (j = 0; j < 65536; j++) { 447141cc406Sopenharmony_ci buffer[2 * j] = ptr[j]; 448141cc406Sopenharmony_ci buffer[2 * j + 1] = ptr[j] >> 8; 449141cc406Sopenharmony_ci } 450141cc406Sopenharmony_ci 451141cc406Sopenharmony_ci hp5400_bulk_command_write (iHandle, 0x2A01 + i, cmd, 3, 2 * 65536, 452141cc406Sopenharmony_ci 65536, (void *) buffer); 453141cc406Sopenharmony_ci } 454141cc406Sopenharmony_ci free (buffer); 455141cc406Sopenharmony_ci 456141cc406Sopenharmony_ci return; 457141cc406Sopenharmony_ci} 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci#ifdef STANDALONE 460141cc406Sopenharmony_ciHP5400_SANE_STATIC 461141cc406Sopenharmony_civoid 462141cc406Sopenharmony_ciSetDefaultGamma (int iHandle) 463141cc406Sopenharmony_ci{ 464141cc406Sopenharmony_ci int *buffer = malloc (sizeof (int) * 65536); 465141cc406Sopenharmony_ci int i; 466141cc406Sopenharmony_ci 467141cc406Sopenharmony_ci for (i = 0; i < 65336; i++) 468141cc406Sopenharmony_ci buffer[i] = i; 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci WriteGammaCalibTable (iHandle, buffer, buffer, buffer); 471141cc406Sopenharmony_ci} 472141cc406Sopenharmony_ci#endif 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci#define BUFFER_SIZE (6*65536) 475141cc406Sopenharmony_ci 476141cc406Sopenharmony_ci#ifdef IMAGE_DEBUG 477141cc406Sopenharmony_ciFILE *temp; 478141cc406Sopenharmony_ci#endif 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci/* Bytes per line is the number of pixels. The actual bytes is one more */ 481141cc406Sopenharmony_ciHP5400_SANE_STATIC 482141cc406Sopenharmony_civoid 483141cc406Sopenharmony_ciCircBufferInit (int iHandle, TDataPipe * p, int iBytesPerLine, 484141cc406Sopenharmony_ci int bpp, int iMisAlignment, int blksize, int iTransferSize) 485141cc406Sopenharmony_ci{ 486141cc406Sopenharmony_ci (void) iHandle; /* to avoid compilation warning */ 487141cc406Sopenharmony_ci p->buffersize = max (BUFFER_SIZE, 3 * blksize); 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_ci if (p->buffer) 490141cc406Sopenharmony_ci { 491141cc406Sopenharmony_ci free (p->buffer); 492141cc406Sopenharmony_ci } 493141cc406Sopenharmony_ci 494141cc406Sopenharmony_ci /* Allocate a large enough buffer for transfer */ 495141cc406Sopenharmony_ci p->buffer = malloc (p->buffersize); 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci p->pixels = (iBytesPerLine / 3) / bpp; 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci /* These three must always be positive */ 500141cc406Sopenharmony_ci p->roff = 0; 501141cc406Sopenharmony_ci p->goff = p->pixels * bpp + 1; 502141cc406Sopenharmony_ci p->boff = 2 * p->pixels * bpp + 2;; 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci p->linelength = iBytesPerLine + 3; /* NUL at end of each row */ 505141cc406Sopenharmony_ci p->bpp = bpp; 506141cc406Sopenharmony_ci p->bufstart = p->bufend = 0; 507141cc406Sopenharmony_ci 508141cc406Sopenharmony_ci if (iMisAlignment > 0) 509141cc406Sopenharmony_ci { 510141cc406Sopenharmony_ci p->roff += 0; 511141cc406Sopenharmony_ci p->goff += p->linelength * iMisAlignment; 512141cc406Sopenharmony_ci p->boff += p->linelength * iMisAlignment * 2; 513141cc406Sopenharmony_ci } 514141cc406Sopenharmony_ci 515141cc406Sopenharmony_ci if (iMisAlignment < 0) 516141cc406Sopenharmony_ci { 517141cc406Sopenharmony_ci p->roff -= p->linelength * iMisAlignment * 2; 518141cc406Sopenharmony_ci p->goff -= p->linelength * iMisAlignment; 519141cc406Sopenharmony_ci p->boff -= 0; 520141cc406Sopenharmony_ci } 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci p->blksize = blksize; 523141cc406Sopenharmony_ci p->transfersize = iTransferSize; 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci#ifdef IMAGE_DEBUG 526141cc406Sopenharmony_ci temp = fopen ("imagedebug.dat", "w+b"); 527141cc406Sopenharmony_ci#endif 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, 530141cc406Sopenharmony_ci "Begin: line=%d (%X), pixels=%d (%X), r=%d (%X), g=%d (%X), b=%d (%X), bpp=%d, step=%d\n", 531141cc406Sopenharmony_ci p->linelength, p->linelength, p->pixels, p->pixels, p->roff, p->roff, 532141cc406Sopenharmony_ci p->goff, p->goff, p->boff, p->boff, bpp, iMisAlignment); 533141cc406Sopenharmony_ci} 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ciHP5400_SANE_STATIC 537141cc406Sopenharmony_ciint 538141cc406Sopenharmony_ciCircBufferGetLine (int iHandle, TDataPipe * p, void *pabLine) 539141cc406Sopenharmony_ci{ 540141cc406Sopenharmony_ci int i; 541141cc406Sopenharmony_ci int maxoff = 0; 542141cc406Sopenharmony_ci char* buftmp = (char*) (p->buffer); 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ci/* HP5400_DBG(DBG_MSG, "CircBufferGetLine:\n"); */ 545141cc406Sopenharmony_ci 546141cc406Sopenharmony_ci if (p->roff > maxoff) 547141cc406Sopenharmony_ci maxoff = p->roff; 548141cc406Sopenharmony_ci if (p->goff > maxoff) 549141cc406Sopenharmony_ci maxoff = p->goff; 550141cc406Sopenharmony_ci if (p->boff > maxoff) 551141cc406Sopenharmony_ci maxoff = p->boff; 552141cc406Sopenharmony_ci 553141cc406Sopenharmony_ci maxoff += p->pixels * p->bpp; 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci if (maxoff < p->linelength) 556141cc406Sopenharmony_ci maxoff = p->linelength; 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci /* resize buffer if needed */ 560141cc406Sopenharmony_ci if (p->bufstart + maxoff >= p->buffersize + p->blksize) 561141cc406Sopenharmony_ci { 562141cc406Sopenharmony_ci /* store actual buffer pointer */ 563141cc406Sopenharmony_ci void *tmpBuf = p->buffer; 564141cc406Sopenharmony_ci /* calculate new size for buffer (oversize a bit) */ 565141cc406Sopenharmony_ci int newsize = p->bufstart + maxoff + 2 * p->blksize; 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci p->buffer = malloc (newsize); 568141cc406Sopenharmony_ci memcpy (p->buffer, tmpBuf, p->buffersize); 569141cc406Sopenharmony_ci p->buffersize = newsize; 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci /* free old buffer */ 572141cc406Sopenharmony_ci free (tmpBuf); 573141cc406Sopenharmony_ci buftmp = (char*)(p->buffer); 574141cc406Sopenharmony_ci } 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci while (p->bufstart + maxoff >= p->bufend) /* Not enough data in buffer */ 577141cc406Sopenharmony_ci { 578141cc406Sopenharmony_ci int res; 579141cc406Sopenharmony_ci unsigned char cmd[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 580141cc406Sopenharmony_ci cmd[4] = p->blksize; 581141cc406Sopenharmony_ci cmd[5] = p->blksize >> 8; 582141cc406Sopenharmony_ci 583141cc406Sopenharmony_ci assert ((p->bufend + p->blksize) <= p->buffersize); 584141cc406Sopenharmony_ci 585141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Reading block, %d bytes remain\n", p->transfersize); 586141cc406Sopenharmony_ci p->transfersize -= p->blksize; 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_ci res = 589141cc406Sopenharmony_ci hp5400_bulk_read_block (iHandle, CMD_INITBULK3, cmd, sizeof (cmd), 590141cc406Sopenharmony_ci buftmp + p->bufend, p->blksize); 591141cc406Sopenharmony_ci if (res != p->blksize) 592141cc406Sopenharmony_ci { 593141cc406Sopenharmony_ci HP5400_DBG (DBG_ERR, "*** ERROR: Read returned %d. FATAL.\n", res); 594141cc406Sopenharmony_ci return -1; 595141cc406Sopenharmony_ci } 596141cc406Sopenharmony_ci#ifdef IMAGE_DEBUG 597141cc406Sopenharmony_ci fwrite ( 598141cc406Sopenharmony_ci buftmp + p->bufend 599141cc406Sopenharmony_ci ,p->blksize 600141cc406Sopenharmony_ci ,1 601141cc406Sopenharmony_ci ,temp 602141cc406Sopenharmony_ci ); 603141cc406Sopenharmony_ci#endif 604141cc406Sopenharmony_ci p->bufend += p->blksize; 605141cc406Sopenharmony_ci } 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci assert (p->bufstart + maxoff < p->bufend); 608141cc406Sopenharmony_ci 609141cc406Sopenharmony_ci /* Copy a line into the result buffer */ 610141cc406Sopenharmony_ci if (p->bpp == 1) 611141cc406Sopenharmony_ci { 612141cc406Sopenharmony_ci char *itPix = (char *) pabLine; 613141cc406Sopenharmony_ci char *itR = (char *) (buftmp + p->bufstart + p->roff); 614141cc406Sopenharmony_ci char *itG = (char *) (buftmp + p->bufstart + p->goff); 615141cc406Sopenharmony_ci char *itB = (char *) (buftmp + p->bufstart + p->boff); 616141cc406Sopenharmony_ci for (i = 0; i < p->pixels; i++) 617141cc406Sopenharmony_ci { 618141cc406Sopenharmony_ci /* pointer move goes a little bit faster than vector access */ 619141cc406Sopenharmony_ci /* Although I wouldn't be surprised if the compiler worked that out anyway. 620141cc406Sopenharmony_ci * No matter, this is easier to read :) */ 621141cc406Sopenharmony_ci *(itPix++) = *(itR++); 622141cc406Sopenharmony_ci *(itPix++) = *(itG++); 623141cc406Sopenharmony_ci *(itPix++) = *(itB++); 624141cc406Sopenharmony_ci } 625141cc406Sopenharmony_ci } 626141cc406Sopenharmony_ci else 627141cc406Sopenharmony_ci { 628141cc406Sopenharmony_ci short *itPix = (short *) pabLine; 629141cc406Sopenharmony_ci short *itR = (short *) (buftmp + p->bufstart + p->roff); 630141cc406Sopenharmony_ci short *itG = (short *) (buftmp + p->bufstart + p->goff); 631141cc406Sopenharmony_ci short *itB = (short *) (buftmp + p->bufstart + p->boff); 632141cc406Sopenharmony_ci for (i = 0; i < p->pixels; i++) 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci#if 0 635141cc406Sopenharmony_ci /* This code, while correct for PBM is not correct for the host and 636141cc406Sopenharmony_ci * since we need it correct for calibration, it has to go */ 637141cc406Sopenharmony_ci ((short *) pabLine)[3 * i + 0] = 638141cc406Sopenharmony_ci *((short *) (p->buffer + p->bufstart + p->roff + 2 * i)); 639141cc406Sopenharmony_ci ((short *) pabLine)[3 * i + 1] = 640141cc406Sopenharmony_ci *((short *) (p->buffer + p->bufstart + p->goff + 2 * i)); 641141cc406Sopenharmony_ci ((short *) pabLine)[3 * i + 2] = 642141cc406Sopenharmony_ci *((short *) (p->buffer + p->bufstart + p->boff + 2 * i)); 643141cc406Sopenharmony_ci#else 644141cc406Sopenharmony_ci /* pointer move goes a little bit faster than vector access */ 645141cc406Sopenharmony_ci *(itPix++) = htons (*(itR++)); 646141cc406Sopenharmony_ci *(itPix++) = htons (*(itG++)); 647141cc406Sopenharmony_ci *(itPix++) = htons (*(itB++)); 648141cc406Sopenharmony_ci#endif 649141cc406Sopenharmony_ci } 650141cc406Sopenharmony_ci } 651141cc406Sopenharmony_ci 652141cc406Sopenharmony_ci p->bufstart += p->linelength; 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci assert (p->bufstart <= p->bufend); 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci /* If we've used a whole block at the beginning, move it */ 657141cc406Sopenharmony_ci if (p->bufstart > p->blksize) 658141cc406Sopenharmony_ci { 659141cc406Sopenharmony_ci memmove ( 660141cc406Sopenharmony_ci buftmp 661141cc406Sopenharmony_ci ,buftmp + p->bufstart 662141cc406Sopenharmony_ci ,p->bufend - p->bufstart 663141cc406Sopenharmony_ci ); 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci p->bufend -= p->bufstart; 666141cc406Sopenharmony_ci p->bufstart = 0; 667141cc406Sopenharmony_ci } 668141cc406Sopenharmony_ci 669141cc406Sopenharmony_ci return 0; 670141cc406Sopenharmony_ci} 671141cc406Sopenharmony_ci 672141cc406Sopenharmony_ciHP5400_SANE_STATIC 673141cc406Sopenharmony_civoid 674141cc406Sopenharmony_ciCircBufferExit (TDataPipe * p) 675141cc406Sopenharmony_ci{ 676141cc406Sopenharmony_ci free (p->buffer); 677141cc406Sopenharmony_ci p->buffer = NULL; 678141cc406Sopenharmony_ci#ifdef IMAGE_DEBUG 679141cc406Sopenharmony_ci fclose (temp); 680141cc406Sopenharmony_ci temp = NULL; 681141cc406Sopenharmony_ci#endif 682141cc406Sopenharmony_ci return; 683141cc406Sopenharmony_ci} 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ci#ifdef STANDALONE 687141cc406Sopenharmony_ci/* bpp is BYTES per pixel */ 688141cc406Sopenharmony_ciHP5400_SANE_STATIC 689141cc406Sopenharmony_civoid 690141cc406Sopenharmony_ciDecodeImage (FILE * file, int planes, int bpp, int xsize, int ysize, 691141cc406Sopenharmony_ci const char *filename) 692141cc406Sopenharmony_ci{ 693141cc406Sopenharmony_ci char *in, *buf; 694141cc406Sopenharmony_ci char *p[3]; 695141cc406Sopenharmony_ci FILE *output; 696141cc406Sopenharmony_ci int i, j, k; 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci /* xsize is byte width, not pixel width */ 699141cc406Sopenharmony_ci xsize /= planes * bpp; 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, 702141cc406Sopenharmony_ci "DecodeImage(planes=%d,bpp=%d,xsize=%d,ysize=%d) => %d (file=%s)\n", 703141cc406Sopenharmony_ci planes, bpp, xsize, ysize, planes * bpp * xsize * ysize, filename); 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci in = malloc (planes * (xsize * bpp + 1)); 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci for (i = 0; i < planes; i++) 708141cc406Sopenharmony_ci p[i] = in + i * (xsize * bpp + 1); 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci buf = malloc (3 * xsize * bpp); 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci output = fopen (filename, "wb"); 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci fprintf (output, "P%d\n%d %d\n", (planes == 3) ? 6 : 5, xsize, ysize); 715141cc406Sopenharmony_ci fprintf (output, "%d\n", (bpp == 1) ? 255 : 0xb000); 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci for (i = 0; i < ysize; i++) 718141cc406Sopenharmony_ci { 719141cc406Sopenharmony_ci fread (in, planes * (xsize * bpp + 1), 1, file); 720141cc406Sopenharmony_ci 721141cc406Sopenharmony_ci for (j = 0; j < xsize; j++) 722141cc406Sopenharmony_ci { 723141cc406Sopenharmony_ci for (k = 0; k < planes; k++) 724141cc406Sopenharmony_ci { 725141cc406Sopenharmony_ci if (bpp == 1) 726141cc406Sopenharmony_ci { 727141cc406Sopenharmony_ci buf[j * planes + k] = p[k][j]; 728141cc406Sopenharmony_ci } 729141cc406Sopenharmony_ci else if (bpp == 2) 730141cc406Sopenharmony_ci { 731141cc406Sopenharmony_ci buf[j * planes * 2 + k * 2 + 0] = p[k][2 * j + 0]; 732141cc406Sopenharmony_ci buf[j * planes * 2 + k * 2 + 1] = p[k][2 * j + 1]; 733141cc406Sopenharmony_ci } 734141cc406Sopenharmony_ci } 735141cc406Sopenharmony_ci } 736141cc406Sopenharmony_ci fwrite (buf, planes * xsize * bpp, 1, output); 737141cc406Sopenharmony_ci } 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci fclose (output); 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci free (in); 742141cc406Sopenharmony_ci free (buf); 743141cc406Sopenharmony_ci} 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ciHP5400_SANE_STATIC 746141cc406Sopenharmony_ciint 747141cc406Sopenharmony_cihp5400_test_scan_response (struct ScanResponse *resp, struct ScanRequest *req) 748141cc406Sopenharmony_ci{ 749141cc406Sopenharmony_ci (void) req; /* to avoid compilation warning */ 750141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Scan response:\n"); 751141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " transfersize=%d htonl-> %d\n", resp->transfersize, 752141cc406Sopenharmony_ci htonl (resp->transfersize)); 753141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " xsize=%d htonl-> %d\n", resp->xsize, 754141cc406Sopenharmony_ci htonl (resp->xsize)); 755141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " ysize=%d htons-> %d\n", resp->ysize, 756141cc406Sopenharmony_ci htons (resp->ysize)); 757141cc406Sopenharmony_ci return 1; 758141cc406Sopenharmony_ci} 759141cc406Sopenharmony_ci#endif 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci/* This is a very specialised scanning function. It does the scan request as 762141cc406Sopenharmony_ci * usual but instead of producing an image it returns three arrays of ints. 763141cc406Sopenharmony_ci * These are averages of the R,G,B values for each column. 764141cc406Sopenharmony_ci * 765141cc406Sopenharmony_ci * Note the array argument should point to an array of three NULL. These 766141cc406Sopenharmony_ci * will be overwritten with allocated pointers. */ 767141cc406Sopenharmony_ci 768141cc406Sopenharmony_ciHP5400_SANE_STATIC 769141cc406Sopenharmony_ciint 770141cc406Sopenharmony_ciDoAverageScan (int iHandle, struct ScanRequest *req, int code, 771141cc406Sopenharmony_ci unsigned int **array) 772141cc406Sopenharmony_ci{ 773141cc406Sopenharmony_ci THWParams HWParams; 774141cc406Sopenharmony_ci struct ScanResponse res; 775141cc406Sopenharmony_ci unsigned short *buffer; 776141cc406Sopenharmony_ci int i, j, k, length; 777141cc406Sopenharmony_ci 778141cc406Sopenharmony_ci memset (&HWParams, 0, sizeof (HWParams)); 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci HWParams.iXferHandle = iHandle; 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci if (InitScan2 (SCAN_TYPE_CALIBRATION, req, &HWParams, &res, 0, code) != 0) 783141cc406Sopenharmony_ci return -1; /* No colour offsetting, we want raw */ 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci length = htonl (res.xsize) / 6; 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Calibration scan: %d pixels wide\n", length); 788141cc406Sopenharmony_ci 789141cc406Sopenharmony_ci for (j = 0; j < 3; j++) 790141cc406Sopenharmony_ci { 791141cc406Sopenharmony_ci array[j] = malloc (sizeof (int) * length); 792141cc406Sopenharmony_ci memset (array[j], 0, sizeof (int) * length); /* Clear array */ 793141cc406Sopenharmony_ci } 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci buffer = malloc (htonl (res.xsize) + 1); 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci /* First we just sum them all */ 798141cc406Sopenharmony_ci for (i = 0; i < htons (res.ysize); i++) 799141cc406Sopenharmony_ci { 800141cc406Sopenharmony_ci CircBufferGetLine (iHandle, &HWParams.pipe, buffer); 801141cc406Sopenharmony_ci 802141cc406Sopenharmony_ci for (j = 0; j < length; j++) 803141cc406Sopenharmony_ci for (k = 0; k < 3; k++) 804141cc406Sopenharmony_ci array[k][j] += buffer[3 * j + k]; 805141cc406Sopenharmony_ci } 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci free (buffer); 808141cc406Sopenharmony_ci FinishScan (&HWParams); 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci /* Now divide by the height to get the average */ 811141cc406Sopenharmony_ci for (j = 0; j < length; j++) 812141cc406Sopenharmony_ci for (k = 0; k < 3; k++) 813141cc406Sopenharmony_ci array[k][j] /= htons (res.ysize); 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci return 0; 816141cc406Sopenharmony_ci} 817141cc406Sopenharmony_ci 818141cc406Sopenharmony_ci#ifdef STANDALONE 819141cc406Sopenharmony_ciHP5400_SANE_STATIC 820141cc406Sopenharmony_ciint 821141cc406Sopenharmony_ciDoScan (int iHandle, struct ScanRequest *req, const char *filename, int code, 822141cc406Sopenharmony_ci struct ScanResponse *res) 823141cc406Sopenharmony_ci{ 824141cc406Sopenharmony_ci FILE *file; 825141cc406Sopenharmony_ci THWParams HWParams; 826141cc406Sopenharmony_ci struct ScanResponse res_temp; 827141cc406Sopenharmony_ci void *buffer; 828141cc406Sopenharmony_ci/* int bpp, planes; */ 829141cc406Sopenharmony_ci int i; 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci (void) code; /*to avoid compilation warning*/ 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci if (res == NULL) 834141cc406Sopenharmony_ci res = &res_temp; 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci memset (&HWParams, 0, sizeof (HWParams)); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci file = fopen (filename, "w+b"); 839141cc406Sopenharmony_ci if (!file) 840141cc406Sopenharmony_ci { 841141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Couldn't open outputfile (%s)\n", strerror (errno)); 842141cc406Sopenharmony_ci return -1; 843141cc406Sopenharmony_ci } 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci HWParams.iXferHandle = iHandle; 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci if (InitScan2 (SCAN_TYPE_NORMAL, req, &HWParams, res, 1, 0x40) != 0) 848141cc406Sopenharmony_ci return -1; 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci fprintf (file, "P%d\n%d %d\n", 6, htonl (res->xsize) / 3, 851141cc406Sopenharmony_ci htons (res->ysize)); 852141cc406Sopenharmony_ci fprintf (file, "%d\n", 255); 853141cc406Sopenharmony_ci 854141cc406Sopenharmony_ci buffer = malloc (htonl (res->xsize) + 1); 855141cc406Sopenharmony_ci for (i = 0; i < htons (res->ysize); i++) 856141cc406Sopenharmony_ci { 857141cc406Sopenharmony_ci CircBufferGetLine (iHandle, &HWParams.pipe, buffer); 858141cc406Sopenharmony_ci 859141cc406Sopenharmony_ci fwrite (buffer, htonl (res->xsize), 1, file); 860141cc406Sopenharmony_ci } 861141cc406Sopenharmony_ci free (buffer); 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci FinishScan (&HWParams); 864141cc406Sopenharmony_ci 865141cc406Sopenharmony_ci fclose (file); 866141cc406Sopenharmony_ci return 0; 867141cc406Sopenharmony_ci} 868141cc406Sopenharmony_ci#endif 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ciHP5400_SANE_STATIC 871141cc406Sopenharmony_ciint 872141cc406Sopenharmony_ciCalibrate (int iHandle, int dpi) 873141cc406Sopenharmony_ci{ 874141cc406Sopenharmony_ci struct ScanRequest req; 875141cc406Sopenharmony_ci 876141cc406Sopenharmony_ci unsigned int *low_array[3]; 877141cc406Sopenharmony_ci unsigned int *high_array[3]; 878141cc406Sopenharmony_ci#ifdef CALIB_DEBUG 879141cc406Sopenharmony_ci char buffer[512]; 880141cc406Sopenharmony_ci int i, j; 881141cc406Sopenharmony_ci#endif 882141cc406Sopenharmony_ci 883141cc406Sopenharmony_ci/* The first calibration scan. Finds maximum of each CCD */ 884141cc406Sopenharmony_ci memset(&req, 0, sizeof(req)); 885141cc406Sopenharmony_ci 886141cc406Sopenharmony_ci req.x1 = 0x08; 887141cc406Sopenharmony_ci req.dpix = htons (300); /* = 300 dpi */ 888141cc406Sopenharmony_ci req.dpiy = htons (300); /* = 300 dpi */ 889141cc406Sopenharmony_ci req.offx = htons (0); /* = 0cm */ 890141cc406Sopenharmony_ci req.offy = htons (0); /* = 0cm */ 891141cc406Sopenharmony_ci req.lenx = htons (2690); /* = 22.78cm */ 892141cc406Sopenharmony_ci req.leny = htons (50); /* = 0.42cm */ 893141cc406Sopenharmony_ci 894141cc406Sopenharmony_ci req.flags1 = htons (0x0000); 895141cc406Sopenharmony_ci req.flags2 = htons (0x0010); 896141cc406Sopenharmony_ci req.flags3 = htons (0x3020); /* First calibration scan, 48bpp */ 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci req.gamma[0] = htons (100); 899141cc406Sopenharmony_ci req.gamma[1] = htons (100); 900141cc406Sopenharmony_ci req.gamma[2] = htons (100); 901141cc406Sopenharmony_ci 902141cc406Sopenharmony_ci if (DoAverageScan (iHandle, &req, 0x40, high_array) != 0) 903141cc406Sopenharmony_ci return -1; 904141cc406Sopenharmony_ci 905141cc406Sopenharmony_ci#ifdef CALIB_DEBUG 906141cc406Sopenharmony_ci for (i = 0; i < 3; i++) 907141cc406Sopenharmony_ci { 908141cc406Sopenharmony_ci int len; 909141cc406Sopenharmony_ci buffer[0] = 0; 910141cc406Sopenharmony_ci sprintf (buffer, "Average %d: \n", i); 911141cc406Sopenharmony_ci len = strlen (buffer); 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci for (j = 0; j < 24; j++) 914141cc406Sopenharmony_ci { 915141cc406Sopenharmony_ci sprintf (buffer + len, "%04X ", high_array[i][j]); 916141cc406Sopenharmony_ci len += 5; 917141cc406Sopenharmony_ci } 918141cc406Sopenharmony_ci strcat (buffer, " ... \n"); 919141cc406Sopenharmony_ci len += 6; 920141cc406Sopenharmony_ci 921141cc406Sopenharmony_ci for (j = 1000; j < 1024; j++) 922141cc406Sopenharmony_ci { 923141cc406Sopenharmony_ci sprintf (buffer + len, "%04X ", high_array[i][j]); 924141cc406Sopenharmony_ci len += 5; 925141cc406Sopenharmony_ci } 926141cc406Sopenharmony_ci strcat (buffer, " ... \n"); 927141cc406Sopenharmony_ci len += 6; 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci for (j = 2000; j < 2024; j++) 930141cc406Sopenharmony_ci { 931141cc406Sopenharmony_ci sprintf (buffer + len, "%04X ", high_array[i][j]); 932141cc406Sopenharmony_ci len += 5; 933141cc406Sopenharmony_ci } 934141cc406Sopenharmony_ci strcat (buffer, " ... \n"); 935141cc406Sopenharmony_ci len += 6; 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, buffer); 938141cc406Sopenharmony_ci } 939141cc406Sopenharmony_ci#endif 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci/* The second calibration scan. Finds minimum of each CCD */ 942141cc406Sopenharmony_ci memset(&req, 0, sizeof(req)); 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci req.x1 = 0x08; 945141cc406Sopenharmony_ci req.dpix = htons (300); /* = 300 dpi */ 946141cc406Sopenharmony_ci req.dpiy = htons (300); /* = 300 dpi */ 947141cc406Sopenharmony_ci req.offx = htons (0); /* = 0cm */ 948141cc406Sopenharmony_ci req.offy = htons (0); /* = 0cm */ 949141cc406Sopenharmony_ci req.lenx = htons (2690); /* = 22.78cm */ 950141cc406Sopenharmony_ci req.leny = htons (16); /* = 0.14cm */ 951141cc406Sopenharmony_ci 952141cc406Sopenharmony_ci req.flags1 = htons (0x0000); 953141cc406Sopenharmony_ci req.flags2 = htons (0x0010); 954141cc406Sopenharmony_ci req.flags3 = htons (0x3024); /* Second calibration scan, 48bpp */ 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ci req.gamma[0] = htons (100); 957141cc406Sopenharmony_ci req.gamma[1] = htons (100); 958141cc406Sopenharmony_ci req.gamma[2] = htons (100); 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci if (DoAverageScan (iHandle, &req, 0x00, low_array) != 0) 961141cc406Sopenharmony_ci return -1; 962141cc406Sopenharmony_ci 963141cc406Sopenharmony_ci#ifdef CALIB_DEBUG 964141cc406Sopenharmony_ci for (i = 0; i < 3; i++) 965141cc406Sopenharmony_ci { 966141cc406Sopenharmony_ci int len; 967141cc406Sopenharmony_ci buffer[0] = 0; 968141cc406Sopenharmony_ci sprintf (buffer, "Average %d: \n", i); 969141cc406Sopenharmony_ci len = strlen (buffer); 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci for (j = 0; j < 24; j++) 972141cc406Sopenharmony_ci { 973141cc406Sopenharmony_ci sprintf (buffer + len, "%04X ", low_array[i][j]); 974141cc406Sopenharmony_ci len += 5; 975141cc406Sopenharmony_ci } 976141cc406Sopenharmony_ci strcat (buffer, " ... \n"); 977141cc406Sopenharmony_ci len += 6; 978141cc406Sopenharmony_ci 979141cc406Sopenharmony_ci for (j = 1000; j < 1024; j++) 980141cc406Sopenharmony_ci { 981141cc406Sopenharmony_ci sprintf (buffer + len, "%04X ", low_array[i][j]); 982141cc406Sopenharmony_ci len += 5; 983141cc406Sopenharmony_ci } 984141cc406Sopenharmony_ci strcat (buffer, " ... \n"); 985141cc406Sopenharmony_ci len += 6; 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci for (j = 2000; j < 2024; j++) 988141cc406Sopenharmony_ci { 989141cc406Sopenharmony_ci sprintf (buffer + len, "%04X ", low_array[i][j]); 990141cc406Sopenharmony_ci len += 5; 991141cc406Sopenharmony_ci } 992141cc406Sopenharmony_ci strcat (buffer, " ... \n"); 993141cc406Sopenharmony_ci len += 6; 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, buffer); 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci#endif 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci SetCalibration (iHandle, 2690, low_array, high_array, dpi); 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci return 0; 1002141cc406Sopenharmony_ci} 1003141cc406Sopenharmony_ci 1004141cc406Sopenharmony_ci#ifdef STANDALONE 1005141cc406Sopenharmony_ciHP5400_SANE_STATIC 1006141cc406Sopenharmony_ciint 1007141cc406Sopenharmony_cihp5400_scan (int iHandle, TScanParams * params, THWParams * pHWParams, 1008141cc406Sopenharmony_ci const char *filename) 1009141cc406Sopenharmony_ci{ 1010141cc406Sopenharmony_ci struct ScanRequest req; 1011141cc406Sopenharmony_ci struct ScanResponse res; 1012141cc406Sopenharmony_ci int result; 1013141cc406Sopenharmony_ci 1014141cc406Sopenharmony_ci (void) pHWParams; /*to avoid compilation warning*/ 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "\n"); 1017141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Scanning :\n"); 1018141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " dpi(x) : %d\n", params->iDpi); 1019141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " dpi(y) : %d\n", params->iLpi); 1020141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " x0 : %d\n", params->iLeft); 1021141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " y0 : %d\n", params->iTop); 1022141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " width : %d\n", params->iWidth); 1023141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, " height : %d\n", params->iHeight); 1024141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "\n"); 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci memset(&req, 0, sizeof(req)); 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci req.x1 = 0x08; 1029141cc406Sopenharmony_ci req.dpix = htons (params->iDpi); 1030141cc406Sopenharmony_ci req.dpiy = htons (params->iLpi); 1031141cc406Sopenharmony_ci 1032141cc406Sopenharmony_ci /* These offsets and lengths should all be in the reference DPI which 1033141cc406Sopenharmony_ci * is set to HW_LPI */ 1034141cc406Sopenharmony_ci req.offx = htons (params->iLeft); 1035141cc406Sopenharmony_ci req.offy = htons (params->iTop); 1036141cc406Sopenharmony_ci req.lenx = htons (params->iWidth); 1037141cc406Sopenharmony_ci req.leny = htons (params->iHeight); 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci req.flags1 = htons (0x0080); 1040141cc406Sopenharmony_ci req.flags2 = htons (0x0000); 1041141cc406Sopenharmony_ci req.flags3 = htons ((params->iDpi < 2400) ? 0x18E8 : 0x18C0); /* Try preview scan */ 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci req.gamma[0] = htons (100); 1044141cc406Sopenharmony_ci req.gamma[1] = htons (100); 1045141cc406Sopenharmony_ci req.gamma[2] = htons (100); 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci if (Calibrate (iHandle, params->iDpi) != 0) 1048141cc406Sopenharmony_ci return -1; 1049141cc406Sopenharmony_ci SetDefaultGamma (iHandle); 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci result = DoScan (iHandle, &req, filename, 0x40, &res); 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci /* Pass the results back to the parent */ 1054141cc406Sopenharmony_ci params->iBytesPerLine = htonl (res.xsize); 1055141cc406Sopenharmony_ci params->iLines = htons (res.ysize); 1056141cc406Sopenharmony_ci 1057141cc406Sopenharmony_ci#if 0 1058141cc406Sopenharmony_ci imageFile = fopen ("output.dat", "r+b"); 1059141cc406Sopenharmony_ci if (imageFile) 1060141cc406Sopenharmony_ci { 1061141cc406Sopenharmony_ci int planes = 3; 1062141cc406Sopenharmony_ci int bpp = 1; 1063141cc406Sopenharmony_ci fseek (imageFile, 0, SEEK_SET); 1064141cc406Sopenharmony_ci DecodeImage (imageFile, planes, bpp, planes * bpp * params->iWidth, 1065141cc406Sopenharmony_ci params->iHeight, filename); 1066141cc406Sopenharmony_ci fclose (imageFile); 1067141cc406Sopenharmony_ci } 1068141cc406Sopenharmony_ci#endif 1069141cc406Sopenharmony_ci return result; 1070141cc406Sopenharmony_ci} 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ciHP5400_SANE_STATIC 1073141cc406Sopenharmony_ciint 1074141cc406Sopenharmony_ciPreviewScan (int iHandle) 1075141cc406Sopenharmony_ci{ 1076141cc406Sopenharmony_ci TScanParams params; 1077141cc406Sopenharmony_ci THWParams pHWParams; 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_ci /* Reference LPI is 300dpi, remember */ 1080141cc406Sopenharmony_ci params.iDpi = 75; 1081141cc406Sopenharmony_ci params.iLpi = 75; 1082141cc406Sopenharmony_ci params.iLeft = 0; 1083141cc406Sopenharmony_ci params.iTop = 0; 1084141cc406Sopenharmony_ci params.iWidth = 2552; /* = 21.61cm * 300dpi */ 1085141cc406Sopenharmony_ci params.iHeight = 3510; /* = 29.72cm * 300dpi */ 1086141cc406Sopenharmony_ci params.iColourOffset = 1; 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci return hp5400_scan (iHandle, ¶ms, &pHWParams, "output.ppm"); 1089141cc406Sopenharmony_ci} 1090141cc406Sopenharmony_ci 1091141cc406Sopenharmony_ci 1092141cc406Sopenharmony_cistatic char UISetup1[] = { 1093141cc406Sopenharmony_ci/* Offset 40 */ 1094141cc406Sopenharmony_ci 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x14, 0x00, 1095141cc406Sopenharmony_ci 0x52, 0x65, 0x61, 0x64, 1096141cc406Sopenharmony_ci 0x79, 0x00, 0x53, 0x63, 0x61, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x4C, 0x6F, 1097141cc406Sopenharmony_ci 0x63, 0x6B, 0x65, 0x64, 1098141cc406Sopenharmony_ci 0x00, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x43, 0x61, 0x6E, 0x63, 0x65, 1099141cc406Sopenharmony_ci 0x6C, 0x69, 0x6E, 0x67, 1100141cc406Sopenharmony_ci 0x14, 0x00, 0x50, 0x6F, 0x77, 0x65, 0x72, 0x53, 0x61, 0x76, 0x65, 0x20, 1101141cc406Sopenharmony_ci 0x4F, 0x6E, 0x00, 0x53, 1102141cc406Sopenharmony_ci}; 1103141cc406Sopenharmony_ci 1104141cc406Sopenharmony_cistatic char UISetup2[] = { 1105141cc406Sopenharmony_ci 1106141cc406Sopenharmony_ci 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x14, 0x00, 0x41, 0x44, 0x46, 1107141cc406Sopenharmony_ci 0x20, 0x70, 0x61, 0x70, 1108141cc406Sopenharmony_ci 0x65, 0x72, 0x20, 0x6A, 0x61, 0x6D, 0x00, 0x43, 0x6F, 0x70, 0x69, 0x65, 1109141cc406Sopenharmony_ci 0x73, 0x00, 0x00, 1110141cc406Sopenharmony_ci}; 1111141cc406Sopenharmony_ci 1112141cc406Sopenharmony_ciHP5400_SANE_STATIC 1113141cc406Sopenharmony_ciint 1114141cc406Sopenharmony_ciInitScanner (int iHandle) 1115141cc406Sopenharmony_ci{ 1116141cc406Sopenharmony_ci WarmupLamp (iHandle); 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_ci if (WriteByte (iHandle, 0xF200, 0x40) < 0) 1119141cc406Sopenharmony_ci return -1; 1120141cc406Sopenharmony_ci 1121141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, 0xF10B, sizeof (UISetup1), UISetup1) < 0) 1122141cc406Sopenharmony_ci { 1123141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to send UISetup1 (%lu)\n", (u_long) sizeof (UISetup1)); 1124141cc406Sopenharmony_ci return -1; 1125141cc406Sopenharmony_ci } 1126141cc406Sopenharmony_ci 1127141cc406Sopenharmony_ci if (WriteByte (iHandle, 0xF200, 0x00) < 0) 1128141cc406Sopenharmony_ci return -1; 1129141cc406Sopenharmony_ci 1130141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, 0xF10C, sizeof (UISetup2), UISetup2) < 0) 1131141cc406Sopenharmony_ci { 1132141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to send UISetup2\n"); 1133141cc406Sopenharmony_ci return -1; 1134141cc406Sopenharmony_ci } 1135141cc406Sopenharmony_ci return 0; 1136141cc406Sopenharmony_ci} 1137141cc406Sopenharmony_ci#endif 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci/* Warning! The caller must have configured the gamma tables at this stage */ 1140141cc406Sopenharmony_ciHP5400_SANE_STATIC 1141141cc406Sopenharmony_ciint 1142141cc406Sopenharmony_ciInitScan (enum ScanType scantype, TScanParams * pParams, 1143141cc406Sopenharmony_ci THWParams * pHWParams) 1144141cc406Sopenharmony_ci{ 1145141cc406Sopenharmony_ci struct ScanRequest req; 1146141cc406Sopenharmony_ci struct ScanResponse res; 1147141cc406Sopenharmony_ci int ret; 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci memset(&req, 0, sizeof(req)); 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ci req.x1 = 0x08; 1152141cc406Sopenharmony_ci req.dpix = htons (pParams->iDpi); /* = 300 dpi */ 1153141cc406Sopenharmony_ci req.dpiy = htons (pParams->iLpi); /* = 300 dpi */ 1154141cc406Sopenharmony_ci req.offx = htons (pParams->iLeft); /* = 0cm */ 1155141cc406Sopenharmony_ci req.offy = htons (pParams->iTop); /* = 0cm */ 1156141cc406Sopenharmony_ci req.lenx = htons (pParams->iWidth); /* = 22.78cm */ 1157141cc406Sopenharmony_ci 1158141cc406Sopenharmony_ci /* Scan a few extra rows so we can colour offset properly. At 300dpi the 1159141cc406Sopenharmony_ci * difference is 4 lines */ 1160141cc406Sopenharmony_ci 1161141cc406Sopenharmony_ci req.leny = htons (pParams->iHeight); /* = 0.42cm */ 1162141cc406Sopenharmony_ci 1163141cc406Sopenharmony_ci req.flags1 = htons ((scantype == SCAN_TYPE_CALIBRATION) ? 0x0000 : 0x0080); 1164141cc406Sopenharmony_ci req.flags2 = htons ((scantype == SCAN_TYPE_CALIBRATION) ? 0x0010 : 1165141cc406Sopenharmony_ci (scantype == SCAN_TYPE_PREVIEW) ? 0x0000 : 1166141cc406Sopenharmony_ci /* SCAN_TYPE_NORMAL */ 0x0040); 1167141cc406Sopenharmony_ci req.flags3 = htons (0x18E8); 1168141cc406Sopenharmony_ci 1169141cc406Sopenharmony_ci req.gamma[0] = htons (100); 1170141cc406Sopenharmony_ci req.gamma[1] = htons (100); 1171141cc406Sopenharmony_ci req.gamma[2] = htons (100); 1172141cc406Sopenharmony_ci 1173141cc406Sopenharmony_ci if (Calibrate (pHWParams->iXferHandle, pParams->iDpi) != 0) 1174141cc406Sopenharmony_ci return -1; 1175141cc406Sopenharmony_ci/* SetDefaultGamma( pHWParams->iXferHandle ); ** Must be done by caller */ 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Calibration complete\n"); 1178141cc406Sopenharmony_ci ret = 1179141cc406Sopenharmony_ci InitScan2 (scantype, &req, pHWParams, &res, pParams->iColourOffset, 0x40); 1180141cc406Sopenharmony_ci 1181141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "InitScan2 returned %d\n", ret); 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci /* Pass the results back to the parent */ 1184141cc406Sopenharmony_ci pParams->iBytesPerLine = htonl (res.xsize); 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci /* Hide the extra lines we're scanning */ 1187141cc406Sopenharmony_ci pParams->iLines = htons (res.ysize); 1188141cc406Sopenharmony_ci 1189141cc406Sopenharmony_ci return ret; /* 0 is good, -1 is bad */ 1190141cc406Sopenharmony_ci} 1191141cc406Sopenharmony_ci 1192141cc406Sopenharmony_ci/* For want of a better name ... */ 1193141cc406Sopenharmony_ciHP5400_SANE_STATIC 1194141cc406Sopenharmony_ciint 1195141cc406Sopenharmony_ciInitScan2 (enum ScanType scantype, struct ScanRequest *req, 1196141cc406Sopenharmony_ci THWParams * pHWParams, struct ScanResponse *result, 1197141cc406Sopenharmony_ci int iColourOffset, int code) 1198141cc406Sopenharmony_ci{ 1199141cc406Sopenharmony_ci struct ScanResponse res; 1200141cc406Sopenharmony_ci int iHandle = pHWParams->iXferHandle; 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci memset(&res, 0, sizeof(res)); 1203141cc406Sopenharmony_ci 1204141cc406Sopenharmony_ci /* Protect scanner from damage. This stops stpuid errors. It basically 1205141cc406Sopenharmony_ci * limits you to the scanner glass. Stuff like calibrations which need 1206141cc406Sopenharmony_ci * more access do it safely by fiddling other parameters. Note you can 1207141cc406Sopenharmony_ci * still break things by fiddling the ScanOffset, but that is not yet 1208141cc406Sopenharmony_ci * under user control */ 1209141cc406Sopenharmony_ci 1210141cc406Sopenharmony_ci if (scantype != SCAN_TYPE_CALIBRATION) 1211141cc406Sopenharmony_ci { 1212141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Off(%d,%d) : Len(%d,%d)\n", htons (req->offx), 1213141cc406Sopenharmony_ci htons (req->offy), htons (req->lenx), htons (req->leny)); 1214141cc406Sopenharmony_ci /* Yes, all the htons() is silly but we want this check as late as possible */ 1215141cc406Sopenharmony_ci if (htons (req->offx) > 0x09F8) 1216141cc406Sopenharmony_ci req->offx = htons (0x09F8); 1217141cc406Sopenharmony_ci if (htons (req->offy) > 0x0DB6) 1218141cc406Sopenharmony_ci req->offy = htons (0x0DB6); 1219141cc406Sopenharmony_ci /* These tests are meaningless as htons() returns unsigned 1220141cc406Sopenharmony_ci if( htons( req->offx ) < 0 ) req->offx = 0; 1221141cc406Sopenharmony_ci if( htons( req->offy ) < 0 ) req->offy = 0; 1222141cc406Sopenharmony_ci */ 1223141cc406Sopenharmony_ci if (htons (req->offx) + htons (req->lenx) > 0x09F8) 1224141cc406Sopenharmony_ci req->lenx = htons (0x09F8 - htons (req->offx)); 1225141cc406Sopenharmony_ci if (htons (req->offy) + htons (req->leny) > 0x0DB6) 1226141cc406Sopenharmony_ci req->leny = htons (0x0DB6 - htons (req->offy)); 1227141cc406Sopenharmony_ci if (htons (req->lenx) <= 1) 1228141cc406Sopenharmony_ci return -1; 1229141cc406Sopenharmony_ci if (htons (req->leny) <= 1) 1230141cc406Sopenharmony_ci return -1; 1231141cc406Sopenharmony_ci } 1232141cc406Sopenharmony_ci 1233141cc406Sopenharmony_ci WarmupLamp (iHandle); 1234141cc406Sopenharmony_ci 1235141cc406Sopenharmony_ci { /* Try to set it to make scan succeed, URB 53 *//* 0x1B01 => 0x40 */ 1236141cc406Sopenharmony_ci /* I think this tries to cancel any existing scan */ 1237141cc406Sopenharmony_ci char flag = 0x40; 1238141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, CMD_STOPSCAN, sizeof (flag), &flag) < 1239141cc406Sopenharmony_ci 0) 1240141cc406Sopenharmony_ci { 1241141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to cancel scan flag\n"); 1242141cc406Sopenharmony_ci return -1; 1243141cc406Sopenharmony_ci } 1244141cc406Sopenharmony_ci } 1245141cc406Sopenharmony_ci 1246141cc406Sopenharmony_ci { /* Try to set it to make scan succeed, URB 55 */ 1247141cc406Sopenharmony_ci char data[4] = { 0x02, 0x03, 0x03, 0x3C }; 1248141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, CMD_UNKNOWN3, sizeof (data), data) < 0) 1249141cc406Sopenharmony_ci { 1250141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to set unknown1\n"); 1251141cc406Sopenharmony_ci return -1; 1252141cc406Sopenharmony_ci } 1253141cc406Sopenharmony_ci } 1254141cc406Sopenharmony_ci 1255141cc406Sopenharmony_ci { /* Try to set it to make scan succeed, URB 59 */ 1256141cc406Sopenharmony_ci char flag = 0x04; 1257141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, CMD_UNKNOWN2, sizeof (flag), &flag) < 1258141cc406Sopenharmony_ci 0) 1259141cc406Sopenharmony_ci { 1260141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to set unknown2\n"); 1261141cc406Sopenharmony_ci return -1; 1262141cc406Sopenharmony_ci } 1263141cc406Sopenharmony_ci } 1264141cc406Sopenharmony_ci 1265141cc406Sopenharmony_ci { /* URB 67 *//* Reference DPI = 300 currently */ 1266141cc406Sopenharmony_ci short dpi = htons (HW_LPI); 1267141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, CMD_SETDPI, sizeof (dpi), &dpi) < 0) 1268141cc406Sopenharmony_ci { 1269141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to set dpi\n"); 1270141cc406Sopenharmony_ci return -1; 1271141cc406Sopenharmony_ci } 1272141cc406Sopenharmony_ci } 1273141cc406Sopenharmony_ci 1274141cc406Sopenharmony_ci if (scantype != SCAN_TYPE_CALIBRATION) 1275141cc406Sopenharmony_ci { /* Setup scan offsets - Should only apply to non-calibration scans */ 1276141cc406Sopenharmony_ci short offsets[2]; 1277141cc406Sopenharmony_ci 1278141cc406Sopenharmony_ci offsets [0] = htons (0x0054); 1279141cc406Sopenharmony_ci offsets [1] = htons (0x0282); 1280141cc406Sopenharmony_ci 1281141cc406Sopenharmony_ci if (hp5400_command_write 1282141cc406Sopenharmony_ci (iHandle, CMD_SETOFFSET, sizeof (offsets), offsets) < 0) 1283141cc406Sopenharmony_ci { 1284141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to set offsets\n"); 1285141cc406Sopenharmony_ci return -1; 1286141cc406Sopenharmony_ci } 1287141cc406Sopenharmony_ci } 1288141cc406Sopenharmony_ci 1289141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Scan request: \n "); 1290141cc406Sopenharmony_ci { 1291141cc406Sopenharmony_ci size_t i; 1292141cc406Sopenharmony_ci for (i = 0; i < sizeof (*req); i++) 1293141cc406Sopenharmony_ci { 1294141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) req)[i]); 1295141cc406Sopenharmony_ci } 1296141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "\n"); 1297141cc406Sopenharmony_ci } 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci if (hp5400_command_write 1300141cc406Sopenharmony_ci (iHandle, 1301141cc406Sopenharmony_ci (scantype != 1302141cc406Sopenharmony_ci SCAN_TYPE_CALIBRATION) ? CMD_SCANREQUEST2 : CMD_SCANREQUEST, 1303141cc406Sopenharmony_ci sizeof (*req), req) < 0) 1304141cc406Sopenharmony_ci { 1305141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to send scan request\n"); 1306141cc406Sopenharmony_ci return -1; 1307141cc406Sopenharmony_ci } 1308141cc406Sopenharmony_ci 1309141cc406Sopenharmony_ci { /* Try to set it to make scan succeed, URB 71 */ 1310141cc406Sopenharmony_ci char flag = code; /* Start scan with light on or off as requested */ 1311141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, CMD_STARTSCAN, sizeof (flag), &flag) < 1312141cc406Sopenharmony_ci 0) 1313141cc406Sopenharmony_ci { 1314141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to set gamma flag\n"); 1315141cc406Sopenharmony_ci return -1; 1316141cc406Sopenharmony_ci } 1317141cc406Sopenharmony_ci } 1318141cc406Sopenharmony_ci 1319141cc406Sopenharmony_ci if (hp5400_command_read (iHandle, CMD_SCANRESPONSE, sizeof (res), &res) < 0) 1320141cc406Sopenharmony_ci { 1321141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to read scan response\n"); 1322141cc406Sopenharmony_ci return -1; 1323141cc406Sopenharmony_ci } 1324141cc406Sopenharmony_ci 1325141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Scan response: \n "); 1326141cc406Sopenharmony_ci { 1327141cc406Sopenharmony_ci size_t i; 1328141cc406Sopenharmony_ci for (i = 0; i < sizeof (res); i++) 1329141cc406Sopenharmony_ci { 1330141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) &res)[i]); 1331141cc406Sopenharmony_ci } 1332141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "\n"); 1333141cc406Sopenharmony_ci } 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Bytes to transfer: %d\nBitmap resolution: %d x %d\n", 1336141cc406Sopenharmony_ci htonl (res.transfersize), htonl (res.xsize), htons (res.ysize)); 1337141cc406Sopenharmony_ci 1338141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Proceeding to scan\n"); 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if (htonl (res.transfersize) == 0) 1341141cc406Sopenharmony_ci { 1342141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Hmm, size is zero. Obviously a problem. Aborting...\n"); 1343141cc406Sopenharmony_ci return -1; 1344141cc406Sopenharmony_ci } 1345141cc406Sopenharmony_ci 1346141cc406Sopenharmony_ci { 1347141cc406Sopenharmony_ci char x1 = 0x14, x2 = 0x24; 1348141cc406Sopenharmony_ci 1349141cc406Sopenharmony_ci float pixels = ((float) htons (req->lenx) * (float) htons (req->leny)) * 1350141cc406Sopenharmony_ci ((float) htons (req->dpix) * (float) htons (req->dpiy)) / 1351141cc406Sopenharmony_ci ((float) HW_LPI * (float) HW_LPI); 1352141cc406Sopenharmony_ci int bpp = (int) ((float) htonl (res.transfersize) / pixels + 0.5); 1353141cc406Sopenharmony_ci int planes = (bpp == 1) ? 1 : 3; 1354141cc406Sopenharmony_ci bpp /= planes; 1355141cc406Sopenharmony_ci 1356141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "bpp = %d / ( (%d * %d) * (%d * %d) / (%d * %d) ) = %d\n", 1357141cc406Sopenharmony_ci htonl (res.transfersize), 1358141cc406Sopenharmony_ci htons (req->lenx), htons (req->leny), 1359141cc406Sopenharmony_ci htons (req->dpix), htons (req->dpiy), HW_LPI, HW_LPI, bpp); 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci hp5400_command_write_noverify (iHandle, CMD_INITBULK1, &x1, 1); 1362141cc406Sopenharmony_ci hp5400_command_write_noverify (iHandle, CMD_INITBULK2, &x2, 1); 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci if (bpp > 2) /* Bug!! */ 1365141cc406Sopenharmony_ci bpp = 2; 1366141cc406Sopenharmony_ci 1367141cc406Sopenharmony_ci CircBufferInit (pHWParams->iXferHandle, &pHWParams->pipe, 1368141cc406Sopenharmony_ci htonl (res.xsize), bpp, iColourOffset, 0xF000, 1369141cc406Sopenharmony_ci htonl (res.transfersize) + 3 * htons (res.ysize)); 1370141cc406Sopenharmony_ci } 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci if (result) /* copy ScanResult to parent if they asked for it */ 1373141cc406Sopenharmony_ci memcpy (result, &res, sizeof (*result)); 1374141cc406Sopenharmony_ci 1375141cc406Sopenharmony_ci return 0; 1376141cc406Sopenharmony_ci} 1377141cc406Sopenharmony_ci 1378141cc406Sopenharmony_ciHP5400_SANE_STATIC 1379141cc406Sopenharmony_civoid 1380141cc406Sopenharmony_ciFinishScan (THWParams * pHWParams) 1381141cc406Sopenharmony_ci{ 1382141cc406Sopenharmony_ci int iHandle = pHWParams->iXferHandle; 1383141cc406Sopenharmony_ci 1384141cc406Sopenharmony_ci CircBufferExit (&pHWParams->pipe); 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci { /* Finish scan request */ 1387141cc406Sopenharmony_ci char flag = 0x40; 1388141cc406Sopenharmony_ci if (hp5400_command_write (iHandle, CMD_STOPSCAN, sizeof (flag), &flag) < 1389141cc406Sopenharmony_ci 0) 1390141cc406Sopenharmony_ci { 1391141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to set gamma flag\n"); 1392141cc406Sopenharmony_ci return; 1393141cc406Sopenharmony_ci } 1394141cc406Sopenharmony_ci } 1395141cc406Sopenharmony_ci} 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_ciHP5400_SANE_STATIC 1398141cc406Sopenharmony_ciint 1399141cc406Sopenharmony_ciHP5400Open (THWParams * params, const char *filename) 1400141cc406Sopenharmony_ci{ 1401141cc406Sopenharmony_ci int iHandle = hp5400_open (filename); 1402141cc406Sopenharmony_ci char szVersion[32]; 1403141cc406Sopenharmony_ci int i; 1404141cc406Sopenharmony_ci#ifndef NO_STRING_VERSION_MATCH 1405141cc406Sopenharmony_ci int versionMatched; 1406141cc406Sopenharmony_ci#endif 1407141cc406Sopenharmony_ci 1408141cc406Sopenharmony_ci if (iHandle < 0) 1409141cc406Sopenharmony_ci { 1410141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "hp5400_open failed\n"); 1411141cc406Sopenharmony_ci return -1; 1412141cc406Sopenharmony_ci } 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci params->iXferHandle = 0; 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci /* read version info */ 1417141cc406Sopenharmony_ci if (hp5400_command_read 1418141cc406Sopenharmony_ci (iHandle, CMD_GETVERSION, sizeof (szVersion), szVersion) < 0) 1419141cc406Sopenharmony_ci { 1420141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to read version string\n"); 1421141cc406Sopenharmony_ci goto hp5400_close_exit; 1422141cc406Sopenharmony_ci } 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "version String :\n"); 1425141cc406Sopenharmony_ci for (i=0; i < 32; i++) { 1426141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "%c\n", szVersion[i]); 1427141cc406Sopenharmony_ci } 1428141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "\n"); 1429141cc406Sopenharmony_ci 1430141cc406Sopenharmony_ci#ifndef NO_STRING_VERSION_MATCH 1431141cc406Sopenharmony_ci i = 0; 1432141cc406Sopenharmony_ci versionMatched = 0; 1433141cc406Sopenharmony_ci while ( !versionMatched && (i < numVersions) ) { 1434141cc406Sopenharmony_ci if (!strncmp (szVersion + 1, MatchVersions[i] .strVersion, strlen(MatchVersions[i] .strVersion) - 4)) { 1435141cc406Sopenharmony_ci versionMatched = 1; 1436141cc406Sopenharmony_ci } 1437141cc406Sopenharmony_ci i++; 1438141cc406Sopenharmony_ci } 1439141cc406Sopenharmony_ci if ( !versionMatched ) { 1440141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, 1441141cc406Sopenharmony_ci "Sorry, unknown scanner version. Attempted match on :\n"); 1442141cc406Sopenharmony_ci i = 0; 1443141cc406Sopenharmony_ci while ( i < numVersions ) { 1444141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "* '%s'\n", MatchVersions[i] .strVersion); 1445141cc406Sopenharmony_ci i++; 1446141cc406Sopenharmony_ci } 1447141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Version is '%s'\n", szVersion); 1448141cc406Sopenharmony_ci goto hp5400_close_exit; 1449141cc406Sopenharmony_ci } 1450141cc406Sopenharmony_ci#else 1451141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Warning, Version match is disabled. Version is '%s'\n", 1452141cc406Sopenharmony_ci szVersion); 1453141cc406Sopenharmony_ci#endif /* NO_STRING_VERSION_MATCH */ 1454141cc406Sopenharmony_ci 1455141cc406Sopenharmony_ci params->iXferHandle = iHandle; 1456141cc406Sopenharmony_ci 1457141cc406Sopenharmony_ci /* Start the lamp warming up */ 1458141cc406Sopenharmony_ci /* No point checking the return value, we don't care anyway */ 1459141cc406Sopenharmony_ci WriteByte (iHandle, 0x0000, 0x01); 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci /* Success */ 1462141cc406Sopenharmony_ci return 0; 1463141cc406Sopenharmony_ci 1464141cc406Sopenharmony_cihp5400_close_exit: 1465141cc406Sopenharmony_ci hp5400_close (iHandle); 1466141cc406Sopenharmony_ci return -1; 1467141cc406Sopenharmony_ci} 1468141cc406Sopenharmony_ci 1469141cc406Sopenharmony_ciHP5400_SANE_STATIC 1470141cc406Sopenharmony_civoid 1471141cc406Sopenharmony_ciHP5400Close (THWParams * params) 1472141cc406Sopenharmony_ci{ 1473141cc406Sopenharmony_ci hp5400_close (params->iXferHandle); 1474141cc406Sopenharmony_ci} 1475141cc406Sopenharmony_ci 1476141cc406Sopenharmony_ciHP5400_SANE_STATIC 1477141cc406Sopenharmony_ciint 1478141cc406Sopenharmony_ciHP5400Detect (const char *filename, 1479141cc406Sopenharmony_ci int (*_ReportDevice) (TScannerModel * pModel, 1480141cc406Sopenharmony_ci const char *pszDeviceName)) 1481141cc406Sopenharmony_ci{ 1482141cc406Sopenharmony_ci int iHandle = hp5400_open (filename); 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci char szVersion[32]; 1485141cc406Sopenharmony_ci int ret = 0; 1486141cc406Sopenharmony_ci#ifndef NO_STRING_VERSION_MATCH 1487141cc406Sopenharmony_ci int versionMatched = 0; 1488141cc406Sopenharmony_ci int i = 0; 1489141cc406Sopenharmony_ci#endif 1490141cc406Sopenharmony_ci 1491141cc406Sopenharmony_ci if (iHandle < 0) 1492141cc406Sopenharmony_ci { 1493141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "hp5400_open failed\n"); 1494141cc406Sopenharmony_ci return -1; 1495141cc406Sopenharmony_ci } 1496141cc406Sopenharmony_ci 1497141cc406Sopenharmony_ci /* read version info */ 1498141cc406Sopenharmony_ci if (hp5400_command_read 1499141cc406Sopenharmony_ci (iHandle, CMD_GETVERSION, sizeof (szVersion), szVersion) < 0) 1500141cc406Sopenharmony_ci { 1501141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "failed to read version string\n"); 1502141cc406Sopenharmony_ci ret = -1; 1503141cc406Sopenharmony_ci goto hp5400_close_exit; 1504141cc406Sopenharmony_ci } 1505141cc406Sopenharmony_ci 1506141cc406Sopenharmony_ci#ifndef NO_STRING_VERSION_MATCH 1507141cc406Sopenharmony_ci i = 0; 1508141cc406Sopenharmony_ci versionMatched = 0; 1509141cc406Sopenharmony_ci while ( !versionMatched && (i < numVersions) ) { 1510141cc406Sopenharmony_ci if (!memcmp (szVersion + 1, MatchVersions[i] .strVersion, strlen (MatchVersions[i] .strVersion) - 4)) { 1511141cc406Sopenharmony_ci versionMatched = 1; 1512141cc406Sopenharmony_ci } 1513141cc406Sopenharmony_ci i++; 1514141cc406Sopenharmony_ci } 1515141cc406Sopenharmony_ci if ( !versionMatched ) { 1516141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, 1517141cc406Sopenharmony_ci "Sorry, unknown scanner version. Attempted match on :\n"); 1518141cc406Sopenharmony_ci i = 0; 1519141cc406Sopenharmony_ci while ( i < numVersions ) { 1520141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "* '%s'\n", MatchVersions[i] .strVersion); 1521141cc406Sopenharmony_ci i++; 1522141cc406Sopenharmony_ci } 1523141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Version is '%s'\n", szVersion); 1524141cc406Sopenharmony_ci goto hp5400_close_exit; 1525141cc406Sopenharmony_ci } 1526141cc406Sopenharmony_ci#else 1527141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, "Warning, Version match is disabled. Version is '%s'\n", 1528141cc406Sopenharmony_ci szVersion); 1529141cc406Sopenharmony_ci#endif /* NO_STRING_VERSION_MATCH */ 1530141cc406Sopenharmony_ci 1531141cc406Sopenharmony_ci if (_ReportDevice) 1532141cc406Sopenharmony_ci _ReportDevice (&Model_HP54xx, filename); 1533141cc406Sopenharmony_ci 1534141cc406Sopenharmony_cihp5400_close_exit: 1535141cc406Sopenharmony_ci hp5400_close (iHandle); 1536141cc406Sopenharmony_ci return ret; 1537141cc406Sopenharmony_ci} 1538141cc406Sopenharmony_ci 1539141cc406Sopenharmony_ci#ifdef STANDALONE 1540141cc406Sopenharmony_ciint 1541141cc406Sopenharmony_cimain (int argc, char *argv[]) 1542141cc406Sopenharmony_ci{ 1543141cc406Sopenharmony_ci THWParams scanner; 1544141cc406Sopenharmony_ci 1545141cc406Sopenharmony_ci assert (sizeof (struct ScanRequest) == 32); 1546141cc406Sopenharmony_ci assert (sizeof (struct ScanResponse) == 16); 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci hp5400_dbg_start(); 1549141cc406Sopenharmony_ci 1550141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, 1551141cc406Sopenharmony_ci "HP5400/5470C sample scan utility, by Martijn van Oosterhout <kleptog@svana.org>\n"); 1552141cc406Sopenharmony_ci HP5400_DBG (DBG_MSG, 1553141cc406Sopenharmony_ci "Based on the testutils by Bertrik Sikken (bertrik@zonnet.nl)\n"); 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci if ((argc == 6) && (!strcmp (argv[1], "-decode"))) 1556141cc406Sopenharmony_ci { 1557141cc406Sopenharmony_ci int width = atoi (argv[3]); 1558141cc406Sopenharmony_ci int height = atoi (argv[4]); 1559141cc406Sopenharmony_ci FILE *temp = fopen (argv[2], "r+b"); 1560141cc406Sopenharmony_ci if (temp) 1561141cc406Sopenharmony_ci { 1562141cc406Sopenharmony_ci int planes = 3; 1563141cc406Sopenharmony_ci int bpp = 1; 1564141cc406Sopenharmony_ci fseek (temp, 0, SEEK_SET); 1565141cc406Sopenharmony_ci DecodeImage (temp, planes, bpp, planes * bpp * width, height, 1566141cc406Sopenharmony_ci argv[5]); 1567141cc406Sopenharmony_ci fclose (temp); 1568141cc406Sopenharmony_ci } 1569141cc406Sopenharmony_ci return 1; 1570141cc406Sopenharmony_ci } 1571141cc406Sopenharmony_ci 1572141cc406Sopenharmony_ci if (HP5400Open (&scanner, NULL) < 0) 1573141cc406Sopenharmony_ci { 1574141cc406Sopenharmony_ci return 1; 1575141cc406Sopenharmony_ci } 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_ci PreviewScan (scanner.iXferHandle); 1578141cc406Sopenharmony_ci 1579141cc406Sopenharmony_ci HP5400Close (&scanner); 1580141cc406Sopenharmony_ci fprintf (stderr, "Note: output is in output.ppm\n"); 1581141cc406Sopenharmony_ci return 0; 1582141cc406Sopenharmony_ci} 1583141cc406Sopenharmony_ci 1584141cc406Sopenharmony_ci#endif 1585