kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			1357 wiersze
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			1357 wiersze
		
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
/* sane - Scanner Access Now Easy.
 | 
						|
   Copyright (C) 2020 Ralph Little <skelband@gmail.com>
 | 
						|
   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, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
   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"
 | 
						|
 | 
						|
/* 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,
 | 
						|
 | 
						|
  optDPI,
 | 
						|
 | 
						|
  optGroupGeometry,
 | 
						|
  optTLX, optTLY, optBRX, optBRY,
 | 
						|
 | 
						|
  optGroupEnhancement,
 | 
						|
 | 
						|
  optGammaTableRed,		/* Gamma Tables */
 | 
						|
  optGammaTableGreen,
 | 
						|
  optGammaTableBlue,
 | 
						|
 | 
						|
  optGroupSensors,
 | 
						|
 | 
						|
  optSensorScanTo,
 | 
						|
  optSensorWeb,
 | 
						|
  optSensorReprint,
 | 
						|
  optSensorEmail,
 | 
						|
  optSensorCopy,
 | 
						|
  optSensorMoreOptions,
 | 
						|
  optSensorCancel,
 | 
						|
  optSensorPowerSave,
 | 
						|
  optSensorCopiesUp,
 | 
						|
  optSensorCopiesDown,
 | 
						|
  optSensorColourBW,
 | 
						|
 | 
						|
  optSensorColourBWState,
 | 
						|
  optSensorCopyCount,
 | 
						|
 | 
						|
  // Unsupported as yet.
 | 
						|
  //optGroupMisc,
 | 
						|
  //optLamp,
 | 
						|
  //optCalibrate,
 | 
						|
 | 
						|
  optLast,			/* Disable the offset code */
 | 
						|
}
 | 
						|
EOptionIndex;
 | 
						|
 | 
						|
/*
 | 
						|
 * Array mapping (optSensor* - optGroupSensors - 1) to the bit mask of the
 | 
						|
 * corresponding sensor bit that we get from the scanner.
 | 
						|
 * All sensor bits are reported as a complete 16-bit word with individual bits set
 | 
						|
 * to indicate that the sensor has been activated.
 | 
						|
 * They seem to be latched so that they are picked up on next query and a number
 | 
						|
 * of bits can be set in any one query.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define SENSOR_BIT_SCAN           0x0400
 | 
						|
#define SENSOR_BIT_WEB            0x0200
 | 
						|
#define SENSOR_BIT_REPRINT        0x0002
 | 
						|
#define SENSOR_BIT_EMAIL          0x0080
 | 
						|
#define SENSOR_BIT_COPY           0x0040
 | 
						|
#define SENSOR_BIT_MOREOPTIONS    0x0004
 | 
						|
#define SENSOR_BIT_CANCEL         0x0100
 | 
						|
#define SENSOR_BIT_POWERSAVE      0x2000
 | 
						|
#define SENSOR_BIT_COPIESUP       0x0008
 | 
						|
#define SENSOR_BIT_COPIESDOWN     0x0020
 | 
						|
#define SENSOR_BIT_COLOURBW       0x0010
 | 
						|
 | 
						|
 | 
						|
uint16_t sensorMaskMap[] =
 | 
						|
{
 | 
						|
    SENSOR_BIT_SCAN,
 | 
						|
    SENSOR_BIT_WEB,
 | 
						|
    SENSOR_BIT_REPRINT,
 | 
						|
    SENSOR_BIT_EMAIL,
 | 
						|
    SENSOR_BIT_COPY,
 | 
						|
    SENSOR_BIT_MOREOPTIONS,
 | 
						|
    SENSOR_BIT_CANCEL,
 | 
						|
 | 
						|
    // Special buttons.
 | 
						|
    // These affect local machine settings, but we can still detect them being pressed.
 | 
						|
    SENSOR_BIT_POWERSAVE,
 | 
						|
    SENSOR_BIT_COPIESUP,
 | 
						|
    SENSOR_BIT_COPIESDOWN,
 | 
						|
    SENSOR_BIT_COLOURBW,
 | 
						|
 | 
						|
    // Extra entries to make the array up to the 16 possible bits.
 | 
						|
    0x0000,     // Unused
 | 
						|
    0x0000,     // Unused
 | 
						|
    0x0000,     // Unused
 | 
						|
    0x0000,     // Unused
 | 
						|
    0x0000      // Unused
 | 
						|
};
 | 
						|
 | 
						|
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;
 | 
						|
 | 
						|
  uint16_t sensorMap;           /* Contains the current unreported sensor bits. */
 | 
						|
}
 | 
						|
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};
 | 
						|
