kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			1024 wiersze
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			1024 wiersze
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
/* sane - Scanner Access Now Easy.
 | 
						|
   Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
 | 
						|
   Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
 | 
						|
 | 
						|
   Originally copied from HP3300 testtools. Original notice follows:
 | 
						|
 | 
						|
   Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
 | 
						|
 | 
						|
   This file is part of the SANE package.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; either version 2
 | 
						|
   of the License, or (at your option) any later version.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
						|
 | 
						|
   As a special exception, the authors of SANE give permission for
 | 
						|
   additional uses of the libraries contained in this release of SANE.
 | 
						|
 | 
						|
   The exception is that, if you link a SANE library with other files
 | 
						|
   to produce an executable, this does not by itself cause the
 | 
						|
   resulting executable to be covered by the GNU General Public
 | 
						|
   License.  Your use of that executable is in no way restricted on
 | 
						|
   account of linking the SANE library code into it.
 | 
						|
 | 
						|
   This exception does not, however, invalidate any other reasons why
 | 
						|
   the executable file might be covered by the GNU General Public
 | 
						|
   License.
 | 
						|
 | 
						|
   If you submit changes to SANE to the maintainers to be included in
 | 
						|
   a subsequent release, you agree by submitting the changes that
 | 
						|
   those changes may be distributed with this exception intact.
 | 
						|
 | 
						|
   If you write modifications of your own for SANE, it is your choice
 | 
						|
   whether to permit this exception to apply to your modifications.
 | 
						|
   If you do not wish that, delete this exception notice.
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
    SANE interface for hp54xx scanners. Prototype.
 | 
						|
    Parts of this source were inspired by other backends.
 | 
						|
*/
 | 
						|
 | 
						|
#include "../include/sane/config.h"
 | 
						|
 | 
						|
/* definitions for debug */
 | 
						|
#include "hp5400_debug.h"
 | 
						|
 | 
						|
#include "../include/sane/sane.h"
 | 
						|
#include "../include/sane/sanei.h"
 | 
						|
#include "../include/sane/sanei_backend.h"
 | 
						|
#include "../include/sane/sanei_config.h"
 | 
						|
#include "../include/sane/saneopts.h"
 | 
						|
#include "../include/sane/sanei_usb.h"
 | 
						|
 | 
						|
#include <stdlib.h>         /* malloc, free */
 | 
						|
#include <string.h>         /* memcpy */
 | 
						|
#include <stdio.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#define HP5400_CONFIG_FILE "hp5400.conf"
 | 
						|
 | 
						|
#include "hp5400.h"
 | 
						|
 | 
						|
/* includes for data transfer methods */
 | 
						|
#include "hp5400.h"
 | 
						|
 | 
						|
#ifdef STANDALONE
 | 
						|
#include "hp5400_scanner.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(LINUX_USB_SUPPORT)
 | 
						|
  #include "hp5400_linux.c"
 | 
						|
#endif
 | 
						|
#if defined(USCANNER_SUPPORT)
 | 
						|
  #include "hp5400_uscanner.c"
 | 
						|
#endif
 | 
						|
#if defined(LIBUSB_SUPPORT)
 | 
						|
  #include "hp5400_libusb.c"
 | 
						|
#endif
 | 
						|
#if defined(LIBIEEE1284_SUPPORT)
 | 
						|
  #include "hp5400_ieee1284.c"
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* other definitions */
 | 
						|
#ifndef min
 | 
						|
#define min(A,B) (((A)<(B)) ? (A) : (B))
 | 
						|
#endif
 | 
						|
#ifndef max
 | 
						|
#define max(A,B) (((A)>(B)) ? (A) : (B))
 | 
						|
#endif
 | 
						|
 | 
						|
#define TRUE 1
 | 
						|
#define FALSE 0
 | 
						|
 | 
						|
#define MM_TO_PIXEL(_mm_, _dpi_)    ((_mm_) * (_dpi_) / 25.4)
 | 
						|
#define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_))
 | 
						|
 | 
						|
#define NUM_GAMMA_ENTRIES  65536
 | 
						|
 | 
						|
 | 
						|
/* options enumerator */
 | 
						|
typedef enum
 | 
						|
{
 | 
						|
  optCount = 0,
 | 
						|
 | 
						|
  optGroupGeometry,
 | 
						|
  optTLX, optTLY, optBRX, optBRY,
 | 
						|
  optDPI,
 | 
						|
 | 
						|
  optGroupImage,
 | 
						|
 | 
						|
  optGammaTableRed,		/* Gamma Tables */
 | 
						|
  optGammaTableGreen,
 | 
						|
  optGammaTableBlue,
 | 
						|
 | 
						|
  optLast,			/* Disable the offset code */
 | 
						|
 | 
						|
  optGroupMisc,
 | 
						|
  optOffsetX, optOffsetY
 | 
						|
 | 
						|
 | 
						|
/* put temporarily disabled options here after optLast */
 | 
						|
/*
 | 
						|
  optLamp,
 | 
						|
*/
 | 
						|
 | 
						|
}
 | 
						|
