1 /************************************************************************************\
3 hpaio.c - HP SANE backend for multi-function peripherals (libsane-hpaio)
5 (c) 2001-2008 Copyright Hewlett-Packard Development Company, LP
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:
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
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.
24 Contributing Authors: David Paschal, Don Welch, David Suffield, Narla Naga Samrat Chowdary,
25 Yashwant Sahu, Sarbeswar Meher
27 \************************************************************************************/
39 #include <sys/types.h>
43 #include <cups/cups.h>
58 #define DEBUG_DECLARE_ONLY
59 #include "sanei_debug.h"
61 static SANE_Device **DeviceList = NULL;
63 static hpaioScanner_t FirstScanner = 0;
64 static hpaioScanner_t LastScanner = 0;
66 static int ResetDeviceList(SANE_Device ***pd)
72 for (i=0; (*pd)[i] && i<MAX_DEVICE; i++)
75 free((void *)(*pd)[i]->name);
77 free((void *)(*pd)[i]->model);
87 static int AddDeviceList(char *uri, char *model, SANE_Device ***pd)
93 /* Allocate array of pointers. */
94 *pd = malloc(sizeof(SANE_Device *) * MAX_DEVICE);
95 memset(*pd, 0, sizeof(SANE_Device *) * MAX_DEVICE);
98 /* Find empty slot in array of pointers. */
99 for (i=0; i<MAX_DEVICE; i++)
101 if ((*pd)[i] == NULL)
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";
117 static int AddCupsList(char *uri, char ***printer)
121 /* Look for hp network URIs only. */
122 if (strncasecmp(uri, "hp:/net/", 8) !=0)
125 if (*printer == NULL)
127 /* Allocate array of string pointers. */
128 *printer = malloc(sizeof(char *) * MAX_DEVICE);
129 memset(*printer, 0, sizeof(char *) * MAX_DEVICE);
132 /* Ignor duplicates (ie: printer queues using the same device). */
133 for (i=0; (*printer)[i] != NULL && i<MAX_DEVICE; i++)
135 if (strcmp((*printer)[i], uri) == 0)
139 /* Find empty slot in array of pointers. */
140 for (i=0; i<MAX_DEVICE; i++)
142 if ((*printer)[i] == NULL)
144 (*printer)[i] = strdup(uri);
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)
160 int maxBuf = HPMUD_LINE_SIZE*64;
164 if (strncasecmp(&buf[i], "direct ", 7) == 0)
168 for (; buf[i] == ' ' && i < maxBuf; i++); /* eat white space before string */
169 while ((buf[i] != ' ') && (i < maxBuf) && (j < HPMUD_LINE_SIZE))
173 for (; buf[i] != '\n' && i < maxBuf; i++); /* eat rest of line */
177 for (; buf[i] != '\n' && i < maxBuf; i++); /* eat line */
180 i++; /* bump past '\n' */
183 *tail = buf + i; /* tail points to next line */
188 static int GetCupsPrinters(char ***printer)
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 */
196 /* Connect to the HTTP server */
197 if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL)
200 /* Assemble the IPP request */
203 request->request.op.operation_id = CUPS_GET_PRINTERS;
204 request->request.any.request_id = 1;
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");
210 /* Send the request and get a response. */
211 if ((response = cupsDoRequest(http, request, "/")) == NULL)
214 for (attr = response->attrs; attr != NULL; attr = attr->next)
216 /* Skip leading attributes until we hit a printer. */
217 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
223 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
225 if (strcmp(attr->name, "device-uri") == 0 && attr->value_tag == IPP_TAG_URI && AddCupsList(attr->values[0].string.text, printer) == 0)
240 static int DevDiscovery(int localOnly)
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];
247 int i, scan_type, cnt=0, total=0, bytes_read;
248 char **cups_printer=NULL; /* list of printers */
249 enum HPMUD_RESULT stat;
251 stat = hpmud_probe_devices(HPMUD_BUS_ALL, message, sizeof(message), &cnt, &bytes_read);
253 if (stat != HPMUD_R_OK)
256 /* Look for local all-in-one scan devices (defined by hpmud). */
258 for (i=0; i<cnt; i++)
261 GetUriLine(tail, uri, &tail);
262 hpmud_query_model(uri, &ma);
265 hpmud_get_uri_model(uri, model, sizeof(model));
266 AddDeviceList(uri, model, &DeviceList);
271 DBG(6,"unsupported scantype=%d %s\n", ma.scantype, uri);
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++)
279 hpmud_query_model(cups_printer[i], &ma);
282 hpmud_get_uri_model(cups_printer[i], model, sizeof(model));
283 AddDeviceList(cups_printer[i], model, &DeviceList);
288 DBG(6,"unsupported scantype=%d %s\n", ma.scantype, cups_printer[i]);
290 free(cups_printer[i]);
299 static void hpaioAddScanner( hpaioScanner_t scanner )
303 FirstScanner = scanner;
305 scanner->prev = LastScanner;
309 LastScanner->next = scanner;
311 LastScanner = scanner;
314 static hpaioScanner_t hpaioFindScanner( SANE_String_Const name )
316 hpaioScanner_t p = FirstScanner;
320 if( strcasecmp( name, p->saneDevice.name ) == 0 )
329 SANE_Status __attribute__ ((visibility ("hidden"))) hpaioScannerToSaneError( hpaioScanner_t hpaio )
333 if( hpaio->scannerType == SCANNER_TYPE_SCL )
337 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
338 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
339 SCL_INQ_CURRENT_ERROR,
344 if( retcode == SANE_STATUS_UNSUPPORTED )
346 retcode = SANE_STATUS_GOOD;
348 else if( retcode == SANE_STATUS_GOOD )
350 bug("hpaio: hpaioScannerToSaneError: sclError=%d.\n", sclError);
353 case SCL_ERROR_UNRECOGNIZED_COMMAND:
354 case SCL_ERROR_PARAMETER_ERROR:
355 retcode = SANE_STATUS_UNSUPPORTED;
358 case SCL_ERROR_NO_MEMORY:
359 retcode = SANE_STATUS_NO_MEM;
362 case SCL_ERROR_CANCELLED:
363 retcode = SANE_STATUS_CANCELLED;
366 case SCL_ERROR_PEN_DOOR_OPEN:
367 retcode = SANE_STATUS_COVER_OPEN;
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;
377 case SCL_ERROR_PAPER_NOT_LOADED:
378 retcode = SANE_STATUS_NO_DOCS;
382 retcode = SANE_STATUS_IO_ERROR;
387 else /* if (hpaio->scannerType==SCANNER_TYPE_PML) */
391 //if( ptalPmlRequestGet( hpaio->pml.objUploadError, 0 ) == ERROR )
392 if( PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid, hpaio->pml.objUploadError ) == ERROR )
394 retcode = SANE_STATUS_GOOD;
396 else if( PmlGetIntegerValue( hpaio->pml.objUploadError,
398 &pmlError ) == ERROR )
400 bug("hpaio: hpaioScannerToSaneError: PmlGetIntegerValue failed, type=%d!\n", type);
401 retcode = SANE_STATUS_IO_ERROR;
405 bug("hpaio: hpaioScannerToSaneError: pmlError=%d.\n", pmlError);
409 case PML_UPLOAD_ERROR_SCANNER_JAM:
410 retcode = SANE_STATUS_JAMMED;
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;
419 case PML_UPLOAD_ERROR_NO_DOC_IN_ADF:
420 case PML_UPLOAD_ERROR_DOC_LOADED:
421 retcode = SANE_STATUS_NO_DOCS;
424 case PML_UPLOAD_ERROR_COVER_OPEN:
425 retcode = SANE_STATUS_COVER_OPEN;
428 case PML_UPLOAD_ERROR_DEVICE_BUSY:
429 retcode = SANE_STATUS_DEVICE_BUSY;
433 retcode = SANE_STATUS_IO_ERROR;
443 SANE_Status __attribute__ ((visibility ("hidden"))) hpaioScannerToSaneStatus( hpaioScanner_t hpaio )
449 // if( hpaio->scannerType == SCANNER_TYPE_SCL )
453 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
454 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
455 SCL_INQ_ADF_FEED_STATUS,
460 if( retcode == SANE_STATUS_UNSUPPORTED )
462 retcode = SANE_STATUS_GOOD;
464 else if( retcode == SANE_STATUS_GOOD )
468 case SCL_ADF_FEED_STATUS_OK:
469 retcode = SANE_STATUS_GOOD;
472 case SCL_ADF_FEED_STATUS_BUSY:
473 /* retcode=SANE_STATUS_DEVICE_BUSY; */
474 retcode = SANE_STATUS_GOOD;
477 case SCL_ADF_FEED_STATUS_PAPER_JAM:
478 case SCL_ADF_FEED_STATUS_ORIGINAL_ON_GLASS:
479 retcode = SANE_STATUS_JAMMED;
482 case SCL_ADF_FEED_STATUS_PORTRAIT_FEED:
483 retcode = SANE_STATUS_UNSUPPORTED;
487 retcode = SANE_STATUS_IO_ERROR;
495 static int hpaioScannerIsUninterruptible( hpaioScanner_t hpaio,
501 pUploadState = &uploadState;
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 ) );
514 static SANE_Status hpaioResetScanner( hpaioScanner_t hpaio )
518 if( hpaio->scannerType == SCANNER_TYPE_SCL )
520 retcode = SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_RESET, 0 );
521 if( retcode != SANE_STATUS_GOOD )
525 sleep(1); /* delay for embeded jetdirect scl scanners (ie: PS 3300, PS C7280, PS C6100) */
527 else /* if (hpaio->scannerType==SCANNER_TYPE_PML) */
529 if( !hpaioScannerIsUninterruptible( hpaio, 0 ) )
531 PmlSetIntegerValue( hpaio->pml.objUploadState,
532 PML_TYPE_ENUMERATION,
533 PML_UPLOAD_STATE_IDLE );
535 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
536 hpaio->pml.objUploadState, 0, 0 ) == ERROR )
538 return SANE_STATUS_IO_ERROR;
542 /* Clear upload error for the sake of the LaserJet 1100A. */
543 PmlSetIntegerValue( hpaio->pml.objUploadError,
544 PML_TYPE_SIGNED_INTEGER,
547 PmlRequestSet( hpaio->deviceid, hpaio->cmd_channelid, hpaio->pml.objUploadError ); /* No retry. */
550 return SANE_STATUS_GOOD;
553 static PmlObject_t hpaioPmlAllocate( hpaioScanner_t hpaio )
555 int size = sizeof( struct PmlObject_s );
558 /* Malloc and zero object. */
559 obj = malloc( size );
561 memset( obj, 0, size );
563 /* Insert into linked list of PML objects for this device. */
564 if( !hpaio->firstPmlObject )
566 hpaio->firstPmlObject = obj;
568 obj->prev = hpaio->lastPmlObject;
570 if( hpaio->lastPmlObject )
572 hpaio->lastPmlObject->next = obj;
574 hpaio->lastPmlObject = obj;
579 static PmlObject_t hpaioPmlAllocateID( hpaioScanner_t hpaio, char * oid )
581 PmlObject_t obj = hpaioPmlAllocate( hpaio );
585 bug("hpaioPmlAllocateID: out of memory!\n");
588 PmlSetID( obj, oid );
593 static void hpaioPmlDeallocateObjects( hpaioScanner_t hpaio )
596 PmlObject_t current, next;
598 current = hpaio->firstPmlObject;
602 next = current->next;
610 static SANE_Status hpaioPmlAllocateObjects(hpaioScanner_t hpaio)
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" );
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" );
634 return SANE_STATUS_GOOD;
637 static int hpaioConnClose( hpaioScanner_t hpaio )
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;
647 } // hpaioConnClose()
649 static SANE_Status hpaioConnOpen( hpaioScanner_t hpaio )
652 enum HPMUD_RESULT stat;
654 if (hpaio->scannerType==SCANNER_TYPE_SCL)
656 stat = hpmud_open_channel(hpaio->deviceid, "HP-SCAN", &hpaio->scan_channelid);
657 if(stat != HPMUD_R_OK)
659 bug("failed to open scan channel: %s %d\n", __FILE__, __LINE__);
660 retcode = SANE_STATUS_DEVICE_BUSY;
665 stat = hpmud_open_channel(hpaio->deviceid, "HP-MESSAGE", &hpaio->cmd_channelid);
666 if(stat != HPMUD_R_OK)
668 bug("failed to open pml channel: %s %d\n", __FILE__, __LINE__);
669 retcode = SANE_STATUS_IO_ERROR;
673 retcode = SANE_STATUS_GOOD;
676 if( retcode != SANE_STATUS_GOOD )
678 SendScanEvent( hpaio->deviceuri, EVENT_SCANNER_FAIL);
683 static SANE_Status hpaioConnPrepareScan( hpaioScanner_t hpaio )
688 /* ADF may already have channel(s) open. */
689 if (hpaio->cmd_channelid < 0)
691 retcode = hpaioConnOpen( hpaio );
693 if( retcode != SANE_STATUS_GOOD )
699 retcode = hpaioResetScanner( hpaio );
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 );
709 char buffer[LEN_SCL_BUFFER];
711 struct timeval tv1, tv2;
712 gettimeofday( &tv1, 0 );
714 if( SclInquire( hpaio->deviceid, hpaio->scan_channelid,
715 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
719 LEN_SCL_BUFFER ) != SANE_STATUS_GOOD )
722 return SANE_STATUS_IO_ERROR;
725 gettimeofday( &tv2, 0 );
727 for( j = 0; j < len && buffer[j] == '0'; j++ ) ;
734 if( i >= SCL_PREPARE_SCAN_DEVICE_LOCK_MAX_RETRIES )
736 return SANE_STATUS_DEVICE_BUSY;
739 DBG(8, "hpaioConnPrepareScan: Waiting for device lock %s %d\n", __FILE__, __LINE__);
741 if( ( ( unsigned ) ( tv2.tv_sec - tv1.tv_sec ) ) <= SCL_PREPARE_SCAN_DEVICE_LOCK_DELAY )
743 sleep( SCL_PREPARE_SCAN_DEVICE_LOCK_DELAY );
747 SendScanEvent( hpaio->deviceuri, EVENT_START_SCAN_JOB);
749 return SANE_STATUS_GOOD;
752 static void hpaioConnEndScan( hpaioScanner_t hpaio )
754 hpaioResetScanner( hpaio );
755 hpaioConnClose( hpaio );
757 SendScanEvent( hpaio->deviceuri, EVENT_END_SCAN_JOB);
760 static SANE_Status SetResolutionListSCL(hpaioScanner_t hpaio)
762 int supported_res[] = {50, 75, 100, 150, 200, 300, 600, 1200, 2400, 4800, 9600};
763 int i, len = sizeof(supported_res)/sizeof(int);
765 if (hpaio->currentAdfMode == ADF_MODE_ADF || hpaio->currentAdfMode == ADF_MODE_AUTO)
767 hpaio->resolutionRange.min = hpaio->scl.minResAdf;
768 hpaio->resolutionRange.max = hpaio->scl.maxResAdf;
772 hpaio->resolutionRange.min = hpaio->scl.minRes;
773 hpaio->resolutionRange.max = hpaio->scl.maxRes;
776 DBG(6,"minRes=%d maxRes=%d minResAdf=%d maxResAdf=%d\n", hpaio->scl.minRes, hpaio->scl.maxRes, hpaio->scl.minResAdf, hpaio->scl.maxResAdf);
778 NumListClear( hpaio->resolutionList );
779 NumListClear( hpaio->lineartResolutionList );
780 for (i = 0; i < len; i++)
782 if (supported_res[i] >= hpaio->resolutionRange.min &&
783 supported_res[i] <= hpaio->resolutionRange.max)
785 NumListAdd (hpaio->resolutionList, supported_res[i]);
786 NumListAdd (hpaio->lineartResolutionList, supported_res[i]);
789 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
791 return SANE_STATUS_GOOD;
794 static SANE_Status hpaioSetDefaultValue( hpaioScanner_t hpaio, int option )
798 case OPTION_SCAN_MODE:
799 if( hpaio->supportsScanMode[SCAN_MODE_COLOR] )
801 hpaio->currentScanMode = SCAN_MODE_COLOR;
803 else if( hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] )
805 hpaio->currentScanMode = SCAN_MODE_GRAYSCALE;
807 else /* if (hpaio->supportsScanMode[SCAN_MODE_LINEART]) */
809 hpaio->currentScanMode = SCAN_MODE_LINEART;
813 case OPTION_SCAN_RESOLUTION:
814 if( hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type == SANE_CONSTRAINT_WORD_LIST )
816 hpaio->currentResolution = NumListGetFirst( ( SANE_Int * )
817 hpaio->option[OPTION_SCAN_RESOLUTION].constraint.word_list );
821 hpaio->currentResolution = hpaio->resolutionRange.min;
825 case OPTION_CONTRAST:
826 hpaio->currentContrast = hpaio->defaultContrast;
829 case OPTION_COMPRESSION:
832 int supportedCompression = hpaio->supportsScanMode[hpaio->currentScanMode];
833 int defaultCompression = hpaio->defaultCompression[hpaio->currentScanMode];
835 if( supportedCompression & defaultCompression )
837 hpaio->currentCompression = defaultCompression;
839 else if( supportedCompression & COMPRESSION_JPEG )
841 hpaio->currentCompression = COMPRESSION_JPEG;
843 else if( supportedCompression & COMPRESSION_MH )
845 hpaio->currentCompression = COMPRESSION_MH;
847 else if( supportedCompression & COMPRESSION_MR )
849 hpaio->currentCompression = COMPRESSION_MR;
851 else if( supportedCompression & COMPRESSION_MMR )
853 hpaio->currentCompression = COMPRESSION_MMR;
857 hpaio->currentCompression = COMPRESSION_NONE;
862 case OPTION_JPEG_COMPRESSION_FACTOR:
863 hpaio->currentJpegCompressionFactor = hpaio->defaultJpegCompressionFactor;
866 case OPTION_BATCH_SCAN:
867 hpaio->currentBatchScan = SANE_FALSE;
870 case OPTION_ADF_MODE:
871 if( hpaio->supportedAdfModes & ADF_MODE_AUTO )
873 if( hpaio->scannerType == SCANNER_TYPE_PML &&
874 !hpaio->pml.flatbedCapability &&
875 hpaio->supportedAdfModes & ADF_MODE_ADF )
879 hpaio->currentAdfMode = ADF_MODE_AUTO;
881 else if( hpaio->supportedAdfModes & ADF_MODE_FLATBED )
883 hpaio->currentAdfMode = ADF_MODE_FLATBED;
885 else if( hpaio->supportedAdfModes & ADF_MODE_ADF )
888 hpaio->currentAdfMode = ADF_MODE_ADF;
892 hpaio->currentAdfMode = ADF_MODE_AUTO;
897 hpaio->currentDuplex = SANE_FALSE;
900 case OPTION_LENGTH_MEASUREMENT:
901 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_PADDED;
905 hpaio->currentTlx = hpaio->tlxRange.min;
909 hpaio->currentTly = hpaio->tlyRange.min;
913 hpaio->currentBrx = hpaio->brxRange.max;
917 hpaio->currentBry = hpaio->bryRange.max;
921 return SANE_STATUS_INVAL;
924 return SANE_STATUS_GOOD;
927 static int hpaioUpdateDescriptors( hpaioScanner_t hpaio, int option )
929 int initValues = ( option == OPTION_FIRST );
932 /* OPTION_SCAN_MODE: */
935 StrListClear( hpaio->scanModeList );
936 if( hpaio->supportsScanMode[SCAN_MODE_LINEART] )
938 StrListAdd( hpaio->scanModeList, SANE_VALUE_SCAN_MODE_LINEART );
940 if( hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] )
942 StrListAdd( hpaio->scanModeList, SANE_VALUE_SCAN_MODE_GRAY );
944 if( hpaio->supportsScanMode[SCAN_MODE_COLOR] )
946 StrListAdd( hpaio->scanModeList, SANE_VALUE_SCAN_MODE_COLOR );
948 hpaioSetDefaultValue( hpaio, OPTION_SCAN_MODE );
949 reload |= SANE_INFO_RELOAD_OPTIONS;
950 reload |= SANE_INFO_RELOAD_PARAMS;
952 else if( option == OPTION_SCAN_MODE )
954 reload |= SANE_INFO_RELOAD_PARAMS;
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 )
963 SANE_Int ** pList = ( SANE_Int ** ) &hpaio->option[OPTION_SCAN_RESOLUTION].constraint.word_list;
965 if( hpaio->currentScanMode == SCAN_MODE_LINEART )
967 if( *pList != hpaio->lineartResolutionList )
969 *pList = hpaio->lineartResolutionList;
970 reload |= SANE_INFO_RELOAD_OPTIONS;
975 if( *pList != hpaio->resolutionList )
977 *pList = hpaio->resolutionList;
978 reload |= SANE_INFO_RELOAD_OPTIONS;
981 if( initValues || !NumListIsInList( *pList,
982 hpaio->currentResolution ) )
984 hpaioSetDefaultValue( hpaio, OPTION_SCAN_RESOLUTION );
985 reload |= SANE_INFO_RELOAD_OPTIONS;
986 reload |= SANE_INFO_RELOAD_PARAMS;
992 hpaio->currentResolution<hpaio->resolutionRange.min ||
993 hpaio->currentResolution>hpaio->resolutionRange.max )
995 hpaioSetDefaultValue( hpaio, OPTION_SCAN_RESOLUTION );
996 reload |= SANE_INFO_RELOAD_OPTIONS;
997 reload |= SANE_INFO_RELOAD_PARAMS;
1000 if( option == OPTION_SCAN_RESOLUTION )
1002 reload |= SANE_INFO_RELOAD_PARAMS;
1005 /* OPTION_CONTRAST: */
1008 hpaioSetDefaultValue( hpaio, OPTION_CONTRAST );
1011 /* OPTION_COMPRESSION: */
1014 int supportedCompression = hpaio->supportsScanMode[hpaio->currentScanMode];
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 ) ) )
1033 StrListClear( hpaio->compressionList );
1034 if( supportedCompression & COMPRESSION_NONE )
1036 StrListAdd( hpaio->compressionList, STR_COMPRESSION_NONE );
1038 if( supportedCompression & COMPRESSION_MH )
1040 StrListAdd( hpaio->compressionList, STR_COMPRESSION_MH );
1042 if( supportedCompression & COMPRESSION_MR )
1044 StrListAdd( hpaio->compressionList, STR_COMPRESSION_MR );
1046 if( supportedCompression & COMPRESSION_MMR )
1048 StrListAdd( hpaio->compressionList, STR_COMPRESSION_MMR );
1050 if( supportedCompression & COMPRESSION_JPEG )
1052 StrListAdd( hpaio->compressionList, STR_COMPRESSION_JPEG );
1054 hpaioSetDefaultValue( hpaio, OPTION_COMPRESSION );
1055 reload |= SANE_INFO_RELOAD_OPTIONS;
1059 /* OPTION_JPEG_COMPRESSION_FACTOR: */
1061 ( ( hpaio->currentCompression == COMPRESSION_JPEG ) !=
1062 ( ( hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap & SANE_CAP_INACTIVE ) == 0 ) ) )
1064 if( hpaio->currentCompression == COMPRESSION_JPEG )
1066 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap &= ~SANE_CAP_INACTIVE;
1070 hpaio->option[OPTION_JPEG_COMPRESSION_FACTOR].cap |= SANE_CAP_INACTIVE;
1072 hpaioSetDefaultValue( hpaio, OPTION_JPEG_COMPRESSION_FACTOR );
1073 reload |= SANE_INFO_RELOAD_OPTIONS;
1076 /* OPTION_BATCH_SCAN: */
1079 hpaioSetDefaultValue( hpaio, OPTION_BATCH_SCAN );
1080 if( hpaio->preDenali )
1082 hpaio->option[OPTION_BATCH_SCAN].cap |= SANE_CAP_INACTIVE;
1084 reload |= SANE_INFO_RELOAD_OPTIONS;
1086 if( !hpaio->currentBatchScan )
1088 hpaio->noDocsConditionPending = 0;
1091 /* OPTION_ADF_MODE: */
1094 StrListClear( hpaio->adfModeList );
1095 if( hpaio->supportedAdfModes & ADF_MODE_AUTO )
1097 StrListAdd( hpaio->adfModeList, STR_ADF_MODE_AUTO );
1099 if( hpaio->supportedAdfModes & ADF_MODE_FLATBED )
1101 StrListAdd( hpaio->adfModeList, STR_ADF_MODE_FLATBED );
1103 if( hpaio->supportedAdfModes & ADF_MODE_ADF )
1105 StrListAdd( hpaio->adfModeList, STR_ADF_MODE_ADF );
1107 hpaioSetDefaultValue( hpaio, OPTION_ADF_MODE );
1108 reload |= SANE_INFO_RELOAD_OPTIONS;
1112 /* OPTION_DUPLEX: */
1114 ( ( hpaio->supportsDuplex &&
1115 hpaio->currentAdfMode != ADF_MODE_FLATBED ) !=
1116 ( ( hpaio->option[OPTION_DUPLEX].cap & SANE_CAP_INACTIVE ) == 0 ) ) )
1118 if( hpaio->supportsDuplex &&
1119 hpaio->currentAdfMode != ADF_MODE_FLATBED )
1121 hpaio->option[OPTION_DUPLEX].cap &= ~SANE_CAP_INACTIVE;
1125 hpaio->option[OPTION_DUPLEX].cap |= SANE_CAP_INACTIVE;
1127 hpaioSetDefaultValue( hpaio, OPTION_DUPLEX );
1128 reload |= SANE_INFO_RELOAD_OPTIONS;
1132 /* OPTION_LENGTH_MEASUREMENT: */
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 )
1141 StrListAdd( hpaio->lengthMeasurementList,
1142 STR_LENGTH_MEASUREMENT_UNLIMITED );
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); */
1152 /* OPTION_TL_X, OPTION_TL_Y, OPTION_BR_X, OPTION_BR_Y: */
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;
1162 else if( option == OPTION_TL_X ||
1163 option == OPTION_TL_Y ||
1164 option == OPTION_BR_X ||
1165 option == OPTION_BR_Y )
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;
1181 if( ( hpaio->currentLengthMeasurement != LENGTH_MEASUREMENT_UNLIMITED ) !=
1182 ( ( hpaio->option[OPTION_BR_Y].cap & SANE_CAP_INACTIVE ) == 0 ) )
1184 if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_UNLIMITED )
1186 hpaio->option[OPTION_BR_Y].cap |= SANE_CAP_INACTIVE;
1190 hpaio->option[OPTION_BR_Y].cap &= ~SANE_CAP_INACTIVE;
1192 reload |= SANE_INFO_RELOAD_OPTIONS;
1195 /* Pre-scan parameters: */
1196 if( reload & SANE_INFO_RELOAD_PARAMS )
1198 switch( hpaio->currentScanMode )
1200 case SCAN_MODE_LINEART:
1201 hpaio->prescanParameters.format = SANE_FRAME_GRAY;
1202 hpaio->prescanParameters.depth = 1;
1205 case SCAN_MODE_GRAYSCALE:
1206 hpaio->prescanParameters.format = SANE_FRAME_GRAY;
1207 hpaio->prescanParameters.depth = 8;
1210 case SCAN_MODE_COLOR:
1212 hpaio->prescanParameters.format = SANE_FRAME_RGB;
1213 hpaio->prescanParameters.depth = 8;
1216 hpaio->prescanParameters.last_frame = SANE_TRUE;
1219 hpaio->prescanParameters.lines = MILLIMETERS_TO_PIXELS( hpaio->effectiveBry - hpaio->effectiveTly,
1220 hpaio->currentResolution );
1222 hpaio->prescanParameters.pixels_per_line = MILLIMETERS_TO_PIXELS( hpaio->effectiveBrx - hpaio->effectiveTlx,
1223 hpaio->currentResolution );
1225 hpaio->prescanParameters.bytes_per_line = BYTES_PER_LINE( hpaio->prescanParameters.pixels_per_line,
1226 hpaio->prescanParameters.depth * ( hpaio->prescanParameters.format ==
1235 static void hpaioSetupOptions( hpaioScanner_t hpaio )
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;
1246 hpaio->option[GROUP_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
1247 hpaio->option[GROUP_SCAN_MODE].type = SANE_TYPE_GROUP;
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;
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;
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;
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 |
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;
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 |
1302 hpaio->option[OPTION_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1303 hpaio->option[OPTION_COMPRESSION].constraint.string_list = hpaio->compressionList;
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 |
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;
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 |
1330 hpaio->option[OPTION_BATCH_SCAN].constraint_type = SANE_CONSTRAINT_NONE;
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 |
1341 hpaio->option[OPTION_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1342 hpaio->option[OPTION_ADF_MODE].constraint.string_list = hpaio->adfModeList;
1344 // Duplex scanning is supported
1345 if (hpaio->supportsDuplex == 1)
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 |
1356 hpaio->option[OPTION_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE;
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;
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 |
1371 hpaio->option[OPTION_LENGTH_MEASUREMENT].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1372 hpaio->option[OPTION_LENGTH_MEASUREMENT].constraint.string_list = hpaio->lengthMeasurementList;
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;
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;
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;
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;
1427 static int hpaioSclSendCommandCheckError( hpaioScanner_t hpaio, int cmd, int param )
1429 SANE_Status retcode;
1431 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_CLEAR_ERROR_STACK, 0 );
1433 retcode = SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, cmd, param );
1435 if( retcode == SANE_STATUS_GOOD &&
1436 ( ( cmd != SCL_CMD_CHANGE_DOCUMENT && cmd != SCL_CMD_UNLOAD_DOCUMENT ) ||
1437 hpaio->beforeScan ) )
1439 retcode = hpaioScannerToSaneError( hpaio );
1445 static SANE_Status hpaioProgramOptions( hpaioScanner_t hpaio )
1449 hpaio->effectiveScanMode = hpaio->currentScanMode;
1450 hpaio->effectiveResolution = hpaio->currentResolution;
1452 // if( hpaio->scannerType == SCANNER_TYPE_SCL )
1454 /* Set output data type and width. */
1455 switch( hpaio->currentScanMode )
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 );
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 );
1475 case SCAN_MODE_COLOR:
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 );
1487 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1489 hpaio->mfpdtf ? SCL_MFPDTF_ON : SCL_MFPDTF_OFF );
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 ) );
1498 /* Set JPEG compression factor. */
1499 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1500 SCL_CMD_SET_JPEG_COMPRESSION_FACTOR,
1501 hpaio->currentJpegCompressionFactor );
1503 /* Set X and Y resolution. */
1504 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1505 SCL_CMD_SET_X_RESOLUTION,
1506 hpaio->currentResolution );
1508 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1509 SCL_CMD_SET_Y_RESOLUTION,
1510 hpaio->currentResolution );
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 ) );
1517 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1518 SCL_CMD_SET_Y_POSITION,
1519 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveTly ) );
1521 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1522 SCL_CMD_SET_X_EXTENT,
1523 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveBrx -
1524 hpaio->effectiveTlx ) );
1526 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1527 SCL_CMD_SET_Y_EXTENT,
1528 MILLIMETERS_TO_DECIPIXELS( hpaio->effectiveBry -
1529 hpaio->effectiveTly ) );
1531 /* Download color map to OfficeJet Pro 11xx. */
1532 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 ) )
1534 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1535 SCL_CMD_SET_DOWNLOAD_TYPE,
1536 SCL_DOWNLOAD_TYPE_COLORMAP );
1538 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1539 SCL_CMD_DOWNLOAD_BINARY_DATA,
1540 sizeof( hp11xxSeriesColorMap ) );
1542 hpmud_write_channel(hpaio->deviceid, hpaio->scan_channelid, hp11xxSeriesColorMap, sizeof(hp11xxSeriesColorMap),
1543 EXCEPTION_TIMEOUT, &bytes_wrote);
1546 /* For OfficeJet R and PSC 500 series, set CCD resolution to 600
1548 if( hpaio->scl.compat & SCL_COMPAT_R_SERIES &&
1549 hpaio->currentScanMode == SCAN_MODE_LINEART )
1551 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid,
1552 SCL_CMD_SET_CCD_RESOLUTION, 600 );
1555 return SANE_STATUS_GOOD;
1558 static SANE_Status hpaioAdvanceDocument(hpaioScanner_t hpaio)
1560 SANE_Status retcode = SANE_STATUS_GOOD;
1561 int documentLoaded = 0;
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__);
1567 if (hpaio->currentAdfMode == ADF_MODE_FLATBED)
1568 goto bugout; /* nothing to do */
1570 /* If there is an ADF see if paper is loaded. */
1571 if (hpaio->supportedAdfModes & ADF_MODE_ADF)
1573 retcode = SclInquire(hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1574 SCL_INQ_ADF_DOCUMENT_LOADED, &documentLoaded, 0, 0);
1576 if (retcode != SANE_STATUS_GOOD)
1580 /* If in Batch mode, by definition we are in ADF mode. */
1581 if (hpaio->currentBatchScan && !documentLoaded)
1583 retcode = SANE_STATUS_NO_DOCS;
1584 goto bugout; /* no paper loaded */
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 */
1591 /* Assume ADF mode. */
1592 if (documentLoaded || (hpaio->currentSideNumber == 2) )
1594 if (hpaio->currentDuplex)
1596 /* Duplex change document. */
1597 if(hpaio->currentSideNumber == 2)
1598 hpaio->currentSideNumber = 1;
1600 hpaio->currentSideNumber = 2;
1602 retcode=hpaioSclSendCommandCheckError(hpaio, SCL_CMD_CHANGE_DOCUMENT, SCL_CHANGE_DOC_DUPLEX);
1606 /* Simplex change document. */
1607 retcode = hpaioSclSendCommandCheckError(hpaio, SCL_CMD_CHANGE_DOCUMENT, SCL_CHANGE_DOC_SIMPLEX);
1609 hpaio->currentPageNumber++;
1612 retcode = SANE_STATUS_NO_DOCS;
1616 DBG(8, "hpaioAdvanceDocument returns %d ADF-loaded=%d: %s %d\n", retcode, documentLoaded, __FILE__, __LINE__);
1621 /******************************************************* SANE API *******************************************************/
1623 extern SANE_Status sane_hpaio_init(SANE_Int * pVersionCode, SANE_Auth_Callback authorize)
1630 DBG(8, "sane_hpaio_init(): %s %d\n", __FILE__, __LINE__);
1634 *pVersionCode = SANE_VERSION_CODE( 1, 0, 0 );
1636 stat = SANE_STATUS_GOOD;
1639 } /* sane_hpaio_init() */
1641 extern void sane_hpaio_exit(void)
1643 DBG(8, "sane_hpaio_exit(): %s %d\n", __FILE__, __LINE__);
1644 ResetDeviceList(&DeviceList);
1647 extern SANE_Status sane_hpaio_get_devices(const SANE_Device ***deviceList, SANE_Bool localOnly)
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;
1656 extern SANE_Status sane_hpaio_open(SANE_String_Const devicename, SANE_Handle * pHandle)
1658 struct hpmud_model_attributes ma;
1659 SANE_Status retcode = SANE_STATUS_INVAL;
1660 hpaioScanner_t hpaio = 0;
1662 char deviceIDString[LEN_DEVICE_ID_STRING];
1664 int forceJpegForGrayAndColor = 0;
1665 int force300dpiForLineart = 0;
1666 int force300dpiForGrayscale = 0;
1667 int supportsMfpdtf = 1;
1668 int modularHardware = 0;
1670 enum HPMUD_RESULT stat;
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);
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);
1686 hpaio = hpaioFindScanner(devicename);
1690 goto done; /* reuse same device, why?? (des) */
1693 hpaio = malloc( sizeof( struct hpaioScanner_s ) );
1697 retcode = SANE_STATUS_NO_MEM;
1701 hpaioAddScanner( hpaio );
1708 memset( hpaio, 0, sizeof( struct hpaioScanner_s ) );
1710 hpaio->tag = "SCL-PML";
1712 stat = hpmud_open_device(devname, ma.mfp_mode, &hpaio->deviceid);
1713 strncpy(hpaio->deviceuri, devname, sizeof(hpaio->deviceuri));
1715 if(stat != HPMUD_R_OK)
1717 retcode = SANE_STATUS_IO_ERROR;
1721 hpaio->scan_channelid = -1;
1722 hpaio->cmd_channelid = -1;
1724 // Set the duplex type supported
1725 if (ma.scantype == HPMUD_SCANTYPE_SCL_DUPLEX)
1726 hpaio->supportsDuplex = 1;
1728 hpaio->supportsDuplex = 0;
1730 /* Get the device ID string and initialize the SANE_Device structure. */
1731 memset(deviceIDString, 0, sizeof(deviceIDString));
1733 if(hpmud_get_device_id(hpaio->deviceid, deviceIDString, sizeof(deviceIDString), &bytes_read) != HPMUD_R_OK)
1735 retcode = SANE_STATUS_INVAL;
1739 DBG(6, "device ID string=<%s>: %s %d\n", deviceIDString, __FILE__, __LINE__);
1741 hpaio->saneDevice.name = strdup( devicename );
1743 hpaio->saneDevice.vendor = "Hewlett-Packard";
1745 hpmud_get_model(deviceIDString, model, sizeof(model));
1747 DBG(6, "Model = %s: %s %d\n", model, __FILE__, __LINE__);
1749 hpaio->saneDevice.model = strdup(model);
1750 hpaio->saneDevice.type = "multi-function peripheral";
1752 /* Initialize option descriptors. */
1753 hpaioSetupOptions( hpaio );
1754 hpaio->currentSideNumber = 1;
1759 /* Guess the command language (SCL or PML) based on the model string. */
1760 if( UNDEFINED_MODEL( hpaio ) )
1762 hpaio->scannerType = SCANNER_TYPE_SCL;
1764 else if( strcasestr( hpaio->saneDevice.model, "laserjet" ) )
1766 hpaio->scannerType = SCANNER_TYPE_PML;
1767 hpaio->pml.openFirst = 1;
1769 if( strcasecmp( hpaio->saneDevice.model, "HP_LaserJet_1100" ) == 0 )
1771 hpaio->pml.dontResetBeforeNextNonBatchPage = 1;
1775 hpaio->pml.startNextBatchPageEarly = 1;
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 )
1782 hpaio->scannerType = SCANNER_TYPE_PML;
1783 hpaio->preDenali = 1;
1785 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_500" ) == 0 ||
1786 strcasecmp( hpaio->saneDevice.model, "All-in-One_IJP-V100" ) == 0 )
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;
1796 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_600" ) == 0 )
1798 hpaio->scannerType = SCANNER_TYPE_PML;
1800 forceJpegForGrayAndColor = 1;
1801 force300dpiForLineart = 1;
1802 hpaio->defaultCompression[SCAN_MODE_LINEART] = COMPRESSION_MH;
1803 hpaio->defaultJpegCompressionFactor = SAFER_JPEG_COMPRESSION_FACTOR;
1805 else if( strcasecmp( hpaio->saneDevice.model, "Printer/Scanner/Copier_300" ) == 0 )
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;
1813 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_Series_700" ) == 0 )
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;
1821 else if( strcasecmp( hpaio->saneDevice.model, "OfficeJet_T_Series" ) == 0 )
1823 hpaio->scannerType = SCANNER_TYPE_PML;
1824 forceJpegForGrayAndColor = 1;
1828 hpaio->scannerType = SCANNER_TYPE_SCL;
1831 DBG(6, "Scanner type=%s: %s %d\n", hpaio->scannerType==0 ? "SCL" : "PML", __FILE__, __LINE__);
1833 hpaioPmlAllocateObjects(hpaio); /* used by pml scanners and scl scanners */
1835 if ((retcode = hpaioConnOpen(hpaio)) != SANE_STATUS_GOOD)
1840 if ((retcode = hpaioResetScanner(hpaio)) != SANE_STATUS_GOOD)
1845 /* Probing and setup for SCL scanners... */
1846 if( hpaio->scannerType == SCANNER_TYPE_SCL )
1848 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_CLEAR_ERROR_STACK, 0 );
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,
1856 hpaio->scl.compat1150,
1857 LEN_MODEL_RESPONSE );
1859 if( retcode == SANE_STATUS_GOOD )
1861 hpaio->scl.compat |= SCL_COMPAT_OFFICEJET;
1863 else if( retcode != SANE_STATUS_UNSUPPORTED )
1867 DBG(6, "scl.compat1150=<%s>: %s %d\n", hpaio->scl.compat1150, __FILE__, __LINE__);
1869 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1870 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
1871 SCL_INQ_HP_MODEL_12,
1873 hpaio->scl.compatPost1150,
1874 LEN_MODEL_RESPONSE );
1876 if( retcode == SANE_STATUS_GOOD )
1878 hpaio->scl.compat |= SCL_COMPAT_POST_1150;
1880 else if( retcode != SANE_STATUS_UNSUPPORTED )
1884 DBG(6, "scl.compatPost1150=<%s>: %s %d\n", hpaio->scl.compatPost1150, __FILE__, __LINE__);
1886 if( !hpaio->scl.compat )
1888 SET_DEFAULT_MODEL( hpaio, "(unknown scanner)" );
1890 else if( hpaio->scl.compat == SCL_COMPAT_OFFICEJET )
1892 hpaio->scl.compat |= SCL_COMPAT_1150;
1893 SET_DEFAULT_MODEL( hpaio, "(OfficeJet 1150)" );
1895 else if( !strcmp( hpaio->scl.compatPost1150, "5400A" ) )
1897 hpaio->scl.compat |= SCL_COMPAT_1170;
1898 SET_DEFAULT_MODEL( hpaio, "(OfficeJet 1170)" );
1900 else if( !strcmp( hpaio->scl.compatPost1150, "5500A" ) )
1902 hpaio->scl.compat |= SCL_COMPAT_R_SERIES;
1903 SET_DEFAULT_MODEL( hpaio, "(OfficeJet R Series)" );
1905 else if( !strcmp( hpaio->scl.compatPost1150, "5600A" ) )
1907 hpaio->scl.compat |= SCL_COMPAT_G_SERIES;
1908 SET_DEFAULT_MODEL( hpaio, "(OfficeJet G Series)" );
1910 else if( !strcmp( hpaio->scl.compatPost1150, "5700A" ) )
1912 hpaio->scl.compat |= SCL_COMPAT_K_SERIES;
1913 SET_DEFAULT_MODEL( hpaio, "(OfficeJet K Series)" );
1915 else if( !strcmp( hpaio->scl.compatPost1150, "5800A" ) )
1917 hpaio->scl.compat |= SCL_COMPAT_D_SERIES;
1918 SET_DEFAULT_MODEL( hpaio, "(OfficeJet D Series)" );
1920 else if( !strcmp( hpaio->scl.compatPost1150, "5900A" ) )
1922 hpaio->scl.compat |= SCL_COMPAT_6100_SERIES;
1923 SET_DEFAULT_MODEL( hpaio, "(OfficeJet 6100 Series)" );
1927 SET_DEFAULT_MODEL( hpaio, "(unknown OfficeJet)" );
1929 DBG(6, "scl.compat=0x%4.4X: %s %d\n", hpaio->scl.compat, __FILE__, __LINE__);
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 ) )
1935 hpaio->scl.decipixelChar = SCL_CHAR_DECIPOINTS;
1936 hpaio->decipixelsPerInch = DECIPOINTS_PER_INCH;
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,
1950 DBG(6, "decipixelChar='%c', decipixelsPerInch=%d: %s %d\n", hpaio->scl.decipixelChar, hpaio->decipixelsPerInch, __FILE__, __LINE__);
1952 /* Is MFPDTF supported? */
1953 if( hpaioSclSendCommandCheckError( hpaio,
1955 SCL_MFPDTF_ON ) != SANE_STATUS_GOOD )
1957 DBG(6, "Doesn't support MFPDTF: %s %d\n", __FILE__, __LINE__);
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;
1966 if( supportsMfpdtf )
1968 if( hpaioSclSendCommandCheckError( hpaio,
1969 SCL_CMD_SET_COMPRESSION,
1970 SCL_COMPRESSION_JPEG ) == SANE_STATUS_GOOD )
1972 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] |= COMPRESSION_JPEG;
1973 hpaio->supportsScanMode[SCAN_MODE_COLOR] |= COMPRESSION_JPEG;
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,
1988 DBG(6, "minXRes=%d retcode=%d\n",minXRes, retcode);
1990 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
1991 SCL_CMD_INQUIRE_MINIMUM_VALUE,
1992 SCL_CMD_SET_Y_RESOLUTION,
1997 DBG(6,"minYRes=%d retcode=%d\n", minYRes, retcode);
1999 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
2000 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
2001 SCL_CMD_SET_X_RESOLUTION,
2006 DBG(6,"maxXRes=%d retcode=%d\n", maxXRes, retcode);
2008 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
2009 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
2010 SCL_CMD_SET_Y_RESOLUTION,
2015 DBG(6,"maxYRes=%d retcode=%d\n", maxYRes, retcode);
2017 if( hpaio->scl.compat & SCL_COMPAT_1150 &&
2018 minYRes < SCL_MIN_Y_RES_1150 )
2020 minYRes = SCL_MIN_Y_RES_1150;
2022 hpaio->scl.minRes = minXRes;
2023 if( hpaio->scl.minRes < minYRes )
2025 hpaio->scl.minRes = minYRes;
2028 hpaio->resolutionRange.min = hpaio->scl.minRes;
2030 hpaio->scl.maxRes = maxXRes;
2032 if( hpaio->scl.maxRes > maxYRes )
2034 hpaio->scl.maxRes = maxYRes;
2037 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 )
2038 && hpaio->scl.maxRes > SCL_MAX_RES_1150_1170 )
2040 hpaio->scl.maxRes = SCL_MAX_RES_1150_1170;
2042 hpaio->resolutionRange.max = hpaio->scl.maxRes;
2044 /* Determine ADF/duplex capabilities. */
2046 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
2047 SCL_CMD_INQUIRE_DEVICE_PARAMETER,
2048 SCL_INQ_ADF_CAPABILITY,
2049 &hpaio->scl.adfCapability,
2053 DBG(6, "ADF capability=%d retcode=%d: %s %d\n", hpaio->scl.adfCapability, retcode,__FILE__, __LINE__);
2055 if (hpaio->scl.adfCapability)
2057 retcode = SclInquire( hpaio->deviceid, hpaio->scan_channelid,
2058 SCL_CMD_INQUIRE_MINIMUM_VALUE,
2059 SCL_PSEUDO_ADF_X_RESOLUTION,
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,
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,
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,
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 )
2088 minYRes = SCL_MIN_Y_RES_1150;
2090 hpaio->scl.minResAdf = minXRes;
2091 if( hpaio->scl.minResAdf < minYRes )
2093 hpaio->scl.minResAdf = minYRes;
2096 hpaio->scl.maxResAdf = maxXRes;
2098 if( hpaio->scl.maxResAdf > maxYRes )
2100 hpaio->scl.maxResAdf = maxYRes;
2103 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 )
2104 && hpaio->scl.maxResAdf > SCL_MAX_RES_1150_1170 )
2106 hpaio->scl.maxResAdf = SCL_MAX_RES_1150_1170;
2110 if(ma.scansrc & HPMUD_SCANSRC_FLATBED)
2112 hpaio->scl.flatbedCapability = 1;
2113 hpaio->supportedAdfModes = ADF_MODE_FLATBED;
2115 if (hpaio->scl.adfCapability)
2117 if( hpaio->scl.compat & SCL_COMPAT_K_SERIES)
2119 hpaio->supportedAdfModes |= ADF_MODE_ADF;
2123 int supportedFunctions;
2125 hpaio->supportedAdfModes |= ADF_MODE_ADF;
2126 if (hpaio->scl.flatbedCapability)
2127 hpaio->supportedAdfModes |= ADF_MODE_AUTO;
2129 if( hpaio->scl.compat & ( SCL_COMPAT_1170 | SCL_COMPAT_R_SERIES |SCL_COMPAT_G_SERIES ) )
2131 hpaio->scl.unloadAfterScan = 1;
2133 if( PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid, hpaio->scl.objSupportedFunctions ) != ERROR &&
2134 PmlGetIntegerValue( hpaio->scl.objSupportedFunctions,
2136 &supportedFunctions ) != ERROR &&
2137 supportedFunctions & PML_SUPPFUNC_DUPLEX )
2139 hpaio->supportsDuplex = 1;
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,
2153 SclInquire( hpaio->deviceid, hpaio->scan_channelid,
2154 SCL_CMD_INQUIRE_MAXIMUM_VALUE,
2155 SCL_CMD_SET_Y_EXTENT,
2156 &hpaio->scl.maxYExtent,
2160 DBG(8, "Maximum extents: x=%d, y=%d %s %d\n", hpaio->scl.maxXExtent, hpaio->scl.maxYExtent, __FILE__, __LINE__);
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 );
2165 /* Probing and setup for PML scanners... */
2167 else /* if (hpaio->scannerType==SCANNER_TYPE_PML) */
2171 hpaio->decipixelsPerInch = DECIPOINTS_PER_INCH;
2173 /*ChannelSetSelectPollTimeout( hpaio->chan, &selectPollTimeout );
2175 ChannelSetSelectPollCallback( hpaio->chan,
2176 hpaioPmlSelectCallback,
2179 /* Determine supported scan modes and compression settings. */
2180 if( hpaio->preDenali )
2182 comps |= COMPRESSION_MMR;
2185 PmlSetIntegerValue( hpaio->pml.objCompression,
2186 PML_TYPE_ENUMERATION,
2187 PML_COMPRESSION_NONE );
2189 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2190 hpaio->pml.objCompression, 0, 0 ) != ERROR )
2192 comps |= COMPRESSION_NONE;
2195 PmlSetIntegerValue( hpaio->pml.objCompression,
2196 PML_TYPE_ENUMERATION,
2197 PML_COMPRESSION_MH );
2199 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2200 hpaio->pml.objCompression, 0, 0 ) != ERROR )
2202 comps |= COMPRESSION_MH;
2205 PmlSetIntegerValue( hpaio->pml.objCompression,
2206 PML_TYPE_ENUMERATION,
2207 PML_COMPRESSION_MR );
2209 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2210 hpaio->pml.objCompression, 0, 0 ) != ERROR )
2212 comps |= COMPRESSION_MR;
2215 PmlSetIntegerValue( hpaio->pml.objCompression,
2216 PML_TYPE_ENUMERATION,
2217 PML_COMPRESSION_MMR );
2219 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2220 hpaio->pml.objCompression, 0, 0 ) != ERROR )
2222 comps |= COMPRESSION_MMR;
2225 PmlSetIntegerValue( hpaio->pml.objPixelDataType,
2226 PML_TYPE_ENUMERATION,
2227 PML_DATA_TYPE_LINEART );
2229 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2230 hpaio->pml.objPixelDataType, 0, 0 ) != ERROR )
2232 hpaio->supportsScanMode[SCAN_MODE_LINEART] = comps;
2234 comps &= COMPRESSION_NONE;
2236 if( forceJpegForGrayAndColor )
2241 PmlSetIntegerValue( hpaio->pml.objCompression,
2242 PML_TYPE_ENUMERATION,
2243 PML_COMPRESSION_JPEG );
2245 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2246 hpaio->pml.objCompression, 0, 0 ) != ERROR )
2248 comps |= COMPRESSION_JPEG;
2251 PmlSetIntegerValue( hpaio->pml.objPixelDataType,
2252 PML_TYPE_ENUMERATION,
2253 PML_DATA_TYPE_GRAYSCALE );
2255 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2256 hpaio->pml.objPixelDataType, 0, 0 ) != ERROR )
2258 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] = comps;
2261 PmlSetIntegerValue( hpaio->pml.objPixelDataType,
2262 PML_TYPE_ENUMERATION,
2263 PML_DATA_TYPE_COLOR );
2265 if( PmlRequestSetRetry( hpaio->deviceid, hpaio->cmd_channelid,
2266 hpaio->pml.objPixelDataType, 0, 0 ) != ERROR )
2268 hpaio->supportsScanMode[SCAN_MODE_COLOR] = comps;
2271 /* Determine supported resolutions. */
2272 NumListClear( hpaio->resolutionList );
2273 NumListClear( hpaio->lineartResolutionList );
2275 if( hpaio->preDenali )
2277 NumListAdd( hpaio->lineartResolutionList, 200 );
2278 if( !strcmp( hpaio->saneDevice.model, "OfficeJet_Series_300" ) )
2280 NumListAdd( hpaio->lineartResolutionList, 300 );
2282 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2284 else if( PmlRequestGet( hpaio->deviceid, hpaio->cmd_channelid,
2285 hpaio->pml.objResolutionRange ) == ERROR )
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;
2295 char resList[PML_MAX_VALUE_LEN + 1];
2296 int i, len, res, consumed;
2298 PmlGetStringValue( hpaio->pml.objResolutionRange,
2301 PML_MAX_VALUE_LEN );
2303 resList[PML_MAX_VALUE_LEN] = 0;
2304 len = strlen( resList );
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; )
2310 if( resList[i] < '0' || resList[i] > '9' )
2315 if( sscanf( resList + i, "%d%n", &res, &consumed ) != 1 )
2320 if( !force300dpiForGrayscale || res >= 300 )
2322 NumListAdd( hpaio->resolutionList, res );
2324 if( !force300dpiForLineart || res >= 300 )
2326 NumListAdd( hpaio->lineartResolutionList, res );
2330 if( !NumListGetCount( hpaio->resolutionList ) )
2332 goto pmlDefaultResRange;
2334 hpaio->option[OPTION_SCAN_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2337 /* Determine contrast support. (Removed, no LJ support, des 7/31/07) */
2338 // if( PmlRequestGet(hpaio->deviceid, hpaio->cmd_channelid, hpaio->pml.objContrast) != ERROR)
2340 // hpaio->option[OPTION_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
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)
2347 hpaio->pml.flatbedCapability = 1;
2349 DBG(6, "Valid PML modularHardware object value=%x: %s %d\n", modularHardware, __FILE__, __LINE__);
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;
2355 if(modularHardware & PML_MODHW_ADF)
2356 hpaio->supportedAdfModes = ADF_MODE_AUTO | ADF_MODE_ADF;
2358 hpaio->supportedAdfModes = ADF_MODE_FLATBED;
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;
2365 hpaio->supportsDuplex = 0;
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 );
2370 } /* if( hpaio->scannerType == SCANNER_TYPE_SCL ) */
2372 /* Allocate MFPDTF parser if supported. */
2373 if( supportsMfpdtf )
2375 hpaio->mfpdtf = MfpdtfAllocate( hpaio->deviceid, hpaio->scan_channelid );
2376 MfpdtfSetChannel( hpaio->mfpdtf, hpaio->scan_channelid );
2378 if( hpaio->preDenali )
2380 MfpdtfReadSetSimulateImageHeaders( hpaio->mfpdtf, 1 );
2385 /* Finish setting up option descriptors. */
2386 hpaioUpdateDescriptors( hpaio, OPTION_FIRST );
2392 //ptalDeviceSetAppInfo( dev, hpaio );
2393 retcode = SANE_STATUS_GOOD;
2398 hpaioConnClose( hpaio );
2400 if( retcode != SANE_STATUS_GOOD )
2404 if( hpaio->saneDevice.name )
2406 free( ( void * ) hpaio->saneDevice.name );
2408 if( hpaio->saneDevice.model )
2410 free( ( void * ) hpaio->saneDevice.model );
2416 } /* sane_hpaio_open() */
2418 extern void sane_hpaio_close(SANE_Handle handle)
2420 hpaioScanner_t hpaio = (hpaioScanner_t) handle;
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);
2431 DBG(8, "sane_hpaio_close(): %s %d\n", __FILE__, __LINE__);
2433 hpaioPmlDeallocateObjects(hpaio);
2435 /* ADF may leave channel(s) open. */
2436 if (hpaio->cmd_channelid > 0)
2437 hpaioConnEndScan(hpaio);
2439 if (hpaio->deviceid > 0)
2441 hpmud_close_device(hpaio->deviceid);
2442 hpaio->deviceid = -1;
2445 /* free hpaio object?? (des) */
2446 } /* sane_hpaio_close() */
2448 extern const SANE_Option_Descriptor * sane_hpaio_get_option_descriptor(SANE_Handle handle, SANE_Int option)
2450 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
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);
2461 DBG(8, "sane_hpaio_get_option_descriptor(option=%s): %s %d\n", hpaio->option[option].name, __FILE__, __LINE__);
2463 if( option < 0 || option >= OPTION_LAST )
2468 return &hpaio->option[option];
2469 } /* sane_hpaio_get_option_descriptor() */
2471 extern SANE_Status sane_hpaio_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void * pValue, SANE_Int * pInfo )
2473 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
2475 SANE_Int * pIntValue = pValue;
2476 SANE_String pStrValue = pValue;
2477 SANE_Status retcode;
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);
2496 case SANE_ACTION_GET_VALUE:
2499 case OPTION_NUM_OPTIONS:
2500 *pIntValue = OPTION_LAST;
2503 case OPTION_SCAN_MODE:
2504 switch( hpaio->currentScanMode )
2506 case SCAN_MODE_LINEART:
2507 strcpy( pStrValue, SANE_VALUE_SCAN_MODE_LINEART );
2509 case SCAN_MODE_GRAYSCALE:
2510 strcpy( pStrValue, SANE_VALUE_SCAN_MODE_GRAY );
2512 case SCAN_MODE_COLOR:
2513 strcpy( pStrValue, SANE_VALUE_SCAN_MODE_COLOR );
2516 strcpy( pStrValue, STR_UNKNOWN );
2521 case OPTION_SCAN_RESOLUTION:
2522 *pIntValue = hpaio->currentResolution;
2525 case OPTION_CONTRAST:
2526 *pIntValue = hpaio->currentContrast;
2529 case OPTION_COMPRESSION:
2530 switch( hpaio->currentCompression )
2532 case COMPRESSION_NONE:
2533 strcpy( pStrValue, STR_COMPRESSION_NONE );
2535 case COMPRESSION_MH:
2536 strcpy( pStrValue, STR_COMPRESSION_MH );
2538 case COMPRESSION_MR:
2539 strcpy( pStrValue, STR_COMPRESSION_MR );
2541 case COMPRESSION_MMR:
2542 strcpy( pStrValue, STR_COMPRESSION_MMR );
2544 case COMPRESSION_JPEG:
2545 strcpy( pStrValue, STR_COMPRESSION_JPEG );
2548 strcpy( pStrValue, STR_UNKNOWN );
2553 case OPTION_JPEG_COMPRESSION_FACTOR:
2554 *pIntValue = hpaio->currentJpegCompressionFactor;
2557 case OPTION_BATCH_SCAN:
2558 *pIntValue = hpaio->currentBatchScan;
2561 case OPTION_ADF_MODE:
2562 switch( hpaio->currentAdfMode )
2565 strcpy( pStrValue, STR_ADF_MODE_AUTO );
2567 case ADF_MODE_FLATBED:
2568 strcpy( pStrValue, STR_ADF_MODE_FLATBED );
2571 strcpy( pStrValue, STR_ADF_MODE_ADF );
2574 strcpy( pStrValue, STR_UNKNOWN );
2580 *pIntValue = hpaio->currentDuplex;
2583 case OPTION_LENGTH_MEASUREMENT:
2584 switch( hpaio->currentLengthMeasurement )
2586 case LENGTH_MEASUREMENT_UNKNOWN:
2587 strcpy( pStrValue, STR_LENGTH_MEASUREMENT_UNKNOWN );
2589 case LENGTH_MEASUREMENT_UNLIMITED:
2591 STR_LENGTH_MEASUREMENT_UNLIMITED );
2593 case LENGTH_MEASUREMENT_APPROXIMATE:
2595 STR_LENGTH_MEASUREMENT_APPROXIMATE );
2597 case LENGTH_MEASUREMENT_PADDED:
2598 strcpy( pStrValue, STR_LENGTH_MEASUREMENT_PADDED );
2600 case LENGTH_MEASUREMENT_EXACT:
2601 strcpy( pStrValue, STR_LENGTH_MEASUREMENT_EXACT );
2604 strcpy( pStrValue, STR_UNKNOWN );
2610 *pIntValue = hpaio->currentTlx;
2614 *pIntValue = hpaio->currentTly;
2618 *pIntValue = hpaio->currentBrx;
2622 *pIntValue = hpaio->currentBry;
2626 return SANE_STATUS_INVAL;
2630 case SANE_ACTION_SET_VALUE:
2631 if( hpaio->option[option].cap & SANE_CAP_INACTIVE )
2633 return SANE_STATUS_INVAL;
2637 case OPTION_SCAN_MODE:
2638 if( !strcasecmp( pStrValue, SANE_VALUE_SCAN_MODE_LINEART ) &&
2639 hpaio->supportsScanMode[SCAN_MODE_LINEART] )
2641 hpaio->currentScanMode = SCAN_MODE_LINEART;
2644 if( !strcasecmp( pStrValue, SANE_VALUE_SCAN_MODE_GRAY ) &&
2645 hpaio->supportsScanMode[SCAN_MODE_GRAYSCALE] )
2647 hpaio->currentScanMode = SCAN_MODE_GRAYSCALE;
2650 if( !strcasecmp( pStrValue, SANE_VALUE_SCAN_MODE_COLOR ) &&
2651 hpaio->supportsScanMode[SCAN_MODE_COLOR] )
2653 hpaio->currentScanMode = SCAN_MODE_COLOR;
2656 return SANE_STATUS_INVAL;
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 ) ) )
2666 return SANE_STATUS_INVAL;
2668 hpaio->currentResolution = *pIntValue;
2671 case OPTION_CONTRAST:
2672 if( *pIntValue<hpaio->contrastRange.min ||
2673 *pIntValue>hpaio->contrastRange.max )
2675 return SANE_STATUS_INVAL;
2677 hpaio->currentContrast = *pIntValue;
2680 case OPTION_COMPRESSION:
2682 int supportedCompression = hpaio->supportsScanMode[hpaio->currentScanMode];
2683 if( !strcasecmp( pStrValue, STR_COMPRESSION_NONE ) &&
2684 supportedCompression & COMPRESSION_NONE )
2686 hpaio->currentCompression = COMPRESSION_NONE;
2689 if( !strcasecmp( pStrValue, STR_COMPRESSION_MH ) &&
2690 supportedCompression & COMPRESSION_MH )
2692 hpaio->currentCompression = COMPRESSION_MH;
2695 if( !strcasecmp( pStrValue, STR_COMPRESSION_MR ) &&
2696 supportedCompression & COMPRESSION_MR )
2698 hpaio->currentCompression = COMPRESSION_MR;
2701 if( !strcasecmp( pStrValue, STR_COMPRESSION_MMR ) &&
2702 supportedCompression & COMPRESSION_MMR )
2704 hpaio->currentCompression = COMPRESSION_MMR;
2707 if( !strcasecmp( pStrValue, STR_COMPRESSION_JPEG ) &&
2708 supportedCompression & COMPRESSION_JPEG )
2710 hpaio->currentCompression = COMPRESSION_JPEG;
2713 return SANE_STATUS_INVAL;
2716 case OPTION_JPEG_COMPRESSION_FACTOR:
2717 if( *pIntValue<MIN_JPEG_COMPRESSION_FACTOR ||
2718 *pIntValue>MAX_JPEG_COMPRESSION_FACTOR )
2720 return SANE_STATUS_INVAL;
2722 hpaio->currentJpegCompressionFactor = *pIntValue;
2725 case OPTION_BATCH_SCAN:
2726 if( *pIntValue != SANE_FALSE && *pIntValue != SANE_TRUE )
2728 return SANE_STATUS_INVAL;
2730 hpaio->currentBatchScan = *pIntValue;
2733 case OPTION_ADF_MODE:
2734 if( !strcasecmp( pStrValue, STR_ADF_MODE_AUTO ) &&
2735 hpaio->supportedAdfModes & ADF_MODE_AUTO )
2737 hpaio->currentAdfMode = ADF_MODE_AUTO;
2740 if( !strcasecmp( pStrValue, STR_ADF_MODE_FLATBED ) &&
2741 hpaio->supportedAdfModes & ADF_MODE_FLATBED )
2743 hpaio->currentAdfMode = ADF_MODE_FLATBED;
2746 if( !strcasecmp( pStrValue, STR_ADF_MODE_ADF ) &&
2747 hpaio->supportedAdfModes & ADF_MODE_ADF )
2749 hpaio->currentAdfMode = ADF_MODE_ADF;
2752 return SANE_STATUS_INVAL;
2755 if( *pIntValue != SANE_FALSE && *pIntValue != SANE_TRUE )
2757 return SANE_STATUS_INVAL;
2759 hpaio->currentDuplex = *pIntValue;
2762 case OPTION_LENGTH_MEASUREMENT:
2763 if( !strcasecmp( pStrValue,
2764 STR_LENGTH_MEASUREMENT_UNKNOWN ) )
2766 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_UNKNOWN;
2769 if( !strcasecmp( pStrValue,
2770 STR_LENGTH_MEASUREMENT_UNLIMITED ) )
2772 if( hpaio->scannerType != SCANNER_TYPE_PML )
2774 return SANE_STATUS_INVAL;
2776 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_UNLIMITED;
2779 if( !strcasecmp( pStrValue,
2780 STR_LENGTH_MEASUREMENT_APPROXIMATE ) )
2782 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_APPROXIMATE;
2785 if( !strcasecmp( pStrValue, STR_LENGTH_MEASUREMENT_PADDED ) )
2787 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_PADDED;
2790 if( !strcasecmp( pStrValue, STR_LENGTH_MEASUREMENT_EXACT ) )
2792 hpaio->currentLengthMeasurement = LENGTH_MEASUREMENT_EXACT;
2795 return SANE_STATUS_INVAL;
2798 if( *pIntValue<hpaio->tlxRange.min ||
2799 *pIntValue>hpaio->tlxRange.max )
2801 return SANE_STATUS_INVAL;
2803 hpaio->currentTlx = *pIntValue;
2807 if( *pIntValue<hpaio->tlyRange.min ||
2808 *pIntValue>hpaio->tlyRange.max )
2810 return SANE_STATUS_INVAL;
2812 hpaio->currentTly = *pIntValue;
2816 if( *pIntValue<hpaio->brxRange.min ||
2817 *pIntValue>hpaio->brxRange.max )
2819 return SANE_STATUS_INVAL;
2821 hpaio->currentBrx = *pIntValue;
2825 if( *pIntValue<hpaio->bryRange.min ||
2826 *pIntValue>hpaio->bryRange.max )
2828 return SANE_STATUS_INVAL;
2830 hpaio->currentBry = *pIntValue;
2834 return SANE_STATUS_INVAL;
2838 case SANE_ACTION_SET_AUTO:
2839 retcode = hpaioSetDefaultValue( hpaio, option );
2840 if( retcode != SANE_STATUS_GOOD )
2844 reload : *pInfo = hpaioUpdateDescriptors( hpaio, option );
2848 return SANE_STATUS_INVAL;
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__);
2855 return SANE_STATUS_GOOD;
2856 } /* sane_hpaio_control_option() */
2858 extern SANE_Status sane_hpaio_get_parameters(SANE_Handle handle, SANE_Parameters *pParams)
2860 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
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);
2874 *pParams = hpaio->prescanParameters;
2879 *pParams = hpaio->scanParameters;
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__);
2884 return SANE_STATUS_GOOD;
2885 } /* sane_hpaio_get_parameters() */
2887 extern SANE_Status sane_hpaio_start(SANE_Handle handle)
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;
2895 DBG(8, "sane_hpaio_start(): %s %d deviceuri=%s\n", __FILE__, __LINE__, hpaio->deviceuri);
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);
2906 hpaio->user_cancel = FALSE;
2908 hpaio->endOfData = 0;
2910 if (hpaio->scannerType==SCANNER_TYPE_PML)
2911 return pml_start(hpaio);
2913 /* TODO: convert to scl_start. des */
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 )
2918 hpaio->noDocsConditionPending = 0;
2919 retcode = SANE_STATUS_NO_DOCS;
2922 /* Open scanner command channel. */
2923 retcode = hpaioConnPrepareScan( hpaio );
2925 if( retcode != SANE_STATUS_GOOD )
2929 /* Change document if needed. */
2930 hpaio->beforeScan = 1;
2931 retcode = hpaioAdvanceDocument( hpaio );
2932 hpaio->beforeScan = 0;
2934 if( retcode != SANE_STATUS_GOOD )
2939 /* Program options. */
2940 retcode = hpaioProgramOptions( hpaio );
2942 if( retcode != SANE_STATUS_GOOD )
2947 hpaio->scanParameters = hpaio->prescanParameters;
2948 memset( xforms, 0, sizeof( xforms ) );
2949 traits.iPixelsPerRow = -1;
2951 switch( hpaio->effectiveScanMode )
2953 case SCAN_MODE_LINEART:
2954 hpaio->scanParameters.format = SANE_FRAME_GRAY;
2955 hpaio->scanParameters.depth = 1;
2956 traits.iBitsPerPixel = 1;
2958 case SCAN_MODE_GRAYSCALE:
2959 hpaio->scanParameters.format = SANE_FRAME_GRAY;
2960 hpaio->scanParameters.depth = 8;
2961 traits.iBitsPerPixel = 8;
2963 case SCAN_MODE_COLOR:
2965 hpaio->scanParameters.format = SANE_FRAME_RGB;
2966 hpaio->scanParameters.depth = 8;
2967 traits.iBitsPerPixel = 24;
2970 traits.lHorizDPI = hpaio->effectiveResolution << 16;
2971 traits.lVertDPI = hpaio->effectiveResolution << 16;
2972 traits.lNumRows = -1;
2973 traits.iNumPages = 1;
2974 traits.iPageNum = 1;
2976 // if( hpaio->scannerType == SCANNER_TYPE_SCL )
2978 int lines, pixelsPerLine;
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 )
2984 traits.lNumRows = lines;
2986 SclInquire( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_INQUIRE_DEVICE_PARAMETER, SCL_INQ_PIXELS_PER_SCAN_LINE,
2987 &pixelsPerLine, 0, 0 );
2989 traits.iPixelsPerRow = pixelsPerLine;
2991 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_CLEAR_ERROR_STACK, 0 );
2993 /* Start scanning. */
2994 SclSendCommand( hpaio->deviceid, hpaio->scan_channelid, SCL_CMD_SCAN_WINDOW, 0 );
2998 MfpdtfSetChannel( hpaio->mfpdtf, hpaio->scan_channelid );
3000 //MfpdtfReadSetTimeout( hpaio->mfpdtf, MFPDTF_EARLY_READ_TIMEOUT );
3001 MfpdtfReadStart( hpaio->mfpdtf ); /* inits mfpdtf */
3014 sprintf(f, "/tmp/mfpdtf_%d.out", cnt++);
3016 bug("saving raw image to %s \n", f);
3018 MfpdtfLogToFile( hpaio->mfpdtf, f );
3023 int rService, sopEncoding;
3025 rService = MfpdtfReadService( hpaio->mfpdtf );
3027 if( retcode != SANE_STATUS_GOOD )
3032 if( rService & MFPDTF_RESULT_ERROR_MASK )
3034 retcode = SANE_STATUS_IO_ERROR;
3038 if( rService & MFPDTF_RESULT_NEW_VARIANT_HEADER && hpaio->preDenali )
3040 union MfpdtfVariantHeader_u vheader;
3041 MfpdtfReadGetVariantHeader( hpaio->mfpdtf, &vheader, sizeof( vheader ) );
3043 traits.iPixelsPerRow = LEND_GET_SHORT( vheader.faxArtoo.pixelsPerRow );
3044 traits.iBitsPerPixel = 1;
3046 switch( vheader.faxArtoo.dataCompression )
3048 case MFPDTF_RASTER_MH:
3049 sopEncoding = MFPDTF_RASTER_MH;
3051 case MFPDTF_RASTER_MR:
3052 sopEncoding = MFPDTF_RASTER_MR;
3054 case MFPDTF_RASTER_MMR:
3056 sopEncoding = MFPDTF_RASTER_MMR;
3061 else if( rService & MFPDTF_RESULT_NEW_START_OF_PAGE_RECORD )
3063 // struct MfpdtfImageStartPageRecord_s sop;
3065 // if( hpaio->scannerType == SCANNER_TYPE_SCL )
3067 if( hpaio->currentCompression == COMPRESSION_NONE )
3071 else /* if (hpaio->currentCompression==COMPRESSION_JPEG) */
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;
3085 /* Set up image-processing pipeline. */
3086 switch( sopEncoding )
3088 case MFPDTF_RASTER_MH:
3089 pXform->aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MH;
3090 ADD_XFORM( X_FAX_DECODE );
3092 case MFPDTF_RASTER_MR:
3093 pXform->aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MR;
3094 ADD_XFORM( X_FAX_DECODE );
3096 case MFPDTF_RASTER_MMR:
3097 pXform->aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MMR;
3098 ADD_XFORM( X_FAX_DECODE );
3101 case MFPDTF_RASTER_BITMAP:
3102 case MFPDTF_RASTER_GRAYMAP:
3103 case MFPDTF_RASTER_RGB:
3107 case MFPDTF_RASTER_JPEG:
3109 pXform->aXformInfo[IP_JPG_DECODE_FROM_DENALI].dword = hpaio->fromDenali;
3110 ADD_XFORM( X_JPG_DECODE );
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 );
3117 case MFPDTF_RASTER_YCC411:
3118 case MFPDTF_RASTER_PCL:
3119 case MFPDTF_RASTER_NOT:
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__);
3127 if( rService & MFPDTF_RESULT_IMAGE_DATA_PENDING )
3129 /*MfpdtfReadSetTimeout( hpaio->mfpdtf, MFPDTF_LATER_READ_TIMEOUT );*/
3134 hpaio->scanParameters.pixels_per_line = traits.iPixelsPerRow;
3135 hpaio->scanParameters.lines = traits.lNumRows;
3137 if( hpaio->scanParameters.lines < 0 )
3139 hpaio->scanParameters.lines = MILLIMETERS_TO_PIXELS( hpaio->bryRange.max,
3140 hpaio->effectiveResolution );
3143 // if( hpaio->scannerType == SCANNER_TYPE_SCL )
3145 /* We have to invert bilevel data from SCL scanners. */
3146 if( hpaio->effectiveScanMode == SCAN_MODE_LINEART )
3148 ADD_XFORM( X_INVERT );
3150 else /* if (hpaio->effectiveScanMode==SCAN_MODE_COLOR) */
3152 /* Do gamma correction on OfficeJet Pro 11xx. */
3153 if( hpaio->scl.compat & ( SCL_COMPAT_1150 | SCL_COMPAT_1170 ) )
3155 pXform->aXformInfo[IP_TABLE_WHICH].dword = IP_TABLE_USER;
3156 pXform->aXformInfo[IP_TABLE_OPTION].pvoid = ( char * )hp11xxSeriesGammaTable;
3157 ADD_XFORM( X_TABLE );
3161 if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_PADDED )
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;
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 )
3175 ADD_XFORM( X_SKEL );
3178 wResult = ipOpen( pXform - xforms, xforms, 0, &hpaio->hJob );
3180 if( wResult != IP_DONE || !hpaio->hJob )
3182 retcode = SANE_STATUS_INVAL;
3186 traits.iComponentsPerPixel = ( ( traits.iBitsPerPixel % 3 ) ? 1 : 3 );
3187 wResult = ipSetDefaultInputTraits( hpaio->hJob, &traits );
3189 if( wResult != IP_DONE )
3191 retcode = SANE_STATUS_INVAL;
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 ) );
3198 hpaio->totalBytesRemaining = hpaio->scanParameters.bytes_per_line * hpaio->scanParameters.lines;
3199 hpaio->bufferOffset = 0;
3200 hpaio->bufferBytesRemaining = 0;
3202 if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_UNKNOWN || hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_UNLIMITED )
3204 hpaio->scanParameters.lines = -1;
3206 else if( hpaio->currentLengthMeasurement == LENGTH_MEASUREMENT_EXACT )
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. */
3213 retcode = SANE_STATUS_GOOD;
3217 if( retcode != SANE_STATUS_GOOD )
3219 if (retcode == SANE_STATUS_NO_DOCS) SendScanEvent (hpaio->deviceuri, EVENT_SCAN_ADF_NO_DOCS);
3220 sane_hpaio_cancel( handle );
3224 } /* sane_hpaio_start() */
3227 extern SANE_Status sane_hpaio_read(SANE_Handle handle, SANE_Byte *data, SANE_Int maxLength, SANE_Int *pLength)
3229 hpaioScanner_t hpaio = ( hpaioScanner_t ) handle;
3230 SANE_Status retcode;
3233 DWORD dwInputUsed, dwInputNextPos;
3234 DWORD dwOutputAvail = maxLength;
3235 LPBYTE pbOutputBuf = data;
3236 DWORD dwOutputUsed, dwOutputThisPos;
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);
3248 if (hpaio->user_cancel) {
3249 bug("sane_hpaio_read(maxLength=%d): User cancelled!\n", maxLength);
3250 return SANE_STATUS_CANCELLED;
3257 bug("sane_hpaio_read(maxLength=%d): No scan pending!\n", maxLength);
3258 retcode = SANE_STATUS_EOF;
3262 if (hpaio->scannerType==SCANNER_TYPE_PML)
3264 retcode = pml_read(hpaio, data, maxLength, pLength);
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__);
3270 /* TODO: convert to scl_read. des */
3273 if( hpaio->bufferBytesRemaining <= 0 && !hpaio->endOfData )
3275 if( !hpaio->mfpdtf )
3277 int r, len = hpaio->totalBytesRemaining;
3280 hpaio->endOfData = 1;
3284 if( len > LEN_BUFFER )
3289 r = ReadChannelEx(hpaio->deviceid,
3290 hpaio->scan_channelid,
3297 retcode = SANE_STATUS_IO_ERROR;
3300 hpaio->bufferBytesRemaining = r;
3301 hpaio->totalBytesRemaining -= r;
3309 rService = MfpdtfReadService( hpaio->mfpdtf );
3311 if( rService & MFPDTF_RESULT_ERROR_MASK )
3313 // retcode = SANE_STATUS_IO_ERROR;
3315 hpaio->endOfData = 1; /* display any data (ie: OJ F380 1200dpi non-compressed can timeout after last scan). */
3318 if( rService & MFPDTF_RESULT_IMAGE_DATA_PENDING )
3320 hpaio->bufferBytesRemaining = MfpdtfReadInnerBlock( hpaio->mfpdtf, hpaio->inBuffer, LEN_BUFFER );
3322 rService = MfpdtfReadGetLastServiceResult( hpaio->mfpdtf );
3324 if( rService & MFPDTF_RESULT_ERROR_MASK )
3326 retcode = SANE_STATUS_IO_ERROR;
3330 else if( rService & MFPDTF_RESULT_NEW_END_OF_PAGE_RECORD || ( rService & MFPDTF_RESULT_END_PAGE && hpaio->preDenali ))
3332 hpaio->endOfData = 1;
3335 } /* if (!hpaio->mfpdtf) */
3337 hpaio->bufferOffset = 0;
3338 if( hpaio->preDenali )
3340 ipMirrorBytes( hpaio->inBuffer, hpaio->bufferBytesRemaining );
3343 } /* if( hpaio->bufferBytesRemaining <= 0 && !hpaio->endOfData ) */
3345 dwInputAvail = hpaio->bufferBytesRemaining;
3347 if( hpaio->bufferBytesRemaining <= 0 && hpaio->endOfData )
3353 pbInputBuf = hpaio->inBuffer + hpaio->bufferOffset;
3356 wResult = ipConvert( hpaio->hJob,
3366 hpaio->bufferOffset += dwInputUsed;
3367 hpaio->bufferBytesRemaining -= dwInputUsed;
3368 *pLength = dwOutputUsed;
3370 if( wResult & ( IP_INPUT_ERROR | IP_FATAL_ERROR ) )
3372 bug("ipConvert error=%x\n", wResult);
3373 retcode = SANE_STATUS_IO_ERROR;
3378 if( wResult & IP_DONE )
3380 retcode = SANE_STATUS_EOF;
3381 // hpaioAdvanceDocument(hpaio);
3382 ipClose(hpaio->hJob);
3389 retcode = SANE_STATUS_GOOD;
3392 if(!(retcode == SANE_STATUS_GOOD || retcode == SANE_STATUS_EOF))
3394 sane_hpaio_cancel( handle );
3397 DBG(8, "sane_hpaio_read returned output=%p outputUsed=%d length=%d status=%d: %s %d\n", pbOutputBuf, dwOutputUsed, *pLength, retcode, __FILE__, __LINE__);
3401 } /* sane_hpaio_read() */
3403 /* Note, sane_cancel is called normally not just during IO abort situations. */
3404 extern void sane_hpaio_cancel( SANE_Handle handle )
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);
3417 if (hpaio->user_cancel) {
3418 bug("sane_hpaio_cancel: already cancelled!\n");
3420 hpaio->user_cancel = TRUE;
3422 if (hpaio->scannerType==SCANNER_TYPE_PML)
3428 /* TODO: convert to scl_cancel. des */
3432 MfpdtfLogToFile( hpaio->mfpdtf, 0 );
3433 //MfpdtfDeallocate( hpaio->mfpdtf );
3438 ipClose( hpaio->hJob );
3442 /* Do not close pml/scan channels if in batch mode. */
3443 if (hpaio->currentBatchScan != SANE_TRUE && hpaio->cmd_channelid > 0)
3444 hpaioConnEndScan(hpaio);
3446 } /* sane_hpaio_cancel() */
3448 extern SANE_Status sane_hpaio_set_io_mode(SANE_Handle handle, SANE_Bool nonBlocking)
3450 return SANE_STATUS_UNSUPPORTED;
3453 extern SANE_Status sane_hpaio_get_select_fd(SANE_Handle handle, SANE_Int *pFd)
3455 return SANE_STATUS_UNSUPPORTED;