1 /************************************************************************************\
2
3 scl-pml.c - HP SANE backend for multi-function peripherals (libsane-hpaio)
4
5 (c) 2001-2014 Copyright HP Development Company, LP
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is furnished to do
12 so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Authors: Sarbeswar Meher
25
26 \************************************************************************************/
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include "sane.h"
34 #include "saneopts.h"
35 #include "common.h"
36 #include "io.h"
37 #include "mfpdtf.h"
38 #include "tables.h"
39 #include "hpmud.h"
40 #include "io.h"
41 #include "common.h"
42 #include "scl.h"
43 #include "hpaio.h"
44 #include "utils.h"
45
46 #define DEBUG_DECLARE_ONLY
47 #include "sanei_debug.h"
48
49 //# define SCLPML_DEBUG
50 # ifdef SCLPML_DEBUG
51 # define _DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
52 # else
53 # define _DBG(args...)
54 # endif
55
56 static struct hpaioScanner_s * session;
57
hpaioScannerToSaneError(hpaioScanner_t hpaio)58 SANE_Status __attribute__ ((visibility ("hidden"))) hpaioScannerToSaneError( hpaioScanner_t hpaio )
59 {
60 SANE_Status retcode;
61
62 if( hpaio->scannerType == SCANNER_TYPE_SCL )
63 {
64 int sclError;
65
66 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
67 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
68 SCL_INQ_CURRENT_ERROR,
69 &sclError,
70 0,
71 0 );
72
73 if( retcode == SANE_STATUS_UNSUPPORTED )
74 {
75 retcode = SANE_STATUS_GOOD;
76 }
77 else if( retcode == SANE_STATUS_GOOD )
78 {
79 bug("hpaio: hpaioScannerToSaneError: sclError=%d.\n", sclError);
80 switch( sclError )
81 {
82 case SCL_ERROR_UNRECOGNIZED_COMMAND:
83 case SCL_ERROR_PARAMETER_ERROR:
84 retcode = SANE_STATUS_UNSUPPORTED;
85 break;
86
87 case SCL_ERROR_NO_MEMORY:
88 retcode = SANE_STATUS_NO_MEM;
89 break;
90
91 case SCL_ERROR_CANCELLED:
92 retcode = SANE_STATUS_CANCELLED;
93 break;
94
95 case SCL_ERROR_PEN_DOOR_OPEN:
96 retcode = SANE_STATUS_COVER_OPEN;
97 break;
98
99 case SCL_ERROR_SCANNER_HEAD_LOCKED:
100 case SCL_ERROR_ADF_PAPER_JAM:
101 case SCL_ERROR_HOME_POSITION_MISSING:
102 case SCL_ERROR_ORIGINAL_ON_GLASS:
103 retcode = SANE_STATUS_JAMMED;
104 break;
105
106 case SCL_ERROR_PAPER_NOT_LOADED:
107 retcode = SANE_STATUS_NO_DOCS;
108 break;
109
110 default:
111 retcode = SANE_STATUS_IO_ERROR;
112 break;
113 }
114 }
115 }
116 else /* if (hpaio->scannerType==SCANNER_TYPE_PML) */
117 {
118 int pmlError, type;
119
120 if( PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid, hpaio->pml.objUploadError ) == ERROR )
121 {
122 retcode = SANE_STATUS_GOOD;
123 }
124 else if( PmlGetIntegerValue( hpaio->pml.objUploadError,
125 &type,
126 &pmlError ) == ERROR )
127 {
128 bug("hpaio: hpaioScannerToSaneError: PmlGetIntegerValue failed, type=%d!\n", type);
129 retcode = SANE_STATUS_IO_ERROR;
130 }
131 else
132 {
133 bug("hpaio: hpaioScannerToSaneError: pmlError=%d.\n", pmlError);
134
135 switch( pmlError )
136 {
137 case PML_UPLOAD_ERROR_SCANNER_JAM:
138 retcode = SANE_STATUS_JAMMED;
139 break;
140
141 case PML_UPLOAD_ERROR_MLC_CHANNEL_CLOSED:
142 case PML_UPLOAD_ERROR_STOPPED_BY_HOST:
143 case PML_UPLOAD_ERROR_STOP_KEY_PRESSED:
144 retcode = SANE_STATUS_CANCELLED;
145 break;
146
147 case PML_UPLOAD_ERROR_NO_DOC_IN_ADF:
148 case PML_UPLOAD_ERROR_DOC_LOADED:
149 retcode = SANE_STATUS_NO_DOCS;
150 break;
151
152 case PML_UPLOAD_ERROR_COVER_OPEN:
153 retcode = SANE_STATUS_COVER_OPEN;
154 break;
155
156 case PML_UPLOAD_ERROR_DEVICE_BUSY:
157 retcode = SANE_STATUS_DEVICE_BUSY;
158 break;
159
160 default:
161 retcode = SANE_STATUS_IO_ERROR;
162 break;
163 }
164 }
165 }
166
167 return retcode;
168 }
169
170
hpaioScannerToSaneStatus(hpaioScanner_t hpaio)171 SANE_Status __attribute__ ((visibility ("hidden"))) hpaioScannerToSaneStatus( hpaioScanner_t hpaio )
172 {
173 SANE_Status retcode;
174
175 int sclStatus;
176
177 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
178 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
179 SCL_INQ_ADF_FEED_STATUS,
180 &sclStatus,
181 0,
182 0 );
183
184 if( retcode == SANE_STATUS_UNSUPPORTED )
185 {
186 retcode = SANE_STATUS_GOOD;
187 }
188 else if( retcode == SANE_STATUS_GOOD )
189 {
190 switch( sclStatus )
191 {
192 case SCL_ADF_FEED_STATUS_OK:
193 retcode = SANE_STATUS_GOOD;
194 break;
195
196 case SCL_ADF_FEED_STATUS_BUSY:
197 /* retcode=SANE_STATUS_DEVICE_BUSY; */
198 retcode = SANE_STATUS_GOOD;
199 break;
200
201 case SCL_ADF_FEED_STATUS_PAPER_JAM:
202 case SCL_ADF_FEED_STATUS_ORIGINAL_ON_GLASS:
203 retcode = SANE_STATUS_JAMMED;
204 break;
205
206 case SCL_ADF_FEED_STATUS_PORTRAIT_FEED:
207 retcode = SANE_STATUS_UNSUPPORTED;
208 break;
209
210 default:
211 retcode = SANE_STATUS_IO_ERROR;
212 break;
213 }
214 }
215
216 return retcode;
217 }
218
hpaioScannerIsUninterruptible(hpaioScanner_t hpaio,int * pUploadState)219 static int hpaioScannerIsUninterruptible( hpaioScanner_t hpaio,
220 int * pUploadState )
221 {
222 int uploadState;
223 if( !pUploadState )
224 {
225 pUploadState = &uploadState;
226 }
227
228 return ( hpaio->scannerType == SCANNER_TYPE_PML &&
229 hpaio->pml.scanDone &&
230 PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid,
231 hpaio->pml.objUploadState ) != ERROR &&
232 PmlGetIntegerValue( hpaio->pml.objUploadState, 0, pUploadState ) != ERROR &&
233 ( *pUploadState == PML_UPLOAD_STATE_START ||
234 *pUploadState == PML_UPLOAD_STATE_ACTIVE ||
235 *pUploadState == PML_UPLOAD_STATE_NEWPAGE ) );
236 }
237
hpaioResetScanner(hpaioScanner_t hpaio)238 static SANE_Status hpaioResetScanner( hpaioScanner_t hpaio )
239 {
240 SANE_Status retcode;
241
242 if( hpaio->scannerType == SCANNER_TYPE_SCL )
243 {
244 retcode = SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_RESET, 0 );
245 if( retcode != SANE_STATUS_GOOD )
246 {
247 return retcode;
248 }
249 sleep(1); /* delay for embeded jetdirect scl scanners (ie: PS 3300, PS C7280, PS C6100) */
250 }
251 else /* if (hpaio->scannerType==SCANNER_TYPE_PML) */
252 {
253 if( !hpaioScannerIsUninterruptible( hpaio, 0 ) )
254 {
255 PmlSetIntegerValue( hpaio->pml.objUploadState,
256 PML_TYPE_ENUMERATION,
257 PML_UPLOAD_STATE_IDLE );
258
259 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
260 hpaio->pml.objUploadState, 0, 0 ) == ERROR )
261 {
262 return SANE_STATUS_IO_ERROR;
263 }
264 }
265
266 /* Clear upload error for the sake of the LaserJet 1100A. */
267 PmlSetIntegerValue( hpaio->pml.objUploadError,
268 PML_TYPE_SIGNED_INTEGER,
269 0 );
270
271 PmlRequestSet( hpaio->deviceid, hpaio->cmd_channelid, hpaio->pml.objUploadError ); /* No retry. */
272 }
273
274 return SANE_STATUS_GOOD;
275 }
276
hpaioPmlAllocate(hpaioScanner_t hpaio)277 static PmlObject_t hpaioPmlAllocate( hpaioScanner_t hpaio )
278 {
279 int size = sizeof( struct PmlObject_s );
280 PmlObject_t obj;
281
282 /* Malloc and zero object. */
283 obj = malloc( size );
284
285 memset( obj, 0, size );
286
287 /* Insert into linked list of PML objects for this device. */
288 if( !hpaio->firstPmlObject )
289 {
290 hpaio->firstPmlObject = obj;
291 }
292 obj->prev = hpaio->lastPmlObject;
293 obj->next = 0;
294 if( hpaio->lastPmlObject )
295 {
296 hpaio->lastPmlObject->next = obj;
297 }
298 hpaio->lastPmlObject = obj;
299
300 return obj;
301 }
302
hpaioPmlAllocateID(hpaioScanner_t hpaio,char * oid)303 static PmlObject_t hpaioPmlAllocateID( hpaioScanner_t hpaio, char * oid )
304 {
305 PmlObject_t obj = hpaioPmlAllocate( hpaio );
306
307 if( !obj )
308 {
309 bug("hpaioPmlAllocateID: out of memory!\n");
310 }
311
312 PmlSetID( obj, oid );
313
314 return obj;
315 }
316
hpaioPmlDeallocateObjects(hpaioScanner_t hpaio)317 static void hpaioPmlDeallocateObjects( hpaioScanner_t hpaio )
318 {
319 PmlObject_t current, next;
320
321 current = hpaio->firstPmlObject;
322
323 while( current )
324 {
325 next = current->next;
326
327 free( current );
328
329 current = next;
330 }
331 }
332
hpaioPmlAllocateObjects(hpaioScanner_t hpaio)333 static SANE_Status hpaioPmlAllocateObjects(hpaioScanner_t hpaio)
334 {
335 /* SNMP oids for PML scanners. */
336 hpaio->pml.objScannerStatus = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.2.1.0" );
337 hpaio->pml.objResolutionRange = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.2.3.0" );
338 hpaio->pml.objUploadTimeout = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.1.1.18.0" );
339 hpaio->pml.objContrast = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.1.0" );
340 hpaio->pml.objResolution = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.2.0" );
341 hpaio->pml.objPixelDataType = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.3.0" );
342 hpaio->pml.objCompression = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.4.0" );
343 hpaio->pml.objCompressionFactor = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.5.0" );
344 hpaio->pml.objUploadError = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.6.0" );
345 hpaio->pml.objUploadState = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.12.0" );
346 hpaio->pml.objAbcThresholds = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.14.0" );
347 hpaio->pml.objSharpeningCoefficient = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.15.0" );
348 hpaio->pml.objNeutralClipThresholds = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.31.0" );
349 hpaio->pml.objToneMap = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.32.0" );
350 hpaio->pml.objCopierReduction = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.5.1.4.0" );
351 hpaio->pml.objScanToken = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.1.1.25.0" );
352 hpaio->pml.objModularHardware = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.2.2.1.75.0" );
353
354 /* Some PML objects for SCL scanners. */
355 hpaio->scl.objSupportedFunctions = hpaioPmlAllocateID( hpaio, "1.3.6.1.4.1.11.2.3.9.4.2.1.1.2.67.0" );
356
357 return SANE_STATUS_GOOD;
358 }
359
hpaioConnClose(hpaioScanner_t hpaio)360 static int hpaioConnClose( hpaioScanner_t hpaio )
361 {
362 if (hpaio->cmd_channelid > 0)
363 hpmud_close_channel(hpaio->deviceid, hpaio->cmd_channelid);
364 hpaio->cmd_channelid = -1;
365 if (hpaio->scan_channelid > 0)
366 hpmud_close_channel(hpaio->deviceid, hpaio->scan_channelid);
367 hpaio->scan_channelid = -1;
368
369 return 0;
370 } // hpaioConnClose()
371
hpaioConnOpen(hpaioScanner_t hpaio)372 static SANE_Status hpaioConnOpen( hpaioScanner_t hpaio )
373 {
374 SANE_Status retcode;
375 enum HPMUD_RESULT stat;
376
377 if (hpaio->scannerType==SCANNER_TYPE_SCL)
378 {
379 stat = hpmud_open_channel(hpaio->deviceid, "HP-SCAN", &hpaio->scan_channelid);
380 if(stat != HPMUD_R_OK)
381 {
382 bug("failed to open scan channel: %s %d\n", __FILE__, __LINE__);
383 retcode = SANE_STATUS_DEVICE_BUSY;
384 goto abort;
385 }
386 }
387
388 stat = hpmud_open_channel(hpaio->deviceid, "HP-MESSAGE", &hpaio->cmd_channelid);
389 if(stat != HPMUD_R_OK)
390 {
391 bug("failed to open pml channel: %s %d\n", __FILE__, __LINE__);
392 retcode = SANE_STATUS_IO_ERROR;
393 goto abort;
394 }
395
396 retcode = SANE_STATUS_GOOD;
397
398 abort:
399 if( retcode != SANE_STATUS_GOOD )
400 {
401 SendScanEvent( hpaio->deviceuri, EVENT_SCANNER_FAIL);
402 }
403 return retcode;
404 }
405
hpaioConnPrepareScan(hpaioScanner_t hpaio)406 static SANE_Status hpaioConnPrepareScan( hpaioScanner_t hpaio )
407 {
408 SANE_Status retcode;
409 int i;
410
411 /* ADF may already have channel(s) open. */
412 if (hpaio->cmd_channelid < 0)
413 {
414 retcode = hpaioConnOpen( hpaio );
415
416 if( retcode != SANE_STATUS_GOOD )
417 {
418 return retcode;
419 }
420 }
421
422 retcode = hpaioResetScanner( hpaio );
423
424 /* Reserve scanner and make sure it got reserved. */
425 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_SET_DEVICE_LOCK, 1 );
426 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
427 SCL_CMD_SET_DEVICE_LOCK_TIMEOUT,
428 SCL_DEVICE_LOCK_TIMEOUT );
429
430 for( i = 0; ; i++ )
431 {
432 char buffer[LEN_SCL_BUFFER];
433 int len, j;
434 struct timeval tv1, tv2;
435 gettimeofday( &tv1, 0 );
436
437 if( SclInquire( hpaio->deviceid, hpaio->scan_channelid,
438 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
439 SCL_INQ_SESSION_ID,
440 &len,
441 buffer,
442 LEN_SCL_BUFFER ) != SANE_STATUS_GOOD )
443 {
444 // break;
445 return SANE_STATUS_IO_ERROR;
446 }
447
448 gettimeofday( &tv2, 0 );
449
450 for( j = 0; j < len && buffer[j] == '0'; j++ ) ;
451
452 if( j < len )
453 {
454 break;
455 }
456
457 if( i >= SCL_PREPARE_SCAN_DEVICE_LOCK_MAX_RETRIES )
458 {
459 return SANE_STATUS_DEVICE_BUSY;
460 }
461
462 DBG(8, "hpaioConnPrepareScan: Waiting for device lock %s %d\n", __FILE__, __LINE__);
463
464 if( ( ( unsigned ) ( tv2.tv_sec - tv1.tv_sec ) ) <= SCL_PREPARE_SCAN_DEVICE_LOCK_DELAY )
465 {
466 sleep( SCL_PREPARE_SCAN_DEVICE_LOCK_DELAY );
467 }
468 }
469
470 SendScanEvent( hpaio->deviceuri, EVENT_START_SCAN_JOB);
471
472 return SANE_STATUS_GOOD;
473 }
474
hpaioConnEndScan(hpaioScanner_t hpaio)475 static void hpaioConnEndScan( hpaioScanner_t hpaio )
476 {
477 hpaioResetScanner( hpaio );
478 hpaioConnClose( hpaio );
479
480 SendScanEvent( hpaio->deviceuri, EVENT_END_SCAN_JOB);
481 }
482
SetResolutionListSCL(hpaioScanner_t hpaio)483 static SANE_Status SetResolutionListSCL(hpaioScanner_t hpaio)
484 {
485 int supported_res[] = {50, 75, 100, 150, 200, 300, 600, 1200, 2400, 4800, 9600};
486 int i, len = sizeof(supported_res)/sizeof(int);
487
488 if (hpaio->currentAdfMode == ADF_MODE_ADF || hpaio->currentAdfMode == ADF_MODE_AUTO)
489 {
490 hpaio->resolutionRange.min = hpaio->scl.minResAdf;
491 hpaio->resolutionRange.max = hpaio->scl.maxResAdf;
492 }
493 else
494 {
495 hpaio->resolutionRange.min = hpaio->scl.minRes;
496 hpaio->resolutionRange.max = hpaio->scl.maxRes;
497 }
498
499 _DBG("currentAdfMode=%d resolutionRange[%d, %d]\n",
500 hpaio->currentAdfMode, hpaio->resolutionRange.min, hpaio->resolutionRange.max);
501
502 NumListClear( hpaio->resolutionList );
503 NumListClear( hpaio->lineartResolutionList );
504 for (i = 0; i < len; i++)
505 {
506 if (supported_res[i] >= hpaio->resolutionRange.min &&
507 supported_res[i] <= hpaio->resolutionRange.max)
508 {
509 NumListAdd (hpaio->resolutionList, supported_res[i]);
510 NumListAdd (hpaio->lineartResolutionList, supported_res[i]);
511 }
512 }
513 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
514
515 return SANE_STATUS_GOOD;
516 }
517
hpaioSetDefaultValue(hpaioScanner_t hpaio,int option)518 static SANE_Status hpaioSetDefaultValue( hpaioScanner_t hpaio, int option )
519 {
520 switch( option )
521 {
522 case OPTION_SCAN_MODE:
523 if( hpaio->supportsScanMode[SCAN_MODE_COLOR] )
524 {
525 hpaio->currentScanMode = SCAN_MODE_COLOR;
526 }
527 else if( hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] )
528 {
529 hpaio->currentScanMode = SCAN_MODE_GRAYSCALE;
530 }
531 else /* if (hpaio->supportsScanMode[SCAN_MODE_LINEART]) */
532 {
533 hpaio->currentScanMode = SCAN_MODE_LINEART;
534 }
535 break;
536
537 case OPTION_SCAN_RESOLUTION:
538 if( hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type == SANE_CONSTRAINT_WORD_LIST )
539 {
540 hpaio->currentResolution = NumListGetFirst( ( SANE_Int * )
541 hpaio->option[OPTION_SCAN_RESOLUTION].constraint.word_list );
542 }
543 else
544 {
545 hpaio->currentResolution = hpaio->resolutionRange.min;
546 }
547 break;
548
549 case OPTION_CONTRAST:
550 hpaio->currentContrast = hpaio->defaultContrast;
551 break;
552 case OPTION_BRIGHTNESS:
553 hpaio->currentBrightness = hpaio->defaultBrightness;
554 break;
555
556 case OPTION_COMPRESSION:
557 {
558 int supportedCompression = hpaio->supportsScanMode[hpaio->currentScanMode];
559 int defaultCompression = hpaio->defaultCompression[hpaio->currentScanMode];
560
561 if( supportedCompression & defaultCompression )
562 {
563 hpaio->currentCompression = defaultCompression;
564 }
565 else if( supportedCompression & COMPRESSION_JPEG )
566 {
567 hpaio->currentCompression = COMPRESSION_JPEG;
568 }
569 else if( supportedCompression & COMPRESSION_MH )
570 {
571 hpaio->currentCompression = COMPRESSION_MH;
572 }
573 else if( supportedCompression & COMPRESSION_MR )
574 {
575 hpaio->currentCompression = COMPRESSION_MR;
576 }
577 else if( supportedCompression & COMPRESSION_MMR )
578 {
579 hpaio->currentCompression = COMPRESSION_MMR;
580 }
581 else
582 {
583 hpaio->currentCompression = COMPRESSION_NONE;
584 }
585 }
586 break;
587
588 case OPTION_JPEG_COMPRESSION_FACTOR:
589 hpaio->currentJpegCompressionFactor = hpaio->defaultJpegCompressionFactor;
590 break;
591
592 case OPTION_BATCH_SCAN:
593 hpaio->currentBatchScan = SANE_FALSE;
594 break;
595
596 case OPTION_ADF_MODE:
597 if( hpaio->supportedAdfModes & ADF_MODE_AUTO )
598 {
599 if( hpaio->scannerType == SCANNER_TYPE_PML &&
600 !hpaio->pml.flatbedCapability &&
601 hpaio->supportedAdfModes & ADF_MODE_ADF )
602 {
603 goto defaultToAdf;
604 }
605 hpaio->currentAdfMode = ADF_MODE_AUTO;
606 }
607 else if( hpaio->supportedAdfModes & ADF_MODE_FLATBED )
608 {
609 hpaio->currentAdfMode = ADF_MODE_FLATBED;
610 }
611 else if( hpaio->supportedAdfModes & ADF_MODE_ADF )
612 {
613 defaultToAdf:
614 hpaio->currentAdfMode = ADF_MODE_ADF;
615 }
616 else
617 {
618 hpaio->currentAdfMode = ADF_MODE_AUTO;
619 }
620 break;
621 #if 1
622 case OPTION_DUPLEX:
623 hpaio->currentDuplex = SANE_FALSE;
624 break;
625 #endif
626 case OPTION_LENGTH_MEASUREMENT:
627 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_PADDED;
628 break;
629
630 case OPTION_TL_X:
631 hpaio->currentTlx = hpaio->tlxRange.min;
632 break;
633
634 case OPTION_TL_Y:
635 hpaio->currentTly = hpaio->tlyRange.min;
636 break;
637
638 case OPTION_BR_X:
639 hpaio->currentBrx = hpaio->brxRange.max;
640 break;
641
642 case OPTION_BR_Y:
643 hpaio->currentBry = hpaio->bryRange.max;
644 break;
645
646 default:
647 return SANE_STATUS_INVAL;
648 }
649
650 return SANE_STATUS_GOOD;
651 }
652
hpaioUpdateDescriptors(hpaioScanner_t hpaio,int option)653 static int hpaioUpdateDescriptors( hpaioScanner_t hpaio, int option )
654 {
655 int initValues = ( option == OPTION_FIRST );
656 int reload = 0;
657
658 /* OPTION_SCAN_MODE: */
659 if( initValues )
660 {
661 StrListClear( hpaio->scanModeList );
662 if( hpaio->supportsScanMode[SCAN_MODE_LINEART] )
663 {
664 StrListAdd( hpaio->scanModeList, SANE_VALUE_SCAN_MODE_LINEART );
665 }
666 if( hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] )
667 {
668 StrListAdd( hpaio->scanModeList, SANE_VALUE_SCAN_MODE_GRAY );
669 }
670 if( hpaio->supportsScanMode[SCAN_MODE_COLOR] )
671 {
672 StrListAdd( hpaio->scanModeList, SANE_VALUE_SCAN_MODE_COLOR );
673 }
674 hpaioSetDefaultValue( hpaio, OPTION_SCAN_MODE );
675 reload |= SANE_INFO_RELOAD_OPTIONS;
676 reload |= SANE_INFO_RELOAD_PARAMS;
677 }
678 else if( option == OPTION_SCAN_MODE )
679 {
680 reload |= SANE_INFO_RELOAD_PARAMS;
681 }
682
683 if (hpaio->scannerType == SCANNER_TYPE_SCL)
684 SetResolutionListSCL(hpaio);
685
686 /* OPTION_SCAN_RESOLUTION: */
687 if( hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type ==
688 SANE_CONSTRAINT_WORD_LIST )
689 {
690 SANE_Int ** pList = ( SANE_Int ** ) &hpaio->option[OPTION_SCAN_RESOLUTION].constraint.word_list;
691
692 if( hpaio->currentScanMode == SCAN_MODE_LINEART )
693 {
694 if( *pList != hpaio->lineartResolutionList )
695 {
696 *pList = hpaio->lineartResolutionList;
697 reload |= SANE_INFO_RELOAD_OPTIONS;
698 }
699 }
700 else
701 {
702 if( *pList != hpaio->resolutionList )
703 {
704 *pList = hpaio->resolutionList;
705 reload |= SANE_INFO_RELOAD_OPTIONS;
706 }
707 }
708 if( initValues || !NumListIsInList( *pList,
709 hpaio->currentResolution ) )
710 {
711 hpaioSetDefaultValue( hpaio, OPTION_SCAN_RESOLUTION );
712 reload |= SANE_INFO_RELOAD_OPTIONS;
713 reload |= SANE_INFO_RELOAD_PARAMS;
714 }
715 }
716 else
717 {
718 if( initValues ||
719 hpaio->currentResolution<hpaio->resolutionRange.min ||
720 hpaio->currentResolution>hpaio->resolutionRange.max )
721 {
722 hpaioSetDefaultValue( hpaio, OPTION_SCAN_RESOLUTION );
723 reload |= SANE_INFO_RELOAD_OPTIONS;
724 reload |= SANE_INFO_RELOAD_PARAMS;
725 }
726 }
727 if( option == OPTION_SCAN_RESOLUTION )
728 {
729 reload |= SANE_INFO_RELOAD_PARAMS;
730 }
731
732 /* OPTION_CONTRAST, OPTION_BRIGHTNESS */
733 if( initValues )
734 {
735 hpaioSetDefaultValue( hpaio, OPTION_CONTRAST );
736 hpaioSetDefaultValue (hpaio, OPTION_BRIGHTNESS);
737 reload |= SANE_INFO_RELOAD_OPTIONS;
738 }
739
740 /* OPTION_COMPRESSION: */
741 {
742 int supportedCompression = hpaio->supportsScanMode[hpaio->currentScanMode];
743 if( initValues ||
744 !( supportedCompression & hpaio->currentCompression ) ||
745 ( ( ( supportedCompression & COMPRESSION_NONE ) != 0 ) !=
746 ( StrListIsInList( hpaio->compressionList,
747 STR_COMPRESSION_NONE ) != 0 ) ) ||
748 ( ( ( supportedCompression & COMPRESSION_MH ) != 0 ) !=
749 ( StrListIsInList( hpaio->compressionList,
750 STR_COMPRESSION_MH ) != 0 ) ) ||
751 ( ( ( supportedCompression & COMPRESSION_MR ) != 0 ) !=
752 ( StrListIsInList( hpaio->compressionList,
753 STR_COMPRESSION_MR ) != 0 ) ) ||
754 ( ( ( supportedCompression & COMPRESSION_MMR ) != 0 ) !=
755 ( StrListIsInList( hpaio->compressionList,
756 STR_COMPRESSION_MMR ) != 0 ) ) ||
757 ( ( ( supportedCompression & COMPRESSION_JPEG ) != 0 ) !=
758 ( StrListIsInList( hpaio->compressionList,
759 STR_COMPRESSION_JPEG ) != 0 ) ) )
760 {
761 StrListClear( hpaio->compressionList );
762 if( supportedCompression & COMPRESSION_NONE )
763 {
764 StrListAdd( hpaio->compressionList, STR_COMPRESSION_NONE );
765 }
766 if( supportedCompression & COMPRESSION_MH )
767 {
768 StrListAdd( hpaio->compressionList, STR_COMPRESSION_MH );
769 }
770 if( supportedCompression & COMPRESSION_MR )
771 {
772 StrListAdd( hpaio->compressionList, STR_COMPRESSION_MR );
773 }
774 if( supportedCompression & COMPRESSION_MMR )
775 {
776 StrListAdd( hpaio->compressionList, STR_COMPRESSION_MMR );
777 }
778 if( supportedCompression & COMPRESSION_JPEG )
779 {
780 StrListAdd( hpaio->compressionList, STR_COMPRESSION_JPEG );
781 }
782 hpaioSetDefaultValue( hpaio, OPTION_COMPRESSION );
783 reload |= SANE_INFO_RELOAD_OPTIONS;
784 }
785 }
786
787 /* OPTION_JPEG_COMPRESSION_FACTOR: */
788 if( initValues ||
789 ( ( hpaio->currentCompression == COMPRESSION_JPEG ) !=
790 ( ( hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap & SANE_CAP_INACTIVE ) == 0 ) ) )
791 {
792 if( hpaio->currentCompression == COMPRESSION_JPEG )
793 {
794 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap &= ~SANE_CAP_INACTIVE;
795 }
796 else
797 {
798 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap |= SANE_CAP_INACTIVE;
799 }
800 hpaioSetDefaultValue( hpaio, OPTION_JPEG_COMPRESSION_FACTOR );
801 reload |= SANE_INFO_RELOAD_OPTIONS;
802 }
803
804 /* OPTION_BATCH_SCAN: */
805 if( initValues )
806 {
807 hpaioSetDefaultValue( hpaio, OPTION_BATCH_SCAN );
808 if( hpaio->preDenali )
809 {
810 hpaio->option[OPTION_BATCH_SCAN].cap |= SANE_CAP_INACTIVE;
811 }
812 reload |= SANE_INFO_RELOAD_OPTIONS;
813 }
814 if( !hpaio->currentBatchScan )
815 {
816 hpaio->noDocsConditionPending = 0;
817 }
818
819 /* OPTION_ADF_MODE: */
820 if( initValues )
821 {
822 StrListClear( hpaio->adfModeList );
823 if( hpaio->supportedAdfModes & ADF_MODE_AUTO )
824 {
825 StrListAdd( hpaio->adfModeList, STR_ADF_MODE_AUTO );
826 }
827 if( hpaio->supportedAdfModes & ADF_MODE_FLATBED )
828 {
829 StrListAdd( hpaio->adfModeList, STR_ADF_MODE_FLATBED );
830 }
831 if( hpaio->supportedAdfModes & ADF_MODE_ADF )
832 {
833 StrListAdd( hpaio->adfModeList, STR_ADF_MODE_ADF );
834 }
835 hpaioSetDefaultValue( hpaio, OPTION_ADF_MODE );
836 reload |= SANE_INFO_RELOAD_OPTIONS;
837 }
838
839 #if 1
840 /* OPTION_DUPLEX: */
841 if( initValues ||
842 ( ( hpaio->supportsDuplex &&
843 hpaio->currentAdfMode != ADF_MODE_FLATBED ) !=
844 ( ( hpaio->option[OPTION_DUPLEX].cap & SANE_CAP_INACTIVE ) == 0 ) ) )
845 {
846 if( hpaio->supportsDuplex &&
847 hpaio->currentAdfMode != ADF_MODE_FLATBED )
848 {
849 hpaio->option[OPTION_DUPLEX].cap &= ~SANE_CAP_INACTIVE;
850 }
851 else
852 {
853 hpaio->option[OPTION_DUPLEX].cap |= SANE_CAP_INACTIVE;
854 }
855 hpaioSetDefaultValue( hpaio, OPTION_DUPLEX );
856 reload |= SANE_INFO_RELOAD_OPTIONS;
857 }
858 #endif
859
860 /* OPTION_LENGTH_MEASUREMENT: */
861 if( initValues )
862 {
863 hpaioSetDefaultValue( hpaio, OPTION_LENGTH_MEASUREMENT );
864 StrListClear( hpaio->lengthMeasurementList );
865 StrListAdd( hpaio->lengthMeasurementList,
866 STR_LENGTH_MEASUREMENT_UNKNOWN );
867 if( hpaio->scannerType == SCANNER_TYPE_PML )
868 {
869 StrListAdd( hpaio->lengthMeasurementList,
870 STR_LENGTH_MEASUREMENT_UNLIMITED );
871 }
872 StrListAdd( hpaio->lengthMeasurementList,
873 STR_LENGTH_MEASUREMENT_APPROXIMATE );
874 StrListAdd( hpaio->lengthMeasurementList,
875 STR_LENGTH_MEASUREMENT_PADDED );
876 /* TODO: hpaioStrListAdd(hpaio->lengthMeasurementList,
877 STR_LENGTH_MEASUREMENT_EXACT); */
878 }
879
880 /* OPTION_TL_X, OPTION_TL_Y, OPTION_BR_X, OPTION_BR_Y: */
881 if( initValues )
882 {
883 hpaioSetDefaultValue( hpaio, OPTION_TL_X );
884 hpaioSetDefaultValue( hpaio, OPTION_TL_Y );
885 hpaioSetDefaultValue( hpaio, OPTION_BR_X );
886 hpaioSetDefaultValue( hpaio, OPTION_BR_Y );
887 reload |= SANE_INFO_RELOAD_OPTIONS;
888 goto processGeometry;
889 }
890 else if( option == OPTION_TL_X ||
891 option == OPTION_TL_Y ||
892 option == OPTION_BR_X ||
893 option == OPTION_BR_Y )
894 {
895 processGeometry : hpaio->effectiveTlx = hpaio->currentTlx;
896 hpaio->effectiveBrx = hpaio->currentBrx;
897 FIX_GEOMETRY( hpaio->effectiveTlx,
898 hpaio->effectiveBrx,
899 hpaio->brxRange.min,
900 hpaio->brxRange.max );
901 hpaio->effectiveTly = hpaio->currentTly;
902 hpaio->effectiveBry = hpaio->currentBry;
903 FIX_GEOMETRY( hpaio->effectiveTly,
904 hpaio->effectiveBry,
905 hpaio->bryRange.min,
906 hpaio->bryRange.max );
907 reload |= SANE_INFO_RELOAD_PARAMS;
908 }
909 if( ( hpaio->currentLengthMeasurement != LENGTH_MEASUREMENT_UNLIMITED ) !=
910 ( ( hpaio->option[OPTION_BR_Y].cap & SANE_CAP_INACTIVE ) == 0 ) )
911 {
912 if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_UNLIMITED )
913 {
914 hpaio->option[OPTION_BR_Y].cap |= SANE_CAP_INACTIVE;
915 }
916 else
917 {
918 hpaio->option[OPTION_BR_Y].cap &= ~SANE_CAP_INACTIVE;
919 }
920 reload |= SANE_INFO_RELOAD_OPTIONS;
921 }
922
923 /* Pre-scan parameters: */
924 if( reload & SANE_INFO_RELOAD_PARAMS )
925 {
926 switch( hpaio->currentScanMode )
927 {
928 case SCAN_MODE_LINEART:
929 hpaio->prescanParameters.format = SANE_FRAME_GRAY;
930 hpaio->prescanParameters.depth = 1;
931 break;
932
933 case SCAN_MODE_GRAYSCALE:
934 hpaio->prescanParameters.format = SANE_FRAME_GRAY;
935 hpaio->prescanParameters.depth = 8;
936 break;
937
938 case SCAN_MODE_COLOR:
939 default:
940 hpaio->prescanParameters.format = SANE_FRAME_RGB;
941 hpaio->prescanParameters.depth = 8;
942 break;
943 }
944 hpaio->prescanParameters.last_frame = SANE_TRUE;
945
946
947 hpaio->prescanParameters.lines = MILLIMETERS_TO_PIXELS( hpaio->effectiveBry - hpaio->effectiveTly,
948 hpaio->currentResolution );
949
950 hpaio->prescanParameters.pixels_per_line = MILLIMETERS_TO_PIXELS( hpaio->effectiveBrx - hpaio->effectiveTlx,
951 hpaio->currentResolution );
952
953 hpaio->prescanParameters.bytes_per_line = BYTES_PER_LINE( hpaio->prescanParameters.pixels_per_line,
954 hpaio->prescanParameters.depth * ( hpaio->prescanParameters.format ==
955 SANE_FRAME_RGB ?
956 3 :
957 1 ) );
958 }
959
960 return reload;
961 }
962
init_options(hpaioScanner_t hpaio)963 static void init_options( hpaioScanner_t hpaio )
964 {
965 hpaio->option[OPTION_NUM_OPTIONS].name = SANE_NAME_NUM_OPTIONS;
966 hpaio->option[OPTION_NUM_OPTIONS].title = SANE_TITLE_NUM_OPTIONS;
967 hpaio->option[OPTION_NUM_OPTIONS].desc = SANE_DESC_NUM_OPTIONS;
968 hpaio->option[OPTION_NUM_OPTIONS].type = SANE_TYPE_INT;
969 hpaio->option[OPTION_NUM_OPTIONS].unit = SANE_UNIT_NONE;
970 hpaio->option[OPTION_NUM_OPTIONS].size = sizeof( SANE_Int );
971 hpaio->option[OPTION_NUM_OPTIONS].cap = SANE_CAP_SOFT_DETECT;
972 hpaio->option[OPTION_NUM_OPTIONS].constraint_type = SANE_CONSTRAINT_NONE;
973
974 hpaio->option[GROUP_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
975 hpaio->option[GROUP_SCAN_MODE].type = SANE_TYPE_GROUP;
976
977 hpaio->option[OPTION_SCAN_MODE].name = SANE_NAME_SCAN_MODE;
978 hpaio->option[OPTION_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
979 hpaio->option[OPTION_SCAN_MODE].desc = SANE_DESC_SCAN_MODE;
980 hpaio->option[OPTION_SCAN_MODE].type = SANE_TYPE_STRING;
981 hpaio->option[OPTION_SCAN_MODE].unit = SANE_UNIT_NONE;
982 hpaio->option[OPTION_SCAN_MODE].size = LEN_STRING_OPTION_VALUE;
983 hpaio->option[OPTION_SCAN_MODE].cap = SANE_CAP_SOFT_SELECT |
984 SANE_CAP_SOFT_DETECT;
985 hpaio->option[OPTION_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
986 hpaio->option[OPTION_SCAN_MODE].constraint.string_list = hpaio->scanModeList;
987
988 hpaio->option[OPTION_SCAN_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
989 hpaio->option[OPTION_SCAN_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
990 hpaio->option[OPTION_SCAN_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
991 hpaio->option[OPTION_SCAN_RESOLUTION].type = SANE_TYPE_INT;
992 hpaio->option[OPTION_SCAN_RESOLUTION].unit = SANE_UNIT_DPI;
993 hpaio->option[OPTION_SCAN_RESOLUTION].size = sizeof( SANE_Int );
994 hpaio->option[OPTION_SCAN_RESOLUTION].cap = SANE_CAP_SOFT_SELECT |
995 SANE_CAP_SOFT_DETECT;
996 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
997 hpaio->option[OPTION_SCAN_RESOLUTION].constraint.range = &hpaio->resolutionRange;
998 hpaio->resolutionRange.quant = 0;
999
1000 hpaio->option[GROUP_ADVANCED].title = STR_TITLE_ADVANCED;
1001 hpaio->option[GROUP_ADVANCED].type = SANE_TYPE_GROUP;
1002 hpaio->option[GROUP_ADVANCED].cap = SANE_CAP_ADVANCED;
1003
1004 hpaio->option[OPTION_CONTRAST].name = SANE_NAME_CONTRAST;
1005 hpaio->option[OPTION_CONTRAST].title = SANE_TITLE_CONTRAST;
1006 hpaio->option[OPTION_CONTRAST].desc = SANE_DESC_CONTRAST;
1007 hpaio->option[OPTION_CONTRAST].type = SANE_TYPE_INT;
1008 hpaio->option[OPTION_CONTRAST].unit = SANE_UNIT_NONE;
1009 hpaio->option[OPTION_CONTRAST].size = sizeof( SANE_Int );
1010 hpaio->option[OPTION_CONTRAST].cap = SANE_CAP_SOFT_SELECT |
1011 SANE_CAP_SOFT_DETECT |
1012 SANE_CAP_ADVANCED;
1013 hpaio->option[OPTION_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
1014 hpaio->option[OPTION_CONTRAST].constraint.range = &hpaio->contrastRange;
1015 hpaio->contrastRange.min = PML_CONTRAST_MIN;
1016 hpaio->contrastRange.max = PML_CONTRAST_MAX;
1017 hpaio->contrastRange.quant = 0;
1018 hpaio->defaultContrast = PML_CONTRAST_DEFAULT;
1019
1020 hpaio->option[OPTION_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
1021 hpaio->option[OPTION_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
1022 hpaio->option[OPTION_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
1023 hpaio->option[OPTION_BRIGHTNESS].type = SANE_TYPE_INT;
1024 hpaio->option[OPTION_BRIGHTNESS].unit = SANE_UNIT_NONE;
1025 hpaio->option[OPTION_BRIGHTNESS].size = sizeof( SANE_Int );
1026 hpaio->option[OPTION_BRIGHTNESS].cap = SANE_CAP_SOFT_SELECT |
1027 SANE_CAP_SOFT_DETECT |
1028 SANE_CAP_ADVANCED;
1029 hpaio->option[OPTION_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
1030 hpaio->option[OPTION_BRIGHTNESS].constraint.range = &hpaio->brightnessRange;
1031 hpaio->brightnessRange.min = PML_BRIGHTNESS_MIN;
1032 hpaio->brightnessRange.max = PML_BRIGHTNESS_MAX;
1033 hpaio->brightnessRange.quant = 0;
1034 hpaio->defaultBrightness = PML_BRIGHTNESS_DEFAULT;
1035
1036 hpaio->option[OPTION_COMPRESSION].name = STR_NAME_COMPRESSION;
1037 hpaio->option[OPTION_COMPRESSION].title = STR_TITLE_COMPRESSION;
1038 hpaio->option[OPTION_COMPRESSION].desc = STR_DESC_COMPRESSION;
1039 hpaio->option[OPTION_COMPRESSION].type = SANE_TYPE_STRING;
1040 hpaio->option[OPTION_COMPRESSION].unit = SANE_UNIT_NONE;
1041 hpaio->option[OPTION_COMPRESSION].size = LEN_STRING_OPTION_VALUE;
1042 hpaio->option[OPTION_COMPRESSION].cap = SANE_CAP_SOFT_SELECT |
1043 SANE_CAP_SOFT_DETECT |
1044 SANE_CAP_ADVANCED;
1045 hpaio->option[OPTION_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1046 hpaio->option[OPTION_COMPRESSION].constraint.string_list = hpaio->compressionList;
1047
1048 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].name = STR_NAME_JPEG_QUALITY;
1049 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].title = STR_TITLE_JPEG_QUALITY;
1050 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].desc = STR_DESC_JPEG_QUALITY;
1051 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].type = SANE_TYPE_INT;
1052 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].unit = SANE_UNIT_NONE;
1053 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].size = sizeof( SANE_Int );
1054 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap = SANE_CAP_SOFT_SELECT |
1055 SANE_CAP_SOFT_DETECT |
1056 SANE_CAP_ADVANCED;
1057 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].constraint_type = SANE_CONSTRAINT_RANGE;
1058 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].constraint.range = &hpaio->jpegCompressionFactorRange;
1059 hpaio->jpegCompressionFactorRange.min = MIN_JPEG_COMPRESSION_FACTOR;
1060 hpaio->jpegCompressionFactorRange.max = MAX_JPEG_COMPRESSION_FACTOR;
1061 hpaio->jpegCompressionFactorRange.quant = 0;
1062 hpaio->defaultJpegCompressionFactor = SAFER_JPEG_COMPRESSION_FACTOR;
1063
1064 hpaio->option[OPTION_BATCH_SCAN].name = STR_NAME_BATCH_SCAN;
1065 hpaio->option[OPTION_BATCH_SCAN].title = STR_TITLE_BATCH_SCAN;
1066 hpaio->option[OPTION_BATCH_SCAN].desc = STR_DESC_BATCH_SCAN;
1067 hpaio->option[OPTION_BATCH_SCAN].type = SANE_TYPE_BOOL;
1068 hpaio->option[OPTION_BATCH_SCAN].unit = SANE_UNIT_NONE;
1069 hpaio->option[OPTION_BATCH_SCAN].size = sizeof( SANE_Bool );
1070 hpaio->option[OPTION_BATCH_SCAN].cap = SANE_CAP_SOFT_SELECT |
1071 SANE_CAP_SOFT_DETECT |
1072 SANE_CAP_ADVANCED;
1073 hpaio->option[OPTION_BATCH_SCAN].constraint_type = SANE_CONSTRAINT_NONE;
1074
1075 hpaio->option[OPTION_ADF_MODE].name = SANE_NAME_SCAN_SOURCE; // xsane expects this.
1076 hpaio->option[OPTION_ADF_MODE].title = SANE_TITLE_SCAN_SOURCE;
1077 hpaio->option[OPTION_ADF_MODE].desc = SANE_DESC_SCAN_SOURCE;
1078 hpaio->option[OPTION_ADF_MODE].type = SANE_TYPE_STRING;
1079 hpaio->option[OPTION_ADF_MODE].unit = SANE_UNIT_NONE;
1080 hpaio->option[OPTION_ADF_MODE].size = LEN_STRING_OPTION_VALUE;
1081 hpaio->option[OPTION_ADF_MODE].cap = SANE_CAP_SOFT_SELECT |
1082 SANE_CAP_SOFT_DETECT |
1083 SANE_CAP_ADVANCED;
1084 hpaio->option[OPTION_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1085 hpaio->option[OPTION_ADF_MODE].constraint.string_list = hpaio->adfModeList;
1086
1087 // Duplex scanning is supported
1088 if (hpaio->supportsDuplex == 1)
1089 {
1090 hpaio->option[OPTION_DUPLEX].name = STR_NAME_DUPLEX;
1091 hpaio->option[OPTION_DUPLEX].title = STR_TITLE_DUPLEX;
1092 hpaio->option[OPTION_DUPLEX].desc = STR_DESC_DUPLEX;
1093 hpaio->option[OPTION_DUPLEX].type = SANE_TYPE_BOOL;
1094 hpaio->option[OPTION_DUPLEX].unit = SANE_UNIT_NONE;
1095 hpaio->option[OPTION_DUPLEX].size = sizeof( SANE_Bool );
1096 hpaio->option[OPTION_DUPLEX].cap = SANE_CAP_SOFT_SELECT |
1097 SANE_CAP_SOFT_DETECT |
1098 SANE_CAP_ADVANCED;
1099 hpaio->option[OPTION_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE;
1100 }
1101 hpaio->option[GROUP_GEOMETRY].title = STR_TITLE_GEOMETRY;
1102 hpaio->option[GROUP_GEOMETRY].type = SANE_TYPE_GROUP;
1103 hpaio->option[GROUP_GEOMETRY].cap = SANE_CAP_ADVANCED;
1104
1105 hpaio->option[OPTION_LENGTH_MEASUREMENT].name = STR_NAME_LENGTH_MEASUREMENT;
1106 hpaio->option[OPTION_LENGTH_MEASUREMENT].title = STR_TITLE_LENGTH_MEASUREMENT;
1107 hpaio->option[OPTION_LENGTH_MEASUREMENT].desc = STR_DESC_LENGTH_MEASUREMENT;
1108 hpaio->option[OPTION_LENGTH_MEASUREMENT].type = SANE_TYPE_STRING;
1109 hpaio->option[OPTION_LENGTH_MEASUREMENT].unit = SANE_UNIT_NONE;
1110 hpaio->option[OPTION_LENGTH_MEASUREMENT].size = LEN_STRING_OPTION_VALUE;
1111 hpaio->option[OPTION_LENGTH_MEASUREMENT].cap = SANE_CAP_SOFT_SELECT |
1112 SANE_CAP_SOFT_DETECT |
1113 SANE_CAP_ADVANCED;
1114 hpaio->option[OPTION_LENGTH_MEASUREMENT].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1115 hpaio->option[OPTION_LENGTH_MEASUREMENT].constraint.string_list = hpaio->lengthMeasurementList;
1116
1117 hpaio->option[OPTION_TL_X].name = SANE_NAME_SCAN_TL_X;
1118 hpaio->option[OPTION_TL_X].title = SANE_TITLE_SCAN_TL_X;
1119 hpaio->option[OPTION_TL_X].desc = SANE_DESC_SCAN_TL_X;
1120 hpaio->option[OPTION_TL_X].type = GEOMETRY_OPTION_TYPE;
1121 hpaio->option[OPTION_TL_X].unit = SANE_UNIT_MM;
1122 hpaio->option[OPTION_TL_X].size = sizeof( SANE_Int );
1123 hpaio->option[OPTION_TL_X].cap = SANE_CAP_SOFT_SELECT |
1124 SANE_CAP_SOFT_DETECT;
1125 hpaio->option[OPTION_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
1126 hpaio->option[OPTION_TL_X].constraint.range = &hpaio->tlxRange;
1127 hpaio->tlxRange.min = 0;
1128 hpaio->tlxRange.quant = 0;
1129
1130 hpaio->option[OPTION_TL_Y].name = SANE_NAME_SCAN_TL_Y;
1131 hpaio->option[OPTION_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
1132 hpaio->option[OPTION_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
1133 hpaio->option[OPTION_TL_Y].type = GEOMETRY_OPTION_TYPE;
1134 hpaio->option[OPTION_TL_Y].unit = SANE_UNIT_MM;
1135 hpaio->option[OPTION_TL_Y].size = sizeof( SANE_Int );
1136 hpaio->option[OPTION_TL_Y].cap = SANE_CAP_SOFT_SELECT |
1137 SANE_CAP_SOFT_DETECT;
1138 hpaio->option[OPTION_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1139 hpaio->option[OPTION_TL_Y].constraint.range = &hpaio->tlyRange;
1140 hpaio->tlyRange.min = 0;
1141 hpaio->tlyRange.quant = 0;
1142
1143 hpaio->option[OPTION_BR_X].name = SANE_NAME_SCAN_BR_X;
1144 hpaio->option[OPTION_BR_X].title = SANE_TITLE_SCAN_BR_X;
1145 hpaio->option[OPTION_BR_X].desc = SANE_DESC_SCAN_BR_X;
1146 hpaio->option[OPTION_BR_X].type = GEOMETRY_OPTION_TYPE;
1147 hpaio->option[OPTION_BR_X].unit = SANE_UNIT_MM;
1148 hpaio->option[OPTION_BR_X].size = sizeof( SANE_Int );
1149 hpaio->option[OPTION_BR_X].cap = SANE_CAP_SOFT_SELECT |
1150 SANE_CAP_SOFT_DETECT;
1151 hpaio->option[OPTION_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
1152 hpaio->option[OPTION_BR_X].constraint.range = &hpaio->brxRange;
1153 hpaio->brxRange.min = 0;
1154 hpaio->brxRange.quant = 0;
1155
1156 hpaio->option[OPTION_BR_Y].name = SANE_NAME_SCAN_BR_Y;
1157 hpaio->option[OPTION_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
1158 hpaio->option[OPTION_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
1159 hpaio->option[OPTION_BR_Y].type = GEOMETRY_OPTION_TYPE;
1160 hpaio->option[OPTION_BR_Y].unit = SANE_UNIT_MM;
1161 hpaio->option[OPTION_BR_Y].size = sizeof( SANE_Int );
1162 hpaio->option[OPTION_BR_Y].cap = SANE_CAP_SOFT_SELECT |
1163 SANE_CAP_SOFT_DETECT;
1164 hpaio->option[OPTION_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1165 hpaio->option[OPTION_BR_Y].constraint.range = &hpaio->bryRange;
1166 hpaio->bryRange.min = 0;
1167 hpaio->bryRange.quant = 0;
1168 }
1169
hpaioSclSendCommandCheckError(hpaioScanner_t hpaio,int cmd,int param)1170 static int hpaioSclSendCommandCheckError( hpaioScanner_t hpaio, int cmd, int param )
1171 {
1172 SANE_Status retcode;
1173
1174 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_CLEAR_ERROR_STACK, 0 );
1175
1176 retcode = SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, cmd, param );
1177
1178 if( retcode == SANE_STATUS_GOOD &&
1179 ( ( cmd != SCL_CMD_CHANGE_DOCUMENT && cmd != SCL_CMD_UNLOAD_DOCUMENT ) ||
1180 hpaio->beforeScan ) )
1181 {
1182 retcode = hpaioScannerToSaneError( hpaio );
1183 }
1184
1185 return retcode;
1186 }
1187
hpaioProgramOptions(hpaioScanner_t hpaio)1188 static SANE_Status hpaioProgramOptions( hpaioScanner_t hpaio )
1189 {
1190 int bytes_wrote;
1191
1192 hpaio->effectiveScanMode = hpaio->currentScanMode;
1193 hpaio->effectiveResolution = hpaio->currentResolution;
1194
1195 /* Set output data type and width. */
1196 switch( hpaio->currentScanMode )
1197 {
1198 case SCAN_MODE_LINEART:
1199 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1200 SCL_CMD_SET_OUTPUT_DATA_TYPE,
1201 SCL_DATA_TYPE_LINEART );
1202 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1203 SCL_CMD_SET_DATA_WIDTH,
1204 SCL_DATA_WIDTH_LINEART );
1205 break;
1206
1207 case SCAN_MODE_GRAYSCALE:
1208 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1209 SCL_CMD_SET_OUTPUT_DATA_TYPE,
1210 SCL_DATA_TYPE_GRAYSCALE );
1211 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1212 SCL_CMD_SET_DATA_WIDTH,
1213 SCL_DATA_WIDTH_GRAYSCALE );
1214 break;
1215
1216 case SCAN_MODE_COLOR:
1217 default:
1218 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1219 SCL_CMD_SET_OUTPUT_DATA_TYPE,
1220 SCL_DATA_TYPE_COLOR );
1221 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1222 SCL_CMD_SET_DATA_WIDTH,
1223 SCL_DATA_WIDTH_COLOR );
1224 break;
1225 }
1226
1227 /* Set MFPDTF. */
1228 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1229 SCL_CMD_SET_MFPDTF,
1230 hpaio->mfpdtf ? SCL_MFPDTF_ON : SCL_MFPDTF_OFF );
1231
1232 /* Set compression. */
1233 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1234 SCL_CMD_SET_COMPRESSION,
1235 ( hpaio->currentCompression ==
1236 COMPRESSION_JPEG ? SCL_COMPRESSION_JPEG : SCL_COMPRESSION_NONE ) );
1237
1238 /* Set JPEG compression factor. */
1239 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1240 SCL_CMD_SET_JPEG_COMPRESSION_FACTOR,
1241 hpaio->currentJpegCompressionFactor );
1242
1243 /* Set X and Y resolution. */
1244 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1245 SCL_CMD_SET_X_RESOLUTION,
1246 hpaio->currentResolution );
1247
1248 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1249 SCL_CMD_SET_Y_RESOLUTION,
1250 hpaio->currentResolution );
1251
1252 /* Set X and Y position and extent. */
1253 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1254 SCL_CMD_SET_X_POSITION,
1255 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveTlx ) );
1256
1257 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1258 SCL_CMD_SET_Y_POSITION,
1259 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveTly ) );
1260
1261 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1262 SCL_CMD_SET_X_EXTENT,
1263 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveBrx -
1264 hpaio->effectiveTlx ) );
1265
1266 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1267 SCL_CMD_SET_Y_EXTENT,
1268 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveBry -
1269 hpaio->effectiveTly ) );
1270 /* Set Contrast */
1271 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1272 SCL_CMD_SET_CONTRAST,
1273 hpaio->currentContrast );
1274
1275 /* Set Brightness */
1276 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1277 SCL_CMD_SET_BRIGHTNESS,
1278 hpaio->currentBrightness );
1279
1280
1281 /* Download color map to OfficeJet Pro 11xx. */
1282 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 ) )
1283 {
1284 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1285 SCL_CMD_SET_DOWNLOAD_TYPE,
1286 SCL_DOWNLOAD_TYPE_COLORMAP );
1287
1288 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1289 SCL_CMD_DOWNLOAD_BINARY_DATA,
1290 sizeof( hp11xxSeriesColorMap ) );
1291
1292 hpmud_write_channel(hpaio->deviceid, hpaio->scan_channelid, hp11xxSeriesColorMap, sizeof(hp11xxSeriesColorMap),
1293 EXCEPTION_TIMEOUT, &bytes_wrote);
1294 }
1295
1296 /* For OfficeJet R and PSC 500 series, set CCD resolution to 600
1297 * for lineart. */
1298 if( hpaio->scl.compat & SCL_COMPAT_R_SERIES &&
1299 hpaio->currentScanMode == SCAN_MODE_LINEART )
1300 {
1301 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1302 SCL_CMD_SET_CCD_RESOLUTION, 600 );
1303 }
1304
1305 return SANE_STATUS_GOOD;
1306 }
1307
hpaioAdvanceDocument(hpaioScanner_t hpaio)1308 static SANE_Status hpaioAdvanceDocument(hpaioScanner_t hpaio)
1309 {
1310 SANE_Status retcode = SANE_STATUS_GOOD;
1311 int documentLoaded = 0;
1312
1313 DBG(8, "hpaioAdvanceDocument: papersource=%s batch=%d %s %d\n",
1314 hpaio->currentAdfMode==ADF_MODE_FLATBED ? "FLATBED" : hpaio->currentAdfMode==ADF_MODE_AUTO ? "AUTO" : "ADF",
1315 hpaio->currentBatchScan, __FILE__, __LINE__);
1316
1317 if (hpaio->currentAdfMode == ADF_MODE_FLATBED)
1318 goto bugout; /* nothing to do */
1319
1320 /* If there is an ADF see if paper is loaded. */
1321 if (hpaio->supportedAdfModes & ADF_MODE_ADF)
1322 {
1323 if (hpaio->currentDuplex && hpaio->currentSideNumber == 2)
1324 documentLoaded = 1;//No need to check paper in ADF
1325 else
1326 {
1327 retcode = SclInquire(hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1328 SCL_INQ_ADF_DOCUMENT_LOADED, &documentLoaded, 0, 0);
1329 if (retcode != SANE_STATUS_GOOD)
1330 goto bugout;
1331 }
1332 }
1333
1334 /* If in Batch mode, by definition we are in ADF mode. */
1335 if (hpaio->currentBatchScan && !documentLoaded)
1336 {
1337 retcode = SANE_STATUS_NO_DOCS;
1338 goto bugout; /* no paper loaded */
1339 }
1340
1341 /* If in Auto mode and no paper loaded use flatbed. */
1342 if (hpaio->currentAdfMode == ADF_MODE_AUTO && !documentLoaded)
1343 goto bugout; /* no paper loaded, use flatbed */
1344
1345 /* Assume ADF mode. */
1346 if (documentLoaded || (hpaio->currentSideNumber == 2) )
1347 {
1348 if (hpaio->currentDuplex)
1349 {
1350 /* Duplex change document. */
1351 if(hpaio->currentSideNumber == 2)
1352 hpaio->currentSideNumber = 1;
1353 else
1354 hpaio->currentSideNumber = 2;
1355
1356 retcode=hpaioSclSendCommandCheckError(hpaio, SCL_CMD_CHANGE_DOCUMENT, SCL_CHANGE_DOC_DUPLEX);
1357 }
1358 else
1359 {
1360 /* Simplex change document. */
1361 retcode = hpaioSclSendCommandCheckError(hpaio, SCL_CMD_CHANGE_DOCUMENT, SCL_CHANGE_DOC_SIMPLEX);
1362 }
1363 hpaio->currentPageNumber++;
1364 }
1365 else
1366 retcode = SANE_STATUS_NO_DOCS;
1367
1368 bugout:
1369
1370 DBG(8, "hpaioAdvanceDocument returns %d ADF-loaded=%d: %s %d\n", retcode, documentLoaded, __FILE__, __LINE__);
1371
1372 return retcode;
1373 }
1374
create_sclpml_session()1375 static struct hpaioScanner_s *create_sclpml_session()
1376 {
1377 struct hpaioScanner_s *ps;
1378
1379 if ((ps = malloc(sizeof(struct hpaioScanner_s))) == NULL)
1380 {
1381 return NULL;
1382 }
1383 memset(ps, 0, sizeof(struct hpaioScanner_s));
1384 ps->tag = "SCL-PML";
1385 ps->scan_channelid = -1;
1386 ps->cmd_channelid = -1;
1387
1388 return ps;
1389 }
1390
setSCLParams(hpaioScanner_t hpaio,struct hpmud_model_attributes * ma)1391 static SANE_Status setSCLParams(hpaioScanner_t hpaio, struct hpmud_model_attributes* ma)
1392 {
1393 SANE_Status retcode = SANE_STATUS_UNSUPPORTED;
1394 int supportsMfpdtf = 1;
1395
1396 /* Probing and setup for PML scanners... */
1397 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_CLEAR_ERROR_STACK, 0 );
1398
1399 /* Probe the SCL model. */
1400 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1401 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1402 SCL_INQ_HP_MODEL_11, 0, hpaio->scl.compat1150,
1403 LEN_MODEL_RESPONSE );
1404
1405 if( retcode == SANE_STATUS_GOOD )
1406 {
1407 hpaio->scl.compat |= SCL_COMPAT_OFFICEJET;
1408 }
1409 else if( retcode != SANE_STATUS_UNSUPPORTED )
1410 {
1411 goto abort;
1412 }
1413 DBG(6, "scl.compat1150=<%s>: %s %d\n", hpaio->scl.compat1150, __FILE__, __LINE__);
1414
1415 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1416 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1417 SCL_INQ_HP_MODEL_12, 0, hpaio->scl.compatPost1150,
1418 LEN_MODEL_RESPONSE );
1419
1420 if( retcode == SANE_STATUS_GOOD )
1421 {
1422 hpaio->scl.compat |= SCL_COMPAT_POST_1150;
1423 }
1424 else if( retcode != SANE_STATUS_UNSUPPORTED )
1425 {
1426 goto abort;
1427 }
1428 DBG(6, "scl.compatPost1150=<%s>: %s %d\n", hpaio->scl.compatPost1150, __FILE__, __LINE__);
1429
1430 if( !hpaio->scl.compat )
1431 {
1432 SET_DEFAULT_MODEL( hpaio, "(unknown scanner)" );
1433 }
1434 else if( hpaio->scl.compat == SCL_COMPAT_OFFICEJET )
1435 {
1436 hpaio->scl.compat |= SCL_COMPAT_1150;
1437 SET_DEFAULT_MODEL( hpaio, "(OfficeJet 1150)" );
1438 }
1439 else if( !strcmp( hpaio->scl.compatPost1150, "5400A" ) )
1440 {
1441 hpaio->scl.compat |= SCL_COMPAT_1170;
1442 SET_DEFAULT_MODEL( hpaio, "(OfficeJet 1170)" );
1443 }
1444 else if( !strcmp( hpaio->scl.compatPost1150, "5500A" ) )
1445 {
1446 hpaio->scl.compat |= SCL_COMPAT_R_SERIES;
1447 SET_DEFAULT_MODEL( hpaio, "(OfficeJet R Series)" );
1448 }
1449 else if( !strcmp( hpaio->scl.compatPost1150, "5600A" ) )
1450 {
1451 hpaio->scl.compat |= SCL_COMPAT_G_SERIES;
1452 SET_DEFAULT_MODEL( hpaio, "(OfficeJet G Series)" );
1453 }
1454 else if( !strcmp( hpaio->scl.compatPost1150, "5700A" ) )
1455 {
1456 hpaio->scl.compat |= SCL_COMPAT_K_SERIES;
1457 SET_DEFAULT_MODEL( hpaio, "(OfficeJet K Series)" );
1458 }
1459 else if( !strcmp( hpaio->scl.compatPost1150, "5800A" ) )
1460 {
1461 hpaio->scl.compat |= SCL_COMPAT_D_SERIES;
1462 SET_DEFAULT_MODEL( hpaio, "(OfficeJet D Series)" );
1463 }
1464 else if( !strcmp( hpaio->scl.compatPost1150, "5900A" ) )
1465 {
1466 hpaio->scl.compat |= SCL_COMPAT_6100_SERIES;
1467 SET_DEFAULT_MODEL( hpaio, "(OfficeJet 6100 Series)" );
1468 }
1469 else
1470 {
1471 SET_DEFAULT_MODEL( hpaio, "(unknown OfficeJet)" );
1472 }
1473 DBG(6, "scl.compat=0x%4.4X: %s %d\n", hpaio->scl.compat, __FILE__, __LINE__);
1474
1475 /* Decide which position/extent unit to use. "Device pixels" works
1476 * better on most models, but the 1150 requires "decipoints." */
1477 if( hpaio->scl.compat & ( SCL_COMPAT_1150 ) )
1478 {
1479 hpaio->scl.decipixelChar = SCL_CHAR_DECIPOINTS;
1480 hpaio->decipixelsPerInch = DECIPOINTS_PER_INCH;
1481 }
1482 else
1483 {
1484 hpaio->scl.decipixelChar = SCL_CHAR_DEVPIXELS;
1485 hpaio->decipixelsPerInch = DEVPIXELS_PER_INCH;
1486 /* Check for non-default decipixelsPerInch definition. */
1487 SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1488 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1489 SCL_INQ_DEVICE_PIXELS_PER_INCH,
1490 &hpaio->decipixelsPerInch, 0, 0 );
1491 }
1492 DBG(6, "decipixelChar='%c', decipixelsPerInch=%d: %s %d\n", hpaio->scl.decipixelChar, hpaio->decipixelsPerInch, __FILE__, __LINE__);
1493
1494 /* Is MFPDTF supported? */
1495 if( hpaioSclSendCommandCheckError( hpaio,
1496 SCL_CMD_SET_MFPDTF,
1497 SCL_MFPDTF_ON ) != SANE_STATUS_GOOD )
1498 {
1499 DBG(6, "Doesn't support MFPDTF: %s %d\n", __FILE__, __LINE__);
1500 supportsMfpdtf = 0;
1501 }
1502
1503 /* All scan modes are supported with no compression. */
1504 hpaio->supportsScanMode[SCAN_MODE_LINEART] = COMPRESSION_NONE;
1505 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] = COMPRESSION_NONE;
1506 hpaio->supportsScanMode[SCAN_MODE_COLOR] = COMPRESSION_NONE;
1507
1508 if( supportsMfpdtf )
1509 {
1510 if( hpaioSclSendCommandCheckError( hpaio,
1511 SCL_CMD_SET_COMPRESSION,
1512 SCL_COMPRESSION_JPEG ) == SANE_STATUS_GOOD )
1513 {
1514 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] |= COMPRESSION_JPEG;
1515 hpaio->supportsScanMode[SCAN_MODE_COLOR] |= COMPRESSION_JPEG;
1516 }
1517 }
1518
1519 /* Determine the minimum and maximum resolution.
1520 * Probe for both X and Y, and pick largest min and smallest max.
1521 * For the 1150, set min to 50 to prevent scan head crashes (<42). */
1522 int minXRes, minYRes, maxXRes, maxYRes;
1523 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1524 SCL_CMD_INQUIRE_MINIMUM_VALUE,
1525 SCL_CMD_SET_X_RESOLUTION,
1526 &minXRes, 0, 0 );
1527 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1528 SCL_CMD_INQUIRE_MINIMUM_VALUE,
1529 SCL_CMD_SET_Y_RESOLUTION,
1530 &minYRes, 0, 0 );
1531 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1532 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
1533 SCL_CMD_SET_X_RESOLUTION,
1534 &maxXRes, 0, 0 );
1535 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1536 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
1537 SCL_CMD_SET_Y_RESOLUTION,
1538 &maxYRes, 0, 0 );
1539
1540 _DBG("Flatbed minXRes=%d minYRes=%d maxXRes=%d maxYRes=%d retcode=%d\n",
1541 minXRes, minYRes, maxXRes, maxYRes, retcode);
1542
1543 if( hpaio->scl.compat & SCL_COMPAT_1150 && minYRes < SCL_MIN_Y_RES_1150 )
1544 minYRes = SCL_MIN_Y_RES_1150;
1545
1546 hpaio->scl.minRes = minXRes;
1547 if( hpaio->scl.minRes < minYRes )
1548 hpaio->scl.minRes = minYRes;
1549
1550 hpaio->resolutionRange.min = hpaio->scl.minRes;
1551
1552 hpaio->scl.maxRes = maxXRes;
1553 if( hpaio->scl.maxRes > maxYRes )
1554 hpaio->scl.maxRes = maxYRes;
1555
1556 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 )
1557 && hpaio->scl.maxRes > SCL_MAX_RES_1150_1170 )
1558 {
1559 hpaio->scl.maxRes = SCL_MAX_RES_1150_1170;
1560 }
1561 hpaio->resolutionRange.max = hpaio->scl.maxRes;
1562
1563 /* Determine ADF/duplex capabilities. */
1564 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1565 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1566 SCL_INQ_ADF_CAPABILITY,
1567 &hpaio->scl.adfCapability, 0, 0 );
1568
1569 DBG(6, "ADF capability=%d retcode=%d: %s %d\n", hpaio->scl.adfCapability, retcode,__FILE__, __LINE__);
1570
1571 /*Set min-max resolution for ADF*/
1572 if (hpaio->scl.adfCapability)
1573 {
1574 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1575 SCL_CMD_INQUIRE_MINIMUM_VALUE,
1576 SCL_PSEUDO_ADF_X_RESOLUTION,
1577 &minXRes, 0, 0 );
1578 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1579 SCL_CMD_INQUIRE_MINIMUM_VALUE,
1580 SCL_PSEUDO_ADF_Y_RESOLUTION,
1581 &minYRes, 0, 0 );
1582 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1583 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
1584 SCL_PSEUDO_ADF_X_RESOLUTION,
1585 &maxXRes, 0, 0 );
1586 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1587 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
1588 SCL_PSEUDO_ADF_Y_RESOLUTION,
1589 &maxYRes, 0, 0 );
1590 _DBG("minXResAdf=%d minYResAdf=%d maxXResAdf=%d maxYResAdf=%d retcode=%d \n",
1591 minXRes, minYRes,maxXRes, maxYRes, retcode);
1592
1593 if( hpaio->scl.compat & SCL_COMPAT_1150 && minYRes < SCL_MIN_Y_RES_1150 )
1594 minYRes = SCL_MIN_Y_RES_1150;
1595
1596 hpaio->scl.minResAdf = minXRes;
1597 if( hpaio->scl.minResAdf < minYRes )
1598 hpaio->scl.minResAdf = minYRes;
1599
1600 hpaio->scl.maxResAdf = maxXRes;
1601 if( hpaio->scl.maxResAdf > maxYRes )
1602 hpaio->scl.maxResAdf = maxYRes;
1603
1604 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 )
1605 && hpaio->scl.maxResAdf > SCL_MAX_RES_1150_1170 )
1606 {
1607 hpaio->scl.maxResAdf = SCL_MAX_RES_1150_1170;
1608 }
1609 }//end if (hpaio->scl.adfCapability)
1610
1611 if(ma->scansrc & HPMUD_SCANSRC_FLATBED)
1612 {
1613 hpaio->scl.flatbedCapability = 1;
1614 hpaio->supportedAdfModes = ADF_MODE_FLATBED;
1615 }
1616 if (hpaio->scl.adfCapability)
1617 {
1618 if( hpaio->scl.compat & SCL_COMPAT_K_SERIES)
1619 {
1620 hpaio->supportedAdfModes |= ADF_MODE_ADF;
1621 }
1622 else
1623 {
1624 int supportedFunctions;
1625
1626 hpaio->supportedAdfModes |= ADF_MODE_ADF;
1627 if (hpaio->scl.flatbedCapability)
1628 hpaio->supportedAdfModes |= ADF_MODE_AUTO;
1629
1630 if( hpaio->scl.compat & ( SCL_COMPAT_1170 | SCL_COMPAT_R_SERIES |SCL_COMPAT_G_SERIES ) )
1631 {
1632 hpaio->scl.unloadAfterScan = 1;
1633 }
1634 if( PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid, hpaio->scl.objSupportedFunctions ) != ERROR &&
1635 PmlGetIntegerValue( hpaio->scl.objSupportedFunctions,
1636 0,
1637 &supportedFunctions ) != ERROR &&
1638 supportedFunctions & PML_SUPPFUNC_DUPLEX )
1639 {
1640 hpaio->supportsDuplex = 1;
1641 }
1642 }
1643 }
1644
1645 /* Determine maximum X and Y extents. */
1646 SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1647 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
1648 SCL_CMD_SET_X_EXTENT,
1649 &hpaio->scl.maxXExtent, 0, 0 );
1650
1651 SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1652 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
1653 SCL_CMD_SET_Y_EXTENT,
1654 &hpaio->scl.maxYExtent, 0, 0 );
1655
1656 DBG(8, "Maximum extents: x=%d, y=%d %s %d\n", hpaio->scl.maxXExtent, hpaio->scl.maxYExtent, __FILE__, __LINE__);
1657
1658 hpaio->tlxRange.max = hpaio->brxRange.max = DECIPIXELS_TO_MILLIMETERS( hpaio->scl.maxXExtent );
1659 hpaio->tlyRange.max = hpaio->bryRange.max = DECIPIXELS_TO_MILLIMETERS( hpaio->scl.maxYExtent );
1660
1661 /* Allocate MFPDTF parser if supported. */
1662 if( supportsMfpdtf )
1663 {
1664 hpaio->mfpdtf = MfpdtfAllocate( hpaio->deviceid, hpaio->scan_channelid );
1665 MfpdtfSetChannel( hpaio->mfpdtf, hpaio->scan_channelid );
1666
1667 if( hpaio->preDenali )
1668 {
1669 MfpdtfReadSetSimulateImageHeaders( hpaio->mfpdtf, 1 );
1670 }
1671 }
1672
1673 retcode = SANE_STATUS_GOOD;
1674
1675 abort:
1676 return retcode;
1677 }
1678
setPMLParams(hpaioScanner_t hpaio,int forceJpegForGrayAndColor,int force300dpiForLineart,int force300dpiForGrayscale)1679 static SANE_Status setPMLParams(hpaioScanner_t hpaio, int forceJpegForGrayAndColor,
1680 int force300dpiForLineart, int force300dpiForGrayscale)
1681 {
1682 SANE_Status retcode = SANE_STATUS_INVAL;
1683 int comps = 0;
1684 int modularHardware = 0;
1685
1686 hpaio->decipixelsPerInch = DECIPOINTS_PER_INCH;
1687
1688 /* Determine supported scan modes and compression settings. */
1689 if( hpaio->preDenali )
1690 {
1691 comps |= COMPRESSION_MMR;
1692 }
1693
1694 PmlSetIntegerValue( hpaio->pml.objCompression,
1695 PML_TYPE_ENUMERATION,
1696 PML_COMPRESSION_NONE );
1697
1698 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1699 hpaio->pml.objCompression, 0, 0 ) != ERROR )
1700 {
1701 comps |= COMPRESSION_NONE;
1702 }
1703
1704 PmlSetIntegerValue( hpaio->pml.objCompression,
1705 PML_TYPE_ENUMERATION,
1706 PML_COMPRESSION_MH );
1707
1708 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1709 hpaio->pml.objCompression, 0, 0 ) != ERROR )
1710 {
1711 comps |= COMPRESSION_MH;
1712 }
1713
1714 PmlSetIntegerValue( hpaio->pml.objCompression,
1715 PML_TYPE_ENUMERATION,
1716 PML_COMPRESSION_MR );
1717
1718 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1719 hpaio->pml.objCompression, 0, 0 ) != ERROR )
1720 {
1721 comps |= COMPRESSION_MR;
1722 }
1723
1724 PmlSetIntegerValue( hpaio->pml.objCompression,
1725 PML_TYPE_ENUMERATION,
1726 PML_COMPRESSION_MMR );
1727
1728 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1729 hpaio->pml.objCompression, 0, 0 ) != ERROR )
1730 {
1731 comps |= COMPRESSION_MMR;
1732 }
1733
1734 PmlSetIntegerValue( hpaio->pml.objPixelDataType,
1735 PML_TYPE_ENUMERATION,
1736 PML_DATA_TYPE_LINEART );
1737
1738 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1739 hpaio->pml.objPixelDataType, 0, 0 ) != ERROR )
1740 {
1741 hpaio->supportsScanMode[SCAN_MODE_LINEART] = comps;
1742 }
1743 comps &= COMPRESSION_NONE;
1744
1745 if( forceJpegForGrayAndColor )
1746 {
1747 comps = 0;
1748 }
1749
1750 PmlSetIntegerValue( hpaio->pml.objCompression,
1751 PML_TYPE_ENUMERATION,
1752 PML_COMPRESSION_JPEG );
1753
1754 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1755 hpaio->pml.objCompression, 0, 0 ) != ERROR )
1756 {
1757 comps |= COMPRESSION_JPEG;
1758 }
1759
1760 PmlSetIntegerValue( hpaio->pml.objPixelDataType,
1761 PML_TYPE_ENUMERATION,
1762 PML_DATA_TYPE_GRAYSCALE );
1763
1764 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1765 hpaio->pml.objPixelDataType, 0, 0 ) != ERROR )
1766 {
1767 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] = comps;
1768 }
1769
1770 PmlSetIntegerValue( hpaio->pml.objPixelDataType,
1771 PML_TYPE_ENUMERATION,
1772 PML_DATA_TYPE_COLOR );
1773
1774 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
1775 hpaio->pml.objPixelDataType, 0, 0 ) != ERROR )
1776 {
1777 hpaio->supportsScanMode[SCAN_MODE_COLOR] = comps;
1778 }
1779
1780 /* Determine supported resolutions. */
1781 NumListClear( hpaio->resolutionList );
1782 NumListClear( hpaio->lineartResolutionList );
1783
1784 if( hpaio->preDenali )
1785 {
1786 NumListAdd( hpaio->lineartResolutionList, 200 );
1787 if( !strcmp( hpaio->saneDevice.model, "OfficeJet_Series_300" ) )
1788 {
1789 NumListAdd( hpaio->lineartResolutionList, 300 );
1790 }
1791 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
1792 }
1793 else if( PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid,
1794 hpaio->pml.objResolutionRange ) == ERROR )
1795 {
1796 pmlDefaultResRange:
1797 /* TODO: What are the correct X and Y resolution ranges
1798 * for the OfficeJet T series? */
1799 hpaio->resolutionRange.min = 75;
1800 hpaio->resolutionRange.max = 600;
1801 }
1802 else
1803 {
1804 char resList[PML_MAX_VALUE_LEN + 1];
1805 int i, len, res, consumed;
1806
1807 PmlGetStringValue( hpaio->pml.objResolutionRange,
1808 0, resList, PML_MAX_VALUE_LEN );
1809
1810 resList[PML_MAX_VALUE_LEN] = 0;
1811 len = strlen( resList );
1812
1813 /* Parse "(100)x(100),(150)x(150),(200)x(200),(300)x(300)".
1814 * This isn't quite the right way to do it, but it'll do. */
1815 for( i = 0; i < len; )
1816 {
1817 if( resList[i] < '0' || resList[i] > '9' )
1818 {
1819 i++;
1820 continue;
1821 }
1822 if( sscanf( resList + i, "%d%n", &res, &consumed ) != 1 )
1823 {
1824 break;
1825 }
1826 i += consumed;
1827 if( !force300dpiForGrayscale || res >= 300 )
1828 {
1829 NumListAdd( hpaio->resolutionList, res );
1830 }
1831 if( !force300dpiForLineart || res >= 300 )
1832 {
1833 NumListAdd( hpaio->lineartResolutionList, res );
1834 }
1835 }
1836
1837 if( !NumListGetCount( hpaio->resolutionList ) )
1838 {
1839 goto pmlDefaultResRange;
1840 }
1841 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
1842 }
1843
1844
1845 /* Determine supported ADF modes. */
1846 if(PmlRequestGet(hpaio->deviceid, hpaio->cmd_channelid, hpaio->pml.objModularHardware) != ERROR &&
1847 PmlGetIntegerValue(hpaio->pml.objModularHardware, 0, &modularHardware) != ERROR)
1848 {
1849 hpaio->pml.flatbedCapability = 1;
1850
1851 DBG(6, "Valid PML modularHardware object value=%x: %s %d\n", modularHardware, __FILE__, __LINE__);
1852
1853 /* LJ3200 does not report ADF mode, so we force it. DES 8/5/08 */
1854 if (strncasecmp( hpaio->saneDevice.model, "hp_laserjet_3200", 16) == 0)
1855 modularHardware = PML_MODHW_ADF;
1856
1857 if(modularHardware & PML_MODHW_ADF)
1858 hpaio->supportedAdfModes = ADF_MODE_AUTO | ADF_MODE_ADF;
1859 else
1860 hpaio->supportedAdfModes = ADF_MODE_FLATBED;
1861 }
1862 else
1863 {
1864 DBG(6, "No valid PML modularHardware object, default to ADF and AUTO support: %s %d\n", __FILE__, __LINE__);
1865 hpaio->supportedAdfModes = ADF_MODE_AUTO | ADF_MODE_ADF;
1866 }
1867 hpaio->supportsDuplex = 0;
1868
1869 hpaio->tlxRange.max = hpaio->brxRange.max = INCHES_TO_MILLIMETERS( PML_MAX_WIDTH_INCHES );
1870 hpaio->tlyRange.max = hpaio->bryRange.max = INCHES_TO_MILLIMETERS( PML_MAX_HEIGHT_INCHES );
1871
1872 return retcode;
1873 }
1874
filldata(hpaioScanner_t hpaio,struct hpmud_model_attributes * ma)1875 static SANE_Status filldata(hpaioScanner_t hpaio, struct hpmud_model_attributes* ma)
1876 {
1877 SANE_Status retcode = SANE_STATUS_INVAL;
1878 int forceJpegForGrayAndColor = 0;
1879 int force300dpiForLineart = 0;
1880 int force300dpiForGrayscale = 0;
1881
1882 /* Guess the command language (SCL or PML) based on the model string. */
1883 if( UNDEFINED_MODEL( hpaio ) )
1884 {
1885 hpaio->scannerType = SCANNER_TYPE_SCL;
1886 }
1887 else if( strcasestr( hpaio->saneDevice.model, "laserjet" ) )
1888 {
1889 hpaio->scannerType = SCANNER_TYPE_PML;
1890 hpaio->pml.openFirst = 1;
1891
1892 if( strcasecmp( hpaio->saneDevice.model, "HP_LaserJet_1100" ) == 0 )
1893 {
1894 hpaio->pml.dontResetBeforeNextNonBatchPage = 1;
1895 }
1896 else
1897 {
1898 hpaio->pml.startNextBatchPageEarly = 1;
1899 }
1900 }
1901 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet" ) == 0 ||
1902 strcasecmp( hpaio->saneDevice.model, "OfficeJet_LX" ) == 0 ||
1903 strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_300" ) == 0 )
1904 {
1905 hpaio->scannerType = SCANNER_TYPE_PML;
1906 hpaio->preDenali = 1;
1907 }
1908 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_500" ) == 0 ||
1909 strcasecmp( hpaio->saneDevice.model, "All-in-One_IJP-V100" ) == 0 )
1910 {
1911 hpaio->scannerType = SCANNER_TYPE_PML;
1912 hpaio->fromDenali = 1;
1913 force300dpiForLineart = 1;
1914 force300dpiForGrayscale = 1;
1915 hpaio->defaultCompression[SCAN_MODE_LINEART] = COMPRESSION_MH;
1916 hpaio->defaultCompression[SCAN_MODE_GRAYSCALE] = COMPRESSION_JPEG;
1917 hpaio->defaultJpegCompressionFactor = SAFER_JPEG_COMPRESSION_FACTOR;
1918 }
1919 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_600" ) == 0 )
1920 {
1921 hpaio->scannerType = SCANNER_TYPE_PML;
1922 hpaio->denali = 1;
1923 forceJpegForGrayAndColor = 1;
1924 force300dpiForLineart = 1;
1925 hpaio->defaultCompression[SCAN_MODE_LINEART] = COMPRESSION_MH;
1926 hpaio->defaultJpegCompressionFactor = SAFER_JPEG_COMPRESSION_FACTOR;
1927 }
1928 else if( strcasecmp( hpaio->saneDevice.model, "Printer/Scanner/Copier_300" ) == 0 )
1929 {
1930 hpaio->scannerType = SCANNER_TYPE_PML;
1931 forceJpegForGrayAndColor = 1;
1932 force300dpiForLineart = 1;
1933 hpaio->defaultCompression[SCAN_MODE_LINEART] = COMPRESSION_MH;
1934 hpaio->defaultJpegCompressionFactor = SAFER_JPEG_COMPRESSION_FACTOR;
1935 }
1936 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_700" ) == 0 )
1937 {
1938 hpaio->scannerType = SCANNER_TYPE_PML;
1939 forceJpegForGrayAndColor = 1;
1940 force300dpiForLineart = 1;
1941 hpaio->defaultCompression[SCAN_MODE_LINEART] = COMPRESSION_MH;
1942 hpaio->defaultJpegCompressionFactor = SAFER_JPEG_COMPRESSION_FACTOR;
1943 }
1944 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_T_Series" ) == 0 )
1945 {
1946 hpaio->scannerType = SCANNER_TYPE_PML;
1947 forceJpegForGrayAndColor = 1;
1948 }
1949 else
1950 {
1951 hpaio->scannerType = SCANNER_TYPE_SCL;
1952 }
1953
1954 DBG(6, "Scanner type=%s: %s %d\n", hpaio->scannerType==0 ? "SCL" : "PML", __FILE__, __LINE__);
1955
1956 hpaioPmlAllocateObjects(hpaio); /* used by pml scanners and scl scanners */
1957
1958 if ((retcode = hpaioConnOpen(hpaio)) != SANE_STATUS_GOOD)
1959 {
1960 goto abort;
1961 }
1962
1963 if ((retcode = hpaioResetScanner(hpaio)) != SANE_STATUS_GOOD)
1964 {
1965 goto abort;
1966 }
1967
1968 /* Probing and setup for SCL scanners... */
1969 if( hpaio->scannerType == SCANNER_TYPE_SCL )
1970 {
1971 setSCLParams(hpaio, ma);
1972
1973 }
1974 else /* if (hpaio->scannerType==SCANNER_TYPE_PML) */
1975 {
1976 setPMLParams(hpaio, forceJpegForGrayAndColor, force300dpiForLineart, force300dpiForGrayscale);
1977
1978 } /* if( hpaio->scannerType == SCANNER_TYPE_SCL ) */
1979
1980 retcode = SANE_STATUS_GOOD;
1981
1982 abort:
1983 return retcode;
1984 }
1985
sclpml_open(SANE_String_Const device,SANE_Handle * pHandle)1986 SANE_Status sclpml_open(SANE_String_Const device, SANE_Handle *pHandle)
1987 {
1988 struct hpmud_model_attributes ma;
1989 SANE_Status retcode = SANE_STATUS_INVAL;
1990
1991 int bytes_read;
1992 char deviceIDString[LEN_DEVICE_ID_STRING];
1993 char model[256];
1994 enum HPMUD_RESULT stat;
1995
1996 if(session)
1997 {
1998 return SANE_STATUS_DEVICE_BUSY;
1999 }
2000 if((session = create_sclpml_session()) == NULL)
2001 return SANE_STATUS_NO_MEM;
2002
2003 /* Set session to specified device. */
2004 snprintf(session->deviceuri, sizeof(session->deviceuri)-1, "hp:%s", device); /* prepend "hp:" */
2005
2006 /* Get actual model attributes from models.dat. */
2007 hpmud_query_model(session->deviceuri, &ma);
2008
2009 // Set the duplex type supported
2010 if (ma.scantype == HPMUD_SCANTYPE_SCL_DUPLEX)
2011 session->supportsDuplex = 1;
2012 else
2013 session->supportsDuplex = 0;
2014
2015
2016 if (hpmud_open_device(session->deviceuri, ma.mfp_mode, &session->deviceid) != HPMUD_R_OK)
2017 {
2018 stat = SANE_STATUS_IO_ERROR;
2019 goto abort;
2020 }
2021
2022 /* Get the device ID string and initialize the SANE_Device structure. */
2023 memset(deviceIDString, 0, sizeof(deviceIDString));
2024
2025 if(hpmud_get_device_id(session->deviceid, deviceIDString, sizeof(deviceIDString), &bytes_read) != HPMUD_R_OK)
2026 {
2027 retcode = SANE_STATUS_INVAL;
2028 goto abort;
2029 }
2030
2031 DBG(6, "device ID string=<%s>: %s %d\n", deviceIDString, __FILE__, __LINE__);
2032
2033 session->saneDevice.name = strdup( device );
2034 session->saneDevice.vendor = "Hewlett-Packard";
2035 hpmud_get_model(deviceIDString, model, sizeof(model));
2036 DBG(6, "Model = %s: %s %d\n", model, __FILE__, __LINE__);
2037 session->saneDevice.model = strdup(model);
2038 session->saneDevice.type = "multi-function peripheral";
2039
2040 /* Initialize option descriptors. */
2041 init_options(session);
2042 session->currentSideNumber = 1;
2043
2044 if(filldata(session, &ma) != SANE_STATUS_GOOD)
2045 {
2046 retcode = SANE_STATUS_INVAL;
2047 goto abort;
2048 }
2049
2050 done:
2051 /* Finish setting up option descriptors. */
2052 hpaioUpdateDescriptors( session, OPTION_FIRST );
2053
2054 *pHandle = (SANE_Handle *)session;
2055
2056 retcode = SANE_STATUS_GOOD;
2057
2058 abort:
2059 if( session )
2060 {
2061 hpaioConnClose( session );
2062 }
2063 if( retcode != SANE_STATUS_GOOD )
2064 {
2065 if( session )
2066 {
2067 if( session->saneDevice.name )
2068 {
2069 free( ( void * ) session->saneDevice.name );
2070 }
2071 if( session->saneDevice.model )
2072 {
2073 free( ( void * ) session->saneDevice.model );
2074 }
2075 if (session->mfpdtf)
2076 {
2077 MfpdtfDeallocate (session->mfpdtf);
2078 }
2079 free( session );
2080 session = NULL;
2081 }
2082 }
2083 return retcode;
2084 } /* sane_hpaio_open() */
2085
sclpml_close(SANE_Handle handle)2086 void sclpml_close(SANE_Handle handle)
2087 {
2088 hpaioScanner_t hpaio = (hpaioScanner_t) handle;
2089
2090 DBG(8, "sane_hpaio_close(): %s %d\n", __FILE__, __LINE__);
2091 if (hpaio == NULL || hpaio != session)
2092 {
2093 BUG("invalid sane_close\n");
2094 return;
2095 }
2096
2097 hpaioPmlDeallocateObjects(hpaio);
2098
2099 /* ADF may leave channel(s) open. */
2100 if (hpaio->cmd_channelid > 0)
2101 hpaioConnEndScan(hpaio);
2102
2103 if (hpaio->deviceid > 0)
2104 {
2105 hpmud_close_device(hpaio->deviceid);
2106 hpaio->deviceid = -1;
2107 }
2108 if( hpaio->saneDevice.name )
2109 {
2110 free( ( void * ) hpaio->saneDevice.name );
2111 }
2112 if( hpaio->saneDevice.model )
2113 {
2114 free( ( void * ) hpaio->saneDevice.model );
2115 }
2116 if (hpaio->mfpdtf)
2117 {
2118 MfpdtfDeallocate (hpaio->mfpdtf);
2119 }
2120 free(hpaio);
2121 session = NULL;
2122 }
2123
sclpml_get_option_descriptor(SANE_Handle handle,SANE_Int option)2124 const SANE_Option_Descriptor * sclpml_get_option_descriptor(SANE_Handle handle, SANE_Int option)
2125 {
2126 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
2127
2128 DBG(8, "sane_hpaio_get_option_descriptor(option=%s): %s %d\n", hpaio->option[option].name, __FILE__, __LINE__);
2129
2130 if( option < 0 || option >= OPTION_LAST )
2131 {
2132 return 0;
2133 }
2134
2135 return &hpaio->option[option];
2136 }
2137
sclpml_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * pValue,SANE_Int * pInfo)2138 SANE_Status sclpml_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *pValue, SANE_Int *pInfo)
2139 {
2140 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
2141 SANE_Int _info;
2142 SANE_Int * pIntValue = pValue;
2143 SANE_String pStrValue = pValue;
2144 SANE_Status retcode;
2145 char sz[64];
2146
2147 if( !pInfo )
2148 {
2149 pInfo = &_info;
2150 }
2151
2152 switch( action )
2153 {
2154 case SANE_ACTION_GET_VALUE:
2155 switch( option )
2156 {
2157 case OPTION_NUM_OPTIONS:
2158 *pIntValue = OPTION_LAST;
2159 break;
2160
2161 case OPTION_SCAN_MODE:
2162 switch( hpaio->currentScanMode )
2163 {
2164 case SCAN_MODE_LINEART:
2165 strcpy( pStrValue, SANE_VALUE_SCAN_MODE_LINEART );
2166 break;
2167 case SCAN_MODE_GRAYSCALE:
2168 strcpy( pStrValue, SANE_VALUE_SCAN_MODE_GRAY );
2169 break;
2170 case SCAN_MODE_COLOR:
2171 strcpy( pStrValue, SANE_VALUE_SCAN_MODE_COLOR );
2172 break;
2173 default:
2174 strcpy( pStrValue, STR_UNKNOWN );
2175 break;
2176 }
2177 break;
2178
2179 case OPTION_SCAN_RESOLUTION:
2180 *pIntValue = hpaio->currentResolution;
2181 break;
2182
2183 case OPTION_CONTRAST:
2184 *pIntValue = hpaio->currentContrast;
2185 break;
2186 case OPTION_BRIGHTNESS:
2187 *pIntValue = hpaio->currentBrightness;
2188 break;
2189
2190 case OPTION_COMPRESSION:
2191 switch( hpaio->currentCompression )
2192 {
2193 case COMPRESSION_NONE:
2194 strcpy( pStrValue, STR_COMPRESSION_NONE );
2195 break;
2196 case COMPRESSION_MH:
2197 strcpy( pStrValue, STR_COMPRESSION_MH );
2198 break;
2199 case COMPRESSION_MR:
2200 strcpy( pStrValue, STR_COMPRESSION_MR );
2201 break;
2202 case COMPRESSION_MMR:
2203 strcpy( pStrValue, STR_COMPRESSION_MMR );
2204 break;
2205 case COMPRESSION_JPEG:
2206 strcpy( pStrValue, STR_COMPRESSION_JPEG );
2207 break;
2208 default:
2209 strcpy( pStrValue, STR_UNKNOWN );
2210 break;
2211 }
2212 break;
2213
2214 case OPTION_JPEG_COMPRESSION_FACTOR:
2215 *pIntValue = hpaio->currentJpegCompressionFactor;
2216 break;
2217
2218 case OPTION_BATCH_SCAN:
2219 *pIntValue = hpaio->currentBatchScan;
2220 break;
2221
2222 case OPTION_ADF_MODE:
2223 switch( hpaio->currentAdfMode )
2224 {
2225 case ADF_MODE_AUTO:
2226 strcpy( pStrValue, STR_ADF_MODE_AUTO );
2227 break;
2228 case ADF_MODE_FLATBED:
2229 strcpy( pStrValue, STR_ADF_MODE_FLATBED );
2230 break;
2231 case ADF_MODE_ADF:
2232 strcpy( pStrValue, STR_ADF_MODE_ADF );
2233 break;
2234 default:
2235 strcpy( pStrValue, STR_UNKNOWN );
2236 break;
2237 }
2238 break;
2239 #if 1
2240 case OPTION_DUPLEX:
2241 *pIntValue = hpaio->currentDuplex;
2242 break;
2243 #endif
2244 case OPTION_LENGTH_MEASUREMENT:
2245 switch( hpaio->currentLengthMeasurement )
2246 {
2247 case LENGTH_MEASUREMENT_UNKNOWN:
2248 strcpy( pStrValue, STR_LENGTH_MEASUREMENT_UNKNOWN );
2249 break;
2250 case LENGTH_MEASUREMENT_UNLIMITED:
2251 strcpy( pStrValue,
2252 STR_LENGTH_MEASUREMENT_UNLIMITED );
2253 break;
2254 case LENGTH_MEASUREMENT_APPROXIMATE:
2255 strcpy( pStrValue,
2256 STR_LENGTH_MEASUREMENT_APPROXIMATE );
2257 break;
2258 case LENGTH_MEASUREMENT_PADDED:
2259 strcpy( pStrValue, STR_LENGTH_MEASUREMENT_PADDED );
2260 break;
2261 case LENGTH_MEASUREMENT_EXACT:
2262 strcpy( pStrValue, STR_LENGTH_MEASUREMENT_EXACT );
2263 break;
2264 default:
2265 strcpy( pStrValue, STR_UNKNOWN );
2266 break;
2267 }
2268 break;
2269
2270 case OPTION_TL_X:
2271 *pIntValue = hpaio->currentTlx;
2272 break;
2273
2274 case OPTION_TL_Y:
2275 *pIntValue = hpaio->currentTly;
2276 break;
2277
2278 case OPTION_BR_X:
2279 *pIntValue = hpaio->currentBrx;
2280 break;
2281
2282 case OPTION_BR_Y:
2283 *pIntValue = hpaio->currentBry;
2284 break;
2285
2286 default:
2287 return SANE_STATUS_INVAL;
2288 }
2289 break;
2290
2291 case SANE_ACTION_SET_VALUE:
2292 if( hpaio->option[option].cap & SANE_CAP_INACTIVE )
2293 {
2294 return SANE_STATUS_INVAL;
2295 }
2296 switch( option )
2297 {
2298 case OPTION_SCAN_MODE:
2299 if( !strcasecmp( pStrValue, SANE_VALUE_SCAN_MODE_LINEART ) &&
2300 hpaio->supportsScanMode[SCAN_MODE_LINEART] )
2301 {
2302 hpaio->currentScanMode = SCAN_MODE_LINEART;
2303 break;
2304 }
2305 if( !strcasecmp( pStrValue, SANE_VALUE_SCAN_MODE_GRAY ) &&
2306 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] )
2307 {
2308 hpaio->currentScanMode = SCAN_MODE_GRAYSCALE;
2309 break;
2310 }
2311 if( !strcasecmp( pStrValue, SANE_VALUE_SCAN_MODE_COLOR ) &&
2312 hpaio->supportsScanMode[SCAN_MODE_COLOR] )
2313 {
2314 hpaio->currentScanMode = SCAN_MODE_COLOR;
2315 break;
2316 }
2317 return SANE_STATUS_INVAL;
2318
2319 case OPTION_SCAN_RESOLUTION:
2320 if( ( hpaio->option[option].constraint_type ==
2321 SANE_CONSTRAINT_WORD_LIST &&
2322 !NumListIsInList( ( SANE_Int * )hpaio->option[option].constraint.word_list, *pIntValue ) ) ||
2323 ( hpaio->option[option].constraint_type == SANE_CONSTRAINT_RANGE &&
2324 ( *pIntValue<hpaio->resolutionRange.min ||
2325 *pIntValue>hpaio->resolutionRange.max ) ) )
2326 {
2327 return SANE_STATUS_INVAL;
2328 }
2329 hpaio->currentResolution = *pIntValue;
2330 break;
2331
2332 case OPTION_CONTRAST:
2333 if( *pIntValue<hpaio->contrastRange.min ||
2334 *pIntValue>hpaio->contrastRange.max )
2335 {
2336 return SANE_STATUS_INVAL;
2337 }
2338 hpaio->currentContrast = *pIntValue;
2339 break;
2340 case OPTION_BRIGHTNESS:
2341 if( *pIntValue<hpaio->brightnessRange.min ||
2342 *pIntValue>hpaio->brightnessRange.max )
2343 {
2344 return SANE_STATUS_INVAL;
2345 }
2346 hpaio->currentBrightness = *pIntValue;
2347 break;
2348
2349 case OPTION_COMPRESSION:
2350 {
2351 int supportedCompression = hpaio->supportsScanMode[hpaio->currentScanMode];
2352 if( !strcasecmp( pStrValue, STR_COMPRESSION_NONE ) &&
2353 supportedCompression & COMPRESSION_NONE )
2354 {
2355 hpaio->currentCompression = COMPRESSION_NONE;
2356 break;
2357 }
2358 if( !strcasecmp( pStrValue, STR_COMPRESSION_MH ) &&
2359 supportedCompression & COMPRESSION_MH )
2360 {
2361 hpaio->currentCompression = COMPRESSION_MH;
2362 break;
2363 }
2364 if( !strcasecmp( pStrValue, STR_COMPRESSION_MR ) &&
2365 supportedCompression & COMPRESSION_MR )
2366 {
2367 hpaio->currentCompression = COMPRESSION_MR;
2368 break;
2369 }
2370 if( !strcasecmp( pStrValue, STR_COMPRESSION_MMR ) &&
2371 supportedCompression & COMPRESSION_MMR )
2372 {
2373 hpaio->currentCompression = COMPRESSION_MMR;
2374 break;
2375 }
2376 if( !strcasecmp( pStrValue, STR_COMPRESSION_JPEG ) &&
2377 supportedCompression & COMPRESSION_JPEG )
2378 {
2379 hpaio->currentCompression = COMPRESSION_JPEG;
2380 break;
2381 }
2382 return SANE_STATUS_INVAL;
2383 }
2384
2385 case OPTION_JPEG_COMPRESSION_FACTOR:
2386 if( *pIntValue<MIN_JPEG_COMPRESSION_FACTOR ||
2387 *pIntValue>MAX_JPEG_COMPRESSION_FACTOR )
2388 {
2389 return SANE_STATUS_INVAL;
2390 }
2391 hpaio->currentJpegCompressionFactor = *pIntValue;
2392 break;
2393
2394 case OPTION_BATCH_SCAN:
2395 if( *pIntValue != SANE_FALSE && *pIntValue != SANE_TRUE )
2396 {
2397 return SANE_STATUS_INVAL;
2398 }
2399 hpaio->currentBatchScan = *pIntValue;
2400 break;
2401
2402 case OPTION_ADF_MODE:
2403 if( !strcasecmp( pStrValue, STR_ADF_MODE_AUTO ) &&
2404 hpaio->supportedAdfModes & ADF_MODE_AUTO )
2405 {
2406 hpaio->currentAdfMode = ADF_MODE_AUTO;
2407 break;
2408 }
2409 if( !strcasecmp( pStrValue, STR_ADF_MODE_FLATBED ) &&
2410 hpaio->supportedAdfModes & ADF_MODE_FLATBED )
2411 {
2412 hpaio->currentAdfMode = ADF_MODE_FLATBED;
2413 break;
2414 }
2415 if( !strcasecmp( pStrValue, STR_ADF_MODE_ADF ) &&
2416 hpaio->supportedAdfModes & ADF_MODE_ADF )
2417 {
2418 hpaio->currentAdfMode = ADF_MODE_ADF;
2419 break;
2420 }
2421 return SANE_STATUS_INVAL;
2422 #if 1
2423 case OPTION_DUPLEX:
2424 if( *pIntValue != SANE_FALSE && *pIntValue != SANE_TRUE )
2425 {
2426 return SANE_STATUS_INVAL;
2427 }
2428 hpaio->currentDuplex = *pIntValue;
2429 break;
2430 #endif
2431 case OPTION_LENGTH_MEASUREMENT:
2432 if( !strcasecmp( pStrValue,
2433 STR_LENGTH_MEASUREMENT_UNKNOWN ) )
2434 {
2435 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_UNKNOWN;
2436 break;
2437 }
2438 if( !strcasecmp( pStrValue,
2439 STR_LENGTH_MEASUREMENT_UNLIMITED ) )
2440 {
2441 if( hpaio->scannerType != SCANNER_TYPE_PML )
2442 {
2443 return SANE_STATUS_INVAL;
2444 }
2445 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_UNLIMITED;
2446 break;
2447 }
2448 if( !strcasecmp( pStrValue,
2449 STR_LENGTH_MEASUREMENT_APPROXIMATE ) )
2450 {
2451 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_APPROXIMATE;
2452 break;
2453 }
2454 if( !strcasecmp( pStrValue, STR_LENGTH_MEASUREMENT_PADDED ) )
2455 {
2456 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_PADDED;
2457 break;
2458 }
2459 if( !strcasecmp( pStrValue, STR_LENGTH_MEASUREMENT_EXACT ) )
2460 {
2461 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_EXACT;
2462 break;
2463 }
2464 return SANE_STATUS_INVAL;
2465
2466 case OPTION_TL_X:
2467 if( *pIntValue<hpaio->tlxRange.min ||
2468 *pIntValue>hpaio->tlxRange.max )
2469 {
2470 return SANE_STATUS_INVAL;
2471 }
2472 hpaio->currentTlx = *pIntValue;
2473 break;
2474
2475 case OPTION_TL_Y:
2476 if( *pIntValue<hpaio->tlyRange.min ||
2477 *pIntValue>hpaio->tlyRange.max )
2478 {
2479 return SANE_STATUS_INVAL;
2480 }
2481 hpaio->currentTly = *pIntValue;
2482 break;
2483
2484 case OPTION_BR_X:
2485 if( *pIntValue<hpaio->brxRange.min ||
2486 *pIntValue>hpaio->brxRange.max )
2487 {
2488 return SANE_STATUS_INVAL;
2489 }
2490 hpaio->currentBrx = *pIntValue;
2491 break;
2492
2493 case OPTION_BR_Y:
2494 if( *pIntValue<hpaio->bryRange.min ||
2495 *pIntValue>hpaio->bryRange.max )
2496 {
2497 return SANE_STATUS_INVAL;
2498 }
2499 hpaio->currentBry = *pIntValue;
2500 break;
2501
2502 default:
2503 return SANE_STATUS_INVAL;
2504 }
2505 goto reload;
2506
2507 case SANE_ACTION_SET_AUTO:
2508 retcode = hpaioSetDefaultValue( hpaio, option );
2509 if( retcode != SANE_STATUS_GOOD )
2510 {
2511 return retcode;
2512 }
2513 reload : *pInfo = hpaioUpdateDescriptors( hpaio, option );
2514 break;
2515
2516 default:
2517 return SANE_STATUS_INVAL;
2518 }
2519
2520 DBG(8, "sane_hpaio_control_option (option=%s action=%s value=%s): %s %d\n", hpaio->option[option].name,
2521 action==SANE_ACTION_GET_VALUE ? "get" : action==SANE_ACTION_SET_VALUE ? "set" : "auto",
2522 pValue ? hpaio->option[option].type == SANE_TYPE_STRING ? (char *)pValue : psnprintf(sz, sizeof(sz), "%d", *(int *)pValue) : "na", __FILE__, __LINE__);
2523
2524 return SANE_STATUS_GOOD;
2525 }
2526
sclpml_get_parameters(SANE_Handle handle,SANE_Parameters * pParams)2527 SANE_Status sclpml_get_parameters(SANE_Handle handle, SANE_Parameters *pParams)
2528 {
2529 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
2530 char *s = "";
2531
2532 if( !hpaio->hJob )
2533 {
2534 *pParams = hpaio->prescanParameters;
2535 s = "pre";
2536 }
2537 else
2538 {
2539 *pParams = hpaio->scanParameters;
2540 }
2541 DBG(8, "sane_hpaio_get_parameters(%sscan): format=%d, last_frame=%d, lines=%d, depth=%d, pixels_per_line=%d, bytes_per_line=%d %s %d\n",
2542 s, pParams->format, pParams->last_frame, pParams->lines, pParams->depth, pParams->pixels_per_line, pParams->bytes_per_line, __FILE__, __LINE__);
2543
2544 return SANE_STATUS_GOOD;
2545 }
2546
sclpml_start(SANE_Handle handle)2547 SANE_Status sclpml_start(SANE_Handle handle)
2548 {
2549 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
2550 SANE_Status retcode;
2551 IP_IMAGE_TRAITS traits;
2552 IP_XFORM_SPEC xforms[IP_MAX_XFORMS], * pXform = xforms;
2553 WORD wResult;
2554
2555 DBG(8, "sane_hpaio_start(): %s %d deviceuri=%s\n", __FILE__, __LINE__, hpaio->deviceuri);
2556
2557 hpaio->user_cancel = FALSE;
2558
2559 hpaio->endOfData = 0;
2560
2561 if (hpaio->scannerType==SCANNER_TYPE_PML)
2562 return pml_start(hpaio);
2563
2564 /* TODO: convert to scl_start. des */
2565
2566 /* If we just scanned the last page of a batch scan, then return the obligatory SANE_STATUS_NO_DOCS condition. */
2567 if( hpaio->noDocsConditionPending )
2568 {
2569 hpaio->noDocsConditionPending = 0;
2570 retcode = SANE_STATUS_NO_DOCS;
2571 goto abort;
2572 }
2573 /* Open scanner command channel. */
2574 retcode = hpaioConnPrepareScan( hpaio );
2575
2576 if( retcode != SANE_STATUS_GOOD )
2577 {
2578 goto abort;
2579 }
2580 /* Change document if needed. */
2581 hpaio->beforeScan = 1;
2582 retcode = hpaioAdvanceDocument( hpaio );
2583 hpaio->beforeScan = 0;
2584
2585 if( retcode != SANE_STATUS_GOOD )
2586 {
2587 goto abort;
2588 }
2589
2590 /* Program options. */
2591 retcode = hpaioProgramOptions( hpaio );
2592
2593 if( retcode != SANE_STATUS_GOOD )
2594 {
2595 goto abort;
2596 }
2597
2598 hpaio->scanParameters = hpaio->prescanParameters;
2599 memset( xforms, 0, sizeof( xforms ) );
2600 traits.iPixelsPerRow = -1;
2601
2602 switch( hpaio->effectiveScanMode )
2603 {
2604 case SCAN_MODE_LINEART:
2605 hpaio->scanParameters.format = SANE_FRAME_GRAY;
2606 hpaio->scanParameters.depth = 1;
2607 traits.iBitsPerPixel = 1;
2608 break;
2609 case SCAN_MODE_GRAYSCALE:
2610 hpaio->scanParameters.format = SANE_FRAME_GRAY;
2611 hpaio->scanParameters.depth = 8;
2612 traits.iBitsPerPixel = 8;
2613 break;
2614 case SCAN_MODE_COLOR:
2615 default:
2616 hpaio->scanParameters.format = SANE_FRAME_RGB;
2617 hpaio->scanParameters.depth = 8;
2618 traits.iBitsPerPixel = 24;
2619 break;
2620 }
2621 traits.lHorizDPI = hpaio->effectiveResolution << 16;
2622 traits.lVertDPI = hpaio->effectiveResolution << 16;
2623 traits.lNumRows = -1;
2624 traits.iNumPages = 1;
2625 traits.iPageNum = 1;
2626
2627 int lines, pixelsPerLine;
2628
2629 /* Inquire exact image dimensions. */
2630 if( SclInquire( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_INQUIRE_DEVICE_PARAMETER, SCL_INQ_NUMBER_OF_SCAN_LINES,
2631 &lines, 0, 0 ) == SANE_STATUS_GOOD )
2632 {
2633 traits.lNumRows = lines;
2634 }
2635 SclInquire( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_INQUIRE_DEVICE_PARAMETER, SCL_INQ_PIXELS_PER_SCAN_LINE,
2636 &pixelsPerLine, 0, 0 );
2637
2638 traits.iPixelsPerRow = pixelsPerLine;
2639
2640 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_CLEAR_ERROR_STACK, 0 );
2641
2642 /* Start scanning. */
2643 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_SCAN_WINDOW, 0 );
2644
2645 if( hpaio->mfpdtf )
2646 {
2647 MfpdtfSetChannel( hpaio->mfpdtf, hpaio->scan_channelid );
2648
2649 //MfpdtfReadSetTimeout( hpaio->mfpdtf, MFPDTF_EARLY_READ_TIMEOUT );
2650 MfpdtfReadStart( hpaio->mfpdtf ); /* inits mfpdtf */
2651
2652 #ifdef HPAIO_DEBUG
2653 int log_output=1;
2654 #else
2655 int log_output=0;
2656 #endif
2657
2658 if( log_output )
2659 {
2660 char f[MAX_FILE_PATH_LEN];
2661 static int cnt=0;
2662
2663 if (getenv("HOME"))
2664 sprintf(f, "%s/.hplip/mfpdtf_%d.out", getenv("HOME"), cnt++);
2665 else
2666 sprintf(f, "/tmp/mfpdtf_%d.out", cnt++);
2667
2668 bug("saving raw image to %s \n", f);
2669
2670 MfpdtfLogToFile( hpaio->mfpdtf, f );
2671 }
2672
2673 while( 1 )
2674 {
2675 int rService, sopEncoding;
2676
2677 rService = MfpdtfReadService( hpaio->mfpdtf );
2678
2679 if( retcode != SANE_STATUS_GOOD )
2680 {
2681 goto abort;
2682 }
2683
2684 if( rService & MFPDTF_RESULT_ERROR_MASK )
2685 {
2686 retcode = SANE_STATUS_IO_ERROR;
2687 goto abort;
2688 }
2689
2690 if( rService & MFPDTF_RESULT_NEW_VARIANT_HEADER && hpaio->preDenali )
2691 {
2692 union MfpdtfVariantHeader_u vheader;
2693 MfpdtfReadGetVariantHeader( hpaio->mfpdtf, &vheader, sizeof( vheader ) );
2694
2695 traits.iPixelsPerRow = LEND_GET_SHORT( vheader.faxArtoo.pixelsPerRow );
2696 traits.iBitsPerPixel = 1;
2697
2698 switch( vheader.faxArtoo.dataCompression )
2699 {
2700 case MFPDTF_RASTER_MH:
2701 sopEncoding = MFPDTF_RASTER_MH;
2702 break;
2703 case MFPDTF_RASTER_MR:
2704 sopEncoding = MFPDTF_RASTER_MR;
2705 break;
2706 case MFPDTF_RASTER_MMR:
2707 default:
2708 sopEncoding = MFPDTF_RASTER_MMR;
2709 break;
2710 }
2711 goto setupDecoder;
2712 }
2713 else if( rService & MFPDTF_RESULT_NEW_START_OF_PAGE_RECORD )
2714 {
2715 if( hpaio->currentCompression == COMPRESSION_NONE )
2716 {
2717 goto rawDecode;
2718 }
2719 else /* if (hpaio->currentCompression==COMPRESSION_JPEG) */
2720 {
2721 goto jpegDecode;
2722 }
2723
2724 /* Read SOP record and set image pipeline input traits. */
2725 // MfpdtfReadGetStartPageRecord( hpaio->mfpdtf, &sop, sizeof( sop ) );
2726 // traits.iPixelsPerRow = LEND_GET_SHORT( sop.black.pixelsPerRow );
2727 // traits.iBitsPerPixel = LEND_GET_SHORT( sop.black.bitsPerPixel );
2728 // traits.lHorizDPI = LEND_GET_LONG( sop.black.xres );
2729 // traits.lVertDPI = LEND_GET_LONG( sop.black.yres );
2730 // sopEncoding = sop.encoding;
2731
2732 setupDecoder:
2733 /* Set up image-processing pipeline. */
2734 switch( sopEncoding )
2735 {
2736 case MFPDTF_RASTER_MH:
2737 pXform->aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MH;
2738 ADD_XFORM( X_FAX_DECODE );
2739 break;
2740 case MFPDTF_RASTER_MR:
2741 pXform->aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MR;
2742 ADD_XFORM( X_FAX_DECODE );
2743 break;
2744 case MFPDTF_RASTER_MMR:
2745 pXform->aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MMR;
2746 ADD_XFORM( X_FAX_DECODE );
2747 break;
2748
2749 case MFPDTF_RASTER_BITMAP:
2750 case MFPDTF_RASTER_GRAYMAP:
2751 case MFPDTF_RASTER_RGB:
2752 rawDecode:
2753 break;
2754
2755 case MFPDTF_RASTER_JPEG:
2756 jpegDecode:
2757 pXform->aXformInfo[IP_JPG_DECODE_FROM_DENALI].dword = hpaio->fromDenali;
2758 ADD_XFORM( X_JPG_DECODE );
2759
2760 pXform->aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_YCC_TO_SRGB;
2761 pXform->aXformInfo[IP_CNV_COLOR_SPACE_GAMMA].dword = 0x00010000;
2762 ADD_XFORM( X_CNV_COLOR_SPACE );
2763 break;
2764
2765 case MFPDTF_RASTER_YCC411:
2766 case MFPDTF_RASTER_PCL:
2767 case MFPDTF_RASTER_NOT:
2768 default:
2769 /* Skip processing for unknown encodings. */
2770 bug("unknown image encoding sane_start: name=%s sop=%d %s %d\n", hpaio->saneDevice.name,sopEncoding, __FILE__, __LINE__);
2771 }
2772 continue;
2773 }
2774
2775 if( rService & MFPDTF_RESULT_IMAGE_DATA_PENDING )
2776 {
2777 /*MfpdtfReadSetTimeout( hpaio->mfpdtf, MFPDTF_LATER_READ_TIMEOUT );*/
2778 break;
2779 }
2780 }
2781 }
2782 hpaio->scanParameters.pixels_per_line = traits.iPixelsPerRow;
2783 hpaio->scanParameters.lines = traits.lNumRows;
2784
2785 if( hpaio->scanParameters.lines < 0 )
2786 {
2787 hpaio->scanParameters.lines = MILLIMETERS_TO_PIXELS( hpaio->bryRange.max,
2788 hpaio->effectiveResolution );
2789 }
2790
2791 /* We have to invert bilevel data from SCL scanners. */
2792 if( hpaio->effectiveScanMode == SCAN_MODE_LINEART )
2793 {
2794 ADD_XFORM( X_INVERT );
2795 }
2796 else /* if (hpaio->effectiveScanMode==SCAN_MODE_COLOR) */
2797 {
2798 /* Do gamma correction on OfficeJet Pro 11xx. */
2799 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 ) )
2800 {
2801 pXform->aXformInfo[IP_TABLE_WHICH].dword = IP_TABLE_USER;
2802 pXform->aXformInfo[IP_TABLE_OPTION].pvoid = ( char * )hp11xxSeriesGammaTable;
2803 ADD_XFORM( X_TABLE );
2804 }
2805 }
2806
2807 if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_PADDED )
2808 {
2809 pXform->aXformInfo[IP_PAD_LEFT].dword = 0;
2810 pXform->aXformInfo[IP_PAD_RIGHT].dword = 0;
2811 pXform->aXformInfo[IP_PAD_TOP].dword = 0;
2812 pXform->aXformInfo[IP_PAD_BOTTOM].dword = 0;
2813 pXform->aXformInfo[IP_PAD_VALUE].dword = ( hpaio->effectiveScanMode == SCAN_MODE_LINEART ) ? PAD_VALUE_LINEART : PAD_VALUE_GRAYSCALE_COLOR;
2814 pXform->aXformInfo[IP_PAD_MIN_HEIGHT].dword = hpaio->scanParameters.lines;
2815 ADD_XFORM( X_PAD );
2816 }
2817
2818 /* If we didn't set up any xforms by now, then add the dummy "skel" xform to simplify our subsequent code path. */
2819 if( pXform == xforms )
2820 {
2821 ADD_XFORM( X_SKEL );
2822 }
2823
2824 wResult = ipOpen( pXform - xforms, xforms, 0, &hpaio->hJob );
2825
2826 if( wResult != IP_DONE || !hpaio->hJob )
2827 {
2828 retcode = SANE_STATUS_INVAL;
2829 goto abort;
2830 }
2831
2832 traits.iComponentsPerPixel = ( ( traits.iBitsPerPixel % 3 ) ? 1 : 3 );
2833 wResult = ipSetDefaultInputTraits( hpaio->hJob, &traits );
2834
2835 if( wResult != IP_DONE )
2836 {
2837 retcode = SANE_STATUS_INVAL;
2838 goto abort;
2839 }
2840
2841 hpaio->scanParameters.bytes_per_line = BYTES_PER_LINE( hpaio->scanParameters.pixels_per_line,
2842 hpaio->scanParameters.depth * ( hpaio->scanParameters.format == SANE_FRAME_RGB ? 3 : 1 ) );
2843
2844 hpaio->totalBytesRemaining = hpaio->scanParameters.bytes_per_line * hpaio->scanParameters.lines;
2845 hpaio->bufferOffset = 0;
2846 hpaio->bufferBytesRemaining = 0;
2847
2848 if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_UNKNOWN || hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_UNLIMITED )
2849 {
2850 hpaio->scanParameters.lines = -1;
2851 }
2852 else if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_EXACT )
2853 {
2854 /* TODO: Set up spool file, scan the whole image into it,
2855 * and set "hpaio->scanParameters.lines" accordingly.
2856 * Then in sane_hpaio_read, read out of the file. */
2857 }
2858
2859 retcode = SANE_STATUS_GOOD;
2860
2861 abort:
2862
2863 if( retcode != SANE_STATUS_GOOD )
2864 {
2865 if (retcode == SANE_STATUS_NO_DOCS) SendScanEvent (hpaio->deviceuri, EVENT_SCAN_ADF_NO_DOCS);
2866 sane_hpaio_cancel( handle );
2867 }
2868 return retcode;
2869 }
2870
sclpml_read(SANE_Handle handle,SANE_Byte * data,SANE_Int maxLength,SANE_Int * pLength)2871 SANE_Status sclpml_read(SANE_Handle handle, SANE_Byte *data, SANE_Int maxLength, SANE_Int *pLength)
2872 {
2873 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
2874 SANE_Status retcode;
2875 DWORD dwInputAvail;
2876 LPBYTE pbInputBuf;
2877 DWORD dwInputUsed, dwInputNextPos;
2878 DWORD dwOutputAvail = maxLength;
2879 LPBYTE pbOutputBuf = data;
2880 DWORD dwOutputUsed, dwOutputThisPos;
2881 WORD wResult;
2882
2883 if (hpaio->user_cancel) {
2884 bug("sane_hpaio_read(maxLength=%d): User cancelled!\n", maxLength);
2885 return SANE_STATUS_CANCELLED;
2886 }
2887
2888 *pLength = 0;
2889
2890 if( !hpaio->hJob )
2891 {
2892 bug("sane_hpaio_read(maxLength=%d): No scan pending!\n", maxLength);
2893 retcode = SANE_STATUS_EOF;
2894 goto abort;
2895 }
2896
2897 if (hpaio->scannerType==SCANNER_TYPE_PML)
2898 {
2899 retcode = pml_read(hpaio, data, maxLength, pLength);
2900 return retcode;
2901 }
2902
2903 DBG(8, "sane_hpaio_read called handle=%p data=%p maxLength=%d length=%d: %s %d\n", (void *)handle, data, maxLength, *pLength, __FILE__, __LINE__);
2904
2905 /* TODO: convert to scl_read. des */
2906
2907 needMoreData:
2908 if( hpaio->bufferBytesRemaining <= 0 && !hpaio->endOfData )
2909 {
2910 if( !hpaio->mfpdtf )
2911 {
2912 int r, len = hpaio->totalBytesRemaining;
2913 if( len <= 0 )
2914 {
2915 hpaio->endOfData = 1;
2916 }
2917 else
2918 {
2919 if( len > LEN_BUFFER )
2920 {
2921 len = LEN_BUFFER;
2922 }
2923
2924 r = ReadChannelEx(hpaio->deviceid,
2925 hpaio->scan_channelid,
2926 hpaio->inBuffer,
2927 len,
2928 EXCEPTION_TIMEOUT);
2929
2930 if( r < 0 )
2931 {
2932 retcode = SANE_STATUS_IO_ERROR;
2933 goto abort;
2934 }
2935 hpaio->bufferBytesRemaining = r;
2936 hpaio->totalBytesRemaining -= r;
2937 }
2938 }
2939 else
2940 {
2941 // mfpdtf
2942 int rService;
2943
2944 rService = MfpdtfReadService( hpaio->mfpdtf );
2945
2946 if( rService & MFPDTF_RESULT_ERROR_MASK )
2947 {
2948 // retcode = SANE_STATUS_IO_ERROR;
2949 // goto abort;
2950 hpaio->endOfData = 1; /* display any data (ie: OJ F380 1200dpi non-compressed can timeout after last scan). */
2951 }
2952
2953 if( rService & MFPDTF_RESULT_IMAGE_DATA_PENDING )
2954 {
2955 hpaio->bufferBytesRemaining = MfpdtfReadInnerBlock( hpaio->mfpdtf, hpaio->inBuffer, LEN_BUFFER );
2956
2957 rService = MfpdtfReadGetLastServiceResult( hpaio->mfpdtf );
2958
2959 if( rService & MFPDTF_RESULT_ERROR_MASK )
2960 {
2961 retcode = SANE_STATUS_IO_ERROR;
2962 goto abort;
2963 }
2964 }
2965 else if( rService & MFPDTF_RESULT_NEW_END_OF_PAGE_RECORD || ( rService & MFPDTF_RESULT_END_PAGE && hpaio->preDenali ))
2966 {
2967 hpaio->endOfData = 1;
2968 }
2969
2970 } /* if (!hpaio->mfpdtf) */
2971
2972 hpaio->bufferOffset = 0;
2973 if( hpaio->preDenali )
2974 {
2975 ipMirrorBytes( hpaio->inBuffer, hpaio->bufferBytesRemaining );
2976 }
2977
2978 } /* if( hpaio->bufferBytesRemaining <= 0 && !hpaio->endOfData ) */
2979
2980 dwInputAvail = hpaio->bufferBytesRemaining;
2981
2982 if( hpaio->bufferBytesRemaining <= 0 && hpaio->endOfData )
2983 {
2984 pbInputBuf = 0;
2985 }
2986 else
2987 {
2988 pbInputBuf = hpaio->inBuffer + hpaio->bufferOffset;
2989 }
2990
2991 wResult = ipConvert( hpaio->hJob,
2992 dwInputAvail,
2993 pbInputBuf,
2994 &dwInputUsed,
2995 &dwInputNextPos,
2996 dwOutputAvail,
2997 pbOutputBuf,
2998 &dwOutputUsed,
2999 &dwOutputThisPos );
3000
3001 hpaio->bufferOffset += dwInputUsed;
3002 hpaio->bufferBytesRemaining -= dwInputUsed;
3003 *pLength = dwOutputUsed;
3004
3005 if( wResult & ( IP_INPUT_ERROR | IP_FATAL_ERROR ) )
3006 {
3007 bug("ipConvert error=%x\n", wResult);
3008 retcode = SANE_STATUS_IO_ERROR;
3009 goto abort;
3010 }
3011 if( !dwOutputUsed )
3012 {
3013 if( wResult & IP_DONE )
3014 {
3015 retcode = SANE_STATUS_EOF;
3016 ipClose(hpaio->hJob);
3017 hpaio->hJob = 0;
3018 goto abort;
3019 }
3020 goto needMoreData;
3021 }
3022
3023 retcode = SANE_STATUS_GOOD;
3024
3025 abort:
3026 if(!(retcode == SANE_STATUS_GOOD || retcode == SANE_STATUS_EOF))
3027 {
3028 sane_hpaio_cancel( handle );
3029 }
3030
3031 DBG(8, "sane_hpaio_read returned output=%p outputUsed=%d length=%d status=%d: %s %d\n", pbOutputBuf, dwOutputUsed, *pLength, retcode, __FILE__, __LINE__);
3032
3033 return retcode;
3034 }
3035
sclpml_cancel(SANE_Handle handle)3036 void sclpml_cancel(SANE_Handle handle)
3037 {
3038 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
3039 DBG(8, "sane_hpaio_cancel(): %s %d\n", __FILE__, __LINE__);
3040
3041 if (hpaio->user_cancel) {
3042 bug("sane_hpaio_cancel: already cancelled!\n");
3043 }
3044 hpaio->user_cancel = TRUE;
3045
3046 if (hpaio->scannerType==SCANNER_TYPE_PML)
3047 {
3048 pml_cancel(hpaio);
3049 return ;
3050 }
3051
3052 /* TODO: convert to scl_cancel. des */
3053
3054 if( hpaio->mfpdtf )
3055 {
3056 MfpdtfLogToFile( hpaio->mfpdtf, 0 );
3057 //MfpdtfDeallocate( hpaio->mfpdtf );
3058 }
3059
3060 if( hpaio->hJob )
3061 {
3062 ipClose( hpaio->hJob );
3063 hpaio->hJob = 0;
3064 }
3065
3066 /* Do not close pml/scan channels if in batch mode. */
3067 if (hpaio->currentBatchScan != SANE_TRUE && hpaio->cmd_channelid > 0)
3068 hpaioConnEndScan(hpaio);
3069 }
3070