EOptionIndex;
 | 
						|
 | 
						|
typedef union
 | 
						|
{
 | 
						|
  SANE_Word w;
 | 
						|
  SANE_Word *wa;		/* word array */
 | 
						|
  SANE_String s;
 | 
						|
}
 | 
						|
TOptionValue;
 | 
						|
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
  SANE_Option_Descriptor aOptions[optLast];
 | 
						|
  TOptionValue aValues[optLast];
 | 
						|
 | 
						|
  TScanParams ScanParams;
 | 
						|
  THWParams HWParams;
 | 
						|
 | 
						|
  TDataPipe DataPipe;
 | 
						|
  int iLinesLeft;
 | 
						|
 | 
						|
  SANE_Int *aGammaTableR;	/* a 16-to-16 bit color lookup table */
 | 
						|
  SANE_Int *aGammaTableG;	/* a 16-to-16 bit color lookup table */
 | 
						|
  SANE_Int *aGammaTableB;	/* a 16-to-16 bit color lookup table */
 | 
						|
 | 
						|
  int fScanning;		/* TRUE if actively scanning */
 | 
						|
  int fCanceled;
 | 
						|
}
 | 
						|
TScanner;
 | 
						|
 | 
						|
 | 
						|
/* linked list of SANE_Device structures */
 | 
						|
typedef struct TDevListEntry
 | 
						|
{
 | 
						|
  struct TDevListEntry *pNext;
 | 
						|
  SANE_Device dev;
 | 
						|
  char* devname;
 | 
						|
}
 | 
						|
TDevListEntry;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Device filename for USB access */
 | 
						|
char usb_devfile[128];
 | 
						|
 | 
						|
static TDevListEntry *_pFirstSaneDev = 0;
 | 
						|
static int iNumSaneDev = 0;
 | 
						|
 | 
						|
 | 
						|
static const SANE_Device **_pSaneDevList = 0;
 | 
						|
 | 
						|
/* option constraints */
 | 
						|
static const SANE_Range rangeGammaTable = {0, 65535, 1};
 | 
						|
#ifdef SUPPORT_2400_DPI
 | 
						|
static const SANE_Int   setResolutions[] = {6, 75, 150, 300, 600, 1200, 2400};
 | 
						|
#else
 | 
						|
static const SANE_Int   setResolutions[] = {5, 75, 150, 300, 600, 1200};
 | 
						|
#endif
 | 
						|
static const SANE_Range rangeXmm = {0, 220, 1};
 | 
						|
static const SANE_Range rangeYmm = {0, 300, 1};
 | 
						|
static const SANE_Range rangeXoffset = {0, 20, 1};
 | 
						|
static const SANE_Range rangeYoffset = {0, 70, 1};
 | 
						|
static const SANE_Int offsetX = 5;
 | 
						|
static const SANE_Int offsetY = 52;
 | 
						|
 | 
						|
 | 
						|
