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