static const SANE_Range rangeCopyCountTable = {0, 99, 1};
 | 
						|
static SANE_String_Const modeSwitchList[] = {
 | 
						|
    SANE_VALUE_SCAN_MODE_COLOR,
 | 
						|
    SANE_VALUE_SCAN_MODE_GRAY,
 | 
						|
    NULL
 | 
						|
};
 | 
						|
#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, 216, 1};
 | 
						|
static const SANE_Range rangeYmm = {0, 297, 1};
 | 
						|
 | 
						|
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 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 optGroupGeometry:
 | 
						|
      pDesc->name  = SANE_NAME_GEOMETRY;
 | 
						|
      pDesc->title  = SANE_TITLE_GEOMETRY;
 | 
						|
      pDesc->desc  = SANE_DESC_GEOMETRY;
 | 
						|
      pDesc->type   = SANE_TYPE_GROUP;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optTLX:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_TL_X;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_TL_X;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_TL_X;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeXmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeXmm.min;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optTLY:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_TL_Y;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_TL_Y;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_TL_Y;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeYmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeYmm.min;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optBRX:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_BR_X;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_BR_X;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_BR_X;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeXmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeXmm.max;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optBRY:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN_BR_Y;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN_BR_Y;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN_BR_Y;
 | 
						|
      pDesc->unit   = SANE_UNIT_MM;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeYmm;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      pVal->w       = rangeYmm.max;
 | 
						|
      break;
 | 
						|
 | 
						|
      //---------------------------------
 | 
						|
    case optGroupEnhancement:
 | 
						|
      pDesc->name  = SANE_NAME_ENHANCEMENT;
 | 
						|
      pDesc->title  = SANE_TITLE_ENHANCEMENT;
 | 
						|
      pDesc->desc  = SANE_DESC_ENHANCEMENT;
 | 
						|
      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 optGroupSensors:
 | 
						|
      pDesc->name  = SANE_NAME_SENSORS;
 | 
						|
      pDesc->title  = SANE_TITLE_SENSORS;
 | 
						|
      pDesc->type   = SANE_TYPE_GROUP;
 | 
						|
      pDesc->desc   = SANE_DESC_SENSORS;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorScanTo:
 | 
						|
      pDesc->name   = SANE_NAME_SCAN;
 | 
						|
      pDesc->title  = SANE_TITLE_SCAN;
 | 
						|
      pDesc->desc   = SANE_DESC_SCAN;
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorWeb:
 | 
						|
      pDesc->name   = SANE_I18N("web");
 | 
						|
      pDesc->title  = SANE_I18N("Share-To-Web button");
 | 
						|
      pDesc->desc   = SANE_I18N("Scan an image and send it on the web");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorReprint:
 | 
						|
      pDesc->name   = SANE_I18N("reprint");
 | 
						|
      pDesc->title  = SANE_I18N("Reprint Photos button");
 | 
						|
      pDesc->desc   = SANE_I18N("Button for reprinting photos");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorEmail:
 | 
						|
      pDesc->name   = SANE_NAME_EMAIL;
 | 
						|
      pDesc->title  = SANE_TITLE_EMAIL;
 | 
						|
      pDesc->desc   = SANE_DESC_EMAIL;
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorCopy:
 | 
						|
      pDesc->name   = SANE_NAME_COPY;
 | 
						|
      pDesc->title  = SANE_TITLE_COPY;
 | 
						|
      pDesc->desc   = SANE_DESC_COPY;
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorMoreOptions:
 | 
						|
      pDesc->name   = SANE_I18N("more-options");
 | 
						|
      pDesc->title  = SANE_I18N("More Options button");
 | 
						|
      pDesc->desc   = SANE_I18N("Button for additional options/configuration");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorCancel:
 | 
						|
      pDesc->name   = SANE_NAME_CANCEL;
 | 
						|
      pDesc->title  = SANE_TITLE_CANCEL;
 | 
						|
      pDesc->desc   = SANE_DESC_CANCEL;
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorPowerSave:
 | 
						|
      pDesc->name   = SANE_I18N("power-save");
 | 
						|
      pDesc->title  = SANE_I18N("Power Save button");
 | 
						|
      pDesc->desc   = SANE_I18N("Puts the scanner in an energy-conservation mode");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorCopiesUp:
 | 
						|
      pDesc->name   = SANE_I18N("copies-up");
 | 
						|
      pDesc->title  = SANE_I18N("Increase Copies button");
 | 
						|
      pDesc->desc   = SANE_I18N("Increase the number of copies");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorCopiesDown:
 | 
						|
      pDesc->name   = SANE_I18N("copies-down");
 | 
						|
      pDesc->title  = SANE_I18N("Decrease Copies button");
 | 
						|
      pDesc->desc   = SANE_I18N("Decrease the number of copies");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorColourBW:
 | 
						|
      pDesc->name   = SANE_I18N("color-bw");
 | 
						|
      pDesc->title  = SANE_I18N("Select color/BW button");
 | 
						|
      pDesc->desc   = SANE_I18N("Alternates between color and black/white scanning");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorColourBWState:
 | 
						|
      pDesc->name   = SANE_I18N("color-bw-state");
 | 
						|
      pDesc->title  = SANE_I18N("Read color/BW button state");
 | 
						|
      pDesc->desc   = SANE_I18N("Reads state of BW/colour panel setting");
 | 
						|
      pDesc->type   = SANE_TYPE_STRING;
 | 
						|
      pDesc->constraint_type  = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
      pDesc->constraint.string_list = modeSwitchList;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optSensorCopyCount:
 | 
						|
      pDesc->name   = SANE_I18N("copies-count");
 | 
						|
      pDesc->title  = SANE_I18N("Read copy count value");
 | 
						|
      pDesc->desc   = SANE_I18N("Reads state of copy count panel setting");
 | 
						|
      pDesc->type   = SANE_TYPE_INT;
 | 
						|
      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
      pDesc->constraint.range = &rangeCopyCountTable;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
 | 
						|
      break;
 | 
						|
 | 
						|