static void _InitOptions(TScanner *s)
 | 
						|
{
 | 
						|
  int i, j;
 | 
						|
  SANE_Option_Descriptor *pDesc;
 | 
						|
  TOptionValue *pVal;
 | 
						|
 | 
						|
  /* set a neutral gamma */
 | 
						|
  if( s->aGammaTableR == NULL )   /* Not yet allocated */
 | 
						|
  {
 | 
						|
    s->aGammaTableR = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) );
 | 
						|
    s->aGammaTableG = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) );
 | 
						|
    s->aGammaTableB = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) );
 | 
						|
 | 
						|
    for (j = 0; j < NUM_GAMMA_ENTRIES; j++) {
 | 
						|
      s->aGammaTableR[j] = j;
 | 
						|
      s->aGammaTableG[j] = j;
 | 
						|
      s->aGammaTableB[j] = j;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = optCount; i < optLast; i++) {
 | 
						|
 | 
						|
    pDesc = &s->aOptions[i];
 | 
						|
    pVal = &s->aValues[i];
 | 
						|
 | 
						|
    /* defaults */
 | 
						|
    pDesc->name   = "";
 | 
						|
    pDesc->title  = "";
 | 
						|
    pDesc->desc   = "";
 | 
						|
    pDesc->type   = SANE_TYPE_INT;
 | 
						|
    pDesc->unit   = SANE_UNIT_NONE;
 | 
						|
    pDesc->size   = sizeof(SANE_Word);
 | 
						|
    pDesc->constraint_type = SANE_CONSTRAINT_NONE;
 | 
						|
    pDesc->cap    = 0;
 | 
						|
 | 
						|
    switch (i) {
 | 
						|
 | 
						|
    case optCount:
 | 
						|
      pDesc->title  = SANE_TITLE_NUM_OPTIONS;
 | 
						|
      pDesc->desc   = SANE_DESC_NUM_OPTIONS;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = (SANE_Word)optLast;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optGroupGeometry:
 | 
						|
      pDesc->title  = "Geometry";
 | 
						|
      pDesc->type   = SANE_TYPE_GROUP;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optTLX:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_TL_X;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_TL_X;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_TL_X;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeXmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeXmm.min + offsetX;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optTLY:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_TL_Y;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_TL_Y;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_TL_Y;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeYmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeYmm.min + offsetY;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optBRX:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_BR_X;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_BR_X;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_BR_X;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeXmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeXmm.max + offsetX;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optBRY:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_BR_Y;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_BR_Y;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_BR_Y;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeYmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeYmm.max + offsetY;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optDPI:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_RESOLUTION;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_RESOLUTION;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_RESOLUTION;
 | 
						|
      pDesc->unit   = SANE_UNIT_DPI;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_WORD_LIST;
 | 
						|
      pDesc->constraint.word_list = setResolutions;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = setResolutions[1];
 | 
						|
      break;
 | 
						|
 | 
						|
    case optGroupImage:
 | 
						|
      pDesc->title  = SANE_I18N("Image");
 | 
						|
      pDesc->type   = SANE_TYPE_GROUP;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optGammaTableRed:
 | 
						|
      pDesc->name   = SANE_NAME_GAMMA_VECTOR_R;
 | 
						|
      pDesc->title  = SANE_TITLE_GAMMA_VECTOR_R;
 | 
						|
      pDesc->desc   = SANE_DESC_GAMMA_VECTOR_R;
 | 
						|
      pDesc->size   = NUM_GAMMA_ENTRIES * sizeof( SANE_Int );
 | 
						|
      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeGammaTable;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->wa      = s->aGammaTableR;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optGammaTableGreen:
 | 
						|
      pDesc->name   = SANE_NAME_GAMMA_VECTOR_G;
 | 
						|
      pDesc->title  = SANE_TITLE_GAMMA_VECTOR_G;
 | 
						|
      pDesc->desc   = SANE_DESC_GAMMA_VECTOR_G;
 | 
						|
      pDesc->size   = NUM_GAMMA_ENTRIES * sizeof( SANE_Int );
 | 
						|
      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeGammaTable;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->wa      = s->aGammaTableG;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optGammaTableBlue:
 | 
						|
      pDesc->name   = SANE_NAME_GAMMA_VECTOR_B;
 | 
						|
      pDesc->title  = SANE_TITLE_GAMMA_VECTOR_B;
 | 
						|
      pDesc->desc   = SANE_DESC_GAMMA_VECTOR_B;
 | 
						|
      pDesc->size   = NUM_GAMMA_ENTRIES * sizeof( SANE_Int );
 | 
						|
      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeGammaTable;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->wa      = s->aGammaTableB;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optGroupMisc:
 | 
						|
      pDesc->title  = SANE_I18N("Miscellaneous");
 | 
						|
      pDesc->type   = SANE_TYPE_GROUP;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optOffsetX:
 | 
						|
      pDesc->title  = SANE_I18N("offset X");
 | 
						|
      pDesc->desc   = SANE_I18N("Hardware internal X position of the scanning area.");
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeXoffset;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT;
 | 
						|
      pVal->w       = offsetX;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optOffsetY:
 | 
						|
      pDesc->title  = SANE_I18N("offset Y");
 | 
						|
      pDesc->desc   = SANE_I18N("Hardware internal Y position of the scanning area.");
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeYoffset;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT;
 | 
						|
      pVal->w       = offsetY;
 | 
						|
      break;
 | 
						|
 | 
						|
 | 
						|
#if 0
 | 
						|
    case optLamp:
 | 
						|
      pDesc->name   = "lamp";
 | 
						|
      pDesc->title  = SANE_I18N("Lamp status");
 | 
						|
      pDesc->desc   = SANE_I18N("Switches the lamp on or off.");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      /* switch the lamp on when starting for first the time */
 | 
						|
      pVal->w       = SANE_TRUE;
 | 
						|
      break;
 | 
						|
#endif
 | 
						|
#if 0
 | 
						|
    case optCalibrate:
 | 
						|
      pDesc->name   = "calibrate";
 | 
						|
      pDesc->title  = SANE_I18N("Calibrate");
 | 
						|
      pDesc->desc   = SANE_I18N("Calibrates for black and white level.");
 | 
						|
      pDesc->type   = SANE_TYPE_BUTTON;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
#endif
 | 
						|
    default:
 | 
						|
      HP5400_DBG(DBG_ERR, "Uninitialised option %d\n", i);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int _ReportDevice(TScannerModel *pModel, const char *pszDeviceName)
 | 
						|
{
 | 
						|
  TDevListEntry *pNew, *pDev;
 | 
						|
 | 
						|
  HP5400_DBG(DBG_MSG, "hp5400: _ReportDevice '%s'\n", pszDeviceName);
 | 
						|
 | 
						|
  pNew = malloc(sizeof(TDevListEntry));
 | 
						|
  if (!pNew) {
 | 
						|
    HP5400_DBG(DBG_ERR, "no mem\n");
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* add new element to the end of the list */
 | 
						|
  if (_pFirstSaneDev == NULL) {
 | 
						|
    _pFirstSaneDev = pNew;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext) {
 | 
						|
      ;
 | 
						|
    }
 | 
						|
    pDev->pNext = pNew;
 | 
						|
  }
 | 
						|
 | 
						|
  /* fill in new element */
 | 
						|
  pNew->pNext = 0;
 | 
						|
  /* we use devname to avoid having to free a const
 | 
						|
   * pointer */
 | 
						|
  pNew->devname = (char*)strdup(pszDeviceName);
 | 
						|
  pNew->dev.name = pNew->devname;
 | 
						|
  (char*)strdup(pszDeviceName);
 | 
						|
  pNew->dev.vendor = pModel->pszVendor;
 | 
						|
  pNew->dev.model = pModel->pszName;
 | 
						|
  pNew->dev.type = "flatbed scanner";
 | 
						|
 | 
						|
  iNumSaneDev++;
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static SANE_Status
 | 
						|
attach_one_device (SANE_String_Const devname)
 | 
						|
{
 | 
						|
  const char * filename = (const char*) devname;
 | 
						|
  if (HP5400Detect (filename, _ReportDevice) < 0)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "attach_one_device: couldn't attach %s\n", devname);
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
    }
 | 
						|
  HP5400_DBG (DBG_MSG, "attach_one_device: attached %s successfully\n", devname);
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth)
 | 
						|
{
 | 
						|
  FILE *conf_fp;		/* Config file stream  */
 | 
						|
  SANE_Char line[PATH_MAX];
 | 
						|
  SANE_Char *str = NULL;
 | 
						|
  SANE_String_Const proper_str;
 | 
						|
  int nline = 0;
 | 
						|
 | 
						|
  /* prevent compiler from complaing about unused parameters */
 | 
						|
  pfnAuth = pfnAuth;
 | 
						|
 | 
						|
  strcpy(usb_devfile, "/dev/usb/scanner0");
 | 
						|
  _pFirstSaneDev = 0;
 | 
						|
  iNumSaneDev = 0;
 | 
						|
 | 
						|
  InitHp5400_internal();
 | 
						|
 | 
						|
 | 
						|
  DBG_INIT ();
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_init: SANE hp5400 backend version %d.%d-%d (from %s)\n",
 | 
						|
       V_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
 | 
						|
 | 
						|
  sanei_usb_init ();
 | 
						|
 | 
						|
  conf_fp = sanei_config_open (HP5400_CONFIG_FILE);
 | 
						|
 | 
						|
  iNumSaneDev = 0;
 | 
						|
 | 
						|
  if (conf_fp)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "Reading config file\n");
 | 
						|
 | 
						|
      while (sanei_config_read (line, sizeof (line), conf_fp))
 | 
						|
	{
 | 
						|
	  ++nline;
 | 
						|
 | 
						|
	  if (str)
 | 
						|
	    {
 | 
						|
	      free (str);
 | 
						|
	    }
 | 
						|
 | 
						|
	  proper_str = sanei_config_get_string (line, &str);
 | 
						|
 | 
						|
	  /* Discards white lines and comments */
 | 
						|
	  if (!str || proper_str == line || str[0] == '#')
 | 
						|
	    {
 | 
						|
	      HP5400_DBG (DBG_MSG, "Discarding line %d\n", nline);
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      /* If line's not blank or a comment, then it's the device
 | 
						|
	       * filename or a usb directive. */
 | 
						|
	      HP5400_DBG (DBG_MSG, "Trying to attach %s\n", line);
 | 
						|
	      sanei_usb_attach_matching_devices (line, attach_one_device);
 | 
						|
	    }
 | 
						|
	}			/* while */
 | 
						|
      fclose (conf_fp);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_ERR, "Unable to read config file \"%s\": %s\n",
 | 
						|
	   HP5400_CONFIG_FILE, strerror (errno));
 | 
						|
      HP5400_DBG (DBG_MSG, "Using default built-in values\n");
 | 
						|
      attach_one_device (usb_devfile);
 | 
						|
    }
 | 
						|
 | 
						|
  if (piVersion != NULL)
 | 
						|
    {
 | 
						|
      *piVersion = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD);
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
sane_exit (void)
 | 
						|
{
 | 
						|
  TDevListEntry *pDev, *pNext;
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_exit\n");
 | 
						|
 | 
						|
  /* free device list memory */
 | 
						|
  if (_pSaneDevList)
 | 
						|
    {
 | 
						|
      for (pDev = _pFirstSaneDev; pDev; pDev = pNext)
 | 
						|
	{
 | 
						|
	  pNext = pDev->pNext;
 | 
						|
	  free (pDev->devname);
 | 
						|
	  /* pDev->dev.name is the same pointer that pDev->devname */
 | 
						|
	  free (pDev);
 | 
						|
	}
 | 
						|
      _pFirstSaneDev = 0;
 | 
						|
      free (_pSaneDevList);
 | 
						|
      _pSaneDevList = 0;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
	FreeHp5400_internal();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
 | 
						|
{
 | 
						|
  TDevListEntry *pDev;
 | 
						|
  int i;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_get_devices\n");
 | 
						|
 | 
						|
  local_only = local_only;
 | 
						|
 | 
						|
  if (_pSaneDevList)
 | 
						|
    {
 | 
						|
      free (_pSaneDevList);
 | 
						|
    }
 | 
						|
 | 
						|
  _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1));
 | 
						|
  if (!_pSaneDevList)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "no mem\n");
 | 
						|
      return SANE_STATUS_NO_MEM;
 | 
						|
    }
 | 
						|
  i = 0;
 | 
						|
  for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext)
 | 
						|
    {
 | 
						|
      _pSaneDevList[i++] = &pDev->dev;
 | 
						|
    }
 | 
						|
  _pSaneDevList[i++] = 0;	/* last entry is 0 */
 | 
						|
 | 
						|
  *device_list = _pSaneDevList;
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_open (SANE_String_Const name, SANE_Handle * h)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_open: %s\n", name);
 | 
						|
 | 
						|
  /* check the name */
 | 
						|
  if (strlen (name) == 0)
 | 
						|
    {
 | 
						|
      /* default to first available device */
 | 
						|
      name = _pFirstSaneDev->dev.name;
 | 
						|
    }
 | 
						|
 | 
						|
  s = malloc (sizeof (TScanner));
 | 
						|
  if (!s)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "malloc failed\n");
 | 
						|
      return SANE_STATUS_NO_MEM;
 | 
						|
    }
 | 
						|
 | 
						|
  memset (s, 0, sizeof (TScanner));	/* Clear everything to zero */
 | 
						|
  if (HP5400Open (&s->HWParams, name) < 0)
 | 
						|
    {
 | 
						|
      /* is this OK ? */
 | 
						|
      HP5400_DBG (DBG_ERR, "HP5400Open failed\n");
 | 
						|
      free ((void *) s);
 | 
						|
      return SANE_STATUS_INVAL;	/* is this OK? */
 | 
						|
    }
 | 
						|
  HP5400_DBG (DBG_MSG, "Handle=%d\n", s->HWParams.iXferHandle);
 | 
						|
  _InitOptions (s);
 | 
						|
  *h = s;
 | 
						|
 | 
						|
  /* Turn on lamp by default at startup */
 | 
						|
