1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci (C) Marian Matthias Eichholz 2001 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci This file is part of the SANE package. 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 7141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 8141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 9141cc406Sopenharmony_ci License, or (at your option) any later version. 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 12141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 13141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14141cc406Sopenharmony_ci General Public License for more details. 15141cc406Sopenharmony_ci 16141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 17141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 18141cc406Sopenharmony_ci 19141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 20141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 23141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 24141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 25141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 26141cc406Sopenharmony_ci account of linking the SANE library code into it. 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 29141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 30141cc406Sopenharmony_ci License. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 33141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 34141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 37141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 38141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci This file implements SANE backend for Microtek scanners with M011 USB 41141cc406Sopenharmony_ci chip like the Microtek ScanMaker 3600, 3700 and 3750. */ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci/* ====================================================================== 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_cism3600.c 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ciSANE backend master module 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci(C) Marian Matthias Eichholz 2001 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ciStart: 2.4.2001 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci====================================================================== */ 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci#include "../include/sane/config.h" 57141cc406Sopenharmony_ci#include <stdlib.h> 58141cc406Sopenharmony_ci#include <string.h> 59141cc406Sopenharmony_ci#include <errno.h> 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci#define BUILD 6 62141cc406Sopenharmony_ci 63141cc406Sopenharmony_ci#ifndef BACKEND_NAME 64141cc406Sopenharmony_ci#define BACKEND_NAME sm3600 65141cc406Sopenharmony_ci#endif 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci#include "../include/sane/sane.h" 68141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 69141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 70141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 71141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_ci#undef HAVE_LIBUSB_LEGACY 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci/* prevent inclusion of scantool.h */ 77141cc406Sopenharmony_ci#define SCANTOOL_H 78141cc406Sopenharmony_ci/* make no real function export, since we include the modules */ 79141cc406Sopenharmony_ci#define __SM3600EXPORT__ static 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci/* if defined, *before* sm3600.h inclusion */ 82141cc406Sopenharmony_ci#define SM3600_SUPPORT_EXPOSURE 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci#include "sm3600.h" 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_cistatic unsigned long ulDebugMask; 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_cistatic int num_devices; 89141cc406Sopenharmony_cistatic TDevice *pdevFirst; 90141cc406Sopenharmony_cistatic TInstance *pinstFirst; 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci/* ====================================================================== */ 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_ci#include "sm3600-scanutil.c" 95141cc406Sopenharmony_ci#include "sm3600-scanusb.c" 96141cc406Sopenharmony_ci#include "sm3600-scanmtek.c" 97141cc406Sopenharmony_ci#include "sm3600-homerun.c" 98141cc406Sopenharmony_ci#include "sm3600-gray.c" 99141cc406Sopenharmony_ci#include "sm3600-color.c" 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci/* ====================================================================== 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ciInitialise SANE options 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci====================================================================== */ 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_citypedef enum { optCount, 108141cc406Sopenharmony_ci optGroupMode, optMode, optResolution, 109141cc406Sopenharmony_ci#ifdef SM3600_SUPPORT_EXPOSURE 110141cc406Sopenharmony_ci optBrightness, optContrast, 111141cc406Sopenharmony_ci#endif 112141cc406Sopenharmony_ci optPreview, optGrayPreview, 113141cc406Sopenharmony_ci optGroupGeometry,optTLX, optTLY, optBRX, optBRY, 114141cc406Sopenharmony_ci optGroupEnhancement, 115141cc406Sopenharmony_ci optGammaY, optGammaR,optGammaG,optGammaB, 116141cc406Sopenharmony_ci optLast } TOptionIndex; 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_cistatic const SANE_String_Const aScanModes[]= { "color", "gray", "lineart", 119141cc406Sopenharmony_ci "halftone", NULL }; 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_cistatic const SANE_Range rangeXmm = { 122141cc406Sopenharmony_ci SANE_FIX(0), 123141cc406Sopenharmony_ci SANE_FIX(220), 124141cc406Sopenharmony_ci SANE_FIX(0.1) }; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_cistatic const SANE_Range rangeYmm = { 127141cc406Sopenharmony_ci SANE_FIX(0), 128141cc406Sopenharmony_ci SANE_FIX(300), 129141cc406Sopenharmony_ci SANE_FIX(0.1) }; 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci#ifdef SM3600_SUPPORT_EXPOSURE 132141cc406Sopenharmony_cistatic const SANE_Range rangeLumi = { 133141cc406Sopenharmony_ci SANE_FIX(-100.0), 134141cc406Sopenharmony_ci SANE_FIX(100.0), 135141cc406Sopenharmony_ci SANE_FIX(1.0) }; 136141cc406Sopenharmony_ci#endif 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_cistatic const SANE_Range rangeGamma = { 0, 4095, 1 }; 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_cistatic const SANE_Int setResolutions[] = { 5, 75,100,200,300,600 }; 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_cistatic 143141cc406Sopenharmony_ciSANE_Status 144141cc406Sopenharmony_ciInitOptions(TInstance *this) 145141cc406Sopenharmony_ci{ 146141cc406Sopenharmony_ci TOptionIndex iOpt; 147141cc406Sopenharmony_ci if (optLast!=NUM_OPTIONS) 148141cc406Sopenharmony_ci { 149141cc406Sopenharmony_ci DBG(1,"NUM_OPTIONS does not fit!"); 150141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 151141cc406Sopenharmony_ci } 152141cc406Sopenharmony_ci memset(this->aoptDesc,0,sizeof(this->aoptDesc)); 153141cc406Sopenharmony_ci memset(this->aoptVal,0,sizeof(this->aoptVal)); 154141cc406Sopenharmony_ci InitGammaTables(this,0,0); 155141cc406Sopenharmony_ci for (iOpt=optCount; iOpt!=optLast; iOpt++) 156141cc406Sopenharmony_ci { 157141cc406Sopenharmony_ci static char *achNamesXY[]= { 158141cc406Sopenharmony_ci SANE_NAME_SCAN_TL_X, SANE_NAME_SCAN_TL_Y, 159141cc406Sopenharmony_ci SANE_NAME_SCAN_BR_X, SANE_NAME_SCAN_BR_Y }; 160141cc406Sopenharmony_ci static char *achTitlesXY[]= { 161141cc406Sopenharmony_ci SANE_TITLE_SCAN_TL_X, SANE_TITLE_SCAN_TL_Y, 162141cc406Sopenharmony_ci SANE_TITLE_SCAN_BR_X, SANE_TITLE_SCAN_BR_Y }; 163141cc406Sopenharmony_ci static char *achDescXY[]= { 164141cc406Sopenharmony_ci SANE_DESC_SCAN_TL_X, SANE_DESC_SCAN_TL_Y, 165141cc406Sopenharmony_ci SANE_DESC_SCAN_BR_X, SANE_DESC_SCAN_BR_Y }; 166141cc406Sopenharmony_ci static double afFullBed[] = { 22.0,30.0, 50.0, 80.0 }; /* TODO: calculate exactly! */ 167141cc406Sopenharmony_ci static const SANE_Range *aRangesXY[] = { &rangeXmm,&rangeYmm,&rangeXmm,&rangeYmm }; 168141cc406Sopenharmony_ci SANE_Option_Descriptor *pdesc; 169141cc406Sopenharmony_ci Option_Value *pval; 170141cc406Sopenharmony_ci /* shorthands */ 171141cc406Sopenharmony_ci pdesc=this->aoptDesc+iOpt; 172141cc406Sopenharmony_ci pval=this->aoptVal+iOpt; 173141cc406Sopenharmony_ci /* default */ 174141cc406Sopenharmony_ci pdesc->size=sizeof(SANE_Word); 175141cc406Sopenharmony_ci pdesc->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci /* 178141cc406Sopenharmony_ci Some hints: 179141cc406Sopenharmony_ci *every* field needs a constraint, elseway there will be a warning. 180141cc406Sopenharmony_ci */ 181141cc406Sopenharmony_ci 182141cc406Sopenharmony_ci switch (iOpt) 183141cc406Sopenharmony_ci { 184141cc406Sopenharmony_ci case optCount: 185141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_NUM_OPTIONS; 186141cc406Sopenharmony_ci pdesc->desc =SANE_DESC_NUM_OPTIONS; 187141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_INT; 188141cc406Sopenharmony_ci pdesc->cap =SANE_CAP_SOFT_DETECT; 189141cc406Sopenharmony_ci pval->w =(SANE_Word)optLast; 190141cc406Sopenharmony_ci break; 191141cc406Sopenharmony_ci case optGroupMode: 192141cc406Sopenharmony_ci pdesc->title="Mode"; 193141cc406Sopenharmony_ci pdesc->desc =""; 194141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_GROUP; 195141cc406Sopenharmony_ci pdesc->cap = SANE_CAP_ADVANCED; 196141cc406Sopenharmony_ci break; 197141cc406Sopenharmony_ci case optMode: 198141cc406Sopenharmony_ci pdesc->name =SANE_NAME_SCAN_MODE; 199141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_SCAN_MODE; 200141cc406Sopenharmony_ci pdesc->desc ="Select the scan mode"; 201141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_STRING; 202141cc406Sopenharmony_ci pdesc->size =20; 203141cc406Sopenharmony_ci pdesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; 204141cc406Sopenharmony_ci pdesc->constraint.string_list = aScanModes; 205141cc406Sopenharmony_ci pval->s = strdup(aScanModes[color]); 206141cc406Sopenharmony_ci break; 207141cc406Sopenharmony_ci case optResolution: 208141cc406Sopenharmony_ci pdesc->name =SANE_NAME_SCAN_RESOLUTION; 209141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_SCAN_RESOLUTION; 210141cc406Sopenharmony_ci pdesc->desc =SANE_DESC_SCAN_RESOLUTION; 211141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_INT; 212141cc406Sopenharmony_ci pdesc->unit =SANE_UNIT_DPI; 213141cc406Sopenharmony_ci pdesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; 214141cc406Sopenharmony_ci pdesc->constraint.word_list = setResolutions; 215141cc406Sopenharmony_ci pval->w =75; 216141cc406Sopenharmony_ci break; 217141cc406Sopenharmony_ci#ifdef SM3600_SUPPORT_EXPOSURE 218141cc406Sopenharmony_ci case optBrightness: 219141cc406Sopenharmony_ci pdesc->name =SANE_NAME_BRIGHTNESS; 220141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_BRIGHTNESS; 221141cc406Sopenharmony_ci pdesc->desc =SANE_DESC_BRIGHTNESS; 222141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_FIXED; 223141cc406Sopenharmony_ci pdesc->unit =SANE_UNIT_PERCENT; 224141cc406Sopenharmony_ci pdesc->constraint_type =SANE_CONSTRAINT_RANGE; 225141cc406Sopenharmony_ci pdesc->constraint.range=&rangeLumi; 226141cc406Sopenharmony_ci pval->w =SANE_FIX(0); 227141cc406Sopenharmony_ci break; 228141cc406Sopenharmony_ci case optContrast: 229141cc406Sopenharmony_ci pdesc->name =SANE_NAME_CONTRAST; 230141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_CONTRAST; 231141cc406Sopenharmony_ci pdesc->desc =SANE_DESC_CONTRAST; 232141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_FIXED; 233141cc406Sopenharmony_ci pdesc->unit =SANE_UNIT_PERCENT; 234141cc406Sopenharmony_ci pdesc->constraint_type =SANE_CONSTRAINT_RANGE; 235141cc406Sopenharmony_ci pdesc->constraint.range=&rangeLumi; 236141cc406Sopenharmony_ci pval->w =SANE_FIX(0); 237141cc406Sopenharmony_ci break; 238141cc406Sopenharmony_ci#endif 239141cc406Sopenharmony_ci case optPreview: 240141cc406Sopenharmony_ci pdesc->name =SANE_NAME_PREVIEW; 241141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_PREVIEW; 242141cc406Sopenharmony_ci pdesc->desc =SANE_DESC_PREVIEW; 243141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_BOOL; 244141cc406Sopenharmony_ci pval->w =SANE_FALSE; 245141cc406Sopenharmony_ci break; 246141cc406Sopenharmony_ci case optGrayPreview: 247141cc406Sopenharmony_ci pdesc->name =SANE_NAME_GRAY_PREVIEW; 248141cc406Sopenharmony_ci pdesc->title =SANE_TITLE_GRAY_PREVIEW; 249141cc406Sopenharmony_ci pdesc->desc =SANE_DESC_GRAY_PREVIEW; 250141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_BOOL; 251141cc406Sopenharmony_ci pval->w =SANE_FALSE; 252141cc406Sopenharmony_ci break; 253141cc406Sopenharmony_ci case optGroupGeometry: 254141cc406Sopenharmony_ci pdesc->title="Geometry"; 255141cc406Sopenharmony_ci pdesc->desc =""; 256141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_GROUP; 257141cc406Sopenharmony_ci pdesc->constraint_type=SANE_CONSTRAINT_NONE; 258141cc406Sopenharmony_ci pdesc->cap = SANE_CAP_ADVANCED; 259141cc406Sopenharmony_ci break; 260141cc406Sopenharmony_ci case optTLX: case optTLY: case optBRX: case optBRY: 261141cc406Sopenharmony_ci pdesc->name =achNamesXY[iOpt-optTLX]; 262141cc406Sopenharmony_ci pdesc->title =achTitlesXY[iOpt-optTLX]; 263141cc406Sopenharmony_ci pdesc->desc =achDescXY[iOpt-optTLX]; 264141cc406Sopenharmony_ci pdesc->type =SANE_TYPE_FIXED; 265141cc406Sopenharmony_ci pdesc->unit =SANE_UNIT_MM; /* arghh */ 266141cc406Sopenharmony_ci pdesc->constraint_type =SANE_CONSTRAINT_RANGE; 267141cc406Sopenharmony_ci pdesc->constraint.range=aRangesXY[iOpt-optTLX]; 268141cc406Sopenharmony_ci pval->w =SANE_FIX(afFullBed[iOpt-optTLX]); 269141cc406Sopenharmony_ci break; 270141cc406Sopenharmony_ci case optGroupEnhancement: 271141cc406Sopenharmony_ci pdesc->title="Enhancement"; 272141cc406Sopenharmony_ci pdesc->desc =""; 273141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_GROUP; 274141cc406Sopenharmony_ci pdesc->constraint_type=SANE_CONSTRAINT_NONE; 275141cc406Sopenharmony_ci pdesc->cap = SANE_CAP_ADVANCED; 276141cc406Sopenharmony_ci break; 277141cc406Sopenharmony_ci case optGammaY: 278141cc406Sopenharmony_ci pdesc->name = SANE_NAME_GAMMA_VECTOR; 279141cc406Sopenharmony_ci pdesc->title = SANE_TITLE_GAMMA_VECTOR; 280141cc406Sopenharmony_ci pdesc->desc = SANE_DESC_GAMMA_VECTOR; 281141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_INT; 282141cc406Sopenharmony_ci pdesc->unit = SANE_UNIT_NONE; 283141cc406Sopenharmony_ci pdesc->size = 4096*sizeof(SANE_Int); 284141cc406Sopenharmony_ci pdesc->constraint_type = SANE_CONSTRAINT_RANGE; 285141cc406Sopenharmony_ci pdesc->constraint.range = &rangeGamma; 286141cc406Sopenharmony_ci pval->wa = this->agammaY; 287141cc406Sopenharmony_ci break; 288141cc406Sopenharmony_ci case optGammaR: 289141cc406Sopenharmony_ci pdesc->name = SANE_NAME_GAMMA_VECTOR_R; 290141cc406Sopenharmony_ci pdesc->title = SANE_TITLE_GAMMA_VECTOR_R; 291141cc406Sopenharmony_ci pdesc->desc = SANE_DESC_GAMMA_VECTOR_R; 292141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_INT; 293141cc406Sopenharmony_ci pdesc->unit = SANE_UNIT_NONE; 294141cc406Sopenharmony_ci pdesc->size = 4096*sizeof(SANE_Int); 295141cc406Sopenharmony_ci pdesc->constraint_type = SANE_CONSTRAINT_RANGE; 296141cc406Sopenharmony_ci pdesc->constraint.range = &rangeGamma; 297141cc406Sopenharmony_ci pval->wa = this->agammaR; 298141cc406Sopenharmony_ci break; 299141cc406Sopenharmony_ci case optGammaG: 300141cc406Sopenharmony_ci pdesc->name = SANE_NAME_GAMMA_VECTOR_G; 301141cc406Sopenharmony_ci pdesc->title = SANE_TITLE_GAMMA_VECTOR_G; 302141cc406Sopenharmony_ci pdesc->desc = SANE_DESC_GAMMA_VECTOR_G; 303141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_INT; 304141cc406Sopenharmony_ci pdesc->unit = SANE_UNIT_NONE; 305141cc406Sopenharmony_ci pdesc->size = 4096*sizeof(SANE_Int); 306141cc406Sopenharmony_ci pdesc->constraint_type = SANE_CONSTRAINT_RANGE; 307141cc406Sopenharmony_ci pdesc->constraint.range = &rangeGamma; 308141cc406Sopenharmony_ci pval->wa = this->agammaG; 309141cc406Sopenharmony_ci break; 310141cc406Sopenharmony_ci case optGammaB: 311141cc406Sopenharmony_ci pdesc->name = SANE_NAME_GAMMA_VECTOR_B; 312141cc406Sopenharmony_ci pdesc->title = SANE_TITLE_GAMMA_VECTOR_B; 313141cc406Sopenharmony_ci pdesc->desc = SANE_DESC_GAMMA_VECTOR_B; 314141cc406Sopenharmony_ci pdesc->type = SANE_TYPE_INT; 315141cc406Sopenharmony_ci pdesc->unit = SANE_UNIT_NONE; 316141cc406Sopenharmony_ci pdesc->size = 4096*sizeof(SANE_Int); 317141cc406Sopenharmony_ci pdesc->constraint_type = SANE_CONSTRAINT_RANGE; 318141cc406Sopenharmony_ci pdesc->constraint.range = &rangeGamma; 319141cc406Sopenharmony_ci pval->wa = this->agammaB; 320141cc406Sopenharmony_ci break; 321141cc406Sopenharmony_ci case optLast: /* not reached */ 322141cc406Sopenharmony_ci break; 323141cc406Sopenharmony_ci } 324141cc406Sopenharmony_ci } 325141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 326141cc406Sopenharmony_ci} 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_cistatic SANE_Status 329141cc406Sopenharmony_ciRegisterSaneDev (TModel model, SANE_String_Const szName) 330141cc406Sopenharmony_ci{ 331141cc406Sopenharmony_ci TDevice * q; 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci errno = 0; 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ci q = malloc (sizeof (*q)); 336141cc406Sopenharmony_ci if (!q) 337141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci memset (q, 0, sizeof (*q)); /* clear every field */ 340141cc406Sopenharmony_ci q->szSaneName = strdup (szName); 341141cc406Sopenharmony_ci q->sane.name = (SANE_String_Const) q->szSaneName; 342141cc406Sopenharmony_ci q->sane.vendor = "Microtek"; 343141cc406Sopenharmony_ci q->sane.model = "ScanMaker 3600"; 344141cc406Sopenharmony_ci q->sane.type = "flatbed scanner"; 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci q->model=model; 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci ++num_devices; 349141cc406Sopenharmony_ci q->pNext = pdevFirst; /* link backwards */ 350141cc406Sopenharmony_ci pdevFirst = q; 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 353141cc406Sopenharmony_ci} 354141cc406Sopenharmony_ci 355141cc406Sopenharmony_cistatic SANE_Status 356141cc406Sopenharmony_cism_usb_attach (SANE_String_Const dev_name) 357141cc406Sopenharmony_ci{ 358141cc406Sopenharmony_ci int fd; 359141cc406Sopenharmony_ci SANE_Status err; 360141cc406Sopenharmony_ci SANE_Word v, p; 361141cc406Sopenharmony_ci TModel model; 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci err = sanei_usb_open(dev_name, &fd); 364141cc406Sopenharmony_ci if (err) 365141cc406Sopenharmony_ci return err; 366141cc406Sopenharmony_ci err = sanei_usb_get_vendor_product (fd, &v, &p); 367141cc406Sopenharmony_ci if (err) 368141cc406Sopenharmony_ci { 369141cc406Sopenharmony_ci sanei_usb_close (fd); 370141cc406Sopenharmony_ci return err; 371141cc406Sopenharmony_ci } 372141cc406Sopenharmony_ci DBG (DEBUG_JUNK, "found dev %04X/%04X, %s\n", v, p, dev_name); 373141cc406Sopenharmony_ci model = GetScannerModel (v, p); 374141cc406Sopenharmony_ci if (model != unknown) 375141cc406Sopenharmony_ci RegisterSaneDev (model, dev_name); 376141cc406Sopenharmony_ci 377141cc406Sopenharmony_ci sanei_usb_close(fd); 378141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 379141cc406Sopenharmony_ci} 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ciSANE_Status 382141cc406Sopenharmony_cisane_init (SANE_Int *version_code, SANE_Auth_Callback authCB) 383141cc406Sopenharmony_ci{ 384141cc406Sopenharmony_ci int i; 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci DBG_INIT(); 387141cc406Sopenharmony_ci 388141cc406Sopenharmony_ci (void) authCB; /* compiler */ 389141cc406Sopenharmony_ci 390141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"SM3600 init\n"); 391141cc406Sopenharmony_ci if (version_code) 392141cc406Sopenharmony_ci { 393141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 394141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"SM3600 version: %x\n", 395141cc406Sopenharmony_ci SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD)); 396141cc406Sopenharmony_ci } 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci pdevFirst=NULL; 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci sanei_usb_init(); 401141cc406Sopenharmony_ci for (i = 0; aScanners[i].idProduct; i++) 402141cc406Sopenharmony_ci { 403141cc406Sopenharmony_ci sanei_usb_find_devices(SCANNER_VENDOR, aScanners[i].idProduct, sm_usb_attach); 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 406141cc406Sopenharmony_ci} 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_cistatic const SANE_Device ** devlist = 0; /* only pseudo-statical */ 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_civoid 411141cc406Sopenharmony_cisane_exit (void) 412141cc406Sopenharmony_ci{ 413141cc406Sopenharmony_ci TDevice *dev, *pNext; 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci /* free all bound resources and instances */ 416141cc406Sopenharmony_ci while (pinstFirst) 417141cc406Sopenharmony_ci sane_close((SANE_Handle)pinstFirst); /* free all resources */ 418141cc406Sopenharmony_ci 419141cc406Sopenharmony_ci /* free all device descriptors */ 420141cc406Sopenharmony_ci for (dev = pdevFirst; dev; dev = pNext) 421141cc406Sopenharmony_ci { 422141cc406Sopenharmony_ci pNext = dev->pNext; 423141cc406Sopenharmony_ci free (dev->szSaneName); 424141cc406Sopenharmony_ci free (dev); 425141cc406Sopenharmony_ci } 426141cc406Sopenharmony_ci if (devlist) free(devlist); 427141cc406Sopenharmony_ci devlist=NULL; 428141cc406Sopenharmony_ci} 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ciSANE_Status 431141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, 432141cc406Sopenharmony_ci SANE_Bool __sane_unused__ local_only) 433141cc406Sopenharmony_ci{ 434141cc406Sopenharmony_ci TDevice *dev; 435141cc406Sopenharmony_ci int i; 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci if (devlist) free (devlist); 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 440141cc406Sopenharmony_ci if (!devlist) 441141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_ci i = 0; 444141cc406Sopenharmony_ci for (dev = pdevFirst; i < num_devices; dev = dev->pNext) 445141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 446141cc406Sopenharmony_ci devlist[i++] = 0; 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci *device_list = devlist; 449141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 450141cc406Sopenharmony_ci} 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ciSANE_Status 453141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle *handle) 454141cc406Sopenharmony_ci{ 455141cc406Sopenharmony_ci TDevice *pdev; 456141cc406Sopenharmony_ci TInstance *this; 457141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"opening %s\n",devicename); 458141cc406Sopenharmony_ci if (devicename[0]) /* selected */ 459141cc406Sopenharmony_ci { 460141cc406Sopenharmony_ci for (pdev=pdevFirst; pdev; pdev=pdev->pNext) 461141cc406Sopenharmony_ci{ 462141cc406Sopenharmony_ciDBG(DEBUG_VERBOSE,"%s<>%s\n",devicename, pdev->sane.name); 463141cc406Sopenharmony_ci if (!strcmp(devicename,pdev->sane.name)) 464141cc406Sopenharmony_ci break; 465141cc406Sopenharmony_ci} 466141cc406Sopenharmony_ci /* no dynamic post-registration */ 467141cc406Sopenharmony_ci } 468141cc406Sopenharmony_ci else 469141cc406Sopenharmony_ci pdev=pdevFirst; 470141cc406Sopenharmony_ci if (!pdev) 471141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 472141cc406Sopenharmony_ci this = (TInstance*) calloc(1,sizeof(TInstance)); 473141cc406Sopenharmony_ci if (!this) return SANE_STATUS_NO_MEM; 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci *handle = (SANE_Handle)this; 476141cc406Sopenharmony_ci 477141cc406Sopenharmony_ci ResetCalibration(this); /* do not release memory */ 478141cc406Sopenharmony_ci this->pNext=pinstFirst; /* register open handle */ 479141cc406Sopenharmony_ci pinstFirst=this; 480141cc406Sopenharmony_ci this->model=pdev->model; /* memorize model */ 481141cc406Sopenharmony_ci /* open and prepare USB scanner handle */ 482141cc406Sopenharmony_ci 483141cc406Sopenharmony_ci if (sanei_usb_open (devicename, &this->hScanner) != SANE_STATUS_GOOD) 484141cc406Sopenharmony_ci return SetError (this, SANE_STATUS_IO_ERROR, "cannot open scanner device"); 485141cc406Sopenharmony_ci 486141cc406Sopenharmony_ci this->quality=fast; 487141cc406Sopenharmony_ci return InitOptions(this); 488141cc406Sopenharmony_ci} 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_civoid 491141cc406Sopenharmony_cisane_close (SANE_Handle handle) 492141cc406Sopenharmony_ci{ 493141cc406Sopenharmony_ci TInstance *this,*pParent,*p; 494141cc406Sopenharmony_ci this=(TInstance*)handle; 495141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"closing scanner\n"); 496141cc406Sopenharmony_ci if (this->hScanner) 497141cc406Sopenharmony_ci { 498141cc406Sopenharmony_ci if (this->state.bScanning) 499141cc406Sopenharmony_ci EndScan(this); 500141cc406Sopenharmony_ci 501141cc406Sopenharmony_ci sanei_usb_close(this->hScanner); 502141cc406Sopenharmony_ci this->hScanner=-1; 503141cc406Sopenharmony_ci } 504141cc406Sopenharmony_ci ResetCalibration(this); /* release calibration data */ 505141cc406Sopenharmony_ci /* unlink active device entry */ 506141cc406Sopenharmony_ci pParent=NULL; 507141cc406Sopenharmony_ci for (p=pinstFirst; p; p=p->pNext) 508141cc406Sopenharmony_ci { 509141cc406Sopenharmony_ci if (p==this) break; 510141cc406Sopenharmony_ci pParent=p; 511141cc406Sopenharmony_ci } 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci if (!p) 514141cc406Sopenharmony_ci { 515141cc406Sopenharmony_ci DBG(1,"invalid handle in close()\n"); 516141cc406Sopenharmony_ci return; 517141cc406Sopenharmony_ci } 518141cc406Sopenharmony_ci /* delete instance from instance list */ 519141cc406Sopenharmony_ci if (pParent) 520141cc406Sopenharmony_ci pParent->pNext=this->pNext; 521141cc406Sopenharmony_ci else 522141cc406Sopenharmony_ci pinstFirst=this->pNext; /* NULL with last entry */ 523141cc406Sopenharmony_ci /* free resources */ 524141cc406Sopenharmony_ci if (this->pchPageBuffer) 525141cc406Sopenharmony_ci free(this->pchPageBuffer); 526141cc406Sopenharmony_ci if (this->szErrorReason) 527141cc406Sopenharmony_ci { 528141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"Error status: %d, %s", 529141cc406Sopenharmony_ci this->nErrorState, this->szErrorReason); 530141cc406Sopenharmony_ci free(this->szErrorReason); 531141cc406Sopenharmony_ci } 532141cc406Sopenharmony_ci free(this); 533141cc406Sopenharmony_ci} 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 536141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int iOpt) 537141cc406Sopenharmony_ci{ 538141cc406Sopenharmony_ci TInstance *this=(TInstance*)handle; 539141cc406Sopenharmony_ci if (iOpt<NUM_OPTIONS) 540141cc406Sopenharmony_ci return this->aoptDesc+iOpt; 541141cc406Sopenharmony_ci return NULL; 542141cc406Sopenharmony_ci} 543141cc406Sopenharmony_ci 544141cc406Sopenharmony_ciSANE_Status 545141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int iOpt, 546141cc406Sopenharmony_ci SANE_Action action, void *pVal, 547141cc406Sopenharmony_ci SANE_Int *pnInfo) 548141cc406Sopenharmony_ci{ 549141cc406Sopenharmony_ci SANE_Word cap; 550141cc406Sopenharmony_ci SANE_Status rc; 551141cc406Sopenharmony_ci TInstance *this; 552141cc406Sopenharmony_ci this=(TInstance*)handle; 553141cc406Sopenharmony_ci rc=SANE_STATUS_GOOD; 554141cc406Sopenharmony_ci if (pnInfo) 555141cc406Sopenharmony_ci *pnInfo=0; 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci if (this->state.bScanning) 558141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 559141cc406Sopenharmony_ci if (iOpt>=NUM_OPTIONS) 560141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci cap=this->aoptDesc[iOpt].cap; 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci switch (action) 565141cc406Sopenharmony_ci { 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci /* ------------------------------------------------------------ */ 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 570141cc406Sopenharmony_ci switch ((TOptionIndex)iOpt) 571141cc406Sopenharmony_ci { 572141cc406Sopenharmony_ci case optCount: 573141cc406Sopenharmony_ci case optPreview: 574141cc406Sopenharmony_ci case optGrayPreview: 575141cc406Sopenharmony_ci case optResolution: 576141cc406Sopenharmony_ci#ifdef SM3600_SUPPORT_EXPOSURE 577141cc406Sopenharmony_ci case optBrightness: 578141cc406Sopenharmony_ci case optContrast: 579141cc406Sopenharmony_ci#endif 580141cc406Sopenharmony_ci case optTLX: case optTLY: case optBRX: case optBRY: 581141cc406Sopenharmony_ci *(SANE_Word*)pVal = this->aoptVal[iOpt].w; 582141cc406Sopenharmony_ci break; 583141cc406Sopenharmony_ci case optMode: 584141cc406Sopenharmony_ci strcpy(pVal,this->aoptVal[iOpt].s); 585141cc406Sopenharmony_ci break; 586141cc406Sopenharmony_ci case optGammaY: 587141cc406Sopenharmony_ci case optGammaR: 588141cc406Sopenharmony_ci case optGammaG: 589141cc406Sopenharmony_ci case optGammaB: 590141cc406Sopenharmony_ci DBG(DEBUG_INFO,"getting gamma\n"); 591141cc406Sopenharmony_ci memcpy(pVal,this->aoptVal[iOpt].wa, this->aoptDesc[iOpt].size); 592141cc406Sopenharmony_ci break; 593141cc406Sopenharmony_ci default: 594141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 595141cc406Sopenharmony_ci } 596141cc406Sopenharmony_ci break; 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_ci /* ------------------------------------------------------------ */ 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 601141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE(cap)) 602141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 603141cc406Sopenharmony_ci rc=sanei_constrain_value(this->aoptDesc+iOpt,pVal,pnInfo); 604141cc406Sopenharmony_ci if (rc!=SANE_STATUS_GOOD) 605141cc406Sopenharmony_ci return rc; 606141cc406Sopenharmony_ci switch ((TOptionIndex)iOpt) 607141cc406Sopenharmony_ci { 608141cc406Sopenharmony_ci case optResolution: 609141cc406Sopenharmony_ci case optTLX: case optTLY: case optBRX: case optBRY: 610141cc406Sopenharmony_ci if (pnInfo) (*pnInfo) |= SANE_INFO_RELOAD_PARAMS; 611141cc406Sopenharmony_ci // fall through 612141cc406Sopenharmony_ci case optPreview: 613141cc406Sopenharmony_ci case optGrayPreview: 614141cc406Sopenharmony_ci#ifdef SM3600_SUPPORT_EXPOSURE 615141cc406Sopenharmony_ci case optBrightness: 616141cc406Sopenharmony_ci case optContrast: 617141cc406Sopenharmony_ci#endif 618141cc406Sopenharmony_ci this->aoptVal[iOpt].w = *(SANE_Word*)pVal; 619141cc406Sopenharmony_ci break; 620141cc406Sopenharmony_ci case optMode: 621141cc406Sopenharmony_ci if (pnInfo) 622141cc406Sopenharmony_ci (*pnInfo) |= SANE_INFO_RELOAD_PARAMS 623141cc406Sopenharmony_ci | SANE_INFO_RELOAD_OPTIONS; 624141cc406Sopenharmony_ci strcpy(this->aoptVal[iOpt].s,pVal); 625141cc406Sopenharmony_ci break; 626141cc406Sopenharmony_ci case optGammaY: 627141cc406Sopenharmony_ci case optGammaR: case optGammaG: case optGammaB: 628141cc406Sopenharmony_ci DBG(DEBUG_INFO,"setting gamma #%d\n",iOpt); 629141cc406Sopenharmony_ci memcpy(this->aoptVal[iOpt].wa, pVal, this->aoptDesc[iOpt].size); 630141cc406Sopenharmony_ci break; 631141cc406Sopenharmony_ci default: 632141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 633141cc406Sopenharmony_ci } 634141cc406Sopenharmony_ci break; 635141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 636141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 637141cc406Sopenharmony_ci } /* switch action */ 638141cc406Sopenharmony_ci return rc; /* normally GOOD */ 639141cc406Sopenharmony_ci} 640141cc406Sopenharmony_ci 641141cc406Sopenharmony_cistatic SANE_Status 642141cc406Sopenharmony_ciSetupInternalParameters(TInstance *this) 643141cc406Sopenharmony_ci{ 644141cc406Sopenharmony_ci int i; 645141cc406Sopenharmony_ci this->param.res=(int)this->aoptVal[optResolution].w; 646141cc406Sopenharmony_ci#ifdef SM3600_SUPPORT_EXPOSURE 647141cc406Sopenharmony_ci this->param.nBrightness=(int)(this->aoptVal[optBrightness].w>>SANE_FIXED_SCALE_SHIFT); 648141cc406Sopenharmony_ci this->param.nContrast=(int)(this->aoptVal[optContrast].w>>SANE_FIXED_SCALE_SHIFT); 649141cc406Sopenharmony_ci#else 650141cc406Sopenharmony_ci this->param.nBrightness=0; 651141cc406Sopenharmony_ci this->param.nContrast=0; 652141cc406Sopenharmony_ci#endif 653141cc406Sopenharmony_ci this->param.x=(int)(SANE_UNFIX(this->aoptVal[optTLX].w)*1200.0/25.4); 654141cc406Sopenharmony_ci this->param.y=(int)(SANE_UNFIX(this->aoptVal[optTLY].w)*1200.0/25.4); 655141cc406Sopenharmony_ci this->param.cx=(int)(SANE_UNFIX(this->aoptVal[optBRX].w-this->aoptVal[optTLX].w)*1200.0/25.4)+1; 656141cc406Sopenharmony_ci this->param.cy=(int)(SANE_UNFIX(this->aoptVal[optBRY].w-this->aoptVal[optTLY].w)*1200.0/25.4)+1; 657141cc406Sopenharmony_ci for (i=0; aScanModes[i]; i++) 658141cc406Sopenharmony_ci if (!strcasecmp(this->aoptVal[optMode].s,aScanModes[i])) 659141cc406Sopenharmony_ci { 660141cc406Sopenharmony_ci this->mode=(TMode)i; 661141cc406Sopenharmony_ci break; 662141cc406Sopenharmony_ci } 663141cc406Sopenharmony_ci DBG(DEBUG_INFO,"mode=%d, res=%d, BC=[%d,%d], xywh=[%d,%d,%d,%d]\n", 664141cc406Sopenharmony_ci this->mode, this->param.res, 665141cc406Sopenharmony_ci this->param.nBrightness, this->param.nContrast, 666141cc406Sopenharmony_ci this->param.x,this->param.y,this->param.cx,this->param.cy); 667141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 668141cc406Sopenharmony_ci} 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ciSANE_Status 671141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters *p) 672141cc406Sopenharmony_ci{ 673141cc406Sopenharmony_ci /* extremely important for xscanimage */ 674141cc406Sopenharmony_ci TInstance *this; 675141cc406Sopenharmony_ci this=(TInstance*)handle; 676141cc406Sopenharmony_ci SetupInternalParameters(this); 677141cc406Sopenharmony_ci GetAreaSize(this); 678141cc406Sopenharmony_ci p->pixels_per_line=this->state.cxPixel; 679141cc406Sopenharmony_ci /* TODO: we need a more stable cyPixel prediction */ 680141cc406Sopenharmony_ci p->lines=this->state.cyPixel; 681141cc406Sopenharmony_ci p->last_frame=SANE_TRUE; 682141cc406Sopenharmony_ci switch (this->mode) 683141cc406Sopenharmony_ci { 684141cc406Sopenharmony_ci case color: 685141cc406Sopenharmony_ci p->format=SANE_FRAME_RGB; 686141cc406Sopenharmony_ci p->depth=8; 687141cc406Sopenharmony_ci p->bytes_per_line=p->pixels_per_line*3; 688141cc406Sopenharmony_ci break; 689141cc406Sopenharmony_ci case gray: 690141cc406Sopenharmony_ci p->format=SANE_FRAME_GRAY; 691141cc406Sopenharmony_ci p->depth=8; 692141cc406Sopenharmony_ci p->bytes_per_line=p->pixels_per_line; 693141cc406Sopenharmony_ci break; 694141cc406Sopenharmony_ci case halftone: 695141cc406Sopenharmony_ci case line: 696141cc406Sopenharmony_ci p->format=SANE_FRAME_GRAY; 697141cc406Sopenharmony_ci p->depth=1; 698141cc406Sopenharmony_ci p->bytes_per_line=(p->pixels_per_line+7)/8; 699141cc406Sopenharmony_ci break; 700141cc406Sopenharmony_ci } 701141cc406Sopenharmony_ci DBG(DEBUG_INFO,"getting parameters (%d,%d)...\n",p->bytes_per_line,p->lines); 702141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 703141cc406Sopenharmony_ci} 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ciSANE_Status 706141cc406Sopenharmony_cisane_start (SANE_Handle handle) 707141cc406Sopenharmony_ci{ 708141cc406Sopenharmony_ci TInstance *this; 709141cc406Sopenharmony_ci SANE_Status rc; 710141cc406Sopenharmony_ci this=(TInstance*)handle; 711141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"starting scan...\n"); 712141cc406Sopenharmony_ci if (this->state.bScanning) return SANE_STATUS_DEVICE_BUSY; 713141cc406Sopenharmony_ci rc=SetupInternalParameters(this); 714141cc406Sopenharmony_ci this->state.bCanceled=false; 715141cc406Sopenharmony_ci if (!rc) rc=DoInit(this); /* oopsi, we should initialise :-) */ 716141cc406Sopenharmony_ci if (!rc && !this->bOptSkipOriginate) rc=DoOriginate(this,true); 717141cc406Sopenharmony_ci if (!rc) rc=DoJog(this,this->calibration.yMargin); 718141cc406Sopenharmony_ci if (rc) return rc; 719141cc406Sopenharmony_ci this->state.bEOF=false; 720141cc406Sopenharmony_ci switch (this->mode) 721141cc406Sopenharmony_ci { 722141cc406Sopenharmony_ci case color: rc=StartScanColor(this); break; 723141cc406Sopenharmony_ci default: rc=StartScanGray(this); break; 724141cc406Sopenharmony_ci } 725141cc406Sopenharmony_ci if (this->state.bCanceled) return SANE_STATUS_CANCELLED; 726141cc406Sopenharmony_ci return rc; 727141cc406Sopenharmony_ci} 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ciSANE_Status 730141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte *puchBuffer, 731141cc406Sopenharmony_ci SANE_Int cchMax, 732141cc406Sopenharmony_ci SANE_Int *pcchRead) 733141cc406Sopenharmony_ci{ 734141cc406Sopenharmony_ci SANE_Status rc; 735141cc406Sopenharmony_ci TInstance *this; 736141cc406Sopenharmony_ci this=(TInstance*)handle; 737141cc406Sopenharmony_ci DBG(DEBUG_INFO,"reading chunk %d...\n",(int)cchMax); 738141cc406Sopenharmony_ci *pcchRead=0; 739141cc406Sopenharmony_ci if (this->state.bEOF) 740141cc406Sopenharmony_ci return SANE_STATUS_EOF; 741141cc406Sopenharmony_ci rc=ReadChunk(this,puchBuffer,cchMax,pcchRead); 742141cc406Sopenharmony_ci DBG(DEBUG_INFO,"... line %d (%d/%d)...\n",this->state.iLine,*pcchRead,rc); 743141cc406Sopenharmony_ci switch (rc) 744141cc406Sopenharmony_ci { 745141cc406Sopenharmony_ci case SANE_STATUS_EOF: 746141cc406Sopenharmony_ci this->state.bEOF=true; /* flag EOF on next read() */ 747141cc406Sopenharmony_ci rc=SANE_STATUS_GOOD; /* we do not flag THIS block! */ 748141cc406Sopenharmony_ci break; 749141cc406Sopenharmony_ci case SANE_STATUS_GOOD: 750141cc406Sopenharmony_ci if (!*pcchRead) rc=SANE_STATUS_EOF; 751141cc406Sopenharmony_ci break; 752141cc406Sopenharmony_ci default: 753141cc406Sopenharmony_ci break; 754141cc406Sopenharmony_ci } 755141cc406Sopenharmony_ci return rc; 756141cc406Sopenharmony_ci} 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_civoid 759141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 760141cc406Sopenharmony_ci{ 761141cc406Sopenharmony_ci TInstance *this; 762141cc406Sopenharmony_ci this=(TInstance*)handle; 763141cc406Sopenharmony_ci DBG(DEBUG_VERBOSE,"cancel called...\n"); 764141cc406Sopenharmony_ci if (this->state.bScanning) 765141cc406Sopenharmony_ci { 766141cc406Sopenharmony_ci this->state.bCanceled=true; 767141cc406Sopenharmony_ci if (this->state.bEOF) /* regular (fast) cancel */ 768141cc406Sopenharmony_ci { 769141cc406Sopenharmony_ci DBG(DEBUG_INFO,"regular end cancel\n"); 770141cc406Sopenharmony_ci EndScan(this); 771141cc406Sopenharmony_ci DoJog(this,-this->calibration.yMargin); 772141cc406Sopenharmony_ci } 773141cc406Sopenharmony_ci else 774141cc406Sopenharmony_ci { 775141cc406Sopenharmony_ci /* since Xsane does not continue scanning, 776141cc406Sopenharmony_ci we cannot defer cancellation */ 777141cc406Sopenharmony_ci DBG(DEBUG_INFO,"hard cancel called...\n"); 778141cc406Sopenharmony_ci CancelScan(this); 779141cc406Sopenharmony_ci } 780141cc406Sopenharmony_ci } 781141cc406Sopenharmony_ci} 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_ciSANE_Status 784141cc406Sopenharmony_cisane_set_io_mode(SANE_Handle h, SANE_Bool m) 785141cc406Sopenharmony_ci{ 786141cc406Sopenharmony_ci (void) h; 787141cc406Sopenharmony_ci if (m==SANE_TRUE) /* no non-blocking-mode */ 788141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 789141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 790141cc406Sopenharmony_ci} 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ciSANE_Status 793141cc406Sopenharmony_cisane_get_select_fd(SANE_Handle handle, SANE_Int *fd) 794141cc406Sopenharmony_ci{ 795141cc406Sopenharmony_ci (void) handle; (void) fd; 796141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; /* we have no file IO */ 797141cc406Sopenharmony_ci} 798