diff --git a/AUTHORS b/AUTHORS index 916a5e718..eaa5a4e5f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -110,7 +110,7 @@ Peter Fales Peter Kirchgessner Petter Reinholdtsen Randolph Bentson -Rene Rebe +Rene Rebe Roger Wolff Simon Munton Tristan Tarrant diff --git a/backend/avision.c b/backend/avision.c index c35bb73bd..5b21eaf9f 100644 --- a/backend/avision.c +++ b/backend/avision.c @@ -41,14 +41,14 @@ ***************************************************************************** - This file implements a SANE backend for the Avision AV 630CS scanner with - SCSI-2 command set. + This file implements a SANE backend for the Avision AV 630CS (and other ...) + scanner with SCSI-2 command set. (feedback to: mccramer@s.netic.de and rene.rebe@myokay.net) Very much thanks to: Avision INC for the documentation we got! ;-) - Gunter Wagner for some fixes and the transparency option + Gunter Wagner for some fixes and the transparency option. ********************************************************************************/ @@ -66,6 +66,8 @@ #include #include +#include + #include #include #include @@ -81,86 +83,90 @@ #endif -#define BACKEND_NAME avision +#define BACKEND_NAME avision +#define BACKEND_BUILD 12 /* avision backend BUILD version */ + +#define MAX_X_RANGE 8.5 /* used when scanner returns invaild ragne fields ... */ +#define MAX_Y_RANGE 11.8 #ifndef PATH_MAX -# define PATH_MAX 1024 +# define PATH_MAX 1024 #endif #define AVISION_CONFIG_FILE "avision.conf" -#define MM_PER_INCH (254.0 / 10.0) +#define MM_PER_INCH (25.4) static int num_devices; -static Avision_Device *first_dev; -static Avision_Scanner *first_handle; +static Avision_Device* first_dev; +static Avision_Scanner* first_handle; static const SANE_String_Const mode_list[] = -{ + { "Line Art", "Dithered", "Gray", "Color", 0 -}; + }; /* avision_res will be overwritten in init_options() !!! */ static const SANE_Range u8_range = { - 0, /* minimum */ - 255, /* maximum */ - 0 /* quantization */ + 0, /* minimum */ + 255, /* maximum */ + 0 /* quantization */ }; static const SANE_Range percentage_range = { - SANE_FIX(-100), /* minimum */ - SANE_FIX( 100), /* maximum */ - SANE_FIX( 1 ) /* quantization */ + SANE_FIX (-100), /* minimum */ + SANE_FIX (100), /* maximum */ + SANE_FIX (1) /* quantization */ }; - + static const SANE_Range abs_percentage_range = { - SANE_FIX( 0), /* minimum */ - SANE_FIX( 100), /* maximum */ - SANE_FIX( 1 ) /* quantization */ + SANE_FIX (0), /* minimum */ + SANE_FIX (100), /* maximum */ + SANE_FIX (1) /* quantization */ + }; + + +#define INQ_LEN 0x60 + +static const u_int8_t inquiry[] = + { + AVISION_SCSI_INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; - -#define INQ_LEN 0x60 - -static const u_int8_t inquiry[] = -{ - AVISION_SCSI_INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00 -}; - static const u_int8_t test_unit_ready[] = -{ - AVISION_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 -}; + { + AVISION_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 + }; static const u_int8_t stop[] = -{ - AVISION_SCSI_START_STOP, 0x00, 0x00, 0x00, 0x00, 0x00 -}; + { + AVISION_SCSI_START_STOP, 0x00, 0x00, 0x00, 0x00, 0x00 + }; static const u_int8_t get_status[] = -{ - AVISION_SCSI_GET_DATA_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x00 -}; + { + AVISION_SCSI_GET_DATA_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00 + }; static int make_mode (char *mode) { - DBG(3, "make_mode\n" ); + DBG (3, "make_mode\n"); - if (strcmp (mode, "Line Art") == 0) - return THRESHOLDED; - if (strcmp (mode, "Dithered") == 0) - return DITHERED; - else if (strcmp (mode, "Gray") == 0) - return GREYSCALE; - else if (strcmp (mode, "Color") == 0) - return TRUECOLOR; + if (strcmp (mode, "Line Art") == 0) + return THRESHOLDED; + if (strcmp (mode, "Dithered") == 0) + return DITHERED; + else if (strcmp (mode, "Gray") == 0) + return GREYSCALE; + else if (strcmp (mode, "Color") == 0) + return TRUECOLOR; - return -1; + return -1; } static SANE_Status @@ -168,10 +174,10 @@ wait_ready (int fd) { SANE_Status status; int i; - + for (i = 0; i < 1000; ++i) { - DBG(3, "wait_ready: sending TEST_UNIT_READY\n"); + DBG (3, "wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) @@ -180,7 +186,7 @@ wait_ready (int fd) /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ - DBG(1, "wait_ready: test unit ready failed (%s)\n", + DBG (1, "wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: @@ -191,300 +197,307 @@ wait_ready (int fd) return status; } } - DBG(1, "wait_ready: timed out after %d attempts\n", i); + DBG (1, "wait_ready: timed out after %d attempts\n", i); return SANE_STATUS_INVAL; } static SANE_Status -sense_handler (int fd, u_char *sense, void *arg) +sense_handler (int fd, u_char* sense, void* arg) { - /*MCC*/ + /*MCC*/ - int i; + int i; - SANE_Status status; + SANE_Status status; - SANE_Bool ASC_switch; + SANE_Bool ASC_switch; - DBG(3, "sense_handler\n"); + DBG (3, "sense_handler\n"); - ASC_switch = SANE_FALSE; + ASC_switch = SANE_FALSE; - switch (sense[0]) - { - case 0x00: - status = SANE_STATUS_GOOD; + switch (sense[0]) + { + case 0x00: + status = SANE_STATUS_GOOD; - default: - DBG(1, "sense_handler: got unknown sense code %02x\n", sense[0]); - status = SANE_STATUS_IO_ERROR; - } + default: + DBG (1, "sense_handler: got unknown sense code %02x\n", sense[0]); + status = SANE_STATUS_IO_ERROR; + } - for (i = 0; i < 21; i++) - { - DBG(1, "%d:[%x]\n", i, sense[i]); - } + for (i = 0; i < 21; i++) + { + DBG (1, "%d:[%x]\n", i, sense[i]); + } - if (sense[VALID_BYTE] & VALID) + if (sense[VALID_BYTE] & VALID) + { + switch (sense[ERRCODE_BYTE] & ERRCODEMASK) { - switch (sense[ERRCODE_BYTE] & ERRCODEMASK) - { - case ERRCODESTND: - { - DBG (5, "SENSE: STANDARD ERROR CODE\n" ); - break; - } - case ERRCODEAV: - { - DBG (5, "SENSE: AVISION SPECIFIC ERROR CODE\n" ); - break; - } - } + case ERRCODESTND: + { + DBG (5, "SENSE: STANDARD ERROR CODE\n"); + break; + } + case ERRCODEAV: + { + DBG (5, "SENSE: AVISION SPECIFIC ERROR CODE\n"); + break; + } + } - switch (sense[SENSEKEY_BYTE] & SENSEKEY_MASK) - { + switch (sense[SENSEKEY_BYTE] & SENSEKEY_MASK) + { - case NOSENSE : - { - DBG (5, "SENSE: NO SENSE\n" ); - break; - } - case NOTREADY : - { - DBG (5, "SENSE: NOT READY\n" ); - break; - } - case MEDIUMERROR : - { - DBG (5, "SENSE: MEDIUM ERROR\n" ); - break; - } - case HARDWAREERROR : - { - DBG (5, "SENSE: HARDWARE FAILURE\n" ); - break; - } - case ILLEGALREQUEST : - { - DBG (5, "SENSE: ILLEGAL REQUEST\n" ); - ASC_switch = SANE_TRUE; - break; - } - case UNIT_ATTENTION : - { - DBG (5, "SENSE: UNIT ATTENTION\n" ); - break; - } - case VENDORSPEC : - { - DBG (5, "SENSE: VENDOR SPECIFIC\n" ); - break; - } - case ABORTEDCOMMAND : - { - DBG (5, "SENSE: COMMAND ABORTED\n" ); - break; - } - } - - if (sense[EOS_BYTE] & EOSMASK) - { - DBG (5, "SENSE: END OF SCAN\n" ); - } - else - { - DBG (5, "SENSE: SCAN HAS NOT YET BEEN COMPLETED\n" ); - } - - if (sense[ILI_BYTE] & INVALIDLOGICLEN) - { - DBG (5, "SENSE: INVALID LOGICAL LENGTH\n" ); - } - - - if ((sense[ASC_BYTE] != 0) && (sense[ASCQ_BYTE] != 0)) - { - if (sense[ASC_BYTE] == ASCFILTERPOSERR) - { - DBG (5, "X\n"); - } - - if (sense[ASCQ_BYTE] == ASCQFILTERPOSERR) - { - DBG (5, "X\n"); - } - - if (sense[ASCQ_BYTE] == ASCQFILTERPOSERR) - { - DBG (5, "SENSE: FILTER POSITIONING ERROR\n" ); - } - - if ((sense[ASC_BYTE] == ASCFILTERPOSERR) && - (sense[ASCQ_BYTE] == ASCQFILTERPOSERR)) - { - DBG (5, "SENSE: FILTER POSITIONING ERROR\n" ); - } - - if ((sense[ASC_BYTE] == ASCADFPAPERJAM) && - (sense[ASCQ_BYTE] == ASCQADFPAPERJAM )) - { - DBG(5, "ADF Paper Jam\n" ); - } - if ((sense[ASC_BYTE] == ASCADFCOVEROPEN) && - (sense[ASCQ_BYTE] == ASCQADFCOVEROPEN)) - { - DBG(5, "ADF Cover Open\n" ); - } - if ((sense[ASC_BYTE] == ASCADFPAPERCHUTEEMPTY) && - (sense[ASCQ_BYTE] == ASCQADFPAPERCHUTEEMPTY)) - { - DBG(5, "ADF Paper Chute Empty\n" ); - } - if ((sense[ASC_BYTE] == ASCINTERNALTARGETFAIL) && - (sense[ASCQ_BYTE] == ASCQINTERNALTARGETFAIL)) - { - DBG(5, "Internal Target Failure\n" ); - } - if ((sense[ASC_BYTE] == ASCSCSIPARITYERROR) && - (sense[ASCQ_BYTE] == ASCQSCSIPARITYERROR)) - { - DBG(5, "SCSI Parity Error\n" ); - } - if ((sense[ASC_BYTE] == ASCINVALIDCOMMANDOPCODE) && - (sense[ASCQ_BYTE] == ASCQINVALIDCOMMANDOPCODE)) - { - DBG(5, "Invalid Command Operation Code\n" ); - } - if ((sense[ASC_BYTE] == ASCINVALIDFIELDCDB) && - (sense[ASCQ_BYTE] == ASCQINVALIDFIELDCDB)) - { - DBG(5, "Invalid Field in CDB\n" ); - } - if ((sense[ASC_BYTE] == ASCLUNNOTSUPPORTED) && - (sense[ASCQ_BYTE] == ASCQLUNNOTSUPPORTED)) - { - DBG(5, "Logical Unit Not Supported\n" ); - } - if ((sense[ASC_BYTE] == ASCINVALIDFIELDPARMLIST) && - (sense[ASCQ_BYTE] == ASCQINVALIDFIELDPARMLIST)) - { - DBG(5, "Invalid Field in parameter List\n" ); - } - if ((sense[ASC_BYTE] == ASCINVALIDCOMBINATIONWIN) && - (sense[ASCQ_BYTE] == ASCQINVALIDCOMBINATIONWIN)) - { - DBG(5, "Invalid Combination of Window Specified\n" ); - } - if ((sense[ASC_BYTE] == ASCMSGERROR) && - (sense[ASCQ_BYTE] == ASCQMSGERROR)) - { - DBG(5, "Message Error\n" ); - } - if ((sense[ASC_BYTE] == ASCCOMMCLREDANOTHINITIATOR) && - (sense[ASCQ_BYTE] == ASCQCOMMCLREDANOTHINITIATOR)) - { - DBG(5, "Command Cleared By Another Initiator.\n" ); - } - if ((sense[ASC_BYTE] == ASCIOPROCTERMINATED) && - (sense[ASCQ_BYTE] == ASCQIOPROCTERMINATED)) - { - DBG(5, "I/O process Terminated.\n" ); - } - if ((sense[ASC_BYTE] == ASCINVBITIDMSG) && - (sense[ASCQ_BYTE] == ASCQINVBITIDMSG)) - { - DBG(5, "Invalid Bit in Identify Message\n" ); - } - if ((sense[ASC_BYTE] == ASCINVMSGERROR) && - (sense[ASCQ_BYTE] == ASCQINVMSGERROR)) - { - DBG(5, "Invalid Message Error\n" ); - } - if ((sense[ASC_BYTE] == ASCLAMPFAILURE) && - (sense[ASCQ_BYTE] == ASCQLAMPFAILURE)) - { - DBG(5, "Lamp Failure\n" ); - } - if ((sense[ASC_BYTE] == ASCMECHPOSERROR) && - (sense[ASCQ_BYTE] == ASCQMECHPOSERROR)) - { - DBG(5, "Mechanical Positioning Error\n" ); - } - if ((sense[ASC_BYTE] == ASCPARAMLISTLENERROR) && - (sense[ASCQ_BYTE] == ASCQPARAMLISTLENERROR)) - { - DBG(5, "Parameter List Length Error\n" ); - } - if ((sense[ASC_BYTE] == ASCPARAMNOTSUPPORTED) && - (sense[ASCQ_BYTE] == ASCQPARAMNOTSUPPORTED)) - { - DBG(5, "Parameter Not Supported\n" ); - } - if ((sense[ASC_BYTE] == ASCPARAMVALINVALID ) && - (sense[ASCQ_BYTE] == ASCQPARAMVALINVALID ) ) - { - DBG(5, "Parameter Value Invalid\n" ); - } - if ((sense[ASC_BYTE] == ASCPOWERONRESET) && - (sense[ASCQ_BYTE] == ASCQPOWERONRESET)) - { - DBG(5, "Power-on, Reset, or Bus Device Reset Occurred\n" ); - } - if ((sense[ASC_BYTE] == ASCSCANHEADPOSERROR) && - (sense[ASCQ_BYTE] == ASCQSCANHEADPOSERROR)) - { - DBG (5, "SENSE: FILTER POSITIONING ERROR\n" ); - } - - } - else - { - DBG(5, "No Additional Sense Information\n" ); - } - - if (ASC_switch == SANE_TRUE) - { - if (sense[SKSV_BYTE] & SKSVMASK) - { - if (sense[CD_BYTE] & CDMASK) - { - DBG (5, "SENSE: ERROR IN COMMAND PARAMETER...\n" ); - } - else - { - DBG (5, "SENSE: ERROR IN DATA PARAMETER...\n" ); - } - - if (sense[BPV_BYTE] & BPVMASK) - { - DBG(5, "BIT %d ERRORNOUS OF\n", (int)sense[BITPOINTER_BYTE] & BITPOINTERMASK); - } - - DBG(5, "ERRORNOUS BYTE %d \n", (int)sense[BYTEPOINTER_BYTE1] ); - - } - - } - - + case NOSENSE : + { + DBG (5, "SENSE: NO SENSE\n"); + break; + } + case NOTREADY : + { + DBG (5, "SENSE: NOT READY\n"); + break; + } + case MEDIUMERROR : + { + DBG (5, "SENSE: MEDIUM ERROR\n"); + break; + } + case HARDWAREERROR : + { + DBG (5, "SENSE: HARDWARE FAILURE\n"); + break; + } + case ILLEGALREQUEST : + { + DBG (5, "SENSE: ILLEGAL REQUEST\n"); + ASC_switch = SANE_TRUE; + break; + } + case UNIT_ATTENTION : + { + DBG (5, "SENSE: UNIT ATTENTION\n"); + break; + } + case VENDORSPEC : + { + DBG (5, "SENSE: VENDOR SPECIFIC\n"); + break; + } + case ABORTEDCOMMAND : + { + DBG (5, "SENSE: COMMAND ABORTED\n"); + break; + } } - return status; + + if (sense[EOS_BYTE] & EOSMASK) + { + DBG (5, "SENSE: END OF SCAN\n"); + } + else + { + DBG (5, "SENSE: SCAN HAS NOT YET BEEN COMPLETED\n"); + } + + if (sense[ILI_BYTE] & INVALIDLOGICLEN) + { + DBG (5, "SENSE: INVALID LOGICAL LENGTH\n"); + } + + + if ((sense[ASC_BYTE] != 0) && (sense[ASCQ_BYTE] != 0)) + { + if (sense[ASC_BYTE] == ASCFILTERPOSERR) + { + DBG (5, "X\n"); + } + + if (sense[ASCQ_BYTE] == ASCQFILTERPOSERR) + { + DBG (5, "X\n"); + } + + if (sense[ASCQ_BYTE] == ASCQFILTERPOSERR) + { + DBG (5, "SENSE: FILTER POSITIONING ERROR\n"); + } + + if ((sense[ASC_BYTE] == ASCFILTERPOSERR) && + (sense[ASCQ_BYTE] == ASCQFILTERPOSERR)) + { + DBG (5, "SENSE: FILTER POSITIONING ERROR\n"); + } + + if ((sense[ASC_BYTE] == ASCADFPAPERJAM) && + (sense[ASCQ_BYTE] == ASCQADFPAPERJAM )) + { + DBG (5, "ADF Paper Jam\n"); + } + if ((sense[ASC_BYTE] == ASCADFCOVEROPEN) && + (sense[ASCQ_BYTE] == ASCQADFCOVEROPEN)) + { + DBG (5, "ADF Cover Open\n"); + } + if ((sense[ASC_BYTE] == ASCADFPAPERCHUTEEMPTY) && + (sense[ASCQ_BYTE] == ASCQADFPAPERCHUTEEMPTY)) + { + DBG (5, "ADF Paper Chute Empty\n"); + } + if ((sense[ASC_BYTE] == ASCINTERNALTARGETFAIL) && + (sense[ASCQ_BYTE] == ASCQINTERNALTARGETFAIL)) + { + DBG (5, "Internal Target Failure\n"); + } + if ((sense[ASC_BYTE] == ASCSCSIPARITYERROR) && + (sense[ASCQ_BYTE] == ASCQSCSIPARITYERROR)) + { + DBG (5, "SCSI Parity Error\n"); + } + if ((sense[ASC_BYTE] == ASCINVALIDCOMMANDOPCODE) && + (sense[ASCQ_BYTE] == ASCQINVALIDCOMMANDOPCODE)) + { + DBG (5, "Invalid Command Operation Code\n"); + } + if ((sense[ASC_BYTE] == ASCINVALIDFIELDCDB) && + (sense[ASCQ_BYTE] == ASCQINVALIDFIELDCDB)) + { + DBG (5, "Invalid Field in CDB\n"); + } + if ((sense[ASC_BYTE] == ASCLUNNOTSUPPORTED) && + (sense[ASCQ_BYTE] == ASCQLUNNOTSUPPORTED)) + { + DBG (5, "Logical Unit Not Supported\n"); + } + if ((sense[ASC_BYTE] == ASCINVALIDFIELDPARMLIST) && + (sense[ASCQ_BYTE] == ASCQINVALIDFIELDPARMLIST)) + { + DBG (5, "Invalid Field in parameter List\n"); + } + if ((sense[ASC_BYTE] == ASCINVALIDCOMBINATIONWIN) && + (sense[ASCQ_BYTE] == ASCQINVALIDCOMBINATIONWIN)) + { + DBG (5, "Invalid Combination of Window Specified\n"); + } + if ((sense[ASC_BYTE] == ASCMSGERROR) && + (sense[ASCQ_BYTE] == ASCQMSGERROR)) + { + DBG (5, "Message Error\n"); + } + if ((sense[ASC_BYTE] == ASCCOMMCLREDANOTHINITIATOR) && + (sense[ASCQ_BYTE] == ASCQCOMMCLREDANOTHINITIATOR)) + { + DBG (5, "Command Cleared By Another Initiator.\n"); + } + if ((sense[ASC_BYTE] == ASCIOPROCTERMINATED) && + (sense[ASCQ_BYTE] == ASCQIOPROCTERMINATED)) + { + DBG (5, "I/O process Terminated.\n"); + } + if ((sense[ASC_BYTE] == ASCINVBITIDMSG) && + (sense[ASCQ_BYTE] == ASCQINVBITIDMSG)) + { + DBG (5, "Invalid Bit in Identify Message\n"); + } + if ((sense[ASC_BYTE] == ASCINVMSGERROR) && + (sense[ASCQ_BYTE] == ASCQINVMSGERROR)) + { + DBG (5, "Invalid Message Error\n"); + } + if ((sense[ASC_BYTE] == ASCLAMPFAILURE) && + (sense[ASCQ_BYTE] == ASCQLAMPFAILURE)) + { + DBG (5, "Lamp Failure\n"); + } + if ((sense[ASC_BYTE] == ASCMECHPOSERROR) && + (sense[ASCQ_BYTE] == ASCQMECHPOSERROR)) + { + DBG (5, "Mechanical Positioning Error\n"); + } + if ((sense[ASC_BYTE] == ASCPARAMLISTLENERROR) && + (sense[ASCQ_BYTE] == ASCQPARAMLISTLENERROR)) + { + DBG (5, "Parameter List Length Error\n"); + } + if ((sense[ASC_BYTE] == ASCPARAMNOTSUPPORTED) && + (sense[ASCQ_BYTE] == ASCQPARAMNOTSUPPORTED)) + { + DBG (5, "Parameter Not Supported\n"); + } + if ((sense[ASC_BYTE] == ASCPARAMVALINVALID ) && + (sense[ASCQ_BYTE] == ASCQPARAMVALINVALID ) ) + { + DBG (5, "Parameter Value Invalid\n"); + } + if ((sense[ASC_BYTE] == ASCPOWERONRESET) && + (sense[ASCQ_BYTE] == ASCQPOWERONRESET)) + { + DBG (5, "Power-on, Reset, or Bus Device Reset Occurred\n"); + } + if ((sense[ASC_BYTE] == ASCSCANHEADPOSERROR) && + (sense[ASCQ_BYTE] == ASCQSCANHEADPOSERROR)) + { + DBG (5, "SENSE: FILTER POSITIONING ERROR\n"); + } + + } + else + { + DBG (5, "No Additional Sense Information\n"); + } + + if (ASC_switch == SANE_TRUE) + { + if (sense[SKSV_BYTE] & SKSVMASK) + { + if (sense[CD_BYTE] & CDMASK) + { + DBG (5, "SENSE: ERROR IN COMMAND PARAMETER...\n"); + } + else + { + DBG (5, "SENSE: ERROR IN DATA PARAMETER...\n"); + } + + if (sense[BPV_BYTE] & BPVMASK) + { + DBG (5, "BIT %d ERRORNOUS OF\n", (int)sense[BITPOINTER_BYTE] & BITPOINTERMASK); + } + + DBG (5, "ERRORNOUS BYTE %d \n", (int)sense[BYTEPOINTER_BYTE1] ); + + } + + } + + + } + return status; } static SANE_Status -attach (const char *devname, Avision_Device **devp) +attach (const char* devname, Avision_Device** devp) { - char result[INQ_LEN]; + unsigned char result [INQ_LEN]; int fd; - Avision_Device *dev; + Avision_Device* dev; SANE_Status status; size_t size; - char *mfg, *model; - char *p; - DBG(3, "attach\n" ); + char mfg[9]; + char model[17]; + char rev[5]; + + int i; + + double x_range; + double y_range; + + DBG (3, "attach\n"); for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { @@ -493,18 +506,18 @@ attach (const char *devname, Avision_Device **devp) return SANE_STATUS_GOOD; } - DBG(3, "attach: opening %s\n", devname); + DBG (3, "attach: opening %s\n", devname); status = sanei_scsi_open (devname, &fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { - DBG(1, "attach: open failed (%s)\n", sane_strstatus (status)); + DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } - DBG(3, "attach: sending INQUIRY\n"); + DBG (3, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size); if (status != SANE_STATUS_GOOD || size != INQ_LEN) { - DBG(1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); + DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } @@ -514,30 +527,18 @@ attach (const char *devname, Avision_Device **devp) if (status != SANE_STATUS_GOOD) return status; - /* DEBUG CODE!! To test new Scanenr Output... - printf ("RAW.Result: "); - for (i = 0; i < sizeof (result); i++) - { - printf ("%d:[%c-%x], ", i, result[i], (unsigned char) result[i]); - } - printf ("\n"); - */ + /* copy string information - and build zero terminated c-strings */ + memcpy (&mfg, result + 8, 8); + mfg [8] = 0; + memcpy (&model, result + 16, 16); + model [16] = 0; + memcpy (&rev, result + 32, 4); + rev [4] = 0; - result[33]= '\0'; - p = strchr(result+16,' '); - if (p) *p = '\0'; - model = strdup (result+16); - - result[16]= '\0'; - p = strchr(result+8,' '); - if (p) *p = '\0'; - mfg = strdup (result+8); - - DBG(1, "attach: Inquiry gives mfg=%s, model=%s.\n", mfg, model); + DBG (1, "attach: Inquiry gives mfg=%s, model=%s, product revision=%s.\n", &mfg, &model, &rev); - if (strcmp (mfg, "AVISION") != 0) { - DBG(1, "attach: device doesn't look like a AVISION scanner " - "(result[0]=%#02x)\n", result[0]); + if (strcmp (&mfg, "AVISION ") != 0) { + DBG (1, "attach: device doesn't look like a AVISION scanner!"); return SANE_STATUS_INVAL; } @@ -545,40 +546,48 @@ attach (const char *devname, Avision_Device **devp) if (!dev) return SANE_STATUS_NO_MEM; - memset (dev, 0, sizeof (*dev)); + memset (dev, 0x0, sizeof (*dev)); dev->sane.name = strdup (devname); dev->sane.vendor = "AVISION"; - dev->sane.model = model; + dev->sane.model = strdup (&model); dev->sane.type = "flatbed scanner"; - dev->x_range.min = 0; - dev->y_range.min = 0; - /* Getting max X and max > ...*/ - /* Doesn't work! Avision doesn't return the information! ... - dev->x_range.max = SANE_FIX ( (int) ((((int) result[81] << 8) + result[82]) / 300) * MM_PER_INCH); - dev->y_range.max = SANE_FIX ( (int) ((((int) result[83] << 8) + result[84]) / 300) * MM_PER_INCH); - */ - dev->x_range.max = SANE_FIX ( 8.5 * MM_PER_INCH); - dev->y_range.max = SANE_FIX (11.8 * MM_PER_INCH); - + /* Get max X and max Y ...*/ + x_range = ( ( ( (unsigned int)result[81] << 8) + (unsigned int)result[82] ) / 300 ) * MM_PER_INCH; + y_range = ( ( ( (unsigned int)result[83] << 8) + (unsigned int)result[84] ) / 300 ) * MM_PER_INCH; + dev->x_range.max = SANE_FIX (x_range); + dev->y_range.max = SANE_FIX (y_range); + dev->x_range.quant = 0; dev->y_range.quant = 0; - /* Maybe an other Avision Scanner returns this ... and I like test it... - printf ("X-Range: %d inch\n", dev->x_range.max); - printf ("Y-Range: %d inch\n", dev->y_range.max); - - printf ("Raw-Range: %d, %d, %d, %d\n", (int)result[81], (int)result[82], (int)result[83], (int)result[84]); - */ - dev->dpi_range.min = 50; dev->dpi_range.quant = 1; dev->dpi_range.max = 1200; - DBG(3, "attach: found AVISION scanner model %s (%s)\n", - dev->sane.model, dev->sane.type); - + DBG (3, "attach: found AVISION scanner model %s (%s)\n", dev->sane.model, dev->sane.type); + DBG (3, " X-Range: %fmm, Y-Range: %fmm (Raw-Range: %d, %d, %d, %d)\n", + SANE_UNFIX (dev->x_range.max), + SANE_UNFIX (dev->y_range.max), + (int)result[81], (int)result[82], (int)result[83], (int)result[84]); + + DBG (5, "RAW.Result:\n"); + for (i = 0; i < sizeof (result); i++) + { + DBG (5, "[%d]:%x->""%c""\n", i, (unsigned char) result[i], result[i]); + } + + /* check if x/y range is vaild :-((( */ + if (dev->x_range.max == 0 || dev->y_range.max == 0) + { + DBG (3, "Inquiry x/y-range is invaild! Using defauld %fx%finch (ISO A4).\n", MAX_X_RANGE, MAX_Y_RANGE); + dev->x_range.max = SANE_FIX (MAX_X_RANGE * MM_PER_INCH); + dev->y_range.max = SANE_FIX (MAX_Y_RANGE * MM_PER_INCH); + } + else + DBG (3, "Inquiry x/y-range is vaild?!?\n"); + ++num_devices; dev->next = first_dev; first_dev = dev; @@ -595,7 +604,7 @@ max_string_size (const SANE_String_Const strings[]) size_t size, max_size = 0; int i; - DBG(3, "max_string_size\n" ); + DBG (3, "max_string_size\n"); for (i = 0; strings[i]; ++i) { @@ -606,196 +615,347 @@ max_string_size (const SANE_String_Const strings[]) return max_size; } - static SANE_Status constrain_value (Avision_Scanner *s, SANE_Int option, void *value, SANE_Int *info) { - DBG(3, "constrain_value\n" ); + DBG (3, "constrain_value\n"); return sanei_constrain_value (s->opt + option, value, info); } - -/* Will we need this ever??? Clean up in next release Meino??? -static unsigned char sign_mag (double val) -{ - if (val > 100) val = 100; - if (val < -100) val = -100; - if (val >= 0) return ( val); - else return ((unsigned char)(-val)) | 0x80; -} +/* next was taken from the GIMP and is a bit modifyed ... ;-) + * original Copyright (C) 1995 Spencer Kimball and Peter Mattis */ - -static SANE_Status -scan_area_and_windows (Avision_Scanner *s) +static double +brightness_contrast_func (double brightness, double contrast, double value) { - SANE_Status status; - struct def_win_par dwp; + double nvalue; + double power; + + /* apply brightness */ + if (brightness < 0.0) + value = value * (1.0 + brightness); + else + value = value + ((1.0 - value) * brightness); + + /* apply contrast */ + if (contrast < 0.0) + { + if (value > 0.5) + nvalue = 1.0 - value; + else + nvalue = value; + if (nvalue < 0.0) + nvalue = 0.0; + nvalue = 0.5 * pow (nvalue * 2.0 , (double) (1.0 + contrast)); + if (value > 0.5) + value = 1.0 - nvalue; + else + value = nvalue; + } + else + { + if (value > 0.5) + nvalue = 1.0 - value; + else + nvalue = value; + if (nvalue < 0.0) + nvalue = 0.0; + power = (contrast == 1.0) ? 127 : 1.0 / (1.0 - contrast); + nvalue = 0.5 * pow (2.0 * nvalue, power); + if (value > 0.5) + value = 1.0 - nvalue; + else + value = nvalue; + } + return value; +} +static SANE_Status +set_gamma (Avision_Scanner* s) +{ +#define GAMMA_TABLE_SIZE 4096 + + SANE_Status status; + struct gamma_cmd + { + struct command_send cmd; + unsigned char gamma_data [GAMMA_TABLE_SIZE]; + }; + + struct gamma_cmd* cmd; + + int color; /* current color */ + int i; /* big table index */ + int j; /* little table index */ + int k; /* big table sub index */ + double v1, v2; + + double brightness; + double contrast; + /* double threshold; */ + + DBG (3, "set_gamma\n"); + + /* prepare for emulating contrast, brightness ... via the gamma-table */ + brightness = SANE_UNFIX (s->val[OPT_BRIGHTNESS].w); + brightness /= 100; + contrast = SANE_UNFIX (s->val[OPT_CONTRAST].w); + contrast /= 100; + + DBG (3, "brightness: %f, contrast: %f\n", brightness, contrast); + + /* threshold = SANE_UNFIX (s->val[OPT_THRESHOLD].w); */ + /* threshold /= 100; */ + + /* should we sent a custom gamma-table ?? + * don't send anything if no - the scanner may not understand the gamma-table + */ + if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) + { + DBG (4, "use custom gamma-table\n"); + for (color = 0; color < 3; color++) + { + cmd = malloc (sizeof (*cmd) ); + + memset (cmd, 0x0, sizeof (*cmd) ); + + cmd->cmd.opc = AVISION_SCSI_SEND; + cmd->cmd.datatypecode = 0x81; /* 0x81 for download gama table */ + set_double (cmd->cmd.datatypequal, color); /* color: 0=red; 1=green; 2=blue */ + set_triple (cmd->cmd.transferlen, GAMMA_TABLE_SIZE); + + i = 0; /* big table index */ + for (j = 0; j < 256; j++) /* little table index */ + { + /* calculate mode dependent values v1 and v2 + * v1 <- current value for table + * v2 <- next value for table (for interpolation) + */ + switch (s->mode) + { + case TRUECOLOR: + { + v1 = (double) (s->gamma_table [0][j] + s->gamma_table [1 + color][j] ) / 2; + if (j == 255) + v2 = (double) v1; + else + v2 = (double) (s->gamma_table [0][j + 1] + s->gamma_table [1 + color][j + 1] ) / 2; + } + break; + default: + /* for all other modes: */ + { + v1 = (double) s->gamma_table [0][j]; + if (j == 255) + v2 = (double) v1; + else + v2 = (double) s->gamma_table [0][j + 1]; + } + } /*end switch */ + /* emulate brightness, contrast ... + * taken from the GIMP source - I'll optimize it when it is known to work + */ + + v1 /= 255; + v2 /= 255; + + v1 = (brightness_contrast_func (brightness, contrast, v1) ); + v2 = (brightness_contrast_func (brightness, contrast, v2) ); + + v1 *= 255; + v2 *= 255; + for (k = 0; k < 8; k++, i++) + cmd->gamma_data [i] = ( ( (unsigned char)v1 * (8 - k)) + ( (unsigned char)v2 * k) ) / 8; + } + /* fill the gamma table */ + for (i = 2048; i < 4096; i++) + cmd->gamma_data [i] = cmd->gamma_data [2047]; + + status = sanei_scsi_cmd (s->fd, cmd, sizeof (*cmd), 0, 0); + + free (cmd); + } + } /* end if custom gamma*/ + else /* no custom gamma */ + { + DBG (4, "don't use custom gamma-table\n"); + status = SANE_STATUS_GOOD; + } + + return status; +} +static SANE_Status +set_window (Avision_Scanner* s) +{ + SANE_Status status; + struct + { + struct command_set_window cmd; + struct command_set_window_window_header window_header; + struct command_set_window_window_descriptor window_descriptor; + } cmd; - DBG(3, "scan_area_and_windows\n" ); + DBG (3, "set_windows\n"); - /* wipe out anything - */ - memset (&dwp,'\0',sizeof (dwp)); + /* wipe out anything */ + memset (&cmd, 0x0, sizeof (cmd) ); - /* command setup - */ - dwp.dwph.opc = AVISION_SCSI_AREA_AND_WINDOWS; - set_triple (dwp.dwph.len,sizeof (dwp.wdh) + sizeof (dwp.wdb)); - set_double (dwp.wdh.wpll, sizeof (dwp.wdb)); + /* command setup */ + cmd.cmd.opc = AVISION_SCSI_SET_WINDOWS; + set_triple (cmd.cmd.transferlen, + sizeof (cmd.window_header) + sizeof (cmd.window_descriptor) ); + set_double (cmd.window_header.desclen, sizeof (cmd.window_descriptor) ); - /* resolution parameters - */ - set_double (dwp.wdb.xres, s->avdimen.res); - set_double (dwp.wdb.yres, s->avdimen.res); + /* resolution parameters */ + set_double (cmd.window_descriptor.xres, s->avdimen.res); + set_double (cmd.window_descriptor.yres, s->avdimen.res); - /* upper left corner coordinates - */ - set_quad (dwp.wdb.ulx, s->avdimen.tlx); - set_quad (dwp.wdb.uly, s->avdimen.tly); + /* upper left corner coordinates */ + set_quad (cmd.window_descriptor.ulx, s->avdimen.tlx); + set_quad (cmd.window_descriptor.uly, s->avdimen.tly); - /* width and length in inch/1200 - */ - set_quad (dwp.wdb.width, s->avdimen.wid); - set_quad (dwp.wdb.length, s->avdimen.len); + /* width and length in inch/1200 */ + set_quad (cmd.window_descriptor.width, s->avdimen.wid); + set_quad (cmd.window_descriptor.length, s->avdimen.len); - /* width and length in bytes - */ - set_double (dwp.wdb.linewidth, s->params.bytes_per_line ); - set_double (dwp.wdb.linecount, s->params.lines ); + /* width and length in bytes */ + set_double (cmd.window_descriptor.linewidth, s->params.bytes_per_line ); + set_double (cmd.window_descriptor.linecount, s->params.lines ); - dwp.wdb.bitset1 = 0x60; - dwp.wdb.bitset1 |= s->val[OPT_SPEED].w; - - dwp.wdb.bitset2 = 0x00; - - /* quality scan option switch - */ - if( s->val[OPT_QSCAN].w == SANE_TRUE ) - { - dwp.wdb.bitset2 |= AV_QSCAN_ON; /* Q_SCAN ON */ - } - - /* quality calibration option switch - */ - if( s->val[OPT_QCALIB].w == SANE_TRUE ) - { - dwp.wdb.bitset2 |= AV_QCALIB_ON; /* Q_CALIB ON */ - } - /* transparency switch - */ - if( s->val[OPT_TRANS].w == SANE_TRUE ) - { - dwp.wdb.bitset2 |= AV_TRANS_ON; /* Set to transparency mode */ - } + cmd.window_descriptor.bitset1 = 0x60; + cmd.window_descriptor.bitset1 |= s->val[OPT_SPEED].w; - /* fixed value - */ - dwp.wdb.pad_type = 3; - dwp.wdb.vendor_specid = 0xFF; - dwp.wdb.paralen = 9; + cmd.window_descriptor.bitset2 = 0x00; - /* currently also fixed - (and unsopported by all Avision scanner I know ...) - */ - dwp.wdb.highlight = 0xFF; - dwp.wdb.shadow = 0x00; - - /* mode dependant settings - */ - switch (s->mode) { - - case THRESHOLDED: - dwp.wdb.bpp = 1; - dwp.wdb.image_comp = 0; - dwp.wdb.bitset1 &= 0xC7; - dwp.wdb.thresh = 1 + 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); - dwp.wdb.brightness = 128 + 1.28 * (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); - dwp.wdb.contrast = 128 + 1.28 * (SANE_UNFIX (s->val[OPT_CONTRAST].w)); - break; - - case DITHERED: - dwp.wdb.bpp = 1; - dwp.wdb.image_comp = 1; - dwp.wdb.bitset1 &= 0xC7; - dwp.wdb.thresh = 1 + 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); - dwp.wdb.brightness = 128 + 1.28 * (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); - dwp.wdb.contrast = 128 + 1.28 * (SANE_UNFIX (s->val[OPT_CONTRAST].w)); - break; - - case GREYSCALE: - dwp.wdb.bpp = 8; - dwp.wdb.image_comp = 2; - dwp.wdb.bitset1 &= 0xC7; - /*dwp.wdb.bitset1 |= 0x30; *//* thanks Gunter */ - break; - - case TRUECOLOR: - dwp.wdb.bpp = 8; - dwp.wdb.image_comp = 5; - break; - - default: - DBG(3, "Invalid mode. %d\n", s->mode); - exit (1); + /* quality scan option switch */ + if( s->val[OPT_QSCAN].w == SANE_TRUE ) + { + cmd.window_descriptor.bitset2 |= AV_QSCAN_ON; /* Q_SCAN ON */ } - /* set window command - */ - status = sanei_scsi_cmd (s->fd, &dwp, sizeof (dwp), 0, 0); + /* quality calibration option switch */ + if ( s->val[OPT_QCALIB].w == SANE_TRUE ) + { + cmd.window_descriptor.bitset2 |= AV_QCALIB_ON; /* Q_CALIB ON */ + } + /* transparency switch */ + if ( s->val[OPT_TRANS].w == SANE_TRUE ) + { + cmd.window_descriptor.bitset2 |= AV_TRANS_ON; /* Set to transparency mode */ + } + + /* fixed value + */ + cmd.window_descriptor.pad_type = 3; + cmd.window_descriptor.vendor_specid = 0xFF; + cmd.window_descriptor.paralen = 9; - /* back to caller - */ - return status; + /* currently also fixed + * (and unsopported by all Avision scanner I know ...) + */ + cmd.window_descriptor.highlight = 0xFF; + cmd.window_descriptor.shadow = 0x00; + + /* this is normaly unsupported by avsion scanner. + * I clear this only to be shure if an other scanner knows about it ... + * we do this via the gamma table (soon) ... + */ + cmd.window_descriptor.thresh = 128; + cmd.window_descriptor.brightness = 128; + cmd.window_descriptor.contrast = 128; + + /* + * cmd.window_descriptor.thresh = 1 + 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); + * cmd.window_descriptor.brightness = 128 + 1.28 * (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); + * cmd.window_descriptor.contrast = 128 + 1.28 * (SANE_UNFIX (s->val[OPT_CONTRAST].w)); + */ + + /* mode dependant settings */ + switch (s->mode) + { + case THRESHOLDED: + cmd.window_descriptor.bpp = 1; + cmd.window_descriptor.image_comp = 0; + cmd.window_descriptor.bitset1 &= 0xC7; + break; + + case DITHERED: + cmd.window_descriptor.bpp = 1; + cmd.window_descriptor.image_comp = 1; + cmd.window_descriptor.bitset1 &= 0xC7; + break; + + case GREYSCALE: + cmd.window_descriptor.bpp = 8; + cmd.window_descriptor.image_comp = 2; + cmd.window_descriptor.bitset1 &= 0xC7; + /* cmd.window_descriptor.bitset1 |= 0x30; */ /* what is it for Gunter ?? - doesn't work */ + break; + + case TRUECOLOR: + cmd.window_descriptor.bpp = 8; + cmd.window_descriptor.image_comp = 5; + break; + + default: + DBG (3, "Invalid mode. %d\n", s->mode); + exit (1); + } + + /* set window command + */ + status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); + + /* back to caller + */ + return status; } static SANE_Status start_scan (Avision_Scanner *s) { - struct command_scan cmd; + struct command_scan cmd; - DBG(3, "start_scan\n" ); + DBG (3, "start_scan\n"); - memset (&cmd,'\0',sizeof (cmd)); - cmd.opc = AVISION_SCSI_START_STOP; - cmd.transferlen = 1; + memset (&cmd, 0x0, sizeof (cmd)); + cmd.opc = AVISION_SCSI_START_STOP; + cmd.transferlen = 1; - if (s->val[OPT_PREVIEW].w == SANE_TRUE) { - cmd.bitset1 |= 0x01<<6; - } - else { - cmd.bitset1 &= ~(0x01<<6); - } + if (s->val[OPT_PREVIEW].w == SANE_TRUE) { + cmd.bitset1 |= 0x01<<6; + } + else { + cmd.bitset1 &= ~(0x01<<6); + } - if (s->val[OPT_QSCAN].w == SANE_TRUE) { - cmd.bitset1 |= 0x01<<7; - } - else { - cmd.bitset1 &= ~(0x01<<7); - } + if (s->val[OPT_QSCAN].w == SANE_TRUE) { + cmd.bitset1 |= 0x01<<7; + } + else { + cmd.bitset1 &= ~(0x01<<7); + } - return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); + return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); } - static SANE_Status stop_scan (Avision_Scanner *s) { /* XXX I don't think a AVISION can stop in mid-scan. Just stop sending it requests for data.... - */ - DBG(3, "stop_scan\n" ); + */ + DBG (3, "stop_scan\n"); return sanei_scsi_cmd (s->fd, stop, sizeof (stop), 0, 0); } - static SANE_Status do_eof (Avision_Scanner *s) { int childstat; - DBG(3, "do_eof\n" ); + DBG (3, "do_eof\n"); if (s->pipe >= 0) @@ -809,12 +969,11 @@ do_eof (Avision_Scanner *s) return SANE_STATUS_EOF; } - static SANE_Status do_cancel (Avision_Scanner *s) { - DBG(3, "do_cancel\n" ); + DBG (3, "do_cancel\n"); s->scanning = SANE_FALSE; s->pass = 0; @@ -842,39 +1001,37 @@ do_cancel (Avision_Scanner *s) } static SANE_Status -read_data (Avision_Scanner *s, SANE_Byte *buf, int lines, int bpl) +read_data (Avision_Scanner* s, SANE_Byte* buf, int lines, int bpl) { struct command_read rcmd; size_t nbytes; SANE_Status status; - DBG(3, "read_data\n" ); + DBG (3, "read_data\n"); nbytes = bpl * lines; - memset (&rcmd,'\0',sizeof (rcmd)); + memset (&rcmd, 0x0, sizeof (rcmd)); rcmd.opc = 0x28; - set_triple (rcmd.transferlen,nbytes); - rcmd.datatypequal[0]=0x0d; - rcmd.datatypequal[1]=0x0a; + set_triple (rcmd.transferlen, nbytes); + rcmd.datatypequal [0] = 0x0d; + rcmd.datatypequal [1] = 0x0a; - DBG(3, "read_data: bytes %d\n", nbytes ); + DBG (3, "read_data: bytes %d\n", nbytes ); status = sanei_scsi_cmd (s->fd, &rcmd, sizeof (rcmd), buf, &nbytes); return status; } - - static SANE_Status -init_options (Avision_Scanner *s) +init_options (Avision_Scanner* s) { int i; - DBG(3, "init_options\n" ); + DBG (3, "init_options\n"); - memset (s->opt, 0, sizeof (s->opt)); - memset (s->val, 0, sizeof (s->val)); + memset (s->opt, 0x0, sizeof (s->opt)); + memset (s->val, 0x0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); @@ -882,13 +1039,13 @@ init_options (Avision_Scanner *s) } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; - s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; + s->opt[OPT_NUM_OPTS].desc = ""; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ - s->opt[OPT_MODE_GROUP].title = "Scan Mode"; - s->opt[OPT_MODE_GROUP].desc = ""; + s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; + s->opt[OPT_MODE_GROUP].desc = ""; /* for groups only title and type are vaild */ s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; @@ -896,7 +1053,7 @@ init_options (Avision_Scanner *s) /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; - s->opt[OPT_MODE].desc = "Select the scan mode"; + s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; @@ -938,7 +1095,7 @@ init_options (Avision_Scanner *s) /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; - s->opt[OPT_GEOMETRY_GROUP].desc = ""; + s->opt[OPT_GEOMETRY_GROUP].desc = ""; /* for groups only title and type are vaild */ s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; @@ -985,15 +1142,17 @@ init_options (Avision_Scanner *s) /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; - s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; + s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* for groups only title and type are vaild */ s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* transparency adapter. */ s->opt[OPT_TRANS].name = "transparency"; - s->opt[OPT_TRANS].title = "transparency"; - s->opt[OPT_TRANS].desc = "Switch transparency mode on."; + s->opt[OPT_TRANS].title = "Enable transparency adapter"; + s->opt[OPT_TRANS].desc = "Switch transparency mode on. Which mainly switches the scanner " \ + "lamp off. (Hint: This can also be used to switch the scanner lamp off when you don't " \ + "use the scanner in the next time. Simply enable this option and do a preview.)"; s->opt[OPT_TRANS].type = SANE_TYPE_BOOL; s->opt[OPT_TRANS].unit = SANE_UNIT_NONE; s->val[OPT_TRANS].w = SANE_FALSE; @@ -1001,9 +1160,7 @@ init_options (Avision_Scanner *s) /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; - s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS - " This option is active for lineart/halftone modes only. " - "For multibit modes (grey/color) use the gamma-table(s)."; + s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; @@ -1013,9 +1170,7 @@ init_options (Avision_Scanner *s) /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; - s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST - " This option is active for lineart/halftone modes only. " - "For multibit modes (grey/color) use the gamma-table(s)."; + s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; @@ -1034,8 +1189,8 @@ init_options (Avision_Scanner *s) s->val[OPT_THRESHOLD].w = SANE_FIX(50); /* Quality Scan */ - s->opt[OPT_QSCAN].name = "Qualitiy Scan"; - s->opt[OPT_QSCAN].title = "Quality Scan"; + s->opt[OPT_QSCAN].name = "quality-scan"; + s->opt[OPT_QSCAN].title = "Quality scan"; s->opt[OPT_QSCAN].desc = "Turn on quality scanning (slower & better)"; s->opt[OPT_QSCAN].type = SANE_TYPE_BOOL; s->opt[OPT_QSCAN].unit = SANE_UNIT_NONE; @@ -1049,21 +1204,22 @@ init_options (Avision_Scanner *s) s->opt[OPT_QCALIB].unit = SANE_UNIT_NONE; s->val[OPT_QCALIB].w = SANE_TRUE; -#if 0 /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; - s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; + s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA " (Hint: When this option is " \ + "disabled NO gamma-table will be send at all. The scanner will use the build in " \ + " gamma-table or (if it got one already) use the last gamma-table it got."; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; - s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; - s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; + /* s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; */ + s->val[OPT_CUSTOM_GAMMA].w = SANE_TRUE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; - s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; + /* s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; */ s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; @@ -1075,7 +1231,7 @@ init_options (Avision_Scanner *s) s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; - s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; + /* s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; */ s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; @@ -1087,7 +1243,7 @@ init_options (Avision_Scanner *s) s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; - s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; + /* s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; */ s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; @@ -1099,13 +1255,12 @@ init_options (Avision_Scanner *s) s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; - s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; + /* s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; */ s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; -#endif return SANE_STATUS_GOOD; } @@ -1124,83 +1279,83 @@ init_options (Avision_Scanner *s) static int reader_process (Avision_Scanner *s, int fd) { - SANE_Byte *data; - int lines_per_buffer, bpl; - SANE_Status status; - sigset_t sigterm_set; - FILE *fp; + SANE_Byte *data; + int lines_per_buffer, bpl; + SANE_Status status; + sigset_t sigterm_set; + FILE *fp; - DBG(3, "reader_process\n" ); + DBG (3, "reader_process\n"); - sigemptyset (&sigterm_set); - sigaddset (&sigterm_set, SIGTERM); + sigemptyset (&sigterm_set); + sigaddset (&sigterm_set, SIGTERM); - fp = fdopen (fd, "w"); - if (!fp) - return 1; + fp = fdopen (fd, "w"); + if (!fp) + return 1; - bpl = s->params.bytes_per_line; - /* the "/2" is a test if scanning gets a bit faster ... ?!? ;-) - (see related discussions on sane-ml) - */ - lines_per_buffer = sanei_scsi_max_request_size / bpl / 2; - if (!lines_per_buffer) - return 2; /* resolution is too high */ + bpl = s->params.bytes_per_line; + /* the "/2" is a test if scanning gets a bit faster ... ?!? ;-) + (see related discussions on sane-ml) + */ + lines_per_buffer = sanei_scsi_max_request_size / bpl / 2; + if (!lines_per_buffer) + return 2; /* resolution is too high */ - /* Limit the size of a single transfer to one inch. - XXX Add a stripsize option. */ - if (lines_per_buffer > s->val[OPT_RESOLUTION].w ) - lines_per_buffer = s->val[OPT_RESOLUTION].w; + /* Limit the size of a single transfer to one inch. + XXX Add a stripsize option. */ + if (lines_per_buffer > s->val[OPT_RESOLUTION].w ) + lines_per_buffer = s->val[OPT_RESOLUTION].w; - DBG(3, "lines_per_buffer=%d, bytes_per_line=%d\n", lines_per_buffer, bpl); + DBG (3, "lines_per_buffer=%d, bytes_per_line=%d\n", lines_per_buffer, bpl); - data = malloc (lines_per_buffer * bpl); + data = malloc (lines_per_buffer * bpl); - for (s->line = 0; s->line < s->params.lines; s->line += lines_per_buffer) { - if (s->line + lines_per_buffer > s->params.lines) - /* do the last few lines: */ - lines_per_buffer = s->params.lines - s->line; + for (s->line = 0; s->line < s->params.lines; s->line += lines_per_buffer) { + if (s->line + lines_per_buffer > s->params.lines) + /* do the last few lines: */ + lines_per_buffer = s->params.lines - s->line; - sigprocmask (SIG_BLOCK, &sigterm_set, 0); - status = read_data (s, data, lines_per_buffer, bpl); - sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); - if (status != SANE_STATUS_GOOD) { - DBG(1, "reader_process: read_data failed with status=%d\n", status); - return 3; - } - DBG(3, "reader_process: read %d lines\n", lines_per_buffer); + sigprocmask (SIG_BLOCK, &sigterm_set, 0); + status = read_data (s, data, lines_per_buffer, bpl); + sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); + if (status != SANE_STATUS_GOOD) { + DBG (1, "reader_process: read_data failed with status=%d\n", status); + return 3; + } + DBG (3, "reader_process: read %d lines\n", lines_per_buffer); - if ((s->mode == TRUECOLOR) || (s->mode == GREYSCALE)) - { - fwrite (data, lines_per_buffer, bpl, fp); - } - else - { - /* in singlebit mode, the scanner returns 1 for black. ;-( --DM */ - int i; + if ((s->mode == TRUECOLOR) || (s->mode == GREYSCALE)) + { + fwrite (data, lines_per_buffer, bpl, fp); + } + else + { + /* in singlebit mode, the scanner returns 1 for black. ;-( --DM */ + int i; - for (i = 0; i < lines_per_buffer * bpl; ++i) - { - fputc (~data[i], fp); - } - } - } - fclose (fp); + for (i = 0; i < lines_per_buffer * bpl; ++i) + { + fputc (~data[i], fp); + } + } + } + fclose (fp); - { - char cmd[] = - {0x17, 0, 0, 0, 0, 0}; - SANE_Status status; + { + char cmd[] = + {0x17, 0, 0, 0, 0, 0}; + SANE_Status status; - status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), NULL, NULL); - if (status != SANE_STATUS_GOOD) - { - DBG (1, "release_unit failed\n" ); - } + status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), NULL, NULL); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "release_unit failed\n"); + } - } + } - return 0; + return 0; } @@ -1213,18 +1368,18 @@ attach_one (const char *dev) SANE_Status -sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) +sane_init (SANE_Int* version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; - DBG(3, "sane_init\n" ); + DBG (3, "sane_init\n"); DBG_INIT(); if (version_code) - *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0); + *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BACKEND_BUILD); fp = sanei_config_open (AVISION_CONFIG_FILE); if (!fp) { @@ -1234,18 +1389,18 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) } while (sanei_config_read (dev_name, sizeof (dev_name), fp) ) - { - if (dev_name[0] == '#') /* ignore line comments */ - continue; - len = strlen (dev_name); - if (dev_name[len - 1] == '\n') - dev_name[--len] = '\0'; + { + if (dev_name[0] == '#') /* ignore line comments */ + continue; + len = strlen (dev_name); + if (dev_name[len - 1] == '\n') + dev_name[--len] = '\0'; - if (!len) - continue; /* ignore empty lines */ + if (!len) + continue; /* ignore empty lines */ - sanei_config_attach_matching_devices (dev_name, attach_one); - } + sanei_config_attach_matching_devices (dev_name, attach_one); + } fclose (fp); return SANE_STATUS_GOOD; } @@ -1256,7 +1411,7 @@ sane_exit (void) { Avision_Device *dev, *next; - DBG(3, "sane_exit\n" ); + DBG (3, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; @@ -1273,7 +1428,7 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) Avision_Device *dev; int i; - DBG(3, "sane_get_devices\n" ); + DBG (3, "sane_get_devices\n"); if (devlist) free (devlist); @@ -1300,7 +1455,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle *handle) Avision_Scanner *s; int i, j; - DBG(3, "sane_open:\n"); + DBG (3, "sane_open:\n"); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) @@ -1323,7 +1478,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle *handle) s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; - memset (s, 0, sizeof (*s)); + memset (s, 0x0, sizeof (*s)); s->fd = -1; s->pipe = -1; s->hw = dev; @@ -1349,8 +1504,8 @@ sane_close (SANE_Handle handle) { Avision_Scanner *prev, *s; - DBG(3, "sane_close\n" ); - DBG(3, " \n" ); + DBG (3, "sane_close\n"); + DBG (3, " \n"); /* remove handle from list of open handles: */ prev = 0; @@ -1361,7 +1516,7 @@ sane_close (SANE_Handle handle) } if (!s) { - DBG(1, "close: invalid handle %p\n", handle); + DBG (1, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } @@ -1382,7 +1537,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Avision_Scanner *s = handle; - DBG(3, "sane_get_option_descriptor\n" ); + DBG (3, "sane_get_option_descriptor\n"); if ((unsigned) option >= NUM_OPTIONS) return 0; @@ -1391,33 +1546,35 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, - SANE_Action action, void *val, SANE_Int *info) + SANE_Action action, void* val, SANE_Int* info) { - Avision_Scanner *s = handle; - SANE_Status status; - SANE_Word cap; + Avision_Scanner* s = handle; + SANE_Status status; + SANE_Word cap; - DBG(3, "sane_control_option\n" ); + DBG (3, "sane_control_option\n"); - if (info) - *info = 0; + if (info) + *info = 0; - if (s->scanning) - return SANE_STATUS_DEVICE_BUSY; + if (s->scanning) + return SANE_STATUS_DEVICE_BUSY; + + if (option >= NUM_OPTIONS) + return SANE_STATUS_INVAL; - if (option >= NUM_OPTIONS) - return SANE_STATUS_INVAL; + cap = s->opt[option].cap; - cap = s->opt[option].cap; + if (!SANE_OPTION_IS_ACTIVE (cap)) + return SANE_STATUS_INVAL; - if (!SANE_OPTION_IS_ACTIVE (cap)) - return SANE_STATUS_INVAL; - - if (action == SANE_ACTION_GET_VALUE) { - switch (option) { - /* word options: */ + if (action == SANE_ACTION_GET_VALUE) + { + switch (option) + { + /* word options: */ case OPT_PREVIEW: - + case OPT_RESOLUTION: case OPT_SPEED: case OPT_TL_X: @@ -1425,380 +1582,387 @@ sane_control_option (SANE_Handle handle, SANE_Int option, case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: - + case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_QSCAN: case OPT_QCALIB: case OPT_TRANS: -#if 0 + case OPT_CUSTOM_GAMMA: -#endif - *(SANE_Word *) val = s->val[option].w; - return SANE_STATUS_GOOD; - -#if 0 - /* word-array options: */ + + *(SANE_Word*) val = s->val[option].w; + return SANE_STATUS_GOOD; + + /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: - memcpy (val, s->val[option].wa, s->opt[option].size); - return SANE_STATUS_GOOD; -#endif - - /* string options: */ + memcpy (val, s->val[option].wa, s->opt[option].size); + return SANE_STATUS_GOOD; + + /* string options: */ case OPT_MODE: - strcpy (val, s->val[option].s); - return SANE_STATUS_GOOD; + strcpy (val, s->val[option].s); + return SANE_STATUS_GOOD; } - } else if (action == SANE_ACTION_SET_VALUE) { - if (!SANE_OPTION_IS_SETTABLE (cap)) - return SANE_STATUS_INVAL; - - status = constrain_value (s, option, val, info); - if (status != SANE_STATUS_GOOD) - return status; - - switch (option) + } + else if (action == SANE_ACTION_SET_VALUE) + { + if (!SANE_OPTION_IS_SETTABLE (cap)) + return SANE_STATUS_INVAL; + + status = constrain_value (s, option, val, info); + if (status != SANE_STATUS_GOOD) + return status; + + switch (option) + { + /* (mostly) side-effect-free word options: */ + case OPT_RESOLUTION: + case OPT_SPEED: + case OPT_TL_X: + case OPT_TL_Y: + case OPT_BR_X: + case OPT_BR_Y: + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + /* fall through */ + case OPT_PREVIEW: + + case OPT_BRIGHTNESS: + case OPT_CONTRAST: + case OPT_THRESHOLD: + + case OPT_QSCAN: + case OPT_QCALIB: + case OPT_TRANS: + s->val[option].w = *(SANE_Word*) val; + return SANE_STATUS_GOOD; + + /* side-effect-free word-array options: */ + case OPT_GAMMA_VECTOR: + case OPT_GAMMA_VECTOR_R: + case OPT_GAMMA_VECTOR_G: + case OPT_GAMMA_VECTOR_B: + memcpy (s->val[option].wa, val, s->opt[option].size); + return SANE_STATUS_GOOD; + + /* options with side-effects: */ + + case OPT_CUSTOM_GAMMA: + s->val[option].w = *(SANE_Word*) val; + if (*(SANE_Word*) val) { - /* (mostly) side-effect-free word options: */ - case OPT_RESOLUTION: - case OPT_SPEED: - case OPT_TL_X: - case OPT_TL_Y: - case OPT_BR_X: - case OPT_BR_Y: - if (info) - *info |= SANE_INFO_RELOAD_PARAMS; - /* fall through */ - case OPT_PREVIEW: - - case OPT_BRIGHTNESS: - case OPT_CONTRAST: - case OPT_THRESHOLD: - - case OPT_QSCAN: - case OPT_QCALIB: - case OPT_TRANS: - s->val[option].w = *(SANE_Word *) val; - return SANE_STATUS_GOOD; - -#if 0 - /* side-effect-free word-array options: */ - case OPT_GAMMA_VECTOR: - case OPT_GAMMA_VECTOR_R: - case OPT_GAMMA_VECTOR_G: - case OPT_GAMMA_VECTOR_B: - memcpy (s->val[option].wa, val, s->opt[option].size); - return SANE_STATUS_GOOD; - - /* options with side-effects: */ - - case OPT_CUSTOM_GAMMA: - w = *(SANE_Word *) val; - if (w == s->val[OPT_CUSTOM_GAMMA].w) - return SANE_STATUS_GOOD; /* no change */ - - s->val[OPT_CUSTOM_GAMMA].w = w; - if (w) { - s->mode = make_mode (s->val[OPT_MODE].s); - - if (s->mode == GREYSCALE) { - s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; - } else if (s->mode == TRUECOLOR) { - s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; - } - } else { - s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; - } - if (info) - *info |= SANE_INFO_RELOAD_OPTIONS; - return SANE_STATUS_GOOD; -#endif - - case OPT_MODE: + s->mode = make_mode (s->val[OPT_MODE].s); + + if (s->mode == GREYSCALE) { - if (s->val[option].s) - free (s->val[option].s); - s->val[option].s = strdup (val); - - s->mode = make_mode (s->val[OPT_MODE].s); - - if (info) - *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; - - s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; -#if 0 - s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; -#endif - - - if (strcmp (val, "Thresholded") == 0) - s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; - else { - s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; - } -#if 0 - if (!binary) - s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; - - if (s->val[OPT_CUSTOM_GAMMA].w) { - if (strcmp (val, "Gray") == 0) - s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; - else if (strcmp (val, "Color") == 0) { - s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; - s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; - } - } -#endif - return SANE_STATUS_GOOD; + s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; + } + else if (s->mode == TRUECOLOR) + { + s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } + else + { + s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; + } + if (info) + *info |= SANE_INFO_RELOAD_OPTIONS; + return SANE_STATUS_GOOD; + + + case OPT_MODE: + { + if (s->val[option].s) + free (s->val[option].s); + s->val[option].s = strdup (val); + + s->mode = make_mode (s->val[OPT_MODE].s); + + if (info) + *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; + + s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; + + s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; + + if (strcmp (val, "Thresholded") == 0) + s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; + else { + s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; + } + + /* if (!binary) */ + s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; + + if (s->val[OPT_CUSTOM_GAMMA].w) { + if (strcmp (val, "Gray") == 0) + s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; + else if (strcmp (val, "Color") == 0) { + s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; + s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; + } + } + + return SANE_STATUS_GOOD; + } + } } - return SANE_STATUS_INVAL; + return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { - Avision_Scanner *s = handle; + Avision_Scanner *s = handle; - DBG(3, "sane_get_parameters\n" ); + DBG (3, "sane_get_parameters\n"); - if (!s->scanning) - { - double tlx,tly,brx,bry,res; - - tlx = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_TL_X].w)/254.0; - tly = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_TL_Y].w)/254.0; - brx = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_BR_X].w)/254.0; - bry = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_BR_Y].w)/254.0; - res = s->val[OPT_RESOLUTION].w; + if (!s->scanning) + { + double tlx,tly,brx,bry,res; + + tlx = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_TL_X].w)/254.0; + tly = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_TL_Y].w)/254.0; + brx = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_BR_X].w)/254.0; + bry = 1200 * 10.0 * SANE_UNFIX(s->val[OPT_BR_Y].w)/254.0; + res = s->val[OPT_RESOLUTION].w; - s->avdimen.tlx = tlx; - s->avdimen.tly = tly; - s->avdimen.brx = brx; - s->avdimen.bry = bry; - s->avdimen.res = res; - s->avdimen.wid = ((s->avdimen.brx-s->avdimen.tlx)/4)*4; - s->avdimen.len = ((s->avdimen.bry-s->avdimen.tly)/4)*4; - s->avdimen.pixelnum = (( s->avdimen.res * s->avdimen.wid ) / 4800)*4; - s->avdimen.linenum = (( s->avdimen.res * s->avdimen.len ) / 4800)*4; + s->avdimen.tlx = tlx; + s->avdimen.tly = tly; + s->avdimen.brx = brx; + s->avdimen.bry = bry; + s->avdimen.res = res; + s->avdimen.wid = ((s->avdimen.brx-s->avdimen.tlx)/4)*4; + s->avdimen.len = ((s->avdimen.bry-s->avdimen.tly)/4)*4; + s->avdimen.pixelnum = (( s->avdimen.res * s->avdimen.wid ) / 4800)*4; + s->avdimen.linenum = (( s->avdimen.res * s->avdimen.len ) / 4800)*4; - if( s->avdimen.tlx == 0 ) - { - s->avdimen.tlx += 4; - s->avdimen.wid -= 4; - } - s->avdimen.tlx = (s->avdimen.tlx/4)*4; + if (s->avdimen.tlx == 0) + { + s->avdimen.tlx += 4; + s->avdimen.wid -= 4; + } + s->avdimen.tlx = (s->avdimen.tlx / 4) * 4; - if( s->avdimen.tly == 0 ) - { - s->avdimen.tly += 4; - } + if (s->avdimen.tly == 0) + { + s->avdimen.tly += 4; + } - s->params.pixels_per_line = s->avdimen.pixelnum; - s->params.lines = s->avdimen.linenum; + s->params.pixels_per_line = s->avdimen.pixelnum; + s->params.lines = s->avdimen.linenum; - memset (&s->params, 0, sizeof (s->params)); + memset (&s->params, 0x0, sizeof (s->params)); - if (s->avdimen.res > 0 && s->avdimen.wid > 0 && s->avdimen.len > 0) - { - s->params.pixels_per_line = s->avdimen.pixelnum; - s->params.lines = s->avdimen.linenum; + if (s->avdimen.res > 0 && s->avdimen.wid > 0 && s->avdimen.len > 0) + { + s->params.pixels_per_line = s->avdimen.pixelnum; + s->params.lines = s->avdimen.linenum; - } - switch (s->mode) - { - case THRESHOLDED: - { - s->params.format = SANE_FRAME_GRAY; - s->avdimen.pixelnum = (s->avdimen.pixelnum / 32) * 32; - s->params.pixels_per_line = s->avdimen.pixelnum; - s->params.bytes_per_line = s->avdimen.pixelnum /8; - s->params.depth = 1; - s->pass=0; - break; - } - case DITHERED: - { - s->params.format = SANE_FRAME_GRAY; - s->avdimen.pixelnum = (s->avdimen.pixelnum / 32) * 32; - s->params.pixels_per_line = s->avdimen.pixelnum; - s->params.bytes_per_line = s->avdimen.pixelnum /8; - s->params.depth = 1; - s->pass=0; - break; - } - case GREYSCALE: - { - s->params.format = SANE_FRAME_GRAY; - s->params.bytes_per_line = s->avdimen.pixelnum; - s->params.pixels_per_line = s->avdimen.pixelnum; - s->params.depth = 8; - s->pass=0; - break; - } - case TRUECOLOR: - { - s->params.format = SANE_FRAME_RGB; - s->params.bytes_per_line = s->avdimen.pixelnum * 3; - s->params.pixels_per_line = s->avdimen.pixelnum; - s->params.depth = 8; - s->pass=0; - break; - } - } - } + } + switch (s->mode) + { + case THRESHOLDED: + { + s->params.format = SANE_FRAME_GRAY; + s->avdimen.pixelnum = (s->avdimen.pixelnum / 32) * 32; + s->params.pixels_per_line = s->avdimen.pixelnum; + s->params.bytes_per_line = s->avdimen.pixelnum /8; + s->params.depth = 1; + s->pass=0; + break; + } + case DITHERED: + { + s->params.format = SANE_FRAME_GRAY; + s->avdimen.pixelnum = (s->avdimen.pixelnum / 32) * 32; + s->params.pixels_per_line = s->avdimen.pixelnum; + s->params.bytes_per_line = s->avdimen.pixelnum /8; + s->params.depth = 1; + s->pass=0; + break; + } + case GREYSCALE: + { + s->params.format = SANE_FRAME_GRAY; + s->params.bytes_per_line = s->avdimen.pixelnum; + s->params.pixels_per_line = s->avdimen.pixelnum; + s->params.depth = 8; + s->pass=0; + break; + } + case TRUECOLOR: + { + s->params.format = SANE_FRAME_RGB; + s->params.bytes_per_line = s->avdimen.pixelnum * 3; + s->params.pixels_per_line = s->avdimen.pixelnum; + s->params.depth = 8; + s->pass=0; + break; + } + } + } - s->params.last_frame = SANE_TRUE; + s->params.last_frame = SANE_TRUE; - if (params) - { - *params = s->params; - } + if (params) + { + *params = s->params; + } - s->pass=0; - return SANE_STATUS_GOOD; + s->pass=0; + return SANE_STATUS_GOOD; } - + SANE_Status sane_start (SANE_Handle handle) { - Avision_Scanner *s = handle; - SANE_Status status; - int fds[2]; - - - DBG(3, "sane_start\n" ); - - /* Fisrt make sure there is no scan running!!! */ - - if (s->scanning) - return SANE_STATUS_DEVICE_BUSY; - - /* Second make sure we have a current parameter set. Some of the - parameters will be overwritten below, but that's OK. */ - status = sane_get_parameters (s, 0); - - if (status != SANE_STATUS_GOOD) - { - return status; - } - - if (s->fd < 0) - { - status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); - if (status != SANE_STATUS_GOOD) - { - DBG(1, "open: open of %s failed: %s\n", - s->hw->sane.name, sane_strstatus (status)); - return status; - } - } - - { /*MCC*/ - char cmd[] = - {0x16, 0, 0, 0, 0, 0}; - SANE_Status status; - - status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), NULL, NULL); - if (status != SANE_STATUS_GOOD) - { - DBG (1, "reserve_unit failed\n" ); - } - } - - status = wait_ready (s->fd); - if (status != SANE_STATUS_GOOD) - { - DBG(1, "open: wait_ready() failed: %s\n", sane_strstatus (status)); - goto stop_scanner_and_return; - } + Avision_Scanner* s = handle; + SANE_Status status; + int fds [2]; - status = scan_area_and_windows (s); - if (status != SANE_STATUS_GOOD) - { - DBG(1, "open: set scan area command failed: %s\n", - sane_strstatus (status)); - goto stop_scanner_and_return; - } + DBG (3, "sane_start\n"); - s->scanning = SANE_TRUE; + /* Fisrt make sure there is no scan running!!! */ + + if (s->scanning) + return SANE_STATUS_DEVICE_BUSY; - status = start_scan (s); - if (status != SANE_STATUS_GOOD) - { - goto stop_scanner_and_return; - } + /* Second make sure we have a current parameter set. Some of the + parameters will be overwritten below, but that's OK. */ + status = sane_get_parameters (s, 0); - s->line = 0; + if (status != SANE_STATUS_GOOD) + { + return status; + } - if (pipe (fds) < 0) - { - return SANE_STATUS_IO_ERROR; - } - - s->reader_pid = fork (); - if (s->reader_pid == 0) - { - sigset_t ignore_set; - struct SIGACTION act; + if (s->fd < 0) + { + status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "open: open of %s failed: %s\n", + s->hw->sane.name, sane_strstatus (status)); + return status; + } + } + + { /*MCC*/ + char cmd[] = + {0x16, 0, 0, 0, 0, 0}; + SANE_Status status; - close (fds[0]); - - sigfillset (&ignore_set); - sigdelset (&ignore_set, SIGTERM); - sigprocmask (SIG_SETMASK, &ignore_set, 0); - - memset (&act, 0, sizeof (act)); - sigaction (SIGTERM, &act, 0); - - /* don't use exit() since that would run the atexit() handlers... */ - _exit (reader_process (s, fds[1])); - } - close (fds[1]); - s->pipe = fds[0]; + status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), NULL, NULL); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "reserve_unit failed\n"); + } + } + + status = wait_ready (s->fd); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "open: wait_ready() failed: %s\n", sane_strstatus (status)); + goto stop_scanner_and_return; + } + + + status = set_window (s); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "open: set scan area command failed: %s\n", + sane_strstatus (status)); + goto stop_scanner_and_return; + } + + status = set_gamma (s); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "open: set gamma failed: %s\n", + sane_strstatus (status)); + goto stop_scanner_and_return; + } + + s->scanning = SANE_TRUE; - return SANE_STATUS_GOOD; + status = start_scan (s); + if (status != SANE_STATUS_GOOD) + { + goto stop_scanner_and_return; + } -stop_scanner_and_return: - do_cancel (s); - return status; + s->line = 0; + + if (pipe (fds) < 0) + { + return SANE_STATUS_IO_ERROR; + } + + s->reader_pid = fork (); + if (s->reader_pid == 0) + { + sigset_t ignore_set; + struct SIGACTION act; + + close (fds [0] ); + + sigfillset (&ignore_set); + sigdelset (&ignore_set, SIGTERM); + sigprocmask (SIG_SETMASK, &ignore_set, 0); + + memset (&act, 0x0, sizeof (act)); + sigaction (SIGTERM, &act, 0); + + /* don't use exit() since that would run the atexit() handlers... */ + _exit (reader_process (s, fds[1] ) ); + } + close (fds [1 ]); + s->pipe = fds [0]; + + return SANE_STATUS_GOOD; + + stop_scanner_and_return: + do_cancel (s); + return status; } SANE_Status -sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) +sane_read (SANE_Handle handle, SANE_Byte* buf, SANE_Int max_len, SANE_Int* len) { - Avision_Scanner *s = handle; + Avision_Scanner* s = handle; ssize_t nread; - DBG(3, "sane_read\n" ); + DBG (3, "sane_read\n"); *len = 0; nread = read (s->pipe, buf, max_len); - DBG(3, "sane_read:read %ld bytes\n", (long) nread); + DBG (3, "sane_read:read %ld bytes\n", (long) nread); if (!s->scanning) return do_cancel (s); @@ -1825,9 +1989,9 @@ sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) void sane_cancel (SANE_Handle handle) { - Avision_Scanner *s = handle; + Avision_Scanner* s = handle; - DBG(3, "sane_cancel\n" ); + DBG (3, "sane_cancel\n"); if (s->reader_pid > 0) kill (s->reader_pid, SIGTERM); @@ -1838,15 +2002,15 @@ sane_cancel (SANE_Handle handle) SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { - Avision_Scanner *s = handle; - - DBG(3, "sane_set_io_mode\n" ); + Avision_Scanner* s = handle; + + DBG (3, "sane_set_io_mode\n"); if (!s->scanning) return SANE_STATUS_INVAL; - + if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; - + return SANE_STATUS_GOOD; } @@ -1854,9 +2018,9 @@ sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { - Avision_Scanner *s = handle; + Avision_Scanner *s = handle; - DBG(3, "sane_get_select_fd\n" ); + DBG (3, "sane_get_select_fd\n"); if (!s->scanning) return SANE_STATUS_INVAL; diff --git a/backend/avision.h b/backend/avision.h index d4768936e..5cd8d53c5 100644 --- a/backend/avision.h +++ b/backend/avision.h @@ -41,14 +41,14 @@ ***************************************************************************** - This file implements a SANE backend for the Avision AV 630CS scanner with - SCSI-2 command set. + This file implements a SANE backend for the Avision AV 630CS (and other ...) + scanner with SCSI-2 command set. (feedback to: mccramer@s.netic.de and rene.rebe@myokay.net) Very much thanks to: Avision INC for the documentation we got! ;-) - Gunter Wagner for some fixes and the transparency option + Gunter Wagner for some fixes and the transparency option. *****************************************************************************/ @@ -57,108 +57,101 @@ #include - enum Avision_Option { - OPT_NUM_OPTS = 0, - - OPT_MODE_GROUP, - OPT_MODE, + OPT_NUM_OPTS = 0, /* must come first */ + + OPT_MODE_GROUP, + OPT_MODE, #define OPT_MODE_DEFAULT 3 - OPT_RESOLUTION, + OPT_RESOLUTION, #define OPT_RESOLUTION_DEFAULT 300 - OPT_SPEED, - OPT_PREVIEW, - - OPT_GEOMETRY_GROUP, - OPT_TL_X, /* top-left x */ - OPT_TL_Y, /* top-left y */ - OPT_BR_X, /* bottom-right x */ - OPT_BR_Y, /* bottom-right y */ - - OPT_ENHANCEMENT_GROUP, - OPT_BRIGHTNESS, - OPT_CONTRAST, - OPT_THRESHOLD, - OPT_QSCAN, - OPT_QCALIB, - OPT_TRANS, /* Transparency Mode */ -#if 0 - OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ - /* The gamma vectors MUST appear in the order gray, red, green, - blue. */ - OPT_GAMMA_VECTOR, - OPT_GAMMA_VECTOR_R, - OPT_GAMMA_VECTOR_G, - OPT_GAMMA_VECTOR_B, - - OPT_HALFTONE_DIMENSION, - OPT_HALFTONE_PATTERN, -#endif - - /* must come last: */ - NUM_OPTIONS + OPT_SPEED, + OPT_PREVIEW, + + OPT_GEOMETRY_GROUP, + OPT_TL_X, /* top-left x */ + OPT_TL_Y, /* top-left y */ + OPT_BR_X, /* bottom-right x */ + OPT_BR_Y, /* bottom-right y */ + + OPT_ENHANCEMENT_GROUP, + OPT_BRIGHTNESS, + OPT_CONTRAST, + OPT_THRESHOLD, + OPT_QSCAN, + OPT_QCALIB, + OPT_TRANS, /* Transparency Mode */ + + OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ + + OPT_GAMMA_VECTOR, /* first must be grey */ + OPT_GAMMA_VECTOR_R, /* then r g b vector */ + OPT_GAMMA_VECTOR_G, + OPT_GAMMA_VECTOR_B, + + NUM_OPTIONS /* must come last */ }; typedef union { - SANE_Word w; - SANE_Word *wa; /* word array */ - SANE_String s; + SANE_Word w; + SANE_Word *wa; /* word array */ + SANE_String s; } Option_Value; -typedef struct Avision_Dimensions +typedef struct { - long tlx; - long tly; - long brx; - long bry; - long wid; - long len; - long pixelnum; - long linenum; - int resx; - int rexy; - int res; + long tlx; + long tly; + long brx; + long bry; + long wid; + long len; + long pixelnum; + long linenum; + int resx; + int rexy; + int res; } Avision_Dimensions; -typedef struct Avision_Device +typedef struct { - struct Avision_Device *next; - SANE_Device sane; - SANE_Range dpi_range; - SANE_Range x_range; - SANE_Range y_range; - SANE_Range speed_range; - unsigned flags; + struct Avision_Device* next; + SANE_Device sane; + SANE_Range dpi_range; + SANE_Range x_range; + SANE_Range y_range; + SANE_Range speed_range; + unsigned flags; } Avision_Device; -typedef struct Avision_Scanner +typedef struct { - /* all the state needed to define a scan request: */ - struct Avision_Scanner *next; - - SANE_Option_Descriptor opt[NUM_OPTIONS]; - Option_Value val[NUM_OPTIONS]; - SANE_Int gamma_table[4][256]; - - int scanning; - int pass; /* pass number */ - int line; /* current line number */ - SANE_Parameters params; - - /* Parsed option values and variables that are valid only during - actual scanning: */ - int mode; - Avision_Dimensions avdimen; /* Used for internal calculationg */ - - int fd; /* SCSI filedescriptor */ - pid_t reader_pid; /* process id of reader */ - int pipe; /* pipe to reader process */ - - /* scanner dependent/low-level state: */ - Avision_Device *hw; + /* all the state needed to define a scan request: */ + struct Avision_Scanner *next; + + SANE_Option_Descriptor opt [NUM_OPTIONS]; + Option_Value val [NUM_OPTIONS]; + SANE_Int gamma_table [4][256]; + + int scanning; + int pass; /* pass number */ + int line; /* current line number */ + SANE_Parameters params; + + /* Parsed option values and variables that are valid only during + actual scanning: */ + int mode; + Avision_Dimensions avdimen; /* Used for internal calculationg */ + + int fd; /* SCSI filedescriptor */ + pid_t reader_pid; /* process id of reader */ + int pipe; /* pipe to reader process */ + + /* scanner dependent/low-level state: */ + Avision_Device *hw; } Avision_Scanner; #define AV_ADF_ON 0x80 @@ -265,105 +258,119 @@ typedef struct Avision_Scanner #define AVISION_SCSI_INQUIRY 0x12 #define AVISION_SCSI_MODE_SELECT 0x15 #define AVISION_SCSI_START_STOP 0x1b -#define AVISION_SCSI_AREA_AND_WINDOWS 0x24 -#define AVISION_SCSI_READ_SCANNED_DATA 0x28 +#define AVISION_SCSI_SET_WINDOWS 0x24 +#define AVISION_SCSI_READ 0x28 +#define AVISION_SCSI_SEND 0x2a #define AVISION_SCSI_GET_DATA_STATUS 0x34 -/* The structures that you have to send to the avision to get it to +/* The structures that you have to send to an avision to get it to do various stuff... */ -struct win_desc_header { - unsigned char pad0[6]; - unsigned char wpll[2]; -}; - -struct win_desc_block { - unsigned char winid; - unsigned char pad0; - unsigned char xres[2]; - unsigned char yres[2]; - unsigned char ulx[4]; - unsigned char uly[4]; - unsigned char width[4]; - unsigned char length[4]; - unsigned char brightness; - unsigned char thresh; - unsigned char contrast; - unsigned char image_comp; - unsigned char bpp; - unsigned char halftone[2]; - unsigned char pad_type; - unsigned char bitordering[2]; - unsigned char compr_type; - unsigned char compr_arg; - unsigned char pad4[6]; - unsigned char vendor_specid; - unsigned char paralen; - unsigned char bitset1; - unsigned char highlight; - unsigned char shadow; - unsigned char linewidth[2]; - unsigned char linecount[2]; - unsigned char bitset2; - unsigned char pad5; -#if 1 - unsigned char r_exposure_time[2]; - unsigned char g_exposure_time[2]; - unsigned char b_exposure_time[2]; -#endif - -}; - -struct command_header { +struct command_header +{ unsigned char opc; - unsigned char pad0[3]; + unsigned char pad0 [3]; unsigned char len; unsigned char pad1; }; -struct command_header_10 { - unsigned char opc; - unsigned char pad0[5]; - unsigned char len[3]; - unsigned char pad1; +struct command_set_window +{ + unsigned char opc; + unsigned char reserved0 [5]; + unsigned char transferlen [3]; + unsigned char control; }; -struct command_read { - unsigned char opc; - unsigned char bitset1; - unsigned char datatypecode; - unsigned char calibchn; - unsigned char datatypequal[2]; - unsigned char transferlen[3]; - unsigned char pad0; +struct command_read +{ + unsigned char opc; + unsigned char bitset1; + unsigned char datatypecode; + unsigned char calibchn; + unsigned char datatypequal [2]; + unsigned char transferlen [3]; + unsigned char control; }; -struct command_scan { - unsigned char opc; - unsigned char pad0[3]; - unsigned char transferlen; - unsigned char bitset1; +struct command_scan +{ + unsigned char opc; + unsigned char pad0 [3]; + unsigned char transferlen; + unsigned char bitset1; }; -struct def_win_par { - struct command_header_10 dwph; - struct win_desc_header wdh; - struct win_desc_block wdb; +struct command_send +{ + unsigned char opc; + unsigned char bitset1; + unsigned char datatypecode; + unsigned char reserved0; + unsigned char datatypequal [2]; + unsigned char transferlen [3]; + unsigned char reserved1; }; -struct page_header{ - char pad0[4]; - char code; - char length; + +struct command_set_window_window_header +{ + unsigned char reserved0 [6]; + unsigned char desclen [2]; }; -struct avision_page { - char gamma; - char thresh; - char masks; - char delay; - char features; - char pad0; +struct command_set_window_window_descriptor +{ + unsigned char winid; + unsigned char pad0; + unsigned char xres [2]; + unsigned char yres [2]; + unsigned char ulx [4]; + unsigned char uly [4]; + unsigned char width [4]; + unsigned char length [4]; + unsigned char brightness; + unsigned char thresh; + unsigned char contrast; + unsigned char image_comp; + unsigned char bpp; + unsigned char halftone [2]; + unsigned char pad_type; + unsigned char bitordering [2]; + unsigned char compr_type; + unsigned char compr_arg; + unsigned char pad4 [6]; + unsigned char vendor_specid; + unsigned char paralen; + unsigned char bitset1; + unsigned char highlight; + unsigned char shadow; + unsigned char linewidth [2]; + unsigned char linecount [2]; + unsigned char bitset2; + unsigned char pad5; +#if 1 + unsigned char r_exposure_time [2]; + unsigned char g_exposure_time [2]; + unsigned char b_exposure_time [2]; +#endif +}; + +struct page_header +{ + char pad0 [4]; + char code; + char length; +}; + +struct avision_page +{ + char gamma; + char thresh; + char masks; + char delay; + char features; + char pad0; };