#if 0
 | 
						|
    case optGroupMisc:
 | 
						|
      pDesc->title  = SANE_I18N("Miscellaneous");
 | 
						|
      pDesc->type   = SANE_TYPE_GROUP;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optLamp:
 | 
						|
      pDesc->name   = "lamp";
 | 
						|
      pDesc->title  = SANE_I18N("Lamp status");
 | 
						|
      pDesc->desc   = SANE_I18N("Switches the lamp on or off.");
 | 
						|
      pDesc->type   = SANE_TYPE_BOOL;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
      /* switch the lamp on when starting for first the time */
 | 
						|
      pVal->w       = SANE_TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case optCalibrate:
 | 
						|
      pDesc->name   = "calibrate";
 | 
						|
      pDesc->title  = SANE_I18N("Calibrate");
 | 
						|
      pDesc->desc   = SANE_I18N("Calibrates for black and white level.");
 | 
						|
      pDesc->type   = SANE_TYPE_BUTTON;
 | 
						|
      pDesc->cap    = SANE_CAP_SOFT_SELECT;
 | 
						|
      pDesc->size   = 0;
 | 
						|
      break;
 | 
						|
#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;
 | 
						|
  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 complaining 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",
 | 
						|
       SANE_CURRENT_MAJOR, SANE_CURRENT_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 (SANE_CURRENT_MAJOR, SANE_CURRENT_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;
 | 
						|
	  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;
 | 
						|
	  HP5400_DBG (DBG_MSG,
 | 
						|
	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
 | 
						|
	       *(SANE_Word *) pVal);
 | 
						|
	  break;
 | 
						|
 | 
						|
	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;
 | 
						|
 | 
						|
	case optSensorScanTo:
 | 
						|
	case optSensorWeb:
 | 
						|
	case optSensorReprint:
 | 
						|
	case optSensorEmail:
 | 
						|
	case optSensorCopy:
 | 
						|
	case optSensorMoreOptions:
 | 
						|
	case optSensorCancel:
 | 
						|
	case optSensorPowerSave:
 | 
						|
	case optSensorCopiesUp:
 | 
						|
	case optSensorCopiesDown:
 | 
						|
        case optSensorColourBW:
 | 
						|
          {
 | 
						|
            HP5400_DBG (DBG_MSG, "Reading sensor state\n");
 | 
						|
 | 
						|
            uint16_t sensorMap;
 | 
						|
            if (GetSensors(&s->HWParams, &sensorMap) != 0)
 | 
						|
              {
 | 
						|
                HP5400_DBG (DBG_ERR,
 | 
						|
                     "sane_control_option: SANE_ACTION_SET_VALUE could not retrieve sensors\n");
 | 
						|
                return SANE_STATUS_IO_ERROR;
 | 
						|
 | 
						|
              }
 | 
						|
 | 
						|
            HP5400_DBG (DBG_MSG, "Sensor state=%x\n", sensorMap);
 | 
						|
 | 
						|
            // Add read flags to what we already have so that we can report them when requested.
 | 
						|
            s->sensorMap |= sensorMap;
 | 
						|
 | 
						|
            // Look up the mask based on the option number.
 | 
						|
            uint16_t mask = sensorMaskMap[n - optGroupSensors - 1];
 | 
						|
            *(SANE_Word *) pVal = (s->sensorMap & mask)? 1:0;
 | 
						|
            s->sensorMap &= ~mask;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
        case optSensorCopyCount:
 | 
						|
            {
 | 
						|
              HP5400_DBG (DBG_MSG, "Reading copy count\n");
 | 
						|
 | 
						|
              TPanelInfo panelInfo;
 | 
						|
              if (GetPanelInfo(&s->HWParams, &panelInfo) != 0)
 | 
						|
                {
 | 
						|
                  HP5400_DBG (DBG_ERR,
 | 
						|
                       "sane_control_option: SANE_ACTION_SET_VALUE could not retrieve panel info\n");
 | 
						|
                  return SANE_STATUS_IO_ERROR;
 | 
						|
 | 
						|
                }
 | 
						|
 | 
						|
              HP5400_DBG (DBG_MSG, "Copy count setting=%u\n", panelInfo.copycount);
 | 
						|
              *(SANE_Word *) pVal = panelInfo.copycount;
 | 
						|
              break;
 | 
						|
            }
 | 
						|
 | 
						|
        case optSensorColourBWState:
 | 
						|
            {
 | 
						|
              HP5400_DBG (DBG_MSG, "Reading BW/Colour setting\n");
 | 
						|
 | 
						|
              TPanelInfo panelInfo;
 | 
						|
              if (GetPanelInfo(&s->HWParams, &panelInfo) != 0)
 | 
						|
                {
 | 
						|
                  HP5400_DBG (DBG_ERR,
 | 
						|
                       "sane_control_option: SANE_ACTION_SET_VALUE could not retrieve panel info\n");
 | 
						|
                  return SANE_STATUS_IO_ERROR;
 | 
						|
 | 
						|
                }
 | 
						|
 | 
						|
              HP5400_DBG (DBG_MSG, "BW/Colour setting=%u\n", panelInfo.bwcolour);
 | 
						|
 | 
						|
              // Just for safety:
 | 
						|
              if (panelInfo.bwcolour < 1)
 | 
						|
                {
 | 
						|
                  panelInfo.bwcolour = 1;
 | 
						|
                }
 | 
						|
              else if (panelInfo.bwcolour > 2)
 | 
						|
                {
 | 
						|
                  panelInfo.bwcolour = 2;
 | 
						|
                }
 | 
						|
              (void)strcpy((SANE_String)pVal, modeSwitchList[panelInfo.bwcolour - 1]);
 | 
						|
              break;
 | 
						|
            }
 | 
						|
 | 
						|
#if 0
 | 
						|
	  /* Get options of type SANE_Bool */
 | 
						|
	case optLamp:
 | 
						|
	  GetLamp (&s->HWParams, &fLampIsOn);
 | 
						|
	  *(SANE_Bool *) pVal = fLampIsOn;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case optCalibrate:
 | 
						|
	  /*  although this option has nothing to read,
 | 
						|
	     it's added here to avoid a warning when running scanimage --help */
 | 
						|
	  break;
 | 
						|
#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:
 | 
						|
	  {
 | 
						|
            // Check against legal values.
 | 
						|
	    SANE_Word value = *(SANE_Word *) pVal;
 | 
						|
	    if ((value < s->aOptions[n].constraint.range->min) ||
 | 
						|
	        (value > s->aOptions[n].constraint.range->max))
 | 
						|
              {
 | 
						|
	        HP5400_DBG (DBG_ERR,
 | 
						|
	                   "sane_control_option: SANE_ACTION_SET_VALUE out of range X value\n");
 | 
						|
                return SANE_STATUS_INVAL;
 | 
						|
              }
 | 
						|
 | 
						|
            info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
            s->ScanParams.iLines = 0;	/* Forget actual image settings */
 | 
						|
            s->aValues[n].w = value;
 | 
						|
            break;
 | 
						|
	  }
 | 
						|
 | 
						|
        case optBRY:
 | 
						|
        case optTLY:
 | 
						|
          {
 | 
						|
            // Check against legal values.
 | 
						|
            SANE_Word value = *(SANE_Word *) pVal;
 | 
						|
            if ((value < s->aOptions[n].constraint.range->min) ||
 | 
						|
                (value > s->aOptions[n].constraint.range->max))
 | 
						|
              {
 | 
						|
                HP5400_DBG (DBG_ERR,
 | 
						|
                           "sane_control_option: SANE_ACTION_SET_VALUE out of range Y value\n");
 | 
						|
                return SANE_STATUS_INVAL;
 | 
						|
              }
 | 
						|
 | 
						|
            info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
            s->ScanParams.iLines = 0;	/* Forget actual image settings */
 | 
						|
            s->aValues[n].w = value;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
        case optDPI:
 | 
						|
          {
 | 
						|
            // Check against legal values.
 | 
						|
            SANE_Word dpiValue = *(SANE_Word *) pVal;
 | 
						|
 | 
						|
            // First check too large.
 | 
						|
            SANE_Word maxRes = setResolutions[setResolutions[0]];
 | 
						|
            if (dpiValue > maxRes)
 | 
						|
              {
 | 
						|
                dpiValue = maxRes;
 | 
						|
              }
 | 
						|
            else // Check smaller values: if not exact match, pick next higher available.
 | 
						|
              {
 | 
						|
                for (SANE_Int resIdx = 1; resIdx <= setResolutions[0]; resIdx++)
 | 
						|
                  {
 | 
						|
                    if (dpiValue <= setResolutions[resIdx])
 | 
						|
                      {
 | 
						|
                        dpiValue = setResolutions[resIdx];
 | 
						|
                        break;
 | 
						|
                      }
 | 
						|
                  }
 | 
						|
              }
 | 
						|
 | 
						|
            info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
            s->ScanParams.iLines = 0;	/* Forget actual image settings */
 | 
						|
            (s->aValues[n].w) = dpiValue;
 | 
						|
            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 optSensorColourBWState:
 | 
						|
            {
 | 
						|
              SANE_String bwColour = (SANE_String)pVal;
 | 
						|
              SANE_Word bwColourValue;
 | 
						|
 | 
						|
              if (strcmp(bwColour, SANE_VALUE_SCAN_MODE_COLOR) == 0)
 | 
						|
                {
 | 
						|
                  bwColourValue = 1;
 | 
						|
                }
 | 
						|
              else if (strcmp(bwColour, SANE_VALUE_SCAN_MODE_GRAY) == 0)
 | 
						|
                {
 | 
						|
                  bwColourValue = 2;
 | 
						|
                }
 | 
						|
              else
 | 
						|
                {
 | 
						|
                  HP5400_DBG (DBG_ERR,
 | 
						|
                       "sane_control_option: SANE_ACTION_SET_VALUE invalid colour/bw mode\n");
 | 
						|
                  return SANE_STATUS_INVAL;
 | 
						|
                }
 | 
						|
 | 
						|
              HP5400_DBG (DBG_MSG, "Setting BW/Colour state=%d\n", bwColourValue);
 | 
						|
 | 
						|
              /*
 | 
						|
               * Now write it with the other panel settings back to the scanner.
 | 
						|
               *
 | 
						|
               */
 | 
						|
              if (SetColourBW(&s->HWParams, bwColourValue) != 0)
 | 
						|
                {
 | 
						|
                  HP5400_DBG (DBG_ERR,
 | 
						|
                       "sane_control_option: SANE_ACTION_SET_VALUE could not set colour/BW mode\n");
 | 
						|
                  return SANE_STATUS_IO_ERROR;
 | 
						|
                }
 | 
						|
              break;
 | 
						|
            }
 | 
						|
 | 
						|
        case optSensorCopyCount:
 | 
						|
            {
 | 
						|
              SANE_Word copyCount = *(SANE_Word *) pVal;
 | 
						|
              if (copyCount < 0)
 | 
						|
                {
 | 
						|
                  copyCount = 0;
 | 
						|
                }
 | 
						|
              else if (copyCount > 99)
 | 
						|
                {
 | 
						|
                  copyCount = 99;
 | 
						|
                }
 | 
						|
 | 
						|
              HP5400_DBG (DBG_MSG, "Setting Copy Count=%d\n", copyCount);
 | 
						|
 | 
						|
              /*
 | 
						|
               * Now write it with the other panel settings back to the scanner.
 | 
						|
               *
 | 
						|
               */
 | 
						|
              if (SetCopyCount(&s->HWParams, copyCount) != 0)
 | 
						|
                {
 | 
						|
                  HP5400_DBG (DBG_ERR,
 | 
						|
                       "sane_control_option: SANE_ACTION_SET_VALUE could not set copy count\n");
 | 
						|
                  return SANE_STATUS_IO_ERROR;
 | 
						|
 | 
						|
                }
 | 
						|
              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;
 | 
						|
  s->fCanceled = FALSE;
 | 
						|
  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 (!s->fScanning || s->fCanceled)
 | 
						|
    {
 | 
						|
      HP5400_DBG (DBG_MSG, "sane_read: we're not scanning.\n");
 | 
						|
      return SANE_STATUS_EOF;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
  /* 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;
 | 
						|
}
 |