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