1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 2020 Ralph Little <skelband@gmail.com>
3    Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
4    Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
5 
6    Originally copied from HP3300 testtools. Original notice follows:
7 
8    Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl)
9 
10    This file is part of the SANE package.
11 
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    as published by the Free Software Foundation; either version 2
15    of the License, or (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <https://www.gnu.org/licenses/>.
24 
25    As a special exception, the authors of SANE give permission for
26    additional uses of the libraries contained in this release of SANE.
27 
28    The exception is that, if you link a SANE library with other files
29    to produce an executable, this does not by itself cause the
30    resulting executable to be covered by the GNU General Public
31    License.  Your use of that executable is in no way restricted on
32    account of linking the SANE library code into it.
33 
34    This exception does not, however, invalidate any other reasons why
35    the executable file might be covered by the GNU General Public
36    License.
37 
38    If you submit changes to SANE to the maintainers to be included in
39    a subsequent release, you agree by submitting the changes that
40    those changes may be distributed with this exception intact.
41 
42    If you write modifications of your own for SANE, it is your choice
43    whether to permit this exception to apply to your modifications.
44    If you do not wish that, delete this exception notice.
45 */
46 
47 
48 /*
49     SANE interface for hp54xx scanners. Prototype.
50     Parts of this source were inspired by other backends.
51 */
52 
53 #include "../include/sane/config.h"
54 
55 /* definitions for debug */
56 #include "hp5400_debug.h"
57 
58 #include "../include/sane/sane.h"
59 #include "../include/sane/sanei.h"
60 #include "../include/sane/sanei_backend.h"
61 #include "../include/sane/sanei_config.h"
62 #include "../include/sane/saneopts.h"
63 #include "../include/sane/sanei_usb.h"
64 
65 #include <stdlib.h>         /* malloc, free */
66 #include <string.h>         /* memcpy */
67 #include <stdio.h>
68 #include <errno.h>
69 
70 #define HP5400_CONFIG_FILE "hp5400.conf"
71 
72 #include "hp5400.h"
73 
74 /* other definitions */
75 #ifndef min
76 #define min(A,B) (((A)<(B)) ? (A) : (B))
77 #endif
78 #ifndef max
79 #define max(A,B) (((A)>(B)) ? (A) : (B))
80 #endif
81 
82 #define TRUE 1
83 #define FALSE 0
84 
85 #define MM_TO_PIXEL(_mm_, _dpi_)    ((_mm_) * (_dpi_) / 25.4)
86 #define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_))
87 
88 #define NUM_GAMMA_ENTRIES  65536
89 
90 
91 /* options enumerator */
92 typedef enum
93 {
94   optCount = 0,
95 
96   optDPI,
97 
98   optGroupGeometry,
99   optTLX, optTLY, optBRX, optBRY,
100 
101   optGroupEnhancement,
102 
103   optGammaTableRed,		/* Gamma Tables */
104   optGammaTableGreen,
105   optGammaTableBlue,
106 
107   optGroupSensors,
108 
109   optSensorScanTo,
110   optSensorWeb,
111   optSensorReprint,
112   optSensorEmail,
113   optSensorCopy,
114   optSensorMoreOptions,
115   optSensorCancel,
116   optSensorPowerSave,
117   optSensorCopiesUp,
118   optSensorCopiesDown,
119   optSensorColourBW,
120 
121   optSensorColourBWState,
122   optSensorCopyCount,
123 
124   // Unsupported as yet.
125   //optGroupMisc,
126   //optLamp,
127   //optCalibrate,
128 
129   optLast,			/* Disable the offset code */
130 }
131 EOptionIndex;
132 
133 /*
134  * Array mapping (optSensor* - optGroupSensors - 1) to the bit mask of the
135  * corresponding sensor bit that we get from the scanner.
136  * All sensor bits are reported as a complete 16-bit word with individual bits set
137  * to indicate that the sensor has been activated.
138  * They seem to be latched so that they are picked up on next query and a number
139  * of bits can be set in any one query.
140  *
141  */
142 
143 #define SENSOR_BIT_SCAN           0x0400
144 #define SENSOR_BIT_WEB            0x0200
145 #define SENSOR_BIT_REPRINT        0x0002
146 #define SENSOR_BIT_EMAIL          0x0080
147 #define SENSOR_BIT_COPY           0x0040
148 #define SENSOR_BIT_MOREOPTIONS    0x0004
149 #define SENSOR_BIT_CANCEL         0x0100
150 #define SENSOR_BIT_POWERSAVE      0x2000
151 #define SENSOR_BIT_COPIESUP       0x0008
152 #define SENSOR_BIT_COPIESDOWN     0x0020
153 #define SENSOR_BIT_COLOURBW       0x0010
154 
155 
156 uint16_t sensorMaskMap[] =
157 {
158     SENSOR_BIT_SCAN,
159     SENSOR_BIT_WEB,
160     SENSOR_BIT_REPRINT,
161     SENSOR_BIT_EMAIL,
162     SENSOR_BIT_COPY,
163     SENSOR_BIT_MOREOPTIONS,
164     SENSOR_BIT_CANCEL,
165 
166     // Special buttons.
167     // These affect local machine settings, but we can still detect them being pressed.
168     SENSOR_BIT_POWERSAVE,
169     SENSOR_BIT_COPIESUP,
170     SENSOR_BIT_COPIESDOWN,
171     SENSOR_BIT_COLOURBW,
172 
173     // Extra entries to make the array up to the 16 possible bits.
174     0x0000,     // Unused
175     0x0000,     // Unused
176     0x0000,     // Unused
177     0x0000,     // Unused
178     0x0000      // Unused
179 };
180 
181 typedef union
182 {
183   SANE_Word w;
184   SANE_Word *wa;		/* word array */
185   SANE_String s;
186 }
187 TOptionValue;
188 
189 
190 typedef struct
191 {
192   SANE_Option_Descriptor aOptions[optLast];
193   TOptionValue aValues[optLast];
194 
195   TScanParams ScanParams;
196   THWParams HWParams;
197 
198   TDataPipe DataPipe;
199   int iLinesLeft;
200 
201   SANE_Int *aGammaTableR;	/* a 16-to-16 bit color lookup table */
202   SANE_Int *aGammaTableG;	/* a 16-to-16 bit color lookup table */
203   SANE_Int *aGammaTableB;	/* a 16-to-16 bit color lookup table */
204 
205   int fScanning;		/* TRUE if actively scanning */
206   int fCanceled;
207 
208   uint16_t sensorMap;           /* Contains the current unreported sensor bits. */
209 }
210 TScanner;
211 
212 
213 /* linked list of SANE_Device structures */
214 typedef struct TDevListEntry
215 {
216   struct TDevListEntry *pNext;
217   SANE_Device dev;
218   char* devname;
219 }
220 TDevListEntry;
221 
222 
223 
224 /* Device filename for USB access */
225 char usb_devfile[128];
226 
227 static TDevListEntry *_pFirstSaneDev = 0;
228 static int iNumSaneDev = 0;
229 
230 
231 static const SANE_Device **_pSaneDevList = 0;
232 
233 /* option constraints */
234 static const SANE_Range rangeGammaTable = {0, 65535, 1};
235 static const SANE_Range rangeCopyCountTable = {0, 99, 1};
236 static SANE_String_Const modeSwitchList[] = {
237     SANE_VALUE_SCAN_MODE_COLOR,
238     SANE_VALUE_SCAN_MODE_GRAY,
239     NULL
240 };
241 #ifdef SUPPORT_2400_DPI
242 static const SANE_Int   setResolutions[] = {6, 75, 150, 300, 600, 1200, 2400};
243 #else
244 static const SANE_Int   setResolutions[] = {5, 75, 150, 300, 600, 1200};
245 #endif
246 static const SANE_Range rangeXmm = {0, 216, 1};
247 static const SANE_Range rangeYmm = {0, 297, 1};
248 
_InitOptions(TScanner * s)249 static void _InitOptions(TScanner *s)
250 {
251   int i, j;
252   SANE_Option_Descriptor *pDesc;
253   TOptionValue *pVal;
254 
255   /* set a neutral gamma */
256   if( s->aGammaTableR == NULL )   /* Not yet allocated */
257   {
258     s->aGammaTableR = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) );
259     s->aGammaTableG = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) );
260     s->aGammaTableB = malloc( NUM_GAMMA_ENTRIES * sizeof( SANE_Int ) );
261 
262     for (j = 0; j < NUM_GAMMA_ENTRIES; j++) {
263       s->aGammaTableR[j] = j;
264       s->aGammaTableG[j] = j;
265       s->aGammaTableB[j] = j;
266     }
267   }
268 
269   for (i = optCount; i < optLast; i++) {
270 
271     pDesc = &s->aOptions[i];
272     pVal = &s->aValues[i];
273 
274     /* defaults */
275     pDesc->name   = "";
276     pDesc->title  = "";
277     pDesc->desc   = "";
278     pDesc->type   = SANE_TYPE_INT;
279     pDesc->unit   = SANE_UNIT_NONE;
280     pDesc->size   = sizeof(SANE_Word);
281     pDesc->constraint_type = SANE_CONSTRAINT_NONE;
282     pDesc->cap    = 0;
283 
284     switch (i) {
285 
286     case optCount:
287       pDesc->title  = SANE_TITLE_NUM_OPTIONS;
288       pDesc->desc   = SANE_DESC_NUM_OPTIONS;
289       pDesc->cap    = SANE_CAP_SOFT_DETECT;
290       pVal->w       = (SANE_Word)optLast;
291       break;
292 
293     case optDPI:
294       pDesc->name   = SANE_NAME_SCAN_RESOLUTION;
295       pDesc->title  = SANE_TITLE_SCAN_RESOLUTION;
296       pDesc->desc   = SANE_DESC_SCAN_RESOLUTION;
297       pDesc->unit   = SANE_UNIT_DPI;
298       pDesc->constraint_type  = SANE_CONSTRAINT_WORD_LIST;
299       pDesc->constraint.word_list = setResolutions;
300       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
301       pVal->w       = setResolutions[1];
302       break;
303 
304       //---------------------------------
305     case optGroupGeometry:
306       pDesc->name  = SANE_NAME_GEOMETRY;
307       pDesc->title  = SANE_TITLE_GEOMETRY;
308       pDesc->desc  = SANE_DESC_GEOMETRY;
309       pDesc->type   = SANE_TYPE_GROUP;
310       pDesc->size   = 0;
311       break;
312 
313     case optTLX:
314       pDesc->name   = SANE_NAME_SCAN_TL_X;
315       pDesc->title  = SANE_TITLE_SCAN_TL_X;
316       pDesc->desc   = SANE_DESC_SCAN_TL_X;
317       pDesc->unit   = SANE_UNIT_MM;
318       pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
319       pDesc->constraint.range = &rangeXmm;
320       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
321       pVal->w       = rangeXmm.min;
322       break;
323 
324     case optTLY:
325       pDesc->name   = SANE_NAME_SCAN_TL_Y;
326       pDesc->title  = SANE_TITLE_SCAN_TL_Y;
327       pDesc->desc   = SANE_DESC_SCAN_TL_Y;
328       pDesc->unit   = SANE_UNIT_MM;
329       pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
330       pDesc->constraint.range = &rangeYmm;
331       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
332       pVal->w       = rangeYmm.min;
333       break;
334 
335     case optBRX:
336       pDesc->name   = SANE_NAME_SCAN_BR_X;
337       pDesc->title  = SANE_TITLE_SCAN_BR_X;
338       pDesc->desc   = SANE_DESC_SCAN_BR_X;
339       pDesc->unit   = SANE_UNIT_MM;
340       pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
341       pDesc->constraint.range = &rangeXmm;
342       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
343       pVal->w       = rangeXmm.max;
344       break;
345 
346     case optBRY:
347       pDesc->name   = SANE_NAME_SCAN_BR_Y;
348       pDesc->title  = SANE_TITLE_SCAN_BR_Y;
349       pDesc->desc   = SANE_DESC_SCAN_BR_Y;
350       pDesc->unit   = SANE_UNIT_MM;
351       pDesc->constraint_type  = SANE_CONSTRAINT_RANGE;
352       pDesc->constraint.range = &rangeYmm;
353       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
354       pVal->w       = rangeYmm.max;
355       break;
356 
357       //---------------------------------
358     case optGroupEnhancement:
359       pDesc->name  = SANE_NAME_ENHANCEMENT;
360       pDesc->title  = SANE_TITLE_ENHANCEMENT;
361       pDesc->desc  = SANE_DESC_ENHANCEMENT;
362       pDesc->type   = SANE_TYPE_GROUP;
363       pDesc->size   = 0;
364       break;
365 
366     case optGammaTableRed:
367       pDesc->name   = SANE_NAME_GAMMA_VECTOR_R;
368       pDesc->title  = SANE_TITLE_GAMMA_VECTOR_R;
369       pDesc->desc   = SANE_DESC_GAMMA_VECTOR_R;
370       pDesc->size   = NUM_GAMMA_ENTRIES * sizeof( SANE_Int );
371       pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
372       pDesc->constraint.range = &rangeGammaTable;
373       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
374       pVal->wa      = s->aGammaTableR;
375       break;
376 
377     case optGammaTableGreen:
378       pDesc->name   = SANE_NAME_GAMMA_VECTOR_G;
379       pDesc->title  = SANE_TITLE_GAMMA_VECTOR_G;
380       pDesc->desc   = SANE_DESC_GAMMA_VECTOR_G;
381       pDesc->size   = NUM_GAMMA_ENTRIES * sizeof( SANE_Int );
382       pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
383       pDesc->constraint.range = &rangeGammaTable;
384       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
385       pVal->wa      = s->aGammaTableG;
386       break;
387 
388     case optGammaTableBlue:
389       pDesc->name   = SANE_NAME_GAMMA_VECTOR_B;
390       pDesc->title  = SANE_TITLE_GAMMA_VECTOR_B;
391       pDesc->desc   = SANE_DESC_GAMMA_VECTOR_B;
392       pDesc->size   = NUM_GAMMA_ENTRIES * sizeof( SANE_Int );
393       pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
394       pDesc->constraint.range = &rangeGammaTable;
395       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
396       pVal->wa      = s->aGammaTableB;
397       break;
398 
399       //---------------------------------
400     case optGroupSensors:
401       pDesc->name  = SANE_NAME_SENSORS;
402       pDesc->title  = SANE_TITLE_SENSORS;
403       pDesc->type   = SANE_TYPE_GROUP;
404       pDesc->desc   = SANE_DESC_SENSORS;
405       pDesc->size   = 0;
406       break;
407 
408     case optSensorScanTo:
409       pDesc->name   = SANE_NAME_SCAN;
410       pDesc->title  = SANE_TITLE_SCAN;
411       pDesc->desc   = SANE_DESC_SCAN;
412       pDesc->type   = SANE_TYPE_BOOL;
413       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
414       break;
415 
416     case optSensorWeb:
417       pDesc->name   = SANE_I18N("web");
418       pDesc->title  = SANE_I18N("Share-To-Web button");
419       pDesc->desc   = SANE_I18N("Scan an image and send it on the web");
420       pDesc->type   = SANE_TYPE_BOOL;
421       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
422       break;
423 
424     case optSensorReprint:
425       pDesc->name   = SANE_I18N("reprint");
426       pDesc->title  = SANE_I18N("Reprint Photos button");
427       pDesc->desc   = SANE_I18N("Button for reprinting photos");
428       pDesc->type   = SANE_TYPE_BOOL;
429       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
430       break;
431 
432     case optSensorEmail:
433       pDesc->name   = SANE_NAME_EMAIL;
434       pDesc->title  = SANE_TITLE_EMAIL;
435       pDesc->desc   = SANE_DESC_EMAIL;
436       pDesc->type   = SANE_TYPE_BOOL;
437       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
438       break;
439 
440     case optSensorCopy:
441       pDesc->name   = SANE_NAME_COPY;
442       pDesc->title  = SANE_TITLE_COPY;
443       pDesc->desc   = SANE_DESC_COPY;
444       pDesc->type   = SANE_TYPE_BOOL;
445       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
446       break;
447 
448     case optSensorMoreOptions:
449       pDesc->name   = SANE_I18N("more-options");
450       pDesc->title  = SANE_I18N("More Options button");
451       pDesc->desc   = SANE_I18N("Button for additional options/configuration");
452       pDesc->type   = SANE_TYPE_BOOL;
453       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
454       break;
455 
456     case optSensorCancel:
457       pDesc->name   = SANE_NAME_CANCEL;
458       pDesc->title  = SANE_TITLE_CANCEL;
459       pDesc->desc   = SANE_DESC_CANCEL;
460       pDesc->type   = SANE_TYPE_BOOL;
461       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
462       break;
463 
464     case optSensorPowerSave:
465       pDesc->name   = SANE_I18N("power-save");
466       pDesc->title  = SANE_I18N("Power Save button");
467       pDesc->desc   = SANE_I18N("Puts the scanner in an energy-conservation mode");
468       pDesc->type   = SANE_TYPE_BOOL;
469       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
470       break;
471 
472     case optSensorCopiesUp:
473       pDesc->name   = SANE_I18N("copies-up");
474       pDesc->title  = SANE_I18N("Increase Copies button");
475       pDesc->desc   = SANE_I18N("Increase the number of copies");
476       pDesc->type   = SANE_TYPE_BOOL;
477       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
478       break;
479 
480     case optSensorCopiesDown:
481       pDesc->name   = SANE_I18N("copies-down");
482       pDesc->title  = SANE_I18N("Decrease Copies button");
483       pDesc->desc   = SANE_I18N("Decrease the number of copies");
484       pDesc->type   = SANE_TYPE_BOOL;
485       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
486       break;
487 
488     case optSensorColourBW:
489       pDesc->name   = SANE_I18N("color-bw");
490       pDesc->title  = SANE_I18N("Select color/BW button");
491       pDesc->desc   = SANE_I18N("Alternates between color and black/white scanning");
492       pDesc->type   = SANE_TYPE_BOOL;
493       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
494       break;
495 
496     case optSensorColourBWState:
497       pDesc->name   = SANE_I18N("color-bw-state");
498       pDesc->title  = SANE_I18N("Read color/BW button state");
499       pDesc->desc   = SANE_I18N("Reads state of BW/colour panel setting");
500       pDesc->type   = SANE_TYPE_STRING;
501       pDesc->constraint_type  = SANE_CONSTRAINT_STRING_LIST;
502       pDesc->constraint.string_list = modeSwitchList;
503       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
504       break;
505 
506     case optSensorCopyCount:
507       pDesc->name   = SANE_I18N("copies-count");
508       pDesc->title  = SANE_I18N("Read copy count value");
509       pDesc->desc   = SANE_I18N("Reads state of copy count panel setting");
510       pDesc->type   = SANE_TYPE_INT;
511       pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
512       pDesc->constraint.range = &rangeCopyCountTable;
513       pDesc->cap    = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
514       break;
515 
516 #if 0
517     case optGroupMisc:
518       pDesc->title  = SANE_I18N("Miscellaneous");
519       pDesc->type   = SANE_TYPE_GROUP;
520       pDesc->size   = 0;
521       break;
522 
523     case optLamp:
524       pDesc->name   = "lamp";
525       pDesc->title  = SANE_I18N("Lamp status");
526       pDesc->desc   = SANE_I18N("Switches the lamp on or off.");
527       pDesc->type   = SANE_TYPE_BOOL;
528       pDesc->cap    = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
529       /* switch the lamp on when starting for first the time */
530       pVal->w       = SANE_TRUE;
531       break;
532 
533     case optCalibrate:
534       pDesc->name   = "calibrate";
535       pDesc->title  = SANE_I18N("Calibrate");
536       pDesc->desc   = SANE_I18N("Calibrates for black and white level.");
537       pDesc->type   = SANE_TYPE_BUTTON;
538       pDesc->cap    = SANE_CAP_SOFT_SELECT;
539       pDesc->size   = 0;
540       break;
541 #endif
542     default:
543       HP5400_DBG(DBG_ERR, "Uninitialised option %d\n", i);
544       break;
545     }
546   }
547 }
548 
549 
_ReportDevice(TScannerModel * pModel,const char * pszDeviceName)550 static int _ReportDevice(TScannerModel *pModel, const char *pszDeviceName)
551 {
552   TDevListEntry *pNew, *pDev;
553 
554   HP5400_DBG(DBG_MSG, "hp5400: _ReportDevice '%s'\n", pszDeviceName);
555 
556   pNew = malloc(sizeof(TDevListEntry));
557   if (!pNew) {
558     HP5400_DBG(DBG_ERR, "no mem\n");
559     return -1;
560   }
561 
562   /* add new element to the end of the list */
563   if (_pFirstSaneDev == NULL) {
564     _pFirstSaneDev = pNew;
565   }
566   else {
567     for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext) {
568       ;
569     }
570     pDev->pNext = pNew;
571   }
572 
573   /* fill in new element */
574   pNew->pNext = 0;
575   /* we use devname to avoid having to free a const
576    * pointer */
577   pNew->devname = (char*)strdup(pszDeviceName);
578   pNew->dev.name = pNew->devname;
579   pNew->dev.vendor = pModel->pszVendor;
580   pNew->dev.model = pModel->pszName;
581   pNew->dev.type = "flatbed scanner";
582 
583   iNumSaneDev++;
584 
585   return 0;
586 }
587 
588 static SANE_Status
attach_one_device(SANE_String_Const devname)589 attach_one_device (SANE_String_Const devname)
590 {
591   const char * filename = (const char*) devname;
592   if (HP5400Detect (filename, _ReportDevice) < 0)
593     {
594       HP5400_DBG (DBG_MSG, "attach_one_device: couldn't attach %s\n", devname);
595       return SANE_STATUS_INVAL;
596     }
597   HP5400_DBG (DBG_MSG, "attach_one_device: attached %s successfully\n", devname);
598   return SANE_STATUS_GOOD;
599 }
600 
601 
602 /*****************************************************************************/
603 
604 SANE_Status
sane_init(SANE_Int * piVersion,SANE_Auth_Callback pfnAuth)605 sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth)
606 {
607   FILE *conf_fp;		/* Config file stream  */
608   SANE_Char line[PATH_MAX];
609   SANE_Char *str = NULL;
610   SANE_String_Const proper_str;
611   int nline = 0;
612 
613   /* prevent compiler from complaining about unused parameters */
614   pfnAuth = pfnAuth;
615 
616   strcpy(usb_devfile, "/dev/usb/scanner0");
617   _pFirstSaneDev = 0;
618   iNumSaneDev = 0;
619 
620   InitHp5400_internal();
621 
622 
623   DBG_INIT ();
624 
625   HP5400_DBG (DBG_MSG, "sane_init: SANE hp5400 backend version %d.%d-%d (from %s)\n",
626        SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
627 
628   sanei_usb_init ();
629 
630   conf_fp = sanei_config_open (HP5400_CONFIG_FILE);
631 
632   iNumSaneDev = 0;
633 
634   if (conf_fp)
635     {
636       HP5400_DBG (DBG_MSG, "Reading config file\n");
637 
638       while (sanei_config_read (line, sizeof (line), conf_fp))
639 	{
640 	  ++nline;
641 
642 	  if (str)
643 	    {
644 	      free (str);
645 	    }
646 
647 	  proper_str = sanei_config_get_string (line, &str);
648 
649 	  /* Discards white lines and comments */
650 	  if (!str || proper_str == line || str[0] == '#')
651 	    {
652 	      HP5400_DBG (DBG_MSG, "Discarding line %d\n", nline);
653 	    }
654 	  else
655 	    {
656 	      /* If line's not blank or a comment, then it's the device
657 	       * filename or a usb directive. */
658 	      HP5400_DBG (DBG_MSG, "Trying to attach %s\n", line);
659 	      sanei_usb_attach_matching_devices (line, attach_one_device);
660 	    }
661 	}			/* while */
662       fclose (conf_fp);
663     }
664   else
665     {
666       HP5400_DBG (DBG_ERR, "Unable to read config file \"%s\": %s\n",
667 	   HP5400_CONFIG_FILE, strerror (errno));
668       HP5400_DBG (DBG_MSG, "Using default built-in values\n");
669       attach_one_device (usb_devfile);
670     }
671 
672   if (piVersion != NULL)
673     {
674       *piVersion = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
675     }
676 
677   return SANE_STATUS_GOOD;
678 }
679 
680 
681 void
sane_exit(void)682 sane_exit (void)
683 {
684   TDevListEntry *pDev, *pNext;
685   HP5400_DBG (DBG_MSG, "sane_exit\n");
686 
687   /* free device list memory */
688   if (_pSaneDevList)
689     {
690       for (pDev = _pFirstSaneDev; pDev; pDev = pNext)
691 	{
692 	  pNext = pDev->pNext;
693 	  free (pDev->devname);
694 	  /* pDev->dev.name is the same pointer that pDev->devname */
695 	  free (pDev);
696 	}
697       _pFirstSaneDev = 0;
698       free (_pSaneDevList);
699       _pSaneDevList = 0;
700     }
701 
702 
703 	FreeHp5400_internal();
704 }
705 
706 
707 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)708 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
709 {
710   TDevListEntry *pDev;
711   int i;
712 
713   HP5400_DBG (DBG_MSG, "sane_get_devices\n");
714 
715   local_only = local_only;
716 
717   if (_pSaneDevList)
718     {
719       free (_pSaneDevList);
720     }
721 
722   _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1));
723   if (!_pSaneDevList)
724     {
725       HP5400_DBG (DBG_MSG, "no mem\n");
726       return SANE_STATUS_NO_MEM;
727     }
728   i = 0;
729   for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext)
730     {
731       _pSaneDevList[i++] = &pDev->dev;
732     }
733   _pSaneDevList[i++] = 0;	/* last entry is 0 */
734 
735   *device_list = _pSaneDevList;
736 
737   return SANE_STATUS_GOOD;
738 }
739 
740 
741 SANE_Status
sane_open(SANE_String_Const name,SANE_Handle * h)742 sane_open (SANE_String_Const name, SANE_Handle * h)
743 {
744   TScanner *s;
745 
746   HP5400_DBG (DBG_MSG, "sane_open: %s\n", name);
747 
748   /* check the name */
749   if (strlen (name) == 0)
750     {
751       /* default to first available device */
752       name = _pFirstSaneDev->dev.name;
753     }
754 
755   s = malloc (sizeof (TScanner));
756   if (!s)
757     {
758       HP5400_DBG (DBG_MSG, "malloc failed\n");
759       return SANE_STATUS_NO_MEM;
760     }
761 
762   memset (s, 0, sizeof (TScanner));	/* Clear everything to zero */
763   if (HP5400Open (&s->HWParams, name) < 0)
764     {
765       /* is this OK ? */
766       HP5400_DBG (DBG_ERR, "HP5400Open failed\n");
767       free ((void *) s);
768       return SANE_STATUS_INVAL;	/* is this OK? */
769     }
770   HP5400_DBG (DBG_MSG, "Handle=%d\n", s->HWParams.iXferHandle);
771   _InitOptions (s);
772   *h = s;
773 
774   /* Turn on lamp by default at startup */
775 /*  SetLamp(&s->HWParams, TRUE);  */
776 
777   return SANE_STATUS_GOOD;
778 }
779 
780 
781 void
sane_close(SANE_Handle h)782 sane_close (SANE_Handle h)
783 {
784   TScanner *s;
785 
786   HP5400_DBG (DBG_MSG, "sane_close\n");
787 
788   s = (TScanner *) h;
789 
790   /* turn of scanner lamp */
791   SetLamp (&s->HWParams, FALSE);
792 
793   /* close scanner */
794   HP5400Close (&s->HWParams);
795 
796   /* free scanner object memory */
797   free ((void *) s);
798 }
799 
800 
801 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle h,SANE_Int n)802 sane_get_option_descriptor (SANE_Handle h, SANE_Int n)
803 {
804   TScanner *s;
805 
806   HP5400_DBG (DBG_MSG, "sane_get_option_descriptor %d\n", n);
807 
808   if ((n < optCount) || (n >= optLast))
809     {
810       return NULL;
811     }
812 
813   s = (TScanner *) h;
814   return &s->aOptions[n];
815 }
816 
817 
818 SANE_Status
sane_control_option(SANE_Handle h,SANE_Int n,SANE_Action Action,void * pVal,SANE_Int * pInfo)819 sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
820 		     void *pVal, SANE_Int * pInfo)
821 {
822   TScanner *s;
823   SANE_Int info;
824 
825   HP5400_DBG (DBG_MSG, "sane_control_option: option %d, action %d\n", n, Action);
826 
827   s = (TScanner *) h;
828   info = 0;
829 
830   switch (Action)
831     {
832     case SANE_ACTION_GET_VALUE:
833       switch (n)
834 	{
835 
836 	  /* Get options of type SANE_Word */
837 	case optBRX:
838 	case optTLX:
839 	  *(SANE_Word *) pVal = s->aValues[n].w;
840 	  HP5400_DBG (DBG_MSG,
841 	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
842 	       *(SANE_Word *) pVal);
843 	  break;
844 
845 	case optBRY:
846 	case optTLY:
847 	  *(SANE_Word *) pVal = s->aValues[n].w;
848 	  HP5400_DBG (DBG_MSG,
849 	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
850 	       *(SANE_Word *) pVal);
851 	  break;
852 
853 	case optCount:
854 	case optDPI:
855 	  HP5400_DBG (DBG_MSG,
856 	       "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
857 	       (int) s->aValues[n].w);
858 	  *(SANE_Word *) pVal = s->aValues[n].w;
859 	  break;
860 
861 	  /* Get options of type SANE_Word array */
862 	case optGammaTableRed:
863 	case optGammaTableGreen:
864 	case optGammaTableBlue:
865 	  HP5400_DBG (DBG_MSG, "Reading gamma table\n");
866 	  memcpy (pVal, s->aValues[n].wa, s->aOptions[n].size);
867 	  break;
868 
869 	case optSensorScanTo:
870 	case optSensorWeb:
871 	case optSensorReprint:
872 	case optSensorEmail:
873 	case optSensorCopy:
874 	case optSensorMoreOptions:
875 	case optSensorCancel:
876 	case optSensorPowerSave:
877 	case optSensorCopiesUp:
878 	case optSensorCopiesDown:
879         case optSensorColourBW:
880           {
881             HP5400_DBG (DBG_MSG, "Reading sensor state\n");
882 
883             uint16_t sensorMap;
884             if (GetSensors(&s->HWParams, &sensorMap) != 0)
885               {
886                 HP5400_DBG (DBG_ERR,
887                      "sane_control_option: SANE_ACTION_SET_VALUE could not retrieve sensors\n");
888                 return SANE_STATUS_IO_ERROR;
889 
890               }
891 
892             HP5400_DBG (DBG_MSG, "Sensor state=%x\n", sensorMap);
893 
894             // Add read flags to what we already have so that we can report them when requested.
895             s->sensorMap |= sensorMap;
896 
897             // Look up the mask based on the option number.
898             uint16_t mask = sensorMaskMap[n - optGroupSensors - 1];
899             *(SANE_Word *) pVal = (s->sensorMap & mask)? 1:0;
900             s->sensorMap &= ~mask;
901             break;
902           }
903 
904         case optSensorCopyCount:
905             {
906               HP5400_DBG (DBG_MSG, "Reading copy count\n");
907 
908               TPanelInfo panelInfo;
909               if (GetPanelInfo(&s->HWParams, &panelInfo) != 0)
910                 {
911                   HP5400_DBG (DBG_ERR,
912                        "sane_control_option: SANE_ACTION_SET_VALUE could not retrieve panel info\n");
913                   return SANE_STATUS_IO_ERROR;
914 
915                 }
916 
917               HP5400_DBG (DBG_MSG, "Copy count setting=%u\n", panelInfo.copycount);
918               *(SANE_Word *) pVal = panelInfo.copycount;
919               break;
920             }
921 
922         case optSensorColourBWState:
923             {
924               HP5400_DBG (DBG_MSG, "Reading BW/Colour setting\n");
925 
926               TPanelInfo panelInfo;
927               if (GetPanelInfo(&s->HWParams, &panelInfo) != 0)
928                 {
929                   HP5400_DBG (DBG_ERR,
930                        "sane_control_option: SANE_ACTION_SET_VALUE could not retrieve panel info\n");
931                   return SANE_STATUS_IO_ERROR;
932 
933                 }
934 
935               HP5400_DBG (DBG_MSG, "BW/Colour setting=%u\n", panelInfo.bwcolour);
936 
937               // Just for safety:
938               if (panelInfo.bwcolour < 1)
939                 {
940                   panelInfo.bwcolour = 1;
941                 }
942               else if (panelInfo.bwcolour > 2)
943                 {
944                   panelInfo.bwcolour = 2;
945                 }
946               (void)strcpy((SANE_String)pVal, modeSwitchList[panelInfo.bwcolour - 1]);
947               break;
948             }
949 
950 #if 0
951 	  /* Get options of type SANE_Bool */
952 	case optLamp:
953 	  GetLamp (&s->HWParams, &fLampIsOn);
954 	  *(SANE_Bool *) pVal = fLampIsOn;
955 	  break;
956 
957 	case optCalibrate:
958 	  /*  although this option has nothing to read,
959 	     it's added here to avoid a warning when running scanimage --help */
960 	  break;
961 #endif
962 	default:
963 	  HP5400_DBG (DBG_MSG, "SANE_ACTION_GET_VALUE: Invalid option (%d)\n", n);
964 	}
965       break;
966 
967 
968     case SANE_ACTION_SET_VALUE:
969       if (s->fScanning)
970 	{
971 	  HP5400_DBG (DBG_ERR,
972 	       "sane_control_option: SANE_ACTION_SET_VALUE not allowed during scan\n");
973 	  return SANE_STATUS_INVAL;
974 	}
975       switch (n)
976 	{
977 
978 	case optCount:
979 	  return SANE_STATUS_INVAL;
980 	  break;
981 
982 	case optBRX:
983 	case optTLX:
984 	  {
985             // Check against legal values.
986 	    SANE_Word value = *(SANE_Word *) pVal;
987 	    if ((value < s->aOptions[n].constraint.range->min) ||
988 	        (value > s->aOptions[n].constraint.range->max))
989               {
990 	        HP5400_DBG (DBG_ERR,
991 	                   "sane_control_option: SANE_ACTION_SET_VALUE out of range X value\n");
992                 return SANE_STATUS_INVAL;
993               }
994 
995             info |= SANE_INFO_RELOAD_PARAMS;
996             s->ScanParams.iLines = 0;	/* Forget actual image settings */
997             s->aValues[n].w = value;
998             break;
999 	  }
1000 
1001         case optBRY:
1002         case optTLY:
1003           {
1004             // Check against legal values.
1005             SANE_Word value = *(SANE_Word *) pVal;
1006             if ((value < s->aOptions[n].constraint.range->min) ||
1007                 (value > s->aOptions[n].constraint.range->max))
1008               {
1009                 HP5400_DBG (DBG_ERR,
1010                            "sane_control_option: SANE_ACTION_SET_VALUE out of range Y value\n");
1011                 return SANE_STATUS_INVAL;
1012               }
1013 
1014             info |= SANE_INFO_RELOAD_PARAMS;
1015             s->ScanParams.iLines = 0;	/* Forget actual image settings */
1016             s->aValues[n].w = value;
1017             break;
1018           }
1019 
1020         case optDPI:
1021           {
1022             // Check against legal values.
1023             SANE_Word dpiValue = *(SANE_Word *) pVal;
1024 
1025             // First check too large.
1026             SANE_Word maxRes = setResolutions[setResolutions[0]];
1027             if (dpiValue > maxRes)
1028               {
1029                 dpiValue = maxRes;
1030               }
1031             else // Check smaller values: if not exact match, pick next higher available.
1032               {
1033                 for (SANE_Int resIdx = 1; resIdx <= setResolutions[0]; resIdx++)
1034                   {
1035                     if (dpiValue <= setResolutions[resIdx])
1036                       {
1037                         dpiValue = setResolutions[resIdx];
1038                         break;
1039                       }
1040                   }
1041               }
1042 
1043             info |= SANE_INFO_RELOAD_PARAMS;
1044             s->ScanParams.iLines = 0;	/* Forget actual image settings */
1045             (s->aValues[n].w) = dpiValue;
1046             break;
1047           }
1048 
1049 	case optGammaTableRed:
1050 	case optGammaTableGreen:
1051 	case optGammaTableBlue:
1052 	  HP5400_DBG (DBG_MSG, "Writing gamma table\n");
1053 	  memcpy (s->aValues[n].wa, pVal, s->aOptions[n].size);
1054 	  break;
1055 
1056         case optSensorColourBWState:
1057             {
1058               SANE_String bwColour = (SANE_String)pVal;
1059               SANE_Word bwColourValue;
1060 
1061               if (strcmp(bwColour, SANE_VALUE_SCAN_MODE_COLOR) == 0)
1062                 {
1063                   bwColourValue = 1;
1064                 }
1065               else if (strcmp(bwColour, SANE_VALUE_SCAN_MODE_GRAY) == 0)
1066                 {
1067                   bwColourValue = 2;
1068                 }
1069               else
1070                 {
1071                   HP5400_DBG (DBG_ERR,
1072                        "sane_control_option: SANE_ACTION_SET_VALUE invalid colour/bw mode\n");
1073                   return SANE_STATUS_INVAL;
1074                 }
1075 
1076               HP5400_DBG (DBG_MSG, "Setting BW/Colour state=%d\n", bwColourValue);
1077 
1078               /*
1079                * Now write it with the other panel settings back to the scanner.
1080                *
1081                */
1082               if (SetColourBW(&s->HWParams, bwColourValue) != 0)
1083                 {
1084                   HP5400_DBG (DBG_ERR,
1085                        "sane_control_option: SANE_ACTION_SET_VALUE could not set colour/BW mode\n");
1086                   return SANE_STATUS_IO_ERROR;
1087                 }
1088               break;
1089             }
1090 
1091         case optSensorCopyCount:
1092             {
1093               SANE_Word copyCount = *(SANE_Word *) pVal;
1094               if (copyCount < 0)
1095                 {
1096                   copyCount = 0;
1097                 }
1098               else if (copyCount > 99)
1099                 {
1100                   copyCount = 99;
1101                 }
1102 
1103               HP5400_DBG (DBG_MSG, "Setting Copy Count=%d\n", copyCount);
1104 
1105               /*
1106                * Now write it with the other panel settings back to the scanner.
1107                *
1108                */
1109               if (SetCopyCount(&s->HWParams, copyCount) != 0)
1110                 {
1111                   HP5400_DBG (DBG_ERR,
1112                        "sane_control_option: SANE_ACTION_SET_VALUE could not set copy count\n");
1113                   return SANE_STATUS_IO_ERROR;
1114 
1115                 }
1116               break;
1117             }
1118 
1119 /*
1120     case optLamp:
1121       fVal = *(SANE_Bool *)pVal;
1122       HP5400_DBG(DBG_MSG, "lamp %s\n", fVal ? "on" : "off");
1123       SetLamp(&s->HWParams, fVal);
1124       break;
1125 */
1126 #if 0
1127 	case optCalibrate:
1128 /*       SimpleCalib(&s->HWParams); */
1129 	  break;
1130 #endif
1131 	default:
1132 	  HP5400_DBG (DBG_ERR, "SANE_ACTION_SET_VALUE: Invalid option (%d)\n", n);
1133 	}
1134       if (pInfo != NULL)
1135 	{
1136 	  *pInfo = info;
1137 	}
1138       break;
1139 
1140     case SANE_ACTION_SET_AUTO:
1141       return SANE_STATUS_UNSUPPORTED;
1142 
1143 
1144     default:
1145       HP5400_DBG (DBG_ERR, "Invalid action (%d)\n", Action);
1146       return SANE_STATUS_INVAL;
1147     }
1148 
1149   return SANE_STATUS_GOOD;
1150 }
1151 
1152 
1153 
1154 SANE_Status
sane_get_parameters(SANE_Handle h,SANE_Parameters * p)1155 sane_get_parameters (SANE_Handle h, SANE_Parameters * p)
1156 {
1157   TScanner *s;
1158   HP5400_DBG (DBG_MSG, "sane_get_parameters\n");
1159 
1160   s = (TScanner *) h;
1161 
1162   /* first do some checks */
1163   if (s->aValues[optTLX].w >= s->aValues[optBRX].w)
1164     {
1165       HP5400_DBG (DBG_ERR, "TLX should be smaller than BRX\n");
1166       return SANE_STATUS_INVAL;	/* proper error code? */
1167     }
1168   if (s->aValues[optTLY].w >= s->aValues[optBRY].w)
1169     {
1170       HP5400_DBG (DBG_ERR, "TLY should be smaller than BRY\n");
1171       return SANE_STATUS_INVAL;	/* proper error code? */
1172     }
1173 
1174   /* return the data */
1175   p->format = SANE_FRAME_RGB;
1176   p->last_frame = SANE_TRUE;
1177 
1178   p->depth = 8;
1179   if (s->ScanParams.iLines)	/* Initialised by doing a scan */
1180     {
1181       p->pixels_per_line = s->ScanParams.iBytesPerLine / 3;
1182       p->lines = s->ScanParams.iLines;
1183       p->bytes_per_line = s->ScanParams.iBytesPerLine;
1184     }
1185   else
1186     {
1187       p->lines = MM_TO_PIXEL (s->aValues[optBRY].w - s->aValues[optTLY].w,
1188 			      s->aValues[optDPI].w);
1189       p->pixels_per_line =
1190 	MM_TO_PIXEL (s->aValues[optBRX].w - s->aValues[optTLX].w,
1191 		     s->aValues[optDPI].w);
1192       p->bytes_per_line = p->pixels_per_line * 3;
1193     }
1194 
1195   return SANE_STATUS_GOOD;
1196 }
1197 
1198 #define BUFFER_READ_HEADER_SIZE 32
1199 
1200 SANE_Status
sane_start(SANE_Handle h)1201 sane_start (SANE_Handle h)
1202 {
1203   TScanner *s;
1204   SANE_Parameters par;
1205 
1206   HP5400_DBG (DBG_MSG, "sane_start\n");
1207 
1208   s = (TScanner *) h;
1209 
1210   if (sane_get_parameters (h, &par) != SANE_STATUS_GOOD)
1211     {
1212       HP5400_DBG (DBG_MSG, "Invalid scan parameters (sane_get_parameters)\n");
1213       return SANE_STATUS_INVAL;
1214     }
1215   s->iLinesLeft = par.lines;
1216 
1217   /* fill in the scanparams using the option values */
1218   s->ScanParams.iDpi = s->aValues[optDPI].w;
1219   s->ScanParams.iLpi = s->aValues[optDPI].w;
1220 
1221   /* Guessing here. 75dpi => 1, 2400dpi => 32 */
1222   /*  s->ScanParams.iColourOffset = s->aValues[optDPI].w / 75; */
1223   /* now we don't need correction => corrected by scan request type ? */
1224   s->ScanParams.iColourOffset = 0;
1225 
1226   s->ScanParams.iTop =
1227     MM_TO_PIXEL (s->aValues[optTLY].w + s->HWParams.iTopLeftY, HW_LPI);
1228   s->ScanParams.iLeft =
1229     MM_TO_PIXEL (s->aValues[optTLX].w + s->HWParams.iTopLeftX, HW_DPI);
1230 
1231   /* Note: All measurements passed to the scanning routines must be in HW_LPI */
1232   s->ScanParams.iWidth =
1233     MM_TO_PIXEL (s->aValues[optBRX].w - s->aValues[optTLX].w, HW_LPI);
1234   s->ScanParams.iHeight =
1235     MM_TO_PIXEL (s->aValues[optBRY].w - s->aValues[optTLY].w, HW_LPI);
1236 
1237   /* After the scanning, the iLines and iBytesPerLine will be filled in */
1238 
1239   /* copy gamma table */
1240   WriteGammaCalibTable (s->HWParams.iXferHandle, s->aGammaTableR,
1241 			s->aGammaTableG, s->aGammaTableB);
1242 
1243   /* prepare the actual scan */
1244   /* We say normal here. In future we should have a preview flag to set preview mode */
1245   if (InitScan (SCAN_TYPE_NORMAL, &s->ScanParams, &s->HWParams) != 0)
1246     {
1247       HP5400_DBG (DBG_MSG, "Invalid scan parameters (InitScan)\n");
1248       return SANE_STATUS_INVAL;
1249     }
1250 
1251   /* for the moment no lines has been read */
1252   s->ScanParams.iLinesRead = 0;
1253 
1254   s->fScanning = TRUE;
1255   s->fCanceled = FALSE;
1256   return SANE_STATUS_GOOD;
1257 }
1258 
1259 
1260 SANE_Status
sane_read(SANE_Handle h,SANE_Byte * buf,SANE_Int maxlen,SANE_Int * len)1261 sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
1262 {
1263 
1264   /* Read actual scan from the circular buffer */
1265   /* Note: this is already color corrected, though some work still needs to be done
1266      to deal with the colour offsetting */
1267   TScanner *s;
1268   char *buffer = (char*)buf;
1269 
1270   HP5400_DBG (DBG_MSG, "sane_read: request %d bytes \n", maxlen);
1271 
1272   s = (TScanner *) h;
1273 
1274   /* nothing has been read for the moment */
1275   *len = 0;
1276   if (!s->fScanning || s->fCanceled)
1277     {
1278       HP5400_DBG (DBG_MSG, "sane_read: we're not scanning.\n");
1279       return SANE_STATUS_EOF;
1280     }
1281 
1282 
1283   /* if we read all the lines return EOF */
1284   if (s->ScanParams.iLinesRead == s->ScanParams.iLines)
1285     {
1286 /*    FinishScan( &s->HWParams );        *** FinishScan called in sane_cancel */
1287       HP5400_DBG (DBG_MSG, "sane_read: EOF\n");
1288       return SANE_STATUS_EOF;
1289     }
1290 
1291   /* read as many lines the buffer may contain and while there are lines to be read */
1292   while ((*len + s->ScanParams.iBytesPerLine <= maxlen)
1293 	 && (s->ScanParams.iLinesRead < s->ScanParams.iLines))
1294     {
1295 
1296       /* get one more line from the circular buffer */
1297       CircBufferGetLine (s->HWParams.iXferHandle, &s->HWParams.pipe, buffer);
1298 
1299       /* increment pointer, size and line number */
1300       buffer += s->ScanParams.iBytesPerLine;
1301       *len += s->ScanParams.iBytesPerLine;
1302       s->ScanParams.iLinesRead++;
1303     }
1304 
1305   HP5400_DBG (DBG_MSG, "sane_read: %d bytes read\n", *len);
1306 
1307   return SANE_STATUS_GOOD;
1308 }
1309 
1310 
1311 void
sane_cancel(SANE_Handle h)1312 sane_cancel (SANE_Handle h)
1313 {
1314   TScanner *s;
1315 
1316   HP5400_DBG (DBG_MSG, "sane_cancel\n");
1317 
1318   s = (TScanner *) h;
1319 
1320   /* to be implemented more thoroughly */
1321 
1322   /* Make sure the scanner head returns home */
1323   FinishScan (&s->HWParams);
1324 
1325   s->fCanceled = TRUE;
1326   s->fScanning = FALSE;
1327 }
1328 
1329 
1330 SANE_Status
sane_set_io_mode(SANE_Handle h,SANE_Bool m)1331 sane_set_io_mode (SANE_Handle h, SANE_Bool m)
1332 {
1333   HP5400_DBG (DBG_MSG, "sane_set_io_mode %s\n", m ? "non-blocking" : "blocking");
1334 
1335   /* prevent compiler from complaining about unused parameters */
1336   h = h;
1337 
1338   if (m)
1339     {
1340       return SANE_STATUS_UNSUPPORTED;
1341     }
1342   return SANE_STATUS_GOOD;
1343 }
1344 
1345 
1346 SANE_Status
sane_get_select_fd(SANE_Handle h,SANE_Int * fd)1347 sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
1348 {
1349   HP5400_DBG (DBG_MSG, "sane_select_fd\n");
1350 
1351   /* prevent compiler from complaining about unused parameters */
1352   h = h;
1353   fd = fd;
1354 
1355   return SANE_STATUS_UNSUPPORTED;
1356 }
1357