1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2000 Mustek. 4141cc406Sopenharmony_ci Originally maintained by Tom Wang <tom.wang@mustek.com.tw> 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci Copyright (C) 2001 - 2004 by Henning Meier-Geinitz. 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 This file implements a SANE backend for Mustek 1200UB and similar 45141cc406Sopenharmony_ci USB flatbed scanners. */ 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#define BUILD 18 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci#include "../include/sane/config.h" 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci#include <ctype.h> 52141cc406Sopenharmony_ci#include <errno.h> 53141cc406Sopenharmony_ci#include <fcntl.h> 54141cc406Sopenharmony_ci#include <limits.h> 55141cc406Sopenharmony_ci#include <signal.h> 56141cc406Sopenharmony_ci#include <stdio.h> 57141cc406Sopenharmony_ci#include <stdlib.h> 58141cc406Sopenharmony_ci#include <string.h> 59141cc406Sopenharmony_ci#include <unistd.h> 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci#include <sys/time.h> 62141cc406Sopenharmony_ci#include <sys/types.h> 63141cc406Sopenharmony_ci#include <sys/wait.h> 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci#include "../include/sane/sane.h" 66141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 67141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 68141cc406Sopenharmony_ci 69141cc406Sopenharmony_ci#define BACKEND_NAME mustek_usb 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 73141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci#include "mustek_usb.h" 76141cc406Sopenharmony_ci#include "mustek_usb_high.c" 77141cc406Sopenharmony_ci 78141cc406Sopenharmony_ci#ifndef SANE_I18N 79141cc406Sopenharmony_ci#define SANE_I18N(text) text 80141cc406Sopenharmony_ci#endif 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_cistatic SANE_Int num_devices; 83141cc406Sopenharmony_cistatic Mustek_Usb_Device *first_dev; 84141cc406Sopenharmony_cistatic Mustek_Usb_Scanner *first_handle; 85141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci/* Maximum amount of data read in one turn from USB. */ 88141cc406Sopenharmony_cistatic SANE_Word max_block_size = (8 * 1024); 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_ci/* Array of newly attached devices */ 91141cc406Sopenharmony_cistatic Mustek_Usb_Device **new_dev; 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci/* Length of new_dev array */ 94141cc406Sopenharmony_cistatic SANE_Int new_dev_len; 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci/* Number of entries allocated for new_dev */ 97141cc406Sopenharmony_cistatic SANE_Int new_dev_alloced; 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_cistatic SANE_String_Const mode_list[6]; 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_cistatic const SANE_Range u8_range = { 102141cc406Sopenharmony_ci 0, /* minimum */ 103141cc406Sopenharmony_ci 255, /* maximum */ 104141cc406Sopenharmony_ci 0 /* quantization */ 105141cc406Sopenharmony_ci}; 106141cc406Sopenharmony_ci 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_cistatic size_t 109141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 110141cc406Sopenharmony_ci{ 111141cc406Sopenharmony_ci size_t size, max_size = 0; 112141cc406Sopenharmony_ci SANE_Int i; 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 115141cc406Sopenharmony_ci { 116141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 117141cc406Sopenharmony_ci if (size > max_size) 118141cc406Sopenharmony_ci max_size = size; 119141cc406Sopenharmony_ci } 120141cc406Sopenharmony_ci return max_size; 121141cc406Sopenharmony_ci} 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_cistatic SANE_Status 125141cc406Sopenharmony_cicalc_parameters (Mustek_Usb_Scanner * s) 126141cc406Sopenharmony_ci{ 127141cc406Sopenharmony_ci SANE_String val; 128141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 129141cc406Sopenharmony_ci SANE_Int max_x, max_y; 130141cc406Sopenharmony_ci 131141cc406Sopenharmony_ci DBG (5, "calc_parameters: start\n"); 132141cc406Sopenharmony_ci val = s->val[OPT_MODE].s; 133141cc406Sopenharmony_ci 134141cc406Sopenharmony_ci s->params.last_frame = SANE_TRUE; 135141cc406Sopenharmony_ci 136141cc406Sopenharmony_ci if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) 137141cc406Sopenharmony_ci { 138141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 139141cc406Sopenharmony_ci s->params.depth = 1; 140141cc406Sopenharmony_ci s->bpp = 1; 141141cc406Sopenharmony_ci s->channels = 1; 142141cc406Sopenharmony_ci } 143141cc406Sopenharmony_ci else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) 144141cc406Sopenharmony_ci { 145141cc406Sopenharmony_ci s->params.format = SANE_FRAME_GRAY; 146141cc406Sopenharmony_ci s->params.depth = 8; 147141cc406Sopenharmony_ci s->bpp = 8; 148141cc406Sopenharmony_ci s->channels = 1; 149141cc406Sopenharmony_ci } 150141cc406Sopenharmony_ci else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR)) 151141cc406Sopenharmony_ci { 152141cc406Sopenharmony_ci s->params.format = SANE_FRAME_RGB; 153141cc406Sopenharmony_ci s->params.depth = 8; 154141cc406Sopenharmony_ci s->bpp = 24; 155141cc406Sopenharmony_ci s->channels = 3; 156141cc406Sopenharmony_ci } 157141cc406Sopenharmony_ci else 158141cc406Sopenharmony_ci { 159141cc406Sopenharmony_ci DBG (1, "calc_parameters: invalid mode %s\n", (SANE_Char *) val); 160141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 161141cc406Sopenharmony_ci } 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH; 164141cc406Sopenharmony_ci s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH; 165141cc406Sopenharmony_ci s->width = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH - s->tl_x; 166141cc406Sopenharmony_ci s->height = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH - s->tl_y; 167141cc406Sopenharmony_ci 168141cc406Sopenharmony_ci if (s->width < 0) 169141cc406Sopenharmony_ci { 170141cc406Sopenharmony_ci DBG (1, "calc_parameters: warning: tl_x > br_x\n"); 171141cc406Sopenharmony_ci } 172141cc406Sopenharmony_ci if (s->height < 0) 173141cc406Sopenharmony_ci { 174141cc406Sopenharmony_ci DBG (1, "calc_parameters: warning: tl_y > br_y\n"); 175141cc406Sopenharmony_ci } 176141cc406Sopenharmony_ci max_x = s->hw->max_width * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; 177141cc406Sopenharmony_ci max_y = s->hw->max_height * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci s->tl_x_dots = s->tl_x * SANE_UNFIX (s->val[OPT_RESOLUTION].w); 180141cc406Sopenharmony_ci s->width_dots = s->width * SANE_UNFIX (s->val[OPT_RESOLUTION].w); 181141cc406Sopenharmony_ci s->tl_y_dots = s->tl_y * SANE_UNFIX (s->val[OPT_RESOLUTION].w); 182141cc406Sopenharmony_ci s->height_dots = s->height * SANE_UNFIX (s->val[OPT_RESOLUTION].w); 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci if (s->width_dots > max_x) 185141cc406Sopenharmony_ci s->width_dots = max_x; 186141cc406Sopenharmony_ci if (s->height_dots > max_y) 187141cc406Sopenharmony_ci s->height_dots = max_y; 188141cc406Sopenharmony_ci if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) 189141cc406Sopenharmony_ci { 190141cc406Sopenharmony_ci s->width_dots = (s->width_dots / 8) * 8; 191141cc406Sopenharmony_ci if (s->width_dots == 0) 192141cc406Sopenharmony_ci s->width_dots = 8; 193141cc406Sopenharmony_ci } 194141cc406Sopenharmony_ci if (s->tl_x_dots < 0) 195141cc406Sopenharmony_ci s->tl_x_dots = 0; 196141cc406Sopenharmony_ci if (s->tl_y_dots < 0) 197141cc406Sopenharmony_ci s->tl_y_dots = 0; 198141cc406Sopenharmony_ci if (s->tl_x_dots + s->width_dots > max_x) 199141cc406Sopenharmony_ci s->tl_x_dots = max_x - s->width_dots; 200141cc406Sopenharmony_ci if (s->tl_y_dots + s->height_dots > max_y) 201141cc406Sopenharmony_ci s->tl_y_dots = max_y - s->height_dots; 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci s->val[OPT_TL_X].w = SANE_FIX (s->tl_x * MM_PER_INCH); 204141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = SANE_FIX (s->tl_y * MM_PER_INCH); 205141cc406Sopenharmony_ci s->val[OPT_BR_X].w = SANE_FIX ((s->tl_x + s->width) * MM_PER_INCH); 206141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = SANE_FIX ((s->tl_y + s->height) * MM_PER_INCH); 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci s->params.pixels_per_line = s->width_dots; 209141cc406Sopenharmony_ci if (s->params.pixels_per_line < 0) 210141cc406Sopenharmony_ci s->params.pixels_per_line = 0; 211141cc406Sopenharmony_ci s->params.lines = s->height_dots; 212141cc406Sopenharmony_ci if (s->params.lines < 0) 213141cc406Sopenharmony_ci s->params.lines = 0; 214141cc406Sopenharmony_ci s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8 215141cc406Sopenharmony_ci * s->channels; 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci DBG (4, "calc_parameters: format=%d\n", s->params.format); 218141cc406Sopenharmony_ci DBG (4, "calc_parameters: last frame=%d\n", s->params.last_frame); 219141cc406Sopenharmony_ci DBG (4, "calc_parameters: lines=%d\n", s->params.lines); 220141cc406Sopenharmony_ci DBG (4, "calc_parameters: pixels per line=%d\n", s->params.pixels_per_line); 221141cc406Sopenharmony_ci DBG (4, "calc_parameters: bytes per line=%d\n", s->params.bytes_per_line); 222141cc406Sopenharmony_ci DBG (4, "calc_parameters: Pixels %dx%dx%d\n", 223141cc406Sopenharmony_ci s->params.pixels_per_line, s->params.lines, 1 << s->params.depth); 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci DBG (5, "calc_parameters: exit\n"); 226141cc406Sopenharmony_ci return status; 227141cc406Sopenharmony_ci} 228141cc406Sopenharmony_ci 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_cistatic SANE_Status 231141cc406Sopenharmony_ciinit_options (Mustek_Usb_Scanner * s) 232141cc406Sopenharmony_ci{ 233141cc406Sopenharmony_ci SANE_Int option; 234141cc406Sopenharmony_ci SANE_Status status; 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci DBG (5, "init_options: start\n"); 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci memset (s->opt, 0, sizeof (s->opt)); 239141cc406Sopenharmony_ci memset (s->val, 0, sizeof (s->val)); 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ci for (option = 0; option < NUM_OPTIONS; ++option) 242141cc406Sopenharmony_ci { 243141cc406Sopenharmony_ci s->opt[option].size = sizeof (SANE_Word); 244141cc406Sopenharmony_ci s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 245141cc406Sopenharmony_ci } 246141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 247141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 248141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 249141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 250141cc406Sopenharmony_ci s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 251141cc406Sopenharmony_ci s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 252141cc406Sopenharmony_ci 253141cc406Sopenharmony_ci /* "Mode" group: */ 254141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); 255141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].desc = ""; 256141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 257141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].size = 0; 258141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].cap = 0; 259141cc406Sopenharmony_ci s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci /* scan mode */ 262141cc406Sopenharmony_ci mode_list[0] = SANE_VALUE_SCAN_MODE_COLOR; 263141cc406Sopenharmony_ci mode_list[1] = SANE_VALUE_SCAN_MODE_GRAY; 264141cc406Sopenharmony_ci mode_list[2] = SANE_VALUE_SCAN_MODE_LINEART; 265141cc406Sopenharmony_ci mode_list[3] = NULL; 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_ci s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 268141cc406Sopenharmony_ci s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 269141cc406Sopenharmony_ci s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 270141cc406Sopenharmony_ci s->opt[OPT_MODE].type = SANE_TYPE_STRING; 271141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 272141cc406Sopenharmony_ci s->opt[OPT_MODE].size = max_string_size (mode_list); 273141cc406Sopenharmony_ci s->opt[OPT_MODE].constraint.string_list = mode_list; 274141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (mode_list[1]); 275141cc406Sopenharmony_ci 276141cc406Sopenharmony_ci /* resolution */ 277141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 278141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 279141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 280141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; 281141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 282141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; 283141cc406Sopenharmony_ci s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; 284141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; 285141cc406Sopenharmony_ci if (s->hw->chip->scanner_type == MT_600CU) 286141cc406Sopenharmony_ci s->hw->dpi_range.max = SANE_FIX (600); 287141cc406Sopenharmony_ci else 288141cc406Sopenharmony_ci s->hw->dpi_range.max = SANE_FIX (1200); 289141cc406Sopenharmony_ci 290141cc406Sopenharmony_ci /* preview */ 291141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 292141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 293141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 294141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 295141cc406Sopenharmony_ci s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 296141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = SANE_FALSE; 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci /* "Geometry" group: */ 299141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); 300141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].desc = ""; 301141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 302141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 303141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].size = 0; 304141cc406Sopenharmony_ci s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci /* top-left x */ 307141cc406Sopenharmony_ci s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 308141cc406Sopenharmony_ci s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 309141cc406Sopenharmony_ci s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 310141cc406Sopenharmony_ci s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 311141cc406Sopenharmony_ci s->opt[OPT_TL_X].unit = SANE_UNIT_MM; 312141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 313141cc406Sopenharmony_ci s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; 314141cc406Sopenharmony_ci s->val[OPT_TL_X].w = 0; 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_ci /* top-left y */ 317141cc406Sopenharmony_ci s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 318141cc406Sopenharmony_ci s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 319141cc406Sopenharmony_ci s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 320141cc406Sopenharmony_ci s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 321141cc406Sopenharmony_ci s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 322141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 323141cc406Sopenharmony_ci s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; 324141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = 0; 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci /* bottom-right x */ 327141cc406Sopenharmony_ci s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 328141cc406Sopenharmony_ci s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 329141cc406Sopenharmony_ci s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 330141cc406Sopenharmony_ci s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 331141cc406Sopenharmony_ci s->opt[OPT_BR_X].unit = SANE_UNIT_MM; 332141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 333141cc406Sopenharmony_ci s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; 334141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->hw->x_range.max; 335141cc406Sopenharmony_ci 336141cc406Sopenharmony_ci /* bottom-right y */ 337141cc406Sopenharmony_ci s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 338141cc406Sopenharmony_ci s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 339141cc406Sopenharmony_ci s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 340141cc406Sopenharmony_ci s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 341141cc406Sopenharmony_ci s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 342141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 343141cc406Sopenharmony_ci s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; 344141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->hw->y_range.max; 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci /* "Enhancement" group: */ 347141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); 348141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; 349141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 350141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].size = 0; 351141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; 352141cc406Sopenharmony_ci s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 353141cc406Sopenharmony_ci 354141cc406Sopenharmony_ci /* threshold */ 355141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 356141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 357141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 358141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; 359141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; 360141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 361141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].constraint.range = &u8_range; 362141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 363141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = 128; 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci /* custom-gamma table */ 366141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 367141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 368141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 369141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 370141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; 371141cc406Sopenharmony_ci 372141cc406Sopenharmony_ci /* gray gamma vector */ 373141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 374141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 375141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 376141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 377141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 378141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 379141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); 380141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 381141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; 382141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR].wa = &s->gray_gamma_table[0]; 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci /* red gamma vector */ 385141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 386141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 387141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 388141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 389141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 390141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 391141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); 392141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 393141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; 394141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_R].wa = &s->red_gamma_table[0]; 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci /* green gamma vector */ 397141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 398141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 399141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 400141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 401141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 402141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 403141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); 404141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 405141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; 406141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_G].wa = &s->green_gamma_table[0]; 407141cc406Sopenharmony_ci 408141cc406Sopenharmony_ci /* blue gamma vector */ 409141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 410141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 411141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 412141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 413141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 414141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 415141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); 416141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 417141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; 418141cc406Sopenharmony_ci s->val[OPT_GAMMA_VECTOR_B].wa = &s->blue_gamma_table[0]; 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci RIE (calc_parameters (s)); 421141cc406Sopenharmony_ci 422141cc406Sopenharmony_ci DBG (5, "init_options: exit\n"); 423141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 424141cc406Sopenharmony_ci} 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_cistatic SANE_Status 428141cc406Sopenharmony_ciattach (SANE_String_Const devname, Mustek_Usb_Device ** devp, 429141cc406Sopenharmony_ci SANE_Bool may_wait) 430141cc406Sopenharmony_ci{ 431141cc406Sopenharmony_ci Mustek_Usb_Device *dev; 432141cc406Sopenharmony_ci SANE_Status status; 433141cc406Sopenharmony_ci Mustek_Type scanner_type; 434141cc406Sopenharmony_ci SANE_Int fd; 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci DBG (5, "attach: start: devp %s NULL, may_wait = %d\n", devp ? "!=" : "==", 437141cc406Sopenharmony_ci may_wait); 438141cc406Sopenharmony_ci if (!devname) 439141cc406Sopenharmony_ci { 440141cc406Sopenharmony_ci DBG (1, "attach: devname == NULL\n"); 441141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 442141cc406Sopenharmony_ci } 443141cc406Sopenharmony_ci 444141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 445141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devname) == 0) 446141cc406Sopenharmony_ci { 447141cc406Sopenharmony_ci if (devp) 448141cc406Sopenharmony_ci *devp = dev; 449141cc406Sopenharmony_ci DBG (4, "attach: device `%s' was already in device list\n", devname); 450141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 451141cc406Sopenharmony_ci } 452141cc406Sopenharmony_ci 453141cc406Sopenharmony_ci DBG (4, "attach: trying to open device `%s'\n", devname); 454141cc406Sopenharmony_ci status = sanei_usb_open (devname, &fd); 455141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 456141cc406Sopenharmony_ci { 457141cc406Sopenharmony_ci DBG (3, "attach: couldn't open device `%s': %s\n", devname, 458141cc406Sopenharmony_ci sane_strstatus (status)); 459141cc406Sopenharmony_ci return status; 460141cc406Sopenharmony_ci } 461141cc406Sopenharmony_ci DBG (4, "attach: device `%s' successfully opened\n", devname); 462141cc406Sopenharmony_ci 463141cc406Sopenharmony_ci /* try to identify model */ 464141cc406Sopenharmony_ci DBG (4, "attach: trying to identify device `%s'\n", devname); 465141cc406Sopenharmony_ci status = usb_low_identify_scanner (fd, &scanner_type); 466141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 467141cc406Sopenharmony_ci { 468141cc406Sopenharmony_ci DBG (1, "attach: device `%s' doesn't look like a supported scanner\n", 469141cc406Sopenharmony_ci devname); 470141cc406Sopenharmony_ci sanei_usb_close (fd); 471141cc406Sopenharmony_ci return status; 472141cc406Sopenharmony_ci } 473141cc406Sopenharmony_ci sanei_usb_close (fd); 474141cc406Sopenharmony_ci if (scanner_type == MT_UNKNOWN) 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci DBG (3, "attach: warning: couldn't identify device `%s', must set " 477141cc406Sopenharmony_ci "type manually\n", devname); 478141cc406Sopenharmony_ci } 479141cc406Sopenharmony_ci 480141cc406Sopenharmony_ci dev = malloc (sizeof (Mustek_Usb_Device)); 481141cc406Sopenharmony_ci if (!dev) 482141cc406Sopenharmony_ci { 483141cc406Sopenharmony_ci DBG (1, "attach: couldn't malloc Mustek_Usb_Device\n"); 484141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 485141cc406Sopenharmony_ci } 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci memset (dev, 0, sizeof (*dev)); 488141cc406Sopenharmony_ci dev->name = strdup (devname); 489141cc406Sopenharmony_ci dev->sane.name = (SANE_String_Const) dev->name; 490141cc406Sopenharmony_ci dev->sane.vendor = "Mustek"; 491141cc406Sopenharmony_ci switch (scanner_type) 492141cc406Sopenharmony_ci { 493141cc406Sopenharmony_ci case MT_1200CU: 494141cc406Sopenharmony_ci dev->sane.model = "1200 CU"; 495141cc406Sopenharmony_ci break; 496141cc406Sopenharmony_ci case MT_1200CU_PLUS: 497141cc406Sopenharmony_ci dev->sane.model = "1200 CU Plus"; 498141cc406Sopenharmony_ci break; 499141cc406Sopenharmony_ci case MT_1200USB: 500141cc406Sopenharmony_ci dev->sane.model = "1200 USB (unsupported)"; 501141cc406Sopenharmony_ci break; 502141cc406Sopenharmony_ci case MT_1200UB: 503141cc406Sopenharmony_ci dev->sane.model = "1200 UB"; 504141cc406Sopenharmony_ci break; 505141cc406Sopenharmony_ci case MT_600CU: 506141cc406Sopenharmony_ci dev->sane.model = "600 CU"; 507141cc406Sopenharmony_ci break; 508141cc406Sopenharmony_ci case MT_600USB: 509141cc406Sopenharmony_ci dev->sane.model = "600 USB (unsupported)"; 510141cc406Sopenharmony_ci break; 511141cc406Sopenharmony_ci default: 512141cc406Sopenharmony_ci dev->sane.model = "(unidentified)"; 513141cc406Sopenharmony_ci break; 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci dev->sane.type = "flatbed scanner"; 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci dev->x_range.min = 0; 518141cc406Sopenharmony_ci dev->x_range.max = SANE_FIX (8.4 * MM_PER_INCH); 519141cc406Sopenharmony_ci dev->x_range.quant = 0; 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci dev->y_range.min = 0; 522141cc406Sopenharmony_ci dev->y_range.max = SANE_FIX (11.7 * MM_PER_INCH); 523141cc406Sopenharmony_ci dev->y_range.quant = 0; 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci dev->max_height = 11.7 * 300; 526141cc406Sopenharmony_ci dev->max_width = 8.4 * 300; 527141cc406Sopenharmony_ci dev->dpi_range.min = SANE_FIX (50); 528141cc406Sopenharmony_ci dev->dpi_range.max = SANE_FIX (600); 529141cc406Sopenharmony_ci dev->dpi_range.quant = SANE_FIX (1); 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci status = usb_high_scan_init (dev); 532141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 533141cc406Sopenharmony_ci { 534141cc406Sopenharmony_ci DBG (1, "attach: usb_high_scan_init returned status: %s\n", 535141cc406Sopenharmony_ci sane_strstatus (status)); 536141cc406Sopenharmony_ci free (dev); 537141cc406Sopenharmony_ci return status; 538141cc406Sopenharmony_ci } 539141cc406Sopenharmony_ci dev->chip->scanner_type = scanner_type; 540141cc406Sopenharmony_ci dev->chip->max_block_size = max_block_size; 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ci DBG (2, "attach: found %s %s %s at %s\n", dev->sane.vendor, dev->sane.type, 543141cc406Sopenharmony_ci dev->sane.model, dev->sane.name); 544141cc406Sopenharmony_ci ++num_devices; 545141cc406Sopenharmony_ci dev->next = first_dev; 546141cc406Sopenharmony_ci first_dev = dev; 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci if (devp) 549141cc406Sopenharmony_ci *devp = dev; 550141cc406Sopenharmony_ci 551141cc406Sopenharmony_ci DBG (5, "attach: exit\n"); 552141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 553141cc406Sopenharmony_ci} 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_cistatic SANE_Status 556141cc406Sopenharmony_ciattach_one_device (SANE_String_Const devname) 557141cc406Sopenharmony_ci{ 558141cc406Sopenharmony_ci Mustek_Usb_Device *dev; 559141cc406Sopenharmony_ci SANE_Status status; 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci RIE (attach (devname, &dev, SANE_FALSE)); 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci if (dev) 564141cc406Sopenharmony_ci { 565141cc406Sopenharmony_ci /* Keep track of newly attached devices so we can set options as 566141cc406Sopenharmony_ci necessary. */ 567141cc406Sopenharmony_ci if (new_dev_len >= new_dev_alloced) 568141cc406Sopenharmony_ci { 569141cc406Sopenharmony_ci new_dev_alloced += 4; 570141cc406Sopenharmony_ci if (new_dev) 571141cc406Sopenharmony_ci new_dev = 572141cc406Sopenharmony_ci realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); 573141cc406Sopenharmony_ci else 574141cc406Sopenharmony_ci new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); 575141cc406Sopenharmony_ci if (!new_dev) 576141cc406Sopenharmony_ci { 577141cc406Sopenharmony_ci DBG (1, "attach_one_device: out of memory\n"); 578141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 579141cc406Sopenharmony_ci } 580141cc406Sopenharmony_ci } 581141cc406Sopenharmony_ci new_dev[new_dev_len++] = dev; 582141cc406Sopenharmony_ci } 583141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 584141cc406Sopenharmony_ci} 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_cistatic SANE_Status 587141cc406Sopenharmony_cifit_lines (Mustek_Usb_Scanner * s, SANE_Byte * src, SANE_Byte * dst, 588141cc406Sopenharmony_ci SANE_Word src_lines, SANE_Word * dst_lines) 589141cc406Sopenharmony_ci{ 590141cc406Sopenharmony_ci SANE_Int threshold; 591141cc406Sopenharmony_ci SANE_Word src_width, dst_width; 592141cc406Sopenharmony_ci SANE_Word dst_pixel, src_pixel; 593141cc406Sopenharmony_ci SANE_Word dst_line, src_line; 594141cc406Sopenharmony_ci SANE_Word pixel_switch; 595141cc406Sopenharmony_ci SANE_Word src_address, dst_address; 596141cc406Sopenharmony_ci src_width = s->hw->width; 597141cc406Sopenharmony_ci dst_width = s->width_dots; 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci threshold = s->val[OPT_THRESHOLD].w; 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci DBG (5, "fit_lines: dst_width=%d, src_width=%d, src_lines=%d, " 602141cc406Sopenharmony_ci "offset=%d\n", dst_width, src_width, src_lines, s->hw->line_offset); 603141cc406Sopenharmony_ci 604141cc406Sopenharmony_ci dst_line = 0; 605141cc406Sopenharmony_ci src_line = s->hw->line_offset; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci while (src_line < src_lines) 608141cc406Sopenharmony_ci { 609141cc406Sopenharmony_ci DBG (5, "fit_lines: getting line: dst_line=%d, src_line=%d, " 610141cc406Sopenharmony_ci "line_switch=%d\n", dst_line, src_line, s->hw->line_switch); 611141cc406Sopenharmony_ci 612141cc406Sopenharmony_ci src_pixel = 0; 613141cc406Sopenharmony_ci pixel_switch = src_width; 614141cc406Sopenharmony_ci for (dst_pixel = 0; dst_pixel < dst_width; dst_pixel++) 615141cc406Sopenharmony_ci { 616141cc406Sopenharmony_ci while (pixel_switch > dst_width) 617141cc406Sopenharmony_ci { 618141cc406Sopenharmony_ci src_pixel++; 619141cc406Sopenharmony_ci pixel_switch -= dst_width; 620141cc406Sopenharmony_ci } 621141cc406Sopenharmony_ci pixel_switch += src_width; 622141cc406Sopenharmony_ci 623141cc406Sopenharmony_ci src_address = src_pixel * s->hw->bpp / 8 624141cc406Sopenharmony_ci + src_width * src_line * s->hw->bpp / 8; 625141cc406Sopenharmony_ci dst_address = dst_pixel * s->bpp / 8 626141cc406Sopenharmony_ci + dst_width * dst_line * s->bpp / 8; 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci if (s->bpp == 8) 629141cc406Sopenharmony_ci { 630141cc406Sopenharmony_ci dst[dst_address] = s->gray_table[src[src_address]]; 631141cc406Sopenharmony_ci } 632141cc406Sopenharmony_ci else if (s->bpp == 24) 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci dst[dst_address] 635141cc406Sopenharmony_ci = s->red_table[s->gray_table[src[src_address]]]; 636141cc406Sopenharmony_ci dst[dst_address + 1] 637141cc406Sopenharmony_ci = s->green_table[s->gray_table[src[src_address + 1]]]; 638141cc406Sopenharmony_ci dst[dst_address + 2] 639141cc406Sopenharmony_ci = s->blue_table[s->gray_table[src[src_address + 2]]]; 640141cc406Sopenharmony_ci } 641141cc406Sopenharmony_ci else /* lineart */ 642141cc406Sopenharmony_ci { 643141cc406Sopenharmony_ci if ((dst_pixel % 8) == 0) 644141cc406Sopenharmony_ci dst[dst_address] = 0; 645141cc406Sopenharmony_ci dst[dst_address] |= 646141cc406Sopenharmony_ci (((src[src_address] > threshold) ? 0 : 1) 647141cc406Sopenharmony_ci << (7 - (dst_pixel % 8))); 648141cc406Sopenharmony_ci } 649141cc406Sopenharmony_ci } 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci dst_line++; 652141cc406Sopenharmony_ci while (s->hw->line_switch >= s->height_dots) 653141cc406Sopenharmony_ci { 654141cc406Sopenharmony_ci src_line++; 655141cc406Sopenharmony_ci s->hw->line_switch -= s->height_dots; 656141cc406Sopenharmony_ci } 657141cc406Sopenharmony_ci s->hw->line_switch += s->hw->height; 658141cc406Sopenharmony_ci } 659141cc406Sopenharmony_ci 660141cc406Sopenharmony_ci *dst_lines = dst_line; 661141cc406Sopenharmony_ci s->hw->line_offset = (src_line - src_lines); 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci DBG (4, "fit_lines: exit, src_line=%d, *dst_lines=%d, offset=%d\n", 664141cc406Sopenharmony_ci src_line, *dst_lines, s->hw->line_offset); 665141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 666141cc406Sopenharmony_ci} 667141cc406Sopenharmony_ci 668141cc406Sopenharmony_cistatic SANE_Status 669141cc406Sopenharmony_cicheck_gamma_table (SANE_Word * table) 670141cc406Sopenharmony_ci{ 671141cc406Sopenharmony_ci SANE_Word entry, value; 672141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 673141cc406Sopenharmony_ci 674141cc406Sopenharmony_ci for (entry = 0; entry < 256; entry++) 675141cc406Sopenharmony_ci { 676141cc406Sopenharmony_ci value = table[entry]; 677141cc406Sopenharmony_ci if (value > 255) 678141cc406Sopenharmony_ci { 679141cc406Sopenharmony_ci DBG (1, "check_gamma_table: warning: entry %d > 255 (%d) - fixed\n", 680141cc406Sopenharmony_ci entry, value); 681141cc406Sopenharmony_ci table[entry] = 255; 682141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 683141cc406Sopenharmony_ci } 684141cc406Sopenharmony_ci } 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ci return status; 687141cc406Sopenharmony_ci} 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci/* -------------------------- SANE API functions ------------------------- */ 690141cc406Sopenharmony_ci 691141cc406Sopenharmony_ciSANE_Status 692141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 693141cc406Sopenharmony_ci{ 694141cc406Sopenharmony_ci SANE_Char line[PATH_MAX]; 695141cc406Sopenharmony_ci SANE_Char *word, *end; 696141cc406Sopenharmony_ci SANE_String_Const cp; 697141cc406Sopenharmony_ci SANE_Int linenumber; 698141cc406Sopenharmony_ci FILE *fp; 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci DBG_INIT (); 701141cc406Sopenharmony_ci DBG (2, "SANE Mustek USB backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, 702141cc406Sopenharmony_ci SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); 703141cc406Sopenharmony_ci 704141cc406Sopenharmony_ci if (version_code) 705141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci DBG (5, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); 708141cc406Sopenharmony_ci 709141cc406Sopenharmony_ci 710141cc406Sopenharmony_ci num_devices = 0; 711141cc406Sopenharmony_ci first_dev = 0; 712141cc406Sopenharmony_ci first_handle = 0; 713141cc406Sopenharmony_ci devlist = 0; 714141cc406Sopenharmony_ci new_dev = 0; 715141cc406Sopenharmony_ci new_dev_len = 0; 716141cc406Sopenharmony_ci new_dev_alloced = 0; 717141cc406Sopenharmony_ci 718141cc406Sopenharmony_ci sanei_usb_init (); 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci fp = sanei_config_open (MUSTEK_USB_CONFIG_FILE); 721141cc406Sopenharmony_ci if (!fp) 722141cc406Sopenharmony_ci { 723141cc406Sopenharmony_ci /* default to /dev/usb/scanner instead of insisting on config file */ 724141cc406Sopenharmony_ci DBG (3, "sane_init: couldn't open config file `%s': %s. Using " 725141cc406Sopenharmony_ci "/dev/usb/scanner directly\n", MUSTEK_USB_CONFIG_FILE, 726141cc406Sopenharmony_ci strerror (errno)); 727141cc406Sopenharmony_ci attach ("/dev/usb/scanner", 0, SANE_FALSE); 728141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 729141cc406Sopenharmony_ci } 730141cc406Sopenharmony_ci linenumber = 0; 731141cc406Sopenharmony_ci DBG (4, "sane_init: reading config file `%s'\n", MUSTEK_USB_CONFIG_FILE); 732141cc406Sopenharmony_ci 733141cc406Sopenharmony_ci while (sanei_config_read (line, sizeof (line), fp)) 734141cc406Sopenharmony_ci { 735141cc406Sopenharmony_ci word = 0; 736141cc406Sopenharmony_ci linenumber++; 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci cp = sanei_config_get_string (line, &word); 739141cc406Sopenharmony_ci if (!word || cp == line) 740141cc406Sopenharmony_ci { 741141cc406Sopenharmony_ci DBG (5, "sane_init: config file line %d: ignoring empty line\n", 742141cc406Sopenharmony_ci linenumber); 743141cc406Sopenharmony_ci if (word) 744141cc406Sopenharmony_ci free (word); 745141cc406Sopenharmony_ci continue; 746141cc406Sopenharmony_ci } 747141cc406Sopenharmony_ci if (word[0] == '#') 748141cc406Sopenharmony_ci { 749141cc406Sopenharmony_ci DBG (5, "sane_init: config file line %d: ignoring comment line\n", 750141cc406Sopenharmony_ci linenumber); 751141cc406Sopenharmony_ci free (word); 752141cc406Sopenharmony_ci continue; 753141cc406Sopenharmony_ci } 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ci if (strcmp (word, "option") == 0) 756141cc406Sopenharmony_ci { 757141cc406Sopenharmony_ci free (word); 758141cc406Sopenharmony_ci word = 0; 759141cc406Sopenharmony_ci cp = sanei_config_get_string (cp, &word); 760141cc406Sopenharmony_ci 761141cc406Sopenharmony_ci if (!word) 762141cc406Sopenharmony_ci { 763141cc406Sopenharmony_ci DBG (1, "sane_init: config file line %d: missing quotation mark?\n", 764141cc406Sopenharmony_ci linenumber); 765141cc406Sopenharmony_ci continue; 766141cc406Sopenharmony_ci } 767141cc406Sopenharmony_ci 768141cc406Sopenharmony_ci if (strcmp (word, "max_block_size") == 0) 769141cc406Sopenharmony_ci { 770141cc406Sopenharmony_ci free (word); 771141cc406Sopenharmony_ci word = 0; 772141cc406Sopenharmony_ci cp = sanei_config_get_string (cp, &word); 773141cc406Sopenharmony_ci if (!word) 774141cc406Sopenharmony_ci { 775141cc406Sopenharmony_ci DBG (1, "sane_init: config file line %d: missing quotation mark?\n", 776141cc406Sopenharmony_ci linenumber); 777141cc406Sopenharmony_ci continue; 778141cc406Sopenharmony_ci } 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci errno = 0; 781141cc406Sopenharmony_ci max_block_size = strtol (word, &end, 0); 782141cc406Sopenharmony_ci if (end == word) 783141cc406Sopenharmony_ci { 784141cc406Sopenharmony_ci DBG (3, "sane-init: config file line %d: max_block_size " 785141cc406Sopenharmony_ci "must have a parameter; using 8192 bytes\n", 786141cc406Sopenharmony_ci linenumber); 787141cc406Sopenharmony_ci max_block_size = 8192; 788141cc406Sopenharmony_ci } 789141cc406Sopenharmony_ci if (errno) 790141cc406Sopenharmony_ci { 791141cc406Sopenharmony_ci DBG (3, 792141cc406Sopenharmony_ci "sane-init: config file line %d: max_block_size `%s' " 793141cc406Sopenharmony_ci "is invalid (%s); using 8192 bytes\n", linenumber, 794141cc406Sopenharmony_ci word, strerror (errno)); 795141cc406Sopenharmony_ci max_block_size = 8192; 796141cc406Sopenharmony_ci } 797141cc406Sopenharmony_ci else 798141cc406Sopenharmony_ci { 799141cc406Sopenharmony_ci DBG (3, 800141cc406Sopenharmony_ci "sane_init: config file line %d: max_block_size set " 801141cc406Sopenharmony_ci "to %d bytes\n", linenumber, max_block_size); 802141cc406Sopenharmony_ci } 803141cc406Sopenharmony_ci if (word) 804141cc406Sopenharmony_ci free (word); 805141cc406Sopenharmony_ci word = 0; 806141cc406Sopenharmony_ci } 807141cc406Sopenharmony_ci else if (strcmp (word, "1200ub") == 0) 808141cc406Sopenharmony_ci { 809141cc406Sopenharmony_ci if (new_dev_len > 0) 810141cc406Sopenharmony_ci { 811141cc406Sopenharmony_ci /* this is a 1200 UB */ 812141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->chip->scanner_type = MT_1200UB; 813141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.model = "1200 UB"; 814141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: `%s' is a Mustek " 815141cc406Sopenharmony_ci "1200 UB\n", linenumber, 816141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.name); 817141cc406Sopenharmony_ci } 818141cc406Sopenharmony_ci else 819141cc406Sopenharmony_ci { 820141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: option " 821141cc406Sopenharmony_ci "1200ub ignored, was set before any device " 822141cc406Sopenharmony_ci "name\n", linenumber); 823141cc406Sopenharmony_ci } 824141cc406Sopenharmony_ci if (word) 825141cc406Sopenharmony_ci free (word); 826141cc406Sopenharmony_ci word = 0; 827141cc406Sopenharmony_ci } 828141cc406Sopenharmony_ci else if (strcmp (word, "1200cu") == 0) 829141cc406Sopenharmony_ci { 830141cc406Sopenharmony_ci if (new_dev_len > 0) 831141cc406Sopenharmony_ci { 832141cc406Sopenharmony_ci /* this is a 1200 CU */ 833141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->chip->scanner_type = MT_1200CU; 834141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.model = "1200 CU"; 835141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: `%s' is a Mustek " 836141cc406Sopenharmony_ci "1200 CU\n", linenumber, 837141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.name); 838141cc406Sopenharmony_ci } 839141cc406Sopenharmony_ci else 840141cc406Sopenharmony_ci { 841141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: option " 842141cc406Sopenharmony_ci "1200cu ignored, was set before any device " 843141cc406Sopenharmony_ci "name\n", linenumber); 844141cc406Sopenharmony_ci } 845141cc406Sopenharmony_ci if (word) 846141cc406Sopenharmony_ci free (word); 847141cc406Sopenharmony_ci word = 0; 848141cc406Sopenharmony_ci } 849141cc406Sopenharmony_ci else if (strcmp (word, "1200cu_plus") == 0) 850141cc406Sopenharmony_ci { 851141cc406Sopenharmony_ci if (new_dev_len > 0) 852141cc406Sopenharmony_ci { 853141cc406Sopenharmony_ci /* this is a 1200 CU Plus */ 854141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->chip->scanner_type 855141cc406Sopenharmony_ci = MT_1200CU_PLUS; 856141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.model = "1200 CU Plus"; 857141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: `%s' is a Mustek " 858141cc406Sopenharmony_ci "1200 CU Plus\n", linenumber, 859141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.name); 860141cc406Sopenharmony_ci } 861141cc406Sopenharmony_ci else 862141cc406Sopenharmony_ci { 863141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: option " 864141cc406Sopenharmony_ci "1200cu_plus ignored, was set before any device " 865141cc406Sopenharmony_ci "name\n", linenumber); 866141cc406Sopenharmony_ci } 867141cc406Sopenharmony_ci if (word) 868141cc406Sopenharmony_ci free (word); 869141cc406Sopenharmony_ci word = 0; 870141cc406Sopenharmony_ci } 871141cc406Sopenharmony_ci else if (strcmp (word, "600cu") == 0) 872141cc406Sopenharmony_ci { 873141cc406Sopenharmony_ci if (new_dev_len > 0) 874141cc406Sopenharmony_ci { 875141cc406Sopenharmony_ci /* this is a 600 CU */ 876141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->chip->scanner_type = MT_600CU; 877141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.model = "600 CU"; 878141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: `%s' is a Mustek " 879141cc406Sopenharmony_ci "600 CU\n", linenumber, 880141cc406Sopenharmony_ci new_dev[new_dev_len - 1]->sane.name); 881141cc406Sopenharmony_ci } 882141cc406Sopenharmony_ci else 883141cc406Sopenharmony_ci { 884141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: option " 885141cc406Sopenharmony_ci "600cu ignored, was set before any device " 886141cc406Sopenharmony_ci "name\n", linenumber); 887141cc406Sopenharmony_ci } 888141cc406Sopenharmony_ci if (word) 889141cc406Sopenharmony_ci free (word); 890141cc406Sopenharmony_ci word = 0; 891141cc406Sopenharmony_ci } 892141cc406Sopenharmony_ci else 893141cc406Sopenharmony_ci { 894141cc406Sopenharmony_ci DBG (3, "sane_init: config file line %d: option " 895141cc406Sopenharmony_ci "%s is unknown\n", linenumber, word); 896141cc406Sopenharmony_ci if (word) 897141cc406Sopenharmony_ci free (word); 898141cc406Sopenharmony_ci word = 0; 899141cc406Sopenharmony_ci } 900141cc406Sopenharmony_ci } 901141cc406Sopenharmony_ci else 902141cc406Sopenharmony_ci { 903141cc406Sopenharmony_ci new_dev_len = 0; 904141cc406Sopenharmony_ci DBG (4, "sane_init: config file line %d: trying to attach `%s'\n", 905141cc406Sopenharmony_ci linenumber, line); 906141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (line, attach_one_device); 907141cc406Sopenharmony_ci if (word) 908141cc406Sopenharmony_ci free (word); 909141cc406Sopenharmony_ci word = 0; 910141cc406Sopenharmony_ci } 911141cc406Sopenharmony_ci } 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci if (new_dev_alloced > 0) 914141cc406Sopenharmony_ci { 915141cc406Sopenharmony_ci new_dev_len = new_dev_alloced = 0; 916141cc406Sopenharmony_ci free (new_dev); 917141cc406Sopenharmony_ci } 918141cc406Sopenharmony_ci 919141cc406Sopenharmony_ci fclose (fp); 920141cc406Sopenharmony_ci DBG (5, "sane_init: exit\n"); 921141cc406Sopenharmony_ci 922141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 923141cc406Sopenharmony_ci} 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_civoid 926141cc406Sopenharmony_cisane_exit (void) 927141cc406Sopenharmony_ci{ 928141cc406Sopenharmony_ci Mustek_Usb_Device *dev, *next; 929141cc406Sopenharmony_ci SANE_Status status; 930141cc406Sopenharmony_ci 931141cc406Sopenharmony_ci DBG (5, "sane_exit: start\n"); 932141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = next) 933141cc406Sopenharmony_ci { 934141cc406Sopenharmony_ci next = dev->next; 935141cc406Sopenharmony_ci if (dev->is_prepared) 936141cc406Sopenharmony_ci { 937141cc406Sopenharmony_ci status = usb_high_scan_clearup (dev); 938141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 939141cc406Sopenharmony_ci DBG (3, "sane_close: usb_high_scan_clearup returned %s\n", 940141cc406Sopenharmony_ci sane_strstatus (status)); 941141cc406Sopenharmony_ci } 942141cc406Sopenharmony_ci status = usb_high_scan_exit (dev); 943141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 944141cc406Sopenharmony_ci DBG (3, "sane_close: usb_high_scan_exit returned %s\n", 945141cc406Sopenharmony_ci sane_strstatus (status)); 946141cc406Sopenharmony_ci if (dev->chip) 947141cc406Sopenharmony_ci { 948141cc406Sopenharmony_ci status = usb_high_scan_exit (dev); 949141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 950141cc406Sopenharmony_ci DBG (3, 951141cc406Sopenharmony_ci "sane_exit: while closing %s, usb_high_scan_exit returned: " 952141cc406Sopenharmony_ci "%s\n", dev->name, sane_strstatus (status)); 953141cc406Sopenharmony_ci } 954141cc406Sopenharmony_ci free ((void *) dev->name); 955141cc406Sopenharmony_ci free (dev); 956141cc406Sopenharmony_ci } 957141cc406Sopenharmony_ci first_dev = 0; 958141cc406Sopenharmony_ci if (devlist) 959141cc406Sopenharmony_ci free (devlist); 960141cc406Sopenharmony_ci devlist = 0; 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci DBG (5, "sane_exit: exit\n"); 963141cc406Sopenharmony_ci} 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ciSANE_Status 966141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 967141cc406Sopenharmony_ci{ 968141cc406Sopenharmony_ci Mustek_Usb_Device *dev; 969141cc406Sopenharmony_ci SANE_Int dev_num; 970141cc406Sopenharmony_ci 971141cc406Sopenharmony_ci DBG (5, "sane_get_devices: start: local_only = %s\n", 972141cc406Sopenharmony_ci local_only == SANE_TRUE ? "true" : "false"); 973141cc406Sopenharmony_ci 974141cc406Sopenharmony_ci if (devlist) 975141cc406Sopenharmony_ci free (devlist); 976141cc406Sopenharmony_ci 977141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 978141cc406Sopenharmony_ci if (!devlist) 979141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_ci dev_num = 0; 982141cc406Sopenharmony_ci for (dev = first_dev; dev_num < num_devices; dev = dev->next) 983141cc406Sopenharmony_ci devlist[dev_num++] = &dev->sane; 984141cc406Sopenharmony_ci devlist[dev_num++] = 0; 985141cc406Sopenharmony_ci 986141cc406Sopenharmony_ci *device_list = devlist; 987141cc406Sopenharmony_ci 988141cc406Sopenharmony_ci DBG (5, "sane_get_devices: exit\n"); 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 991141cc406Sopenharmony_ci} 992141cc406Sopenharmony_ci 993141cc406Sopenharmony_ciSANE_Status 994141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 995141cc406Sopenharmony_ci{ 996141cc406Sopenharmony_ci Mustek_Usb_Device *dev; 997141cc406Sopenharmony_ci SANE_Status status; 998141cc406Sopenharmony_ci Mustek_Usb_Scanner *s; 999141cc406Sopenharmony_ci SANE_Int value; 1000141cc406Sopenharmony_ci 1001141cc406Sopenharmony_ci DBG (5, "sane_open: start (devicename = `%s')\n", devicename); 1002141cc406Sopenharmony_ci 1003141cc406Sopenharmony_ci if (devicename[0]) 1004141cc406Sopenharmony_ci { 1005141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1006141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 1007141cc406Sopenharmony_ci break; 1008141cc406Sopenharmony_ci 1009141cc406Sopenharmony_ci if (!dev) 1010141cc406Sopenharmony_ci { 1011141cc406Sopenharmony_ci DBG (5, 1012141cc406Sopenharmony_ci "sane_open: couldn't find `%s' in devlist, trying attach)\n", 1013141cc406Sopenharmony_ci devicename); 1014141cc406Sopenharmony_ci RIE (attach (devicename, &dev, SANE_TRUE)); 1015141cc406Sopenharmony_ci } 1016141cc406Sopenharmony_ci else 1017141cc406Sopenharmony_ci DBG (5, "sane_open: found `%s' in devlist\n", dev->name); 1018141cc406Sopenharmony_ci } 1019141cc406Sopenharmony_ci else 1020141cc406Sopenharmony_ci { 1021141cc406Sopenharmony_ci /* empty devicname -> use first device */ 1022141cc406Sopenharmony_ci dev = first_dev; 1023141cc406Sopenharmony_ci if (dev) 1024141cc406Sopenharmony_ci DBG (5, "sane_open: empty devicename, trying `%s'\n", dev->name); 1025141cc406Sopenharmony_ci } 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci if (!dev) 1028141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci if (dev->chip->scanner_type == MT_UNKNOWN) 1031141cc406Sopenharmony_ci { 1032141cc406Sopenharmony_ci DBG (0, "sane_open: the type of your scanner is unknown, edit " 1033141cc406Sopenharmony_ci "mustek_usb.conf before using the scanner\n"); 1034141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1035141cc406Sopenharmony_ci } 1036141cc406Sopenharmony_ci s = malloc (sizeof (*s)); 1037141cc406Sopenharmony_ci if (!s) 1038141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1039141cc406Sopenharmony_ci memset (s, 0, sizeof (*s)); 1040141cc406Sopenharmony_ci s->hw = dev; 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_ci RIE (init_options (s)); 1043141cc406Sopenharmony_ci 1044141cc406Sopenharmony_ci /* insert newly opened handle into list of open handles: */ 1045141cc406Sopenharmony_ci s->next = first_handle; 1046141cc406Sopenharmony_ci first_handle = s; 1047141cc406Sopenharmony_ci 1048141cc406Sopenharmony_ci *handle = s; 1049141cc406Sopenharmony_ci strcpy (s->hw->device_name, dev->name); 1050141cc406Sopenharmony_ci 1051141cc406Sopenharmony_ci RIE (usb_high_scan_turn_power (s->hw, SANE_TRUE)); 1052141cc406Sopenharmony_ci RIE (usb_high_scan_back_home (s->hw)); 1053141cc406Sopenharmony_ci 1054141cc406Sopenharmony_ci s->hw->scan_buffer = (SANE_Byte *) malloc (SCAN_BUFFER_SIZE * 2); 1055141cc406Sopenharmony_ci if (!s->hw->scan_buffer) 1056141cc406Sopenharmony_ci { 1057141cc406Sopenharmony_ci DBG (5, "sane_open: couldn't malloc s->hw->scan_buffer (%d bytes)\n", 1058141cc406Sopenharmony_ci SCAN_BUFFER_SIZE * 2); 1059141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1060141cc406Sopenharmony_ci } 1061141cc406Sopenharmony_ci s->hw->scan_buffer_len = 0; 1062141cc406Sopenharmony_ci s->hw->scan_buffer_start = s->hw->scan_buffer; 1063141cc406Sopenharmony_ci 1064141cc406Sopenharmony_ci s->hw->temp_buffer = (SANE_Byte *) malloc (SCAN_BUFFER_SIZE); 1065141cc406Sopenharmony_ci if (!s->hw->temp_buffer) 1066141cc406Sopenharmony_ci { 1067141cc406Sopenharmony_ci DBG (5, "sane_open: couldn't malloc s->hw->temp_buffer (%d bytes)\n", 1068141cc406Sopenharmony_ci SCAN_BUFFER_SIZE); 1069141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1070141cc406Sopenharmony_ci } 1071141cc406Sopenharmony_ci s->hw->temp_buffer_len = 0; 1072141cc406Sopenharmony_ci s->hw->temp_buffer_start = s->hw->temp_buffer; 1073141cc406Sopenharmony_ci 1074141cc406Sopenharmony_ci for (value = 0; value < 256; value++) 1075141cc406Sopenharmony_ci { 1076141cc406Sopenharmony_ci s->linear_gamma_table[value] = value; 1077141cc406Sopenharmony_ci s->red_gamma_table[value] = value; 1078141cc406Sopenharmony_ci s->green_gamma_table[value] = value; 1079141cc406Sopenharmony_ci s->blue_gamma_table[value] = value; 1080141cc406Sopenharmony_ci s->gray_gamma_table[value] = value; 1081141cc406Sopenharmony_ci } 1082141cc406Sopenharmony_ci 1083141cc406Sopenharmony_ci s->red_table = s->linear_gamma_table; 1084141cc406Sopenharmony_ci s->green_table = s->linear_gamma_table; 1085141cc406Sopenharmony_ci s->blue_table = s->linear_gamma_table; 1086141cc406Sopenharmony_ci s->gray_table = s->linear_gamma_table; 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci DBG (5, "sane_open: exit\n"); 1089141cc406Sopenharmony_ci 1090141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1091141cc406Sopenharmony_ci} 1092141cc406Sopenharmony_ci 1093141cc406Sopenharmony_civoid 1094141cc406Sopenharmony_cisane_close (SANE_Handle handle) 1095141cc406Sopenharmony_ci{ 1096141cc406Sopenharmony_ci Mustek_Usb_Scanner *prev, *s; 1097141cc406Sopenharmony_ci SANE_Status status; 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci DBG (5, "sane_close: start\n"); 1100141cc406Sopenharmony_ci 1101141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 1102141cc406Sopenharmony_ci prev = 0; 1103141cc406Sopenharmony_ci for (s = first_handle; s; s = s->next) 1104141cc406Sopenharmony_ci { 1105141cc406Sopenharmony_ci if (s == handle) 1106141cc406Sopenharmony_ci break; 1107141cc406Sopenharmony_ci prev = s; 1108141cc406Sopenharmony_ci } 1109141cc406Sopenharmony_ci if (!s) 1110141cc406Sopenharmony_ci { 1111141cc406Sopenharmony_ci DBG (5, "close: invalid handle %p\n", handle); 1112141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 1113141cc406Sopenharmony_ci } 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci if (prev) 1116141cc406Sopenharmony_ci prev->next = s->next; 1117141cc406Sopenharmony_ci else 1118141cc406Sopenharmony_ci first_handle = s->next; 1119141cc406Sopenharmony_ci 1120141cc406Sopenharmony_ci if (s->hw->is_open) 1121141cc406Sopenharmony_ci { 1122141cc406Sopenharmony_ci status = usb_high_scan_turn_power (s->hw, SANE_FALSE); 1123141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1124141cc406Sopenharmony_ci DBG (3, "sane_close: usb_high_scan_turn_power returned %s\n", 1125141cc406Sopenharmony_ci sane_strstatus (status)); 1126141cc406Sopenharmony_ci } 1127141cc406Sopenharmony_ci#if 0 1128141cc406Sopenharmony_ci if (s->hw->is_prepared) 1129141cc406Sopenharmony_ci { 1130141cc406Sopenharmony_ci status = usb_high_scan_clearup (s->hw); 1131141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1132141cc406Sopenharmony_ci DBG (3, "sane_close: usb_high_scan_clearup returned %s\n", 1133141cc406Sopenharmony_ci sane_strstatus (status)); 1134141cc406Sopenharmony_ci } 1135141cc406Sopenharmony_ci status = usb_high_scan_exit (s->hw); 1136141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1137141cc406Sopenharmony_ci DBG (3, "sane_close: usb_high_scan_exit returned %s\n", 1138141cc406Sopenharmony_ci sane_strstatus (status)); 1139141cc406Sopenharmony_ci#endif 1140141cc406Sopenharmony_ci if (s->hw->scan_buffer) 1141141cc406Sopenharmony_ci { 1142141cc406Sopenharmony_ci free (s->hw->scan_buffer); 1143141cc406Sopenharmony_ci s->hw->scan_buffer = 0; 1144141cc406Sopenharmony_ci } 1145141cc406Sopenharmony_ci if (s->hw->temp_buffer) 1146141cc406Sopenharmony_ci { 1147141cc406Sopenharmony_ci free (s->hw->temp_buffer); 1148141cc406Sopenharmony_ci s->hw->temp_buffer = 0; 1149141cc406Sopenharmony_ci } 1150141cc406Sopenharmony_ci 1151141cc406Sopenharmony_ci free (handle); 1152141cc406Sopenharmony_ci 1153141cc406Sopenharmony_ci DBG (5, "sane_close: exit\n"); 1154141cc406Sopenharmony_ci} 1155141cc406Sopenharmony_ci 1156141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1157141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1158141cc406Sopenharmony_ci{ 1159141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1160141cc406Sopenharmony_ci 1161141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 1162141cc406Sopenharmony_ci return 0; 1163141cc406Sopenharmony_ci DBG (5, "sane_get_option_descriptor: option = %s (%d)\n", 1164141cc406Sopenharmony_ci s->opt[option].name, option); 1165141cc406Sopenharmony_ci return s->opt + option; 1166141cc406Sopenharmony_ci} 1167141cc406Sopenharmony_ci 1168141cc406Sopenharmony_ciSANE_Status 1169141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1170141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1171141cc406Sopenharmony_ci{ 1172141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1173141cc406Sopenharmony_ci SANE_Status status; 1174141cc406Sopenharmony_ci SANE_Word cap; 1175141cc406Sopenharmony_ci SANE_Int myinfo = 0; 1176141cc406Sopenharmony_ci 1177141cc406Sopenharmony_ci DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n", 1178141cc406Sopenharmony_ci (action == SANE_ACTION_GET_VALUE) ? "get" : 1179141cc406Sopenharmony_ci (action == SANE_ACTION_SET_VALUE) ? "set" : 1180141cc406Sopenharmony_ci (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", 1181141cc406Sopenharmony_ci s->opt[option].name, option); 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci if (info) 1184141cc406Sopenharmony_ci *info = 0; 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci if (s->scanning) 1187141cc406Sopenharmony_ci { 1188141cc406Sopenharmony_ci DBG (1, "sane_control_option: don't call this function while " 1189141cc406Sopenharmony_ci "scanning\n"); 1190141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1191141cc406Sopenharmony_ci } 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci if (option >= NUM_OPTIONS || option < 0) 1194141cc406Sopenharmony_ci { 1195141cc406Sopenharmony_ci DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", 1196141cc406Sopenharmony_ci option); 1197141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1198141cc406Sopenharmony_ci } 1199141cc406Sopenharmony_ci 1200141cc406Sopenharmony_ci cap = s->opt[option].cap; 1201141cc406Sopenharmony_ci 1202141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 1203141cc406Sopenharmony_ci { 1204141cc406Sopenharmony_ci DBG (2, "sane_control_option: option %d is inactive\n", option); 1205141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1206141cc406Sopenharmony_ci } 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1209141cc406Sopenharmony_ci { 1210141cc406Sopenharmony_ci switch (option) 1211141cc406Sopenharmony_ci { 1212141cc406Sopenharmony_ci /* word options: */ 1213141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1214141cc406Sopenharmony_ci case OPT_RESOLUTION: 1215141cc406Sopenharmony_ci case OPT_PREVIEW: 1216141cc406Sopenharmony_ci case OPT_TL_X: 1217141cc406Sopenharmony_ci case OPT_TL_Y: 1218141cc406Sopenharmony_ci case OPT_BR_X: 1219141cc406Sopenharmony_ci case OPT_BR_Y: 1220141cc406Sopenharmony_ci case OPT_THRESHOLD: 1221141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1222141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 1223141cc406Sopenharmony_ci break; 1224141cc406Sopenharmony_ci /* word-array options: */ 1225141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1226141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1227141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1228141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1229141cc406Sopenharmony_ci memcpy (val, s->val[option].wa, s->opt[option].size); 1230141cc406Sopenharmony_ci break; 1231141cc406Sopenharmony_ci /* string options: */ 1232141cc406Sopenharmony_ci case OPT_MODE: 1233141cc406Sopenharmony_ci strcpy (val, s->val[option].s); 1234141cc406Sopenharmony_ci break; 1235141cc406Sopenharmony_ci default: 1236141cc406Sopenharmony_ci DBG (2, "sane_control_option: can't get unknown option %d\n", 1237141cc406Sopenharmony_ci option); 1238141cc406Sopenharmony_ci } 1239141cc406Sopenharmony_ci } 1240141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1241141cc406Sopenharmony_ci { 1242141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 1243141cc406Sopenharmony_ci { 1244141cc406Sopenharmony_ci DBG (2, "sane_control_option: option %d is not settable\n", option); 1245141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1246141cc406Sopenharmony_ci } 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, &myinfo); 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1251141cc406Sopenharmony_ci { 1252141cc406Sopenharmony_ci DBG (2, "sane_control_option: sanei_constrain_value returned %s\n", 1253141cc406Sopenharmony_ci sane_strstatus (status)); 1254141cc406Sopenharmony_ci return status; 1255141cc406Sopenharmony_ci } 1256141cc406Sopenharmony_ci 1257141cc406Sopenharmony_ci switch (option) 1258141cc406Sopenharmony_ci { 1259141cc406Sopenharmony_ci /* (mostly) side-effect-free word options: */ 1260141cc406Sopenharmony_ci case OPT_RESOLUTION: 1261141cc406Sopenharmony_ci case OPT_TL_X: 1262141cc406Sopenharmony_ci case OPT_TL_Y: 1263141cc406Sopenharmony_ci case OPT_BR_X: 1264141cc406Sopenharmony_ci case OPT_BR_Y: 1265141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 1266141cc406Sopenharmony_ci RIE (calc_parameters (s)); 1267141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_PARAMS; 1268141cc406Sopenharmony_ci break; 1269141cc406Sopenharmony_ci case OPT_THRESHOLD: 1270141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 1271141cc406Sopenharmony_ci break; 1272141cc406Sopenharmony_ci /* Boolean */ 1273141cc406Sopenharmony_ci case OPT_PREVIEW: 1274141cc406Sopenharmony_ci s->val[option].w = *(SANE_Bool *) val; 1275141cc406Sopenharmony_ci break; 1276141cc406Sopenharmony_ci /* side-effect-free word-array options: */ 1277141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 1278141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 1279141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 1280141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 1281141cc406Sopenharmony_ci memcpy (s->val[option].wa, val, s->opt[option].size); 1282141cc406Sopenharmony_ci check_gamma_table (s->val[option].wa); 1283141cc406Sopenharmony_ci break; 1284141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 1285141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; 1286141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_OPTIONS; 1287141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) 1288141cc406Sopenharmony_ci { 1289141cc406Sopenharmony_ci s->red_table = s->red_gamma_table; 1290141cc406Sopenharmony_ci s->green_table = s->green_gamma_table; 1291141cc406Sopenharmony_ci s->blue_table = s->blue_gamma_table; 1292141cc406Sopenharmony_ci s->gray_table = s->gray_gamma_table; 1293141cc406Sopenharmony_ci if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) 1294141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1295141cc406Sopenharmony_ci else if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) 1296141cc406Sopenharmony_ci { 1297141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1298141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1299141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1300141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1301141cc406Sopenharmony_ci } 1302141cc406Sopenharmony_ci } 1303141cc406Sopenharmony_ci else 1304141cc406Sopenharmony_ci { 1305141cc406Sopenharmony_ci s->red_table = s->linear_gamma_table; 1306141cc406Sopenharmony_ci s->green_table = s->linear_gamma_table; 1307141cc406Sopenharmony_ci s->blue_table = s->linear_gamma_table; 1308141cc406Sopenharmony_ci s->gray_table = s->linear_gamma_table; 1309141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1310141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1311141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1312141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1313141cc406Sopenharmony_ci } 1314141cc406Sopenharmony_ci break; 1315141cc406Sopenharmony_ci case OPT_MODE: 1316141cc406Sopenharmony_ci if (s->val[option].s) 1317141cc406Sopenharmony_ci free (s->val[option].s); 1318141cc406Sopenharmony_ci s->val[option].s = strdup (val); 1319141cc406Sopenharmony_ci 1320141cc406Sopenharmony_ci RIE (calc_parameters (s)); 1321141cc406Sopenharmony_ci 1322141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 1323141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; 1324141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; 1325141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; 1326141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; 1327141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; 1328141cc406Sopenharmony_ci 1329141cc406Sopenharmony_ci if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) 1330141cc406Sopenharmony_ci { 1331141cc406Sopenharmony_ci s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 1332141cc406Sopenharmony_ci } 1333141cc406Sopenharmony_ci else 1334141cc406Sopenharmony_ci { 1335141cc406Sopenharmony_ci s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; 1336141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) 1337141cc406Sopenharmony_ci { 1338141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; 1339141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; 1340141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; 1341141cc406Sopenharmony_ci s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; 1342141cc406Sopenharmony_ci } 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 1345141cc406Sopenharmony_ci break; 1346141cc406Sopenharmony_ci default: 1347141cc406Sopenharmony_ci DBG (2, "sane_control_option: can't set unknown option %d\n", 1348141cc406Sopenharmony_ci option); 1349141cc406Sopenharmony_ci } 1350141cc406Sopenharmony_ci } 1351141cc406Sopenharmony_ci else 1352141cc406Sopenharmony_ci { 1353141cc406Sopenharmony_ci DBG (2, "sane_control_option: unknown action %d for option %d\n", 1354141cc406Sopenharmony_ci action, option); 1355141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1356141cc406Sopenharmony_ci } 1357141cc406Sopenharmony_ci if (info) 1358141cc406Sopenharmony_ci *info = myinfo; 1359141cc406Sopenharmony_ci 1360141cc406Sopenharmony_ci DBG (5, "sane_control_option: exit\n"); 1361141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1362141cc406Sopenharmony_ci} 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ciSANE_Status 1365141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1366141cc406Sopenharmony_ci{ 1367141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1368141cc406Sopenharmony_ci SANE_Status status; 1369141cc406Sopenharmony_ci 1370141cc406Sopenharmony_ci DBG (5, "sane_get_parameters: start\n"); 1371141cc406Sopenharmony_ci 1372141cc406Sopenharmony_ci RIE (calc_parameters (s)); 1373141cc406Sopenharmony_ci if (params) 1374141cc406Sopenharmony_ci *params = s->params; 1375141cc406Sopenharmony_ci 1376141cc406Sopenharmony_ci DBG (5, "sane_get_parameters: exit\n"); 1377141cc406Sopenharmony_ci 1378141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1379141cc406Sopenharmony_ci} 1380141cc406Sopenharmony_ci 1381141cc406Sopenharmony_ciSANE_Status 1382141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1383141cc406Sopenharmony_ci{ 1384141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1385141cc406Sopenharmony_ci SANE_Status status; 1386141cc406Sopenharmony_ci SANE_String val; 1387141cc406Sopenharmony_ci Colormode color_mode; 1388141cc406Sopenharmony_ci SANE_Word dpi, x, y, width, height; 1389141cc406Sopenharmony_ci 1390141cc406Sopenharmony_ci DBG (5, "sane_start: start\n"); 1391141cc406Sopenharmony_ci 1392141cc406Sopenharmony_ci /* First make sure we have a current parameter set. Some of the 1393141cc406Sopenharmony_ci parameters will be overwritten below, but that's OK. */ 1394141cc406Sopenharmony_ci 1395141cc406Sopenharmony_ci s->total_bytes = 0; 1396141cc406Sopenharmony_ci s->total_lines = 0; 1397141cc406Sopenharmony_ci RIE (calc_parameters (s)); 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci if (s->width_dots <= 0) 1400141cc406Sopenharmony_ci { 1401141cc406Sopenharmony_ci DBG (0, "sane_start: top left x > bottom right x --- exiting\n"); 1402141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1403141cc406Sopenharmony_ci } 1404141cc406Sopenharmony_ci if (s->height_dots <= 0) 1405141cc406Sopenharmony_ci { 1406141cc406Sopenharmony_ci DBG (0, "sane_start: top left y > bottom right y --- exiting\n"); 1407141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1408141cc406Sopenharmony_ci } 1409141cc406Sopenharmony_ci 1410141cc406Sopenharmony_ci 1411141cc406Sopenharmony_ci val = s->val[OPT_MODE].s; 1412141cc406Sopenharmony_ci if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) 1413141cc406Sopenharmony_ci color_mode = GRAY8; 1414141cc406Sopenharmony_ci else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) 1415141cc406Sopenharmony_ci color_mode = GRAY8; 1416141cc406Sopenharmony_ci else /* Color */ 1417141cc406Sopenharmony_ci color_mode = RGB24; 1418141cc406Sopenharmony_ci 1419141cc406Sopenharmony_ci dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); 1420141cc406Sopenharmony_ci x = s->tl_x_dots; 1421141cc406Sopenharmony_ci y = s->tl_y_dots; 1422141cc406Sopenharmony_ci width = s->width_dots; 1423141cc406Sopenharmony_ci height = s->height_dots; 1424141cc406Sopenharmony_ci 1425141cc406Sopenharmony_ci if (!s->hw->is_prepared) 1426141cc406Sopenharmony_ci { 1427141cc406Sopenharmony_ci RIE (usb_high_scan_prepare (s->hw)); 1428141cc406Sopenharmony_ci RIE (usb_high_scan_reset (s->hw)); 1429141cc406Sopenharmony_ci } 1430141cc406Sopenharmony_ci RIE (usb_high_scan_set_threshold (s->hw, 128)); 1431141cc406Sopenharmony_ci RIE (usb_high_scan_embed_gamma (s->hw, NULL)); 1432141cc406Sopenharmony_ci RIE (usb_high_scan_suggest_parameters (s->hw, dpi, x, y, width, height, 1433141cc406Sopenharmony_ci color_mode)); 1434141cc406Sopenharmony_ci RIE (usb_high_scan_setup_scan (s->hw, s->hw->scan_mode, s->hw->x_dpi, 1435141cc406Sopenharmony_ci s->hw->y_dpi, 0, s->hw->x, s->hw->y, 1436141cc406Sopenharmony_ci s->hw->width)); 1437141cc406Sopenharmony_ci 1438141cc406Sopenharmony_ci DBG (3, "sane_start: wanted: dpi=%d, x=%d, y=%d, width=%d, height=%d, " 1439141cc406Sopenharmony_ci "scan_mode=%d\n", dpi, x, y, width, height, color_mode); 1440141cc406Sopenharmony_ci DBG (3, "sane_start: got: x_dpi=%d, y_dpi=%d, x=%d, y=%d, width=%d, " 1441141cc406Sopenharmony_ci "height=%d, scan_mode=%d\n", s->hw->x_dpi, s->hw->y_dpi, s->hw->x, 1442141cc406Sopenharmony_ci s->hw->y, s->hw->width, s->hw->height, s->hw->scan_mode); 1443141cc406Sopenharmony_ci 1444141cc406Sopenharmony_ci s->scanning = SANE_TRUE; 1445141cc406Sopenharmony_ci s->read_rows = s->hw->height; 1446141cc406Sopenharmony_ci s->hw->line_switch = s->hw->height; 1447141cc406Sopenharmony_ci s->hw->line_offset = 0; 1448141cc406Sopenharmony_ci s->hw->scan_buffer_len = 0; 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci DBG (5, "sane_start: exit\n"); 1451141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1452141cc406Sopenharmony_ci} 1453141cc406Sopenharmony_ci 1454141cc406Sopenharmony_ciSANE_Status 1455141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 1456141cc406Sopenharmony_ci SANE_Int * len) 1457141cc406Sopenharmony_ci{ 1458141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1459141cc406Sopenharmony_ci SANE_Word lines_to_read, lines_read; 1460141cc406Sopenharmony_ci SANE_Status status; 1461141cc406Sopenharmony_ci 1462141cc406Sopenharmony_ci DBG (5, "sane_read: start\n"); 1463141cc406Sopenharmony_ci 1464141cc406Sopenharmony_ci if (!s) 1465141cc406Sopenharmony_ci { 1466141cc406Sopenharmony_ci DBG (1, "sane_read: handle is null!\n"); 1467141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1468141cc406Sopenharmony_ci } 1469141cc406Sopenharmony_ci 1470141cc406Sopenharmony_ci if (!buf) 1471141cc406Sopenharmony_ci { 1472141cc406Sopenharmony_ci DBG (1, "sane_read: buf is null!\n"); 1473141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1474141cc406Sopenharmony_ci } 1475141cc406Sopenharmony_ci 1476141cc406Sopenharmony_ci if (!len) 1477141cc406Sopenharmony_ci { 1478141cc406Sopenharmony_ci DBG (1, "sane_read: len is null!\n"); 1479141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1480141cc406Sopenharmony_ci } 1481141cc406Sopenharmony_ci 1482141cc406Sopenharmony_ci *len = 0; 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci if (!s->scanning) 1485141cc406Sopenharmony_ci { 1486141cc406Sopenharmony_ci DBG (3, "sane_read: scan was cancelled, is over or has not been " 1487141cc406Sopenharmony_ci "initiated yet\n"); 1488141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1489141cc406Sopenharmony_ci } 1490141cc406Sopenharmony_ci 1491141cc406Sopenharmony_ci if (s->hw->scan_buffer_len == 0) 1492141cc406Sopenharmony_ci { 1493141cc406Sopenharmony_ci if (s->read_rows > 0) 1494141cc406Sopenharmony_ci { 1495141cc406Sopenharmony_ci lines_to_read = SCAN_BUFFER_SIZE / (s->hw->width * s->hw->bpp / 8); 1496141cc406Sopenharmony_ci if (lines_to_read > s->read_rows) 1497141cc406Sopenharmony_ci lines_to_read = s->read_rows; 1498141cc406Sopenharmony_ci s->hw->temp_buffer_start = s->hw->temp_buffer; 1499141cc406Sopenharmony_ci s->hw->temp_buffer_len = (s->hw->width * s->hw->bpp / 8) 1500141cc406Sopenharmony_ci * lines_to_read; 1501141cc406Sopenharmony_ci DBG (4, "sane_read: reading %d source lines\n", lines_to_read); 1502141cc406Sopenharmony_ci RIE (usb_high_scan_get_rows (s->hw, s->hw->temp_buffer, 1503141cc406Sopenharmony_ci lines_to_read, SANE_FALSE)); 1504141cc406Sopenharmony_ci RIE (fit_lines (s, s->hw->temp_buffer, s->hw->scan_buffer, 1505141cc406Sopenharmony_ci lines_to_read, &lines_read)); 1506141cc406Sopenharmony_ci s->read_rows -= lines_to_read; 1507141cc406Sopenharmony_ci if ((s->total_lines + lines_read) > s->height_dots) 1508141cc406Sopenharmony_ci lines_read = s->height_dots - s->total_lines; 1509141cc406Sopenharmony_ci s->total_lines += lines_read; 1510141cc406Sopenharmony_ci DBG (4, "sane_read: %d destination lines, %d total\n", 1511141cc406Sopenharmony_ci lines_read, s->total_lines); 1512141cc406Sopenharmony_ci s->hw->scan_buffer_start = s->hw->scan_buffer; 1513141cc406Sopenharmony_ci s->hw->scan_buffer_len = (s->width_dots * s->bpp / 8) * lines_read; 1514141cc406Sopenharmony_ci } 1515141cc406Sopenharmony_ci else 1516141cc406Sopenharmony_ci { 1517141cc406Sopenharmony_ci DBG (4, "sane_read: scan finished -- exit\n"); 1518141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1519141cc406Sopenharmony_ci } 1520141cc406Sopenharmony_ci } 1521141cc406Sopenharmony_ci if (s->hw->scan_buffer_len == 0) 1522141cc406Sopenharmony_ci { 1523141cc406Sopenharmony_ci DBG (4, "sane_read: scan finished -- exit\n"); 1524141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1525141cc406Sopenharmony_ci } 1526141cc406Sopenharmony_ci 1527141cc406Sopenharmony_ci *len = MIN (max_len, (SANE_Int) s->hw->scan_buffer_len); 1528141cc406Sopenharmony_ci memcpy (buf, s->hw->scan_buffer_start, *len); 1529141cc406Sopenharmony_ci DBG (4, "sane_read: exit, read %d bytes from scan_buffer; " 1530141cc406Sopenharmony_ci "%ld bytes remaining\n", *len, 1531141cc406Sopenharmony_ci (long int) (s->hw->scan_buffer_len - *len)); 1532141cc406Sopenharmony_ci s->hw->scan_buffer_len -= (*len); 1533141cc406Sopenharmony_ci s->hw->scan_buffer_start += (*len); 1534141cc406Sopenharmony_ci s->total_bytes += (*len); 1535141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1536141cc406Sopenharmony_ci} 1537141cc406Sopenharmony_ci 1538141cc406Sopenharmony_civoid 1539141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 1540141cc406Sopenharmony_ci{ 1541141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1542141cc406Sopenharmony_ci SANE_Status status; 1543141cc406Sopenharmony_ci 1544141cc406Sopenharmony_ci DBG (5, "sane_cancel: start\n"); 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci status = usb_high_scan_stop_scan (s->hw); 1547141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1548141cc406Sopenharmony_ci DBG (3, "sane_cancel: usb_high_scan_stop_scan returned `%s' for `%s'\n", 1549141cc406Sopenharmony_ci sane_strstatus (status), s->hw->name); 1550141cc406Sopenharmony_ci usb_high_scan_back_home (s->hw); 1551141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1552141cc406Sopenharmony_ci DBG (3, "sane_cancel: usb_high_scan_back_home returned `%s' for `%s'\n", 1553141cc406Sopenharmony_ci sane_strstatus (status), s->hw->name); 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci if (s->scanning) 1556141cc406Sopenharmony_ci { 1557141cc406Sopenharmony_ci s->scanning = SANE_FALSE; 1558141cc406Sopenharmony_ci if (s->total_bytes != (s->params.bytes_per_line * s->params.lines)) 1559141cc406Sopenharmony_ci DBG (1, "sane_cancel: warning: scanned %d bytes, expected %d " 1560141cc406Sopenharmony_ci "bytes\n", s->total_bytes, 1561141cc406Sopenharmony_ci s->params.bytes_per_line * s->params.lines); 1562141cc406Sopenharmony_ci else 1563141cc406Sopenharmony_ci DBG (3, "sane_cancel: scan finished, scanned %d bytes\n", 1564141cc406Sopenharmony_ci s->total_bytes); 1565141cc406Sopenharmony_ci } 1566141cc406Sopenharmony_ci else 1567141cc406Sopenharmony_ci { 1568141cc406Sopenharmony_ci DBG (4, "sane_cancel: scan has not been initiated yet, " 1569141cc406Sopenharmony_ci "or it is already aborted\n"); 1570141cc406Sopenharmony_ci } 1571141cc406Sopenharmony_ci DBG (5, "sane_cancel: exit\n"); 1572141cc406Sopenharmony_ci return; 1573141cc406Sopenharmony_ci} 1574141cc406Sopenharmony_ci 1575141cc406Sopenharmony_ciSANE_Status 1576141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 1577141cc406Sopenharmony_ci{ 1578141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1579141cc406Sopenharmony_ci 1580141cc406Sopenharmony_ci DBG (5, "sane_set_io_mode: handle = %p, non_blocking = %s\n", 1581141cc406Sopenharmony_ci handle, non_blocking == SANE_TRUE ? "true" : "false"); 1582141cc406Sopenharmony_ci if (!s->scanning) 1583141cc406Sopenharmony_ci { 1584141cc406Sopenharmony_ci DBG (1, "sane_set_io_mode: not scanning\n"); 1585141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1586141cc406Sopenharmony_ci } 1587141cc406Sopenharmony_ci if (non_blocking) 1588141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1589141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1590141cc406Sopenharmony_ci} 1591141cc406Sopenharmony_ci 1592141cc406Sopenharmony_ciSANE_Status 1593141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 1594141cc406Sopenharmony_ci{ 1595141cc406Sopenharmony_ci Mustek_Usb_Scanner *s = handle; 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci DBG (5, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd); 1598141cc406Sopenharmony_ci if (!s->scanning) 1599141cc406Sopenharmony_ci { 1600141cc406Sopenharmony_ci DBG (1, "sane_get_select_fd: not scanning\n"); 1601141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1602141cc406Sopenharmony_ci } 1603141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1604141cc406Sopenharmony_ci} 1605