1141cc406Sopenharmony_ci/*************************************************************************** 2141cc406Sopenharmony_ci * SANE - Scanner Access Now Easy. 3141cc406Sopenharmony_ci 4141cc406Sopenharmony_ci microtek.c 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file Copyright 2002 Matthew Marjanovic 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This file is part of the SANE package. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 11141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 12141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 13141cc406Sopenharmony_ci License, or (at your option) any later version. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 16141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 17141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18141cc406Sopenharmony_ci General Public License for more details. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 21141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 24141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 27141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 28141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 29141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 30141cc406Sopenharmony_ci account of linking the SANE library code into it. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 33141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 34141cc406Sopenharmony_ci License. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 37141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 38141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 41141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 42141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci *************************************************************************** 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci This file implements a SANE backend for Microtek scanners. 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci (feedback to: mtek-bugs@mir.com) 49141cc406Sopenharmony_ci (for latest info: http://www.mir.com/mtek/) 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci ***************************************************************************/ 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci 54141cc406Sopenharmony_ci#define MICROTEK_MAJOR 0 55141cc406Sopenharmony_ci#define MICROTEK_MINOR 13 56141cc406Sopenharmony_ci#define MICROTEK_PATCH 1 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#include "../include/sane/config.h" 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#include <stdarg.h> 61141cc406Sopenharmony_ci#include <stdlib.h> 62141cc406Sopenharmony_ci#include <string.h> 63141cc406Sopenharmony_ci#include <unistd.h> 64141cc406Sopenharmony_ci#include <fcntl.h> 65141cc406Sopenharmony_ci#include <math.h> 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci#include "../include/_stdint.h" 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#include "../include/sane/sane.h" 70141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 71141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 73141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci#define BACKEND_NAME microtek 76141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#include "microtek.h" 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci#define MICROTEK_CONFIG_FILE "microtek.conf" 82141cc406Sopenharmony_ci 83141cc406Sopenharmony_ci#ifndef PATH_MAX 84141cc406Sopenharmony_ci# define PATH_MAX 1024 85141cc406Sopenharmony_ci#endif 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci#define SCSI_BUFF_SIZE sanei_scsi_max_request_size 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci 91141cc406Sopenharmony_ci#define MIN(a,b) (((a) < (b)) ? (a) : (b)) 92141cc406Sopenharmony_ci#define MAX(a,b) (((a) > (b)) ? (a) : (b)) 93141cc406Sopenharmony_ci 94141cc406Sopenharmony_cistatic int num_devices = 0; 95141cc406Sopenharmony_cistatic Microtek_Device *first_dev = NULL; /* list of known devices */ 96141cc406Sopenharmony_cistatic Microtek_Scanner *first_handle = NULL; /* list of open scanners */ 97141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; /* sane_get_devices() */ 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci 100141cc406Sopenharmony_cistatic SANE_Bool inhibit_clever_precal = SANE_FALSE; 101141cc406Sopenharmony_cistatic SANE_Bool inhibit_real_calib = SANE_FALSE; 102141cc406Sopenharmony_ci 103141cc406Sopenharmony_ci 104141cc406Sopenharmony_ci#define M_GSS_WAIT 5 /* seconds */ 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci#define M_LINEART SANE_VALUE_SCAN_MODE_LINEART 107141cc406Sopenharmony_ci#define M_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE 108141cc406Sopenharmony_ci#define M_GRAY SANE_VALUE_SCAN_MODE_GRAY 109141cc406Sopenharmony_ci#define M_COLOR SANE_VALUE_SCAN_MODE_COLOR 110141cc406Sopenharmony_ci 111141cc406Sopenharmony_ci#define M_OPAQUE "Opaque/Normal" 112141cc406Sopenharmony_ci#define M_TRANS "Transparency" 113141cc406Sopenharmony_ci#define M_AUTOFEED "AutoFeeder" 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci#define M_NONE "None" 116141cc406Sopenharmony_ci#define M_SCALAR "Scalar" 117141cc406Sopenharmony_ci#define M_TABLE "Table" 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_cistatic SANE_String_Const gamma_mode_list[4] = { 120141cc406Sopenharmony_ci M_NONE, 121141cc406Sopenharmony_ci M_SCALAR, 122141cc406Sopenharmony_ci M_TABLE, 123141cc406Sopenharmony_ci NULL 124141cc406Sopenharmony_ci}; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci/* These are for the E6. Does this hold for other models? */ 128141cc406Sopenharmony_cistatic SANE_String_Const halftone_mode_list[13] = { 129141cc406Sopenharmony_ci " 1 53-dot screen (53 gray levels)", 130141cc406Sopenharmony_ci " 2 Horiz. screen (65 gray levels)", 131141cc406Sopenharmony_ci " 3 Vert. screen (65 gray levels)", 132141cc406Sopenharmony_ci " 4 Mixed page (33 gray levels)", 133141cc406Sopenharmony_ci " 5 71-dot screen (29 gray levels)", 134141cc406Sopenharmony_ci " 6 60-dot #1 (26 gray levels)", 135141cc406Sopenharmony_ci " 7 60-dot #2 (26 gray levels)", 136141cc406Sopenharmony_ci " 8 Fine detail #1 (17 gray levels)", 137141cc406Sopenharmony_ci " 9 Fine detail #2 (17 gray levels)", 138141cc406Sopenharmony_ci "10 Slant line (17 gray levels)", 139141cc406Sopenharmony_ci "11 Posterizing (10 gray levels)", 140141cc406Sopenharmony_ci "12 High Contrast (5 gray levels)", 141141cc406Sopenharmony_ci NULL 142141cc406Sopenharmony_ci}; 143141cc406Sopenharmony_ci 144141cc406Sopenharmony_ci 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_cistatic SANE_Range speed_range = {1, 7, 1}; 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_cistatic SANE_Range brightness_range = {-100, 100, 1}; 149141cc406Sopenharmony_ci/*static SANE_Range brightness_range = {0, 255, 1};*/ 150141cc406Sopenharmony_ci/*static SANE_Range exposure_range = {-18, 21, 3};*/ 151141cc406Sopenharmony_ci/*static SANE_Range contrast_range = {-42, 49, 7};*/ 152141cc406Sopenharmony_cistatic SANE_Range u8_range = {0, 255, 1}; 153141cc406Sopenharmony_cistatic SANE_Range analog_gamma_range = 154141cc406Sopenharmony_ci{ SANE_FIX(0.1), SANE_FIX(4.0), SANE_FIX(0) }; 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_ci#define MAX_MDBG_LENGTH 1024 160141cc406Sopenharmony_cistatic char _mdebug_string[MAX_MDBG_LENGTH]; 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_cistatic void MDBG_INIT(const char *format, ...) 163141cc406Sopenharmony_ci{ 164141cc406Sopenharmony_ci va_list ap; 165141cc406Sopenharmony_ci va_start(ap, format); 166141cc406Sopenharmony_ci vsnprintf(_mdebug_string, MAX_MDBG_LENGTH, format, ap); 167141cc406Sopenharmony_ci va_end(ap); 168141cc406Sopenharmony_ci} 169141cc406Sopenharmony_ci 170141cc406Sopenharmony_cistatic void MDBG_ADD(const char *format, ...) 171141cc406Sopenharmony_ci{ 172141cc406Sopenharmony_ci int len = strlen(_mdebug_string); 173141cc406Sopenharmony_ci va_list ap; 174141cc406Sopenharmony_ci va_start(ap, format); 175141cc406Sopenharmony_ci vsnprintf(_mdebug_string+len, MAX_MDBG_LENGTH-len, format, ap); 176141cc406Sopenharmony_ci va_end(ap); 177141cc406Sopenharmony_ci} 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_cistatic void MDBG_FINISH(int dbglvl) 180141cc406Sopenharmony_ci{ 181141cc406Sopenharmony_ci DBG(dbglvl, "%s\n", _mdebug_string); 182141cc406Sopenharmony_ci} 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci 186141cc406Sopenharmony_ci/********************************************************************/ 187141cc406Sopenharmony_ci/********************************************************************/ 188141cc406Sopenharmony_ci/*** Utility Functions **********************************************/ 189141cc406Sopenharmony_ci/********************************************************************/ 190141cc406Sopenharmony_ci/********************************************************************/ 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_cistatic size_t max_string_size (const SANE_String_Const strings[]) 193141cc406Sopenharmony_ci{ 194141cc406Sopenharmony_ci size_t size, max_size = 0; 195141cc406Sopenharmony_ci int i; 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) { 198141cc406Sopenharmony_ci size = strlen(strings[i]) + 1; 199141cc406Sopenharmony_ci if (size > max_size) max_size = size; 200141cc406Sopenharmony_ci } 201141cc406Sopenharmony_ci return max_size; 202141cc406Sopenharmony_ci} 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci/********************************************************************/ 207141cc406Sopenharmony_ci/* Allocate/create a new ring buffer */ 208141cc406Sopenharmony_ci/********************************************************************/ 209141cc406Sopenharmony_cistatic ring_buffer * 210141cc406Sopenharmony_ciring_alloc (size_t initial_size, size_t bpl, size_t ppl) 211141cc406Sopenharmony_ci{ 212141cc406Sopenharmony_ci ring_buffer *rb; 213141cc406Sopenharmony_ci uint8_t *buff; 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_ci if ((rb = (ring_buffer *)malloc(sizeof(*rb))) == NULL) 216141cc406Sopenharmony_ci return NULL; 217141cc406Sopenharmony_ci if ((buff = (uint8_t *)malloc(initial_size * sizeof(*buff))) == NULL) { 218141cc406Sopenharmony_ci free(rb); 219141cc406Sopenharmony_ci return NULL; 220141cc406Sopenharmony_ci } 221141cc406Sopenharmony_ci rb->base = buff; 222141cc406Sopenharmony_ci rb->size = initial_size; 223141cc406Sopenharmony_ci rb->initial_size = initial_size; 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci rb->bpl = bpl; 226141cc406Sopenharmony_ci rb->ppl = ppl; 227141cc406Sopenharmony_ci 228141cc406Sopenharmony_ci rb->tail_red = 0; 229141cc406Sopenharmony_ci rb->tail_green = 1; 230141cc406Sopenharmony_ci rb->tail_blue = 2; 231141cc406Sopenharmony_ci rb->head_complete = 0; 232141cc406Sopenharmony_ci 233141cc406Sopenharmony_ci rb->red_extra = 0; 234141cc406Sopenharmony_ci rb->green_extra = 0; 235141cc406Sopenharmony_ci rb->blue_extra = 0; 236141cc406Sopenharmony_ci rb->complete_count = 0; 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci return rb; 239141cc406Sopenharmony_ci} 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci/********************************************************************/ 243141cc406Sopenharmony_ci/* Enlarge an existing ring buffer */ 244141cc406Sopenharmony_ci/********************************************************************/ 245141cc406Sopenharmony_cistatic SANE_Status 246141cc406Sopenharmony_ciring_expand (ring_buffer *rb, size_t amount) 247141cc406Sopenharmony_ci{ 248141cc406Sopenharmony_ci uint8_t *buff; 249141cc406Sopenharmony_ci size_t oldsize; 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci if (rb == NULL) return SANE_STATUS_INVAL; 252141cc406Sopenharmony_ci buff = (uint8_t *)realloc(rb->base, (rb->size + amount) * sizeof(*buff)); 253141cc406Sopenharmony_ci if (buff == NULL) return SANE_STATUS_NO_MEM; 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci rb->base = buff; 256141cc406Sopenharmony_ci oldsize = rb->size; 257141cc406Sopenharmony_ci rb->size += amount; 258141cc406Sopenharmony_ci 259141cc406Sopenharmony_ci DBG(23, "ring_expand: old, new, inc size: %lu, %lu, %lu\n", 260141cc406Sopenharmony_ci (u_long)oldsize, (u_long)rb->size, (u_long)amount); 261141cc406Sopenharmony_ci DBG(23, "ring_expand: old tr: %lu tg: %lu tb: %lu hc: %lu\n", 262141cc406Sopenharmony_ci (u_long)rb->tail_red, (u_long)rb->tail_green, 263141cc406Sopenharmony_ci (u_long)rb->tail_blue, (u_long)rb->head_complete); 264141cc406Sopenharmony_ci /* if necessary, move data and fix up them pointers */ 265141cc406Sopenharmony_ci /* (will break subtly if ring is filled with G or B bytes, 266141cc406Sopenharmony_ci and tail_g or tail_b have rolled over...) */ 267141cc406Sopenharmony_ci if (((rb->complete_count) || 268141cc406Sopenharmony_ci (rb->red_extra) || 269141cc406Sopenharmony_ci (rb->green_extra) || 270141cc406Sopenharmony_ci (rb->blue_extra)) && ((rb->tail_red <= rb->head_complete) || 271141cc406Sopenharmony_ci (rb->tail_green <= rb->head_complete) || 272141cc406Sopenharmony_ci (rb->tail_blue <= rb->head_complete))) { 273141cc406Sopenharmony_ci memmove(rb->base + rb->head_complete + amount, 274141cc406Sopenharmony_ci rb->base + rb->head_complete, 275141cc406Sopenharmony_ci oldsize - rb->head_complete); 276141cc406Sopenharmony_ci if ((rb->tail_red > rb->head_complete) || 277141cc406Sopenharmony_ci ((rb->tail_red == rb->head_complete) && 278141cc406Sopenharmony_ci !(rb->complete_count) && !(rb->red_extra))) 279141cc406Sopenharmony_ci rb->tail_red += amount; 280141cc406Sopenharmony_ci if ((rb->tail_green > rb->head_complete) || 281141cc406Sopenharmony_ci ((rb->tail_green == rb->head_complete) && 282141cc406Sopenharmony_ci !(rb->complete_count) && !(rb->green_extra))) 283141cc406Sopenharmony_ci rb->tail_green += amount; 284141cc406Sopenharmony_ci if ((rb->tail_blue > rb->head_complete) || 285141cc406Sopenharmony_ci ((rb->tail_blue == rb->head_complete) && 286141cc406Sopenharmony_ci !(rb->complete_count) && !(rb->blue_extra))) 287141cc406Sopenharmony_ci rb->tail_blue += amount; 288141cc406Sopenharmony_ci rb->head_complete += amount; 289141cc406Sopenharmony_ci } 290141cc406Sopenharmony_ci DBG(23, "ring_expand: new tr: %lu tg: %lu tb: %lu hc: %lu\n", 291141cc406Sopenharmony_ci (u_long)rb->tail_red, (u_long)rb->tail_green, 292141cc406Sopenharmony_ci (u_long)rb->tail_blue, (u_long)rb->head_complete); 293141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 294141cc406Sopenharmony_ci} 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ci/********************************************************************/ 298141cc406Sopenharmony_ci/* Deallocate a ring buffer */ 299141cc406Sopenharmony_ci/********************************************************************/ 300141cc406Sopenharmony_cistatic void 301141cc406Sopenharmony_ciring_free (ring_buffer *rb) 302141cc406Sopenharmony_ci{ 303141cc406Sopenharmony_ci free(rb->base); 304141cc406Sopenharmony_ci free(rb); 305141cc406Sopenharmony_ci} 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_ci/********************************************************************/ 310141cc406Sopenharmony_ci/********************************************************************/ 311141cc406Sopenharmony_ci/*** Basic SCSI Commands ********************************************/ 312141cc406Sopenharmony_ci/********************************************************************/ 313141cc406Sopenharmony_ci/********************************************************************/ 314141cc406Sopenharmony_ci 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_ci/********************************************************************/ 317141cc406Sopenharmony_ci/* parse sense from scsi error */ 318141cc406Sopenharmony_ci/* (even though microtek sense codes are non-standard and */ 319141cc406Sopenharmony_ci/* typically misinterpreted/munged by the low-level scsi driver) */ 320141cc406Sopenharmony_ci/********************************************************************/ 321141cc406Sopenharmony_cistatic SANE_Status 322141cc406Sopenharmony_cisense_handler (int scsi_fd, u_char *sense, void *arg) 323141cc406Sopenharmony_ci{ 324141cc406Sopenharmony_ci int *sense_flags = (int *)arg; 325141cc406Sopenharmony_ci SANE_Status stat; 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci DBG(10, "SENSE! fd = %d\n", scsi_fd); 328141cc406Sopenharmony_ci DBG(10, "sense = %02x %02x %02x %02x.\n", 329141cc406Sopenharmony_ci sense[0], sense[1], sense[2], sense[3]); 330141cc406Sopenharmony_ci switch(sense[0]) { 331141cc406Sopenharmony_ci case 0x00: 332141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 333141cc406Sopenharmony_ci case 0x81: /* COMMAND/DATA ERROR */ 334141cc406Sopenharmony_ci stat = SANE_STATUS_GOOD; 335141cc406Sopenharmony_ci if (sense[1] & 0x01) { 336141cc406Sopenharmony_ci if ((sense_flags != NULL) && (*sense_flags & MS_SENSE_IGNORE)) 337141cc406Sopenharmony_ci DBG(10, "sense: ERR_SCSICMD -- ignored\n"); 338141cc406Sopenharmony_ci else { 339141cc406Sopenharmony_ci DBG(10, "sense: ERR_SCSICMD\n"); 340141cc406Sopenharmony_ci stat = SANE_STATUS_IO_ERROR; 341141cc406Sopenharmony_ci } 342141cc406Sopenharmony_ci } 343141cc406Sopenharmony_ci if (sense[1] & 0x02) { 344141cc406Sopenharmony_ci DBG(10, "sense: ERR_TOOMANY\n"); 345141cc406Sopenharmony_ci stat = SANE_STATUS_IO_ERROR; 346141cc406Sopenharmony_ci } 347141cc406Sopenharmony_ci return stat; 348141cc406Sopenharmony_ci case 0x82 : /* SCANNER HARDWARE ERROR */ 349141cc406Sopenharmony_ci if (sense[1] & 0x01) DBG(10, "sense: ERR_CPURAMFAIL\n"); 350141cc406Sopenharmony_ci if (sense[1] & 0x02) DBG(10, "sense: ERR_SYSRAMFAIL\n"); 351141cc406Sopenharmony_ci if (sense[1] & 0x04) DBG(10, "sense: ERR_IMGRAMFAIL\n"); 352141cc406Sopenharmony_ci if (sense[1] & 0x10) DBG(10, "sense: ERR_CALIBRATE\n"); 353141cc406Sopenharmony_ci if (sense[1] & 0x20) DBG(10, "sense: ERR_LAMPFAIL\n"); 354141cc406Sopenharmony_ci if (sense[1] & 0x40) DBG(10, "sense: ERR_MOTORFAIL\n"); 355141cc406Sopenharmony_ci if (sense[1] & 0x80) DBG(10, "sense: ERR_FEEDERFAIL\n"); 356141cc406Sopenharmony_ci if (sense[2] & 0x01) DBG(10, "sense: ERR_POWERFAIL\n"); 357141cc406Sopenharmony_ci if (sense[2] & 0x02) DBG(10, "sense: ERR_ILAMPFAIL\n"); 358141cc406Sopenharmony_ci if (sense[2] & 0x04) DBG(10, "sense: ERR_IMOTORFAIL\n"); 359141cc406Sopenharmony_ci if (sense[2] & 0x08) DBG(10, "sense: ERR_PAPERFAIL\n"); 360141cc406Sopenharmony_ci if (sense[2] & 0x10) DBG(10, "sense: ERR_FILTERFAIL\n"); 361141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 362141cc406Sopenharmony_ci case 0x83 : /* OPERATION ERROR */ 363141cc406Sopenharmony_ci if (sense[1] & 0x01) DBG(10, "sense: ERR_ILLGRAIN\n"); 364141cc406Sopenharmony_ci if (sense[1] & 0x02) DBG(10, "sense: ERR_ILLRES\n"); 365141cc406Sopenharmony_ci if (sense[1] & 0x04) DBG(10, "sense: ERR_ILLCOORD\n"); 366141cc406Sopenharmony_ci if (sense[1] & 0x10) DBG(10, "sense: ERR_ILLCNTR\n"); 367141cc406Sopenharmony_ci if (sense[1] & 0x20) DBG(10, "sense: ERR_ILLLENGTH\n"); 368141cc406Sopenharmony_ci if (sense[1] & 0x40) DBG(10, "sense: ERR_ILLADJUST\n"); 369141cc406Sopenharmony_ci if (sense[1] & 0x80) DBG(10, "sense: ERR_ILLEXPOSE\n"); 370141cc406Sopenharmony_ci if (sense[2] & 0x01) DBG(10, "sense: ERR_ILLFILTER\n"); 371141cc406Sopenharmony_ci if (sense[2] & 0x02) DBG(10, "sense: ERR_NOPAPER\n"); 372141cc406Sopenharmony_ci if (sense[2] & 0x04) DBG(10, "sense: ERR_ILLTABLE\n"); 373141cc406Sopenharmony_ci if (sense[2] & 0x08) DBG(10, "sense: ERR_ILLOFFSET\n"); 374141cc406Sopenharmony_ci if (sense[2] & 0x10) DBG(10, "sense: ERR_ILLBPP\n"); 375141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 376141cc406Sopenharmony_ci default : 377141cc406Sopenharmony_ci DBG(10, "sense: unknown error\n"); 378141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 379141cc406Sopenharmony_ci } 380141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 381141cc406Sopenharmony_ci} 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci 385141cc406Sopenharmony_ci/********************************************************************/ 386141cc406Sopenharmony_ci/* wait (via polling) until scanner seems "ready" */ 387141cc406Sopenharmony_ci/********************************************************************/ 388141cc406Sopenharmony_cistatic SANE_Status 389141cc406Sopenharmony_ciwait_ready(Microtek_Scanner *ms) 390141cc406Sopenharmony_ci{ 391141cc406Sopenharmony_ci uint8_t comm[6] = { 0, 0, 0, 0, 0, 0 }; 392141cc406Sopenharmony_ci SANE_Status status; 393141cc406Sopenharmony_ci int retry = 0; 394141cc406Sopenharmony_ci 395141cc406Sopenharmony_ci DBG(23, ".wait_ready %d...\n", ms->sfd); 396141cc406Sopenharmony_ci while ((status = sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0)) 397141cc406Sopenharmony_ci != SANE_STATUS_GOOD) { 398141cc406Sopenharmony_ci DBG(23, "wait_ready failed (%d)\n", retry); 399141cc406Sopenharmony_ci if (retry > 5) return SANE_STATUS_IO_ERROR; /* XXXXXXXX */ 400141cc406Sopenharmony_ci retry++; 401141cc406Sopenharmony_ci sleep(3); 402141cc406Sopenharmony_ci } 403141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 404141cc406Sopenharmony_ci} 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci/********************************************************************/ 408141cc406Sopenharmony_ci/* send scan region coordinates */ 409141cc406Sopenharmony_ci/********************************************************************/ 410141cc406Sopenharmony_cistatic SANE_Status 411141cc406Sopenharmony_ciscanning_frame(Microtek_Scanner *ms) 412141cc406Sopenharmony_ci{ 413141cc406Sopenharmony_ci uint8_t *data, comm[15] = { 0x04, 0, 0, 0, 0x09, 0 }; 414141cc406Sopenharmony_ci int x1, y1, x2, y2; 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci DBG(23, ".scanning_frame...\n"); 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci x1 = ms->x1; 419141cc406Sopenharmony_ci x2 = ms->x2; 420141cc406Sopenharmony_ci y1 = ms->y1; 421141cc406Sopenharmony_ci y2 = ms->y2; 422141cc406Sopenharmony_ci /* E6 weirdness (other models too?) */ 423141cc406Sopenharmony_ci if (ms->unit_type == MS_UNIT_18INCH) { 424141cc406Sopenharmony_ci x1 /= 2; 425141cc406Sopenharmony_ci x2 /= 2; 426141cc406Sopenharmony_ci y1 /= 2; 427141cc406Sopenharmony_ci y2 /= 2; 428141cc406Sopenharmony_ci } 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci DBG(23, ".scanning_frame: in- %d,%d %d,%d\n", 431141cc406Sopenharmony_ci ms->x1, ms->y1, ms->x2, ms->y2); 432141cc406Sopenharmony_ci DBG(23, ".scanning_frame: out- %d,%d %d,%d\n", x1, y1, x2, y2); 433141cc406Sopenharmony_ci data = comm + 6; 434141cc406Sopenharmony_ci data[0] = 435141cc406Sopenharmony_ci ((ms->unit_type == MS_UNIT_PIXELS) ? 0x08 : 0 ) | 436141cc406Sopenharmony_ci ((ms->mode == MS_MODE_HALFTONE) ? 0x01 : 0 ); 437141cc406Sopenharmony_ci data[1] = x1 & 0xFF; 438141cc406Sopenharmony_ci data[2] = (x1 >> 8) & 0xFF; 439141cc406Sopenharmony_ci data[3] = y1 & 0xFF; 440141cc406Sopenharmony_ci data[4] = (y1 >> 8) & 0xFF; 441141cc406Sopenharmony_ci data[5] = x2 & 0xFF; 442141cc406Sopenharmony_ci data[6] = (x2 >> 8) & 0xFF; 443141cc406Sopenharmony_ci data[7] = y2 & 0xFF; 444141cc406Sopenharmony_ci data[8] = (y2 >> 8) & 0xFF; 445141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 446141cc406Sopenharmony_ci int i; 447141cc406Sopenharmony_ci#if 0 448141cc406Sopenharmony_ci fprintf(stderr, "SF: "); 449141cc406Sopenharmony_ci for (i=0;i<6+0x09;i++) fprintf(stderr, "%2x ", comm[i]); 450141cc406Sopenharmony_ci fprintf(stderr, "\n"); 451141cc406Sopenharmony_ci#endif 452141cc406Sopenharmony_ci MDBG_INIT("SF: "); 453141cc406Sopenharmony_ci for (i=0;i<6+0x09;i++) MDBG_ADD("%2x ", comm[i]); 454141cc406Sopenharmony_ci MDBG_FINISH(192); 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x09, 0, 0); 457141cc406Sopenharmony_ci} 458141cc406Sopenharmony_ci 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci/********************************************************************/ 462141cc406Sopenharmony_ci/* send "mode_select" */ 463141cc406Sopenharmony_ci/********************************************************************/ 464141cc406Sopenharmony_cistatic SANE_Status 465141cc406Sopenharmony_cimode_select(Microtek_Scanner *ms) 466141cc406Sopenharmony_ci{ 467141cc406Sopenharmony_ci uint8_t *data, comm[19] = { 0x15, 0, 0, 0, 0, 0 }; 468141cc406Sopenharmony_ci 469141cc406Sopenharmony_ci DBG(23, ".mode_select %d...\n", ms->sfd); 470141cc406Sopenharmony_ci data = comm + 6; 471141cc406Sopenharmony_ci data[0] = 472141cc406Sopenharmony_ci 0x81 | 473141cc406Sopenharmony_ci ((ms->unit_type == MS_UNIT_18INCH) ? 0 : 0x08) | 474141cc406Sopenharmony_ci ((ms->res_type == MS_RES_5PER) ? 0 : 0x02); 475141cc406Sopenharmony_ci data[1] = ms->resolution_code; 476141cc406Sopenharmony_ci data[2] = ms->exposure; 477141cc406Sopenharmony_ci data[3] = ms->contrast; 478141cc406Sopenharmony_ci data[4] = ms->pattern; 479141cc406Sopenharmony_ci data[5] = ms->velocity; 480141cc406Sopenharmony_ci data[6] = ms->shadow; 481141cc406Sopenharmony_ci data[7] = ms->highlight; 482141cc406Sopenharmony_ci DBG(23, ".mode_select: pap_len: %d\n", ms->paper_length); 483141cc406Sopenharmony_ci data[8] = ms->paper_length & 0xFF; 484141cc406Sopenharmony_ci data[9] = (ms->paper_length >> 8) & 0xFF; 485141cc406Sopenharmony_ci data[10] = ms->midtone; 486141cc406Sopenharmony_ci /* set command/data length */ 487141cc406Sopenharmony_ci comm[4] = (ms->midtone_support) ? 0x0B : 0x0A; 488141cc406Sopenharmony_ci 489141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 490141cc406Sopenharmony_ci int i; 491141cc406Sopenharmony_ci#if 0 492141cc406Sopenharmony_ci fprintf(stderr, "MSL: "); 493141cc406Sopenharmony_ci for (i=0;i<6+comm[4];i++) fprintf(stderr, "%2x ", comm[i]); 494141cc406Sopenharmony_ci fprintf(stderr, "\n"); 495141cc406Sopenharmony_ci#endif 496141cc406Sopenharmony_ci MDBG_INIT("MSL: "); 497141cc406Sopenharmony_ci for (i=0;i<6+comm[4];i++) MDBG_ADD("%2x ", comm[i]); 498141cc406Sopenharmony_ci MDBG_FINISH(192); 499141cc406Sopenharmony_ci } 500141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6 + comm[4], 0, 0); 501141cc406Sopenharmony_ci} 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci 505141cc406Sopenharmony_ci/********************************************************************/ 506141cc406Sopenharmony_ci/* send "mode_select_1" */ 507141cc406Sopenharmony_ci/********************************************************************/ 508141cc406Sopenharmony_cistatic SANE_Status 509141cc406Sopenharmony_cimode_select_1(Microtek_Scanner *ms) 510141cc406Sopenharmony_ci{ 511141cc406Sopenharmony_ci uint8_t *data, comm[16] = { 0x16, 0, 0, 0, 0x0A, 0, 512141cc406Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci DBG(23, ".mode_select_1 %d...\n", ms->sfd); 515141cc406Sopenharmony_ci data = comm + 6; 516141cc406Sopenharmony_ci data[1] = ms->bright_r; 517141cc406Sopenharmony_ci data[3] = ((ms->allow_calibrate) ? 0 : 0x02); /* | 0x01; */ 518141cc406Sopenharmony_ci 519141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 520141cc406Sopenharmony_ci int i; 521141cc406Sopenharmony_ci#if 0 522141cc406Sopenharmony_ci fprintf(stderr, "MSL1: "); 523141cc406Sopenharmony_ci for (i=0;i<6+0x0A;i++) fprintf(stderr, "%2x ", comm[i]); 524141cc406Sopenharmony_ci fprintf(stderr, "\n"); 525141cc406Sopenharmony_ci#endif 526141cc406Sopenharmony_ci MDBG_INIT("MSL1: "); 527141cc406Sopenharmony_ci for (i=0;i<6+0x0A;i++) MDBG_ADD("%2x ", comm[i]); 528141cc406Sopenharmony_ci MDBG_FINISH(192); 529141cc406Sopenharmony_ci } 530141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x0A, 0, 0); 531141cc406Sopenharmony_ci} 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci/********************************************************************/ 536141cc406Sopenharmony_ci/* record mode_sense results in the mode_sense buffer */ 537141cc406Sopenharmony_ci/* (this is to tell if something catastrophic has happened */ 538141cc406Sopenharmony_ci/* to the scanner in-between scans) */ 539141cc406Sopenharmony_ci/********************************************************************/ 540141cc406Sopenharmony_cistatic SANE_Status 541141cc406Sopenharmony_cisave_mode_sense(Microtek_Scanner *ms) 542141cc406Sopenharmony_ci{ 543141cc406Sopenharmony_ci uint8_t data[20], comm[6] = { 0x1A, 0, 0, 0, 0, 0}; 544141cc406Sopenharmony_ci size_t lenp; 545141cc406Sopenharmony_ci SANE_Status status; 546141cc406Sopenharmony_ci int i; 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci DBG(23, ".save_mode_sense %d...\n", ms->sfd); 549141cc406Sopenharmony_ci if (ms->onepass) comm[4] = 0x13; 550141cc406Sopenharmony_ci else if (ms->midtone_support) comm[4] = 0x0B; 551141cc406Sopenharmony_ci else comm[4] = 0x0A; 552141cc406Sopenharmony_ci lenp = comm[4]; 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp); 555141cc406Sopenharmony_ci for (i=0; i<10; i++) ms->mode_sense_cache[i] = data[i]; 556141cc406Sopenharmony_ci 557141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 558141cc406Sopenharmony_ci unsigned int i; 559141cc406Sopenharmony_ci#if 0 560141cc406Sopenharmony_ci fprintf(stderr, "SMS: "); 561141cc406Sopenharmony_ci for (i=0;i<lenp;i++) fprintf(stderr, "%2x ", data[i]); 562141cc406Sopenharmony_ci fprintf(stderr, "\n"); 563141cc406Sopenharmony_ci#endif 564141cc406Sopenharmony_ci MDBG_INIT("SMS: "); 565141cc406Sopenharmony_ci for (i=0;i<lenp;i++) MDBG_ADD("%2x ", data[i]); 566141cc406Sopenharmony_ci MDBG_FINISH(192); 567141cc406Sopenharmony_ci } 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci return status; 570141cc406Sopenharmony_ci} 571141cc406Sopenharmony_ci 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci/********************************************************************/ 574141cc406Sopenharmony_ci/* read mode_sense and compare to what we saved before */ 575141cc406Sopenharmony_ci/********************************************************************/ 576141cc406Sopenharmony_cistatic SANE_Status 577141cc406Sopenharmony_cicompare_mode_sense(Microtek_Scanner *ms, int *match) 578141cc406Sopenharmony_ci{ 579141cc406Sopenharmony_ci uint8_t data[20], comm[6] = { 0x1A, 0, 0, 0, 0, 0}; 580141cc406Sopenharmony_ci size_t lenp; 581141cc406Sopenharmony_ci SANE_Status status; 582141cc406Sopenharmony_ci int i; 583141cc406Sopenharmony_ci 584141cc406Sopenharmony_ci DBG(23, ".compare_mode_sense %d...\n", ms->sfd); 585141cc406Sopenharmony_ci if (ms->onepass) comm[4] = 0x13; 586141cc406Sopenharmony_ci else if (ms->midtone_support) comm[4] = 0x0B; 587141cc406Sopenharmony_ci else comm[4] = 0x0A; 588141cc406Sopenharmony_ci lenp = comm[4]; 589141cc406Sopenharmony_ci 590141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp); 591141cc406Sopenharmony_ci *match = 1; 592141cc406Sopenharmony_ci for (i=0; i<10; i++) 593141cc406Sopenharmony_ci *match = *match && (ms->mode_sense_cache[i] == data[i]); 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 596141cc406Sopenharmony_ci unsigned int i; 597141cc406Sopenharmony_ci#if 0 598141cc406Sopenharmony_ci fprintf(stderr, "CMS: "); 599141cc406Sopenharmony_ci for (i=0;i<lenp;i++) fprintf(stderr, "%2x(%2x) ", 600141cc406Sopenharmony_ci data[i], 601141cc406Sopenharmony_ci ms->mode_sense_cache[i]); 602141cc406Sopenharmony_ci fprintf(stderr, "\n"); 603141cc406Sopenharmony_ci#endif 604141cc406Sopenharmony_ci MDBG_INIT("CMS: "); 605141cc406Sopenharmony_ci for (i=0;i<lenp;i++) MDBG_ADD("%2x(%2x) ", 606141cc406Sopenharmony_ci data[i], 607141cc406Sopenharmony_ci ms->mode_sense_cache[i]); 608141cc406Sopenharmony_ci MDBG_FINISH(192); 609141cc406Sopenharmony_ci } 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci return status; 612141cc406Sopenharmony_ci} 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ci/********************************************************************/ 615141cc406Sopenharmony_ci/* send mode_sense_1, and upset every scsi driver known to mankind */ 616141cc406Sopenharmony_ci/********************************************************************/ 617141cc406Sopenharmony_ci#if 0 618141cc406Sopenharmony_cistatic SANE_Status 619141cc406Sopenharmony_cimode_sense_1(Microtek_Scanner *ms) 620141cc406Sopenharmony_ci{ 621141cc406Sopenharmony_ci uint8_t *data, comm[36] = { 0x19, 0, 0, 0, 0x1E, 0 }; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci DBG(23, ".mode_sense_1...\n"); 624141cc406Sopenharmony_ci data = comm + 6; 625141cc406Sopenharmony_ci memset(data, 0, 30); 626141cc406Sopenharmony_ci data[1] = ms->bright_r; 627141cc406Sopenharmony_ci data[2] = ms->bright_g; 628141cc406Sopenharmony_ci data[3] = ms->bright_b; 629141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 630141cc406Sopenharmony_ci int i; 631141cc406Sopenharmony_ci fprintf(stderr, "MS1: "); 632141cc406Sopenharmony_ci for (i=0;i<6+0x1E;i++) fprintf(stderr, "%2x ", comm[i]); 633141cc406Sopenharmony_ci fprintf(stderr, "\n"); 634141cc406Sopenharmony_ci } 635141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x1E, 0, 0); 636141cc406Sopenharmony_ci} 637141cc406Sopenharmony_ci#endif 638141cc406Sopenharmony_ci 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci 641141cc406Sopenharmony_ci/********************************************************************/ 642141cc406Sopenharmony_ci/* send "accessory" command */ 643141cc406Sopenharmony_ci/********************************************************************/ 644141cc406Sopenharmony_cistatic SANE_Status 645141cc406Sopenharmony_ciaccessory(Microtek_Scanner *ms) 646141cc406Sopenharmony_ci{ 647141cc406Sopenharmony_ci uint8_t comm[6] = { 0x10, 0, 0, 0, 0, 0 }; 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci DBG(23, ".accessory...\n"); 650141cc406Sopenharmony_ci comm[4] = 651141cc406Sopenharmony_ci ((ms->useADF) ? 0x41 : 0x40) | 652141cc406Sopenharmony_ci ((ms->prescan) ? 0x18 : 0x10) | 653141cc406Sopenharmony_ci ((ms->transparency) ? 0x24 : 0x20) | 654141cc406Sopenharmony_ci ((ms->allowbacktrack) ? 0x82 : 0x80); 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 657141cc406Sopenharmony_ci int i; 658141cc406Sopenharmony_ci#if 0 659141cc406Sopenharmony_ci fprintf(stderr, "AC: "); 660141cc406Sopenharmony_ci for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]); 661141cc406Sopenharmony_ci fprintf(stderr, "\n"); 662141cc406Sopenharmony_ci#endif 663141cc406Sopenharmony_ci MDBG_INIT("AC: "); 664141cc406Sopenharmony_ci for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]); 665141cc406Sopenharmony_ci MDBG_FINISH(192); 666141cc406Sopenharmony_ci } 667141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0); 668141cc406Sopenharmony_ci} 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci 672141cc406Sopenharmony_ci/********************************************************************/ 673141cc406Sopenharmony_ci/* start the scanner a-scannin' */ 674141cc406Sopenharmony_ci/********************************************************************/ 675141cc406Sopenharmony_cistatic SANE_Status 676141cc406Sopenharmony_cistart_scan(Microtek_Scanner *ms) 677141cc406Sopenharmony_ci{ 678141cc406Sopenharmony_ci uint8_t comm[6] = { 0x1B, 0, 0, 0, 0, 0 }; 679141cc406Sopenharmony_ci 680141cc406Sopenharmony_ci DBG(23, ".start_scan...\n"); 681141cc406Sopenharmony_ci comm[4] = 682141cc406Sopenharmony_ci 0x01 | /* "start" */ 683141cc406Sopenharmony_ci ((ms->expandedresolution) ? 0x80 : 0) | 684141cc406Sopenharmony_ci ((ms->multibit) ? 0x40 : 0) | 685141cc406Sopenharmony_ci ((ms->onepasscolor) ? 0x20 : 0) | 686141cc406Sopenharmony_ci ((ms->reversecolors) ? 0x04 : 0) | 687141cc406Sopenharmony_ci ((ms->fastprescan) ? 0x02 : 0) | 688141cc406Sopenharmony_ci ((ms->filter == MS_FILT_RED) ? 0x08 : 0) | 689141cc406Sopenharmony_ci ((ms->filter == MS_FILT_GREEN) ? 0x10 : 0) | 690141cc406Sopenharmony_ci ((ms->filter == MS_FILT_BLUE) ? 0x18 : 0) ; 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 693141cc406Sopenharmony_ci int i; 694141cc406Sopenharmony_ci#if 0 695141cc406Sopenharmony_ci fprintf(stderr, "SS: "); 696141cc406Sopenharmony_ci for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]); 697141cc406Sopenharmony_ci fprintf(stderr, "\n"); 698141cc406Sopenharmony_ci#endif 699141cc406Sopenharmony_ci MDBG_INIT("SS: "); 700141cc406Sopenharmony_ci for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]); 701141cc406Sopenharmony_ci MDBG_FINISH(192); 702141cc406Sopenharmony_ci } 703141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0); 704141cc406Sopenharmony_ci} 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci/********************************************************************/ 709141cc406Sopenharmony_ci/* stop the scanner a-scannin' */ 710141cc406Sopenharmony_ci/********************************************************************/ 711141cc406Sopenharmony_cistatic SANE_Status 712141cc406Sopenharmony_cistop_scan(Microtek_Scanner *ms) 713141cc406Sopenharmony_ci{ 714141cc406Sopenharmony_ci uint8_t comm[6] = { 0x1B, 0, 0, 0, 0, 0 }; 715141cc406Sopenharmony_ci 716141cc406Sopenharmony_ci DBG(23, ".stop_scan...\n"); 717141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 718141cc406Sopenharmony_ci int i; 719141cc406Sopenharmony_ci#if 0 720141cc406Sopenharmony_ci fprintf(stderr, "SPS:"); 721141cc406Sopenharmony_ci for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]); 722141cc406Sopenharmony_ci fprintf(stderr, "\n"); 723141cc406Sopenharmony_ci#endif 724141cc406Sopenharmony_ci MDBG_INIT("SPS:"); 725141cc406Sopenharmony_ci for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]); 726141cc406Sopenharmony_ci MDBG_FINISH(192); 727141cc406Sopenharmony_ci } 728141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0); 729141cc406Sopenharmony_ci} 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci/********************************************************************/ 734141cc406Sopenharmony_ci/* get scan status */ 735141cc406Sopenharmony_ci/********************************************************************/ 736141cc406Sopenharmony_cistatic SANE_Status 737141cc406Sopenharmony_ciget_scan_status(Microtek_Scanner *ms, 738141cc406Sopenharmony_ci SANE_Int *busy, 739141cc406Sopenharmony_ci SANE_Int *bytes_per_line, 740141cc406Sopenharmony_ci SANE_Int *lines) 741141cc406Sopenharmony_ci{ 742141cc406Sopenharmony_ci uint8_t data[6], comm[6] = { 0x0F, 0, 0, 0, 0x06, 0 }; 743141cc406Sopenharmony_ci SANE_Status status; 744141cc406Sopenharmony_ci size_t lenp; 745141cc406Sopenharmony_ci int retry = 0; 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci DBG(23, ".get_scan_status %d...\n", ms->sfd); 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci do { 750141cc406Sopenharmony_ci lenp = 6; 751141cc406Sopenharmony_ci /* do some retry stuff in here, too */ 752141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp); 753141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 754141cc406Sopenharmony_ci DBG(20, "get_scan_status: scsi error\n"); 755141cc406Sopenharmony_ci return status; 756141cc406Sopenharmony_ci } 757141cc406Sopenharmony_ci *busy = data[0]; 758141cc406Sopenharmony_ci *bytes_per_line = (data[1]) + (data[2] << 8); 759141cc406Sopenharmony_ci *lines = (data[3]) + (data[4] << 8) + (data[5] << 16); 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci DBG(20, "get_scan_status(%lu): %d, %d, %d -> #%d\n", 762141cc406Sopenharmony_ci (u_long) lenp, *busy, *bytes_per_line, *lines, retry); 763141cc406Sopenharmony_ci DBG(20, "> %2x %2x %2x %2x %2x %2x\n", 764141cc406Sopenharmony_ci data[0], data[1], data[2], data[3], data[4], data[5]); 765141cc406Sopenharmony_ci if (*busy != 0) { 766141cc406Sopenharmony_ci retry++; 767141cc406Sopenharmony_ci DBG(23, "get_scan_status: busy, retry in %d...\n", 768141cc406Sopenharmony_ci M_GSS_WAIT * retry); 769141cc406Sopenharmony_ci sleep(M_GSS_WAIT * retry); 770141cc406Sopenharmony_ci } 771141cc406Sopenharmony_ci } while ((*busy != 0) && (retry < 4)); 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci if (*busy == 0) return status; 774141cc406Sopenharmony_ci else return SANE_STATUS_IO_ERROR; 775141cc406Sopenharmony_ci} 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci/********************************************************************/ 780141cc406Sopenharmony_ci/* get scanlines from scanner */ 781141cc406Sopenharmony_ci/********************************************************************/ 782141cc406Sopenharmony_cistatic SANE_Status 783141cc406Sopenharmony_ciread_scan_data(Microtek_Scanner *ms, 784141cc406Sopenharmony_ci int lines, 785141cc406Sopenharmony_ci uint8_t *buffer, 786141cc406Sopenharmony_ci size_t *bufsize) 787141cc406Sopenharmony_ci{ 788141cc406Sopenharmony_ci uint8_t comm[6] = { 0x08, 0, 0, 0, 0, 0 }; 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci DBG(23, ".read_scan_data...\n"); 791141cc406Sopenharmony_ci comm[2] = (lines >> 16) & 0xFF; 792141cc406Sopenharmony_ci comm[3] = (lines >> 8) & 0xFF; 793141cc406Sopenharmony_ci comm[4] = (lines) & 0xFF; 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6, buffer, bufsize); 796141cc406Sopenharmony_ci} 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci 800141cc406Sopenharmony_ci/********************************************************************/ 801141cc406Sopenharmony_ci/* download color LUT to scanner (if it takes one) */ 802141cc406Sopenharmony_ci/********************************************************************/ 803141cc406Sopenharmony_cistatic SANE_Status 804141cc406Sopenharmony_cidownload_gamma(Microtek_Scanner *ms) 805141cc406Sopenharmony_ci{ 806141cc406Sopenharmony_ci uint8_t *data, *comm; /* commbytes[10] = { 0x55, 0, 0x27, 0, 0, 807141cc406Sopenharmony_ci 0, 0, 0, 0, 0 };*/ 808141cc406Sopenharmony_ci int i, pl; 809141cc406Sopenharmony_ci int commsize; 810141cc406Sopenharmony_ci int bit_depth = 8; /* hard-code for now, should match bpp XXXXXXX */ 811141cc406Sopenharmony_ci int max_entry; 812141cc406Sopenharmony_ci SANE_Status status; 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci DBG(23, ".download_gamma...\n"); 815141cc406Sopenharmony_ci /* skip if scanner doesn't take 'em */ 816141cc406Sopenharmony_ci if (!(ms->gamma_entries)) { 817141cc406Sopenharmony_ci DBG(23, ".download_gamma: no entries; skipping\n"); 818141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 819141cc406Sopenharmony_ci } 820141cc406Sopenharmony_ci if ((ms->gamma_entry_size != 1) && (ms->gamma_entry_size != 2)) { 821141cc406Sopenharmony_ci DBG(23, ".download_gamma: entry size %d?!?!?\n", ms->gamma_entry_size); 822141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* XXXXXXXxx */ 823141cc406Sopenharmony_ci } 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci max_entry = (1 << bit_depth) - 1; 826141cc406Sopenharmony_ci 827141cc406Sopenharmony_ci DBG(23, ".download_gamma: %d entries of %d bytes, max %d\n", 828141cc406Sopenharmony_ci ms->gamma_entries, ms->gamma_entry_size, max_entry); 829141cc406Sopenharmony_ci commsize = 10 + (ms->gamma_entries * ms->gamma_entry_size); 830141cc406Sopenharmony_ci comm = calloc(commsize, sizeof(uint8_t)); 831141cc406Sopenharmony_ci if (comm == NULL) { 832141cc406Sopenharmony_ci DBG(23, ".download_gamma: couldn't allocate %d bytes for comm buffer!\n", 833141cc406Sopenharmony_ci commsize); 834141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 835141cc406Sopenharmony_ci } 836141cc406Sopenharmony_ci data = comm + 10; 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci comm[0] = 0x55; 839141cc406Sopenharmony_ci comm[1] = 0; 840141cc406Sopenharmony_ci comm[2] = 0x27; 841141cc406Sopenharmony_ci comm[3] = 0; 842141cc406Sopenharmony_ci comm[4] = 0; 843141cc406Sopenharmony_ci comm[5] = 0; 844141cc406Sopenharmony_ci comm[6] = 0; 845141cc406Sopenharmony_ci comm[7] = ((ms->gamma_entries * ms->gamma_entry_size) >> 8) & 0xFF; 846141cc406Sopenharmony_ci comm[8] = (ms->gamma_entries * ms->gamma_entry_size) & 0xFF; 847141cc406Sopenharmony_ci comm[9] = (ms->gamma_entry_size == 2) ? 1 : 0; 848141cc406Sopenharmony_ci 849141cc406Sopenharmony_ci if (!(strcmp(ms->val[OPT_CUSTOM_GAMMA].s, M_TABLE))) { 850141cc406Sopenharmony_ci /***** Gamma by TABLE *****/ 851141cc406Sopenharmony_ci int table_shift = (ms->gamma_bit_depth - bit_depth); 852141cc406Sopenharmony_ci 853141cc406Sopenharmony_ci DBG(23, ".download_gamma: by table (%d bpe, %d shift)\n", 854141cc406Sopenharmony_ci ms->gamma_bit_depth, table_shift); 855141cc406Sopenharmony_ci 856141cc406Sopenharmony_ci if (ms->val[OPT_GAMMA_BIND].w == SANE_TRUE) { 857141cc406Sopenharmony_ci for (i=0; i<ms->gamma_entries; i++) { 858141cc406Sopenharmony_ci int val = ms->gray_lut[i] >> table_shift; 859141cc406Sopenharmony_ci switch (ms->gamma_entry_size) { 860141cc406Sopenharmony_ci case 1: 861141cc406Sopenharmony_ci data[i] = (uint8_t) val; 862141cc406Sopenharmony_ci break; 863141cc406Sopenharmony_ci case 2: 864141cc406Sopenharmony_ci data[i*2] = val & 0xFF; 865141cc406Sopenharmony_ci data[(i*2)+1] = (val>>8) & 0xFF; 866141cc406Sopenharmony_ci break; 867141cc406Sopenharmony_ci } 868141cc406Sopenharmony_ci } 869141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); 870141cc406Sopenharmony_ci } else { 871141cc406Sopenharmony_ci pl = 1; 872141cc406Sopenharmony_ci do { 873141cc406Sopenharmony_ci SANE_Int *pl_lut; 874141cc406Sopenharmony_ci switch (pl) { 875141cc406Sopenharmony_ci case 1: pl_lut = ms->red_lut; break; 876141cc406Sopenharmony_ci case 2: pl_lut = ms->green_lut; break; 877141cc406Sopenharmony_ci case 3: pl_lut = ms->blue_lut; break; 878141cc406Sopenharmony_ci default: 879141cc406Sopenharmony_ci DBG(23, ".download_gamma: uh, exceeded pl bound!\n"); 880141cc406Sopenharmony_ci free(comm); 881141cc406Sopenharmony_ci return SANE_STATUS_INVAL; /* XXXXXXXxx */ 882141cc406Sopenharmony_ci break; 883141cc406Sopenharmony_ci } 884141cc406Sopenharmony_ci for (i=0; i<ms->gamma_entries; i++) { 885141cc406Sopenharmony_ci int val = pl_lut[i] >> table_shift; 886141cc406Sopenharmony_ci switch (ms->gamma_entry_size) { 887141cc406Sopenharmony_ci case 1: 888141cc406Sopenharmony_ci data[i] = (uint8_t) val; 889141cc406Sopenharmony_ci break; 890141cc406Sopenharmony_ci case 2: 891141cc406Sopenharmony_ci data[i*2] = val & 0xFF; 892141cc406Sopenharmony_ci data[(i*2)+1] = (val>>8) & 0xFF; 893141cc406Sopenharmony_ci break; 894141cc406Sopenharmony_ci } 895141cc406Sopenharmony_ci } 896141cc406Sopenharmony_ci /* XXXXXXX */ 897141cc406Sopenharmony_ci comm[9] = (comm[9] & 0x3F) | (pl << 6); 898141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); 899141cc406Sopenharmony_ci pl++; 900141cc406Sopenharmony_ci } while ((pl < 4) && (status == SANE_STATUS_GOOD)); 901141cc406Sopenharmony_ci } 902141cc406Sopenharmony_ci } else if (!(strcmp(ms->val[OPT_CUSTOM_GAMMA].s, M_SCALAR))) { 903141cc406Sopenharmony_ci /***** Gamma by SCALAR *****/ 904141cc406Sopenharmony_ci DBG(23, ".download_gamma: by scalar\n"); 905141cc406Sopenharmony_ci if (ms->val[OPT_GAMMA_BIND].w == SANE_TRUE) { 906141cc406Sopenharmony_ci double gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA].w); 907141cc406Sopenharmony_ci for (i=0; i<ms->gamma_entries; i++) { 908141cc406Sopenharmony_ci int val = (max_entry * 909141cc406Sopenharmony_ci pow((double) i / ((double) ms->gamma_entries - 1.0), 910141cc406Sopenharmony_ci 1.0 / gamma)); 911141cc406Sopenharmony_ci switch (ms->gamma_entry_size) { 912141cc406Sopenharmony_ci case 1: 913141cc406Sopenharmony_ci data[i] = (uint8_t) val; 914141cc406Sopenharmony_ci break; 915141cc406Sopenharmony_ci case 2: 916141cc406Sopenharmony_ci data[i*2] = val & 0xFF; 917141cc406Sopenharmony_ci data[(i*2)+1] = (val>>8) & 0xFF; 918141cc406Sopenharmony_ci break; 919141cc406Sopenharmony_ci } 920141cc406Sopenharmony_ci } 921141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); 922141cc406Sopenharmony_ci } else { 923141cc406Sopenharmony_ci double gamma; 924141cc406Sopenharmony_ci pl = 1; 925141cc406Sopenharmony_ci do { 926141cc406Sopenharmony_ci switch (pl) { 927141cc406Sopenharmony_ci case 1: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_R].w); break; 928141cc406Sopenharmony_ci case 2: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_G].w); break; 929141cc406Sopenharmony_ci case 3: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_B].w); break; 930141cc406Sopenharmony_ci default: gamma = 1.0; break; /* should never happen */ 931141cc406Sopenharmony_ci } 932141cc406Sopenharmony_ci for (i=0; i<ms->gamma_entries; i++) { 933141cc406Sopenharmony_ci int val = (max_entry * 934141cc406Sopenharmony_ci pow((double) i / ((double) ms->gamma_entries - 1.0), 935141cc406Sopenharmony_ci 1.0 / gamma)); 936141cc406Sopenharmony_ci switch (ms->gamma_entry_size) { 937141cc406Sopenharmony_ci case 1: 938141cc406Sopenharmony_ci data[i] = (uint8_t) val; 939141cc406Sopenharmony_ci break; 940141cc406Sopenharmony_ci case 2: 941141cc406Sopenharmony_ci data[i*2] = val & 0xFF; 942141cc406Sopenharmony_ci data[(i*2)+1] = (val>>8) & 0xFF; 943141cc406Sopenharmony_ci break; 944141cc406Sopenharmony_ci } 945141cc406Sopenharmony_ci } 946141cc406Sopenharmony_ci comm[9] = (comm[9] & 0x3F) | (pl << 6); 947141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); 948141cc406Sopenharmony_ci pl++; 949141cc406Sopenharmony_ci } while ((pl < 4) && (status == SANE_STATUS_GOOD)); 950141cc406Sopenharmony_ci } 951141cc406Sopenharmony_ci } else { 952141cc406Sopenharmony_ci /***** No custom Gamma *****/ 953141cc406Sopenharmony_ci DBG(23, ".download_gamma: by default\n"); 954141cc406Sopenharmony_ci for (i=0; i<ms->gamma_entries; i++) { 955141cc406Sopenharmony_ci /* int val = (((double) max_entry * (double) i / 956141cc406Sopenharmony_ci ((double) ms->gamma_entries - 1.0)) + 0.5); ROUNDING????*/ 957141cc406Sopenharmony_ci int val = 958141cc406Sopenharmony_ci (double) max_entry * (double) i / 959141cc406Sopenharmony_ci ((double) ms->gamma_entries - 1.0); 960141cc406Sopenharmony_ci switch (ms->gamma_entry_size) { 961141cc406Sopenharmony_ci case 1: 962141cc406Sopenharmony_ci data[i] = (uint8_t) val; 963141cc406Sopenharmony_ci break; 964141cc406Sopenharmony_ci case 2: 965141cc406Sopenharmony_ci data[i*2] = val & 0xFF; 966141cc406Sopenharmony_ci data[(i*2)+1] = (val >> 8) & 0xFF; 967141cc406Sopenharmony_ci break; 968141cc406Sopenharmony_ci } 969141cc406Sopenharmony_ci } 970141cc406Sopenharmony_ci status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); 971141cc406Sopenharmony_ci } 972141cc406Sopenharmony_ci free(comm); 973141cc406Sopenharmony_ci return status; 974141cc406Sopenharmony_ci} 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci 977141cc406Sopenharmony_ci/********************************************************************/ 978141cc406Sopenharmony_ci/* magic command to start calibration */ 979141cc406Sopenharmony_ci/********************************************************************/ 980141cc406Sopenharmony_cistatic SANE_Status 981141cc406Sopenharmony_cistart_calibration(Microtek_Scanner *ms) 982141cc406Sopenharmony_ci{ 983141cc406Sopenharmony_ci uint8_t comm[8] = { 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x0a }; 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci DBG(23, ".start_calibrate...\n"); 986141cc406Sopenharmony_ci if (DBG_LEVEL >= 192) { 987141cc406Sopenharmony_ci int i; 988141cc406Sopenharmony_ci#if 0 989141cc406Sopenharmony_ci fprintf(stderr, "STCal:"); 990141cc406Sopenharmony_ci for (i=0;i<8;i++) fprintf(stderr, "%2x ", comm[i]); 991141cc406Sopenharmony_ci fprintf(stderr, "\n"); 992141cc406Sopenharmony_ci#endif 993141cc406Sopenharmony_ci MDBG_INIT("STCal:"); 994141cc406Sopenharmony_ci for (i=0;i<8;i++) MDBG_ADD("%2x ", comm[i]); 995141cc406Sopenharmony_ci MDBG_FINISH(192); 996141cc406Sopenharmony_ci } 997141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 8, 0, 0); 998141cc406Sopenharmony_ci} 999141cc406Sopenharmony_ci 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci 1002141cc406Sopenharmony_ci/********************************************************************/ 1003141cc406Sopenharmony_ci/* magic command to download calibration values */ 1004141cc406Sopenharmony_ci/********************************************************************/ 1005141cc406Sopenharmony_cistatic SANE_Status 1006141cc406Sopenharmony_cidownload_calibration(Microtek_Scanner *ms, uint8_t *comm, 1007141cc406Sopenharmony_ci uint8_t letter, int linewidth) 1008141cc406Sopenharmony_ci{ 1009141cc406Sopenharmony_ci DBG(23, ".download_calibration... %c %d\n", letter, linewidth); 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_ci comm[0] = 0x0c; 1012141cc406Sopenharmony_ci comm[1] = 0x00; 1013141cc406Sopenharmony_ci comm[2] = 0x00; 1014141cc406Sopenharmony_ci comm[3] = (linewidth >> 8) & 0xFF; 1015141cc406Sopenharmony_ci comm[4] = linewidth & 0xFF; 1016141cc406Sopenharmony_ci comm[5] = 0x00; 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci comm[6] = 0x00; 1019141cc406Sopenharmony_ci switch (letter) { 1020141cc406Sopenharmony_ci case 'R': comm[7] = 0x40; break; 1021141cc406Sopenharmony_ci case 'G': comm[7] = 0x80; break; 1022141cc406Sopenharmony_ci case 'B': comm[7] = 0xc0; break; 1023141cc406Sopenharmony_ci default: /* XXXXXXX */ break; 1024141cc406Sopenharmony_ci } 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci return sanei_scsi_cmd(ms->sfd, comm, 6 + linewidth, 0, 0); 1027141cc406Sopenharmony_ci} 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci 1031141cc406Sopenharmony_ci/********************************************************************/ 1032141cc406Sopenharmony_ci/********************************************************************/ 1033141cc406Sopenharmony_ci/* */ 1034141cc406Sopenharmony_ci/* Myriad of internal functions */ 1035141cc406Sopenharmony_ci/* */ 1036141cc406Sopenharmony_ci/********************************************************************/ 1037141cc406Sopenharmony_ci/********************************************************************/ 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci 1040141cc406Sopenharmony_ci 1041141cc406Sopenharmony_ci/********************************************************************/ 1042141cc406Sopenharmony_ci/* Initialize the options registry */ 1043141cc406Sopenharmony_ci/********************************************************************/ 1044141cc406Sopenharmony_cistatic SANE_Status 1045141cc406Sopenharmony_ciinit_options(Microtek_Scanner *ms) 1046141cc406Sopenharmony_ci{ 1047141cc406Sopenharmony_ci int i; 1048141cc406Sopenharmony_ci SANE_Option_Descriptor *sod = ms->sod; 1049141cc406Sopenharmony_ci Option_Value *val = ms->val; 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci DBG(15, "init_options...\n"); 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci memset(ms->sod, 0, sizeof(ms->sod)); 1054141cc406Sopenharmony_ci memset(ms->val, 0, sizeof(ms->val)); 1055141cc406Sopenharmony_ci /* default: software selectable word options... */ 1056141cc406Sopenharmony_ci for (i=0; i<NUM_OPTIONS; i++) { 1057141cc406Sopenharmony_ci sod[i].size = sizeof(SANE_Word); 1058141cc406Sopenharmony_ci sod[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1059141cc406Sopenharmony_ci } 1060141cc406Sopenharmony_ci 1061141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 1062141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 1063141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 1064141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].type = SANE_TYPE_INT; 1065141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; 1066141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].size = sizeof (SANE_Word); 1067141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 1068141cc406Sopenharmony_ci sod[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; 1069141cc406Sopenharmony_ci 1070141cc406Sopenharmony_ci /* The Scan Mode Group */ 1071141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].name = ""; 1072141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].title = "Scan Mode"; 1073141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].desc = ""; 1074141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 1075141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].cap = 0; 1076141cc406Sopenharmony_ci sod[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1077141cc406Sopenharmony_ci 1078141cc406Sopenharmony_ci sod[OPT_MODE].name = SANE_NAME_SCAN_MODE; 1079141cc406Sopenharmony_ci sod[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 1080141cc406Sopenharmony_ci sod[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 1081141cc406Sopenharmony_ci sod[OPT_MODE].type = SANE_TYPE_STRING; 1082141cc406Sopenharmony_ci sod[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1083141cc406Sopenharmony_ci { 1084141cc406Sopenharmony_ci SANE_String_Const *mode_list; 1085141cc406Sopenharmony_ci mode_list = (SANE_String_Const *) malloc(5 * sizeof(SANE_String_Const)); 1086141cc406Sopenharmony_ci if (mode_list == NULL) return SANE_STATUS_NO_MEM; 1087141cc406Sopenharmony_ci i = 0; 1088141cc406Sopenharmony_ci if (ms->dev->info.modes & MI_MODES_COLOR) mode_list[i++] = M_COLOR; 1089141cc406Sopenharmony_ci if (ms->dev->info.modes & MI_MODES_GRAY) mode_list[i++] = M_GRAY; 1090141cc406Sopenharmony_ci if (ms->dev->info.modes & MI_MODES_HALFTONE) mode_list[i++] = M_HALFTONE; 1091141cc406Sopenharmony_ci if (ms->dev->info.modes & MI_MODES_LINEART) mode_list[i++] = M_LINEART; 1092141cc406Sopenharmony_ci mode_list[i] = NULL; 1093141cc406Sopenharmony_ci sod[OPT_MODE].constraint.string_list = mode_list; 1094141cc406Sopenharmony_ci sod[OPT_MODE].size = max_string_size(mode_list); 1095141cc406Sopenharmony_ci val[OPT_MODE].s = strdup(mode_list[0]); 1096141cc406Sopenharmony_ci } 1097141cc406Sopenharmony_ci 1098141cc406Sopenharmony_ci sod[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 1099141cc406Sopenharmony_ci sod[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 1100141cc406Sopenharmony_ci sod[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1101141cc406Sopenharmony_ci sod[OPT_RESOLUTION].type = SANE_TYPE_FIXED; 1102141cc406Sopenharmony_ci sod[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 1103141cc406Sopenharmony_ci sod[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 1104141cc406Sopenharmony_ci { 1105141cc406Sopenharmony_ci SANE_Int maxres = ms->dev->info.base_resolution; 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ci ms->res_range.max = SANE_FIX(maxres); 1108141cc406Sopenharmony_ci ms->exp_res_range.max = SANE_FIX(2 * maxres); 1109141cc406Sopenharmony_ci if (ms->dev->info.res_step & MI_RESSTEP_1PER) { 1110141cc406Sopenharmony_ci DBG(23, "init_options: quant yes\n"); 1111141cc406Sopenharmony_ci ms->res_range.min = SANE_FIX( maxres / 100 ); 1112141cc406Sopenharmony_ci ms->res_range.quant = ms->res_range.min; 1113141cc406Sopenharmony_ci ms->exp_res_range.min = SANE_FIX(2 * maxres / 100); 1114141cc406Sopenharmony_ci ms->exp_res_range.quant = ms->exp_res_range.min; 1115141cc406Sopenharmony_ci } else { 1116141cc406Sopenharmony_ci /* XXXXXXXXXXX */ 1117141cc406Sopenharmony_ci DBG(23, "init_options: quant no\n"); 1118141cc406Sopenharmony_ci ms->res_range.quant = SANE_FIX( 0 ); 1119141cc406Sopenharmony_ci } 1120141cc406Sopenharmony_ci sod[OPT_RESOLUTION].constraint.range = &(ms->res_range); 1121141cc406Sopenharmony_ci } 1122141cc406Sopenharmony_ci val[OPT_RESOLUTION].w = SANE_FIX(100); 1123141cc406Sopenharmony_ci 1124141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; 1125141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; 1126141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; 1127141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; 1128141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].size = max_string_size(halftone_mode_list); 1129141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1130141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1131141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_mode_list; 1132141cc406Sopenharmony_ci val[OPT_HALFTONE_PATTERN].s = strdup(halftone_mode_list[0]); 1133141cc406Sopenharmony_ci 1134141cc406Sopenharmony_ci sod[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; 1135141cc406Sopenharmony_ci sod[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; 1136141cc406Sopenharmony_ci sod[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; 1137141cc406Sopenharmony_ci sod[OPT_NEGATIVE].type = SANE_TYPE_BOOL; 1138141cc406Sopenharmony_ci sod[OPT_NEGATIVE].cap |= 1139141cc406Sopenharmony_ci (ms->dev->info.modes & MI_MODES_NEGATIVE) ? 0 : SANE_CAP_INACTIVE; 1140141cc406Sopenharmony_ci val[OPT_NEGATIVE].w = SANE_FALSE; 1141141cc406Sopenharmony_ci 1142141cc406Sopenharmony_ci sod[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; 1143141cc406Sopenharmony_ci sod[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; 1144141cc406Sopenharmony_ci /* sod[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED;*/ 1145141cc406Sopenharmony_ci sod[OPT_SPEED].desc = "Scan speed throttle -- higher values are *slower*."; 1146141cc406Sopenharmony_ci sod[OPT_SPEED].type = SANE_TYPE_INT; 1147141cc406Sopenharmony_ci sod[OPT_SPEED].cap |= SANE_CAP_ADVANCED; 1148141cc406Sopenharmony_ci sod[OPT_SPEED].unit = SANE_UNIT_NONE; 1149141cc406Sopenharmony_ci sod[OPT_SPEED].size = sizeof(SANE_Word); 1150141cc406Sopenharmony_ci sod[OPT_SPEED].constraint_type = SANE_CONSTRAINT_RANGE; 1151141cc406Sopenharmony_ci sod[OPT_SPEED].constraint.range = &speed_range; 1152141cc406Sopenharmony_ci val[OPT_SPEED].w = 1; 1153141cc406Sopenharmony_ci 1154141cc406Sopenharmony_ci sod[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; 1155141cc406Sopenharmony_ci sod[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; 1156141cc406Sopenharmony_ci sod[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; 1157141cc406Sopenharmony_ci sod[OPT_SOURCE].type = SANE_TYPE_STRING; 1158141cc406Sopenharmony_ci sod[OPT_SOURCE].unit = SANE_UNIT_NONE; 1159141cc406Sopenharmony_ci sod[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1160141cc406Sopenharmony_ci { 1161141cc406Sopenharmony_ci SANE_String_Const *source_list; 1162141cc406Sopenharmony_ci source_list = (SANE_String_Const *) malloc(4 * sizeof(SANE_String_Const)); 1163141cc406Sopenharmony_ci if (source_list == NULL) return SANE_STATUS_NO_MEM; 1164141cc406Sopenharmony_ci i = 0; 1165141cc406Sopenharmony_ci source_list[i++] = M_OPAQUE; 1166141cc406Sopenharmony_ci if (ms->dev->info.source_options & MI_SRC_HAS_TRANS) 1167141cc406Sopenharmony_ci source_list[i++] = M_TRANS; 1168141cc406Sopenharmony_ci if (ms->dev->info.source_options & MI_SRC_HAS_FEED) 1169141cc406Sopenharmony_ci source_list[i++] = M_AUTOFEED; 1170141cc406Sopenharmony_ci source_list[i] = NULL; 1171141cc406Sopenharmony_ci sod[OPT_SOURCE].constraint.string_list = source_list; 1172141cc406Sopenharmony_ci sod[OPT_SOURCE].size = max_string_size(source_list); 1173141cc406Sopenharmony_ci if (i < 2) 1174141cc406Sopenharmony_ci sod[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; 1175141cc406Sopenharmony_ci val[OPT_SOURCE].s = strdup(source_list[0]); 1176141cc406Sopenharmony_ci } 1177141cc406Sopenharmony_ci 1178141cc406Sopenharmony_ci sod[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 1179141cc406Sopenharmony_ci sod[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 1180141cc406Sopenharmony_ci sod[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 1181141cc406Sopenharmony_ci sod[OPT_PREVIEW].type = SANE_TYPE_BOOL; 1182141cc406Sopenharmony_ci sod[OPT_PREVIEW].unit = SANE_UNIT_NONE; 1183141cc406Sopenharmony_ci sod[OPT_PREVIEW].size = sizeof(SANE_Word); 1184141cc406Sopenharmony_ci val[OPT_PREVIEW].w = SANE_FALSE; 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci 1187141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].name = ""; 1188141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].title = "Geometry"; 1189141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].desc = ""; 1190141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 1191141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 1192141cc406Sopenharmony_ci sod[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1193141cc406Sopenharmony_ci 1194141cc406Sopenharmony_ci 1195141cc406Sopenharmony_ci sod[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 1196141cc406Sopenharmony_ci sod[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 1197141cc406Sopenharmony_ci sod[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 1198141cc406Sopenharmony_ci sod[OPT_TL_X].type = SANE_TYPE_FIXED; 1199141cc406Sopenharmony_ci sod[OPT_TL_X].unit = SANE_UNIT_MM; 1200141cc406Sopenharmony_ci sod[OPT_TL_X].size = sizeof(SANE_Word); 1201141cc406Sopenharmony_ci sod[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1202141cc406Sopenharmony_ci 1203141cc406Sopenharmony_ci sod[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 1204141cc406Sopenharmony_ci sod[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 1205141cc406Sopenharmony_ci sod[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 1206141cc406Sopenharmony_ci sod[OPT_TL_Y].type = SANE_TYPE_FIXED; 1207141cc406Sopenharmony_ci sod[OPT_TL_Y].unit = SANE_UNIT_MM; 1208141cc406Sopenharmony_ci sod[OPT_TL_Y].size = sizeof(SANE_Word); 1209141cc406Sopenharmony_ci sod[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1210141cc406Sopenharmony_ci 1211141cc406Sopenharmony_ci sod[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 1212141cc406Sopenharmony_ci sod[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 1213141cc406Sopenharmony_ci sod[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 1214141cc406Sopenharmony_ci sod[OPT_BR_X].type = SANE_TYPE_FIXED; 1215141cc406Sopenharmony_ci sod[OPT_BR_X].unit = SANE_UNIT_MM; 1216141cc406Sopenharmony_ci sod[OPT_BR_X].size = sizeof(SANE_Word); 1217141cc406Sopenharmony_ci sod[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci sod[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 1220141cc406Sopenharmony_ci sod[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 1221141cc406Sopenharmony_ci sod[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 1222141cc406Sopenharmony_ci sod[OPT_BR_Y].type = SANE_TYPE_FIXED; 1223141cc406Sopenharmony_ci sod[OPT_BR_Y].unit = SANE_UNIT_MM; 1224141cc406Sopenharmony_ci sod[OPT_BR_Y].size = sizeof(SANE_Word); 1225141cc406Sopenharmony_ci sod[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1226141cc406Sopenharmony_ci 1227141cc406Sopenharmony_ci sod[OPT_TL_X].constraint.range = 1228141cc406Sopenharmony_ci sod[OPT_BR_X].constraint.range = &(ms->dev->info.doc_x_range); 1229141cc406Sopenharmony_ci sod[OPT_TL_Y].constraint.range = 1230141cc406Sopenharmony_ci sod[OPT_BR_Y].constraint.range = &(ms->dev->info.doc_y_range); 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci /* set default scan region to be maximum size */ 1233141cc406Sopenharmony_ci val[OPT_TL_X].w = sod[OPT_TL_X].constraint.range->min; 1234141cc406Sopenharmony_ci val[OPT_TL_Y].w = sod[OPT_TL_Y].constraint.range->min; 1235141cc406Sopenharmony_ci val[OPT_BR_X].w = sod[OPT_BR_X].constraint.range->max; 1236141cc406Sopenharmony_ci val[OPT_BR_Y].w = sod[OPT_BR_Y].constraint.range->max; 1237141cc406Sopenharmony_ci 1238141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].name = ""; 1239141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; 1240141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].desc = ""; 1241141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 1242141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].cap = 0; 1243141cc406Sopenharmony_ci sod[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1244141cc406Sopenharmony_ci 1245141cc406Sopenharmony_ci sod[OPT_EXPOSURE].name = "exposure"; 1246141cc406Sopenharmony_ci sod[OPT_EXPOSURE].title = "Exposure"; 1247141cc406Sopenharmony_ci sod[OPT_EXPOSURE].desc = "Analog exposure control"; 1248141cc406Sopenharmony_ci sod[OPT_EXPOSURE].type = SANE_TYPE_INT; 1249141cc406Sopenharmony_ci sod[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; 1250141cc406Sopenharmony_ci sod[OPT_EXPOSURE].size = sizeof(SANE_Word); 1251141cc406Sopenharmony_ci sod[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; 1252141cc406Sopenharmony_ci ms->exposure_range.min = ms->dev->info.min_exposure; 1253141cc406Sopenharmony_ci ms->exposure_range.max = ms->dev->info.max_exposure; 1254141cc406Sopenharmony_ci ms->exposure_range.quant = 3; 1255141cc406Sopenharmony_ci sod[OPT_EXPOSURE].constraint.range = &(ms->exposure_range); 1256141cc406Sopenharmony_ci val[OPT_EXPOSURE].w = 0; 1257141cc406Sopenharmony_ci 1258141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 1259141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 1260141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 1261141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 1262141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; 1263141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].size = sizeof(SANE_Word); 1264141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].cap |= 1265141cc406Sopenharmony_ci ((ms->dev->info.extra_cap & MI_EXCAP_OFF_CTL) ? 0: SANE_CAP_INACTIVE); 1266141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 1267141cc406Sopenharmony_ci sod[OPT_BRIGHTNESS].constraint.range = &brightness_range; 1268141cc406Sopenharmony_ci val[OPT_BRIGHTNESS].w = 0; 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci sod[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 1271141cc406Sopenharmony_ci sod[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 1272141cc406Sopenharmony_ci sod[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 1273141cc406Sopenharmony_ci sod[OPT_CONTRAST].type = SANE_TYPE_INT; 1274141cc406Sopenharmony_ci sod[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; 1275141cc406Sopenharmony_ci sod[OPT_CONTRAST].size = sizeof(SANE_Word); 1276141cc406Sopenharmony_ci sod[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 1277141cc406Sopenharmony_ci ms->contrast_range.min = ms->dev->info.min_contrast; 1278141cc406Sopenharmony_ci ms->contrast_range.max = ms->dev->info.max_contrast; 1279141cc406Sopenharmony_ci ms->contrast_range.quant = 7; 1280141cc406Sopenharmony_ci sod[OPT_CONTRAST].constraint.range = &(ms->contrast_range); 1281141cc406Sopenharmony_ci val[OPT_CONTRAST].w = 0; 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci 1284141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].name = SANE_NAME_WHITE_LEVEL; 1285141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].title = SANE_TITLE_WHITE_LEVEL; 1286141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].desc = SANE_DESC_WHITE_LEVEL; 1287141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].type = SANE_TYPE_INT; 1288141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].unit = SANE_UNIT_NONE; 1289141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].size = sizeof(SANE_Word); 1290141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].constraint_type = SANE_CONSTRAINT_RANGE; 1291141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].constraint.range = &u8_range; 1292141cc406Sopenharmony_ci val[OPT_HIGHLIGHT].w = 255; 1293141cc406Sopenharmony_ci 1294141cc406Sopenharmony_ci sod[OPT_SHADOW].name = SANE_NAME_BLACK_LEVEL; 1295141cc406Sopenharmony_ci sod[OPT_SHADOW].title = SANE_TITLE_BLACK_LEVEL; 1296141cc406Sopenharmony_ci sod[OPT_SHADOW].desc = SANE_DESC_BLACK_LEVEL; 1297141cc406Sopenharmony_ci sod[OPT_SHADOW].type = SANE_TYPE_INT; 1298141cc406Sopenharmony_ci sod[OPT_SHADOW].unit = SANE_UNIT_NONE; 1299141cc406Sopenharmony_ci sod[OPT_SHADOW].size = sizeof(SANE_Word); 1300141cc406Sopenharmony_ci sod[OPT_SHADOW].constraint_type = SANE_CONSTRAINT_RANGE; 1301141cc406Sopenharmony_ci sod[OPT_SHADOW].constraint.range = &u8_range; 1302141cc406Sopenharmony_ci val[OPT_SHADOW].w = 0; 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci if (ms->dev->info.enhance_cap & MI_ENH_CAP_SHADOW) { 1305141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_ADVANCED; 1306141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_ADVANCED; 1307141cc406Sopenharmony_ci } else { 1308141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 1309141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 1310141cc406Sopenharmony_ci } 1311141cc406Sopenharmony_ci 1312141cc406Sopenharmony_ci sod[OPT_MIDTONE].name = "midtone"; 1313141cc406Sopenharmony_ci sod[OPT_MIDTONE].title = "Midtone Level"; 1314141cc406Sopenharmony_ci sod[OPT_MIDTONE].desc = "Midtone Level"; 1315141cc406Sopenharmony_ci sod[OPT_MIDTONE].type = SANE_TYPE_INT; 1316141cc406Sopenharmony_ci sod[OPT_MIDTONE].unit = SANE_UNIT_NONE; 1317141cc406Sopenharmony_ci sod[OPT_MIDTONE].size = sizeof(SANE_Word); 1318141cc406Sopenharmony_ci sod[OPT_MIDTONE].constraint_type = SANE_CONSTRAINT_RANGE; 1319141cc406Sopenharmony_ci sod[OPT_MIDTONE].constraint.range = &u8_range; 1320141cc406Sopenharmony_ci val[OPT_MIDTONE].w = 128; 1321141cc406Sopenharmony_ci if (ms->midtone_support) { 1322141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_ADVANCED; 1323141cc406Sopenharmony_ci } else { 1324141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 1325141cc406Sopenharmony_ci } 1326141cc406Sopenharmony_ci /* XXXXXXXX is this supported by all scanners?? 1327141cc406Sopenharmony_ci if ((strcmp(M_COLOR, val[OPT_MODE].s)) && 1328141cc406Sopenharmony_ci (strcmp(M_GRAY, val[OPT_MODE].s))) { 1329141cc406Sopenharmony_ci sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; 1330141cc406Sopenharmony_ci sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; 1331141cc406Sopenharmony_ci sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; 1332141cc406Sopenharmony_ci } 1333141cc406Sopenharmony_ci */ 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].name = ""; 1336141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].title = "Gamma Control"; 1337141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].desc = ""; 1338141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].type = SANE_TYPE_GROUP; 1339141cc406Sopenharmony_ci if (!(ms->gamma_entries)) 1340141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1341141cc406Sopenharmony_ci sod[OPT_GAMMA_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1342141cc406Sopenharmony_ci 1343141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].name = "gamma-mode"; 1344141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].title = "Gamma Control Mode"; 1345141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].desc = "How to specify gamma correction, if at all"; 1346141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].type = SANE_TYPE_STRING; 1347141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].size = max_string_size(gamma_mode_list); 1348141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1349141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].constraint.string_list = gamma_mode_list; 1350141cc406Sopenharmony_ci if (!(ms->gamma_entries)) 1351141cc406Sopenharmony_ci sod[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1352141cc406Sopenharmony_ci val[OPT_CUSTOM_GAMMA].s = strdup(gamma_mode_list[0]); 1353141cc406Sopenharmony_ci 1354141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].name = SANE_NAME_ANALOG_GAMMA_BIND; 1355141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND; 1356141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].desc = SANE_DESC_ANALOG_GAMMA_BIND; 1357141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; 1358141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; 1359141cc406Sopenharmony_ci val[OPT_GAMMA_BIND].w = SANE_TRUE; 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].name = SANE_NAME_ANALOG_GAMMA; 1362141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].title = SANE_TITLE_ANALOG_GAMMA; 1363141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].desc = SANE_DESC_ANALOG_GAMMA; 1364141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].type = SANE_TYPE_FIXED; 1365141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].unit = SANE_UNIT_NONE; 1366141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].size = sizeof(SANE_Word); 1367141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; 1368141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE; 1369141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].constraint.range = &analog_gamma_range; 1370141cc406Sopenharmony_ci val[OPT_ANALOG_GAMMA].w = SANE_FIX(1.0); 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R; 1373141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R; 1374141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R; 1375141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].type = SANE_TYPE_FIXED; 1376141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].unit = SANE_UNIT_NONE; 1377141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].size = sizeof(SANE_Word); 1378141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; 1379141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE; 1380141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].constraint.range = &analog_gamma_range; 1381141cc406Sopenharmony_ci val[OPT_ANALOG_GAMMA_R].w = SANE_FIX(1.0); 1382141cc406Sopenharmony_ci 1383141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G; 1384141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G; 1385141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G; 1386141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].type = SANE_TYPE_FIXED; 1387141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].unit = SANE_UNIT_NONE; 1388141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].size = sizeof(SANE_Word); 1389141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; 1390141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE; 1391141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].constraint.range = &analog_gamma_range; 1392141cc406Sopenharmony_ci val[OPT_ANALOG_GAMMA_G].w = SANE_FIX(1.0); 1393141cc406Sopenharmony_ci 1394141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B; 1395141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B; 1396141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B; 1397141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].type = SANE_TYPE_FIXED; 1398141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].unit = SANE_UNIT_NONE; 1399141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].size = sizeof(SANE_Word); 1400141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; 1401141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE; 1402141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].constraint.range = &analog_gamma_range; 1403141cc406Sopenharmony_ci val[OPT_ANALOG_GAMMA_B].w = SANE_FIX(1.0); 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 1406141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 1407141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 1408141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 1409141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 1410141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].size = ms->gamma_entries * sizeof(SANE_Word); 1411141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1412141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 1413141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].constraint.range = &(ms->gamma_entry_range); 1414141cc406Sopenharmony_ci val[OPT_GAMMA_VECTOR].wa = ms->gray_lut; 1415141cc406Sopenharmony_ci 1416141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 1417141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 1418141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 1419141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 1420141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 1421141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].size = ms->gamma_entries * sizeof(SANE_Word); 1422141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1423141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 1424141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].constraint.range = &(ms->gamma_entry_range); 1425141cc406Sopenharmony_ci val[OPT_GAMMA_VECTOR_R].wa = ms->red_lut; 1426141cc406Sopenharmony_ci 1427141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 1428141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 1429141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 1430141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 1431141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 1432141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].size = ms->gamma_entries * sizeof(SANE_Word); 1433141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1434141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 1435141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].constraint.range = &(ms->gamma_entry_range); 1436141cc406Sopenharmony_ci val[OPT_GAMMA_VECTOR_G].wa = ms->green_lut; 1437141cc406Sopenharmony_ci 1438141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 1439141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 1440141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 1441141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 1442141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 1443141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].size = ms->gamma_entries * sizeof(SANE_Word); 1444141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1445141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 1446141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].constraint.range = &(ms->gamma_entry_range); 1447141cc406Sopenharmony_ci val[OPT_GAMMA_VECTOR_B].wa = ms->blue_lut; 1448141cc406Sopenharmony_ci 1449141cc406Sopenharmony_ci sod[OPT_EXP_RES].name = "exp_res"; 1450141cc406Sopenharmony_ci sod[OPT_EXP_RES].title = "Expanded Resolution"; 1451141cc406Sopenharmony_ci sod[OPT_EXP_RES].desc = "Enable double-resolution scans"; 1452141cc406Sopenharmony_ci sod[OPT_EXP_RES].type = SANE_TYPE_BOOL; 1453141cc406Sopenharmony_ci sod[OPT_EXP_RES].cap |= SANE_CAP_ADVANCED; 1454141cc406Sopenharmony_ci if (!(ms->dev->info.expanded_resolution)) 1455141cc406Sopenharmony_ci sod[OPT_EXP_RES].cap |= SANE_CAP_INACTIVE; 1456141cc406Sopenharmony_ci val[OPT_EXP_RES].w = SANE_FALSE; 1457141cc406Sopenharmony_ci 1458141cc406Sopenharmony_ci sod[OPT_CALIB_ONCE].name = "calib_once"; 1459141cc406Sopenharmony_ci sod[OPT_CALIB_ONCE].title = "Calibrate Only Once"; 1460141cc406Sopenharmony_ci sod[OPT_CALIB_ONCE].desc = "Avoid CCD calibration on every scan" \ 1461141cc406Sopenharmony_ci "(toggle off/on to cause calibration on next scan)"; 1462141cc406Sopenharmony_ci sod[OPT_CALIB_ONCE].type = SANE_TYPE_BOOL; 1463141cc406Sopenharmony_ci sod[OPT_CALIB_ONCE].cap |= SANE_CAP_ADVANCED; 1464141cc406Sopenharmony_ci if (!(ms->do_real_calib)) { 1465141cc406Sopenharmony_ci sod[OPT_CALIB_ONCE].cap |= SANE_CAP_INACTIVE; 1466141cc406Sopenharmony_ci val[OPT_CALIB_ONCE].w = SANE_FALSE; 1467141cc406Sopenharmony_ci } else 1468141cc406Sopenharmony_ci val[OPT_CALIB_ONCE].w = SANE_TRUE; 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci /* 1471141cc406Sopenharmony_ci sod[OPT_].name = SANE_NAME_; 1472141cc406Sopenharmony_ci sod[OPT_].title = SANE_TITLE_; 1473141cc406Sopenharmony_ci sod[OPT_].desc = SANE_DESC_; 1474141cc406Sopenharmony_ci sod[OPT_].type = SANE_TYPE_; 1475141cc406Sopenharmony_ci sod[OPT_].unit = SANE_UNIT_NONE; 1476141cc406Sopenharmony_ci sod[OPT_].size = sizeof(SANE_Word); 1477141cc406Sopenharmony_ci sod[OPT_].cap = 0; 1478141cc406Sopenharmony_ci sod[OPT_].constraint_type = SANE_CONSTRAINT_NONE; 1479141cc406Sopenharmony_ci sod[OPT_].constraint = ; 1480141cc406Sopenharmony_ci val[OPT_].w = ; 1481141cc406Sopenharmony_ci */ 1482141cc406Sopenharmony_ci 1483141cc406Sopenharmony_ci DBG(15, "init_options: done.\n"); 1484141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1485141cc406Sopenharmony_ci} 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci 1488141cc406Sopenharmony_ci/********************************************************************/ 1489141cc406Sopenharmony_ci/* Parse an INQUIRY information block, as returned by scanner */ 1490141cc406Sopenharmony_ci/********************************************************************/ 1491141cc406Sopenharmony_cistatic SANE_Status 1492141cc406Sopenharmony_ciparse_inquiry(Microtek_Info *mi, unsigned char *result) 1493141cc406Sopenharmony_ci{ 1494141cc406Sopenharmony_ci#if 0 1495141cc406Sopenharmony_ci unsigned char result[0x60] = { 1496141cc406Sopenharmony_ci 0x06,0x31,0x23,0x01,0x5b,0x00,0x00,0x00,0x41,0x47,0x46,0x41,0x20,0x20,0x20,0x20, 1497141cc406Sopenharmony_ci 0x53,0x74,0x75,0x64,0x69,0x6f,0x53,0x63,0x61,0x6e,0x20,0x49,0x49,0x20,0x20,0x20, 1498141cc406Sopenharmony_ci 0x32,0x2e,0x33,0x30,0x53,0x43,0x53,0x49,0x20,0x46,0x2f,0x57,0x56,0x33,0x2e,0x31, 1499141cc406Sopenharmony_ci 0x20,0x43,0x54,0x4c,0x35,0x33,0x38,0x30,0x03,0x4f,0x8c,0xc5,0x00,0xee,0x5b,0x43, 1500141cc406Sopenharmony_ci 0x01,0x01,0x02,0x00,0x00,0x03,0x00,0x01,0x00,0x4a,0x01,0x04,0x00,0x00,0x00,0x00, 1501141cc406Sopenharmony_ci 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff 1502141cc406Sopenharmony_ci }; 1503141cc406Sopenharmony_ci#endif 1504141cc406Sopenharmony_ci DBG(15, "parse_inquiry...\n"); 1505141cc406Sopenharmony_ci snprintf(mi->vendor_id, 8 + 1, "%.*s", 8, (char *)&result[8]); 1506141cc406Sopenharmony_ci snprintf(mi->model_name, 16 + 1, "%.*s", 16, (char *)&result[16]); 1507141cc406Sopenharmony_ci snprintf(mi->revision_num, 4 + 1, "%.*s", 4, (char *)&result[32]); 1508141cc406Sopenharmony_ci snprintf(mi->vendor_string, 20 + 1, "%.*s", 20, (char *)&result[36]); 1509141cc406Sopenharmony_ci 1510141cc406Sopenharmony_ci mi->device_type = (SANE_Byte)(result[0] & 0x1f); 1511141cc406Sopenharmony_ci mi->SCSI_firmware_ver_major = (SANE_Byte)((result[1] & 0xf0) >> 4); 1512141cc406Sopenharmony_ci mi->SCSI_firmware_ver_minor = (SANE_Byte)(result[1] & 0x0f); 1513141cc406Sopenharmony_ci mi->scanner_firmware_ver_major = (SANE_Byte)((result[2] & 0xf0) >> 4); 1514141cc406Sopenharmony_ci mi->scanner_firmware_ver_minor = (SANE_Byte)(result[2] & 0x0f); 1515141cc406Sopenharmony_ci mi->response_data_format = (SANE_Byte)(result[3]); 1516141cc406Sopenharmony_ci 1517141cc406Sopenharmony_ci mi->res_step = (SANE_Byte)(result[56] & 0x03); 1518141cc406Sopenharmony_ci mi->modes = (SANE_Byte)(result[57]); 1519141cc406Sopenharmony_ci mi->pattern_count = (SANE_Int)(result[58] & 0x7f); 1520141cc406Sopenharmony_ci mi->pattern_dwnld = (SANE_Byte)(result[58] & 0x80) > 0; 1521141cc406Sopenharmony_ci mi->feed_type = (SANE_Byte)(result[59] & 0x0F); 1522141cc406Sopenharmony_ci mi->compress_type = (SANE_Byte)(result[59] & 0x30); 1523141cc406Sopenharmony_ci mi->unit_type = (SANE_Byte)(result[59] & 0xC0); 1524141cc406Sopenharmony_ci 1525141cc406Sopenharmony_ci mi->doc_size_code = (SANE_Byte)result[60]; 1526141cc406Sopenharmony_ci /* we'll compute the max sizes after we know base resolution... */ 1527141cc406Sopenharmony_ci 1528141cc406Sopenharmony_ci /* why are these things set in two places (and probably wrong anyway)? */ 1529141cc406Sopenharmony_ci mi->cont_settings = (SANE_Int)((result[61] & 0xf0) >> 4); 1530141cc406Sopenharmony_ci if ((SANE_Int)(result[72])) 1531141cc406Sopenharmony_ci mi->cont_settings = (SANE_Int)(result[72]); 1532141cc406Sopenharmony_ci mi->min_contrast = -42; 1533141cc406Sopenharmony_ci mi->max_contrast = (mi->cont_settings * 7) - 49; 1534141cc406Sopenharmony_ci 1535141cc406Sopenharmony_ci mi->exp_settings = (SANE_Int)(result[61] & 0x0f); 1536141cc406Sopenharmony_ci if ((SANE_Int)(result[73])) 1537141cc406Sopenharmony_ci mi->exp_settings = (SANE_Int)(result[73]); 1538141cc406Sopenharmony_ci mi->min_exposure = -18; 1539141cc406Sopenharmony_ci mi->max_exposure = (mi->exp_settings * 3) - 21; 1540141cc406Sopenharmony_ci#if 0 1541141cc406Sopenharmony_ci mi->contrast_vals = (SANE_Int)(result[72]); 1542141cc406Sopenharmony_ci mi->min_contrast = -42; 1543141cc406Sopenharmony_ci mi->max_contrast = 49; 1544141cc406Sopenharmony_ci if (mi->contrast_vals) 1545141cc406Sopenharmony_ci mi->max_contrast = (mi->contrast_vals * 7) - 49; 1546141cc406Sopenharmony_ci 1547141cc406Sopenharmony_ci mi->exposure_vals = (SANE_Int)(result[73]); 1548141cc406Sopenharmony_ci mi->min_exposure = -18; 1549141cc406Sopenharmony_ci mi->max_exposure = 21; 1550141cc406Sopenharmony_ci if (mi->exposure_vals) 1551141cc406Sopenharmony_ci mi->max_exposure = (mi->exposure_vals * 3) - 21; 1552141cc406Sopenharmony_ci#endif 1553141cc406Sopenharmony_ci 1554141cc406Sopenharmony_ci mi->model_code = (SANE_Byte)(result[62]); 1555141cc406Sopenharmony_ci switch (mi->model_code) { 1556141cc406Sopenharmony_ci case 0x16: /* the other ScanMaker 600ZS */ 1557141cc406Sopenharmony_ci case 0x50: /* ScanMaker II/IIXE */ 1558141cc406Sopenharmony_ci case 0x54: /* ScanMaker IISP */ 1559141cc406Sopenharmony_ci case 0x55: /* ScanMaker IIER */ 1560141cc406Sopenharmony_ci case 0x58: /* ScanMaker IIG */ 1561141cc406Sopenharmony_ci case 0x5a: /* Agfa StudioScan (untested!) */ 1562141cc406Sopenharmony_ci case 0x5f: /* ScanMaker E3 */ 1563141cc406Sopenharmony_ci case 0x56: /* ScanMaker A3t */ 1564141cc406Sopenharmony_ci case 0x64: /* ScanMaker E2 (,Vobis RealScan) */ 1565141cc406Sopenharmony_ci case 0x65: /* Color PageWiz */ 1566141cc406Sopenharmony_ci case 0xC8: /* ScanMaker 600ZS */ 1567141cc406Sopenharmony_ci mi->base_resolution = 300; 1568141cc406Sopenharmony_ci break; 1569141cc406Sopenharmony_ci case 0x5b: /* Agfa StudioScan II/IIsi (untested!) */ 1570141cc406Sopenharmony_ci mi->base_resolution = 400; 1571141cc406Sopenharmony_ci break; 1572141cc406Sopenharmony_ci case 0x57: /* ScanMaker IIHR */ 1573141cc406Sopenharmony_ci case 0x59: /* ScanMaker III */ 1574141cc406Sopenharmony_ci case 0x5c: /* Agfa Arcus II */ 1575141cc406Sopenharmony_ci case 0x5e: /* Agfa StudioStar */ 1576141cc406Sopenharmony_ci case 0x63: /* ScanMaker E6 */ 1577141cc406Sopenharmony_ci case 0x66: /* ScanMaker E6 (new)*/ 1578141cc406Sopenharmony_ci mi->base_resolution = 600; 1579141cc406Sopenharmony_ci break; 1580141cc406Sopenharmony_ci case 0x51: /* ScanMaker 45t */ 1581141cc406Sopenharmony_ci case 0x5d: /* Agfa DuoScan */ 1582141cc406Sopenharmony_ci mi->base_resolution = 1000; 1583141cc406Sopenharmony_ci break; 1584141cc406Sopenharmony_ci case 0x52: /* ScanMaker 35t */ 1585141cc406Sopenharmony_ci mi->base_resolution = 1828; 1586141cc406Sopenharmony_ci break; 1587141cc406Sopenharmony_ci case 0x62: /* ScanMaker 35t+, Polaroid 35/LE */ 1588141cc406Sopenharmony_ci mi->base_resolution = 1950; 1589141cc406Sopenharmony_ci break; 1590141cc406Sopenharmony_ci default: 1591141cc406Sopenharmony_ci mi->base_resolution = 300; 1592141cc406Sopenharmony_ci DBG(15, "parse_inquiry: Unknown base resolution for 0x%x!\n", 1593141cc406Sopenharmony_ci mi->model_code); 1594141cc406Sopenharmony_ci break; 1595141cc406Sopenharmony_ci } 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci /* Our max_x,y is in pixels. `Some scanners think in 1/8", though.' */ 1598141cc406Sopenharmony_ci /* max pixel is, of course, total - 1 */ 1599141cc406Sopenharmony_ci switch (mi->doc_size_code) { 1600141cc406Sopenharmony_ci case 0x00: 1601141cc406Sopenharmony_ci mi->max_x = 8.5 * mi->base_resolution - 1; 1602141cc406Sopenharmony_ci mi->max_y = 14.0 * mi->base_resolution - 1; 1603141cc406Sopenharmony_ci break; 1604141cc406Sopenharmony_ci case 0x01: 1605141cc406Sopenharmony_ci mi->max_x = 8.5 * mi->base_resolution - 1; 1606141cc406Sopenharmony_ci mi->max_y = 11.0 * mi->base_resolution - 1; 1607141cc406Sopenharmony_ci break; 1608141cc406Sopenharmony_ci case 0x02: 1609141cc406Sopenharmony_ci mi->max_x = 8.5 * mi->base_resolution - 1; 1610141cc406Sopenharmony_ci mi->max_y = 11.69 * mi->base_resolution - 1; 1611141cc406Sopenharmony_ci break; 1612141cc406Sopenharmony_ci case 0x03: 1613141cc406Sopenharmony_ci mi->max_x = 8.5 * mi->base_resolution - 1; 1614141cc406Sopenharmony_ci mi->max_y = 13.0 * mi->base_resolution - 1; 1615141cc406Sopenharmony_ci break; 1616141cc406Sopenharmony_ci case 0x04: 1617141cc406Sopenharmony_ci mi->max_x = 8.0 * mi->base_resolution - 1; 1618141cc406Sopenharmony_ci mi->max_y = 10.0 * mi->base_resolution - 1; 1619141cc406Sopenharmony_ci break; 1620141cc406Sopenharmony_ci case 0x05: 1621141cc406Sopenharmony_ci mi->max_x = 8.3 * mi->base_resolution - 1; 1622141cc406Sopenharmony_ci mi->max_y = 14.0 * mi->base_resolution - 1; 1623141cc406Sopenharmony_ci break; 1624141cc406Sopenharmony_ci case 0x06: 1625141cc406Sopenharmony_ci mi->max_x = 8.3 * mi->base_resolution - 1; 1626141cc406Sopenharmony_ci mi->max_y = 13.5 * mi->base_resolution - 1; 1627141cc406Sopenharmony_ci break; 1628141cc406Sopenharmony_ci case 0x07: 1629141cc406Sopenharmony_ci mi->max_x = 8.0 * mi->base_resolution - 1; 1630141cc406Sopenharmony_ci mi->max_y = 14.0 * mi->base_resolution - 1; 1631141cc406Sopenharmony_ci break; 1632141cc406Sopenharmony_ci case 0x80: 1633141cc406Sopenharmony_ci /* Slide format, size is mm */ 1634141cc406Sopenharmony_ci mi->max_x = (35.0 / MM_PER_INCH) * mi->base_resolution - 1; 1635141cc406Sopenharmony_ci mi->max_y = (35.0 / MM_PER_INCH) * mi->base_resolution - 1; 1636141cc406Sopenharmony_ci break; 1637141cc406Sopenharmony_ci case 0x81: 1638141cc406Sopenharmony_ci mi->max_x = 5.0 * mi->base_resolution - 1; 1639141cc406Sopenharmony_ci mi->max_y = 5.0 * mi->base_resolution - 1; 1640141cc406Sopenharmony_ci break; 1641141cc406Sopenharmony_ci case 0x82: 1642141cc406Sopenharmony_ci /* Slide format, size is mm */ 1643141cc406Sopenharmony_ci mi->max_x = (36.0 / MM_PER_INCH) * mi->base_resolution - 1; 1644141cc406Sopenharmony_ci mi->max_y = (36.0 / MM_PER_INCH) * mi->base_resolution - 1; 1645141cc406Sopenharmony_ci break; 1646141cc406Sopenharmony_ci default: 1647141cc406Sopenharmony_ci /* Undefined document format code */ 1648141cc406Sopenharmony_ci mi->max_x = mi->max_y = 0; 1649141cc406Sopenharmony_ci DBG(15, "parse_inquiry: Unknown doc_size_code! 0x%x\n", 1650141cc406Sopenharmony_ci mi->doc_size_code); 1651141cc406Sopenharmony_ci } 1652141cc406Sopenharmony_ci 1653141cc406Sopenharmony_ci /* create the proper range constraints, given the doc size */ 1654141cc406Sopenharmony_ci { 1655141cc406Sopenharmony_ci /* we need base resolution in dots-per-millimeter... */ 1656141cc406Sopenharmony_ci float base_res_dpmm = (float) mi->base_resolution / MM_PER_INCH; 1657141cc406Sopenharmony_ci mi->doc_x_range.min = SANE_FIX(0); 1658141cc406Sopenharmony_ci mi->doc_x_range.max = SANE_FIX((float)mi->max_x / base_res_dpmm); 1659141cc406Sopenharmony_ci mi->doc_x_range.quant = SANE_FIX(0); 1660141cc406Sopenharmony_ci mi->doc_y_range.min = SANE_FIX(0); 1661141cc406Sopenharmony_ci mi->doc_y_range.max = SANE_FIX((float)mi->max_y / base_res_dpmm); 1662141cc406Sopenharmony_ci mi->doc_y_range.quant = SANE_FIX(0); 1663141cc406Sopenharmony_ci } 1664141cc406Sopenharmony_ci 1665141cc406Sopenharmony_ci mi->source_options = (SANE_Byte)(result[63]); 1666141cc406Sopenharmony_ci 1667141cc406Sopenharmony_ci mi->expanded_resolution = (result[64] & 0x01); 1668141cc406Sopenharmony_ci /* my E6 reports exp-res capability incorrectly */ 1669141cc406Sopenharmony_ci if ((mi->model_code == 0x66) || (mi->model_code == 0x63)) { 1670141cc406Sopenharmony_ci mi->expanded_resolution = 0xFF; 1671141cc406Sopenharmony_ci DBG(4, "parse_inquiry: E6 falsely denies expanded resolution.\n"); 1672141cc406Sopenharmony_ci } 1673141cc406Sopenharmony_ci /* the StudioScan II(si) does the expanded-mode aspect correction 1674141cc406Sopenharmony_ci within the scanner... (do others too?) */ 1675141cc406Sopenharmony_ci if (mi->model_code == 0x5b) { 1676141cc406Sopenharmony_ci DBG(4, "parse_inquiry: does expanded-mode expansion internally.\n"); 1677141cc406Sopenharmony_ci mi->does_expansion = 1; 1678141cc406Sopenharmony_ci } else 1679141cc406Sopenharmony_ci mi->does_expansion = 0; 1680141cc406Sopenharmony_ci 1681141cc406Sopenharmony_ci mi->enhance_cap = (result[65] & 0x03); 1682141cc406Sopenharmony_ci 1683141cc406Sopenharmony_ci /* 1684141cc406Sopenharmony_ci switch (result[66] & 0x0F) { 1685141cc406Sopenharmony_ci case 0x00: mi->max_lookup_size = 0; break; 1686141cc406Sopenharmony_ci case 0x01: mi->max_lookup_size = 256; break; 1687141cc406Sopenharmony_ci case 0x03: mi->max_lookup_size = 1024; break; 1688141cc406Sopenharmony_ci case 0x05: mi->max_lookup_size = 4096; break; 1689141cc406Sopenharmony_ci case 0x09: mi->max_lookup_size = 65536; break; 1690141cc406Sopenharmony_ci default: 1691141cc406Sopenharmony_ci mi->max_lookup_size = 0; 1692141cc406Sopenharmony_ci DBG(15, "parse_inquiry: Unknown gamma LUT size! 0x%x\n", 1693141cc406Sopenharmony_ci result[66]); 1694141cc406Sopenharmony_ci } 1695141cc406Sopenharmony_ci */ 1696141cc406Sopenharmony_ci 1697141cc406Sopenharmony_ci /* This is not how the vague documentation specifies this register. 1698141cc406Sopenharmony_ci We're going to take it literally here -- i.e. if the bit is 1699141cc406Sopenharmony_ci set, the scanner supports the value, otherwise it doesn't. 1700141cc406Sopenharmony_ci (The docs say all lower values are always supported. This is 1701141cc406Sopenharmony_ci not the case for the StudioScan IIsi, at least, which only 1702141cc406Sopenharmony_ci specifies 0x02==1024-byte table, and only supports that, too.) 1703141cc406Sopenharmony_ci 1704141cc406Sopenharmony_ci All-in-all, it doesn't matter, since we take the largest 1705141cc406Sopenharmony_ci allowed LUT size anyway. 1706141cc406Sopenharmony_ci */ 1707141cc406Sopenharmony_ci if (result[66] & 0x08) 1708141cc406Sopenharmony_ci mi->max_lookup_size = 65536; 1709141cc406Sopenharmony_ci else if (result[66] & 0x04) 1710141cc406Sopenharmony_ci mi->max_lookup_size = 4096; 1711141cc406Sopenharmony_ci else if (result[66] & 0x02) 1712141cc406Sopenharmony_ci mi->max_lookup_size = 1024; 1713141cc406Sopenharmony_ci else if (result[66] & 0x01) 1714141cc406Sopenharmony_ci mi->max_lookup_size = 256; 1715141cc406Sopenharmony_ci else 1716141cc406Sopenharmony_ci mi->max_lookup_size = 0; 1717141cc406Sopenharmony_ci 1718141cc406Sopenharmony_ci /* my E6 reports incorrectly */ 1719141cc406Sopenharmony_ci if ((mi->model_code == 0x66) || (mi->model_code == 0x63)) { 1720141cc406Sopenharmony_ci mi->max_lookup_size = 1024; 1721141cc406Sopenharmony_ci DBG(4, "parse_inquiry: E6 falsely denies 1024-byte LUT.\n"); 1722141cc406Sopenharmony_ci } 1723141cc406Sopenharmony_ci 1724141cc406Sopenharmony_ci /* 1725141cc406Sopenharmony_ci switch (result[66] >> 5) { 1726141cc406Sopenharmony_ci case 0x00: mi->max_gamma_val = 255; mi->gamma_size = 1; break; 1727141cc406Sopenharmony_ci case 0x01: mi->max_gamma_val = 1023; mi->gamma_size = 2; break; 1728141cc406Sopenharmony_ci case 0x02: mi->max_gamma_val = 4095; mi->gamma_size = 2; break; 1729141cc406Sopenharmony_ci case 0x03: mi->max_gamma_val = 65535; mi->gamma_size = 2; break; 1730141cc406Sopenharmony_ci default: 1731141cc406Sopenharmony_ci mi->max_gamma_val = 0; mi->gamma_size = 0; 1732141cc406Sopenharmony_ci DBG(15, "parse_inquiry: Unknown gamma max val! 0x%x\n", 1733141cc406Sopenharmony_ci result[66]); 1734141cc406Sopenharmony_ci } 1735141cc406Sopenharmony_ci */ 1736141cc406Sopenharmony_ci switch (result[66] >> 5) { 1737141cc406Sopenharmony_ci case 0x00: mi->max_gamma_bit_depth = 8; mi->gamma_size = 1; break; 1738141cc406Sopenharmony_ci case 0x01: mi->max_gamma_bit_depth = 10; mi->gamma_size = 2; break; 1739141cc406Sopenharmony_ci case 0x02: mi->max_gamma_bit_depth = 12; mi->gamma_size = 2; break; 1740141cc406Sopenharmony_ci case 0x03: mi->max_gamma_bit_depth = 16; mi->gamma_size = 2; break; 1741141cc406Sopenharmony_ci default: 1742141cc406Sopenharmony_ci mi->max_gamma_bit_depth = 0; mi->gamma_size = 0; 1743141cc406Sopenharmony_ci DBG(15, "parse_inquiry: Unknown gamma max val! 0x%x\n", 1744141cc406Sopenharmony_ci result[66]); 1745141cc406Sopenharmony_ci } 1746141cc406Sopenharmony_ci 1747141cc406Sopenharmony_ci mi->fast_color_preview = (SANE_Byte)(result[67] & 0x01); 1748141cc406Sopenharmony_ci mi->xfer_format_select = (SANE_Byte)(result[68] & 0x01); 1749141cc406Sopenharmony_ci mi->color_sequence = (SANE_Byte)(result[69] & 0x7f); 1750141cc406Sopenharmony_ci mi->does_3pass = (SANE_Byte)(!(result[69] & 0x80)); 1751141cc406Sopenharmony_ci mi->does_mode1 = (SANE_Byte)(result[71] & 0x01); 1752141cc406Sopenharmony_ci 1753141cc406Sopenharmony_ci mi->bit_formats = (SANE_Byte)(result[74] & 0x0F); 1754141cc406Sopenharmony_ci mi->extra_cap = (SANE_Byte)(result[75] & 0x07); 1755141cc406Sopenharmony_ci 1756141cc406Sopenharmony_ci /* XXXXXX a quick hack to disable any [pre/real]cal stuff for 1757141cc406Sopenharmony_ci anything but an E6... */ 1758141cc406Sopenharmony_ci if (!((mi->model_code == 0x66) || (mi->model_code == 0x63))) { 1759141cc406Sopenharmony_ci mi->extra_cap &= ~MI_EXCAP_DIS_RECAL; 1760141cc406Sopenharmony_ci DBG(4, "parse_inquiry: Not an E6 -- pretend recal cannot be disabled.\n"); 1761141cc406Sopenharmony_ci } 1762141cc406Sopenharmony_ci 1763141cc406Sopenharmony_ci /* The E2 lies... */ 1764141cc406Sopenharmony_ci if (mi->model_code == 0x64) { 1765141cc406Sopenharmony_ci DBG(4, "parse_inquiry: The E2 lies about it's 3-pass heritage.\n"); 1766141cc406Sopenharmony_ci mi->does_3pass = 1; 1767141cc406Sopenharmony_ci mi->modes &= ~MI_MODES_ONEPASS; 1768141cc406Sopenharmony_ci } 1769141cc406Sopenharmony_ci 1770141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1771141cc406Sopenharmony_ci} 1772141cc406Sopenharmony_ci 1773141cc406Sopenharmony_ci 1774141cc406Sopenharmony_ci 1775141cc406Sopenharmony_ci/********************************************************************/ 1776141cc406Sopenharmony_ci/* Dump all we know about scanner to stderr */ 1777141cc406Sopenharmony_ci/********************************************************************/ 1778141cc406Sopenharmony_cistatic SANE_Status 1779141cc406Sopenharmony_cidump_inquiry(Microtek_Info *mi, unsigned char *result) 1780141cc406Sopenharmony_ci{ 1781141cc406Sopenharmony_ci int i; 1782141cc406Sopenharmony_ci 1783141cc406Sopenharmony_ci DBG(15, "dump_inquiry...\n"); 1784141cc406Sopenharmony_ci DBG(1, " === SANE/Microtek backend v%d.%d.%d ===\n", 1785141cc406Sopenharmony_ci MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH); 1786141cc406Sopenharmony_ci DBG(1, "========== Scanner Inquiry Block ========mm\n"); 1787141cc406Sopenharmony_ci for (i=0; i<96; ) { 1788141cc406Sopenharmony_ci if (!(i % 16)) MDBG_INIT(""); 1789141cc406Sopenharmony_ci MDBG_ADD("%02x ", (int)result[i++]); 1790141cc406Sopenharmony_ci if (!(i % 16)) MDBG_FINISH(1); 1791141cc406Sopenharmony_ci } 1792141cc406Sopenharmony_ci DBG(1, "========== Scanner Inquiry Report ==========\n"); 1793141cc406Sopenharmony_ci DBG(1, "===== Scanner ID...\n"); 1794141cc406Sopenharmony_ci DBG(1, "Device Type Code: 0x%02x\n", mi->device_type); 1795141cc406Sopenharmony_ci DBG(1, "Model Code: 0x%02x\n", mi->model_code); 1796141cc406Sopenharmony_ci DBG(1, "Vendor Name: '%s' Model Name: '%s'\n", 1797141cc406Sopenharmony_ci mi->vendor_id, mi->model_name); 1798141cc406Sopenharmony_ci DBG(1, "Vendor Specific String: '%s'\n", mi->vendor_string); 1799141cc406Sopenharmony_ci DBG(1, "Firmware Rev: '%s'\n", mi->revision_num); 1800141cc406Sopenharmony_ci DBG(1, 1801141cc406Sopenharmony_ci "SCSI F/W version: %1d.%1d Scanner F/W version: %1d.%1d\n", 1802141cc406Sopenharmony_ci mi->SCSI_firmware_ver_major, mi->SCSI_firmware_ver_minor, 1803141cc406Sopenharmony_ci mi->scanner_firmware_ver_major, mi->scanner_firmware_ver_minor); 1804141cc406Sopenharmony_ci DBG(1, "Response data format: 0x%02x\n", mi->response_data_format); 1805141cc406Sopenharmony_ci 1806141cc406Sopenharmony_ci DBG(1, "===== Imaging Capabilities...\n"); 1807141cc406Sopenharmony_ci DBG(1, "Modes: %s%s%s%s%s%s%s\n", 1808141cc406Sopenharmony_ci (mi->modes & MI_MODES_LINEART) ? "Lineart " : "", 1809141cc406Sopenharmony_ci (mi->modes & MI_MODES_HALFTONE) ? "Halftone " : "", 1810141cc406Sopenharmony_ci (mi->modes & MI_MODES_GRAY) ? "Gray " : "", 1811141cc406Sopenharmony_ci (mi->modes & MI_MODES_COLOR) ? "Color " : "", 1812141cc406Sopenharmony_ci (mi->modes & MI_MODES_TRANSMSV) ? "(X-msv) " : "", 1813141cc406Sopenharmony_ci (mi->modes & MI_MODES_ONEPASS) ? "(OnePass) " : "", 1814141cc406Sopenharmony_ci (mi->modes & MI_MODES_NEGATIVE) ? "(Negative) " : ""); 1815141cc406Sopenharmony_ci DBG(1, 1816141cc406Sopenharmony_ci "Resolution Step Sizes: %s%s Expanded Resolution Support? %s%s\n", 1817141cc406Sopenharmony_ci (mi->res_step & MI_RESSTEP_1PER) ? "1% " : "", 1818141cc406Sopenharmony_ci (mi->res_step & MI_RESSTEP_5PER) ? "5%" : "", 1819141cc406Sopenharmony_ci (mi->expanded_resolution) ? "yes" : "no", 1820141cc406Sopenharmony_ci (mi->expanded_resolution == 0xFF) ? "(but says no)" : ""); 1821141cc406Sopenharmony_ci DBG(1, "Supported Bits Per Sample: %s8 %s%s%s\n", 1822141cc406Sopenharmony_ci (mi->bit_formats & MI_FMT_CAP_4BPP) ? "4 " : "", 1823141cc406Sopenharmony_ci (mi->bit_formats & MI_FMT_CAP_10BPP) ? "10 " : "", 1824141cc406Sopenharmony_ci (mi->bit_formats & MI_FMT_CAP_12BPP) ? "12 " : "", 1825141cc406Sopenharmony_ci (mi->bit_formats & MI_FMT_CAP_16BPP) ? "16 " : ""); 1826141cc406Sopenharmony_ci DBG(1, "Max. document size code: 0x%02x\n", 1827141cc406Sopenharmony_ci mi->doc_size_code); 1828141cc406Sopenharmony_ci DBG(1, "Max. document size: %d x %d pixels\n", 1829141cc406Sopenharmony_ci mi->max_x, mi->max_y); 1830141cc406Sopenharmony_ci DBG(1, "Frame units: %s%s\n", 1831141cc406Sopenharmony_ci (mi->unit_type & MI_UNIT_PIXELS) ? "pixels " : "", 1832141cc406Sopenharmony_ci (mi->unit_type & MI_UNIT_8TH_INCH) ? "1/8\"'s " : ""); 1833141cc406Sopenharmony_ci DBG(1, "# of built-in halftones: %d Downloadable patterns? %s\n", 1834141cc406Sopenharmony_ci mi->pattern_count, (mi->pattern_dwnld) ? "Yes" : "No"); 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci DBG(1, "Data Compression: %s%s\n", 1837141cc406Sopenharmony_ci (mi->compress_type & MI_COMPRSS_HUFF) ? "huffman " : "", 1838141cc406Sopenharmony_ci (mi->compress_type & MI_COMPRSS_RD) ? "read-data " : ""); 1839141cc406Sopenharmony_ci DBG(1, "Contrast Settings: %d Exposure Settings: %d\n", 1840141cc406Sopenharmony_ci mi->cont_settings, mi->exp_settings); 1841141cc406Sopenharmony_ci DBG(1, "Adjustable Shadow/Highlight? %s Adjustable Midtone? %s\n", 1842141cc406Sopenharmony_ci (mi->enhance_cap & MI_ENH_CAP_SHADOW) ? "yes" : "no ", 1843141cc406Sopenharmony_ci (mi->enhance_cap & MI_ENH_CAP_MIDTONE) ? "yes" : "no "); 1844141cc406Sopenharmony_ci DBG(1, "Digital brightness/offset? %s\n", 1845141cc406Sopenharmony_ci (mi->extra_cap & MI_EXCAP_OFF_CTL) ? "yes" : "no"); 1846141cc406Sopenharmony_ci /* 1847141cc406Sopenharmony_ci fprintf(stderr, 1848141cc406Sopenharmony_ci "Gamma Table Size: %d entries of %d bytes (max. value: %d)\n", 1849141cc406Sopenharmony_ci mi->max_lookup_size, mi->gamma_size, mi->max_gamma_val); 1850141cc406Sopenharmony_ci */ 1851141cc406Sopenharmony_ci DBG(1, 1852141cc406Sopenharmony_ci "Gamma Table Size: %d entries of %d bytes (max. depth: %d)\n", 1853141cc406Sopenharmony_ci mi->max_lookup_size, mi->gamma_size, mi->max_gamma_bit_depth); 1854141cc406Sopenharmony_ci 1855141cc406Sopenharmony_ci DBG(1, "===== Source Options...\n"); 1856141cc406Sopenharmony_ci DBG(1, "Feed type: %s%s ADF support? %s\n", 1857141cc406Sopenharmony_ci (mi->feed_type & MI_FEED_FLATBED) ? "flatbed " : "", 1858141cc406Sopenharmony_ci (mi->feed_type & MI_FEED_EDGEFEED) ? "edge-feed " : "", 1859141cc406Sopenharmony_ci (mi->feed_type & MI_FEED_AUTOSUPP) ? "yes" : "no"); 1860141cc406Sopenharmony_ci DBG(1, "Document Feeder Support? %s Feeder Backtracking? %s\n", 1861141cc406Sopenharmony_ci (mi->source_options & MI_SRC_FEED_SUPP) ? "yes" : "no ", 1862141cc406Sopenharmony_ci (mi->source_options & MI_SRC_FEED_BT) ? "yes" : "no "); 1863141cc406Sopenharmony_ci DBG(1, "Feeder Installed? %s Feeder Ready? %s\n", 1864141cc406Sopenharmony_ci (mi->source_options & MI_SRC_HAS_FEED) ? "yes" : "no ", 1865141cc406Sopenharmony_ci (mi->source_options & MI_SRC_FEED_RDY) ? "yes" : "no "); 1866141cc406Sopenharmony_ci DBG(1, "Transparency Adapter Installed? %s\n", 1867141cc406Sopenharmony_ci (mi->source_options & MI_SRC_HAS_TRANS) ? "yes" : "no "); 1868141cc406Sopenharmony_ci /* GET_TRANS GET_FEED XXXXXXXXX */ 1869141cc406Sopenharmony_ci /* mt_SWslct ???? XXXXXXXXXXX */ 1870141cc406Sopenharmony_ci /*#define DOC_ON_FLATBED 0x00 1871141cc406Sopenharmony_ci #define DOC_IN_FEEDER 0x01 1872141cc406Sopenharmony_ci #define TRANSPARENCY 0x10 1873141cc406Sopenharmony_ci */ 1874141cc406Sopenharmony_ci DBG(1, "Fast Color Prescan? %s\n", 1875141cc406Sopenharmony_ci (mi->fast_color_preview) ? "yes" : "no"); 1876141cc406Sopenharmony_ci DBG(1, "Selectable Transfer Format? %s\n", 1877141cc406Sopenharmony_ci (mi->xfer_format_select) ? "yes" : "no"); 1878141cc406Sopenharmony_ci MDBG_INIT("Color Transfer Sequence: "); 1879141cc406Sopenharmony_ci switch (mi->color_sequence) { 1880141cc406Sopenharmony_ci case MI_COLSEQ_PLANE: 1881141cc406Sopenharmony_ci MDBG_ADD("plane-by-plane (3-pass)"); break; 1882141cc406Sopenharmony_ci case MI_COLSEQ_PIXEL: 1883141cc406Sopenharmony_ci MDBG_ADD("pixel-by-pixel RGB"); break; 1884141cc406Sopenharmony_ci case MI_COLSEQ_RGB: 1885141cc406Sopenharmony_ci MDBG_ADD("line-by-line, R-G-B sequence"); break; 1886141cc406Sopenharmony_ci case MI_COLSEQ_NONRGB: 1887141cc406Sopenharmony_ci MDBG_ADD("line-by-line, non-sequential with headers"); break; 1888141cc406Sopenharmony_ci case MI_COLSEQ_2PIXEL: 1889141cc406Sopenharmony_ci MDBG_ADD("2pixel-by-2pixel RRGGBB"); break; 1890141cc406Sopenharmony_ci default: 1891141cc406Sopenharmony_ci MDBG_ADD("UNKNOWN CODE (0x%02x)", mi->color_sequence); 1892141cc406Sopenharmony_ci } 1893141cc406Sopenharmony_ci MDBG_FINISH(1); 1894141cc406Sopenharmony_ci /* if (mi->modes & MI_MODES_ONEPASS) XXXXXXXXXXX */ 1895141cc406Sopenharmony_ci DBG(1, "Three pass scan support? %s\n", 1896141cc406Sopenharmony_ci (mi->does_3pass ? "yes" : "no")); 1897141cc406Sopenharmony_ci DBG(1, "ModeSelect-1 and ModeSense-1 Support? %s\n", 1898141cc406Sopenharmony_ci (mi->does_mode1) ? "yes" : "no"); 1899141cc406Sopenharmony_ci DBG(1, "Can Disable Linearization Table? %s\n", 1900141cc406Sopenharmony_ci (mi->extra_cap & MI_EXCAP_DIS_LNTBL) ? "yes" : "no"); 1901141cc406Sopenharmony_ci DBG(1, "Can Disable Start-of-Scan Recalibration? %s\n", 1902141cc406Sopenharmony_ci (mi->extra_cap & MI_EXCAP_DIS_RECAL) ? "yes" : "no"); 1903141cc406Sopenharmony_ci 1904141cc406Sopenharmony_ci DBG(1, "Internal expanded expansion? %s\n", 1905141cc406Sopenharmony_ci mi->does_expansion ? "yes" : "no"); 1906141cc406Sopenharmony_ci /* 1907141cc406Sopenharmony_ci fprintf(stderr, "cntr_vals = %d, min_cntr = %d, max_cntr = %d\n", 1908141cc406Sopenharmony_ci cntr_vals, min_cntr, max_cntr); 1909141cc406Sopenharmony_ci fprintf(stderr, "exp_vals = %d, min_exp = %d, max_exp = %d\n", 1910141cc406Sopenharmony_ci exp_vals, min_exp, max_exp); 1911141cc406Sopenharmony_ci */ 1912141cc406Sopenharmony_ci DBG(1, "====== End of Scanner Inquiry Report =======\n"); 1913141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1914141cc406Sopenharmony_ci} 1915141cc406Sopenharmony_ci 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci/********************************************************************/ 1918141cc406Sopenharmony_ci/* Dump all we know about some unknown scanner to stderr */ 1919141cc406Sopenharmony_ci/********************************************************************/ 1920141cc406Sopenharmony_cistatic SANE_Status 1921141cc406Sopenharmony_cidump_suspect_inquiry(unsigned char *result) 1922141cc406Sopenharmony_ci{ 1923141cc406Sopenharmony_ci int i; 1924141cc406Sopenharmony_ci char vendor_id[9], model_name[17], revision_num[5]; 1925141cc406Sopenharmony_ci SANE_Byte device_type, model_code; 1926141cc406Sopenharmony_ci SANE_Byte SCSI_firmware_ver_major, SCSI_firmware_ver_minor; 1927141cc406Sopenharmony_ci SANE_Byte scanner_firmware_ver_major, scanner_firmware_ver_minor; 1928141cc406Sopenharmony_ci SANE_Byte response_data_format; 1929141cc406Sopenharmony_ci 1930141cc406Sopenharmony_ci DBG(15, "dump_suspect_inquiry...\n"); 1931141cc406Sopenharmony_ci DBG(1, " === SANE/Microtek backend v%d.%d.%d ===\n", 1932141cc406Sopenharmony_ci MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH); 1933141cc406Sopenharmony_ci DBG(1, "========== Scanner Inquiry Block ========mm\n"); 1934141cc406Sopenharmony_ci for (i=0; i<96; ) { 1935141cc406Sopenharmony_ci if (!(i % 16)) MDBG_INIT(""); 1936141cc406Sopenharmony_ci MDBG_ADD("%02x ", (int)result[i++]); 1937141cc406Sopenharmony_ci if (!(i % 16)) MDBG_FINISH(1); 1938141cc406Sopenharmony_ci } 1939141cc406Sopenharmony_ci#if 0 1940141cc406Sopenharmony_ci for (i=0; i<96; i++) { 1941141cc406Sopenharmony_ci if (!(i % 16) && (i)) fprintf(stderr, "\n"); 1942141cc406Sopenharmony_ci fprintf(stderr, "%02x ", (int)result[i]); 1943141cc406Sopenharmony_ci } 1944141cc406Sopenharmony_ci fprintf(stderr, "\n\n"); 1945141cc406Sopenharmony_ci#endif 1946141cc406Sopenharmony_ci snprintf(vendor_id, 8 + 1, "%.*s", 8, (char *)&result[8]); 1947141cc406Sopenharmony_ci snprintf(model_name, 16 + 1, "%.*s", 16, (char *)&result[16]); 1948141cc406Sopenharmony_ci snprintf(revision_num, 4 + 1, "%.*s", 4, (char *)&result[32]); 1949141cc406Sopenharmony_ci device_type = (SANE_Byte)(result[0] & 0x1f); 1950141cc406Sopenharmony_ci SCSI_firmware_ver_major = (SANE_Byte)((result[1] & 0xf0) >> 4); 1951141cc406Sopenharmony_ci SCSI_firmware_ver_minor = (SANE_Byte)(result[1] & 0x0f); 1952141cc406Sopenharmony_ci scanner_firmware_ver_major = (SANE_Byte)((result[2] & 0xf0) >> 4); 1953141cc406Sopenharmony_ci scanner_firmware_ver_minor = (SANE_Byte)(result[2] & 0x0f); 1954141cc406Sopenharmony_ci response_data_format = (SANE_Byte)(result[3]); 1955141cc406Sopenharmony_ci model_code = (SANE_Byte)(result[62]); 1956141cc406Sopenharmony_ci 1957141cc406Sopenharmony_ci DBG(1, "========== Scanner Inquiry Report ==========\n"); 1958141cc406Sopenharmony_ci DBG(1, "===== Scanner ID...\n"); 1959141cc406Sopenharmony_ci DBG(1, "Device Type Code: 0x%02x\n", device_type); 1960141cc406Sopenharmony_ci DBG(1, "Model Code: 0x%02x\n", model_code); 1961141cc406Sopenharmony_ci DBG(1, "Vendor Name: '%s' Model Name: '%s'\n", 1962141cc406Sopenharmony_ci vendor_id, model_name); 1963141cc406Sopenharmony_ci DBG(1, "Firmware Rev: '%s'\n", revision_num); 1964141cc406Sopenharmony_ci DBG(1, 1965141cc406Sopenharmony_ci "SCSI F/W version: %1d.%1d Scanner F/W version: %1d.%1d\n", 1966141cc406Sopenharmony_ci SCSI_firmware_ver_major, SCSI_firmware_ver_minor, 1967141cc406Sopenharmony_ci scanner_firmware_ver_major, scanner_firmware_ver_minor); 1968141cc406Sopenharmony_ci DBG(1, "Response data format: 0x%02x\n", response_data_format); 1969141cc406Sopenharmony_ci DBG(1, "====== End of Scanner Inquiry Report =======\n"); 1970141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1971141cc406Sopenharmony_ci} 1972141cc406Sopenharmony_ci 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci/********************************************************************/ 1975141cc406Sopenharmony_ci/* Determine if device is a Microtek Scanner (from INQUIRY info) */ 1976141cc406Sopenharmony_ci/********************************************************************/ 1977141cc406Sopenharmony_cistatic SANE_Status 1978141cc406Sopenharmony_ciid_microtek(uint8_t *result, char **model_string) 1979141cc406Sopenharmony_ci{ 1980141cc406Sopenharmony_ci SANE_Byte device_type, response_data_format; 1981141cc406Sopenharmony_ci int forcewarn = 0; 1982141cc406Sopenharmony_ci 1983141cc406Sopenharmony_ci DBG(15, "id_microtek...\n"); 1984141cc406Sopenharmony_ci /* check device type first... */ 1985141cc406Sopenharmony_ci device_type = (SANE_Byte)(result[0] & 0x1f); 1986141cc406Sopenharmony_ci if (device_type != 0x06) { 1987141cc406Sopenharmony_ci DBG(15, "id_microtek: not even a scanner: dev_type = %d\n", 1988141cc406Sopenharmony_ci device_type); 1989141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1990141cc406Sopenharmony_ci } 1991141cc406Sopenharmony_ci if (!(strncmp("MICROTEK", (char *)&(result[8]), 8)) || 1992141cc406Sopenharmony_ci !(strncmp("MII SC31", (char *)&(result[8]), 8)) || /* the IISP */ 1993141cc406Sopenharmony_ci !(strncmp("MII SC21", (char *)&(result[8]), 8)) || /* the 600ZS */ 1994141cc406Sopenharmony_ci !(strncmp("MII SC23", (char *)&(result[8]), 8)) || /* the other 600ZS */ 1995141cc406Sopenharmony_ci !(strncmp("MII SC25", (char *)&(result[8]), 8)) || /* some other 600GS */ 1996141cc406Sopenharmony_ci !(strncmp("AGFA ", (char *)&(result[8]), 8)) || /* Arcus II */ 1997141cc406Sopenharmony_ci !(strncmp("Microtek", (char *)&(result[8]), 8)) || /* some 35t+'s */ 1998141cc406Sopenharmony_ci !(strncmp("Polaroid", (char *)&(result[8]), 8)) || /* SprintScan 35LE */ 1999141cc406Sopenharmony_ci !(strncmp(" ", (char *)&(result[8]), 8)) ) { 2000141cc406Sopenharmony_ci switch (result[62]) { 2001141cc406Sopenharmony_ci case 0x16 : 2002141cc406Sopenharmony_ci *model_string = "ScanMaker 600ZS"; break; 2003141cc406Sopenharmony_ci case 0x50 : 2004141cc406Sopenharmony_ci *model_string = "ScanMaker II/IIXE"; break; 2005141cc406Sopenharmony_ci case 0x51 : 2006141cc406Sopenharmony_ci *model_string = "ScanMaker 45t"; break; 2007141cc406Sopenharmony_ci case 0x52 : 2008141cc406Sopenharmony_ci *model_string = "ScanMaker 35t"; break; 2009141cc406Sopenharmony_ci case 0x54 : 2010141cc406Sopenharmony_ci *model_string = "ScanMaker IISP"; break; 2011141cc406Sopenharmony_ci case 0x55 : 2012141cc406Sopenharmony_ci *model_string = "ScanMaker IIER"; break; 2013141cc406Sopenharmony_ci case 0x56 : 2014141cc406Sopenharmony_ci *model_string = "ScanMaker A3t"; break; 2015141cc406Sopenharmony_ci case 0x57 : 2016141cc406Sopenharmony_ci *model_string = "ScanMaker IIHR"; break; 2017141cc406Sopenharmony_ci case 0x58 : 2018141cc406Sopenharmony_ci *model_string = "ScanMaker IIG"; break; 2019141cc406Sopenharmony_ci case 0x59 : 2020141cc406Sopenharmony_ci *model_string = "ScanMaker III"; break; 2021141cc406Sopenharmony_ci case 0x5A : 2022141cc406Sopenharmony_ci *model_string = "Agfa StudioScan"; break; 2023141cc406Sopenharmony_ci case 0x5B : 2024141cc406Sopenharmony_ci *model_string = "Agfa StudioScan II"; break; 2025141cc406Sopenharmony_ci case 0x5C : 2026141cc406Sopenharmony_ci *model_string = "Agfa Arcus II"; break; 2027141cc406Sopenharmony_ci case 0x5f : 2028141cc406Sopenharmony_ci *model_string = "ScanMaker E3"; break; 2029141cc406Sopenharmony_ci case 0x62 : 2030141cc406Sopenharmony_ci if (!(strncmp("Polaroid", (char *)&(result[8]), 8))) 2031141cc406Sopenharmony_ci *model_string = "Polaroid SprintScan 35/LE"; 2032141cc406Sopenharmony_ci else 2033141cc406Sopenharmony_ci *model_string = "ScanMaker 35t+"; 2034141cc406Sopenharmony_ci break; 2035141cc406Sopenharmony_ci case 0x63 : 2036141cc406Sopenharmony_ci case 0x66 : 2037141cc406Sopenharmony_ci *model_string = "ScanMaker E6"; break; 2038141cc406Sopenharmony_ci case 0x64 : /* and "Vobis RealScan" */ 2039141cc406Sopenharmony_ci *model_string = "ScanMaker E2"; break; 2040141cc406Sopenharmony_ci case 0x65: 2041141cc406Sopenharmony_ci *model_string = "Color PageWiz"; break; 2042141cc406Sopenharmony_ci case 0xC8: 2043141cc406Sopenharmony_ci *model_string = "ScanMaker 600ZS"; break; 2044141cc406Sopenharmony_ci /* the follow are listed in the docs, but are otherwise a mystery... */ 2045141cc406Sopenharmony_ci case 0x5D: 2046141cc406Sopenharmony_ci *model_string = "Agfa DuoScan"; forcewarn = 1; break; 2047141cc406Sopenharmony_ci case 0x5E: 2048141cc406Sopenharmony_ci *model_string = "SS3"; forcewarn = 1; break; 2049141cc406Sopenharmony_ci case 0x60: 2050141cc406Sopenharmony_ci *model_string = "HR1"; forcewarn = 1; break; 2051141cc406Sopenharmony_ci case 0x61: 2052141cc406Sopenharmony_ci *model_string = "45T+"; forcewarn = 1; break; 2053141cc406Sopenharmony_ci case 0x67: 2054141cc406Sopenharmony_ci *model_string = "TR3"; forcewarn = 1; break; 2055141cc406Sopenharmony_ci default : 2056141cc406Sopenharmony_ci /* this might be a newer scanner, which uses the SCSI II command set. */ 2057141cc406Sopenharmony_ci /* that's unfortunate, but we'll warn the user anyway.... */ 2058141cc406Sopenharmony_ci response_data_format = (SANE_Byte)(result[3]); 2059141cc406Sopenharmony_ci if (response_data_format == 0x02) { 2060141cc406Sopenharmony_ci DBG(15, "id_microtek: (uses new SCSI II command set)\n"); 2061141cc406Sopenharmony_ci if (DBG_LEVEL >= 15) { 2062141cc406Sopenharmony_ci DBG(1, "\n"); 2063141cc406Sopenharmony_ci DBG(1, "\n"); 2064141cc406Sopenharmony_ci DBG(1, "\n"); 2065141cc406Sopenharmony_ci DBG(1, "========== Congratulations! ==========\n"); 2066141cc406Sopenharmony_ci DBG(1, "You appear to be the proud owner of a \n"); 2067141cc406Sopenharmony_ci DBG(1, "brand-new Microtek scanner, which uses\n"); 2068141cc406Sopenharmony_ci DBG(1, "a new SCSI II command set. \n"); 2069141cc406Sopenharmony_ci DBG(1, "\n"); 2070141cc406Sopenharmony_ci DBG(1, "Try the `microtek2' backend instead. \n"); 2071141cc406Sopenharmony_ci DBG(1, "\n"); 2072141cc406Sopenharmony_ci DBG(1, "\n"); 2073141cc406Sopenharmony_ci DBG(1, "\n"); 2074141cc406Sopenharmony_ci } 2075141cc406Sopenharmony_ci } 2076141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2077141cc406Sopenharmony_ci } 2078141cc406Sopenharmony_ci if (forcewarn) { 2079141cc406Sopenharmony_ci /* force debugging on, to encourage user to send in a report */ 2080141cc406Sopenharmony_ci#ifndef NDEBUG 2081141cc406Sopenharmony_ci DBG_LEVEL = 1; 2082141cc406Sopenharmony_ci#endif 2083141cc406Sopenharmony_ci DBG(1, "\n"); 2084141cc406Sopenharmony_ci DBG(1, "\n"); 2085141cc406Sopenharmony_ci DBG(1, "\n"); 2086141cc406Sopenharmony_ci DBG(1, "========== Congratulations! ==========\n"); 2087141cc406Sopenharmony_ci DBG(1, "Your scanner appears to be supported \n"); 2088141cc406Sopenharmony_ci DBG(1, "by the microtek backend. However, it \n"); 2089141cc406Sopenharmony_ci DBG(1, "has never been tried before, and some \n"); 2090141cc406Sopenharmony_ci DBG(1, "parameters are bound to be wrong. \n"); 2091141cc406Sopenharmony_ci DBG(1, "\n"); 2092141cc406Sopenharmony_ci DBG(1, "Please send the scanner inquiry log in\n"); 2093141cc406Sopenharmony_ci DBG(1, "its entirety to mtek-bugs@mir.com and \n"); 2094141cc406Sopenharmony_ci DBG(1, "include a description of the scanner, \n"); 2095141cc406Sopenharmony_ci DBG(1, "including the base optical resolution.\n"); 2096141cc406Sopenharmony_ci DBG(1, "\n"); 2097141cc406Sopenharmony_ci DBG(1, "You'll find complete instructions for \n"); 2098141cc406Sopenharmony_ci DBG(1, "submitting an error/debug log in the \n"); 2099141cc406Sopenharmony_ci DBG(1, "'sane-microtek' man-page. \n"); 2100141cc406Sopenharmony_ci DBG(1, "\n"); 2101141cc406Sopenharmony_ci DBG(1, "\n"); 2102141cc406Sopenharmony_ci DBG(1, "\n"); 2103141cc406Sopenharmony_ci } 2104141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2105141cc406Sopenharmony_ci } 2106141cc406Sopenharmony_ci DBG(15, "id_microtek: not microtek: %d, %d, %d\n", 2107141cc406Sopenharmony_ci strncmp("MICROTEK", (char *)&(result[8]), 8), 2108141cc406Sopenharmony_ci strncmp(" ", (char *)&(result[8]), 8), 2109141cc406Sopenharmony_ci result[62]); 2110141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2111141cc406Sopenharmony_ci} 2112141cc406Sopenharmony_ci 2113141cc406Sopenharmony_ci 2114141cc406Sopenharmony_ci 2115141cc406Sopenharmony_ci/********************************************************************/ 2116141cc406Sopenharmony_ci/* Try to attach a device as a Microtek scanner */ 2117141cc406Sopenharmony_ci/********************************************************************/ 2118141cc406Sopenharmony_cistatic SANE_Status 2119141cc406Sopenharmony_ciattach_scanner(const char *devicename, Microtek_Device **devp) 2120141cc406Sopenharmony_ci{ 2121141cc406Sopenharmony_ci Microtek_Device *dev; 2122141cc406Sopenharmony_ci int sfd; 2123141cc406Sopenharmony_ci size_t size; 2124141cc406Sopenharmony_ci unsigned char result[0x60]; 2125141cc406Sopenharmony_ci SANE_Status status; 2126141cc406Sopenharmony_ci char *model_string; 2127141cc406Sopenharmony_ci uint8_t inquiry[] = { 0x12, 0, 0, 0, 0x60, 0 }; 2128141cc406Sopenharmony_ci 2129141cc406Sopenharmony_ci DBG(15,"attach_scanner: %s\n", devicename); 2130141cc406Sopenharmony_ci /* check if device is already known... */ 2131141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) { 2132141cc406Sopenharmony_ci if (strcmp(dev->sane.name, devicename) == 0) { 2133141cc406Sopenharmony_ci if (devp) *devp = dev; 2134141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2135141cc406Sopenharmony_ci } 2136141cc406Sopenharmony_ci } 2137141cc406Sopenharmony_ci 2138141cc406Sopenharmony_ci /* open scsi device... */ 2139141cc406Sopenharmony_ci DBG(20, "attach_scanner: opening %s\n", devicename); 2140141cc406Sopenharmony_ci if (sanei_scsi_open(devicename, &sfd, sense_handler, NULL) != 0) { 2141141cc406Sopenharmony_ci DBG(20, "attach_scanner: open failed\n"); 2142141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2143141cc406Sopenharmony_ci } 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci /* say hello... */ 2146141cc406Sopenharmony_ci DBG(20, "attach_scanner: sending INQUIRY\n"); 2147141cc406Sopenharmony_ci size = sizeof(result); 2148141cc406Sopenharmony_ci status = sanei_scsi_cmd(sfd, inquiry, sizeof(inquiry), result, &size); 2149141cc406Sopenharmony_ci sanei_scsi_close (sfd); 2150141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size != 0x60) { 2151141cc406Sopenharmony_ci DBG(20, "attach_scanner: inquiry failed (%s)\n", sane_strstatus (status)); 2152141cc406Sopenharmony_ci return status; 2153141cc406Sopenharmony_ci } 2154141cc406Sopenharmony_ci 2155141cc406Sopenharmony_ci if (id_microtek(result, &model_string) != SANE_STATUS_GOOD) { 2156141cc406Sopenharmony_ci DBG(15, "attach_scanner: device doesn't look like a Microtek scanner."); 2157141cc406Sopenharmony_ci if (DBG_LEVEL >= 5) dump_suspect_inquiry(result); 2158141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2159141cc406Sopenharmony_ci } 2160141cc406Sopenharmony_ci 2161141cc406Sopenharmony_ci dev=malloc(sizeof(*dev)); 2162141cc406Sopenharmony_ci if (!dev) return SANE_STATUS_NO_MEM; 2163141cc406Sopenharmony_ci memset(dev, 0, sizeof(*dev)); 2164141cc406Sopenharmony_ci 2165141cc406Sopenharmony_ci parse_inquiry(&(dev->info), result); 2166141cc406Sopenharmony_ci if (DBG_LEVEL > 0) dump_inquiry(&(dev->info), result); 2167141cc406Sopenharmony_ci 2168141cc406Sopenharmony_ci /* initialize dev structure */ 2169141cc406Sopenharmony_ci dev->sane.name = strdup(devicename); 2170141cc406Sopenharmony_ci dev->sane.vendor = "Microtek"; 2171141cc406Sopenharmony_ci dev->sane.model = strdup(model_string); 2172141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 2173141cc406Sopenharmony_ci 2174141cc406Sopenharmony_ci /* link into device list... */ 2175141cc406Sopenharmony_ci ++num_devices; 2176141cc406Sopenharmony_ci dev->next = first_dev; 2177141cc406Sopenharmony_ci first_dev = dev; 2178141cc406Sopenharmony_ci if (devp) *devp = dev; 2179141cc406Sopenharmony_ci 2180141cc406Sopenharmony_ci DBG(15, "attach_scanner: happy.\n"); 2181141cc406Sopenharmony_ci 2182141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2183141cc406Sopenharmony_ci} 2184141cc406Sopenharmony_ci 2185141cc406Sopenharmony_ci 2186141cc406Sopenharmony_ci/********************************************************************/ 2187141cc406Sopenharmony_ci/* Attach a scanner (convenience wrapper for find_scanners...) */ 2188141cc406Sopenharmony_ci/********************************************************************/ 2189141cc406Sopenharmony_cistatic SANE_Status 2190141cc406Sopenharmony_ciattach_one (const char *dev) 2191141cc406Sopenharmony_ci{ 2192141cc406Sopenharmony_ci attach_scanner (dev, 0); 2193141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2194141cc406Sopenharmony_ci} 2195141cc406Sopenharmony_ci 2196141cc406Sopenharmony_ci 2197141cc406Sopenharmony_ci 2198141cc406Sopenharmony_ci 2199141cc406Sopenharmony_ci/********************************************************************/ 2200141cc406Sopenharmony_ci/* End a scan, and clean up afterwards */ 2201141cc406Sopenharmony_ci/********************************************************************/ 2202141cc406Sopenharmony_cistatic SANE_Status end_scan(Microtek_Scanner *s, SANE_Status ostat) 2203141cc406Sopenharmony_ci{ 2204141cc406Sopenharmony_ci SANE_Status status; 2205141cc406Sopenharmony_ci 2206141cc406Sopenharmony_ci DBG(15, "end_scan...\n"); 2207141cc406Sopenharmony_ci if (s->scanning) { 2208141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 2209141cc406Sopenharmony_ci /* stop the scanner */ 2210141cc406Sopenharmony_ci if (s->scan_started) { 2211141cc406Sopenharmony_ci status = stop_scan(s); 2212141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2213141cc406Sopenharmony_ci DBG(23, "end_scan: OY! on stop_scan\n"); 2214141cc406Sopenharmony_ci s->scan_started = SANE_FALSE; 2215141cc406Sopenharmony_ci } 2216141cc406Sopenharmony_ci /* close the SCSI device */ 2217141cc406Sopenharmony_ci if (s->sfd != -1) { 2218141cc406Sopenharmony_ci sanei_scsi_close(s->sfd); 2219141cc406Sopenharmony_ci s->sfd = -1; 2220141cc406Sopenharmony_ci } 2221141cc406Sopenharmony_ci /* free the buffers we malloc'ed */ 2222141cc406Sopenharmony_ci if (s->scsi_buffer != NULL) { 2223141cc406Sopenharmony_ci free(s->scsi_buffer); 2224141cc406Sopenharmony_ci s->scsi_buffer = NULL; 2225141cc406Sopenharmony_ci } 2226141cc406Sopenharmony_ci if (s->rb != NULL) { 2227141cc406Sopenharmony_ci ring_free(s->rb); 2228141cc406Sopenharmony_ci s->rb = NULL; 2229141cc406Sopenharmony_ci } 2230141cc406Sopenharmony_ci } 2231141cc406Sopenharmony_ci /* if this -was- pass 3, or cancel, then we must be done */ 2232141cc406Sopenharmony_ci if ((s->this_pass == 3) || (s->cancel)) 2233141cc406Sopenharmony_ci s->this_pass = 0; 2234141cc406Sopenharmony_ci return ostat; 2235141cc406Sopenharmony_ci} 2236141cc406Sopenharmony_ci 2237141cc406Sopenharmony_ci 2238141cc406Sopenharmony_ci 2239141cc406Sopenharmony_ci/********************************************************************/ 2240141cc406Sopenharmony_ci/********************************************************************/ 2241141cc406Sopenharmony_ci/***** Scan-time operations *****/ 2242141cc406Sopenharmony_ci/********************************************************************/ 2243141cc406Sopenharmony_ci/********************************************************************/ 2244141cc406Sopenharmony_ci 2245141cc406Sopenharmony_ci 2246141cc406Sopenharmony_ci/* number of lines of calibration data returned by scanner */ 2247141cc406Sopenharmony_ci#define STRIPS 12 /* well, that's what it seems to be for the E6 */ 2248141cc406Sopenharmony_ci 2249141cc406Sopenharmony_ci 2250141cc406Sopenharmony_ci/* simple comparison for the qsort below */ 2251141cc406Sopenharmony_ci 2252141cc406Sopenharmony_cistatic int comparo(const void *a, const void *b) 2253141cc406Sopenharmony_ci{ 2254141cc406Sopenharmony_ci return (*(const int *)a - *(const int *)b); 2255141cc406Sopenharmony_ci} 2256141cc406Sopenharmony_ci 2257141cc406Sopenharmony_ci 2258141cc406Sopenharmony_ci/* extract values from scanlines and sort */ 2259141cc406Sopenharmony_ci 2260141cc406Sopenharmony_cistatic void sort_values(int *result, uint8_t *scanline[], int pix) 2261141cc406Sopenharmony_ci{ 2262141cc406Sopenharmony_ci int i; 2263141cc406Sopenharmony_ci for (i=0; i<STRIPS; i++) result[i] = (scanline[i])[pix]; 2264141cc406Sopenharmony_ci qsort(result, STRIPS, sizeof(result[0]), comparo); 2265141cc406Sopenharmony_ci} 2266141cc406Sopenharmony_ci 2267141cc406Sopenharmony_ci 2268141cc406Sopenharmony_ci/********************************************************************/ 2269141cc406Sopenharmony_ci/* Calculate the calibration data. */ 2270141cc406Sopenharmony_ci/* This seems to be, for each pixel of each R/G/B ccd, the average */ 2271141cc406Sopenharmony_ci/* of the STRIPS# values read by the scanner, presumably off some */ 2272141cc406Sopenharmony_ci/* blank spot under the cover. */ 2273141cc406Sopenharmony_ci/* The raw scanner data does indeed resemble the intensity profile */ 2274141cc406Sopenharmony_ci/* of a lamp. */ 2275141cc406Sopenharmony_ci/* The sort is used to calc the median, which is used to remove */ 2276141cc406Sopenharmony_ci/* outliers in the data; maybe from dust under the cover? */ 2277141cc406Sopenharmony_ci/********************************************************************/ 2278141cc406Sopenharmony_ci 2279141cc406Sopenharmony_ci 2280141cc406Sopenharmony_cistatic void calc_calibration(uint8_t *caldata, uint8_t *scanline[], 2281141cc406Sopenharmony_ci int pixels) 2282141cc406Sopenharmony_ci{ 2283141cc406Sopenharmony_ci int i,j; 2284141cc406Sopenharmony_ci int sorted[STRIPS]; 2285141cc406Sopenharmony_ci 2286141cc406Sopenharmony_ci DBG(23, ".calc_calibration...\n"); 2287141cc406Sopenharmony_ci for (i=0; i<pixels; i++) { 2288141cc406Sopenharmony_ci int q1, q3; 2289141cc406Sopenharmony_ci int bot, top; 2290141cc406Sopenharmony_ci int sum = 0; 2291141cc406Sopenharmony_ci int count = 0; 2292141cc406Sopenharmony_ci 2293141cc406Sopenharmony_ci sort_values(sorted, scanline, i); 2294141cc406Sopenharmony_ci q1 = sorted[STRIPS / 4]; /* first quartile */ 2295141cc406Sopenharmony_ci q3 = sorted[STRIPS * 3 / 4]; /* third quartile */ 2296141cc406Sopenharmony_ci bot = q1 - 3 * (q3 - q1) / 2; /* quick'n'easy bounds */ 2297141cc406Sopenharmony_ci top = q3 + 3 * (q3 - q1) / 2; 2298141cc406Sopenharmony_ci 2299141cc406Sopenharmony_ci for (j=0; j<STRIPS; j++) { 2300141cc406Sopenharmony_ci if ((sorted[j] >= bot) && (sorted[j] <= top)) { 2301141cc406Sopenharmony_ci sum += sorted[j]; 2302141cc406Sopenharmony_ci count++; 2303141cc406Sopenharmony_ci } 2304141cc406Sopenharmony_ci } 2305141cc406Sopenharmony_ci if (count) 2306141cc406Sopenharmony_ci caldata[i] = (sum + (count / 2)) / count; 2307141cc406Sopenharmony_ci else { 2308141cc406Sopenharmony_ci DBG(23, "zero: i=%d b/t=%d/%d ", i, bot, top); 2309141cc406Sopenharmony_ci if (DBG_LEVEL >= 23) { 2310141cc406Sopenharmony_ci MDBG_INIT(""); 2311141cc406Sopenharmony_ci for (j=0; j<STRIPS; j++) MDBG_ADD(" %3d", sorted[j]); 2312141cc406Sopenharmony_ci MDBG_FINISH(23); 2313141cc406Sopenharmony_ci } 2314141cc406Sopenharmony_ci caldata[i] = 0; 2315141cc406Sopenharmony_ci } 2316141cc406Sopenharmony_ci } 2317141cc406Sopenharmony_ci} 2318141cc406Sopenharmony_ci 2319141cc406Sopenharmony_ci 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci/********************************************************************/ 2322141cc406Sopenharmony_ci/* Calibrate scanner CCD, the "real" way. */ 2323141cc406Sopenharmony_ci/* This stuff is not documented in the command set, but this is */ 2324141cc406Sopenharmony_ci/* what Microtek's TWAIN driver seems to do, more or less, on an */ 2325141cc406Sopenharmony_ci/* E6 at least. What other scanners will do this??? */ 2326141cc406Sopenharmony_ci/********************************************************************/ 2327141cc406Sopenharmony_ci 2328141cc406Sopenharmony_ci 2329141cc406Sopenharmony_cistatic SANE_Status do_real_calibrate(Microtek_Scanner *s) 2330141cc406Sopenharmony_ci{ 2331141cc406Sopenharmony_ci SANE_Status status, statusA; 2332141cc406Sopenharmony_ci SANE_Int busy, linewidth, lines; 2333141cc406Sopenharmony_ci size_t buffsize; 2334141cc406Sopenharmony_ci uint8_t *input, *scanline[STRIPS], *combuff; 2335141cc406Sopenharmony_ci uint8_t letter; 2336141cc406Sopenharmony_ci int i, spot; 2337141cc406Sopenharmony_ci int nmax, ntoget, nleft; 2338141cc406Sopenharmony_ci 2339141cc406Sopenharmony_ci DBG(10, "do_real_calibrate...\n"); 2340141cc406Sopenharmony_ci 2341141cc406Sopenharmony_ci /* tell scanner to read it's little chart */ 2342141cc406Sopenharmony_ci if ((status = start_calibration(s)) != SANE_STATUS_GOOD) return status; 2343141cc406Sopenharmony_ci if ((status = get_scan_status(s, &busy, &linewidth, &lines)) 2344141cc406Sopenharmony_ci != SANE_STATUS_GOOD) { 2345141cc406Sopenharmony_ci DBG(23, "do_real_cal: get_scan_status failed!\n"); 2346141cc406Sopenharmony_ci return status; 2347141cc406Sopenharmony_ci } 2348141cc406Sopenharmony_ci /* make room for data in and data out */ 2349141cc406Sopenharmony_ci input = calloc(STRIPS * 3 * linewidth, sizeof(input[0])); 2350141cc406Sopenharmony_ci combuff = calloc(linewidth + 6, sizeof(combuff[0])); 2351141cc406Sopenharmony_ci if ((input == NULL) || (combuff == NULL)) { 2352141cc406Sopenharmony_ci DBG(23, "do_real_cal: bad calloc %p %p\n", 2353141cc406Sopenharmony_ci (void *) input, (void *) combuff); 2354141cc406Sopenharmony_ci free(input); 2355141cc406Sopenharmony_ci free(combuff); 2356141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2357141cc406Sopenharmony_ci } 2358141cc406Sopenharmony_ci /* read STRIPS lines of R, G, B ccd data */ 2359141cc406Sopenharmony_ci nmax = SCSI_BUFF_SIZE / (3 * linewidth); 2360141cc406Sopenharmony_ci DBG(23, "do_real_cal: getting data (max=%d)\n", nmax); 2361141cc406Sopenharmony_ci for (nleft = STRIPS, spot=0; 2362141cc406Sopenharmony_ci nleft > 0; 2363141cc406Sopenharmony_ci nleft -= ntoget, spot += buffsize) { 2364141cc406Sopenharmony_ci ntoget = (nleft > nmax) ? nmax : nleft; 2365141cc406Sopenharmony_ci buffsize = ntoget * 3 * linewidth; 2366141cc406Sopenharmony_ci DBG(23, "...nleft %d toget %d size %lu spot %d input+spot %p\n", 2367141cc406Sopenharmony_ci nleft, ntoget, (u_long) buffsize, spot, (void *) (input+spot)); 2368141cc406Sopenharmony_ci if ((statusA = read_scan_data(s, ntoget, input+spot, &buffsize)) 2369141cc406Sopenharmony_ci != SANE_STATUS_GOOD) { 2370141cc406Sopenharmony_ci DBG(23, "...read scan failed\n"); 2371141cc406Sopenharmony_ci break; 2372141cc406Sopenharmony_ci } 2373141cc406Sopenharmony_ci } 2374141cc406Sopenharmony_ci status = stop_scan(s); 2375141cc406Sopenharmony_ci if ((statusA != SANE_STATUS_GOOD) || (status != SANE_STATUS_GOOD)) { 2376141cc406Sopenharmony_ci free(input); 2377141cc406Sopenharmony_ci free(combuff); 2378141cc406Sopenharmony_ci return ((statusA != SANE_STATUS_GOOD) ? statusA : status); 2379141cc406Sopenharmony_ci } 2380141cc406Sopenharmony_ci /* calculate calibration data for each element and download */ 2381141cc406Sopenharmony_ci for (letter = 'R'; letter != 'X'; ) { 2382141cc406Sopenharmony_ci DBG(23, "do_real_calibrate: working on %c\n", letter); 2383141cc406Sopenharmony_ci for (spot=0, i=0; spot < linewidth * STRIPS * 3; spot += linewidth) { 2384141cc406Sopenharmony_ci if (input[spot+1] == letter) { 2385141cc406Sopenharmony_ci DBG(23, " found %d (at %d)\n", i, spot); 2386141cc406Sopenharmony_ci if (i >= STRIPS) { 2387141cc406Sopenharmony_ci DBG(23, "WHOA!!! %i have already been found!\n", i); 2388141cc406Sopenharmony_ci break; 2389141cc406Sopenharmony_ci } 2390141cc406Sopenharmony_ci scanline[i] = &(input[spot+2]); 2391141cc406Sopenharmony_ci i++; 2392141cc406Sopenharmony_ci } 2393141cc406Sopenharmony_ci } 2394141cc406Sopenharmony_ci calc_calibration(combuff + 8, scanline, linewidth - 2); 2395141cc406Sopenharmony_ci if ((status = download_calibration(s, combuff, letter, linewidth)) 2396141cc406Sopenharmony_ci != SANE_STATUS_GOOD) { 2397141cc406Sopenharmony_ci DBG(23, "...download_calibration failed\n"); 2398141cc406Sopenharmony_ci free(input); 2399141cc406Sopenharmony_ci free(combuff); 2400141cc406Sopenharmony_ci return status; 2401141cc406Sopenharmony_ci } 2402141cc406Sopenharmony_ci switch (letter) { 2403141cc406Sopenharmony_ci case 'R': letter = 'G'; break; 2404141cc406Sopenharmony_ci case 'G': letter = 'B'; break; 2405141cc406Sopenharmony_ci case 'B': 2406141cc406Sopenharmony_ci default: letter = 'X'; break; 2407141cc406Sopenharmony_ci } 2408141cc406Sopenharmony_ci } 2409141cc406Sopenharmony_ci /* clean up */ 2410141cc406Sopenharmony_ci free(input); 2411141cc406Sopenharmony_ci free(combuff); 2412141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2413141cc406Sopenharmony_ci} 2414141cc406Sopenharmony_ci 2415141cc406Sopenharmony_ci 2416141cc406Sopenharmony_ci 2417141cc406Sopenharmony_ci 2418141cc406Sopenharmony_ci/********************************************************************/ 2419141cc406Sopenharmony_ci/* Cause scanner to calibrate, but don't really scan anything */ 2420141cc406Sopenharmony_ci/* (i.e. do everything but read data) */ 2421141cc406Sopenharmony_ci/********************************************************************/ 2422141cc406Sopenharmony_cistatic SANE_Status do_precalibrate(SANE_Handle handle) 2423141cc406Sopenharmony_ci{ 2424141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 2425141cc406Sopenharmony_ci SANE_Status status, statusA; 2426141cc406Sopenharmony_ci SANE_Int busy, linewidth, lines; 2427141cc406Sopenharmony_ci 2428141cc406Sopenharmony_ci DBG(10, "do_precalibrate...\n"); 2429141cc406Sopenharmony_ci 2430141cc406Sopenharmony_ci if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status; 2431141cc406Sopenharmony_ci { 2432141cc406Sopenharmony_ci SANE_Int y1 = s->y1; 2433141cc406Sopenharmony_ci SANE_Int y2 = s->y2; 2434141cc406Sopenharmony_ci /* some small range, but large enough to cause the scanner 2435141cc406Sopenharmony_ci to think it'll scan *something*... */ 2436141cc406Sopenharmony_ci s->y1 = 0; 2437141cc406Sopenharmony_ci s->y2 = 2438141cc406Sopenharmony_ci (s->resolution > s->dev->info.base_resolution) ? 2439141cc406Sopenharmony_ci 4 : 4 * s->dev->info.base_resolution / s->resolution; 2440141cc406Sopenharmony_ci status = scanning_frame(s); 2441141cc406Sopenharmony_ci s->y1 = y1; 2442141cc406Sopenharmony_ci s->y2 = y2; 2443141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 2444141cc406Sopenharmony_ci } 2445141cc406Sopenharmony_ci 2446141cc406Sopenharmony_ci if (s->dev->info.source_options & 2447141cc406Sopenharmony_ci (MI_SRC_FEED_BT | MI_SRC_HAS_TRANS | 2448141cc406Sopenharmony_ci MI_SRC_FEED_SUPP | MI_SRC_HAS_FEED)) { /* ZZZZZZZZZZZ */ 2449141cc406Sopenharmony_ci if ((status = accessory(s)) != SANE_STATUS_GOOD) return status; 2450141cc406Sopenharmony_ci } 2451141cc406Sopenharmony_ci if ((status = mode_select(s)) != SANE_STATUS_GOOD) return status; 2452141cc406Sopenharmony_ci /* why would we even try if this were not true?... */ 2453141cc406Sopenharmony_ci /*if (s->dev->info.extra_cap & MI_EXCAP_DIS_RECAL) */ 2454141cc406Sopenharmony_ci { 2455141cc406Sopenharmony_ci SANE_Bool allow_calibrate = s->allow_calibrate; 2456141cc406Sopenharmony_ci s->allow_calibrate = SANE_TRUE; 2457141cc406Sopenharmony_ci status = mode_select_1(s); 2458141cc406Sopenharmony_ci s->allow_calibrate = allow_calibrate; 2459141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 2460141cc406Sopenharmony_ci } 2461141cc406Sopenharmony_ci 2462141cc406Sopenharmony_ci if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status; 2463141cc406Sopenharmony_ci if ((status = start_scan(s)) != SANE_STATUS_GOOD) return status; 2464141cc406Sopenharmony_ci if ((statusA = get_scan_status(s, &busy, 2465141cc406Sopenharmony_ci &linewidth, &lines)) != SANE_STATUS_GOOD) { 2466141cc406Sopenharmony_ci DBG(10, "do_precalibrate: get_scan_status fails\n"); 2467141cc406Sopenharmony_ci } 2468141cc406Sopenharmony_ci if ((status = stop_scan(s)) != SANE_STATUS_GOOD) return status; 2469141cc406Sopenharmony_ci if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status; 2470141cc406Sopenharmony_ci DBG(10, "do_precalibrate done.\n"); 2471141cc406Sopenharmony_ci if (statusA != SANE_STATUS_GOOD) 2472141cc406Sopenharmony_ci return statusA; 2473141cc406Sopenharmony_ci else 2474141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2475141cc406Sopenharmony_ci} 2476141cc406Sopenharmony_ci 2477141cc406Sopenharmony_ci 2478141cc406Sopenharmony_ci/********************************************************************/ 2479141cc406Sopenharmony_ci/* Calibrate scanner, if necessary; record results */ 2480141cc406Sopenharmony_ci/********************************************************************/ 2481141cc406Sopenharmony_cistatic SANE_Status finagle_precal(SANE_Handle handle) 2482141cc406Sopenharmony_ci{ 2483141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 2484141cc406Sopenharmony_ci SANE_Status status; 2485141cc406Sopenharmony_ci int match; 2486141cc406Sopenharmony_ci 2487141cc406Sopenharmony_ci /* try to check if scanner has been reset */ 2488141cc406Sopenharmony_ci /* if so, calibrate it 2489141cc406Sopenharmony_ci (either for real, or via a fake scan, with calibration */ 2490141cc406Sopenharmony_ci /* (but only bother if you *could* disable calibration) */ 2491141cc406Sopenharmony_ci DBG(23, "finagle_precal...\n"); 2492141cc406Sopenharmony_ci if ((s->do_clever_precal) || (s->do_real_calib)) { 2493141cc406Sopenharmony_ci if ((status = compare_mode_sense(s, &match)) != SANE_STATUS_GOOD) 2494141cc406Sopenharmony_ci return status; 2495141cc406Sopenharmony_ci if (((s->do_real_calib) && (!s->calib_once)) || /* user want recal */ 2496141cc406Sopenharmony_ci (!match) || /* or, possible reset */ 2497141cc406Sopenharmony_ci ((s->mode == MS_MODE_COLOR) && /* or, other weirdness */ 2498141cc406Sopenharmony_ci (s->precal_record < MS_PRECAL_COLOR)) || 2499141cc406Sopenharmony_ci ((s->mode == MS_MODE_COLOR) && 2500141cc406Sopenharmony_ci (s->expandedresolution) && 2501141cc406Sopenharmony_ci (s->precal_record < MS_PRECAL_EXP_COLOR))) { 2502141cc406Sopenharmony_ci DBG(23, "finagle_precal: must precalibrate!\n"); 2503141cc406Sopenharmony_ci s->precal_record = MS_PRECAL_NONE; 2504141cc406Sopenharmony_ci if (s->do_real_calib) { /* do a real calibration if allowed */ 2505141cc406Sopenharmony_ci if ((status = do_real_calibrate(s)) != SANE_STATUS_GOOD) 2506141cc406Sopenharmony_ci return status; 2507141cc406Sopenharmony_ci } else if (s->do_clever_precal) {/* otherwise do the fake-scan version */ 2508141cc406Sopenharmony_ci if ((status = do_precalibrate(s)) != SANE_STATUS_GOOD) 2509141cc406Sopenharmony_ci return status; 2510141cc406Sopenharmony_ci } 2511141cc406Sopenharmony_ci if (s->mode == MS_MODE_COLOR) { 2512141cc406Sopenharmony_ci if (s->expandedresolution) 2513141cc406Sopenharmony_ci s->precal_record = MS_PRECAL_EXP_COLOR; 2514141cc406Sopenharmony_ci else 2515141cc406Sopenharmony_ci s->precal_record = MS_PRECAL_COLOR; 2516141cc406Sopenharmony_ci } else 2517141cc406Sopenharmony_ci s->precal_record = MS_PRECAL_GRAY; 2518141cc406Sopenharmony_ci } else 2519141cc406Sopenharmony_ci DBG(23, "finagle_precal: no precalibrate necessary.\n"); 2520141cc406Sopenharmony_ci } 2521141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2522141cc406Sopenharmony_ci} 2523141cc406Sopenharmony_ci 2524141cc406Sopenharmony_ci 2525141cc406Sopenharmony_ci 2526141cc406Sopenharmony_ci/********************************************************************/ 2527141cc406Sopenharmony_ci/* Set pass-dependent parameters (for 3-pass color scans) */ 2528141cc406Sopenharmony_ci/********************************************************************/ 2529141cc406Sopenharmony_cistatic void 2530141cc406Sopenharmony_ciset_pass_parameters (SANE_Handle handle) 2531141cc406Sopenharmony_ci{ 2532141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 2533141cc406Sopenharmony_ci 2534141cc406Sopenharmony_ci if (s->threepasscolor) { 2535141cc406Sopenharmony_ci s->this_pass += 1; 2536141cc406Sopenharmony_ci DBG(23, "set_pass_parameters: three-pass, on %d\n", s->this_pass); 2537141cc406Sopenharmony_ci switch (s->this_pass) { 2538141cc406Sopenharmony_ci case 1: 2539141cc406Sopenharmony_ci s->filter = MS_FILT_RED; 2540141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RED; 2541141cc406Sopenharmony_ci s->params.last_frame = SANE_FALSE; 2542141cc406Sopenharmony_ci break; 2543141cc406Sopenharmony_ci case 2: 2544141cc406Sopenharmony_ci s->filter = MS_FILT_GREEN; 2545141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GREEN; 2546141cc406Sopenharmony_ci s->params.last_frame = SANE_FALSE; 2547141cc406Sopenharmony_ci break; 2548141cc406Sopenharmony_ci case 3: 2549141cc406Sopenharmony_ci s->filter = MS_FILT_BLUE; 2550141cc406Sopenharmony_ci s->params.format = SANE_FRAME_BLUE; 2551141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 2552141cc406Sopenharmony_ci break; 2553141cc406Sopenharmony_ci default: 2554141cc406Sopenharmony_ci s->filter = MS_FILT_CLEAR; 2555141cc406Sopenharmony_ci DBG(23, "set_pass_parameters: What?!? pass %d = filter?\n", 2556141cc406Sopenharmony_ci s->this_pass); 2557141cc406Sopenharmony_ci break; 2558141cc406Sopenharmony_ci } 2559141cc406Sopenharmony_ci } else 2560141cc406Sopenharmony_ci s->this_pass = 0; 2561141cc406Sopenharmony_ci} 2562141cc406Sopenharmony_ci 2563141cc406Sopenharmony_ci 2564141cc406Sopenharmony_ci 2565141cc406Sopenharmony_ci/********************************************************************/ 2566141cc406Sopenharmony_ci/********************************************************************/ 2567141cc406Sopenharmony_ci/***** Packing functions *****/ 2568141cc406Sopenharmony_ci/***** ...process raw scanner bytes, and shove into *****/ 2569141cc406Sopenharmony_ci/***** the ring buffer *****/ 2570141cc406Sopenharmony_ci/********************************************************************/ 2571141cc406Sopenharmony_ci/********************************************************************/ 2572141cc406Sopenharmony_ci 2573141cc406Sopenharmony_ci 2574141cc406Sopenharmony_ci/********************************************************************/ 2575141cc406Sopenharmony_ci/* Process flat (byte-by-byte) data */ 2576141cc406Sopenharmony_ci/********************************************************************/ 2577141cc406Sopenharmony_cistatic SANE_Status pack_flat_data(Microtek_Scanner *s, size_t nlines) 2578141cc406Sopenharmony_ci{ 2579141cc406Sopenharmony_ci SANE_Status status; 2580141cc406Sopenharmony_ci ring_buffer *rb = s->rb; 2581141cc406Sopenharmony_ci size_t nbytes = nlines * rb->bpl; 2582141cc406Sopenharmony_ci 2583141cc406Sopenharmony_ci size_t start = (rb->head_complete + rb->complete_count) % rb->size; 2584141cc406Sopenharmony_ci size_t max_xfer = 2585141cc406Sopenharmony_ci (start < rb->head_complete) ? 2586141cc406Sopenharmony_ci (rb->head_complete - start) : 2587141cc406Sopenharmony_ci (rb->size - start + rb->head_complete); 2588141cc406Sopenharmony_ci size_t length = MIN(nbytes, max_xfer); 2589141cc406Sopenharmony_ci 2590141cc406Sopenharmony_ci if (nbytes > max_xfer) { 2591141cc406Sopenharmony_ci DBG(23, "pack_flat: must expand ring, %lu + %lu\n", 2592141cc406Sopenharmony_ci (u_long)rb->size, (u_long)(nbytes - max_xfer)); 2593141cc406Sopenharmony_ci status = ring_expand(rb, (nbytes - max_xfer)); 2594141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 2595141cc406Sopenharmony_ci } 2596141cc406Sopenharmony_ci 2597141cc406Sopenharmony_ci if (s->doexpansion) { 2598141cc406Sopenharmony_ci unsigned int line, bit; 2599141cc406Sopenharmony_ci SANE_Byte *sb, *db, byte; 2600141cc406Sopenharmony_ci 2601141cc406Sopenharmony_ci size_t pos; 2602141cc406Sopenharmony_ci 2603141cc406Sopenharmony_ci sb = s->scsi_buffer; 2604141cc406Sopenharmony_ci db = rb->base; 2605141cc406Sopenharmony_ci pos = start; 2606141cc406Sopenharmony_ci 2607141cc406Sopenharmony_ci if (!(s->multibit)) { 2608141cc406Sopenharmony_ci for (line=0; line<nlines; line++) { 2609141cc406Sopenharmony_ci size_t i; 2610141cc406Sopenharmony_ci double x1, x2, n1, n2; 2611141cc406Sopenharmony_ci for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2); 2612141cc406Sopenharmony_ci i < rb->bpl; 2613141cc406Sopenharmony_ci i++) { 2614141cc406Sopenharmony_ci byte = 0; 2615141cc406Sopenharmony_ci for (bit=0; 2616141cc406Sopenharmony_ci bit < 8; 2617141cc406Sopenharmony_ci bit++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { 2618141cc406Sopenharmony_ci /* #define getbit(byte, index) (((byte)>>(index))&1) */ 2619141cc406Sopenharmony_ci byte |= 2620141cc406Sopenharmony_ci (( 2621141cc406Sopenharmony_ci (x2 == n2) ? 2622141cc406Sopenharmony_ci (((sb[(int)n1 / 8])>>(7 - ((int)n1) % 8))&1) : 2623141cc406Sopenharmony_ci (((double)(((sb[(int)n1/8])>>(7-(int)n1%8))&1) * (n2 - x1) + 2624141cc406Sopenharmony_ci (double)(((sb[(int)n2/8])>>(7-(int)n2%8))&1) * (x2 - n2) 2625141cc406Sopenharmony_ci ) / s->exp_aspect) 2626141cc406Sopenharmony_ci ) > 0.5) << (7 - bit); 2627141cc406Sopenharmony_ci } 2628141cc406Sopenharmony_ci db[pos] = byte; 2629141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2630141cc406Sopenharmony_ci } 2631141cc406Sopenharmony_ci sb += s->pixel_bpl; 2632141cc406Sopenharmony_ci } 2633141cc406Sopenharmony_ci } else { /* multibit scan (8 is assumed!) */ 2634141cc406Sopenharmony_ci for (line=0; line<nlines; line++) { 2635141cc406Sopenharmony_ci double x1, x2, n1, n2; 2636141cc406Sopenharmony_ci int i; 2637141cc406Sopenharmony_ci for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2); 2638141cc406Sopenharmony_ci i < s->dest_ppl; 2639141cc406Sopenharmony_ci i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { 2640141cc406Sopenharmony_ci db[pos] = 2641141cc406Sopenharmony_ci (x2 == n2) ? 2642141cc406Sopenharmony_ci sb[(int)n1] : 2643141cc406Sopenharmony_ci (int)(((double)sb[(int)n1] * (n2 - x1) + 2644141cc406Sopenharmony_ci (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect); 2645141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2646141cc406Sopenharmony_ci } 2647141cc406Sopenharmony_ci sb += s->pixel_bpl; 2648141cc406Sopenharmony_ci } 2649141cc406Sopenharmony_ci } 2650141cc406Sopenharmony_ci } else { 2651141cc406Sopenharmony_ci /* adjust for rollover!!! */ 2652141cc406Sopenharmony_ci if ((start + length) < rb->size) { 2653141cc406Sopenharmony_ci memcpy(rb->base + start, s->scsi_buffer, length); 2654141cc406Sopenharmony_ci } else { 2655141cc406Sopenharmony_ci size_t chunk1 = rb->size - start; 2656141cc406Sopenharmony_ci size_t chunk2 = length - chunk1; 2657141cc406Sopenharmony_ci memcpy(rb->base + start, s->scsi_buffer, chunk1); 2658141cc406Sopenharmony_ci memcpy(rb->base, s->scsi_buffer + chunk1, chunk2); 2659141cc406Sopenharmony_ci } 2660141cc406Sopenharmony_ci } 2661141cc406Sopenharmony_ci rb->complete_count += length; 2662141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2663141cc406Sopenharmony_ci} 2664141cc406Sopenharmony_ci 2665141cc406Sopenharmony_ci 2666141cc406Sopenharmony_ci/********************************************************************/ 2667141cc406Sopenharmony_ci/* Process sequential R-G-B scan lines (who uses this??? ) */ 2668141cc406Sopenharmony_ci/********************************************************************/ 2669141cc406Sopenharmony_cistatic SANE_Status 2670141cc406Sopenharmony_cipack_seqrgb_data (Microtek_Scanner *s, size_t nlines) 2671141cc406Sopenharmony_ci{ 2672141cc406Sopenharmony_ci ring_buffer *rb = s->rb; 2673141cc406Sopenharmony_ci unsigned int seg; 2674141cc406Sopenharmony_ci SANE_Byte *db = rb->base; 2675141cc406Sopenharmony_ci SANE_Byte *sb = s->scsi_buffer; 2676141cc406Sopenharmony_ci size_t completed; 2677141cc406Sopenharmony_ci size_t spot; 2678141cc406Sopenharmony_ci SANE_Byte id; 2679141cc406Sopenharmony_ci 2680141cc406Sopenharmony_ci { 2681141cc406Sopenharmony_ci size_t ar, ag, ab; /* allowed additions */ 2682141cc406Sopenharmony_ci size_t dr, dg, db; /* additions which will occur */ 2683141cc406Sopenharmony_ci SANE_Status status; 2684141cc406Sopenharmony_ci 2685141cc406Sopenharmony_ci dr = dg = db = nlines * rb->bpl; 2686141cc406Sopenharmony_ci ar = rb->size - (rb->complete_count + rb->red_extra * 3); 2687141cc406Sopenharmony_ci ag = rb->size - (rb->complete_count + rb->green_extra * 3); 2688141cc406Sopenharmony_ci ab = rb->size - (rb->complete_count + rb->blue_extra * 3); 2689141cc406Sopenharmony_ci DBG(23, "pack_seq: dr/ar: %lu/%lu dg/ag: %lu/%lu db/ab: %lu/%lu\n", 2690141cc406Sopenharmony_ci (u_long)dr, (u_long)ar, 2691141cc406Sopenharmony_ci (u_long)dg, (u_long)ag, 2692141cc406Sopenharmony_ci (u_long)db, (u_long)ab); 2693141cc406Sopenharmony_ci if ((dr > ar) || 2694141cc406Sopenharmony_ci (dg > ag) || 2695141cc406Sopenharmony_ci (db > ab)) { 2696141cc406Sopenharmony_ci size_t increase = 0; 2697141cc406Sopenharmony_ci if (dr > ar) increase = (dr - ar); 2698141cc406Sopenharmony_ci if (dg > ag) increase = MAX(increase, (dg - ag)); 2699141cc406Sopenharmony_ci if (db > ab) increase = MAX(increase, (db - ab)); 2700141cc406Sopenharmony_ci DBG(23, "pack_seq: must expand ring, %lu + %lu\n", 2701141cc406Sopenharmony_ci (u_long)rb->size, (u_long)increase); 2702141cc406Sopenharmony_ci status = ring_expand(rb, increase); 2703141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 2704141cc406Sopenharmony_ci } 2705141cc406Sopenharmony_ci } 2706141cc406Sopenharmony_ci 2707141cc406Sopenharmony_ci for (seg = 0, id = 0; seg < nlines * 3; seg++, id = (id+1)%3) { 2708141cc406Sopenharmony_ci switch (id) { 2709141cc406Sopenharmony_ci case 0: spot = rb->tail_red; break; 2710141cc406Sopenharmony_ci case 1: spot = rb->tail_green; break; 2711141cc406Sopenharmony_ci case 2: spot = rb->tail_blue; break; 2712141cc406Sopenharmony_ci default: 2713141cc406Sopenharmony_ci DBG(18, "pack_seq: missing scanline RGB header!\n"); 2714141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2715141cc406Sopenharmony_ci } 2716141cc406Sopenharmony_ci 2717141cc406Sopenharmony_ci if (s->doexpansion) { 2718141cc406Sopenharmony_ci int i; 2719141cc406Sopenharmony_ci double x1, x2, n1, n2; 2720141cc406Sopenharmony_ci for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2); 2721141cc406Sopenharmony_ci i < s->dest_ppl; 2722141cc406Sopenharmony_ci i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { 2723141cc406Sopenharmony_ci db[spot] = 2724141cc406Sopenharmony_ci (x2 == n2) ? 2725141cc406Sopenharmony_ci sb[(int)n1] : 2726141cc406Sopenharmony_ci (int)(((double)sb[(int)n1] * (n2 - x1) + 2727141cc406Sopenharmony_ci (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect); 2728141cc406Sopenharmony_ci if ((spot += 3) >= rb->size) spot -= rb->size; 2729141cc406Sopenharmony_ci } 2730141cc406Sopenharmony_ci sb += s->ppl; 2731141cc406Sopenharmony_ci } else { 2732141cc406Sopenharmony_ci size_t i; 2733141cc406Sopenharmony_ci for (i=0; i < rb->ppl; i++) { 2734141cc406Sopenharmony_ci db[spot] = *sb; 2735141cc406Sopenharmony_ci sb++; 2736141cc406Sopenharmony_ci if ((spot += 3) >= rb->size) spot -= rb->size; 2737141cc406Sopenharmony_ci } 2738141cc406Sopenharmony_ci } 2739141cc406Sopenharmony_ci 2740141cc406Sopenharmony_ci switch (id) { 2741141cc406Sopenharmony_ci case 0: rb->tail_red = spot; rb->red_extra += rb->ppl; break; 2742141cc406Sopenharmony_ci case 1: rb->tail_green = spot; rb->green_extra += rb->ppl; break; 2743141cc406Sopenharmony_ci case 2: rb->tail_blue = spot; rb->blue_extra += rb->ppl; break; 2744141cc406Sopenharmony_ci } 2745141cc406Sopenharmony_ci } 2746141cc406Sopenharmony_ci 2747141cc406Sopenharmony_ci completed = MIN(rb->red_extra, MIN(rb->green_extra, rb->blue_extra)); 2748141cc406Sopenharmony_ci rb->complete_count += completed * 3; /* 3 complete bytes per pixel! */ 2749141cc406Sopenharmony_ci rb->red_extra -= completed; 2750141cc406Sopenharmony_ci rb->green_extra -= completed; 2751141cc406Sopenharmony_ci rb->blue_extra -= completed; 2752141cc406Sopenharmony_ci 2753141cc406Sopenharmony_ci DBG(18, "pack_seq: extra r: %lu g: %lu b: %lu\n", 2754141cc406Sopenharmony_ci (u_long)rb->red_extra, 2755141cc406Sopenharmony_ci (u_long)rb->green_extra, 2756141cc406Sopenharmony_ci (u_long)rb->blue_extra); 2757141cc406Sopenharmony_ci DBG(18, "pack_seq: completed: %lu complete: %lu\n", 2758141cc406Sopenharmony_ci (u_long)completed, (u_long)rb->complete_count); 2759141cc406Sopenharmony_ci 2760141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2761141cc406Sopenharmony_ci} 2762141cc406Sopenharmony_ci 2763141cc406Sopenharmony_ci 2764141cc406Sopenharmony_ci/********************************************************************/ 2765141cc406Sopenharmony_ci/* Process non-sequential R,G, and B scan-lines */ 2766141cc406Sopenharmony_ci/********************************************************************/ 2767141cc406Sopenharmony_cistatic SANE_Status 2768141cc406Sopenharmony_cipack_goofyrgb_data(Microtek_Scanner *s, size_t nlines) 2769141cc406Sopenharmony_ci{ 2770141cc406Sopenharmony_ci ring_buffer *rb = s->rb; 2771141cc406Sopenharmony_ci unsigned int seg; /* , i;*/ 2772141cc406Sopenharmony_ci SANE_Byte *db; 2773141cc406Sopenharmony_ci SANE_Byte *sb = s->scsi_buffer; 2774141cc406Sopenharmony_ci size_t completed; 2775141cc406Sopenharmony_ci size_t spot; 2776141cc406Sopenharmony_ci SANE_Byte id; 2777141cc406Sopenharmony_ci 2778141cc406Sopenharmony_ci /* prescan to decide if ring should be expanded */ 2779141cc406Sopenharmony_ci { 2780141cc406Sopenharmony_ci size_t ar, ag, ab; /* allowed additions */ 2781141cc406Sopenharmony_ci size_t dr, dg, db; /* additions which will occur */ 2782141cc406Sopenharmony_ci SANE_Status status; 2783141cc406Sopenharmony_ci SANE_Byte *pt; 2784141cc406Sopenharmony_ci 2785141cc406Sopenharmony_ci for (dr = dg = db = 0, seg = 0, pt = s->scsi_buffer + 1; 2786141cc406Sopenharmony_ci seg < nlines * 3; 2787141cc406Sopenharmony_ci seg++, pt += s->ppl + 2) { 2788141cc406Sopenharmony_ci switch (*pt) { 2789141cc406Sopenharmony_ci case 'R': dr += rb->bpl; break; 2790141cc406Sopenharmony_ci case 'G': dg += rb->bpl; break; 2791141cc406Sopenharmony_ci case 'B': db += rb->bpl; break; 2792141cc406Sopenharmony_ci } 2793141cc406Sopenharmony_ci } 2794141cc406Sopenharmony_ci ar = rb->size - (rb->complete_count + rb->red_extra * 3); 2795141cc406Sopenharmony_ci ag = rb->size - (rb->complete_count + rb->green_extra * 3); 2796141cc406Sopenharmony_ci ab = rb->size - (rb->complete_count + rb->blue_extra * 3); 2797141cc406Sopenharmony_ci DBG(23, "pack_goofy: dr/ar: %lu/%lu dg/ag: %lu/%lu db/ab: %lu/%lu\n", 2798141cc406Sopenharmony_ci (u_long)dr, (u_long)ar, 2799141cc406Sopenharmony_ci (u_long)dg, (u_long)ag, 2800141cc406Sopenharmony_ci (u_long)db, (u_long)ab); 2801141cc406Sopenharmony_ci /* >, or >= ???????? */ 2802141cc406Sopenharmony_ci if ((dr > ar) || 2803141cc406Sopenharmony_ci (dg > ag) || 2804141cc406Sopenharmony_ci (db > ab)) { 2805141cc406Sopenharmony_ci size_t increase = 0; 2806141cc406Sopenharmony_ci if (dr > ar) increase = (dr - ar); 2807141cc406Sopenharmony_ci if (dg > ag) increase = MAX(increase, (dg - ag)); 2808141cc406Sopenharmony_ci if (db > ab) increase = MAX(increase, (db - ab)); 2809141cc406Sopenharmony_ci DBG(23, "pack_goofy: must expand ring, %lu + %lu\n", 2810141cc406Sopenharmony_ci (u_long)rb->size, (u_long)increase); 2811141cc406Sopenharmony_ci status = ring_expand(rb, increase); 2812141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 2813141cc406Sopenharmony_ci } 2814141cc406Sopenharmony_ci } 2815141cc406Sopenharmony_ci 2816141cc406Sopenharmony_ci db = rb->base; 2817141cc406Sopenharmony_ci for (seg = 0; seg < nlines * 3; seg++) { 2818141cc406Sopenharmony_ci sb++; /* skip first byte in line (two byte header) */ 2819141cc406Sopenharmony_ci id = *sb; 2820141cc406Sopenharmony_ci switch (id) { 2821141cc406Sopenharmony_ci case 'R': spot = rb->tail_red; break; 2822141cc406Sopenharmony_ci case 'G': spot = rb->tail_green; break; 2823141cc406Sopenharmony_ci case 'B': spot = rb->tail_blue; break; 2824141cc406Sopenharmony_ci default: 2825141cc406Sopenharmony_ci DBG(18, "pack_goofy: missing scanline RGB header!\n"); 2826141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2827141cc406Sopenharmony_ci } 2828141cc406Sopenharmony_ci sb++; /* skip the other header byte */ 2829141cc406Sopenharmony_ci 2830141cc406Sopenharmony_ci if (s->doexpansion) { 2831141cc406Sopenharmony_ci int i; 2832141cc406Sopenharmony_ci double x1, x2, n1, n2; 2833141cc406Sopenharmony_ci for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2); 2834141cc406Sopenharmony_ci i < s->dest_ppl; 2835141cc406Sopenharmony_ci i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { 2836141cc406Sopenharmony_ci db[spot] = 2837141cc406Sopenharmony_ci (x2 == n2) ? 2838141cc406Sopenharmony_ci sb[(int)n1] : 2839141cc406Sopenharmony_ci (int)(((double)sb[(int)n1] * (n2 - x1) + 2840141cc406Sopenharmony_ci (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect); 2841141cc406Sopenharmony_ci if ((spot += 3) >= rb->size) spot -= rb->size; 2842141cc406Sopenharmony_ci } 2843141cc406Sopenharmony_ci sb += s->ppl; 2844141cc406Sopenharmony_ci } else { 2845141cc406Sopenharmony_ci unsigned int i; 2846141cc406Sopenharmony_ci for (i=0; i < rb->ppl; i++) { 2847141cc406Sopenharmony_ci db[spot] = *sb; 2848141cc406Sopenharmony_ci sb++; 2849141cc406Sopenharmony_ci if ((spot += 3) >= rb->size) spot -= rb->size; 2850141cc406Sopenharmony_ci } 2851141cc406Sopenharmony_ci } 2852141cc406Sopenharmony_ci switch (id) { 2853141cc406Sopenharmony_ci case 'R': rb->tail_red = spot; rb->red_extra += rb->ppl; break; 2854141cc406Sopenharmony_ci case 'G': rb->tail_green = spot; rb->green_extra += rb->ppl; break; 2855141cc406Sopenharmony_ci case 'B': rb->tail_blue = spot; rb->blue_extra += rb->ppl; break; 2856141cc406Sopenharmony_ci } 2857141cc406Sopenharmony_ci } 2858141cc406Sopenharmony_ci 2859141cc406Sopenharmony_ci completed = MIN(rb->red_extra, MIN(rb->green_extra, rb->blue_extra)); 2860141cc406Sopenharmony_ci rb->complete_count += completed * 3; /* 3 complete bytes per pixel! */ 2861141cc406Sopenharmony_ci rb->red_extra -= completed; 2862141cc406Sopenharmony_ci rb->green_extra -= completed; 2863141cc406Sopenharmony_ci rb->blue_extra -= completed; 2864141cc406Sopenharmony_ci 2865141cc406Sopenharmony_ci DBG(18, "pack_goofy: extra r: %lu g: %lu b: %lu\n", 2866141cc406Sopenharmony_ci (u_long)rb->red_extra, 2867141cc406Sopenharmony_ci (u_long)rb->green_extra, 2868141cc406Sopenharmony_ci (u_long)rb->blue_extra); 2869141cc406Sopenharmony_ci DBG(18, "pack_goofy: completed: %lu complete: %lu\n", 2870141cc406Sopenharmony_ci (u_long)completed, (u_long)rb->complete_count); 2871141cc406Sopenharmony_ci 2872141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2873141cc406Sopenharmony_ci} 2874141cc406Sopenharmony_ci 2875141cc406Sopenharmony_ci 2876141cc406Sopenharmony_ci 2877141cc406Sopenharmony_ci/********************************************************************/ 2878141cc406Sopenharmony_ci/* Process R1R2-G1G2-B1B2 double pixels (AGFA StudioStar) */ 2879141cc406Sopenharmony_ci/********************************************************************/ 2880141cc406Sopenharmony_ci 2881141cc406Sopenharmony_cistatic SANE_Status 2882141cc406Sopenharmony_cipack_seq2r2g2b_data(Microtek_Scanner *s, size_t nlines) 2883141cc406Sopenharmony_ci{ 2884141cc406Sopenharmony_ci SANE_Status status; 2885141cc406Sopenharmony_ci ring_buffer *rb = s->rb; 2886141cc406Sopenharmony_ci size_t nbytes = nlines * rb->bpl; 2887141cc406Sopenharmony_ci 2888141cc406Sopenharmony_ci size_t start = (rb->head_complete + rb->complete_count) % rb->size; 2889141cc406Sopenharmony_ci size_t max_xfer = 2890141cc406Sopenharmony_ci (start < rb->head_complete) ? 2891141cc406Sopenharmony_ci (rb->head_complete - start) : 2892141cc406Sopenharmony_ci (rb->size - start + rb->head_complete); 2893141cc406Sopenharmony_ci size_t length = MIN(nbytes, max_xfer); 2894141cc406Sopenharmony_ci 2895141cc406Sopenharmony_ci if (nbytes > max_xfer) { 2896141cc406Sopenharmony_ci DBG(23, "pack_2r2g2b: must expand ring, %lu + %lu\n", 2897141cc406Sopenharmony_ci (u_long)rb->size, (u_long)(nbytes - max_xfer)); 2898141cc406Sopenharmony_ci status = ring_expand(rb, (nbytes - max_xfer)); 2899141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 2900141cc406Sopenharmony_ci } 2901141cc406Sopenharmony_ci { 2902141cc406Sopenharmony_ci unsigned int line; 2903141cc406Sopenharmony_ci int p; 2904141cc406Sopenharmony_ci size_t pos = start; 2905141cc406Sopenharmony_ci SANE_Byte *sb = s->scsi_buffer; 2906141cc406Sopenharmony_ci SANE_Byte *db = rb->base; 2907141cc406Sopenharmony_ci 2908141cc406Sopenharmony_ci for (line = 0; line < nlines; line++) { 2909141cc406Sopenharmony_ci for (p = 0; p < s->dest_ppl; p += 2){ 2910141cc406Sopenharmony_ci /* first pixel */ 2911141cc406Sopenharmony_ci db[pos] = sb[0]; 2912141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; /* watch out for ringbuff end? */ 2913141cc406Sopenharmony_ci db[pos] = sb[2]; 2914141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2915141cc406Sopenharmony_ci db[pos] = sb[4]; 2916141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2917141cc406Sopenharmony_ci /* second pixel */ 2918141cc406Sopenharmony_ci db[pos] = sb[1]; 2919141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2920141cc406Sopenharmony_ci db[pos] = sb[3]; 2921141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2922141cc406Sopenharmony_ci db[pos] = sb[5]; 2923141cc406Sopenharmony_ci if (++pos >= rb->size) pos = 0; 2924141cc406Sopenharmony_ci sb += 6; 2925141cc406Sopenharmony_ci } 2926141cc406Sopenharmony_ci } 2927141cc406Sopenharmony_ci } 2928141cc406Sopenharmony_ci rb->complete_count += length; 2929141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2930141cc406Sopenharmony_ci} 2931141cc406Sopenharmony_ci 2932141cc406Sopenharmony_ci 2933141cc406Sopenharmony_ci 2934141cc406Sopenharmony_ci/********************************************************************/ 2935141cc406Sopenharmony_ci/********************************************************************/ 2936141cc406Sopenharmony_ci/***** the basic scanning chunks for sane_read() *****/ 2937141cc406Sopenharmony_ci/********************************************************************/ 2938141cc406Sopenharmony_ci/********************************************************************/ 2939141cc406Sopenharmony_ci 2940141cc406Sopenharmony_ci 2941141cc406Sopenharmony_ci/********************************************************************/ 2942141cc406Sopenharmony_ci/* Request bytes from scanner (and put in scsi_buffer) */ 2943141cc406Sopenharmony_ci/********************************************************************/ 2944141cc406Sopenharmony_cistatic SANE_Status 2945141cc406Sopenharmony_ciread_from_scanner (Microtek_Scanner *s, int *nlines) 2946141cc406Sopenharmony_ci{ 2947141cc406Sopenharmony_ci SANE_Status status; 2948141cc406Sopenharmony_ci SANE_Int busy, linewidth, remaining; 2949141cc406Sopenharmony_ci size_t buffsize; 2950141cc406Sopenharmony_ci 2951141cc406Sopenharmony_ci DBG(23, "read_from_scanner...\n"); 2952141cc406Sopenharmony_ci if (s->unscanned_lines > 0) { 2953141cc406Sopenharmony_ci status = get_scan_status(s, &busy, &linewidth, &remaining); 2954141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 2955141cc406Sopenharmony_ci DBG(18, "read_from_scanner: bad get_scan_status!\n"); 2956141cc406Sopenharmony_ci return status; 2957141cc406Sopenharmony_ci } 2958141cc406Sopenharmony_ci DBG(18, "read_from_scanner: gss busy, linewidth, remaining: %d, %d, %d\n", 2959141cc406Sopenharmony_ci busy, linewidth, remaining); 2960141cc406Sopenharmony_ci } else { 2961141cc406Sopenharmony_ci DBG(18, "read_from_scanner: no gss/no unscanned\n"); 2962141cc406Sopenharmony_ci remaining = 0; 2963141cc406Sopenharmony_ci } 2964141cc406Sopenharmony_ci 2965141cc406Sopenharmony_ci *nlines = MIN(remaining, s->max_scsi_lines); 2966141cc406Sopenharmony_ci DBG(18, "sane_read: max_scsi: %d, rem: %d, nlines: %d\n", 2967141cc406Sopenharmony_ci s->max_scsi_lines, remaining, *nlines); 2968141cc406Sopenharmony_ci 2969141cc406Sopenharmony_ci /* grab them bytes! (only if the scanner still has bytes to give...) */ 2970141cc406Sopenharmony_ci if (*nlines > 0) { 2971141cc406Sopenharmony_ci buffsize = *nlines * (s->pixel_bpl + s->header_bpl);/* == "* linewidth" */ 2972141cc406Sopenharmony_ci status = read_scan_data(s, *nlines, s->scsi_buffer, &buffsize); 2973141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 2974141cc406Sopenharmony_ci DBG(18, "sane_read: bad read_scan_data!\n"); 2975141cc406Sopenharmony_ci return status; 2976141cc406Sopenharmony_ci } 2977141cc406Sopenharmony_ci s->unscanned_lines -= *nlines; 2978141cc406Sopenharmony_ci DBG(18, "sane_read: buffsize: %lu, unscanned: %d\n", 2979141cc406Sopenharmony_ci (u_long) buffsize, s->unscanned_lines); 2980141cc406Sopenharmony_ci } 2981141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2982141cc406Sopenharmony_ci} 2983141cc406Sopenharmony_ci 2984141cc406Sopenharmony_ci 2985141cc406Sopenharmony_ci 2986141cc406Sopenharmony_ci/********************************************************************/ 2987141cc406Sopenharmony_ci/* Process scanner bytes, and shove in ring_buffer */ 2988141cc406Sopenharmony_ci/********************************************************************/ 2989141cc406Sopenharmony_cistatic SANE_Status 2990141cc406Sopenharmony_cipack_into_ring(Microtek_Scanner *s, int nlines) 2991141cc406Sopenharmony_ci{ 2992141cc406Sopenharmony_ci SANE_Status status; 2993141cc406Sopenharmony_ci 2994141cc406Sopenharmony_ci DBG(23, "pack_into_ring...\n"); 2995141cc406Sopenharmony_ci switch (s->line_format) { 2996141cc406Sopenharmony_ci case MS_LNFMT_FLAT: 2997141cc406Sopenharmony_ci status = pack_flat_data(s, nlines); break; 2998141cc406Sopenharmony_ci case MS_LNFMT_SEQ_RGB: 2999141cc406Sopenharmony_ci status = pack_seqrgb_data(s, nlines); break; 3000141cc406Sopenharmony_ci case MS_LNFMT_GOOFY_RGB: 3001141cc406Sopenharmony_ci status = pack_goofyrgb_data(s, nlines); break; 3002141cc406Sopenharmony_ci case MS_LNFMT_SEQ_2R2G2B: 3003141cc406Sopenharmony_ci status = pack_seq2r2g2b_data(s, nlines); break; 3004141cc406Sopenharmony_ci default: 3005141cc406Sopenharmony_ci status = SANE_STATUS_JAMMED; 3006141cc406Sopenharmony_ci } 3007141cc406Sopenharmony_ci return status; 3008141cc406Sopenharmony_ci} 3009141cc406Sopenharmony_ci 3010141cc406Sopenharmony_ci 3011141cc406Sopenharmony_ci 3012141cc406Sopenharmony_ci/********************************************************************/ 3013141cc406Sopenharmony_ci/* Pack processed image bytes into frontend destination buffer */ 3014141cc406Sopenharmony_ci/********************************************************************/ 3015141cc406Sopenharmony_cistatic SANE_Int 3016141cc406Sopenharmony_cipack_into_dest(SANE_Byte *dest_buffer, size_t dest_length, ring_buffer *rb) 3017141cc406Sopenharmony_ci{ 3018141cc406Sopenharmony_ci size_t ret_length = MIN(rb->complete_count, dest_length); 3019141cc406Sopenharmony_ci 3020141cc406Sopenharmony_ci DBG(23, "pack_into_dest...\n"); 3021141cc406Sopenharmony_ci DBG(23, "pack_into_dest: rl: %lu sz: %lu hc: %lu\n", 3022141cc406Sopenharmony_ci (u_long)ret_length, (u_long)rb->size, (u_long)rb->head_complete); 3023141cc406Sopenharmony_ci /* adjust for rollover!!! */ 3024141cc406Sopenharmony_ci if ((rb->head_complete + ret_length) < rb->size) { 3025141cc406Sopenharmony_ci memcpy(dest_buffer, rb->base + rb->head_complete, ret_length); 3026141cc406Sopenharmony_ci rb->head_complete += ret_length; 3027141cc406Sopenharmony_ci } else { 3028141cc406Sopenharmony_ci size_t chunk1 = rb->size - rb->head_complete; 3029141cc406Sopenharmony_ci size_t chunk2 = ret_length - chunk1; 3030141cc406Sopenharmony_ci memcpy(dest_buffer, rb->base + rb->head_complete, chunk1); 3031141cc406Sopenharmony_ci memcpy(dest_buffer + chunk1, rb->base, chunk2); 3032141cc406Sopenharmony_ci rb->head_complete = chunk2; 3033141cc406Sopenharmony_ci } 3034141cc406Sopenharmony_ci rb->complete_count -= ret_length; 3035141cc406Sopenharmony_ci return ret_length; 3036141cc406Sopenharmony_ci} 3037141cc406Sopenharmony_ci 3038141cc406Sopenharmony_ci 3039141cc406Sopenharmony_ci 3040141cc406Sopenharmony_ci/********************************************************************/ 3041141cc406Sopenharmony_ci/********************************************************************/ 3042141cc406Sopenharmony_ci/****** "Registered" SANE API Functions *****************************/ 3043141cc406Sopenharmony_ci/********************************************************************/ 3044141cc406Sopenharmony_ci/********************************************************************/ 3045141cc406Sopenharmony_ci 3046141cc406Sopenharmony_ci 3047141cc406Sopenharmony_ci/********************************************************************/ 3048141cc406Sopenharmony_ci/* sane_init() */ 3049141cc406Sopenharmony_ci/********************************************************************/ 3050141cc406Sopenharmony_ciSANE_Status 3051141cc406Sopenharmony_cisane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) 3052141cc406Sopenharmony_ci{ 3053141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 3054141cc406Sopenharmony_ci size_t len; 3055141cc406Sopenharmony_ci FILE *fp; 3056141cc406Sopenharmony_ci 3057141cc406Sopenharmony_ci (void) authorize; 3058141cc406Sopenharmony_ci DBG_INIT(); 3059141cc406Sopenharmony_ci DBG(1, "sane_init: MICROTEK says hello! (v%d.%d.%d)\n", 3060141cc406Sopenharmony_ci MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH); 3061141cc406Sopenharmony_ci /* return the SANE version we got compiled under */ 3062141cc406Sopenharmony_ci if (version_code) 3063141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0); 3064141cc406Sopenharmony_ci 3065141cc406Sopenharmony_ci /* parse config file */ 3066141cc406Sopenharmony_ci fp = sanei_config_open (MICROTEK_CONFIG_FILE); 3067141cc406Sopenharmony_ci if (!fp) { 3068141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 3069141cc406Sopenharmony_ci DBG(1, "sane_init: missing config file '%s'\n", MICROTEK_CONFIG_FILE); 3070141cc406Sopenharmony_ci attach_scanner("/dev/scanner", 0); 3071141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3072141cc406Sopenharmony_ci } 3073141cc406Sopenharmony_ci while (sanei_config_read(dev_name, sizeof (dev_name), fp)) { 3074141cc406Sopenharmony_ci DBG(23, "sane_init: config-> %s\n", dev_name); 3075141cc406Sopenharmony_ci if (dev_name[0] == '#') continue; /* ignore comments */ 3076141cc406Sopenharmony_ci if (!(strncmp("noprecal", dev_name, 8))) { 3077141cc406Sopenharmony_ci DBG(23, 3078141cc406Sopenharmony_ci "sane_init: Clever Precalibration will be forcibly disabled...\n"); 3079141cc406Sopenharmony_ci inhibit_clever_precal = SANE_TRUE; 3080141cc406Sopenharmony_ci continue; 3081141cc406Sopenharmony_ci } 3082141cc406Sopenharmony_ci if (!(strncmp("norealcal", dev_name, 9))) { 3083141cc406Sopenharmony_ci DBG(23, 3084141cc406Sopenharmony_ci "sane_init: Real calibration will be forcibly disabled...\n"); 3085141cc406Sopenharmony_ci inhibit_real_calib = SANE_TRUE; 3086141cc406Sopenharmony_ci continue; 3087141cc406Sopenharmony_ci } 3088141cc406Sopenharmony_ci len = strlen (dev_name); 3089141cc406Sopenharmony_ci if (!len) continue; /* ignore empty lines */ 3090141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 3091141cc406Sopenharmony_ci } 3092141cc406Sopenharmony_ci fclose (fp); 3093141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3094141cc406Sopenharmony_ci} 3095141cc406Sopenharmony_ci 3096141cc406Sopenharmony_ci 3097141cc406Sopenharmony_ci 3098141cc406Sopenharmony_ci/********************************************************************/ 3099141cc406Sopenharmony_ci/* sane_get_devices */ 3100141cc406Sopenharmony_ci/********************************************************************/ 3101141cc406Sopenharmony_ciSANE_Status 3102141cc406Sopenharmony_cisane_get_devices(const SANE_Device ***device_list, 3103141cc406Sopenharmony_ci SANE_Bool local_only) 3104141cc406Sopenharmony_ci{ 3105141cc406Sopenharmony_ci Microtek_Device *dev; 3106141cc406Sopenharmony_ci int i; 3107141cc406Sopenharmony_ci 3108141cc406Sopenharmony_ci (void) local_only; 3109141cc406Sopenharmony_ci DBG(10, "sane_get_devices\n"); 3110141cc406Sopenharmony_ci /* we keep an internal copy */ 3111141cc406Sopenharmony_ci if (devlist) 3112141cc406Sopenharmony_ci free(devlist); /* hmm, free it if we want a new one, I guess. YYYYY*/ 3113141cc406Sopenharmony_ci 3114141cc406Sopenharmony_ci devlist = malloc((num_devices + 1) * sizeof(devlist[0])); 3115141cc406Sopenharmony_ci if (!devlist) return SANE_STATUS_NO_MEM; 3116141cc406Sopenharmony_ci 3117141cc406Sopenharmony_ci for (i=0, dev=first_dev; i < num_devices; dev = dev->next) 3118141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 3119141cc406Sopenharmony_ci devlist[i++] = 0; 3120141cc406Sopenharmony_ci 3121141cc406Sopenharmony_ci *device_list = devlist; 3122141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3123141cc406Sopenharmony_ci} 3124141cc406Sopenharmony_ci 3125141cc406Sopenharmony_ci 3126141cc406Sopenharmony_ci 3127141cc406Sopenharmony_ci/********************************************************************/ 3128141cc406Sopenharmony_ci/* sane_open */ 3129141cc406Sopenharmony_ci/********************************************************************/ 3130141cc406Sopenharmony_ciSANE_Status 3131141cc406Sopenharmony_cisane_open(SANE_String_Const devicename, 3132141cc406Sopenharmony_ci SANE_Handle *handle) 3133141cc406Sopenharmony_ci{ 3134141cc406Sopenharmony_ci Microtek_Scanner *scanner; 3135141cc406Sopenharmony_ci Microtek_Device *dev; 3136141cc406Sopenharmony_ci SANE_Status status; 3137141cc406Sopenharmony_ci 3138141cc406Sopenharmony_ci DBG(10, "sane_open\n"); 3139141cc406Sopenharmony_ci /* find device... */ 3140141cc406Sopenharmony_ci DBG(23, "sane_open: find device...\n"); 3141141cc406Sopenharmony_ci if (devicename[0]) { 3142141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) { 3143141cc406Sopenharmony_ci if (strcmp(dev->sane.name, devicename) == 0) 3144141cc406Sopenharmony_ci break; 3145141cc406Sopenharmony_ci } 3146141cc406Sopenharmony_ci if (!dev) { /* not in list, try manually... */ 3147141cc406Sopenharmony_ci status = attach_scanner(devicename, &dev); 3148141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) return status; 3149141cc406Sopenharmony_ci } 3150141cc406Sopenharmony_ci } else { /* no device specified, so use first */ 3151141cc406Sopenharmony_ci dev = first_dev; 3152141cc406Sopenharmony_ci } 3153141cc406Sopenharmony_ci if (!dev) return SANE_STATUS_INVAL; 3154141cc406Sopenharmony_ci 3155141cc406Sopenharmony_ci /* create a scanner... */ 3156141cc406Sopenharmony_ci DBG(23, "sane_open: create scanner...\n"); 3157141cc406Sopenharmony_ci scanner = malloc(sizeof(*scanner)); 3158141cc406Sopenharmony_ci if (!scanner) return SANE_STATUS_NO_MEM; 3159141cc406Sopenharmony_ci memset(scanner, 0, sizeof(*scanner)); 3160141cc406Sopenharmony_ci 3161141cc406Sopenharmony_ci /* initialize scanner dependent stuff */ 3162141cc406Sopenharmony_ci DBG(23, "sane_open: initialize scanner dependent stuff...\n"); 3163141cc406Sopenharmony_ci /* ZZZZZZZZZZZZZZ */ 3164141cc406Sopenharmony_ci scanner->unit_type = 3165141cc406Sopenharmony_ci (dev->info.unit_type & MI_UNIT_PIXELS) ? MS_UNIT_PIXELS : MS_UNIT_18INCH; 3166141cc406Sopenharmony_ci scanner->res_type = 3167141cc406Sopenharmony_ci (dev->info.res_step & MI_RESSTEP_1PER) ? MS_RES_1PER : MS_RES_5PER; 3168141cc406Sopenharmony_ci scanner->midtone_support = 3169141cc406Sopenharmony_ci (dev->info.enhance_cap & MI_ENH_CAP_MIDTONE) ? SANE_TRUE : SANE_FALSE; 3170141cc406Sopenharmony_ci scanner->paper_length = 3171141cc406Sopenharmony_ci (scanner->unit_type == MS_UNIT_PIXELS) ? 3172141cc406Sopenharmony_ci dev->info.max_y : 3173141cc406Sopenharmony_ci (SANE_Int)((double)dev->info.max_y * 8.0 / 3174141cc406Sopenharmony_ci (double)dev->info.base_resolution); 3175141cc406Sopenharmony_ci /* 3176141cc406Sopenharmony_ci (SANE_Int)(SANE_UNFIX(dev->info.max_y) * dev->info.base_resolution) : 3177141cc406Sopenharmony_ci (SANE_Int)(SANE_UNFIX(dev->info.max_y) * 8); 3178141cc406Sopenharmony_ci ZZZZZZZ */ 3179141cc406Sopenharmony_ci scanner->bright_r = 0; 3180141cc406Sopenharmony_ci scanner->bright_g = 0; 3181141cc406Sopenharmony_ci scanner->bright_b = 0; 3182141cc406Sopenharmony_ci 3183141cc406Sopenharmony_ci /* calibration shenanigans */ 3184141cc406Sopenharmony_ci if ((dev->info.extra_cap & MI_EXCAP_DIS_RECAL) && 3185141cc406Sopenharmony_ci (!(inhibit_real_calib))) { 3186141cc406Sopenharmony_ci DBG(23, "sane_open: Real calibration enabled.\n"); 3187141cc406Sopenharmony_ci scanner->allow_calibrate = SANE_FALSE; 3188141cc406Sopenharmony_ci scanner->do_real_calib = SANE_TRUE; 3189141cc406Sopenharmony_ci scanner->do_clever_precal = SANE_FALSE; 3190141cc406Sopenharmony_ci } else if ((dev->info.extra_cap & MI_EXCAP_DIS_RECAL) && 3191141cc406Sopenharmony_ci (!(inhibit_clever_precal))) { 3192141cc406Sopenharmony_ci DBG(23, "sane_open: Clever precalibration enabled.\n"); 3193141cc406Sopenharmony_ci scanner->allow_calibrate = SANE_FALSE; 3194141cc406Sopenharmony_ci scanner->do_real_calib = SANE_FALSE; 3195141cc406Sopenharmony_ci scanner->do_clever_precal = SANE_TRUE; 3196141cc406Sopenharmony_ci } else { 3197141cc406Sopenharmony_ci DBG(23, "sane_open: All calibration routines disabled.\n"); 3198141cc406Sopenharmony_ci scanner->allow_calibrate = SANE_TRUE; 3199141cc406Sopenharmony_ci scanner->do_real_calib = SANE_FALSE; 3200141cc406Sopenharmony_ci scanner->do_clever_precal = SANE_FALSE; 3201141cc406Sopenharmony_ci } 3202141cc406Sopenharmony_ci 3203141cc406Sopenharmony_ci scanner->onepass = (dev->info.modes & MI_MODES_ONEPASS); 3204141cc406Sopenharmony_ci scanner->allowbacktrack = SANE_TRUE; /* ??? XXXXXXX */ 3205141cc406Sopenharmony_ci scanner->reversecolors = SANE_FALSE; 3206141cc406Sopenharmony_ci scanner->fastprescan = SANE_FALSE; 3207141cc406Sopenharmony_ci scanner->bits_per_color = 8; 3208141cc406Sopenharmony_ci 3209141cc406Sopenharmony_ci /* init gamma tables */ 3210141cc406Sopenharmony_ci if (dev->info.max_lookup_size) { 3211141cc406Sopenharmony_ci int j, v, max_entry; 3212141cc406Sopenharmony_ci DBG(23, "sane_open: init gamma tables...\n"); 3213141cc406Sopenharmony_ci scanner->gamma_entries = dev->info.max_lookup_size; 3214141cc406Sopenharmony_ci scanner->gamma_entry_size = dev->info.gamma_size; 3215141cc406Sopenharmony_ci scanner->gamma_bit_depth = dev->info.max_gamma_bit_depth; 3216141cc406Sopenharmony_ci max_entry = (1 << scanner->gamma_bit_depth) - 1; 3217141cc406Sopenharmony_ci scanner->gamma_entry_range.min = 0; 3218141cc406Sopenharmony_ci scanner->gamma_entry_range.max = max_entry; 3219141cc406Sopenharmony_ci scanner->gamma_entry_range.quant = 1; 3220141cc406Sopenharmony_ci 3221141cc406Sopenharmony_ci scanner->gray_lut = calloc(scanner->gamma_entries, 3222141cc406Sopenharmony_ci sizeof(scanner->gray_lut[0])); 3223141cc406Sopenharmony_ci scanner->red_lut = calloc(scanner->gamma_entries, 3224141cc406Sopenharmony_ci sizeof(scanner->red_lut[0])); 3225141cc406Sopenharmony_ci scanner->green_lut = calloc(scanner->gamma_entries, 3226141cc406Sopenharmony_ci sizeof(scanner->green_lut[0])); 3227141cc406Sopenharmony_ci scanner->blue_lut = calloc(scanner->gamma_entries, 3228141cc406Sopenharmony_ci sizeof(scanner->blue_lut[0])); 3229141cc406Sopenharmony_ci if ((scanner->gray_lut == NULL) || 3230141cc406Sopenharmony_ci (scanner->red_lut == NULL) || 3231141cc406Sopenharmony_ci (scanner->green_lut == NULL) || 3232141cc406Sopenharmony_ci (scanner->blue_lut == NULL)) { 3233141cc406Sopenharmony_ci DBG(23, "sane_open: unable to allocate space for %d-entry LUT's;\n", 3234141cc406Sopenharmony_ci scanner->gamma_entries); 3235141cc406Sopenharmony_ci DBG(23, " so, gamma tables now DISABLED.\n"); 3236141cc406Sopenharmony_ci free(scanner->gray_lut); 3237141cc406Sopenharmony_ci free(scanner->red_lut); 3238141cc406Sopenharmony_ci free(scanner->green_lut); 3239141cc406Sopenharmony_ci free(scanner->blue_lut); 3240141cc406Sopenharmony_ci } 3241141cc406Sopenharmony_ci for (j=0; j<scanner->gamma_entries; j += scanner->gamma_entry_size) { 3242141cc406Sopenharmony_ci v = (SANE_Int) 3243141cc406Sopenharmony_ci ((double) j * (double) max_entry / 3244141cc406Sopenharmony_ci ((double) scanner->gamma_entries - 1.0) + 0.5); 3245141cc406Sopenharmony_ci scanner->gray_lut[j] = v; 3246141cc406Sopenharmony_ci scanner->red_lut[j] = v; 3247141cc406Sopenharmony_ci scanner->green_lut[j] = v; 3248141cc406Sopenharmony_ci scanner->blue_lut[j] = v; 3249141cc406Sopenharmony_ci } 3250141cc406Sopenharmony_ci } else { 3251141cc406Sopenharmony_ci DBG(23, "sane_open: NO gamma tables. (max size = %lu)\n", 3252141cc406Sopenharmony_ci (u_long)dev->info.max_lookup_size); 3253141cc406Sopenharmony_ci scanner->gamma_entries = 0; 3254141cc406Sopenharmony_ci scanner->gray_lut = NULL; 3255141cc406Sopenharmony_ci scanner->red_lut = NULL; 3256141cc406Sopenharmony_ci scanner->green_lut = NULL; 3257141cc406Sopenharmony_ci scanner->blue_lut = NULL; 3258141cc406Sopenharmony_ci } 3259141cc406Sopenharmony_ci 3260141cc406Sopenharmony_ci DBG(23, "sane_open: init pass-time variables...\n"); 3261141cc406Sopenharmony_ci scanner->scanning = SANE_FALSE; 3262141cc406Sopenharmony_ci scanner->this_pass = 0; 3263141cc406Sopenharmony_ci scanner->sfd = -1; 3264141cc406Sopenharmony_ci scanner->dev = dev; 3265141cc406Sopenharmony_ci scanner->sense_flags = 0; 3266141cc406Sopenharmony_ci scanner->scan_started = SANE_FALSE; 3267141cc406Sopenharmony_ci scanner->woe = SANE_FALSE; 3268141cc406Sopenharmony_ci scanner->cancel = SANE_FALSE; 3269141cc406Sopenharmony_ci 3270141cc406Sopenharmony_ci DBG(23, "sane_open: init clever cache...\n"); 3271141cc406Sopenharmony_ci /* clear out that clever cache, so it doesn't match anything */ 3272141cc406Sopenharmony_ci { 3273141cc406Sopenharmony_ci int j; 3274141cc406Sopenharmony_ci for (j=0; j<10; j++) 3275141cc406Sopenharmony_ci scanner->mode_sense_cache[j] = 0; 3276141cc406Sopenharmony_ci scanner->precal_record = MS_PRECAL_NONE; 3277141cc406Sopenharmony_ci } 3278141cc406Sopenharmony_ci 3279141cc406Sopenharmony_ci DBG(23, "sane_open: initialize options: \n"); 3280141cc406Sopenharmony_ci if ((status = init_options(scanner)) != SANE_STATUS_GOOD) return status; 3281141cc406Sopenharmony_ci 3282141cc406Sopenharmony_ci scanner->next = first_handle; 3283141cc406Sopenharmony_ci first_handle = scanner; 3284141cc406Sopenharmony_ci *handle = scanner; 3285141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3286141cc406Sopenharmony_ci} 3287141cc406Sopenharmony_ci 3288141cc406Sopenharmony_ci 3289141cc406Sopenharmony_ci 3290141cc406Sopenharmony_ci/********************************************************************/ 3291141cc406Sopenharmony_ci/* sane_close */ 3292141cc406Sopenharmony_ci/********************************************************************/ 3293141cc406Sopenharmony_civoid 3294141cc406Sopenharmony_cisane_close (SANE_Handle handle) 3295141cc406Sopenharmony_ci{ 3296141cc406Sopenharmony_ci Microtek_Scanner *ms = handle; 3297141cc406Sopenharmony_ci 3298141cc406Sopenharmony_ci DBG(10, "sane_close...\n"); 3299141cc406Sopenharmony_ci /* free malloc'ed stuff (strdup counts too!) */ 3300141cc406Sopenharmony_ci free((void *) ms->sod[OPT_MODE].constraint.string_list); 3301141cc406Sopenharmony_ci free((void *) ms->sod[OPT_SOURCE].constraint.string_list); 3302141cc406Sopenharmony_ci free(ms->val[OPT_MODE].s); 3303141cc406Sopenharmony_ci free(ms->val[OPT_HALFTONE_PATTERN].s); 3304141cc406Sopenharmony_ci free(ms->val[OPT_SOURCE].s); 3305141cc406Sopenharmony_ci free(ms->val[OPT_CUSTOM_GAMMA].s); 3306141cc406Sopenharmony_ci free(ms->gray_lut); 3307141cc406Sopenharmony_ci free(ms->red_lut); 3308141cc406Sopenharmony_ci free(ms->green_lut); 3309141cc406Sopenharmony_ci free(ms->blue_lut); 3310141cc406Sopenharmony_ci /* remove Scanner from linked list */ 3311141cc406Sopenharmony_ci if (first_handle == ms) 3312141cc406Sopenharmony_ci first_handle = ms->next; 3313141cc406Sopenharmony_ci else { 3314141cc406Sopenharmony_ci Microtek_Scanner *ts = first_handle; 3315141cc406Sopenharmony_ci while ((ts != NULL) && (ts->next != ms)) ts = ts->next; 3316141cc406Sopenharmony_ci ts->next = ts->next->next; /* == ms->next */ 3317141cc406Sopenharmony_ci } 3318141cc406Sopenharmony_ci /* finally, say goodbye to the Scanner */ 3319141cc406Sopenharmony_ci free(ms); 3320141cc406Sopenharmony_ci} 3321141cc406Sopenharmony_ci 3322141cc406Sopenharmony_ci 3323141cc406Sopenharmony_ci 3324141cc406Sopenharmony_ci/********************************************************************/ 3325141cc406Sopenharmony_ci/* sane_get_option_descriptor */ 3326141cc406Sopenharmony_ci/********************************************************************/ 3327141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 3328141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, 3329141cc406Sopenharmony_ci SANE_Int option) 3330141cc406Sopenharmony_ci{ 3331141cc406Sopenharmony_ci Microtek_Scanner *scanner = handle; 3332141cc406Sopenharmony_ci 3333141cc406Sopenharmony_ci DBG(96, "sane_get_option_descriptor (%d)...\n", option); 3334141cc406Sopenharmony_ci if ((unsigned)option >= NUM_OPTIONS) return NULL; 3335141cc406Sopenharmony_ci return &(scanner->sod[option]); 3336141cc406Sopenharmony_ci} 3337141cc406Sopenharmony_ci 3338141cc406Sopenharmony_ci 3339141cc406Sopenharmony_ci 3340141cc406Sopenharmony_ci/********************************************************************/ 3341141cc406Sopenharmony_ci/* sane_control_option */ 3342141cc406Sopenharmony_ci/********************************************************************/ 3343141cc406Sopenharmony_ciSANE_Status 3344141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, 3345141cc406Sopenharmony_ci SANE_Int option, 3346141cc406Sopenharmony_ci SANE_Action action, 3347141cc406Sopenharmony_ci void *value, 3348141cc406Sopenharmony_ci SANE_Int *info) 3349141cc406Sopenharmony_ci{ 3350141cc406Sopenharmony_ci Microtek_Scanner *scanner = handle; 3351141cc406Sopenharmony_ci SANE_Option_Descriptor *sod; 3352141cc406Sopenharmony_ci Option_Value *val; 3353141cc406Sopenharmony_ci SANE_Status status; 3354141cc406Sopenharmony_ci 3355141cc406Sopenharmony_ci DBG(96, "sane_control_option (opt=%d,act=%d,val=%p,info=%p)\n", 3356141cc406Sopenharmony_ci option, action, value, (void*) info); 3357141cc406Sopenharmony_ci 3358141cc406Sopenharmony_ci sod = scanner->sod; 3359141cc406Sopenharmony_ci val = scanner->val; 3360141cc406Sopenharmony_ci 3361141cc406Sopenharmony_ci /* no changes while in mid-pass! */ 3362141cc406Sopenharmony_ci if (scanner->scanning) return SANE_STATUS_DEVICE_BUSY; 3363141cc406Sopenharmony_ci /* and... no changes while in middle of three-pass series! */ 3364141cc406Sopenharmony_ci if (scanner->this_pass != 0) return SANE_STATUS_DEVICE_BUSY; 3365141cc406Sopenharmony_ci 3366141cc406Sopenharmony_ci if ( ((option >= NUM_OPTIONS) || (option < 0)) || 3367141cc406Sopenharmony_ci (!SANE_OPTION_IS_ACTIVE(scanner->sod[option].cap)) ) 3368141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3369141cc406Sopenharmony_ci 3370141cc406Sopenharmony_ci if (info) *info = 0; 3371141cc406Sopenharmony_ci 3372141cc406Sopenharmony_ci /* choose by action */ 3373141cc406Sopenharmony_ci switch (action) { 3374141cc406Sopenharmony_ci 3375141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 3376141cc406Sopenharmony_ci switch (option) { 3377141cc406Sopenharmony_ci /* word options... */ 3378141cc406Sopenharmony_ci case OPT_RESOLUTION: 3379141cc406Sopenharmony_ci case OPT_SPEED: 3380141cc406Sopenharmony_ci case OPT_BACKTRACK: 3381141cc406Sopenharmony_ci case OPT_NEGATIVE: 3382141cc406Sopenharmony_ci case OPT_PREVIEW: 3383141cc406Sopenharmony_ci case OPT_TL_X: 3384141cc406Sopenharmony_ci case OPT_TL_Y: 3385141cc406Sopenharmony_ci case OPT_BR_X: 3386141cc406Sopenharmony_ci case OPT_BR_Y: 3387141cc406Sopenharmony_ci case OPT_EXPOSURE: 3388141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3389141cc406Sopenharmony_ci case OPT_CONTRAST: 3390141cc406Sopenharmony_ci case OPT_HIGHLIGHT: 3391141cc406Sopenharmony_ci case OPT_SHADOW: 3392141cc406Sopenharmony_ci case OPT_MIDTONE: 3393141cc406Sopenharmony_ci case OPT_GAMMA_BIND: 3394141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA: 3395141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA_R: 3396141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA_G: 3397141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA_B: 3398141cc406Sopenharmony_ci case OPT_EXP_RES: 3399141cc406Sopenharmony_ci case OPT_CALIB_ONCE: 3400141cc406Sopenharmony_ci *(SANE_Word *)value = val[option].w; 3401141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3402141cc406Sopenharmony_ci /* word-array options... */ 3403141cc406Sopenharmony_ci /* case OPT_HALFTONE_PATTERN:*/ 3404141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 3405141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3406141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3407141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3408141cc406Sopenharmony_ci memcpy(value, val[option].wa, sod[option].size); 3409141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3410141cc406Sopenharmony_ci /* string options... */ 3411141cc406Sopenharmony_ci case OPT_MODE: 3412141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 3413141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 3414141cc406Sopenharmony_ci case OPT_SOURCE: 3415141cc406Sopenharmony_ci strcpy(value, val[option].s); 3416141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3417141cc406Sopenharmony_ci /* others.... */ 3418141cc406Sopenharmony_ci case OPT_NUM_OPTS: 3419141cc406Sopenharmony_ci *(SANE_Word *) value = NUM_OPTIONS; 3420141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3421141cc406Sopenharmony_ci default: 3422141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3423141cc406Sopenharmony_ci } 3424141cc406Sopenharmony_ci break; 3425141cc406Sopenharmony_ci 3426141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: { 3427141cc406Sopenharmony_ci status = sanei_constrain_value(sod + option, value, info); 3428141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3429141cc406Sopenharmony_ci return status; 3430141cc406Sopenharmony_ci 3431141cc406Sopenharmony_ci switch (option) { 3432141cc406Sopenharmony_ci /* set word options... */ 3433141cc406Sopenharmony_ci case OPT_TL_X: 3434141cc406Sopenharmony_ci case OPT_TL_Y: 3435141cc406Sopenharmony_ci case OPT_BR_X: 3436141cc406Sopenharmony_ci case OPT_BR_Y: 3437141cc406Sopenharmony_ci case OPT_RESOLUTION: 3438141cc406Sopenharmony_ci if (info) 3439141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 3440141cc406Sopenharmony_ci // fall through 3441141cc406Sopenharmony_ci case OPT_SPEED: 3442141cc406Sopenharmony_ci case OPT_PREVIEW: 3443141cc406Sopenharmony_ci case OPT_BACKTRACK: 3444141cc406Sopenharmony_ci case OPT_NEGATIVE: 3445141cc406Sopenharmony_ci case OPT_EXPOSURE: 3446141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 3447141cc406Sopenharmony_ci case OPT_CONTRAST: 3448141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA: 3449141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA_R: 3450141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA_G: 3451141cc406Sopenharmony_ci case OPT_ANALOG_GAMMA_B: 3452141cc406Sopenharmony_ci val[option].w = *(SANE_Word *)value; 3453141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3454141cc406Sopenharmony_ci 3455141cc406Sopenharmony_ci case OPT_HIGHLIGHT: 3456141cc406Sopenharmony_ci case OPT_SHADOW: 3457141cc406Sopenharmony_ci case OPT_MIDTONE: 3458141cc406Sopenharmony_ci val[option].w = *(SANE_Word *)value; 3459141cc406Sopenharmony_ci /* we need to (silently) make sure shadow <= midtone <= highlight */ 3460141cc406Sopenharmony_ci if (scanner->midtone_support) { 3461141cc406Sopenharmony_ci if (val[OPT_SHADOW].w > val[OPT_MIDTONE].w) { 3462141cc406Sopenharmony_ci if (option == OPT_SHADOW) 3463141cc406Sopenharmony_ci val[OPT_SHADOW].w = val[OPT_MIDTONE].w; 3464141cc406Sopenharmony_ci else 3465141cc406Sopenharmony_ci val[OPT_MIDTONE].w = val[OPT_SHADOW].w; 3466141cc406Sopenharmony_ci } 3467141cc406Sopenharmony_ci if (val[OPT_HIGHLIGHT].w < val[OPT_MIDTONE].w) { 3468141cc406Sopenharmony_ci if (option == OPT_HIGHLIGHT) 3469141cc406Sopenharmony_ci val[OPT_HIGHLIGHT].w = val[OPT_MIDTONE].w; 3470141cc406Sopenharmony_ci else 3471141cc406Sopenharmony_ci val[OPT_MIDTONE].w = val[OPT_HIGHLIGHT].w; 3472141cc406Sopenharmony_ci } 3473141cc406Sopenharmony_ci } else { 3474141cc406Sopenharmony_ci if (val[OPT_SHADOW].w > val[OPT_HIGHLIGHT].w) { 3475141cc406Sopenharmony_ci if (option == OPT_SHADOW) 3476141cc406Sopenharmony_ci val[OPT_SHADOW].w = val[OPT_HIGHLIGHT].w; 3477141cc406Sopenharmony_ci else 3478141cc406Sopenharmony_ci val[OPT_HIGHLIGHT].w = val[OPT_SHADOW].w; 3479141cc406Sopenharmony_ci } 3480141cc406Sopenharmony_ci } 3481141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3482141cc406Sopenharmony_ci 3483141cc406Sopenharmony_ci case OPT_EXP_RES: 3484141cc406Sopenharmony_ci if (val[option].w != *(SANE_Word *) value) { 3485141cc406Sopenharmony_ci val[option].w = *(SANE_Word *)value; 3486141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 3487141cc406Sopenharmony_ci if (val[OPT_EXP_RES].w) { 3488141cc406Sopenharmony_ci sod[OPT_RESOLUTION].constraint.range = &(scanner->exp_res_range); 3489141cc406Sopenharmony_ci val[OPT_RESOLUTION].w *= 2; 3490141cc406Sopenharmony_ci } else { 3491141cc406Sopenharmony_ci sod[OPT_RESOLUTION].constraint.range = &(scanner->res_range); 3492141cc406Sopenharmony_ci val[OPT_RESOLUTION].w /= 2; 3493141cc406Sopenharmony_ci } 3494141cc406Sopenharmony_ci } 3495141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3496141cc406Sopenharmony_ci 3497141cc406Sopenharmony_ci case OPT_CALIB_ONCE: 3498141cc406Sopenharmony_ci val[option].w = *(SANE_Word *)value; 3499141cc406Sopenharmony_ci /* toggling off and on should force a recalibration... */ 3500141cc406Sopenharmony_ci if (!(val[option].w)) scanner->precal_record = MS_PRECAL_NONE; 3501141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3502141cc406Sopenharmony_ci 3503141cc406Sopenharmony_ci case OPT_GAMMA_BIND: 3504141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 3505141cc406Sopenharmony_ci if (option == OPT_GAMMA_BIND) { 3506141cc406Sopenharmony_ci if (val[option].w != *(SANE_Word *) value) 3507141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3508141cc406Sopenharmony_ci val[option].w = *(SANE_Word *) value; 3509141cc406Sopenharmony_ci } else if (option == OPT_CUSTOM_GAMMA) { 3510141cc406Sopenharmony_ci if (val[option].s) { 3511141cc406Sopenharmony_ci if (strcmp(value, val[option].s)) 3512141cc406Sopenharmony_ci if (info) *info |= SANE_INFO_RELOAD_OPTIONS; 3513141cc406Sopenharmony_ci free(val[option].s); 3514141cc406Sopenharmony_ci } 3515141cc406Sopenharmony_ci val[option].s = strdup(value); 3516141cc406Sopenharmony_ci } 3517141cc406Sopenharmony_ci if ( !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)) || 3518141cc406Sopenharmony_ci !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_SCALAR)) ) { 3519141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 3520141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 3521141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 3522141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 3523141cc406Sopenharmony_ci } 3524141cc406Sopenharmony_ci if ( !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)) || 3525141cc406Sopenharmony_ci !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_TABLE)) ) { 3526141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; 3527141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; 3528141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; 3529141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; 3530141cc406Sopenharmony_ci } 3531141cc406Sopenharmony_ci if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_SCALAR))) { 3532141cc406Sopenharmony_ci if (val[OPT_GAMMA_BIND].w == SANE_TRUE) { 3533141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].cap &= ~SANE_CAP_INACTIVE; 3534141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; 3535141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; 3536141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; 3537141cc406Sopenharmony_ci } else { 3538141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; 3539141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_R].cap &= ~SANE_CAP_INACTIVE; 3540141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_G].cap &= ~SANE_CAP_INACTIVE; 3541141cc406Sopenharmony_ci sod[OPT_ANALOG_GAMMA_B].cap &= ~SANE_CAP_INACTIVE; 3542141cc406Sopenharmony_ci } 3543141cc406Sopenharmony_ci } 3544141cc406Sopenharmony_ci if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_TABLE))) { 3545141cc406Sopenharmony_ci if (val[OPT_GAMMA_BIND].w == SANE_TRUE) { 3546141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 3547141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 3548141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 3549141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 3550141cc406Sopenharmony_ci } else { 3551141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 3552141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 3553141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 3554141cc406Sopenharmony_ci sod[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 3555141cc406Sopenharmony_ci } 3556141cc406Sopenharmony_ci } 3557141cc406Sopenharmony_ci if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE))) 3558141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; 3559141cc406Sopenharmony_ci else if (!(strcmp(val[OPT_MODE].s, M_COLOR))) 3560141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; 3561141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3562141cc406Sopenharmony_ci 3563141cc406Sopenharmony_ci 3564141cc406Sopenharmony_ci case OPT_MODE: 3565141cc406Sopenharmony_ci if (val[option].s) { 3566141cc406Sopenharmony_ci if (strcmp(val[option].s, value)) 3567141cc406Sopenharmony_ci if (info) 3568141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 3569141cc406Sopenharmony_ci free(val[option].s); 3570141cc406Sopenharmony_ci } 3571141cc406Sopenharmony_ci val[option].s = strdup(value); 3572141cc406Sopenharmony_ci if (strcmp(val[option].s, M_HALFTONE)) { 3573141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 3574141cc406Sopenharmony_ci } else { 3575141cc406Sopenharmony_ci sod[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; 3576141cc406Sopenharmony_ci } 3577141cc406Sopenharmony_ci if (strcmp(val[option].s, M_COLOR)) { /* not color */ 3578141cc406Sopenharmony_ci /*val[OPT_GAMMA_BIND].w = SANE_TRUE;*/ 3579141cc406Sopenharmony_ci DBG(23, "FLIP ma LID! bind is %d\n", val[OPT_GAMMA_BIND].w); 3580141cc406Sopenharmony_ci { 3581141cc406Sopenharmony_ci SANE_Bool Trueness = SANE_TRUE; 3582141cc406Sopenharmony_ci SANE_Status status; 3583141cc406Sopenharmony_ci status = sane_control_option(handle, 3584141cc406Sopenharmony_ci OPT_GAMMA_BIND, 3585141cc406Sopenharmony_ci SANE_ACTION_SET_VALUE, 3586141cc406Sopenharmony_ci &Trueness, 3587141cc406Sopenharmony_ci NULL); 3588141cc406Sopenharmony_ci DBG(23, "stat is: %d\n", status); 3589141cc406Sopenharmony_ci } 3590141cc406Sopenharmony_ci DBG(23, "LID be FLIPPED! bind is %d\n", val[OPT_GAMMA_BIND].w); 3591141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; 3592141cc406Sopenharmony_ci /* sod[OPT_FORCE_3PASS].cap |= SANE_CAP_INACTIVE;*/ 3593141cc406Sopenharmony_ci } else { 3594141cc406Sopenharmony_ci sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; 3595141cc406Sopenharmony_ci /* if (scanner->dev->info.modes & MI_MODES_ONEPASS) 3596141cc406Sopenharmony_ci sod[OPT_FORCE_3PASS].cap &= ~SANE_CAP_INACTIVE;*/ 3597141cc406Sopenharmony_ci } 3598141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3599141cc406Sopenharmony_ci 3600141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 3601141cc406Sopenharmony_ci case OPT_SOURCE: 3602141cc406Sopenharmony_ci if (val[option].s) free(val[option].s); 3603141cc406Sopenharmony_ci val[option].s = strdup(value); 3604141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3605141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 3606141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 3607141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 3608141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 3609141cc406Sopenharmony_ci memcpy(val[option].wa, value, sod[option].size); 3610141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3611141cc406Sopenharmony_ci default: 3612141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3613141cc406Sopenharmony_ci } 3614141cc406Sopenharmony_ci } 3615141cc406Sopenharmony_ci break; 3616141cc406Sopenharmony_ci 3617141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 3618141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; /* We are DUMB. */ 3619141cc406Sopenharmony_ci } 3620141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3621141cc406Sopenharmony_ci} 3622141cc406Sopenharmony_ci 3623141cc406Sopenharmony_ci 3624141cc406Sopenharmony_ci 3625141cc406Sopenharmony_ci/********************************************************************/ 3626141cc406Sopenharmony_ci/* sane_get_parameters */ 3627141cc406Sopenharmony_ci/********************************************************************/ 3628141cc406Sopenharmony_ciSANE_Status 3629141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, 3630141cc406Sopenharmony_ci SANE_Parameters *params) 3631141cc406Sopenharmony_ci{ 3632141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 3633141cc406Sopenharmony_ci 3634141cc406Sopenharmony_ci DBG(23, "sane_get_parameters...\n"); 3635141cc406Sopenharmony_ci 3636141cc406Sopenharmony_ci if (!s->scanning) { 3637141cc406Sopenharmony_ci /* decipher scan mode */ 3638141cc406Sopenharmony_ci if (!(strcmp(s->val[OPT_MODE].s, M_LINEART))) 3639141cc406Sopenharmony_ci s->mode = MS_MODE_LINEART; 3640141cc406Sopenharmony_ci else if (!(strcmp(s->val[OPT_MODE].s, M_HALFTONE))) 3641141cc406Sopenharmony_ci s->mode = MS_MODE_HALFTONE; 3642141cc406Sopenharmony_ci else if (!(strcmp(s->val[OPT_MODE].s, M_GRAY))) 3643141cc406Sopenharmony_ci s->mode = MS_MODE_GRAY; 3644141cc406Sopenharmony_ci else if (!(strcmp(s->val[OPT_MODE].s, M_COLOR))) 3645141cc406Sopenharmony_ci s->mode = MS_MODE_COLOR; 3646141cc406Sopenharmony_ci 3647141cc406Sopenharmony_ci if (s->mode == MS_MODE_COLOR) { 3648141cc406Sopenharmony_ci if (s->onepass) { 3649141cc406Sopenharmony_ci /* regular one-pass */ 3650141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: regular 1-pass color\n"); 3651141cc406Sopenharmony_ci s->threepasscolor = SANE_FALSE; 3652141cc406Sopenharmony_ci s->onepasscolor = SANE_TRUE; 3653141cc406Sopenharmony_ci s->color_seq = s->dev->info.color_sequence; 3654141cc406Sopenharmony_ci } else { /* 3-pass scanner */ 3655141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: regular 3-pass color\n"); 3656141cc406Sopenharmony_ci s->threepasscolor = SANE_TRUE; 3657141cc406Sopenharmony_ci s->onepasscolor = SANE_FALSE; 3658141cc406Sopenharmony_ci s->color_seq = s->dev->info.color_sequence; 3659141cc406Sopenharmony_ci } 3660141cc406Sopenharmony_ci } else { /* not color! */ 3661141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: non-color\n"); 3662141cc406Sopenharmony_ci s->threepasscolor = SANE_FALSE; 3663141cc406Sopenharmony_ci s->onepasscolor = SANE_FALSE; 3664141cc406Sopenharmony_ci s->color_seq = s->dev->info.color_sequence; 3665141cc406Sopenharmony_ci } 3666141cc406Sopenharmony_ci 3667141cc406Sopenharmony_ci s->transparency = !(strcmp(s->val[OPT_SOURCE].s, M_TRANS)); 3668141cc406Sopenharmony_ci s->useADF = !(strcmp(s->val[OPT_SOURCE].s, M_AUTOFEED)); 3669141cc406Sopenharmony_ci /* disallow exp. res. during preview scan XXXXXXXXXXX */ 3670141cc406Sopenharmony_ci /*s->expandedresolution = 3671141cc406Sopenharmony_ci (s->val[OPT_EXP_RES].w) && !(s->val[OPT_PREVIEW].w);*/ 3672141cc406Sopenharmony_ci s->expandedresolution = (s->val[OPT_EXP_RES].w); 3673141cc406Sopenharmony_ci s->doexpansion = (s->expandedresolution && !(s->dev->info.does_expansion)); 3674141cc406Sopenharmony_ci 3675141cc406Sopenharmony_ci if (s->res_type == MS_RES_1PER) { 3676141cc406Sopenharmony_ci s->resolution = (SANE_Int)(SANE_UNFIX(s->val[OPT_RESOLUTION].w)); 3677141cc406Sopenharmony_ci s->resolution_code = 3678141cc406Sopenharmony_ci 0xFF & ((s->resolution * 100) / 3679141cc406Sopenharmony_ci s->dev->info.base_resolution / 3680141cc406Sopenharmony_ci (s->expandedresolution ? 2 : 1)); 3681141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: res_code = %d (%2x)\n", 3682141cc406Sopenharmony_ci s->resolution_code, s->resolution_code); 3683141cc406Sopenharmony_ci } else { 3684141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: 5 percent!!!\n"); 3685141cc406Sopenharmony_ci /* XXXXXXXXXXXXX */ 3686141cc406Sopenharmony_ci } 3687141cc406Sopenharmony_ci 3688141cc406Sopenharmony_ci s->calib_once = s->val[OPT_CALIB_ONCE].w; 3689141cc406Sopenharmony_ci 3690141cc406Sopenharmony_ci s->reversecolors = s->val[OPT_NEGATIVE].w; 3691141cc406Sopenharmony_ci s->prescan = s->val[OPT_PREVIEW].w; 3692141cc406Sopenharmony_ci s->exposure = (s->val[OPT_EXPOSURE].w / 3) + 7; 3693141cc406Sopenharmony_ci s->contrast = (s->val[OPT_CONTRAST].w / 7) + 7; 3694141cc406Sopenharmony_ci s->velocity = s->val[OPT_SPEED].w; 3695141cc406Sopenharmony_ci s->shadow = s->val[OPT_SHADOW].w; 3696141cc406Sopenharmony_ci s->highlight = s->val[OPT_HIGHLIGHT].w; 3697141cc406Sopenharmony_ci s->midtone = s->val[OPT_MIDTONE].w; 3698141cc406Sopenharmony_ci if (SANE_OPTION_IS_ACTIVE(s->sod[OPT_BRIGHTNESS].cap)) { 3699141cc406Sopenharmony_ci#if 1 /* this is _not_ what the docs specify! */ 3700141cc406Sopenharmony_ci if (s->val[OPT_BRIGHTNESS].w >= 0) 3701141cc406Sopenharmony_ci s->bright_r = (SANE_Byte) (s->val[OPT_BRIGHTNESS].w); 3702141cc406Sopenharmony_ci else 3703141cc406Sopenharmony_ci s->bright_r = (SANE_Byte) (0x80 | (- s->val[OPT_BRIGHTNESS].w)); 3704141cc406Sopenharmony_ci#else 3705141cc406Sopenharmony_ci s->bright_r = (SANE_Byte) (s->val[OPT_BRIGHTNESS].w); 3706141cc406Sopenharmony_ci#endif 3707141cc406Sopenharmony_ci s->bright_g = s->bright_b = s->bright_r; 3708141cc406Sopenharmony_ci DBG(23, "bright_r of %d set to 0x%0x\n", 3709141cc406Sopenharmony_ci s->val[OPT_BRIGHTNESS].w, s->bright_r); 3710141cc406Sopenharmony_ci } else { 3711141cc406Sopenharmony_ci s->bright_r = s->bright_g = s->bright_b = 0; 3712141cc406Sopenharmony_ci } 3713141cc406Sopenharmony_ci /* figure out halftone pattern selection... */ 3714141cc406Sopenharmony_ci if (s->mode == MS_MODE_HALFTONE) { 3715141cc406Sopenharmony_ci int i = 0; 3716141cc406Sopenharmony_ci while ((halftone_mode_list[i] != NULL) && 3717141cc406Sopenharmony_ci (strcmp(halftone_mode_list[i], s->val[OPT_HALFTONE_PATTERN].s))) 3718141cc406Sopenharmony_ci i++; 3719141cc406Sopenharmony_ci s->pattern = ((i < s->dev->info.pattern_count) ? i : 0); 3720141cc406Sopenharmony_ci } else 3721141cc406Sopenharmony_ci s->pattern = 0; 3722141cc406Sopenharmony_ci 3723141cc406Sopenharmony_ci 3724141cc406Sopenharmony_ci 3725141cc406Sopenharmony_ci { 3726141cc406Sopenharmony_ci /* need to 'round' things properly! XXXXXXXX */ 3727141cc406Sopenharmony_ci SANE_Int widthpix; 3728141cc406Sopenharmony_ci double dots_per_mm = s->resolution / MM_PER_INCH; 3729141cc406Sopenharmony_ci double units_per_mm = 3730141cc406Sopenharmony_ci (s->unit_type == MS_UNIT_18INCH) ? 3731141cc406Sopenharmony_ci (8.0 / MM_PER_INCH) : /* 1/8 inches */ 3732141cc406Sopenharmony_ci (s->dev->info.base_resolution / MM_PER_INCH); /* pixels */ 3733141cc406Sopenharmony_ci 3734141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: dots_per_mm: %f\n", dots_per_mm); 3735141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: units_per_mm: %f\n", units_per_mm); 3736141cc406Sopenharmony_ci 3737141cc406Sopenharmony_ci /* calculate frame coordinates... 3738141cc406Sopenharmony_ci * scanner coords are in 'units' -- pixels or 1/8" 3739141cc406Sopenharmony_ci * option coords are MM 3740141cc406Sopenharmony_ci */ 3741141cc406Sopenharmony_ci s->x1 = (SANE_Int)(SANE_UNFIX(s->val[OPT_TL_X].w) * units_per_mm + 0.5); 3742141cc406Sopenharmony_ci s->y1 = (SANE_Int)(SANE_UNFIX(s->val[OPT_TL_Y].w) * units_per_mm + 0.5); 3743141cc406Sopenharmony_ci s->x2 = (SANE_Int)(SANE_UNFIX(s->val[OPT_BR_X].w) * units_per_mm + 0.5); 3744141cc406Sopenharmony_ci s->y2 = (SANE_Int)(SANE_UNFIX(s->val[OPT_BR_Y].w) * units_per_mm + 0.5); 3745141cc406Sopenharmony_ci /* bug out if length or width is <= zero... */ 3746141cc406Sopenharmony_ci if ((s->x1 >= s->x2) || (s->y1 >= s->y2)) 3747141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 3748141cc406Sopenharmony_ci 3749141cc406Sopenharmony_ci /* these are just an estimate... (but *should* be completely accurate) 3750141cc406Sopenharmony_ci * real values come from scanner after sane_start. 3751141cc406Sopenharmony_ci */ 3752141cc406Sopenharmony_ci if (s->unit_type == MS_UNIT_18INCH) { 3753141cc406Sopenharmony_ci /* who *knows* what happens */ 3754141cc406Sopenharmony_ci widthpix = 3755141cc406Sopenharmony_ci (SANE_Int)((double)(s->x2 - s->x1 + 1) / 8.0 * 3756141cc406Sopenharmony_ci (double)s->resolution); 3757141cc406Sopenharmony_ci s->params.lines = 3758141cc406Sopenharmony_ci (SANE_Int)((double)(s->y2 - s->y1 + 1) / 8.0 * 3759141cc406Sopenharmony_ci (double)s->resolution); 3760141cc406Sopenharmony_ci } else { 3761141cc406Sopenharmony_ci /* calculate pixels per scanline returned by scanner... */ 3762141cc406Sopenharmony_ci /* scanner (E6 at least) always seems to return 3763141cc406Sopenharmony_ci an -even- number of -bytes- */ 3764141cc406Sopenharmony_ci if (s->resolution <= s->dev->info.base_resolution) 3765141cc406Sopenharmony_ci widthpix = 3766141cc406Sopenharmony_ci (SANE_Int)((double)(s->x2 - s->x1 + 1) * 3767141cc406Sopenharmony_ci (double)(s->resolution) / 3768141cc406Sopenharmony_ci (double)(s->dev->info.base_resolution)); 3769141cc406Sopenharmony_ci else 3770141cc406Sopenharmony_ci widthpix = (s->x2 - s->x1 + 1); 3771141cc406Sopenharmony_ci if ((s->mode == MS_MODE_LINEART) || 3772141cc406Sopenharmony_ci (s->mode == MS_MODE_HALFTONE)) { 3773141cc406Sopenharmony_ci DBG(23, "WIDTHPIX: before: %d", widthpix); 3774141cc406Sopenharmony_ci widthpix = ((widthpix / 8) & ~0x1) * 8; 3775141cc406Sopenharmony_ci DBG(23, "after: %d", widthpix); 3776141cc406Sopenharmony_ci } else { 3777141cc406Sopenharmony_ci widthpix = widthpix & ~0x1; 3778141cc406Sopenharmony_ci } 3779141cc406Sopenharmony_ci DBG(23, "WIDTHPIX: before exp: %d\n", widthpix); 3780141cc406Sopenharmony_ci /* ok, now fix up expanded-mode conversions */ 3781141cc406Sopenharmony_ci if (s->resolution > s->dev->info.base_resolution) 3782141cc406Sopenharmony_ci widthpix = (SANE_Int) ((double)widthpix * 3783141cc406Sopenharmony_ci (double)s->resolution / 3784141cc406Sopenharmony_ci (double)s->dev->info.base_resolution); 3785141cc406Sopenharmony_ci s->params.pixels_per_line = widthpix; 3786141cc406Sopenharmony_ci s->params.lines = 3787141cc406Sopenharmony_ci (SANE_Int)((double)(s->y2 - s->y1 + 1) * 3788141cc406Sopenharmony_ci (double)(s->resolution) / 3789141cc406Sopenharmony_ci (double)(s->dev->info.base_resolution)); 3790141cc406Sopenharmony_ci } 3791141cc406Sopenharmony_ci } 3792141cc406Sopenharmony_ci 3793141cc406Sopenharmony_ci switch (s->mode) { 3794141cc406Sopenharmony_ci case MS_MODE_LINEART: 3795141cc406Sopenharmony_ci case MS_MODE_HALFTONE: 3796141cc406Sopenharmony_ci s->multibit = SANE_FALSE; 3797141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 3798141cc406Sopenharmony_ci s->params.depth = 1; 3799141cc406Sopenharmony_ci s->filter = MS_FILT_CLEAR; 3800141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line / 8; 3801141cc406Sopenharmony_ci break; 3802141cc406Sopenharmony_ci case MS_MODE_GRAY: 3803141cc406Sopenharmony_ci s->multibit = SANE_TRUE; 3804141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 3805141cc406Sopenharmony_ci s->params.depth = s->bits_per_color; 3806141cc406Sopenharmony_ci s->filter = MS_FILT_CLEAR; 3807141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 3808141cc406Sopenharmony_ci break; 3809141cc406Sopenharmony_ci case MS_MODE_COLOR: 3810141cc406Sopenharmony_ci s->multibit = SANE_TRUE; 3811141cc406Sopenharmony_ci if (s->onepasscolor) { /* a single-pass color scan */ 3812141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RGB; 3813141cc406Sopenharmony_ci s->params.depth = s->bits_per_color; 3814141cc406Sopenharmony_ci s->filter = MS_FILT_CLEAR; 3815141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line * 3; 3816141cc406Sopenharmony_ci } else { /* a three-pass color scan */ 3817141cc406Sopenharmony_ci s->params.depth = s->bits_per_color; 3818141cc406Sopenharmony_ci /* this will be correctly set in sane_start */ 3819141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RED; 3820141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line; 3821141cc406Sopenharmony_ci } 3822141cc406Sopenharmony_ci break; 3823141cc406Sopenharmony_ci } 3824141cc406Sopenharmony_ci 3825141cc406Sopenharmony_ci DBG(23, "sane_get_parameters: lines: %d ppl: %d bpl: %d\n", 3826141cc406Sopenharmony_ci s->params.lines, s->params.pixels_per_line, s->params.bytes_per_line); 3827141cc406Sopenharmony_ci 3828141cc406Sopenharmony_ci /* also fixed in sane_start for multi-pass scans */ 3829141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; /* ?? XXXXXXXX */ 3830141cc406Sopenharmony_ci } 3831141cc406Sopenharmony_ci 3832141cc406Sopenharmony_ci if (params) 3833141cc406Sopenharmony_ci *params = s->params; 3834141cc406Sopenharmony_ci 3835141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3836141cc406Sopenharmony_ci} 3837141cc406Sopenharmony_ci 3838141cc406Sopenharmony_ci 3839141cc406Sopenharmony_ci 3840141cc406Sopenharmony_ci/********************************************************************/ 3841141cc406Sopenharmony_ci/* sane_start */ 3842141cc406Sopenharmony_ci/********************************************************************/ 3843141cc406Sopenharmony_cistatic SANE_Status 3844141cc406Sopenharmony_cisane_start_guts (SANE_Handle handle) 3845141cc406Sopenharmony_ci{ 3846141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 3847141cc406Sopenharmony_ci SANE_Status status; 3848141cc406Sopenharmony_ci SANE_Int busy, linewidth; 3849141cc406Sopenharmony_ci 3850141cc406Sopenharmony_ci DBG(10, "sane_start...\n"); 3851141cc406Sopenharmony_ci 3852141cc406Sopenharmony_ci if (s->sfd != -1) { 3853141cc406Sopenharmony_ci DBG(23, "sane_start: sfd already set!\n"); 3854141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 3855141cc406Sopenharmony_ci } 3856141cc406Sopenharmony_ci 3857141cc406Sopenharmony_ci if ((status = sane_get_parameters(s, 0)) != SANE_STATUS_GOOD) 3858141cc406Sopenharmony_ci return end_scan(s, status); 3859141cc406Sopenharmony_ci set_pass_parameters(s); 3860141cc406Sopenharmony_ci 3861141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 3862141cc406Sopenharmony_ci s->cancel = SANE_FALSE; 3863141cc406Sopenharmony_ci 3864141cc406Sopenharmony_ci status = sanei_scsi_open(s->dev->sane.name, 3865141cc406Sopenharmony_ci &(s->sfd), 3866141cc406Sopenharmony_ci sense_handler, 3867141cc406Sopenharmony_ci &(s->sense_flags)); 3868141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) { 3869141cc406Sopenharmony_ci DBG(10, "sane_start: open of %s failed: %s\n", 3870141cc406Sopenharmony_ci s->dev->sane.name, sane_strstatus (status)); 3871141cc406Sopenharmony_ci s->sfd = -1; 3872141cc406Sopenharmony_ci return end_scan(s, status); 3873141cc406Sopenharmony_ci } 3874141cc406Sopenharmony_ci 3875141cc406Sopenharmony_ci if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return end_scan(s, status); 3876141cc406Sopenharmony_ci 3877141cc406Sopenharmony_ci if ((status = finagle_precal(s)) != SANE_STATUS_GOOD) 3878141cc406Sopenharmony_ci return end_scan(s, status); 3879141cc406Sopenharmony_ci 3880141cc406Sopenharmony_ci if ((status = scanning_frame(s)) != SANE_STATUS_GOOD) return end_scan(s, status); 3881141cc406Sopenharmony_ci if (s->dev->info.source_options & 3882141cc406Sopenharmony_ci (MI_SRC_FEED_BT | MI_SRC_HAS_TRANS | 3883141cc406Sopenharmony_ci MI_SRC_FEED_SUPP | MI_SRC_HAS_FEED)) { /* ZZZZZZZZZZZ */ 3884141cc406Sopenharmony_ci if ((status = accessory(s)) != SANE_STATUS_GOOD) return end_scan(s, status); 3885141cc406Sopenharmony_ci /* if SWslct ???? XXXXXXXXXXXXXXX */ 3886141cc406Sopenharmony_ci } 3887141cc406Sopenharmony_ci if ((status = download_gamma(s)) != SANE_STATUS_GOOD) 3888141cc406Sopenharmony_ci return end_scan(s, status); 3889141cc406Sopenharmony_ci if ((status = mode_select(s)) != SANE_STATUS_GOOD) 3890141cc406Sopenharmony_ci return end_scan(s, status); 3891141cc406Sopenharmony_ci if (s->dev->info.does_mode1) { 3892141cc406Sopenharmony_ci if ((status = mode_select_1(s)) != SANE_STATUS_GOOD) 3893141cc406Sopenharmony_ci return end_scan(s, status); 3894141cc406Sopenharmony_ci } 3895141cc406Sopenharmony_ci if ((s->do_clever_precal) || (s->do_real_calib)) { 3896141cc406Sopenharmony_ci if ((status = save_mode_sense(s)) != SANE_STATUS_GOOD) 3897141cc406Sopenharmony_ci return end_scan(s, status); 3898141cc406Sopenharmony_ci } 3899141cc406Sopenharmony_ci if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return end_scan(s, status); 3900141cc406Sopenharmony_ci s->scan_started = SANE_TRUE; 3901141cc406Sopenharmony_ci if ((status = start_scan(s)) != SANE_STATUS_GOOD) return end_scan(s, status); 3902141cc406Sopenharmony_ci if ((status = get_scan_status(s, &busy, 3903141cc406Sopenharmony_ci &linewidth, &(s->unscanned_lines))) != 3904141cc406Sopenharmony_ci SANE_STATUS_GOOD) { 3905141cc406Sopenharmony_ci DBG(10, "sane_start: get_scan_status fails\n"); 3906141cc406Sopenharmony_ci return end_scan(s, status); 3907141cc406Sopenharmony_ci } 3908141cc406Sopenharmony_ci /* check for a bizarre linecount */ 3909141cc406Sopenharmony_ci if ((s->unscanned_lines < 0) || 3910141cc406Sopenharmony_ci (s->unscanned_lines > 3911141cc406Sopenharmony_ci (s->params.lines * 2 * (s->expandedresolution ? 2 : 1)))) { 3912141cc406Sopenharmony_ci DBG(10, "sane_start: get_scan_status returns weird line count %d\n", 3913141cc406Sopenharmony_ci s->unscanned_lines); 3914141cc406Sopenharmony_ci return end_scan(s, SANE_STATUS_DEVICE_BUSY); 3915141cc406Sopenharmony_ci } 3916141cc406Sopenharmony_ci 3917141cc406Sopenharmony_ci 3918141cc406Sopenharmony_ci /* figure out image format parameters */ 3919141cc406Sopenharmony_ci switch (s->mode) { 3920141cc406Sopenharmony_ci case MS_MODE_LINEART: 3921141cc406Sopenharmony_ci case MS_MODE_HALFTONE: 3922141cc406Sopenharmony_ci s->pixel_bpl = linewidth; 3923141cc406Sopenharmony_ci s->header_bpl = 0; 3924141cc406Sopenharmony_ci s->ppl = linewidth * 8; 3925141cc406Sopenharmony_ci s->planes = 1; 3926141cc406Sopenharmony_ci s->line_format = MS_LNFMT_FLAT; 3927141cc406Sopenharmony_ci break; 3928141cc406Sopenharmony_ci case MS_MODE_GRAY: 3929141cc406Sopenharmony_ci if (s->bits_per_color < 8) { 3930141cc406Sopenharmony_ci s->pixel_bpl = linewidth; 3931141cc406Sopenharmony_ci s->ppl = linewidth * (8 / s->bits_per_color); 3932141cc406Sopenharmony_ci } else { 3933141cc406Sopenharmony_ci s->pixel_bpl = linewidth * ((s->bits_per_color + 7) / 8); 3934141cc406Sopenharmony_ci s->ppl = linewidth; 3935141cc406Sopenharmony_ci } 3936141cc406Sopenharmony_ci s->header_bpl = 0; 3937141cc406Sopenharmony_ci s->planes = 1; 3938141cc406Sopenharmony_ci s->line_format = MS_LNFMT_FLAT; 3939141cc406Sopenharmony_ci break; 3940141cc406Sopenharmony_ci case MS_MODE_COLOR: 3941141cc406Sopenharmony_ci switch (s->color_seq) { 3942141cc406Sopenharmony_ci case MI_COLSEQ_PLANE: 3943141cc406Sopenharmony_ci s->pixel_bpl = linewidth * ((s->bits_per_color + 7) / 8); 3944141cc406Sopenharmony_ci s->ppl = linewidth; 3945141cc406Sopenharmony_ci s->header_bpl = 0; 3946141cc406Sopenharmony_ci s->planes = 1; 3947141cc406Sopenharmony_ci s->line_format = MS_LNFMT_FLAT; 3948141cc406Sopenharmony_ci break; 3949141cc406Sopenharmony_ci case MI_COLSEQ_NONRGB: 3950141cc406Sopenharmony_ci s->pixel_bpl = (linewidth - 2) * 3 * ((s->bits_per_color + 7) / 8); 3951141cc406Sopenharmony_ci s->ppl = linewidth - 2; 3952141cc406Sopenharmony_ci s->header_bpl = 2 * 3; 3953141cc406Sopenharmony_ci s->planes = 3; 3954141cc406Sopenharmony_ci s->line_format = MS_LNFMT_GOOFY_RGB; 3955141cc406Sopenharmony_ci break; 3956141cc406Sopenharmony_ci case MI_COLSEQ_PIXEL: 3957141cc406Sopenharmony_ci s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8); 3958141cc406Sopenharmony_ci s->ppl = linewidth; 3959141cc406Sopenharmony_ci s->header_bpl = 0; 3960141cc406Sopenharmony_ci s->planes = 3; 3961141cc406Sopenharmony_ci s->line_format = MS_LNFMT_FLAT; 3962141cc406Sopenharmony_ci break; 3963141cc406Sopenharmony_ci case MI_COLSEQ_2PIXEL: 3964141cc406Sopenharmony_ci s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8); 3965141cc406Sopenharmony_ci s->ppl = linewidth; 3966141cc406Sopenharmony_ci s->header_bpl = 0; 3967141cc406Sopenharmony_ci s->planes = 3; 3968141cc406Sopenharmony_ci s->line_format = MS_LNFMT_SEQ_2R2G2B; 3969141cc406Sopenharmony_ci break; 3970141cc406Sopenharmony_ci case MI_COLSEQ_RGB: 3971141cc406Sopenharmony_ci s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8); 3972141cc406Sopenharmony_ci s->ppl = linewidth; 3973141cc406Sopenharmony_ci s->header_bpl = 0; 3974141cc406Sopenharmony_ci s->planes = 3; 3975141cc406Sopenharmony_ci s->line_format = MS_LNFMT_SEQ_RGB; 3976141cc406Sopenharmony_ci break; 3977141cc406Sopenharmony_ci default: 3978141cc406Sopenharmony_ci DBG(10, "sane_start: Unknown color_sequence: %d\n", 3979141cc406Sopenharmony_ci s->dev->info.color_sequence); 3980141cc406Sopenharmony_ci return end_scan(s, SANE_STATUS_INVAL); 3981141cc406Sopenharmony_ci } 3982141cc406Sopenharmony_ci break; 3983141cc406Sopenharmony_ci default: 3984141cc406Sopenharmony_ci DBG(10, "sane_start: Unknown scan mode: %d\n", s->mode); 3985141cc406Sopenharmony_ci return end_scan(s, SANE_STATUS_INVAL); 3986141cc406Sopenharmony_ci } 3987141cc406Sopenharmony_ci 3988141cc406Sopenharmony_ci if ((s->doexpansion) && 3989141cc406Sopenharmony_ci (s->resolution > s->dev->info.base_resolution)) { 3990141cc406Sopenharmony_ci s->dest_ppl = (int) ((double)s->ppl * 3991141cc406Sopenharmony_ci (double)s->resolution / 3992141cc406Sopenharmony_ci (double)s->dev->info.base_resolution); 3993141cc406Sopenharmony_ci /*+ 0.5 XXXXXX */ 3994141cc406Sopenharmony_ci s->exp_aspect = (double)s->ppl / (double)s->dest_ppl; 3995141cc406Sopenharmony_ci s->dest_pixel_bpl = (int) ceil((double)s->pixel_bpl / s->exp_aspect); 3996141cc406Sopenharmony_ci /*s->exp_aspect = 3997141cc406Sopenharmony_ci (double) s->dev->info.base_resolution / (double) s->resolution;*/ 3998141cc406Sopenharmony_ci /* s->dest_pixel_bpl = s->pixel_bpl / s->exp_aspect; 3999141cc406Sopenharmony_ci s->dest_ppl = s->ppl / s->exp_aspect;*/ 4000141cc406Sopenharmony_ci /*s->dest_ppl = s->ppl / s->exp_aspect; 4001141cc406Sopenharmony_ci s->dest_pixel_bpl = (int) ceil((double)s->dest_ppl * 4002141cc406Sopenharmony_ci (double)s->pixel_bpl / 4003141cc406Sopenharmony_ci (double)s->ppl);*/ 4004141cc406Sopenharmony_ci } else { 4005141cc406Sopenharmony_ci s->exp_aspect = 1.0; 4006141cc406Sopenharmony_ci s->dest_pixel_bpl = s->pixel_bpl; 4007141cc406Sopenharmony_ci s->dest_ppl = s->ppl; 4008141cc406Sopenharmony_ci } 4009141cc406Sopenharmony_ci 4010141cc406Sopenharmony_ci s->params.lines = s->unscanned_lines; 4011141cc406Sopenharmony_ci s->params.pixels_per_line = s->dest_ppl; 4012141cc406Sopenharmony_ci s->params.bytes_per_line = s->dest_pixel_bpl; 4013141cc406Sopenharmony_ci 4014141cc406Sopenharmony_ci /* calculate maximum line capacity of SCSI buffer */ 4015141cc406Sopenharmony_ci s->max_scsi_lines = SCSI_BUFF_SIZE / (s->pixel_bpl + s->header_bpl); 4016141cc406Sopenharmony_ci if (s->max_scsi_lines < 1) { 4017141cc406Sopenharmony_ci DBG(10, "sane_start: SCSI buffer smaller that one scan line!\n"); 4018141cc406Sopenharmony_ci return end_scan(s, SANE_STATUS_NO_MEM); 4019141cc406Sopenharmony_ci } 4020141cc406Sopenharmony_ci 4021141cc406Sopenharmony_ci s->scsi_buffer = (uint8_t *) malloc(SCSI_BUFF_SIZE * sizeof(uint8_t)); 4022141cc406Sopenharmony_ci if (s->scsi_buffer == NULL) return SANE_STATUS_NO_MEM; 4023141cc406Sopenharmony_ci 4024141cc406Sopenharmony_ci /* what's a good initial size for this? */ 4025141cc406Sopenharmony_ci s->rb = ring_alloc(s->max_scsi_lines * s->dest_pixel_bpl, 4026141cc406Sopenharmony_ci s->dest_pixel_bpl, s->dest_ppl); 4027141cc406Sopenharmony_ci 4028141cc406Sopenharmony_ci s->undelivered_bytes = s->unscanned_lines * s->dest_pixel_bpl; 4029141cc406Sopenharmony_ci 4030141cc406Sopenharmony_ci DBG(23, "Scan Param:\n"); 4031141cc406Sopenharmony_ci DBG(23, "pix bpl: %d hdr bpl: %d ppl: %d\n", 4032141cc406Sopenharmony_ci s->pixel_bpl, s->header_bpl, s->ppl); 4033141cc406Sopenharmony_ci DBG(23, "undel bytes: %d unscan lines: %d planes: %d\n", 4034141cc406Sopenharmony_ci s->undelivered_bytes, s->unscanned_lines, s->planes); 4035141cc406Sopenharmony_ci DBG(23, "dest bpl: %d dest ppl: %d aspect: %f\n", 4036141cc406Sopenharmony_ci s->dest_pixel_bpl, s->dest_ppl, s->exp_aspect); 4037141cc406Sopenharmony_ci 4038141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4039141cc406Sopenharmony_ci} 4040141cc406Sopenharmony_ci 4041141cc406Sopenharmony_ci 4042141cc406Sopenharmony_ciSANE_Status 4043141cc406Sopenharmony_cisane_start (SANE_Handle handle) 4044141cc406Sopenharmony_ci{ 4045141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 4046141cc406Sopenharmony_ci SANE_Status status; 4047141cc406Sopenharmony_ci 4048141cc406Sopenharmony_ci s->woe = SANE_TRUE; 4049141cc406Sopenharmony_ci status = sane_start_guts(handle); 4050141cc406Sopenharmony_ci s->woe = SANE_FALSE; 4051141cc406Sopenharmony_ci return status; 4052141cc406Sopenharmony_ci} 4053141cc406Sopenharmony_ci 4054141cc406Sopenharmony_ci 4055141cc406Sopenharmony_ci 4056141cc406Sopenharmony_ci/********************************************************************/ 4057141cc406Sopenharmony_ci/* sane_read */ 4058141cc406Sopenharmony_ci/********************************************************************/ 4059141cc406Sopenharmony_cistatic SANE_Status 4060141cc406Sopenharmony_cisane_read_guts (SANE_Handle handle, SANE_Byte *dest_buffer, 4061141cc406Sopenharmony_ci SANE_Int dest_length, SANE_Int *ret_length) 4062141cc406Sopenharmony_ci{ 4063141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 4064141cc406Sopenharmony_ci SANE_Status status; 4065141cc406Sopenharmony_ci int nlines; 4066141cc406Sopenharmony_ci ring_buffer *rb = s->rb; 4067141cc406Sopenharmony_ci 4068141cc406Sopenharmony_ci DBG(10, "sane_read...\n"); 4069141cc406Sopenharmony_ci 4070141cc406Sopenharmony_ci *ret_length = 0; /* default: no data */ 4071141cc406Sopenharmony_ci /* we have been cancelled... */ 4072141cc406Sopenharmony_ci if (s->cancel) return end_scan(s, SANE_STATUS_CANCELLED); 4073141cc406Sopenharmony_ci /* we're not really scanning!... */ 4074141cc406Sopenharmony_ci if (!(s->scanning)) return SANE_STATUS_INVAL; 4075141cc406Sopenharmony_ci /* we are done scanning... */ 4076141cc406Sopenharmony_ci if (s->undelivered_bytes <= 0) return end_scan(s, SANE_STATUS_EOF); 4077141cc406Sopenharmony_ci 4078141cc406Sopenharmony_ci /* get more bytes if our ring is empty... */ 4079141cc406Sopenharmony_ci while (rb->complete_count == 0) { 4080141cc406Sopenharmony_ci if ((status = read_from_scanner(s, &nlines)) != SANE_STATUS_GOOD) { 4081141cc406Sopenharmony_ci DBG(18, "sane_read: read_from_scanner failed.\n"); 4082141cc406Sopenharmony_ci return end_scan(s, status); 4083141cc406Sopenharmony_ci } 4084141cc406Sopenharmony_ci if ((status = pack_into_ring(s, nlines)) != SANE_STATUS_GOOD) { 4085141cc406Sopenharmony_ci DBG(18, "sane_read: pack_into_ring failed.\n"); 4086141cc406Sopenharmony_ci return end_scan(s, status); 4087141cc406Sopenharmony_ci } 4088141cc406Sopenharmony_ci } 4089141cc406Sopenharmony_ci /* return some data to caller */ 4090141cc406Sopenharmony_ci *ret_length = pack_into_dest(dest_buffer, dest_length, rb); 4091141cc406Sopenharmony_ci s->undelivered_bytes -= *ret_length; 4092141cc406Sopenharmony_ci 4093141cc406Sopenharmony_ci if (s->cancel) return end_scan(s, SANE_STATUS_CANCELLED); 4094141cc406Sopenharmony_ci 4095141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4096141cc406Sopenharmony_ci} 4097141cc406Sopenharmony_ci 4098141cc406Sopenharmony_ci 4099141cc406Sopenharmony_ciSANE_Status 4100141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte *dest_buffer, 4101141cc406Sopenharmony_ci SANE_Int dest_length, SANE_Int *ret_length) 4102141cc406Sopenharmony_ci{ 4103141cc406Sopenharmony_ci Microtek_Scanner *s = handle; 4104141cc406Sopenharmony_ci SANE_Status status; 4105141cc406Sopenharmony_ci 4106141cc406Sopenharmony_ci s->woe = SANE_TRUE; 4107141cc406Sopenharmony_ci status = sane_read_guts(handle, dest_buffer, dest_length, ret_length); 4108141cc406Sopenharmony_ci s->woe = SANE_FALSE; 4109141cc406Sopenharmony_ci return status; 4110141cc406Sopenharmony_ci} 4111141cc406Sopenharmony_ci 4112141cc406Sopenharmony_ci 4113141cc406Sopenharmony_ci 4114141cc406Sopenharmony_ci/********************************************************************/ 4115141cc406Sopenharmony_ci/* sane_exit */ 4116141cc406Sopenharmony_ci/********************************************************************/ 4117141cc406Sopenharmony_civoid 4118141cc406Sopenharmony_cisane_exit (void) 4119141cc406Sopenharmony_ci{ 4120141cc406Sopenharmony_ci Microtek_Device *next; 4121141cc406Sopenharmony_ci 4122141cc406Sopenharmony_ci DBG(10, "sane_exit...\n"); 4123141cc406Sopenharmony_ci /* close all leftover Scanners */ 4124141cc406Sopenharmony_ci /*(beware of how sane_close interacts with linked list) */ 4125141cc406Sopenharmony_ci while (first_handle != NULL) 4126141cc406Sopenharmony_ci sane_close(first_handle); 4127141cc406Sopenharmony_ci /* free up device list */ 4128141cc406Sopenharmony_ci while (first_dev != NULL) { 4129141cc406Sopenharmony_ci next = first_dev->next; 4130141cc406Sopenharmony_ci free((void *) first_dev->sane.name); 4131141cc406Sopenharmony_ci free((void *) first_dev->sane.model); 4132141cc406Sopenharmony_ci free(first_dev); 4133141cc406Sopenharmony_ci first_dev = next; 4134141cc406Sopenharmony_ci } 4135141cc406Sopenharmony_ci /* the devlist allocated by sane_get_devices */ 4136141cc406Sopenharmony_ci free(devlist); 4137141cc406Sopenharmony_ci DBG(10, "sane_exit: MICROTEK says goodbye.\n"); 4138141cc406Sopenharmony_ci} 4139141cc406Sopenharmony_ci 4140141cc406Sopenharmony_ci 4141141cc406Sopenharmony_ci 4142141cc406Sopenharmony_ci/********************************************************************/ 4143141cc406Sopenharmony_ci/* sane_cancel */ 4144141cc406Sopenharmony_ci/********************************************************************/ 4145141cc406Sopenharmony_civoid 4146141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 4147141cc406Sopenharmony_ci{ 4148141cc406Sopenharmony_ci Microtek_Scanner *ms = handle; 4149141cc406Sopenharmony_ci DBG(10, "sane_cancel...\n"); 4150141cc406Sopenharmony_ci ms->cancel = SANE_TRUE; 4151141cc406Sopenharmony_ci if (!(ms->woe)) end_scan(ms, SANE_STATUS_CANCELLED); 4152141cc406Sopenharmony_ci} 4153141cc406Sopenharmony_ci 4154141cc406Sopenharmony_ci 4155141cc406Sopenharmony_ci 4156141cc406Sopenharmony_ci/********************************************************************/ 4157141cc406Sopenharmony_ci/* sane_set_io_mode */ 4158141cc406Sopenharmony_ci/********************************************************************/ 4159141cc406Sopenharmony_ciSANE_Status 4160141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 4161141cc406Sopenharmony_ci{ 4162141cc406Sopenharmony_ci DBG(10, "sane_set_io_mode...\n"); 4163141cc406Sopenharmony_ci (void) handle; 4164141cc406Sopenharmony_ci if (non_blocking) 4165141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 4166141cc406Sopenharmony_ci else 4167141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4168141cc406Sopenharmony_ci} 4169141cc406Sopenharmony_ci 4170141cc406Sopenharmony_ci 4171141cc406Sopenharmony_ci 4172141cc406Sopenharmony_ci/********************************************************************/ 4173141cc406Sopenharmony_ci/* sane_get_select_fd */ 4174141cc406Sopenharmony_ci/********************************************************************/ 4175141cc406Sopenharmony_ciSANE_Status 4176141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 4177141cc406Sopenharmony_ci{ 4178141cc406Sopenharmony_ci DBG(10, "sane_get_select_fd...\n"); 4179141cc406Sopenharmony_ci (void) handle, (void) fd; 4180141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 4181141cc406Sopenharmony_ci} 4182