/*  SetLamp(&s->HWParams, TRUE);  */
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
sane_close (SANE_Handle h)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_close\n");
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
 | 
						|
  /* turn of scanner lamp */
 | 
						|
  SetLamp (&s->HWParams, FALSE);
 | 
						|
 | 
						|
  /* close scanner */
 | 
						|
  HP5400Close (&s->HWParams);
 | 
						|
 | 
						|
  /* free scanner object memory */
 | 
						|
  free ((void *) s);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
const SANE_Option_Descriptor *
 | 
						|
sane_get_option_descriptor (SANE_Handle h, SANE_Int n)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_get_option_descriptor %d\n", n);
 | 
						|
 | 
						|
  if ((n < optCount) || (n >= optLast))
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
  return &s->aOptions[n];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
 | 
						|
		     void *pVal, SANE_Int * pInfo)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
  SANE_Int info;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_control_option: option %d, action %d\n", n, Action);
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
  info = 0;
 | 
						|
 | 
						|
  switch (Action)
 | 
						|
    {
 | 
						|
    case SANE_ACTION_GET_VALUE:
 | 
						|
      switch (n)
 | 
						|
	{
 | 
						|
 | 
						|
	  /* Get options of type SANE_Word */
 | 
						|
	case optBRX:
 | 
						|
	case optTLX:
 | 
						|
	  *(SANE_Word *) pVal = s->aValues[n].w;	/* Not needed anymore  - s->aValues[optOffsetX].w; */
 | 
						|
	  HP5400_DBG (DBG_MSG,
 | 
						|
	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
 | 
						|
	       *(SANE_Word *) pVal);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case optBRY:
 | 
						|
	case optTLY:
 | 
						|
	  *(SANE_Word *) pVal = s->aValues[n].w;	/* Not needed anymore - - s->aValues[optOffsetY].w; */
 | 
						|
	  HP5400_DBG (DBG_MSG,
 | 
						|
	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
 | 
						|
	       *(SANE_Word *) pVal);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case optOffsetX:
 | 
						|
	case optOffsetY:
 | 
						|
	case optCount:
 | 
						|
	case optDPI:
 | 
						|
	  HP5400_DBG (DBG_MSG,
 | 
						|
	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
 | 
						|
	       (int) s->aValues[n].w);
 | 
						|
	  *(SANE_Word *) pVal = s->aValues[n].w;
 | 
						|
	  break;
 | 
						|
 | 
						|
	  /* Get options of type SANE_Word array */
 | 
						|
	case optGammaTableRed:
 | 
						|
	case optGammaTableGreen:
 | 
						|
	case optGammaTableBlue:
 | 
						|
	  HP5400_DBG (DBG_MSG, "Reading gamma table\n");
 | 
						|
	  memcpy (pVal, s->aValues[n].wa, s->aOptions[n].size);
 | 
						|
	  break;
 | 
						|
 | 
						|
#if 0
 | 
						|
	  /* Get options of type SANE_Bool */
 | 
						|
	case optLamp:
 | 
						|
	  GetLamp (&s->HWParams, &fLampIsOn);
 | 
						|
	  *(SANE_Bool *) pVal = fLampIsOn;
 | 
						|
	  break;
 | 
						|
#endif
 | 
						|
#if 0
 | 
						|
	case optCalibrate:
 | 
						|
	  /*  although this option has nothing to read,
 | 
						|
	     it's added here to avoid a warning when running scanimage --help */
 | 
						|
	  break;
 | 
						|
#endif
 | 
						|
	default:
 | 
						|
	  HP5400_DBG (DBG_MSG, "SANE_ACTION_GET_VALUE: Invalid option (%d)\n", n);
 | 
						|
	}
 | 
						|
      break;
 | 
						|
 | 
						|
 | 
						|
    case SANE_ACTION_SET_VALUE:
 | 
						|
      if (s->fScanning)
 | 
						|
	{
 | 
						|
	  HP5400_DBG (DBG_ERR,
 | 
						|
	       "sane_control_option: SANE_ACTION_SET_VALUE not allowed during scan\n");
 | 
						|
	  return SANE_STATUS_INVAL;
 | 
						|
	}
 | 
						|
      switch (n)
 | 
						|
	{
 | 
						|
 | 
						|
	case optCount:
 | 
						|
	  return SANE_STATUS_INVAL;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case optBRX:
 | 
						|
	case optTLX:
 | 
						|
	  info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
	  s->ScanParams.iLines = 0;	/* Forget actual image settings */
 | 
						|
	  s->aValues[n].w = *(SANE_Word *) pVal;	/* Not needed anymore - + s->aValues[optOffsetX].w; */
 | 
						|
	  break;
 | 
						|
 | 
						|
	case optBRY:
 | 
						|
	case optTLY:
 | 
						|
	  info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
	  s->ScanParams.iLines = 0;	/* Forget actual image settings */
 | 
						|
	  s->aValues[n].w = *(SANE_Word *) pVal;	/* Not needed anymore - + s->aValues[optOffsetY].w; */
 | 
						|
	  break;
 | 
						|
	case optDPI:
 | 
						|
	  info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
	  s->ScanParams.iLines = 0;	/* Forget actual image settings */
 | 
						|
#ifdef SUPPORT_2400_DPI
 | 
						|
	  (s->aValues[n].w) = *(SANE_Word *) pVal;
 | 
						|
#else
 | 
						|
	  (s->aValues[n].w) = min (1200, *(SANE_Word *) pVal);
 | 
						|
#endif
 | 
						|
	  break;
 | 
						|
 | 
						|
	case optGammaTableRed:
 | 
						|
	case optGammaTableGreen:
 | 
						|
	case optGammaTableBlue:
 | 
						|
	  HP5400_DBG (DBG_MSG, "Writing gamma table\n");
 | 
						|
	  memcpy (s->aValues[n].wa, pVal, s->aOptions[n].size);
 | 
						|
	  break;
 | 
						|
/*
 | 
						|
    case optLamp:
 | 
						|
      fVal = *(SANE_Bool *)pVal;
 | 
						|
      HP5400_DBG(DBG_MSG, "lamp %s\n", fVal ? "on" : "off");
 | 
						|
      SetLamp(&s->HWParams, fVal);
 | 
						|
      break;
 | 
						|
*/
 | 
						|
#if 0
 | 
						|
	case optCalibrate:
 | 
						|
/*       SimpleCalib(&s->HWParams); */
 | 
						|
	  break;
 | 
						|
#endif
 | 
						|
	default:
 | 
						|
	  HP5400_DBG (DBG_ERR, "SANE_ACTION_SET_VALUE: Invalid option (%d)\n", n);
 | 
						|
	}
 | 
						|
      if (pInfo != NULL)
 | 
						|
	{
 | 
						|
	  *pInfo = info;
 | 
						|
	}
 | 
						|
      break;
 | 
						|
 | 
						|
    case SANE_ACTION_SET_AUTO:
 | 
						|
      return SANE_STATUS_UNSUPPORTED;
 | 
						|
 | 
						|
 | 
						|
    default:
 | 
						|
      HP5400_DBG (DBG_ERR, "Invalid action (%d)\n", Action);
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_get_parameters (SANE_Handle h, SANE_Parameters * p)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_get_parameters\n");
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
 | 
						|
  /* first do some checks */
 | 
						|
  if (s->aValues[optTLX].w >= s->aValues[optBRX].w)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_ERR, "TLX should be smaller than BRX\n");
 | 
						|
      return SANE_STATUS_INVAL;	/* proper error code? */
 | 
						|
    }
 | 
						|
  if (s->aValues[optTLY].w >= s->aValues[optBRY].w)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_ERR, "TLY should be smaller than BRY\n");
 | 
						|
      return SANE_STATUS_INVAL;	/* proper error code? */
 | 
						|
    }
 | 
						|
 | 
						|
  /* return the data */
 | 
						|
  p->format = SANE_FRAME_RGB;
 | 
						|
  p->last_frame = SANE_TRUE;
 | 
						|
 | 
						|
  p->depth = 8;
 | 
						|
  if (s->ScanParams.iLines)	/* Initialised by doing a scan */
 | 
						|
    {
 | 
						|
      p->pixels_per_line = s->ScanParams.iBytesPerLine / 3;
 | 
						|
      p->lines = s->ScanParams.iLines;
 | 
						|
      p->bytes_per_line = s->ScanParams.iBytesPerLine;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      p->lines = MM_TO_PIXEL (s->aValues[optBRY].w - s->aValues[optTLY].w,
 | 
						|
			      s->aValues[optDPI].w);
 | 
						|
      p->pixels_per_line =
 | 
						|
	MM_TO_PIXEL (s->aValues[optBRX].w - s->aValues[optTLX].w,
 | 
						|
		     s->aValues[optDPI].w);
 | 
						|
      p->bytes_per_line = p->pixels_per_line * 3;
 | 
						|
    }
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
#define BUFFER_READ_HEADER_SIZE 32
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_start (SANE_Handle h)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
  SANE_Parameters par;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_start\n");
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
 | 
						|
  if (sane_get_parameters (h, &par) != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "Invalid scan parameters (sane_get_parameters)\n");
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
    }
 | 
						|
  s->iLinesLeft = par.lines;
 | 
						|
 | 
						|
  /* fill in the scanparams using the option values */
 | 
						|
  s->ScanParams.iDpi = s->aValues[optDPI].w;
 | 
						|
  s->ScanParams.iLpi = s->aValues[optDPI].w;
 | 
						|
 | 
						|
  /* Guessing here. 75dpi => 1, 2400dpi => 32 */
 | 
						|
  /*  s->ScanParams.iColourOffset = s->aValues[optDPI].w / 75; */
 | 
						|
  /* now we don't need correction => corrected by scan request type ? */
 | 
						|
  s->ScanParams.iColourOffset = 0;
 | 
						|
 | 
						|
  s->ScanParams.iTop =
 | 
						|
    MM_TO_PIXEL (s->aValues[optTLY].w + s->HWParams.iTopLeftY, HW_LPI);
 | 
						|
  s->ScanParams.iLeft =
 | 
						|
    MM_TO_PIXEL (s->aValues[optTLX].w + s->HWParams.iTopLeftX, HW_DPI);
 | 
						|
 | 
						|
  /* Note: All measurements passed to the scanning routines must be in HW_LPI */
 | 
						|
  s->ScanParams.iWidth =
 | 
						|
    MM_TO_PIXEL (s->aValues[optBRX].w - s->aValues[optTLX].w, HW_LPI);
 | 
						|
  s->ScanParams.iHeight =
 | 
						|
    MM_TO_PIXEL (s->aValues[optBRY].w - s->aValues[optTLY].w, HW_LPI);
 | 
						|
 | 
						|
  /* After the scanning, the iLines and iBytesPerLine will be filled in */
 | 
						|
 | 
						|
  /* copy gamma table */
 | 
						|
  WriteGammaCalibTable (s->HWParams.iXferHandle, s->aGammaTableR,
 | 
						|
			s->aGammaTableG, s->aGammaTableB);
 | 
						|
 | 
						|
  /* prepare the actual scan */
 | 
						|
  /* We say normal here. In future we should have a preview flag to set preview mode */
 | 
						|
  if (InitScan (SCAN_TYPE_NORMAL, &s->ScanParams, &s->HWParams) != 0)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "Invalid scan parameters (InitScan)\n");
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
  /* for the moment no lines has been read */
 | 
						|
  s->ScanParams.iLinesRead = 0;
 | 
						|
 | 
						|
  s->fScanning = TRUE;
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
 | 
						|
{
 | 
						|
 | 
						|
  /* Read actual scan from the circular buffer */
 | 
						|
  /* Note: this is already color corrected, though some work still needs to be done
 | 
						|
     to deal with the colour offsetting */
 | 
						|
  TScanner *s;
 | 
						|
  char *buffer = (char*)buf;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_read: request %d bytes \n", maxlen);
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
 | 
						|
  /* nothing has been read for the moment */
 | 
						|
  *len = 0;
 | 
						|
 | 
						|
 | 
						|
  /* if we read all the lines return EOF */
 | 
						|
  if (s->ScanParams.iLinesRead == s->ScanParams.iLines)
 | 
						|
    {
 | 
						|
/*    FinishScan( &s->HWParams );        *** FinishScan called in sane_cancel */
 | 
						|
      HP5400_DBG (DBG_MSG, "sane_read: EOF\n");
 | 
						|
      return SANE_STATUS_EOF;
 | 
						|
    }
 | 
						|
 | 
						|
  /* read as many lines the buffer may contain and while there are lines to be read */
 | 
						|
  while ((*len + s->ScanParams.iBytesPerLine <= maxlen)
 | 
						|
	 && (s->ScanParams.iLinesRead < s->ScanParams.iLines))
 | 
						|
    {
 | 
						|
 | 
						|
      /* get one more line from the circular buffer */
 | 
						|
      CircBufferGetLine (s->HWParams.iXferHandle, &s->HWParams.pipe, buffer);
 | 
						|
 | 
						|
      /* increment pointer, size and line number */
 | 
						|
      buffer += s->ScanParams.iBytesPerLine;
 | 
						|
      *len += s->ScanParams.iBytesPerLine;
 | 
						|
      s->ScanParams.iLinesRead++;
 | 
						|
    }
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_read: %d bytes read\n", *len);
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
sane_cancel (SANE_Handle h)
 | 
						|
{
 | 
						|
  TScanner *s;
 | 
						|
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_cancel\n");
 | 
						|
 | 
						|
  s = (TScanner *) h;
 | 
						|
 | 
						|
  /* to be implemented more thoroughly */
 | 
						|
 | 
						|
  /* Make sure the scanner head returns home */
 | 
						|
  FinishScan (&s->HWParams);
 | 
						|
 | 
						|
  s->fCanceled = TRUE;
 | 
						|
  s->fScanning = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_set_io_mode (SANE_Handle h, SANE_Bool m)
 | 
						|
{
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_set_io_mode %s\n", m ? "non-blocking" : "blocking");
 | 
						|
 | 
						|
  /* prevent compiler from complaining about unused parameters */
 | 
						|
  h = h;
 | 
						|
 | 
						|
  if (m)
 | 
						|
    {
 | 
						|
      return SANE_STATUS_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
 | 
						|
{
 | 
						|
  HP5400_DBG (DBG_MSG, "sane_select_fd\n");
 | 
						|
 | 
						|
  /* prevent compiler from complaining about unused parameters */
 | 
						|
  h = h;
 | 
						|
  fd = fd;
 | 
						|
 | 
						|
  return SANE_STATUS_UNSUPPORTED;
 | 
						|
}
 |