summaryrefslogtreecommitdiff
path: root/backend/hp5400_sane.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/hp5400_sane.c')
-rw-r--r--backend/hp5400_sane.c543
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 */