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