diff options
Diffstat (limited to 'backend/hp5400_sane.c')
| -rw-r--r-- | backend/hp5400_sane.c | 543 | 
1 files changed, 439 insertions, 104 deletions
| diff --git a/backend/hp5400_sane.c b/backend/hp5400_sane.c index e5fdf43..b6fa6da 100644 --- a/backend/hp5400_sane.c +++ b/backend/hp5400_sane.c @@ -1,4 +1,5 @@  /* 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> @@ -71,28 +72,6 @@  #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)) @@ -115,30 +94,91 @@ typedef enum  {    optCount = 0, +  optDPI, +    optGroupGeometry,    optTLX, optTLY, optBRX, optBRY, -  optDPI, -  optGroupImage, +  optGroupEnhancement,    optGammaTableRed,		/* Gamma Tables */    optGammaTableGreen,    optGammaTableBlue, -  optLast,			/* Disable the offset code */ +  optGroupSensors, -  optGroupMisc, -  optOffsetX, optOffsetY +  optSensorScanTo, +  optSensorWeb, +  optSensorReprint, +  optSensorEmail, +  optSensorCopy, +  optSensorMoreOptions, +  optSensorCancel, +  optSensorPowerSave, +  optSensorCopiesUp, +  optSensorCopiesDown, +  optSensorColourBW, +  optSensorColourBWState, +  optSensorCopyCount, -/* put temporarily disabled options here after optLast */ -/* -  optLamp, -*/ +  // 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; @@ -165,6 +205,8 @@ typedef struct    int fScanning;		/* TRUE if actively scanning */    int fCanceled; + +  uint16_t sensorMap;           /* Contains the current unreported sensor bits. */  }  TScanner; @@ -191,18 +233,19 @@ 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, 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 const SANE_Range rangeXmm = {0, 216, 1}; +static const SANE_Range rangeYmm = {0, 297, 1};  static void _InitOptions(TScanner *s)  { @@ -248,8 +291,22 @@ static void _InitOptions(TScanner *s)        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->title  = "Geometry"; +      pDesc->name  = SANE_NAME_GEOMETRY; +      pDesc->title  = SANE_TITLE_GEOMETRY; +      pDesc->desc  = SANE_DESC_GEOMETRY;        pDesc->type   = SANE_TYPE_GROUP;        pDesc->size   = 0;        break; @@ -262,7 +319,7 @@ static void _InitOptions(TScanner *s)        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; +      pVal->w       = rangeXmm.min;        break;      case optTLY: @@ -273,7 +330,7 @@ static void _InitOptions(TScanner *s)        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; +      pVal->w       = rangeYmm.min;        break;      case optBRX: @@ -284,7 +341,7 @@ static void _InitOptions(TScanner *s)        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; +      pVal->w       = rangeXmm.max;        break;      case optBRY: @@ -295,22 +352,14 @@ static void _InitOptions(TScanner *s)        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]; +      pVal->w       = rangeYmm.max;        break; -    case optGroupImage: -      pDesc->title  = SANE_I18N("Image"); +      //--------------------------------- +    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; @@ -348,34 +397,130 @@ static void _InitOptions(TScanner *s)        pVal->wa      = s->aGammaTableB;        break; -    case optGroupMisc: -      pDesc->title  = SANE_I18N("Miscellaneous"); +      //--------------------------------- +    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 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; +    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 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; +    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"); @@ -385,8 +530,7 @@ static void _InitOptions(TScanner *s)        /* 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"); @@ -467,7 +611,7 @@ sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth)    SANE_String_Const proper_str;    int nline = 0; -  /* prevent compiler from complaing about unused parameters */ +  /* prevent compiler from complaining about unused parameters */    pfnAuth = pfnAuth;    strcpy(usb_devfile, "/dev/usb/scanner0"); @@ -531,7 +675,6 @@ sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth)        *piVersion = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);      } -    return SANE_STATUS_GOOD;  } @@ -694,7 +837,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,  	  /* Get options of type SANE_Word */  	case optBRX:  	case optTLX: -	  *(SANE_Word *) pVal = s->aValues[n].w;	/* Not needed anymore  - s->aValues[optOffsetX].w; */ +	  *(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); @@ -702,14 +845,12 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,  	case optBRY:  	case optTLY: -	  *(SANE_Word *) pVal = s->aValues[n].w;	/* Not needed anymore - - s->aValues[optOffsetY].w; */ +	  *(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 optOffsetX: -	case optOffsetY:  	case optCount:  	case optDPI:  	  HP5400_DBG (DBG_MSG, @@ -726,14 +867,94 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,  	  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; -#endif -#if 0 +  	case optCalibrate:  	  /*  although this option has nothing to read,  	     it's added here to avoid a warning when running scanimage --help */ @@ -761,26 +982,70 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,  	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; +	  { +            // 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: @@ -788,6 +1053,70 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,  	  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; @@ -924,6 +1253,7 @@ sane_start (SANE_Handle h)    s->ScanParams.iLinesRead = 0;    s->fScanning = TRUE; +  s->fCanceled = FALSE;    return SANE_STATUS_GOOD;  } @@ -944,6 +1274,11 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)    /* 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 */ | 
