~ubuntu-branches/ubuntu/saucy/hplip/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/hpaio-option-duplex.diff/scan/sane/hpaio.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-05-26 11:20:39 UTC
  • mfrom: (1.5.6) (31.1.3 precise)
  • Revision ID: package-import@ubuntu.com-20120526112039-bevxczegxnbyr5m7
Tags: 3.12.4-1
* New upstream release
* Switch to source/format 3.0 (quilt) - drop dpatch
* Refreshed debian/patches
* dh_autoreconf debian/autogen.sh & set local-options single-debian-patch
* Update to debian/compat -> 9
* Fix "hardened build flags" patch from Moritz - thanks (Closes: #667828)
* Fix "duplex descriptor uninitialized" patch from Matej (Closes: #583273)
* Fix "please migrate to kde-runtime" patch from Pino (Closes: #666544)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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