1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2002, 2004 Frank Zago (sane at zago dot net) 4141cc406Sopenharmony_ci Copyright (C) 2002 Other SANE contributors 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 22141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 25141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 26141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 27141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 28141cc406Sopenharmony_ci account of linking the SANE library code into it. 29141cc406Sopenharmony_ci 30141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 31141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 32141cc406Sopenharmony_ci License. 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 35141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 36141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 37141cc406Sopenharmony_ci 38141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 39141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 40141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 41141cc406Sopenharmony_ci*/ 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci/* 44141cc406Sopenharmony_ci Matsushita/Panasonic KV-SS25, KV-SS50, KV-SS55, KV-SS50EX, 45141cc406Sopenharmony_ci KV-SS55EX, KV-SS850, KV-SS855 SCSI scanners. 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci This backend may support more Panasonic scanners. 48141cc406Sopenharmony_ci*/ 49141cc406Sopenharmony_ci 50141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci#define BUILD 7 /* 2004-02-11 */ 53141cc406Sopenharmony_ci#define BACKEND_NAME matsushita 54141cc406Sopenharmony_ci#define MATSUSHITA_CONFIG_FILE "matsushita.conf" 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#include "../include/sane/config.h" 59141cc406Sopenharmony_ci 60141cc406Sopenharmony_ci#include <errno.h> 61141cc406Sopenharmony_ci#include <fcntl.h> 62141cc406Sopenharmony_ci#include <limits.h> 63141cc406Sopenharmony_ci#include <signal.h> 64141cc406Sopenharmony_ci#include <stdio.h> 65141cc406Sopenharmony_ci#include <stdlib.h> 66141cc406Sopenharmony_ci#include <string.h> 67141cc406Sopenharmony_ci#include <sys/types.h> 68141cc406Sopenharmony_ci#include <sys/wait.h> 69141cc406Sopenharmony_ci#include <unistd.h> 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci#include "../include/sane/sane.h" 72141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 73141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 74141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 75141cc406Sopenharmony_ci#include "../include/sane/sanei_debug.h" 76141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 77141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 78141cc406Sopenharmony_ci#include "../include/lassert.h" 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_ci#include "matsushita.h" 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_ci/* Lists of possible scan modes. */ 85141cc406Sopenharmony_cistatic SANE_String_Const scan_mode_list_1[] = { 86141cc406Sopenharmony_ci BLACK_WHITE_STR, 87141cc406Sopenharmony_ci NULL 88141cc406Sopenharmony_ci}; 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_cistatic SANE_String_Const scan_mode_list_3[] = { 91141cc406Sopenharmony_ci BLACK_WHITE_STR, 92141cc406Sopenharmony_ci GRAY4_STR, 93141cc406Sopenharmony_ci GRAY8_STR, 94141cc406Sopenharmony_ci NULL 95141cc406Sopenharmony_ci}; 96141cc406Sopenharmony_ci 97141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci/* Lists of supported resolutions (in DPI). 100141cc406Sopenharmony_ci * 200 DPI scanners are using resolutions_list_200 101141cc406Sopenharmony_ci * 300 DPI scanners are using resolutions_list_300 102141cc406Sopenharmony_ci * 400 DPI scanners are using resolutions_list_400 103141cc406Sopenharmony_ci * 104141cc406Sopenharmony_ci * The resolutions_rounds_* lists provide the value with which round 105141cc406Sopenharmony_ci * up the X value given by the interface. 106141cc406Sopenharmony_ci */ 107141cc406Sopenharmony_ci#ifdef unused_yet 108141cc406Sopenharmony_cistatic const SANE_Word resolutions_list_200[4] = { 109141cc406Sopenharmony_ci 3, 100, 150, 200 110141cc406Sopenharmony_ci}; 111141cc406Sopenharmony_cistatic const SANE_Word resolutions_rounds_200[4] = { 112141cc406Sopenharmony_ci 3, 0x100, 0x40, 0x20 113141cc406Sopenharmony_ci}; 114141cc406Sopenharmony_ci#endif 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_cistatic const SANE_Word resolutions_list_300[5] = { 117141cc406Sopenharmony_ci 4, 150, 200, 240, 300 118141cc406Sopenharmony_ci}; 119141cc406Sopenharmony_cistatic const SANE_Word resolutions_rounds_300[5] = { 120141cc406Sopenharmony_ci 4, 0x100, 0x40, 0x20, 0x80 121141cc406Sopenharmony_ci}; 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_cistatic const SANE_Word resolutions_list_400[8] = { 124141cc406Sopenharmony_ci 7, 100, 150, 200, 240, 300, 360, 400 125141cc406Sopenharmony_ci}; 126141cc406Sopenharmony_cistatic const SANE_Word resolutions_rounds_400[8] = { 127141cc406Sopenharmony_ci 7, 0x100, 0x100, 0x40, 0x20, 0x80, 0x100, 0x100 /* TO FIX */ 128141cc406Sopenharmony_ci}; 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 131141cc406Sopenharmony_ci 132141cc406Sopenharmony_ci/* Lists of supported halftone. They are only valid with 133141cc406Sopenharmony_ci * for the Black&White mode. */ 134141cc406Sopenharmony_cistatic SANE_String_Const halftone_pattern_list[] = { 135141cc406Sopenharmony_ci SANE_I18N ("None"), 136141cc406Sopenharmony_ci SANE_I18N ("Bayer Dither 16"), 137141cc406Sopenharmony_ci SANE_I18N ("Bayer Dither 64"), 138141cc406Sopenharmony_ci SANE_I18N ("Halftone Dot 32"), 139141cc406Sopenharmony_ci SANE_I18N ("Halftone Dot 64"), 140141cc406Sopenharmony_ci SANE_I18N ("Error Diffusion"), 141141cc406Sopenharmony_ci NULL 142141cc406Sopenharmony_ci}; 143141cc406Sopenharmony_cistatic const int halftone_pattern_val[] = { 144141cc406Sopenharmony_ci -1, 145141cc406Sopenharmony_ci 0x01, 146141cc406Sopenharmony_ci 0x00, 147141cc406Sopenharmony_ci 0x02, 148141cc406Sopenharmony_ci 0x03, 149141cc406Sopenharmony_ci 0x04 150141cc406Sopenharmony_ci}; 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci/* List of automatic threshold options */ 155141cc406Sopenharmony_cistatic SANE_String_Const automatic_threshold_list[] = { 156141cc406Sopenharmony_ci SANE_I18N ("None"), 157141cc406Sopenharmony_ci SANE_I18N ("Mode 1"), 158141cc406Sopenharmony_ci SANE_I18N ("Mode 2"), 159141cc406Sopenharmony_ci SANE_I18N ("Mode 3"), 160141cc406Sopenharmony_ci NULL 161141cc406Sopenharmony_ci}; 162141cc406Sopenharmony_cistatic const int automatic_threshold_val[] = { 163141cc406Sopenharmony_ci 0, 164141cc406Sopenharmony_ci 0x80, 165141cc406Sopenharmony_ci 0x81, 166141cc406Sopenharmony_ci 0x82 167141cc406Sopenharmony_ci}; 168141cc406Sopenharmony_ci 169141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci/* List of white level base. */ 172141cc406Sopenharmony_cistatic SANE_String_Const white_level_list[] = { 173141cc406Sopenharmony_ci SANE_I18N ("From white stick"), 174141cc406Sopenharmony_ci SANE_I18N ("From paper"), 175141cc406Sopenharmony_ci SANE_I18N ("Automatic"), 176141cc406Sopenharmony_ci NULL 177141cc406Sopenharmony_ci}; 178141cc406Sopenharmony_cistatic const int white_level_val[] = { 179141cc406Sopenharmony_ci 0x00, 180141cc406Sopenharmony_ci 0x80, 181141cc406Sopenharmony_ci 0x81 182141cc406Sopenharmony_ci}; 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 185141cc406Sopenharmony_ci 186141cc406Sopenharmony_ci/* List of noise reduction options. */ 187141cc406Sopenharmony_cistatic SANE_String_Const noise_reduction_list[] = { 188141cc406Sopenharmony_ci SANE_I18N ("None"), 189141cc406Sopenharmony_ci "1x1", 190141cc406Sopenharmony_ci "2x2", 191141cc406Sopenharmony_ci "3x3", 192141cc406Sopenharmony_ci "4x4", 193141cc406Sopenharmony_ci "5x5", 194141cc406Sopenharmony_ci NULL 195141cc406Sopenharmony_ci}; 196141cc406Sopenharmony_cistatic const int noise_reduction_val[] = { 197141cc406Sopenharmony_ci 0x00, 198141cc406Sopenharmony_ci 0x01, 199141cc406Sopenharmony_ci 0x02, 200141cc406Sopenharmony_ci 0x03, 201141cc406Sopenharmony_ci 0x04, 202141cc406Sopenharmony_ci 0x05 203141cc406Sopenharmony_ci}; 204141cc406Sopenharmony_ci 205141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci/* List of image emphasis options, 5 steps */ 208141cc406Sopenharmony_cistatic SANE_String_Const image_emphasis_list_5[] = { 209141cc406Sopenharmony_ci SANE_I18N ("Smooth"), 210141cc406Sopenharmony_ci SANE_I18N ("None"), 211141cc406Sopenharmony_ci SANE_I18N ("Low"), 212141cc406Sopenharmony_ci SANE_I18N ("Medium"), /* default */ 213141cc406Sopenharmony_ci SANE_I18N ("High"), 214141cc406Sopenharmony_ci NULL 215141cc406Sopenharmony_ci}; 216141cc406Sopenharmony_cistatic const int image_emphasis_val_5[] = { 217141cc406Sopenharmony_ci 0x80, 218141cc406Sopenharmony_ci 0x00, 219141cc406Sopenharmony_ci 0x01, 220141cc406Sopenharmony_ci 0x30, 221141cc406Sopenharmony_ci 0x50 222141cc406Sopenharmony_ci}; 223141cc406Sopenharmony_ci 224141cc406Sopenharmony_ci/* List of image emphasis options, 3 steps */ 225141cc406Sopenharmony_cistatic SANE_String_Const image_emphasis_list_3[] = { 226141cc406Sopenharmony_ci SANE_I18N ("Low"), 227141cc406Sopenharmony_ci SANE_I18N ("Medium"), /* default ? */ 228141cc406Sopenharmony_ci SANE_I18N ("High"), 229141cc406Sopenharmony_ci NULL 230141cc406Sopenharmony_ci}; 231141cc406Sopenharmony_cistatic const int image_emphasis_val_3[] = { 232141cc406Sopenharmony_ci 0x01, 233141cc406Sopenharmony_ci 0x30, 234141cc406Sopenharmony_ci 0x50 235141cc406Sopenharmony_ci}; 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci/* List of gamma */ 240141cc406Sopenharmony_cistatic SANE_String_Const gamma_list[] = { 241141cc406Sopenharmony_ci SANE_I18N ("Normal"), 242141cc406Sopenharmony_ci SANE_I18N ("CRT"), 243141cc406Sopenharmony_ci NULL 244141cc406Sopenharmony_ci}; 245141cc406Sopenharmony_cistatic const int gamma_val[] = { 246141cc406Sopenharmony_ci 0x00, 247141cc406Sopenharmony_ci 0x01 248141cc406Sopenharmony_ci}; 249141cc406Sopenharmony_ci 250141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci/* Page feeder options */ 253141cc406Sopenharmony_cistatic SANE_String_Const feeder_mode_list[] = { 254141cc406Sopenharmony_ci SANE_I18N ("One page"), 255141cc406Sopenharmony_ci SANE_I18N ("All pages"), 256141cc406Sopenharmony_ci NULL 257141cc406Sopenharmony_ci}; 258141cc406Sopenharmony_cistatic const int feeder_mode_val[] = { 259141cc406Sopenharmony_ci 0x00, 260141cc406Sopenharmony_ci 0xff 261141cc406Sopenharmony_ci}; 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 264141cc406Sopenharmony_ci 265141cc406Sopenharmony_ci/* Paper size in millimeters. 266141cc406Sopenharmony_ci * Values from http://www.twics.com/~eds/paper/. */ 267141cc406Sopenharmony_cistatic const struct paper_sizes paper_sizes[] = { 268141cc406Sopenharmony_ci {"2A0", 1189, 1682}, 269141cc406Sopenharmony_ci {"4A0", 1682, 2378}, 270141cc406Sopenharmony_ci {"A0", 841, 1189}, 271141cc406Sopenharmony_ci {"A1", 594, 841}, 272141cc406Sopenharmony_ci {"A2", 420, 594}, 273141cc406Sopenharmony_ci {"A3", 297, 420}, 274141cc406Sopenharmony_ci {"A4", 210, 297}, 275141cc406Sopenharmony_ci {"A5", 148, 210}, 276141cc406Sopenharmony_ci {"A6", 105, 148}, 277141cc406Sopenharmony_ci {"A7", 74, 105}, 278141cc406Sopenharmony_ci {"A8", 52, 74}, 279141cc406Sopenharmony_ci {"A9", 37, 52}, 280141cc406Sopenharmony_ci {"A10", 26, 37}, 281141cc406Sopenharmony_ci {"B0", 1000, 1414}, 282141cc406Sopenharmony_ci {"B1", 707, 1000}, 283141cc406Sopenharmony_ci {"B2", 500, 707}, 284141cc406Sopenharmony_ci {"B3", 353, 500}, 285141cc406Sopenharmony_ci {"B4", 250, 353}, 286141cc406Sopenharmony_ci {"B5", 176, 250}, 287141cc406Sopenharmony_ci {"B6", 125, 176}, 288141cc406Sopenharmony_ci {"B7", 88, 125}, 289141cc406Sopenharmony_ci {"B8", 62, 88}, 290141cc406Sopenharmony_ci {"B9", 44, 62}, 291141cc406Sopenharmony_ci {"B10", 31, 44}, 292141cc406Sopenharmony_ci {"C0", 917, 1297}, 293141cc406Sopenharmony_ci {"C1", 648, 917}, 294141cc406Sopenharmony_ci {"C2", 458, 648}, 295141cc406Sopenharmony_ci {"C3", 324, 458}, 296141cc406Sopenharmony_ci {"C4", 229, 324}, 297141cc406Sopenharmony_ci {"C5", 162, 229}, 298141cc406Sopenharmony_ci {"C6", 114, 162}, 299141cc406Sopenharmony_ci {"C7", 81, 114}, 300141cc406Sopenharmony_ci {"C8", 57, 81}, 301141cc406Sopenharmony_ci {"C9", 40, 57}, 302141cc406Sopenharmony_ci {"C10", 28, 40}, 303141cc406Sopenharmony_ci {"Legal", 8.5 * MM_PER_INCH, 14 * MM_PER_INCH}, 304141cc406Sopenharmony_ci {"Letter", 8.5 * MM_PER_INCH, 11 * MM_PER_INCH} 305141cc406Sopenharmony_ci}; 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 308141cc406Sopenharmony_ci 309141cc406Sopenharmony_ci/* Define the supported scanners and their characteristics. */ 310141cc406Sopenharmony_cistatic const struct scanners_supported scanners[] = { 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci /* Panasonic KV-SS25 */ 313141cc406Sopenharmony_ci { 314141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS25A ", 315141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 316141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ 317141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 318141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range */ 319141cc406Sopenharmony_ci scan_mode_list_3, 320141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, 321141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 322141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | 323141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 324141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION}, 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci /* Panasonic KV-SS25D */ 327141cc406Sopenharmony_ci { 328141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS25D ", /* TO FIX */ 329141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 330141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ 331141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 332141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range */ 333141cc406Sopenharmony_ci scan_mode_list_3, 334141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, 335141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 336141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | 337141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 338141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION}, 339141cc406Sopenharmony_ci 340141cc406Sopenharmony_ci /* Panasonic KV-SS50 */ 341141cc406Sopenharmony_ci { 342141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS50 ", /* TO FIX */ 343141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 344141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ 345141cc406Sopenharmony_ci {1, 5, 1}, /* brightness range, TO FIX */ 346141cc406Sopenharmony_ci {0, 0, 0}, /* contrast range */ 347141cc406Sopenharmony_ci scan_mode_list_1, 348141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, /* TO FIX */ 349141cc406Sopenharmony_ci image_emphasis_list_3, image_emphasis_val_3, 350141cc406Sopenharmony_ci MAT_CAP_PAPER_DETECT | MAT_CAP_MIRROR_IMAGE}, 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci /* Panasonic KV-SS55 */ 353141cc406Sopenharmony_ci { 354141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS55 ", /* TO FIX */ 355141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 356141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ 357141cc406Sopenharmony_ci {1, 5, 1}, /* brightness range, TO FIX */ 358141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range, TO FIX */ 359141cc406Sopenharmony_ci scan_mode_list_1, 360141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, /* TO FIX */ 361141cc406Sopenharmony_ci image_emphasis_list_3, image_emphasis_val_3, 362141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_PAPER_DETECT | 363141cc406Sopenharmony_ci MAT_CAP_MIRROR_IMAGE}, 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci /* Panasonic KV-SS50EX */ 366141cc406Sopenharmony_ci { 367141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS50EX ", /* TO FIX */ 368141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 369141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ 370141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 371141cc406Sopenharmony_ci {0, 0, 0}, /* contrast range */ 372141cc406Sopenharmony_ci scan_mode_list_3, 373141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, /* TO FIX */ 374141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 375141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 376141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION | MAT_CAP_PAPER_DETECT | MAT_CAP_MIRROR_IMAGE}, 377141cc406Sopenharmony_ci 378141cc406Sopenharmony_ci /* Panasonic KV-SS55EX */ 379141cc406Sopenharmony_ci { 380141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS55EX ", 381141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 382141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ 383141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 384141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range */ 385141cc406Sopenharmony_ci scan_mode_list_3, 386141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, 387141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 388141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | 389141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 390141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION}, 391141cc406Sopenharmony_ci 392141cc406Sopenharmony_ci /* Panasonic KV-SS850 */ 393141cc406Sopenharmony_ci { 394141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS850 ", /* TO FIX */ 395141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (11.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 396141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ 397141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 398141cc406Sopenharmony_ci {0, 0, 0}, /* contrast range */ 399141cc406Sopenharmony_ci scan_mode_list_3, 400141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, /* TO FIX */ 401141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 402141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | 403141cc406Sopenharmony_ci MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION | MAT_CAP_PAPER_DETECT | 404141cc406Sopenharmony_ci MAT_CAP_DETECT_DOUBLE_FEED | MAT_CAP_MANUAL_FEED}, 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci /* Panasonic KV-SS855 */ 407141cc406Sopenharmony_ci { 408141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-SS855 ", /* TO FIX */ 409141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (11.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 410141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ 411141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 412141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range, TO FIX */ 413141cc406Sopenharmony_ci scan_mode_list_3, 414141cc406Sopenharmony_ci resolutions_list_400, resolutions_rounds_400, /* TO FIX */ 415141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 416141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | 417141cc406Sopenharmony_ci MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION | 418141cc406Sopenharmony_ci MAT_CAP_PAPER_DETECT | MAT_CAP_DETECT_DOUBLE_FEED | MAT_CAP_MANUAL_FEED}, 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci /* Panasonic KV-S2065L */ 421141cc406Sopenharmony_ci { 422141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-S2065L ", 423141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 424141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ 425141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 426141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range */ 427141cc406Sopenharmony_ci scan_mode_list_3, 428141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, 429141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 430141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | 431141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 432141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION}, 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci /* Panasonic KV-S2025C */ 435141cc406Sopenharmony_ci { 436141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-S2025C ", 437141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 438141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ 439141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 440141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range */ 441141cc406Sopenharmony_ci scan_mode_list_3, 442141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, 443141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 444141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | 445141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 446141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION}, 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci /* Panasonic KV-S2045C */ 449141cc406Sopenharmony_ci { 450141cc406Sopenharmony_ci 0x06, "K.M.E. ", "KV-S2045C ", 451141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ 452141cc406Sopenharmony_ci {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ 453141cc406Sopenharmony_ci {1, 255, 1}, /* brightness range */ 454141cc406Sopenharmony_ci {1, 255, 1}, /* contrast range */ 455141cc406Sopenharmony_ci scan_mode_list_3, 456141cc406Sopenharmony_ci resolutions_list_300, resolutions_rounds_300, 457141cc406Sopenharmony_ci image_emphasis_list_5, image_emphasis_val_5, 458141cc406Sopenharmony_ci MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | 459141cc406Sopenharmony_ci MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | 460141cc406Sopenharmony_ci MAT_CAP_NOISE_REDUCTION} 461141cc406Sopenharmony_ci}; 462141cc406Sopenharmony_ci 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci/* List of scanner attached. */ 467141cc406Sopenharmony_cistatic Matsushita_Scanner *first_dev = NULL; 468141cc406Sopenharmony_cistatic int num_devices = 0; 469141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL; 470141cc406Sopenharmony_ci 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci/* Local functions. */ 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci/* Display a buffer in the log. */ 475141cc406Sopenharmony_cistatic void 476141cc406Sopenharmony_cihexdump (int level, const char *comment, unsigned char *p, int l) 477141cc406Sopenharmony_ci{ 478141cc406Sopenharmony_ci int i; 479141cc406Sopenharmony_ci char line[128]; 480141cc406Sopenharmony_ci char *ptr; 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci DBG (level, "%s\n", comment); 483141cc406Sopenharmony_ci ptr = line; 484141cc406Sopenharmony_ci for (i = 0; i < l; i++, p++) 485141cc406Sopenharmony_ci { 486141cc406Sopenharmony_ci if ((i % 16) == 0) 487141cc406Sopenharmony_ci { 488141cc406Sopenharmony_ci if (ptr != line) 489141cc406Sopenharmony_ci { 490141cc406Sopenharmony_ci *ptr = '\0'; 491141cc406Sopenharmony_ci DBG (level, "%s\n", line); 492141cc406Sopenharmony_ci ptr = line; 493141cc406Sopenharmony_ci } 494141cc406Sopenharmony_ci sprintf (ptr, "%3.3d:", i); 495141cc406Sopenharmony_ci ptr += 4; 496141cc406Sopenharmony_ci } 497141cc406Sopenharmony_ci sprintf (ptr, " %2.2x", *p); 498141cc406Sopenharmony_ci ptr += 3; 499141cc406Sopenharmony_ci } 500141cc406Sopenharmony_ci *ptr = '\0'; 501141cc406Sopenharmony_ci DBG (level, "%s\n", line); 502141cc406Sopenharmony_ci} 503141cc406Sopenharmony_ci 504141cc406Sopenharmony_ci/* Returns the length of the longest string, including the terminating 505141cc406Sopenharmony_ci * character. */ 506141cc406Sopenharmony_cistatic size_t 507141cc406Sopenharmony_cimax_string_size (SANE_String_Const strings[]) 508141cc406Sopenharmony_ci{ 509141cc406Sopenharmony_ci size_t size, max_size = 0; 510141cc406Sopenharmony_ci int i; 511141cc406Sopenharmony_ci 512141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 513141cc406Sopenharmony_ci { 514141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 515141cc406Sopenharmony_ci if (size > max_size) 516141cc406Sopenharmony_ci { 517141cc406Sopenharmony_ci max_size = size; 518141cc406Sopenharmony_ci } 519141cc406Sopenharmony_ci } 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci return max_size; 522141cc406Sopenharmony_ci} 523141cc406Sopenharmony_ci 524141cc406Sopenharmony_ci/* After the windows has been set, issue that command to get the 525141cc406Sopenharmony_ci * document size. */ 526141cc406Sopenharmony_cistatic SANE_Status 527141cc406Sopenharmony_cimatsushita_read_document_size (Matsushita_Scanner * dev) 528141cc406Sopenharmony_ci{ 529141cc406Sopenharmony_ci CDB cdb; 530141cc406Sopenharmony_ci SANE_Status status; 531141cc406Sopenharmony_ci size_t size; 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_read_document_size: enter\n"); 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci size = 0x10; 536141cc406Sopenharmony_ci MKSCSI_READ_10 (cdb, 0x80, 0, size); 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 539141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD || size != 0x10) 542141cc406Sopenharmony_ci { 543141cc406Sopenharmony_ci DBG (DBG_error, 544141cc406Sopenharmony_ci "matsushita_read_document_size: cannot read document size\n"); 545141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 546141cc406Sopenharmony_ci } 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci hexdump (DBG_info2, "document size", dev->buffer, 16); 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci /* Check that X and Y are the same values the backend computed. */ 551141cc406Sopenharmony_ci 552141cc406Sopenharmony_ci assert (dev->params.lines == B32TOI (&dev->buffer[4])); 553141cc406Sopenharmony_ci assert (dev->params.pixels_per_line == B32TOI (&dev->buffer[0])); 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_read_document_size: exit, %ld bytes read\n", 556141cc406Sopenharmony_ci (long)size); 557141cc406Sopenharmony_ci 558141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 559141cc406Sopenharmony_ci} 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci/* Initialize a scanner entry. Return an allocated scanner with some 562141cc406Sopenharmony_ci * preset values. */ 563141cc406Sopenharmony_cistatic Matsushita_Scanner * 564141cc406Sopenharmony_cimatsushita_init (void) 565141cc406Sopenharmony_ci{ 566141cc406Sopenharmony_ci Matsushita_Scanner *dev; 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_init: enter\n"); 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ci /* Allocate a new scanner entry. */ 571141cc406Sopenharmony_ci dev = malloc (sizeof (Matsushita_Scanner)); 572141cc406Sopenharmony_ci if (dev == NULL) 573141cc406Sopenharmony_ci { 574141cc406Sopenharmony_ci return NULL; 575141cc406Sopenharmony_ci } 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci memset (dev, 0, sizeof (Matsushita_Scanner)); 578141cc406Sopenharmony_ci 579141cc406Sopenharmony_ci /* Allocate the buffer used to transfer the SCSI data. */ 580141cc406Sopenharmony_ci dev->buffer_size = 64 * 1024; 581141cc406Sopenharmony_ci dev->buffer = malloc (dev->buffer_size); 582141cc406Sopenharmony_ci if (dev->buffer == NULL) 583141cc406Sopenharmony_ci { 584141cc406Sopenharmony_ci free (dev); 585141cc406Sopenharmony_ci return NULL; 586141cc406Sopenharmony_ci } 587141cc406Sopenharmony_ci 588141cc406Sopenharmony_ci /* Allocate a buffer to store the temporary image. */ 589141cc406Sopenharmony_ci dev->image_size = 64 * 1024; /* enough for 1 line at max res */ 590141cc406Sopenharmony_ci dev->image = malloc (dev->image_size); 591141cc406Sopenharmony_ci if (dev->image == NULL) 592141cc406Sopenharmony_ci { 593141cc406Sopenharmony_ci free (dev->buffer); 594141cc406Sopenharmony_ci free (dev); 595141cc406Sopenharmony_ci return NULL; 596141cc406Sopenharmony_ci } 597141cc406Sopenharmony_ci 598141cc406Sopenharmony_ci dev->sfd = -1; 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_init: exit\n"); 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci return (dev); 603141cc406Sopenharmony_ci} 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci/* Closes an open scanner. */ 606141cc406Sopenharmony_cistatic void 607141cc406Sopenharmony_cimatsushita_close (Matsushita_Scanner * dev) 608141cc406Sopenharmony_ci{ 609141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_close: enter\n"); 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci if (dev->sfd != -1) 612141cc406Sopenharmony_ci { 613141cc406Sopenharmony_ci sanei_scsi_close (dev->sfd); 614141cc406Sopenharmony_ci dev->sfd = -1; 615141cc406Sopenharmony_ci } 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_close: exit\n"); 618141cc406Sopenharmony_ci} 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci/* Frees the memory used by a scanner. */ 621141cc406Sopenharmony_cistatic void 622141cc406Sopenharmony_cimatsushita_free (Matsushita_Scanner * dev) 623141cc406Sopenharmony_ci{ 624141cc406Sopenharmony_ci int i; 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_free: enter\n"); 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci if (dev == NULL) 629141cc406Sopenharmony_ci return; 630141cc406Sopenharmony_ci 631141cc406Sopenharmony_ci matsushita_close (dev); 632141cc406Sopenharmony_ci if (dev->devicename) 633141cc406Sopenharmony_ci { 634141cc406Sopenharmony_ci free (dev->devicename); 635141cc406Sopenharmony_ci } 636141cc406Sopenharmony_ci if (dev->buffer) 637141cc406Sopenharmony_ci { 638141cc406Sopenharmony_ci free (dev->buffer); 639141cc406Sopenharmony_ci } 640141cc406Sopenharmony_ci if (dev->image) 641141cc406Sopenharmony_ci { 642141cc406Sopenharmony_ci free (dev->image); 643141cc406Sopenharmony_ci } 644141cc406Sopenharmony_ci for (i = 1; i < OPT_NUM_OPTIONS; i++) 645141cc406Sopenharmony_ci { 646141cc406Sopenharmony_ci if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) 647141cc406Sopenharmony_ci { 648141cc406Sopenharmony_ci free (dev->val[i].s); 649141cc406Sopenharmony_ci } 650141cc406Sopenharmony_ci } 651141cc406Sopenharmony_ci free (dev->paper_sizes_list); 652141cc406Sopenharmony_ci free (dev->paper_sizes_val); 653141cc406Sopenharmony_ci 654141cc406Sopenharmony_ci free (dev); 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_free: exit\n"); 657141cc406Sopenharmony_ci} 658141cc406Sopenharmony_ci 659141cc406Sopenharmony_ci/* Inquiry a device and returns TRUE if is supported. */ 660141cc406Sopenharmony_cistatic int 661141cc406Sopenharmony_cimatsushita_identify_scanner (Matsushita_Scanner * dev) 662141cc406Sopenharmony_ci{ 663141cc406Sopenharmony_ci CDB cdb; 664141cc406Sopenharmony_ci SANE_Status status; 665141cc406Sopenharmony_ci size_t size; 666141cc406Sopenharmony_ci int i; 667141cc406Sopenharmony_ci 668141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_identify_scanner: enter\n"); 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci size = 5; 671141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 672141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 673141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci if (status) 676141cc406Sopenharmony_ci { 677141cc406Sopenharmony_ci DBG (DBG_error, 678141cc406Sopenharmony_ci "matsushita_identify_scanner: inquiry failed with status %s\n", 679141cc406Sopenharmony_ci sane_strstatus (status)); 680141cc406Sopenharmony_ci return (SANE_FALSE); 681141cc406Sopenharmony_ci } 682141cc406Sopenharmony_ci 683141cc406Sopenharmony_ci size = dev->buffer[4] + 5; /* total length of the inquiry data */ 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci if (size < 36) 686141cc406Sopenharmony_ci { 687141cc406Sopenharmony_ci DBG (DBG_error, 688141cc406Sopenharmony_ci "matsushita_identify_scanner: not enough data to identify device\n"); 689141cc406Sopenharmony_ci return (SANE_FALSE); 690141cc406Sopenharmony_ci } 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci MKSCSI_INQUIRY (cdb, size); 693141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 694141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci if (status) 697141cc406Sopenharmony_ci { 698141cc406Sopenharmony_ci DBG (DBG_error, 699141cc406Sopenharmony_ci "matsushita_identify_scanner: inquiry failed with status %s\n", 700141cc406Sopenharmony_ci sane_strstatus (status)); 701141cc406Sopenharmony_ci return (SANE_FALSE); 702141cc406Sopenharmony_ci } 703141cc406Sopenharmony_ci 704141cc406Sopenharmony_ci hexdump (DBG_info2, "inquiry", dev->buffer, size); 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ci dev->scsi_type = dev->buffer[0] & 0x1f; 707141cc406Sopenharmony_ci memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); 708141cc406Sopenharmony_ci dev->scsi_vendor[0x08] = 0; 709141cc406Sopenharmony_ci memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); 710141cc406Sopenharmony_ci dev->scsi_product[0x10] = 0; 711141cc406Sopenharmony_ci memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); 712141cc406Sopenharmony_ci dev->scsi_version[0x04] = 0; 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\"\n", 715141cc406Sopenharmony_ci dev->scsi_vendor, dev->scsi_product, dev->scsi_version); 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci /* Lookup through the supported scanners table to find if this 718141cc406Sopenharmony_ci * backend supports that one. */ 719141cc406Sopenharmony_ci for (i = 0; i < NELEMS (scanners); i++) 720141cc406Sopenharmony_ci { 721141cc406Sopenharmony_ci if (dev->scsi_type == scanners[i].scsi_type && 722141cc406Sopenharmony_ci strcmp (dev->scsi_vendor, scanners[i].scsi_vendor) == 0 && 723141cc406Sopenharmony_ci strcmp (dev->scsi_product, scanners[i].scsi_product) == 0) 724141cc406Sopenharmony_ci { 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci DBG (DBG_error, "matsushita_identify_scanner: scanner supported\n"); 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci dev->scnum = i; 729141cc406Sopenharmony_ci 730141cc406Sopenharmony_ci return (SANE_TRUE); 731141cc406Sopenharmony_ci } 732141cc406Sopenharmony_ci } 733141cc406Sopenharmony_ci 734141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_identify_scanner: exit, device not supported\n"); 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci return (SANE_FALSE); 737141cc406Sopenharmony_ci} 738141cc406Sopenharmony_ci 739141cc406Sopenharmony_ci/* The interface can show different paper sizes. Show only the sizes 740141cc406Sopenharmony_ci * available for that scanner. */ 741141cc406Sopenharmony_cistatic int 742141cc406Sopenharmony_cimatsushita_build_paper_sizes (Matsushita_Scanner * dev) 743141cc406Sopenharmony_ci{ 744141cc406Sopenharmony_ci SANE_String_Const *psl; /* string list */ 745141cc406Sopenharmony_ci int *psv; /* value list */ 746141cc406Sopenharmony_ci int num; 747141cc406Sopenharmony_ci int i; 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_build_paper_sizes: enter\n"); 750141cc406Sopenharmony_ci 751141cc406Sopenharmony_ci psl = malloc ((sizeof (SANE_String_Const) + 1) * NELEMS (paper_sizes)); 752141cc406Sopenharmony_ci if (psl == NULL) 753141cc406Sopenharmony_ci { 754141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: not enough memory\n"); 755141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 756141cc406Sopenharmony_ci } 757141cc406Sopenharmony_ci 758141cc406Sopenharmony_ci psv = malloc ((sizeof (int) + 1) * NELEMS (paper_sizes)); 759141cc406Sopenharmony_ci if (psv == NULL) 760141cc406Sopenharmony_ci { 761141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: not enough memory\n"); 762141cc406Sopenharmony_ci free (psl); 763141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 764141cc406Sopenharmony_ci } 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci for (i = 0, num = 0; i < NELEMS (paper_sizes); i++) 767141cc406Sopenharmony_ci { 768141cc406Sopenharmony_ci if (SANE_UNFIX (scanners[dev->scnum].x_range.max) >= 769141cc406Sopenharmony_ci paper_sizes[i].width 770141cc406Sopenharmony_ci && SANE_UNFIX (scanners[dev->scnum].y_range.max) >= 771141cc406Sopenharmony_ci paper_sizes[i].length) 772141cc406Sopenharmony_ci { 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci /* This paper size fits into the scanner. */ 775141cc406Sopenharmony_ci psl[num] = paper_sizes[i].name; 776141cc406Sopenharmony_ci psv[num] = i; 777141cc406Sopenharmony_ci num++; 778141cc406Sopenharmony_ci } 779141cc406Sopenharmony_ci } 780141cc406Sopenharmony_ci psl[num] = NULL; /* terminate the list */ 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci dev->paper_sizes_list = psl; 783141cc406Sopenharmony_ci dev->paper_sizes_val = psv; 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_build_paper_sizes: exit (%d)\n", num); 786141cc406Sopenharmony_ci 787141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 788141cc406Sopenharmony_ci} 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci/* Lookup a string list from one array and return its index. */ 791141cc406Sopenharmony_cistatic int 792141cc406Sopenharmony_ciget_string_list_index (SANE_String_Const list[], SANE_String_Const name) 793141cc406Sopenharmony_ci{ 794141cc406Sopenharmony_ci int index; 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_ci index = 0; 797141cc406Sopenharmony_ci while (list[index] != NULL) 798141cc406Sopenharmony_ci { 799141cc406Sopenharmony_ci if (strcmp (list[index], name) == 0) 800141cc406Sopenharmony_ci { 801141cc406Sopenharmony_ci return (index); 802141cc406Sopenharmony_ci } 803141cc406Sopenharmony_ci index++; 804141cc406Sopenharmony_ci } 805141cc406Sopenharmony_ci 806141cc406Sopenharmony_ci DBG (DBG_error, "name %s not found in list\n", name); 807141cc406Sopenharmony_ci 808141cc406Sopenharmony_ci assert (0 == 1); /* bug in backend, core dump */ 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci return (-1); 811141cc406Sopenharmony_ci} 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci/* Lookup an int list from one array and return its index. */ 814141cc406Sopenharmony_cistatic int 815141cc406Sopenharmony_ciget_int_list_index (const SANE_Word list[], const SANE_Word value) 816141cc406Sopenharmony_ci{ 817141cc406Sopenharmony_ci int index; 818141cc406Sopenharmony_ci int size; /* number of elements */ 819141cc406Sopenharmony_ci 820141cc406Sopenharmony_ci index = 1; 821141cc406Sopenharmony_ci size = list[0]; 822141cc406Sopenharmony_ci while (index <= size) 823141cc406Sopenharmony_ci { 824141cc406Sopenharmony_ci if (list[index] == value) 825141cc406Sopenharmony_ci { 826141cc406Sopenharmony_ci return (index); 827141cc406Sopenharmony_ci } 828141cc406Sopenharmony_ci index++; 829141cc406Sopenharmony_ci } 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci DBG (DBG_error, "word %d not found in list\n", value); 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci assert (0 == 1); /* bug in backend, core dump */ 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_ci return (-1); 836141cc406Sopenharmony_ci} 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci/* SCSI sense handler. Callback for SANE. */ 839141cc406Sopenharmony_cistatic SANE_Status 840141cc406Sopenharmony_cimatsushita_sense_handler (int scsi_fd, unsigned char *result, void __sane_unused__ *arg) 841141cc406Sopenharmony_ci{ 842141cc406Sopenharmony_ci int asc, ascq, sensekey; 843141cc406Sopenharmony_ci int len; 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_sense_handler (scsi_fd = %d)\n", scsi_fd); 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci sensekey = get_RS_sense_key (result); 848141cc406Sopenharmony_ci len = 7 + get_RS_additional_length (result); 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_ci hexdump (DBG_info2, "sense", result, len); 851141cc406Sopenharmony_ci 852141cc406Sopenharmony_ci if (get_RS_error_code (result) != 0x70) 853141cc406Sopenharmony_ci { 854141cc406Sopenharmony_ci DBG (DBG_error, 855141cc406Sopenharmony_ci "matsushita_sense_handler: invalid sense key error code (%d)\n", 856141cc406Sopenharmony_ci get_RS_error_code (result)); 857141cc406Sopenharmony_ci 858141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 859141cc406Sopenharmony_ci } 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci if (get_RS_ILI (result) != 0) 862141cc406Sopenharmony_ci { 863141cc406Sopenharmony_ci DBG (DBG_sense, "matsushita_sense_handler: short read\n"); 864141cc406Sopenharmony_ci } 865141cc406Sopenharmony_ci 866141cc406Sopenharmony_ci if (len < 14) 867141cc406Sopenharmony_ci { 868141cc406Sopenharmony_ci DBG (DBG_error, 869141cc406Sopenharmony_ci "matsushita_sense_handler: sense too short, no ASC/ASCQ\n"); 870141cc406Sopenharmony_ci 871141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 872141cc406Sopenharmony_ci } 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_ci asc = get_RS_ASC (result); 875141cc406Sopenharmony_ci ascq = get_RS_ASCQ (result); 876141cc406Sopenharmony_ci 877141cc406Sopenharmony_ci DBG (DBG_sense, "matsushita_sense_handler: sense=%d, ASC/ASCQ=%02x%02x\n", 878141cc406Sopenharmony_ci sensekey, asc, ascq); 879141cc406Sopenharmony_ci 880141cc406Sopenharmony_ci switch (sensekey) 881141cc406Sopenharmony_ci { 882141cc406Sopenharmony_ci case 0x00: /* no sense */ 883141cc406Sopenharmony_ci if (get_RS_EOM (result) && asc == 0x00 && ascq == 0x00) 884141cc406Sopenharmony_ci { 885141cc406Sopenharmony_ci DBG (DBG_sense, "matsushita_sense_handler: EOF\n"); 886141cc406Sopenharmony_ci return SANE_STATUS_EOF; 887141cc406Sopenharmony_ci } 888141cc406Sopenharmony_ci 889141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 890141cc406Sopenharmony_ci break; 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci case 0x02: /* not ready */ 893141cc406Sopenharmony_ci if (asc == 0x04 && ascq == 0x81) 894141cc406Sopenharmony_ci { 895141cc406Sopenharmony_ci /* Jam door open. */ 896141cc406Sopenharmony_ci return SANE_STATUS_COVER_OPEN; 897141cc406Sopenharmony_ci } 898141cc406Sopenharmony_ci break; 899141cc406Sopenharmony_ci 900141cc406Sopenharmony_ci case 0x03: /* medium error */ 901141cc406Sopenharmony_ci if (asc == 0x3a) 902141cc406Sopenharmony_ci { 903141cc406Sopenharmony_ci /* No paper in the feeder. */ 904141cc406Sopenharmony_ci return SANE_STATUS_NO_DOCS; 905141cc406Sopenharmony_ci } 906141cc406Sopenharmony_ci if (asc == 0x80) 907141cc406Sopenharmony_ci { 908141cc406Sopenharmony_ci /* Probably a paper jam. ascq might give more info. */ 909141cc406Sopenharmony_ci return SANE_STATUS_JAMMED; 910141cc406Sopenharmony_ci } 911141cc406Sopenharmony_ci break; 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci case 0x05: 914141cc406Sopenharmony_ci if (asc == 0x20 || asc == 0x24 || asc == 0x26) 915141cc406Sopenharmony_ci { 916141cc406Sopenharmony_ci /* Invalid command, invalid field in CDB or invalid field in data. 917141cc406Sopenharmony_ci * The backend has prepared some wrong combination of options. 918141cc406Sopenharmony_ci * Shot the backend maintainer. */ 919141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 920141cc406Sopenharmony_ci } 921141cc406Sopenharmony_ci else if (asc == 0x2c && ascq == 0x80) 922141cc406Sopenharmony_ci { 923141cc406Sopenharmony_ci /* The scanner does have enough memory to scan the whole 924141cc406Sopenharmony_ci * area. For instance the KV-SS25 has only 4MB of memory, 925141cc406Sopenharmony_ci * which is not enough to scan a A4 page at 300dpi in gray 926141cc406Sopenharmony_ci * 8 bits. */ 927141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 928141cc406Sopenharmony_ci } 929141cc406Sopenharmony_ci break; 930141cc406Sopenharmony_ci 931141cc406Sopenharmony_ci case 0x06: 932141cc406Sopenharmony_ci if (asc == 0x29) 933141cc406Sopenharmony_ci { 934141cc406Sopenharmony_ci /* Reset occurred. May be the backend should retry the 935141cc406Sopenharmony_ci * command. */ 936141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 937141cc406Sopenharmony_ci } 938141cc406Sopenharmony_ci break; 939141cc406Sopenharmony_ci } 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_ci DBG (DBG_sense, 942141cc406Sopenharmony_ci "matsushita_sense_handler: unknown error condition. Please report it to the backend maintainer\n"); 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 945141cc406Sopenharmony_ci} 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci/* Check that a new page is available by issuing an empty read. The 948141cc406Sopenharmony_ci * sense handler might return SANE_STATUS_NO_DOCS which indicates that 949141cc406Sopenharmony_ci * the feeder is now empty. */ 950141cc406Sopenharmony_cistatic SANE_Status 951141cc406Sopenharmony_cimatsushita_check_next_page (Matsushita_Scanner * dev) 952141cc406Sopenharmony_ci{ 953141cc406Sopenharmony_ci CDB cdb; 954141cc406Sopenharmony_ci SANE_Status status; 955141cc406Sopenharmony_ci 956141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_check_next_page: enter\n"); 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci MKSCSI_READ_10 (cdb, 0, 0, 0); 959141cc406Sopenharmony_ci cdb.data[4] = dev->page_num; /* May be cdb.data[3] too? */ 960141cc406Sopenharmony_ci cdb.data[5] = dev->page_side; 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 963141cc406Sopenharmony_ci 964141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_check_next_page: exit with status %d\n", status); 965141cc406Sopenharmony_ci 966141cc406Sopenharmony_ci return (status); 967141cc406Sopenharmony_ci} 968141cc406Sopenharmony_ci 969141cc406Sopenharmony_ci/* Attach a scanner to this backend. */ 970141cc406Sopenharmony_cistatic SANE_Status 971141cc406Sopenharmony_ciattach_scanner (const char *devicename, Matsushita_Scanner ** devp) 972141cc406Sopenharmony_ci{ 973141cc406Sopenharmony_ci Matsushita_Scanner *dev; 974141cc406Sopenharmony_ci int sfd; 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); 977141cc406Sopenharmony_ci 978141cc406Sopenharmony_ci if (devp) 979141cc406Sopenharmony_ci *devp = NULL; 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_ci /* Check if we know this device name. */ 982141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 983141cc406Sopenharmony_ci { 984141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 985141cc406Sopenharmony_ci { 986141cc406Sopenharmony_ci if (devp) 987141cc406Sopenharmony_ci { 988141cc406Sopenharmony_ci *devp = dev; 989141cc406Sopenharmony_ci } 990141cc406Sopenharmony_ci DBG (DBG_info, "device is already known\n"); 991141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 992141cc406Sopenharmony_ci } 993141cc406Sopenharmony_ci } 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_ci /* Allocate a new scanner entry. */ 996141cc406Sopenharmony_ci dev = matsushita_init (); 997141cc406Sopenharmony_ci if (dev == NULL) 998141cc406Sopenharmony_ci { 999141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: not enough memory\n"); 1000141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1001141cc406Sopenharmony_ci } 1002141cc406Sopenharmony_ci 1003141cc406Sopenharmony_ci DBG (DBG_info, "attach_scanner: opening %s\n", devicename); 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci if (sanei_scsi_open (devicename, &sfd, matsushita_sense_handler, dev) != 0) 1006141cc406Sopenharmony_ci { 1007141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); 1008141cc406Sopenharmony_ci matsushita_free (dev); 1009141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1010141cc406Sopenharmony_ci } 1011141cc406Sopenharmony_ci 1012141cc406Sopenharmony_ci /* Fill some scanner specific values. */ 1013141cc406Sopenharmony_ci dev->devicename = strdup (devicename); 1014141cc406Sopenharmony_ci dev->sfd = sfd; 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci /* Now, check that it is a scanner we support. */ 1017141cc406Sopenharmony_ci if (matsushita_identify_scanner (dev) == SANE_FALSE) 1018141cc406Sopenharmony_ci { 1019141cc406Sopenharmony_ci DBG (DBG_error, 1020141cc406Sopenharmony_ci "ERROR: attach_scanner: scanner-identification failed\n"); 1021141cc406Sopenharmony_ci matsushita_free (dev); 1022141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1023141cc406Sopenharmony_ci } 1024141cc406Sopenharmony_ci 1025141cc406Sopenharmony_ci matsushita_close (dev); 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci /* Set the default options for that scanner. */ 1028141cc406Sopenharmony_ci dev->sane.name = dev->devicename; 1029141cc406Sopenharmony_ci dev->sane.vendor = "Panasonic"; 1030141cc406Sopenharmony_ci dev->sane.model = dev->scsi_product; 1031141cc406Sopenharmony_ci dev->sane.type = SANE_I18N ("sheetfed scanner"); 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci /* Link the scanner with the others. */ 1034141cc406Sopenharmony_ci dev->next = first_dev; 1035141cc406Sopenharmony_ci first_dev = dev; 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci if (devp) 1038141cc406Sopenharmony_ci { 1039141cc406Sopenharmony_ci *devp = dev; 1040141cc406Sopenharmony_ci } 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_ci num_devices++; 1043141cc406Sopenharmony_ci 1044141cc406Sopenharmony_ci DBG (DBG_proc, "attach_scanner: exit\n"); 1045141cc406Sopenharmony_ci 1046141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1047141cc406Sopenharmony_ci} 1048141cc406Sopenharmony_ci 1049141cc406Sopenharmony_cistatic SANE_Status 1050141cc406Sopenharmony_ciattach_one (const char *dev) 1051141cc406Sopenharmony_ci{ 1052141cc406Sopenharmony_ci attach_scanner (dev, NULL); 1053141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1054141cc406Sopenharmony_ci} 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_ci/* Reset the options for that scanner. */ 1057141cc406Sopenharmony_cistatic void 1058141cc406Sopenharmony_cimatsushita_init_options (Matsushita_Scanner * dev) 1059141cc406Sopenharmony_ci{ 1060141cc406Sopenharmony_ci int i; 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_ci /* Pre-initialize the options. */ 1063141cc406Sopenharmony_ci memset (dev->opt, 0, sizeof (dev->opt)); 1064141cc406Sopenharmony_ci memset (dev->val, 0, sizeof (dev->val)); 1065141cc406Sopenharmony_ci 1066141cc406Sopenharmony_ci for (i = 0; i < OPT_NUM_OPTIONS; ++i) 1067141cc406Sopenharmony_ci { 1068141cc406Sopenharmony_ci dev->opt[i].size = sizeof (SANE_Word); 1069141cc406Sopenharmony_ci dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 1070141cc406Sopenharmony_ci } 1071141cc406Sopenharmony_ci 1072141cc406Sopenharmony_ci /* Number of options. */ 1073141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].name = ""; 1074141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 1075141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 1076141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 1077141cc406Sopenharmony_ci dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 1078141cc406Sopenharmony_ci dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; 1079141cc406Sopenharmony_ci 1080141cc406Sopenharmony_ci /* Mode group */ 1081141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); 1082141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ 1083141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; 1084141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].cap = 0; 1085141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].size = 0; 1086141cc406Sopenharmony_ci dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci /* Scanner supported modes */ 1089141cc406Sopenharmony_ci dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 1090141cc406Sopenharmony_ci dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 1091141cc406Sopenharmony_ci dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 1092141cc406Sopenharmony_ci dev->opt[OPT_MODE].type = SANE_TYPE_STRING; 1093141cc406Sopenharmony_ci dev->opt[OPT_MODE].size = 1094141cc406Sopenharmony_ci max_string_size (scanners[dev->scnum].scan_mode_list); 1095141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1096141cc406Sopenharmony_ci dev->opt[OPT_MODE].constraint.string_list = 1097141cc406Sopenharmony_ci scanners[dev->scnum].scan_mode_list; 1098141cc406Sopenharmony_ci dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ 1099141cc406Sopenharmony_ci 1100141cc406Sopenharmony_ci /* X and Y resolution */ 1101141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 1102141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 1103141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 1104141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 1105141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 1106141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 1107141cc406Sopenharmony_ci dev->opt[OPT_RESOLUTION].constraint.word_list = 1108141cc406Sopenharmony_ci scanners[dev->scnum].resolutions_list; 1109141cc406Sopenharmony_ci dev->val[OPT_RESOLUTION].w = resolutions_list_300[1]; 1110141cc406Sopenharmony_ci 1111141cc406Sopenharmony_ci /* Duplex */ 1112141cc406Sopenharmony_ci dev->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; 1113141cc406Sopenharmony_ci dev->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; 1114141cc406Sopenharmony_ci dev->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; 1115141cc406Sopenharmony_ci dev->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; 1116141cc406Sopenharmony_ci dev->opt[OPT_DUPLEX].unit = SANE_UNIT_NONE; 1117141cc406Sopenharmony_ci dev->val[OPT_DUPLEX].w = SANE_FALSE; 1118141cc406Sopenharmony_ci if ((scanners[dev->scnum].cap & MAT_CAP_DUPLEX) == 0) 1119141cc406Sopenharmony_ci dev->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; 1120141cc406Sopenharmony_ci 1121141cc406Sopenharmony_ci /* Feeder mode */ 1122141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].name = "feeder-mode"; 1123141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].title = SANE_I18N ("Feeder mode"); 1124141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].desc = SANE_I18N ("Sets the feeding mode"); 1125141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].type = SANE_TYPE_STRING; 1126141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].size = max_string_size (feeder_mode_list); 1127141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1128141cc406Sopenharmony_ci dev->opt[OPT_FEEDER_MODE].constraint.string_list = feeder_mode_list; 1129141cc406Sopenharmony_ci dev->val[OPT_FEEDER_MODE].s = strdup (feeder_mode_list[0]); 1130141cc406Sopenharmony_ci 1131141cc406Sopenharmony_ci /* Geometry group */ 1132141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); 1133141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ 1134141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 1135141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].cap = 0; 1136141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].size = 0; 1137141cc406Sopenharmony_ci dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1138141cc406Sopenharmony_ci 1139141cc406Sopenharmony_ci /* Paper sizes list. */ 1140141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; 1141141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; 1142141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; 1143141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; 1144141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].size = max_string_size (dev->paper_sizes_list); 1145141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1146141cc406Sopenharmony_ci dev->opt[OPT_PAPER_SIZE].constraint.string_list = dev->paper_sizes_list; 1147141cc406Sopenharmony_ci dev->val[OPT_PAPER_SIZE].s = strdup (""); /* will do it later */ 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci /* Upper left X */ 1150141cc406Sopenharmony_ci dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 1151141cc406Sopenharmony_ci dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 1152141cc406Sopenharmony_ci dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 1153141cc406Sopenharmony_ci dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 1154141cc406Sopenharmony_ci dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; 1155141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 1156141cc406Sopenharmony_ci dev->opt[OPT_TL_X].constraint.range = &(scanners[dev->scnum].x_range); 1157141cc406Sopenharmony_ci 1158141cc406Sopenharmony_ci /* Upper left Y */ 1159141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 1160141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 1161141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 1162141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 1163141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 1164141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1165141cc406Sopenharmony_ci dev->opt[OPT_TL_Y].constraint.range = &(scanners[dev->scnum].y_range); 1166141cc406Sopenharmony_ci 1167141cc406Sopenharmony_ci /* Bottom-right x */ 1168141cc406Sopenharmony_ci dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 1169141cc406Sopenharmony_ci dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 1170141cc406Sopenharmony_ci dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 1171141cc406Sopenharmony_ci dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 1172141cc406Sopenharmony_ci dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; 1173141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 1174141cc406Sopenharmony_ci dev->opt[OPT_BR_X].constraint.range = &(scanners[dev->scnum].x_range); 1175141cc406Sopenharmony_ci 1176141cc406Sopenharmony_ci /* Bottom-right y */ 1177141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 1178141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 1179141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 1180141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 1181141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 1182141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 1183141cc406Sopenharmony_ci dev->opt[OPT_BR_Y].constraint.range = &(scanners[dev->scnum].y_range); 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_ci /* Enhancement group */ 1186141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); 1187141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ 1188141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 1189141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; 1190141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; 1191141cc406Sopenharmony_ci dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 1192141cc406Sopenharmony_ci 1193141cc406Sopenharmony_ci /* Brightness */ 1194141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; 1195141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; 1196141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; 1197141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; 1198141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; 1199141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].size = sizeof (SANE_Int); 1200141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; 1201141cc406Sopenharmony_ci dev->opt[OPT_BRIGHTNESS].constraint.range = 1202141cc406Sopenharmony_ci &(scanners[dev->scnum].brightness_range); 1203141cc406Sopenharmony_ci dev->val[OPT_BRIGHTNESS].w = 128; 1204141cc406Sopenharmony_ci 1205141cc406Sopenharmony_ci /* Contrast */ 1206141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; 1207141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; 1208141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; 1209141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].type = SANE_TYPE_INT; 1210141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; 1211141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].size = sizeof (SANE_Int); 1212141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; 1213141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].constraint.range = 1214141cc406Sopenharmony_ci &(scanners[dev->scnum].contrast_range); 1215141cc406Sopenharmony_ci dev->val[OPT_CONTRAST].w = 128; 1216141cc406Sopenharmony_ci if ((scanners[dev->scnum].cap & MAT_CAP_CONTRAST) == 0) 1217141cc406Sopenharmony_ci dev->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci /* Automatic threshold */ 1220141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].name = "automatic-threshold"; 1221141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].title = SANE_I18N ("Automatic threshold"); 1222141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].desc = 1223141cc406Sopenharmony_ci SANE_I18N 1224141cc406Sopenharmony_ci ("Automatically sets brightness, contrast, white level, gamma, noise reduction and image emphasis"); 1225141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].type = SANE_TYPE_STRING; 1226141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].size = 1227141cc406Sopenharmony_ci max_string_size (automatic_threshold_list); 1228141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint_type = 1229141cc406Sopenharmony_ci SANE_CONSTRAINT_STRING_LIST; 1230141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint.string_list = 1231141cc406Sopenharmony_ci automatic_threshold_list; 1232141cc406Sopenharmony_ci dev->val[OPT_AUTOMATIC_THRESHOLD].s = strdup (automatic_threshold_list[0]); 1233141cc406Sopenharmony_ci if ((scanners[dev->scnum].cap & MAT_CAP_AUTOMATIC_THRESHOLD) == 0) 1234141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; 1235141cc406Sopenharmony_ci 1236141cc406Sopenharmony_ci /* Halftone pattern */ 1237141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; 1238141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; 1239141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; 1240141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; 1241141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].size = 1242141cc406Sopenharmony_ci max_string_size (halftone_pattern_list); 1243141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 1244141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].constraint_type = 1245141cc406Sopenharmony_ci SANE_CONSTRAINT_STRING_LIST; 1246141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].constraint.string_list = 1247141cc406Sopenharmony_ci halftone_pattern_list; 1248141cc406Sopenharmony_ci dev->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]); 1249141cc406Sopenharmony_ci 1250141cc406Sopenharmony_ci /* Automatic separation */ 1251141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].name = SANE_NAME_AUTOSEP; 1252141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].title = SANE_TITLE_AUTOSEP; 1253141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].desc = SANE_DESC_AUTOSEP; 1254141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].type = SANE_TYPE_BOOL; 1255141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].unit = SANE_UNIT_NONE; 1256141cc406Sopenharmony_ci dev->val[OPT_AUTOMATIC_SEPARATION].w = SANE_FALSE; 1257141cc406Sopenharmony_ci 1258141cc406Sopenharmony_ci /* White level base */ 1259141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL; 1260141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL; 1261141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL; 1262141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_STRING; 1263141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].size = max_string_size (white_level_list); 1264141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1265141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].constraint.string_list = white_level_list; 1266141cc406Sopenharmony_ci dev->val[OPT_WHITE_LEVEL].s = strdup (white_level_list[0]); 1267141cc406Sopenharmony_ci if ((scanners[dev->scnum].cap & MAT_CAP_WHITE_LEVEL) == 0) 1268141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci /* Noise reduction */ 1271141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].name = "noise-reduction"; 1272141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].title = SANE_I18N ("Noise reduction"); 1273141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].desc = 1274141cc406Sopenharmony_ci SANE_I18N ("Reduce the isolated dot noise"); 1275141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].type = SANE_TYPE_STRING; 1276141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].size = max_string_size (noise_reduction_list); 1277141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1278141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].constraint.string_list = noise_reduction_list; 1279141cc406Sopenharmony_ci dev->val[OPT_NOISE_REDUCTION].s = strdup (noise_reduction_list[0]); 1280141cc406Sopenharmony_ci if ((scanners[dev->scnum].cap & MAT_CAP_NOISE_REDUCTION) == 0) 1281141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci /* Image emphasis */ 1284141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].name = "image-emphasis"; 1285141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].title = SANE_I18N ("Image emphasis"); 1286141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].desc = SANE_I18N ("Sets the image emphasis"); 1287141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].type = SANE_TYPE_STRING; 1288141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].size = 1289141cc406Sopenharmony_ci max_string_size (scanners[dev->scnum].image_emphasis_list); 1290141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1291141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].constraint.string_list = 1292141cc406Sopenharmony_ci scanners[dev->scnum].image_emphasis_list; 1293141cc406Sopenharmony_ci dev->val[OPT_IMAGE_EMPHASIS].s = strdup (SANE_I18N ("Medium")); 1294141cc406Sopenharmony_ci 1295141cc406Sopenharmony_ci /* Gamma */ 1296141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].name = "gamma"; 1297141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].title = SANE_I18N ("Gamma"); 1298141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].desc = SANE_I18N ("Gamma"); 1299141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].type = SANE_TYPE_STRING; 1300141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].size = max_string_size (gamma_list); 1301141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; 1302141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].constraint.string_list = gamma_list; 1303141cc406Sopenharmony_ci dev->val[OPT_GAMMA].s = strdup (gamma_list[0]); 1304141cc406Sopenharmony_ci 1305141cc406Sopenharmony_ci /* Lastly, set the default scan mode. This might change some 1306141cc406Sopenharmony_ci * values previously set here. */ 1307141cc406Sopenharmony_ci sane_control_option (dev, OPT_PAPER_SIZE, SANE_ACTION_SET_VALUE, 1308141cc406Sopenharmony_ci (SANE_String_Const *) dev->paper_sizes_list[0], NULL); 1309141cc406Sopenharmony_ci sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, 1310141cc406Sopenharmony_ci (SANE_String_Const *) scanners[dev->scnum]. 1311141cc406Sopenharmony_ci scan_mode_list[0], NULL); 1312141cc406Sopenharmony_ci} 1313141cc406Sopenharmony_ci 1314141cc406Sopenharmony_ci/* Wait until the scanner is ready. 1315141cc406Sopenharmony_ci * 1316141cc406Sopenharmony_ci * The only reason I know the scanner is not ready is because it is 1317141cc406Sopenharmony_ci * moving the CCD. 1318141cc406Sopenharmony_ci */ 1319141cc406Sopenharmony_cistatic SANE_Status 1320141cc406Sopenharmony_cimatsushita_wait_scanner (Matsushita_Scanner * dev) 1321141cc406Sopenharmony_ci{ 1322141cc406Sopenharmony_ci SANE_Status status; 1323141cc406Sopenharmony_ci int timeout; 1324141cc406Sopenharmony_ci CDB cdb; 1325141cc406Sopenharmony_ci 1326141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_wait_scanner: enter\n"); 1327141cc406Sopenharmony_ci 1328141cc406Sopenharmony_ci MKSCSI_TEST_UNIT_READY (cdb); 1329141cc406Sopenharmony_ci 1330141cc406Sopenharmony_ci /* Set the timeout to 60 seconds. */ 1331141cc406Sopenharmony_ci timeout = 60; 1332141cc406Sopenharmony_ci 1333141cc406Sopenharmony_ci while (timeout > 0) 1334141cc406Sopenharmony_ci { 1335141cc406Sopenharmony_ci 1336141cc406Sopenharmony_ci /* test unit ready */ 1337141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1338141cc406Sopenharmony_ci NULL, 0, NULL, NULL); 1339141cc406Sopenharmony_ci 1340141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 1341141cc406Sopenharmony_ci { 1342141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci sleep (1); 1346141cc406Sopenharmony_ci }; 1347141cc406Sopenharmony_ci 1348141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_wait_scanner: scanner not ready\n"); 1349141cc406Sopenharmony_ci return (SANE_STATUS_IO_ERROR); 1350141cc406Sopenharmony_ci} 1351141cc406Sopenharmony_ci 1352141cc406Sopenharmony_ci/* Reset a window. This is used to re-initialize the scanner. */ 1353141cc406Sopenharmony_cistatic SANE_Status 1354141cc406Sopenharmony_cimatsushita_reset_window (Matsushita_Scanner * dev) 1355141cc406Sopenharmony_ci{ 1356141cc406Sopenharmony_ci CDB cdb; 1357141cc406Sopenharmony_ci SANE_Status status; 1358141cc406Sopenharmony_ci 1359141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_reset_window: enter\n"); 1360141cc406Sopenharmony_ci 1361141cc406Sopenharmony_ci MKSCSI_SET_WINDOW (cdb, 0); 1362141cc406Sopenharmony_ci 1363141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); 1364141cc406Sopenharmony_ci 1365141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_reset_window: exit, status=%d\n", status); 1366141cc406Sopenharmony_ci 1367141cc406Sopenharmony_ci return status; 1368141cc406Sopenharmony_ci} 1369141cc406Sopenharmony_ci 1370141cc406Sopenharmony_ci/* Set a window. */ 1371141cc406Sopenharmony_cistatic SANE_Status 1372141cc406Sopenharmony_cimatsushita_set_window (Matsushita_Scanner * dev, int side) 1373141cc406Sopenharmony_ci{ 1374141cc406Sopenharmony_ci size_t size; 1375141cc406Sopenharmony_ci CDB cdb; 1376141cc406Sopenharmony_ci unsigned char window[72]; 1377141cc406Sopenharmony_ci SANE_Status status; 1378141cc406Sopenharmony_ci int i; 1379141cc406Sopenharmony_ci 1380141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_set_window: enter\n"); 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci size = sizeof (window); 1383141cc406Sopenharmony_ci MKSCSI_SET_WINDOW (cdb, size); 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci memset (window, 0, size); 1386141cc406Sopenharmony_ci 1387141cc406Sopenharmony_ci /* size of the windows descriptor block */ 1388141cc406Sopenharmony_ci window[7] = sizeof (window) - 8; 1389141cc406Sopenharmony_ci 1390141cc406Sopenharmony_ci /* Page side */ 1391141cc406Sopenharmony_ci window[8] = side; 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci /* X and Y resolution */ 1394141cc406Sopenharmony_ci Ito16 (dev->resolution, &window[10]); 1395141cc406Sopenharmony_ci Ito16 (dev->resolution, &window[12]); 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_ci /* Upper Left (X,Y) */ 1398141cc406Sopenharmony_ci Ito32 (dev->x_tl, &window[14]); 1399141cc406Sopenharmony_ci Ito32 (dev->y_tl, &window[18]); 1400141cc406Sopenharmony_ci 1401141cc406Sopenharmony_ci /* Width and length */ 1402141cc406Sopenharmony_ci Ito32 (dev->width, &window[22]); 1403141cc406Sopenharmony_ci Ito32 (dev->length, &window[26]); 1404141cc406Sopenharmony_ci Ito32 (dev->width, &window[56]); /* again, verso? */ 1405141cc406Sopenharmony_ci Ito32 (dev->length, &window[60]); /* again, verso? */ 1406141cc406Sopenharmony_ci 1407141cc406Sopenharmony_ci /* Brightness */ 1408141cc406Sopenharmony_ci window[30] = 255 - dev->val[OPT_BRIGHTNESS].w; 1409141cc406Sopenharmony_ci window[31] = window[30]; /* same as brightness. */ 1410141cc406Sopenharmony_ci 1411141cc406Sopenharmony_ci /* Contrast */ 1412141cc406Sopenharmony_ci window[32] = dev->val[OPT_CONTRAST].w; 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci /* Image Composition */ 1415141cc406Sopenharmony_ci switch (dev->scan_mode) 1416141cc406Sopenharmony_ci { 1417141cc406Sopenharmony_ci case MATSUSHITA_BW: 1418141cc406Sopenharmony_ci window[33] = 0x00; 1419141cc406Sopenharmony_ci break; 1420141cc406Sopenharmony_ci case MATSUSHITA_HALFTONE: 1421141cc406Sopenharmony_ci window[33] = 0x01; 1422141cc406Sopenharmony_ci break; 1423141cc406Sopenharmony_ci case MATSUSHITA_GRAYSCALE: 1424141cc406Sopenharmony_ci window[33] = 0x02; 1425141cc406Sopenharmony_ci break; 1426141cc406Sopenharmony_ci } 1427141cc406Sopenharmony_ci 1428141cc406Sopenharmony_ci /* Depth */ 1429141cc406Sopenharmony_ci window[34] = dev->depth; 1430141cc406Sopenharmony_ci 1431141cc406Sopenharmony_ci /* Halftone pattern. */ 1432141cc406Sopenharmony_ci if (dev->scan_mode == MATSUSHITA_HALFTONE) 1433141cc406Sopenharmony_ci { 1434141cc406Sopenharmony_ci i = get_string_list_index (halftone_pattern_list, 1435141cc406Sopenharmony_ci dev->val[OPT_HALFTONE_PATTERN].s); 1436141cc406Sopenharmony_ci window[36] = halftone_pattern_val[i]; 1437141cc406Sopenharmony_ci } 1438141cc406Sopenharmony_ci 1439141cc406Sopenharmony_ci /* Gamma */ 1440141cc406Sopenharmony_ci if (dev->scan_mode == MATSUSHITA_GRAYSCALE) 1441141cc406Sopenharmony_ci { 1442141cc406Sopenharmony_ci i = get_string_list_index (gamma_list, dev->val[OPT_GAMMA].s); 1443141cc406Sopenharmony_ci window[52] = gamma_val[i]; 1444141cc406Sopenharmony_ci } 1445141cc406Sopenharmony_ci 1446141cc406Sopenharmony_ci /* Feeder mode */ 1447141cc406Sopenharmony_ci i = get_string_list_index (feeder_mode_list, dev->val[OPT_FEEDER_MODE].s); 1448141cc406Sopenharmony_ci window[65] = feeder_mode_val[i]; 1449141cc406Sopenharmony_ci 1450141cc406Sopenharmony_ci /* Image emphasis */ 1451141cc406Sopenharmony_ci i = get_string_list_index (scanners[dev->scnum].image_emphasis_list, 1452141cc406Sopenharmony_ci dev->val[OPT_IMAGE_EMPHASIS].s); 1453141cc406Sopenharmony_ci window[51] = scanners[dev->scnum].image_emphasis_val[i]; 1454141cc406Sopenharmony_ci 1455141cc406Sopenharmony_ci /* White level */ 1456141cc406Sopenharmony_ci i = get_string_list_index (white_level_list, dev->val[OPT_WHITE_LEVEL].s); 1457141cc406Sopenharmony_ci window[68] = white_level_val[i]; 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci if (dev->scan_mode == MATSUSHITA_BW || 1460141cc406Sopenharmony_ci dev->scan_mode == MATSUSHITA_HALFTONE) 1461141cc406Sopenharmony_ci { 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci /* Noise reduction */ 1464141cc406Sopenharmony_ci i = get_string_list_index (noise_reduction_list, 1465141cc406Sopenharmony_ci dev->val[OPT_NOISE_REDUCTION].s); 1466141cc406Sopenharmony_ci window[69] = noise_reduction_val[i]; 1467141cc406Sopenharmony_ci 1468141cc406Sopenharmony_ci /* Automatic separation */ 1469141cc406Sopenharmony_ci if (dev->val[OPT_AUTOMATIC_SEPARATION].w) 1470141cc406Sopenharmony_ci { 1471141cc406Sopenharmony_ci window[67] = 0x80; 1472141cc406Sopenharmony_ci } 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_ci /* Automatic threshold. Must be last because it may override 1475141cc406Sopenharmony_ci * some previous options. */ 1476141cc406Sopenharmony_ci i = get_string_list_index (automatic_threshold_list, 1477141cc406Sopenharmony_ci dev->val[OPT_AUTOMATIC_THRESHOLD].s); 1478141cc406Sopenharmony_ci window[66] = automatic_threshold_val[i]; 1479141cc406Sopenharmony_ci 1480141cc406Sopenharmony_ci if (automatic_threshold_val[i] != 0) 1481141cc406Sopenharmony_ci { 1482141cc406Sopenharmony_ci /* Automatic threshold is enabled. */ 1483141cc406Sopenharmony_ci window[30] = 0; /* brightness. */ 1484141cc406Sopenharmony_ci window[31] = 0; /* same as brightness. */ 1485141cc406Sopenharmony_ci window[32] = 0; /* contrast */ 1486141cc406Sopenharmony_ci window[33] = 0; /* B&W mode */ 1487141cc406Sopenharmony_ci window[36] = 0; /* Halftone pattern. */ 1488141cc406Sopenharmony_ci window[51] = 0; /* Image emphasis */ 1489141cc406Sopenharmony_ci window[67] = 0; /* Automatic separation */ 1490141cc406Sopenharmony_ci window[68] = 0; /* White level */ 1491141cc406Sopenharmony_ci window[69] = 0; /* Noise reduction */ 1492141cc406Sopenharmony_ci } 1493141cc406Sopenharmony_ci } 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci hexdump (DBG_info2, "windows", window, 72); 1496141cc406Sopenharmony_ci 1497141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1498141cc406Sopenharmony_ci window, sizeof (window), NULL, NULL); 1499141cc406Sopenharmony_ci 1500141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_set_window: exit, status=%d\n", status); 1501141cc406Sopenharmony_ci 1502141cc406Sopenharmony_ci return status; 1503141cc406Sopenharmony_ci} 1504141cc406Sopenharmony_ci 1505141cc406Sopenharmony_ci/* Read the image from the scanner and fill the temporary buffer with it. */ 1506141cc406Sopenharmony_cistatic SANE_Status 1507141cc406Sopenharmony_cimatsushita_fill_image (Matsushita_Scanner * dev) 1508141cc406Sopenharmony_ci{ 1509141cc406Sopenharmony_ci SANE_Status status; 1510141cc406Sopenharmony_ci size_t size; 1511141cc406Sopenharmony_ci CDB cdb; 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci DBG (DBG_proc, "matsushita_fill_image: enter\n"); 1514141cc406Sopenharmony_ci 1515141cc406Sopenharmony_ci assert (dev->image_begin == dev->image_end); 1516141cc406Sopenharmony_ci assert (dev->real_bytes_left > 0); 1517141cc406Sopenharmony_ci 1518141cc406Sopenharmony_ci dev->image_begin = 0; 1519141cc406Sopenharmony_ci dev->image_end = 0; 1520141cc406Sopenharmony_ci 1521141cc406Sopenharmony_ci while (dev->real_bytes_left) 1522141cc406Sopenharmony_ci { 1523141cc406Sopenharmony_ci 1524141cc406Sopenharmony_ci /* 1525141cc406Sopenharmony_ci * Try to read the maximum number of bytes. 1526141cc406Sopenharmony_ci * 1527141cc406Sopenharmony_ci * The windows driver reads no more than 0x8000 byte. 1528141cc406Sopenharmony_ci * 1529141cc406Sopenharmony_ci * This backend operates differently than the windows 1530141cc406Sopenharmony_ci * driver. The windows TWAIN driver always read 2 more bytes 1531141cc406Sopenharmony_ci * at the end, so it gets a CHECK CONDITION with a short read 1532141cc406Sopenharmony_ci * sense. Since the linux scsi layer seem to be buggy 1533141cc406Sopenharmony_ci * regarding the resid, always read exactly the number of 1534141cc406Sopenharmony_ci * remaining bytes. 1535141cc406Sopenharmony_ci */ 1536141cc406Sopenharmony_ci 1537141cc406Sopenharmony_ci size = dev->real_bytes_left; 1538141cc406Sopenharmony_ci if (size > dev->image_size - dev->image_end) 1539141cc406Sopenharmony_ci size = dev->image_size - dev->image_end; 1540141cc406Sopenharmony_ci if (size > 0x8000) 1541141cc406Sopenharmony_ci size = 0x8000; 1542141cc406Sopenharmony_ci 1543141cc406Sopenharmony_ci if (size == 0) 1544141cc406Sopenharmony_ci { 1545141cc406Sopenharmony_ci /* Probably reached the end of the buffer. 1546141cc406Sopenharmony_ci * Check, just in case. */ 1547141cc406Sopenharmony_ci assert (dev->image_end != 0); 1548141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); 1549141cc406Sopenharmony_ci } 1550141cc406Sopenharmony_ci 1551141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: to read = %ld bytes (bpl=%d)\n", 1552141cc406Sopenharmony_ci (long) size, dev->params.bytes_per_line); 1553141cc406Sopenharmony_ci 1554141cc406Sopenharmony_ci MKSCSI_READ_10 (cdb, 0, 0, size); 1555141cc406Sopenharmony_ci cdb.data[4] = dev->page_num; /* May be cdb.data[3] too? */ 1556141cc406Sopenharmony_ci cdb.data[5] = dev->page_side; 1557141cc406Sopenharmony_ci 1558141cc406Sopenharmony_ci hexdump (DBG_info2, "sane_read: READ_10 CDB", cdb.data, 10); 1559141cc406Sopenharmony_ci 1560141cc406Sopenharmony_ci status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, 1561141cc406Sopenharmony_ci NULL, 0, dev->buffer, &size); 1562141cc406Sopenharmony_ci 1563141cc406Sopenharmony_ci if (status == SANE_STATUS_EOF) 1564141cc406Sopenharmony_ci { 1565141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: exit, end of page scan\n"); 1566141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 1567141cc406Sopenharmony_ci } 1568141cc406Sopenharmony_ci 1569141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1570141cc406Sopenharmony_ci { 1571141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: cannot read from the scanner\n"); 1572141cc406Sopenharmony_ci return status; 1573141cc406Sopenharmony_ci } 1574141cc406Sopenharmony_ci 1575141cc406Sopenharmony_ci dev->real_bytes_left -= size; 1576141cc406Sopenharmony_ci 1577141cc406Sopenharmony_ci switch (dev->depth) 1578141cc406Sopenharmony_ci { 1579141cc406Sopenharmony_ci case 1: 1580141cc406Sopenharmony_ci { 1581141cc406Sopenharmony_ci /* For Black & White, the bits in every bytes are mirrored. 1582141cc406Sopenharmony_ci * for instance 11010001 is coded as 10001011 */ 1583141cc406Sopenharmony_ci 1584141cc406Sopenharmony_ci unsigned char *src = dev->buffer; 1585141cc406Sopenharmony_ci unsigned char *dest = dev->image + dev->image_end; 1586141cc406Sopenharmony_ci unsigned char s; 1587141cc406Sopenharmony_ci unsigned char d; 1588141cc406Sopenharmony_ci 1589141cc406Sopenharmony_ci size_t i; 1590141cc406Sopenharmony_ci 1591141cc406Sopenharmony_ci for (i = 0; i < size; i++) 1592141cc406Sopenharmony_ci { 1593141cc406Sopenharmony_ci s = *src; 1594141cc406Sopenharmony_ci d = 0; 1595141cc406Sopenharmony_ci if (s & 0x01) 1596141cc406Sopenharmony_ci d |= 0x80; 1597141cc406Sopenharmony_ci if (s & 0x02) 1598141cc406Sopenharmony_ci d |= 0x40; 1599141cc406Sopenharmony_ci if (s & 0x04) 1600141cc406Sopenharmony_ci d |= 0x20; 1601141cc406Sopenharmony_ci if (s & 0x08) 1602141cc406Sopenharmony_ci d |= 0x10; 1603141cc406Sopenharmony_ci if (s & 0x10) 1604141cc406Sopenharmony_ci d |= 0x08; 1605141cc406Sopenharmony_ci if (s & 0x20) 1606141cc406Sopenharmony_ci d |= 0x04; 1607141cc406Sopenharmony_ci if (s & 0x40) 1608141cc406Sopenharmony_ci d |= 0x02; 1609141cc406Sopenharmony_ci if (s & 0x80) 1610141cc406Sopenharmony_ci d |= 0x01; 1611141cc406Sopenharmony_ci *dest = d; 1612141cc406Sopenharmony_ci src++; 1613141cc406Sopenharmony_ci dest++; 1614141cc406Sopenharmony_ci } 1615141cc406Sopenharmony_ci } 1616141cc406Sopenharmony_ci break; 1617141cc406Sopenharmony_ci 1618141cc406Sopenharmony_ci case 4: 1619141cc406Sopenharmony_ci { 1620141cc406Sopenharmony_ci /* Adjust from a depth of 4 bits ([0..15]) to 1621141cc406Sopenharmony_ci * a depth of 8 bits ([0..255]) */ 1622141cc406Sopenharmony_ci 1623141cc406Sopenharmony_ci unsigned char *src = dev->buffer; 1624141cc406Sopenharmony_ci unsigned char *dest = dev->image + dev->image_end; 1625141cc406Sopenharmony_ci size_t i; 1626141cc406Sopenharmony_ci 1627141cc406Sopenharmony_ci /* n bytes from image --> 2*n bytes in buf. */ 1628141cc406Sopenharmony_ci 1629141cc406Sopenharmony_ci for (i = 0; i < size; i++) 1630141cc406Sopenharmony_ci { 1631141cc406Sopenharmony_ci *dest = ((*src & 0x0f) >> 0) * 17; 1632141cc406Sopenharmony_ci dest++; 1633141cc406Sopenharmony_ci *dest = ((*src & 0xf0) >> 4) * 17; 1634141cc406Sopenharmony_ci dest++; 1635141cc406Sopenharmony_ci src++; 1636141cc406Sopenharmony_ci } 1637141cc406Sopenharmony_ci 1638141cc406Sopenharmony_ci size *= 2; 1639141cc406Sopenharmony_ci } 1640141cc406Sopenharmony_ci break; 1641141cc406Sopenharmony_ci 1642141cc406Sopenharmony_ci default: 1643141cc406Sopenharmony_ci memcpy (dev->image + dev->image_end, dev->buffer, size); 1644141cc406Sopenharmony_ci break; 1645141cc406Sopenharmony_ci } 1646141cc406Sopenharmony_ci 1647141cc406Sopenharmony_ci dev->image_end += size; 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci } 1650141cc406Sopenharmony_ci 1651141cc406Sopenharmony_ci return (SANE_STATUS_GOOD); /* unreachable */ 1652141cc406Sopenharmony_ci} 1653141cc406Sopenharmony_ci 1654141cc406Sopenharmony_ci/* Copy from the raw buffer to the buffer given by the backend. 1655141cc406Sopenharmony_ci * 1656141cc406Sopenharmony_ci * len in input is the maximum length available in buf, and, in 1657141cc406Sopenharmony_ci * output, is the length written into buf. 1658141cc406Sopenharmony_ci */ 1659141cc406Sopenharmony_cistatic void 1660141cc406Sopenharmony_cimatsushita_copy_raw_to_frontend (Matsushita_Scanner * dev, SANE_Byte * buf, 1661141cc406Sopenharmony_ci size_t * len) 1662141cc406Sopenharmony_ci{ 1663141cc406Sopenharmony_ci size_t size; 1664141cc406Sopenharmony_ci 1665141cc406Sopenharmony_ci size = dev->image_end - dev->image_begin; 1666141cc406Sopenharmony_ci if (size > *len) 1667141cc406Sopenharmony_ci { 1668141cc406Sopenharmony_ci size = *len; 1669141cc406Sopenharmony_ci } 1670141cc406Sopenharmony_ci *len = size; 1671141cc406Sopenharmony_ci 1672141cc406Sopenharmony_ci memcpy (buf, dev->image + dev->image_begin, size); 1673141cc406Sopenharmony_ci dev->image_begin += size; 1674141cc406Sopenharmony_ci} 1675141cc406Sopenharmony_ci 1676141cc406Sopenharmony_ci/* Stop a scan. */ 1677141cc406Sopenharmony_cistatic SANE_Status 1678141cc406Sopenharmony_cido_cancel (Matsushita_Scanner * dev) 1679141cc406Sopenharmony_ci{ 1680141cc406Sopenharmony_ci DBG (DBG_sane_proc, "do_cancel enter\n"); 1681141cc406Sopenharmony_ci 1682141cc406Sopenharmony_ci if (dev->scanning == SANE_TRUE) 1683141cc406Sopenharmony_ci { 1684141cc406Sopenharmony_ci 1685141cc406Sopenharmony_ci /* Reset the scanner */ 1686141cc406Sopenharmony_ci matsushita_reset_window (dev); 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci matsushita_close (dev); 1689141cc406Sopenharmony_ci } 1690141cc406Sopenharmony_ci 1691141cc406Sopenharmony_ci dev->scanning = SANE_FALSE; 1692141cc406Sopenharmony_ci 1693141cc406Sopenharmony_ci DBG (DBG_sane_proc, "do_cancel exit\n"); 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1696141cc406Sopenharmony_ci} 1697141cc406Sopenharmony_ci 1698141cc406Sopenharmony_ci/*--------------------------------------------------------------------------*/ 1699141cc406Sopenharmony_ci 1700141cc406Sopenharmony_ci/* Entry points */ 1701141cc406Sopenharmony_ci 1702141cc406Sopenharmony_ciSANE_Status 1703141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) 1704141cc406Sopenharmony_ci{ 1705141cc406Sopenharmony_ci FILE *fp; 1706141cc406Sopenharmony_ci char dev_name[PATH_MAX]; 1707141cc406Sopenharmony_ci size_t len; 1708141cc406Sopenharmony_ci 1709141cc406Sopenharmony_ci DBG_INIT (); 1710141cc406Sopenharmony_ci 1711141cc406Sopenharmony_ci DBG (DBG_sane_init, "sane_init\n"); 1712141cc406Sopenharmony_ci 1713141cc406Sopenharmony_ci DBG (DBG_error, "This is sane-matsushita version %d.%d-%d\n", SANE_CURRENT_MAJOR, 1714141cc406Sopenharmony_ci SANE_CURRENT_MINOR, BUILD); 1715141cc406Sopenharmony_ci DBG (DBG_error, "(C) 2002 by Frank Zago\n"); 1716141cc406Sopenharmony_ci 1717141cc406Sopenharmony_ci if (version_code) 1718141cc406Sopenharmony_ci { 1719141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 1720141cc406Sopenharmony_ci } 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ci fp = sanei_config_open (MATSUSHITA_CONFIG_FILE); 1723141cc406Sopenharmony_ci if (!fp) 1724141cc406Sopenharmony_ci { 1725141cc406Sopenharmony_ci /* default to /dev/scanner instead of insisting on config file */ 1726141cc406Sopenharmony_ci attach_scanner ("/dev/scanner", 0); 1727141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1728141cc406Sopenharmony_ci } 1729141cc406Sopenharmony_ci 1730141cc406Sopenharmony_ci while (sanei_config_read (dev_name, sizeof (dev_name), fp)) 1731141cc406Sopenharmony_ci { 1732141cc406Sopenharmony_ci if (dev_name[0] == '#') /* ignore line comments */ 1733141cc406Sopenharmony_ci continue; 1734141cc406Sopenharmony_ci len = strlen (dev_name); 1735141cc406Sopenharmony_ci 1736141cc406Sopenharmony_ci if (!len) 1737141cc406Sopenharmony_ci continue; /* ignore empty lines */ 1738141cc406Sopenharmony_ci 1739141cc406Sopenharmony_ci sanei_config_attach_matching_devices (dev_name, attach_one); 1740141cc406Sopenharmony_ci } 1741141cc406Sopenharmony_ci 1742141cc406Sopenharmony_ci fclose (fp); 1743141cc406Sopenharmony_ci 1744141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: leave\n"); 1745141cc406Sopenharmony_ci 1746141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1747141cc406Sopenharmony_ci} 1748141cc406Sopenharmony_ci 1749141cc406Sopenharmony_ciSANE_Status 1750141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) 1751141cc406Sopenharmony_ci{ 1752141cc406Sopenharmony_ci Matsushita_Scanner *dev; 1753141cc406Sopenharmony_ci int i; 1754141cc406Sopenharmony_ci 1755141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: enter\n"); 1756141cc406Sopenharmony_ci 1757141cc406Sopenharmony_ci if (devlist) 1758141cc406Sopenharmony_ci free (devlist); 1759141cc406Sopenharmony_ci 1760141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 1761141cc406Sopenharmony_ci if (!devlist) 1762141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1763141cc406Sopenharmony_ci 1764141cc406Sopenharmony_ci i = 0; 1765141cc406Sopenharmony_ci for (dev = first_dev; i < num_devices; dev = dev->next) 1766141cc406Sopenharmony_ci devlist[i++] = &dev->sane; 1767141cc406Sopenharmony_ci devlist[i++] = 0; 1768141cc406Sopenharmony_ci 1769141cc406Sopenharmony_ci *device_list = devlist; 1770141cc406Sopenharmony_ci 1771141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: exit\n"); 1772141cc406Sopenharmony_ci 1773141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1774141cc406Sopenharmony_ci} 1775141cc406Sopenharmony_ci 1776141cc406Sopenharmony_ciSANE_Status 1777141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 1778141cc406Sopenharmony_ci{ 1779141cc406Sopenharmony_ci Matsushita_Scanner *dev; 1780141cc406Sopenharmony_ci SANE_Status status; 1781141cc406Sopenharmony_ci 1782141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: enter\n"); 1783141cc406Sopenharmony_ci 1784141cc406Sopenharmony_ci /* search for devicename */ 1785141cc406Sopenharmony_ci if (devicename[0]) 1786141cc406Sopenharmony_ci { 1787141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: devicename=%s\n", devicename); 1788141cc406Sopenharmony_ci 1789141cc406Sopenharmony_ci for (dev = first_dev; dev; dev = dev->next) 1790141cc406Sopenharmony_ci { 1791141cc406Sopenharmony_ci if (strcmp (dev->sane.name, devicename) == 0) 1792141cc406Sopenharmony_ci { 1793141cc406Sopenharmony_ci break; 1794141cc406Sopenharmony_ci } 1795141cc406Sopenharmony_ci } 1796141cc406Sopenharmony_ci 1797141cc406Sopenharmony_ci if (!dev) 1798141cc406Sopenharmony_ci { 1799141cc406Sopenharmony_ci status = attach_scanner (devicename, &dev); 1800141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1801141cc406Sopenharmony_ci { 1802141cc406Sopenharmony_ci return status; 1803141cc406Sopenharmony_ci } 1804141cc406Sopenharmony_ci } 1805141cc406Sopenharmony_ci } 1806141cc406Sopenharmony_ci else 1807141cc406Sopenharmony_ci { 1808141cc406Sopenharmony_ci DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); 1809141cc406Sopenharmony_ci dev = first_dev; /* empty devicename -> use first device */ 1810141cc406Sopenharmony_ci } 1811141cc406Sopenharmony_ci 1812141cc406Sopenharmony_ci if (!dev) 1813141cc406Sopenharmony_ci { 1814141cc406Sopenharmony_ci DBG (DBG_error, "No scanner found\n"); 1815141cc406Sopenharmony_ci 1816141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1817141cc406Sopenharmony_ci } 1818141cc406Sopenharmony_ci 1819141cc406Sopenharmony_ci /* Build a list a paper size that fit into this scanner. */ 1820141cc406Sopenharmony_ci matsushita_build_paper_sizes (dev); 1821141cc406Sopenharmony_ci 1822141cc406Sopenharmony_ci matsushita_init_options (dev); 1823141cc406Sopenharmony_ci 1824141cc406Sopenharmony_ci *handle = dev; 1825141cc406Sopenharmony_ci 1826141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit\n"); 1827141cc406Sopenharmony_ci 1828141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1829141cc406Sopenharmony_ci} 1830141cc406Sopenharmony_ci 1831141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 1832141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 1833141cc406Sopenharmony_ci{ 1834141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); 1837141cc406Sopenharmony_ci 1838141cc406Sopenharmony_ci if ((unsigned) option >= OPT_NUM_OPTIONS) 1839141cc406Sopenharmony_ci { 1840141cc406Sopenharmony_ci return NULL; 1841141cc406Sopenharmony_ci } 1842141cc406Sopenharmony_ci 1843141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); 1844141cc406Sopenharmony_ci 1845141cc406Sopenharmony_ci return dev->opt + option; 1846141cc406Sopenharmony_ci} 1847141cc406Sopenharmony_ci 1848141cc406Sopenharmony_ciSANE_Status 1849141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 1850141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 1851141cc406Sopenharmony_ci{ 1852141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 1853141cc406Sopenharmony_ci SANE_Status status; 1854141cc406Sopenharmony_ci SANE_Word cap; 1855141cc406Sopenharmony_ci SANE_String_Const name; 1856141cc406Sopenharmony_ci int i; 1857141cc406Sopenharmony_ci SANE_Word value; 1858141cc406Sopenharmony_ci int rc; 1859141cc406Sopenharmony_ci 1860141cc406Sopenharmony_ci DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", 1861141cc406Sopenharmony_ci option, action); 1862141cc406Sopenharmony_ci 1863141cc406Sopenharmony_ci if (info) 1864141cc406Sopenharmony_ci { 1865141cc406Sopenharmony_ci *info = 0; 1866141cc406Sopenharmony_ci } 1867141cc406Sopenharmony_ci 1868141cc406Sopenharmony_ci if (dev->scanning) 1869141cc406Sopenharmony_ci { 1870141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1871141cc406Sopenharmony_ci } 1872141cc406Sopenharmony_ci 1873141cc406Sopenharmony_ci if (option < 0 || option >= OPT_NUM_OPTIONS) 1874141cc406Sopenharmony_ci { 1875141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1876141cc406Sopenharmony_ci } 1877141cc406Sopenharmony_ci 1878141cc406Sopenharmony_ci cap = dev->opt[option].cap; 1879141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 1880141cc406Sopenharmony_ci { 1881141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1882141cc406Sopenharmony_ci } 1883141cc406Sopenharmony_ci 1884141cc406Sopenharmony_ci name = dev->opt[option].name; 1885141cc406Sopenharmony_ci if (!name) 1886141cc406Sopenharmony_ci { 1887141cc406Sopenharmony_ci name = "(no name)"; 1888141cc406Sopenharmony_ci } 1889141cc406Sopenharmony_ci if (action == SANE_ACTION_GET_VALUE) 1890141cc406Sopenharmony_ci { 1891141cc406Sopenharmony_ci 1892141cc406Sopenharmony_ci switch (option) 1893141cc406Sopenharmony_ci { 1894141cc406Sopenharmony_ci /* word options */ 1895141cc406Sopenharmony_ci case OPT_NUM_OPTS: 1896141cc406Sopenharmony_ci case OPT_RESOLUTION: 1897141cc406Sopenharmony_ci case OPT_TL_Y: 1898141cc406Sopenharmony_ci case OPT_BR_Y: 1899141cc406Sopenharmony_ci case OPT_TL_X: 1900141cc406Sopenharmony_ci case OPT_BR_X: 1901141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1902141cc406Sopenharmony_ci case OPT_CONTRAST: 1903141cc406Sopenharmony_ci case OPT_DUPLEX: 1904141cc406Sopenharmony_ci case OPT_AUTOMATIC_SEPARATION: 1905141cc406Sopenharmony_ci *(SANE_Word *) val = dev->val[option].w; 1906141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1907141cc406Sopenharmony_ci 1908141cc406Sopenharmony_ci /* string options */ 1909141cc406Sopenharmony_ci case OPT_MODE: 1910141cc406Sopenharmony_ci case OPT_FEEDER_MODE: 1911141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 1912141cc406Sopenharmony_ci case OPT_PAPER_SIZE: 1913141cc406Sopenharmony_ci case OPT_AUTOMATIC_THRESHOLD: 1914141cc406Sopenharmony_ci case OPT_WHITE_LEVEL: 1915141cc406Sopenharmony_ci case OPT_NOISE_REDUCTION: 1916141cc406Sopenharmony_ci case OPT_IMAGE_EMPHASIS: 1917141cc406Sopenharmony_ci case OPT_GAMMA: 1918141cc406Sopenharmony_ci strcpy (val, dev->val[option].s); 1919141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1920141cc406Sopenharmony_ci 1921141cc406Sopenharmony_ci default: 1922141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1923141cc406Sopenharmony_ci } 1924141cc406Sopenharmony_ci } 1925141cc406Sopenharmony_ci else if (action == SANE_ACTION_SET_VALUE) 1926141cc406Sopenharmony_ci { 1927141cc406Sopenharmony_ci 1928141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 1929141cc406Sopenharmony_ci { 1930141cc406Sopenharmony_ci DBG (DBG_error, "could not set option, not settable\n"); 1931141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1932141cc406Sopenharmony_ci } 1933141cc406Sopenharmony_ci 1934141cc406Sopenharmony_ci status = sanei_constrain_value (dev->opt + option, val, info); 1935141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1936141cc406Sopenharmony_ci { 1937141cc406Sopenharmony_ci DBG (DBG_error, "could not set option, invalid value\n"); 1938141cc406Sopenharmony_ci return status; 1939141cc406Sopenharmony_ci } 1940141cc406Sopenharmony_ci 1941141cc406Sopenharmony_ci switch (option) 1942141cc406Sopenharmony_ci { 1943141cc406Sopenharmony_ci 1944141cc406Sopenharmony_ci /* Side-effect options */ 1945141cc406Sopenharmony_ci case OPT_TL_Y: 1946141cc406Sopenharmony_ci case OPT_BR_Y: 1947141cc406Sopenharmony_ci case OPT_RESOLUTION: 1948141cc406Sopenharmony_ci if (info) 1949141cc406Sopenharmony_ci { 1950141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1951141cc406Sopenharmony_ci } 1952141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1953141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1954141cc406Sopenharmony_ci 1955141cc406Sopenharmony_ci /* The length of X must be rounded (up). */ 1956141cc406Sopenharmony_ci case OPT_TL_X: 1957141cc406Sopenharmony_ci case OPT_BR_X: 1958141cc406Sopenharmony_ci 1959141cc406Sopenharmony_ci value = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); 1960141cc406Sopenharmony_ci 1961141cc406Sopenharmony_ci i = get_int_list_index (scanners[dev->scnum].resolutions_list, 1962141cc406Sopenharmony_ci dev->val[OPT_RESOLUTION].w); 1963141cc406Sopenharmony_ci 1964141cc406Sopenharmony_ci if (value & (scanners[dev->scnum].resolutions_round[i] - 1)) 1965141cc406Sopenharmony_ci { 1966141cc406Sopenharmony_ci value = 1967141cc406Sopenharmony_ci (value | (scanners[dev->scnum].resolutions_round[i] - 1)) + 1; 1968141cc406Sopenharmony_ci if (info) 1969141cc406Sopenharmony_ci { 1970141cc406Sopenharmony_ci *info |= SANE_INFO_INEXACT; 1971141cc406Sopenharmony_ci } 1972141cc406Sopenharmony_ci } 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FIX (iluToMm (value)); 1975141cc406Sopenharmony_ci 1976141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1977141cc406Sopenharmony_ci 1978141cc406Sopenharmony_ci if (info) 1979141cc406Sopenharmony_ci { 1980141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 1981141cc406Sopenharmony_ci } 1982141cc406Sopenharmony_ci 1983141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1984141cc406Sopenharmony_ci 1985141cc406Sopenharmony_ci /* Side-effect free options */ 1986141cc406Sopenharmony_ci case OPT_CONTRAST: 1987141cc406Sopenharmony_ci case OPT_BRIGHTNESS: 1988141cc406Sopenharmony_ci case OPT_DUPLEX: 1989141cc406Sopenharmony_ci case OPT_AUTOMATIC_SEPARATION: 1990141cc406Sopenharmony_ci dev->val[option].w = *(SANE_Word *) val; 1991141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1992141cc406Sopenharmony_ci 1993141cc406Sopenharmony_ci /* String mode */ 1994141cc406Sopenharmony_ci case OPT_WHITE_LEVEL: 1995141cc406Sopenharmony_ci case OPT_NOISE_REDUCTION: 1996141cc406Sopenharmony_ci case OPT_IMAGE_EMPHASIS: 1997141cc406Sopenharmony_ci case OPT_GAMMA: 1998141cc406Sopenharmony_ci case OPT_FEEDER_MODE: 1999141cc406Sopenharmony_ci free (dev->val[option].s); 2000141cc406Sopenharmony_ci dev->val[option].s = (SANE_String) strdup (val); 2001141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2002141cc406Sopenharmony_ci 2003141cc406Sopenharmony_ci case OPT_MODE: 2004141cc406Sopenharmony_ci if (strcmp (dev->val[option].s, val) == 0) 2005141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2006141cc406Sopenharmony_ci 2007141cc406Sopenharmony_ci free (dev->val[OPT_MODE].s); 2008141cc406Sopenharmony_ci dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ci /* Set default options for the scan modes. */ 2011141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 2012141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; 2013141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; 2014141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; 2015141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; 2016141cc406Sopenharmony_ci 2017141cc406Sopenharmony_ci if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) 2018141cc406Sopenharmony_ci { 2019141cc406Sopenharmony_ci dev->depth = 1; 2020141cc406Sopenharmony_ci 2021141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; 2022141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 2023141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; 2024141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci i = get_string_list_index (halftone_pattern_list, 2027141cc406Sopenharmony_ci dev->val[OPT_HALFTONE_PATTERN].s); 2028141cc406Sopenharmony_ci if (halftone_pattern_val[i] == -1) 2029141cc406Sopenharmony_ci { 2030141cc406Sopenharmony_ci dev->scan_mode = MATSUSHITA_BW; 2031141cc406Sopenharmony_ci } 2032141cc406Sopenharmony_ci else 2033141cc406Sopenharmony_ci { 2034141cc406Sopenharmony_ci dev->scan_mode = MATSUSHITA_HALFTONE; 2035141cc406Sopenharmony_ci } 2036141cc406Sopenharmony_ci } 2037141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, GRAY4_STR) == 0) 2038141cc406Sopenharmony_ci { 2039141cc406Sopenharmony_ci dev->scan_mode = MATSUSHITA_GRAYSCALE; 2040141cc406Sopenharmony_ci dev->depth = 4; 2041141cc406Sopenharmony_ci 2042141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; 2043141cc406Sopenharmony_ci } 2044141cc406Sopenharmony_ci else if (strcmp (dev->val[OPT_MODE].s, GRAY8_STR) == 0) 2045141cc406Sopenharmony_ci { 2046141cc406Sopenharmony_ci dev->scan_mode = MATSUSHITA_GRAYSCALE; 2047141cc406Sopenharmony_ci dev->depth = 8; 2048141cc406Sopenharmony_ci 2049141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; 2050141cc406Sopenharmony_ci } 2051141cc406Sopenharmony_ci else 2052141cc406Sopenharmony_ci { 2053141cc406Sopenharmony_ci assert (0 == 1); 2054141cc406Sopenharmony_ci } 2055141cc406Sopenharmony_ci 2056141cc406Sopenharmony_ci /* Some options might not be supported by the scanner. */ 2057141cc406Sopenharmony_ci if ((scanners[dev->scnum].cap & MAT_CAP_GAMMA) == 0) 2058141cc406Sopenharmony_ci dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; 2059141cc406Sopenharmony_ci 2060141cc406Sopenharmony_ci if (info) 2061141cc406Sopenharmony_ci { 2062141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2063141cc406Sopenharmony_ci } 2064141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2065141cc406Sopenharmony_ci 2066141cc406Sopenharmony_ci case OPT_HALFTONE_PATTERN: 2067141cc406Sopenharmony_ci free (dev->val[option].s); 2068141cc406Sopenharmony_ci dev->val[option].s = (SANE_String) strdup (val); 2069141cc406Sopenharmony_ci i = get_string_list_index (halftone_pattern_list, 2070141cc406Sopenharmony_ci dev->val[OPT_HALFTONE_PATTERN].s); 2071141cc406Sopenharmony_ci if (halftone_pattern_val[i] == -1) 2072141cc406Sopenharmony_ci { 2073141cc406Sopenharmony_ci dev->scan_mode = MATSUSHITA_BW; 2074141cc406Sopenharmony_ci } 2075141cc406Sopenharmony_ci else 2076141cc406Sopenharmony_ci { 2077141cc406Sopenharmony_ci dev->scan_mode = MATSUSHITA_HALFTONE; 2078141cc406Sopenharmony_ci } 2079141cc406Sopenharmony_ci 2080141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2081141cc406Sopenharmony_ci 2082141cc406Sopenharmony_ci case OPT_PAPER_SIZE: 2083141cc406Sopenharmony_ci if (strcmp (dev->val[option].s, val) == 0) 2084141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2085141cc406Sopenharmony_ci 2086141cc406Sopenharmony_ci free (dev->val[OPT_PAPER_SIZE].s); 2087141cc406Sopenharmony_ci dev->val[OPT_PAPER_SIZE].s = (SANE_Char *) strdup (val); 2088141cc406Sopenharmony_ci 2089141cc406Sopenharmony_ci i = get_string_list_index (dev->paper_sizes_list, 2090141cc406Sopenharmony_ci dev->val[OPT_PAPER_SIZE].s); 2091141cc406Sopenharmony_ci i = dev->paper_sizes_val[i]; 2092141cc406Sopenharmony_ci 2093141cc406Sopenharmony_ci /* Set the 4 corners values. */ 2094141cc406Sopenharmony_ci value = 0; 2095141cc406Sopenharmony_ci rc = sane_control_option (handle, OPT_TL_X, SANE_ACTION_SET_VALUE, 2096141cc406Sopenharmony_ci &value, info); 2097141cc406Sopenharmony_ci assert (rc == SANE_STATUS_GOOD); 2098141cc406Sopenharmony_ci 2099141cc406Sopenharmony_ci value = 0; 2100141cc406Sopenharmony_ci rc = sane_control_option (handle, OPT_TL_Y, SANE_ACTION_SET_VALUE, 2101141cc406Sopenharmony_ci &value, info); 2102141cc406Sopenharmony_ci assert (rc == SANE_STATUS_GOOD); 2103141cc406Sopenharmony_ci 2104141cc406Sopenharmony_ci value = SANE_FIX (paper_sizes[i].width); 2105141cc406Sopenharmony_ci rc = sane_control_option (handle, OPT_BR_X, SANE_ACTION_SET_VALUE, 2106141cc406Sopenharmony_ci &value, info); 2107141cc406Sopenharmony_ci assert (rc == SANE_STATUS_GOOD); 2108141cc406Sopenharmony_ci 2109141cc406Sopenharmony_ci value = SANE_FIX (paper_sizes[i].length); 2110141cc406Sopenharmony_ci rc = sane_control_option (handle, OPT_BR_Y, SANE_ACTION_SET_VALUE, 2111141cc406Sopenharmony_ci &value, info); 2112141cc406Sopenharmony_ci assert (rc == SANE_STATUS_GOOD); 2113141cc406Sopenharmony_ci 2114141cc406Sopenharmony_ci if (info) 2115141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 2116141cc406Sopenharmony_ci 2117141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2118141cc406Sopenharmony_ci 2119141cc406Sopenharmony_ci case OPT_AUTOMATIC_THRESHOLD: 2120141cc406Sopenharmony_ci if (strcmp (dev->val[option].s, val) == 0) 2121141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2122141cc406Sopenharmony_ci 2123141cc406Sopenharmony_ci free (dev->val[option].s); 2124141cc406Sopenharmony_ci dev->val[option].s = (SANE_Char *) strdup (val); 2125141cc406Sopenharmony_ci 2126141cc406Sopenharmony_ci /* If the threshold is not set to none, some option must 2127141cc406Sopenharmony_ci * disappear. */ 2128141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; 2129141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; 2130141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; 2131141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; 2132141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; 2133141cc406Sopenharmony_ci 2134141cc406Sopenharmony_ci if (strcmp (dev->val[option].s, automatic_threshold_list[0]) == 0) 2135141cc406Sopenharmony_ci { 2136141cc406Sopenharmony_ci dev->opt[OPT_WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE; 2137141cc406Sopenharmony_ci dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; 2138141cc406Sopenharmony_ci dev->opt[OPT_IMAGE_EMPHASIS].cap &= ~SANE_CAP_INACTIVE; 2139141cc406Sopenharmony_ci dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; 2140141cc406Sopenharmony_ci if (dev->scan_mode == MATSUSHITA_BW 2141141cc406Sopenharmony_ci || dev->scan_mode == MATSUSHITA_HALFTONE) 2142141cc406Sopenharmony_ci { 2143141cc406Sopenharmony_ci dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; 2144141cc406Sopenharmony_ci } 2145141cc406Sopenharmony_ci } 2146141cc406Sopenharmony_ci 2147141cc406Sopenharmony_ci if (info) 2148141cc406Sopenharmony_ci { 2149141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; 2150141cc406Sopenharmony_ci } 2151141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2152141cc406Sopenharmony_ci 2153141cc406Sopenharmony_ci default: 2154141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2155141cc406Sopenharmony_ci } 2156141cc406Sopenharmony_ci } 2157141cc406Sopenharmony_ci 2158141cc406Sopenharmony_ci DBG (DBG_proc, "sane_control_option: exit, bad\n"); 2159141cc406Sopenharmony_ci 2160141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2161141cc406Sopenharmony_ci} 2162141cc406Sopenharmony_ci 2163141cc406Sopenharmony_ciSANE_Status 2164141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 2165141cc406Sopenharmony_ci{ 2166141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 2167141cc406Sopenharmony_ci 2168141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: enter\n"); 2169141cc406Sopenharmony_ci 2170141cc406Sopenharmony_ci if (!(dev->scanning)) 2171141cc406Sopenharmony_ci { 2172141cc406Sopenharmony_ci 2173141cc406Sopenharmony_ci /* Setup the parameters for the scan. These values will be re-used 2174141cc406Sopenharmony_ci * in the SET WINDOWS command. */ 2175141cc406Sopenharmony_ci dev->resolution = dev->val[OPT_RESOLUTION].w; 2176141cc406Sopenharmony_ci 2177141cc406Sopenharmony_ci dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); 2178141cc406Sopenharmony_ci dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); 2179141cc406Sopenharmony_ci dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); 2180141cc406Sopenharmony_ci dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); 2181141cc406Sopenharmony_ci 2182141cc406Sopenharmony_ci /* Check the corners are OK. */ 2183141cc406Sopenharmony_ci if (dev->x_tl > dev->x_br) 2184141cc406Sopenharmony_ci { 2185141cc406Sopenharmony_ci int s; 2186141cc406Sopenharmony_ci s = dev->x_tl; 2187141cc406Sopenharmony_ci dev->x_tl = dev->x_br; 2188141cc406Sopenharmony_ci dev->x_br = s; 2189141cc406Sopenharmony_ci } 2190141cc406Sopenharmony_ci if (dev->y_tl > dev->y_br) 2191141cc406Sopenharmony_ci { 2192141cc406Sopenharmony_ci int s; 2193141cc406Sopenharmony_ci s = dev->y_tl; 2194141cc406Sopenharmony_ci dev->y_tl = dev->y_br; 2195141cc406Sopenharmony_ci dev->y_br = s; 2196141cc406Sopenharmony_ci } 2197141cc406Sopenharmony_ci 2198141cc406Sopenharmony_ci dev->width = dev->x_br - dev->x_tl; 2199141cc406Sopenharmony_ci dev->length = dev->y_br - dev->y_tl; 2200141cc406Sopenharmony_ci 2201141cc406Sopenharmony_ci /* Prepare the parameters for the caller. */ 2202141cc406Sopenharmony_ci memset (&dev->params, 0, sizeof (SANE_Parameters)); 2203141cc406Sopenharmony_ci 2204141cc406Sopenharmony_ci dev->params.format = SANE_FRAME_GRAY; 2205141cc406Sopenharmony_ci dev->params.last_frame = SANE_TRUE; 2206141cc406Sopenharmony_ci dev->params.pixels_per_line = 2207141cc406Sopenharmony_ci (((dev->width * dev->resolution) / 1200) + 7) & ~0x7; 2208141cc406Sopenharmony_ci 2209141cc406Sopenharmony_ci if (dev->depth == 4) 2210141cc406Sopenharmony_ci { 2211141cc406Sopenharmony_ci dev->params.depth = 8; 2212141cc406Sopenharmony_ci } 2213141cc406Sopenharmony_ci else 2214141cc406Sopenharmony_ci { 2215141cc406Sopenharmony_ci dev->params.depth = dev->depth; 2216141cc406Sopenharmony_ci } 2217141cc406Sopenharmony_ci dev->params.bytes_per_line = 2218141cc406Sopenharmony_ci (dev->params.pixels_per_line / 8) * dev->params.depth; 2219141cc406Sopenharmony_ci dev->params.lines = (dev->length * dev->resolution) / 1200; 2220141cc406Sopenharmony_ci } 2221141cc406Sopenharmony_ci 2222141cc406Sopenharmony_ci /* Return the current values. */ 2223141cc406Sopenharmony_ci if (params) 2224141cc406Sopenharmony_ci { 2225141cc406Sopenharmony_ci *params = (dev->params); 2226141cc406Sopenharmony_ci } 2227141cc406Sopenharmony_ci 2228141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: exit\n"); 2229141cc406Sopenharmony_ci 2230141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2231141cc406Sopenharmony_ci} 2232141cc406Sopenharmony_ci 2233141cc406Sopenharmony_ciSANE_Status 2234141cc406Sopenharmony_cisane_start (SANE_Handle handle) 2235141cc406Sopenharmony_ci{ 2236141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 2237141cc406Sopenharmony_ci SANE_Status status; 2238141cc406Sopenharmony_ci 2239141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: enter\n"); 2240141cc406Sopenharmony_ci 2241141cc406Sopenharmony_ci if (!(dev->scanning)) 2242141cc406Sopenharmony_ci { 2243141cc406Sopenharmony_ci 2244141cc406Sopenharmony_ci sane_get_parameters (dev, NULL); 2245141cc406Sopenharmony_ci 2246141cc406Sopenharmony_ci if (dev->image == NULL) 2247141cc406Sopenharmony_ci { 2248141cc406Sopenharmony_ci dev->image_size = 3 * dev->buffer_size; 2249141cc406Sopenharmony_ci dev->image = malloc (dev->image_size); 2250141cc406Sopenharmony_ci if (dev->image == NULL) 2251141cc406Sopenharmony_ci { 2252141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2253141cc406Sopenharmony_ci } 2254141cc406Sopenharmony_ci } 2255141cc406Sopenharmony_ci 2256141cc406Sopenharmony_ci /* Open again the scanner. */ 2257141cc406Sopenharmony_ci if (sanei_scsi_open 2258141cc406Sopenharmony_ci (dev->devicename, &(dev->sfd), matsushita_sense_handler, dev) != 0) 2259141cc406Sopenharmony_ci { 2260141cc406Sopenharmony_ci DBG (DBG_error, "ERROR: sane_start: open failed\n"); 2261141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2262141cc406Sopenharmony_ci } 2263141cc406Sopenharmony_ci 2264141cc406Sopenharmony_ci dev->page_side = 0; /* page front */ 2265141cc406Sopenharmony_ci dev->page_num = 0; /* first page */ 2266141cc406Sopenharmony_ci 2267141cc406Sopenharmony_ci /* The scanner must be ready. */ 2268141cc406Sopenharmony_ci status = matsushita_wait_scanner (dev); 2269141cc406Sopenharmony_ci if (status) 2270141cc406Sopenharmony_ci { 2271141cc406Sopenharmony_ci matsushita_close (dev); 2272141cc406Sopenharmony_ci return status; 2273141cc406Sopenharmony_ci } 2274141cc406Sopenharmony_ci 2275141cc406Sopenharmony_ci status = matsushita_reset_window (dev); 2276141cc406Sopenharmony_ci if (status) 2277141cc406Sopenharmony_ci { 2278141cc406Sopenharmony_ci matsushita_close (dev); 2279141cc406Sopenharmony_ci return status; 2280141cc406Sopenharmony_ci } 2281141cc406Sopenharmony_ci 2282141cc406Sopenharmony_ci status = matsushita_set_window (dev, PAGE_FRONT); 2283141cc406Sopenharmony_ci if (status) 2284141cc406Sopenharmony_ci { 2285141cc406Sopenharmony_ci matsushita_close (dev); 2286141cc406Sopenharmony_ci return status; 2287141cc406Sopenharmony_ci } 2288141cc406Sopenharmony_ci 2289141cc406Sopenharmony_ci if (dev->val[OPT_DUPLEX].w == SANE_TRUE) 2290141cc406Sopenharmony_ci { 2291141cc406Sopenharmony_ci status = matsushita_set_window (dev, PAGE_BACK); 2292141cc406Sopenharmony_ci if (status) 2293141cc406Sopenharmony_ci { 2294141cc406Sopenharmony_ci matsushita_close (dev); 2295141cc406Sopenharmony_ci return status; 2296141cc406Sopenharmony_ci } 2297141cc406Sopenharmony_ci } 2298141cc406Sopenharmony_ci 2299141cc406Sopenharmony_ci status = matsushita_read_document_size (dev); 2300141cc406Sopenharmony_ci if (status) 2301141cc406Sopenharmony_ci { 2302141cc406Sopenharmony_ci matsushita_close (dev); 2303141cc406Sopenharmony_ci return status; 2304141cc406Sopenharmony_ci } 2305141cc406Sopenharmony_ci 2306141cc406Sopenharmony_ci } 2307141cc406Sopenharmony_ci else 2308141cc406Sopenharmony_ci { 2309141cc406Sopenharmony_ci if (dev->val[OPT_DUPLEX].w == SANE_TRUE && dev->page_side == PAGE_FRONT) 2310141cc406Sopenharmony_ci { 2311141cc406Sopenharmony_ci dev->page_side = PAGE_BACK; 2312141cc406Sopenharmony_ci } 2313141cc406Sopenharmony_ci else 2314141cc406Sopenharmony_ci { 2315141cc406Sopenharmony_ci /* new sheet. */ 2316141cc406Sopenharmony_ci dev->page_side = PAGE_FRONT; 2317141cc406Sopenharmony_ci dev->page_num++; 2318141cc406Sopenharmony_ci } 2319141cc406Sopenharmony_ci 2320141cc406Sopenharmony_ci status = matsushita_check_next_page (dev); 2321141cc406Sopenharmony_ci if (status) 2322141cc406Sopenharmony_ci { 2323141cc406Sopenharmony_ci return status; 2324141cc406Sopenharmony_ci } 2325141cc406Sopenharmony_ci } 2326141cc406Sopenharmony_ci 2327141cc406Sopenharmony_ci dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; 2328141cc406Sopenharmony_ci dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; 2329141cc406Sopenharmony_ci if (dev->depth == 4) 2330141cc406Sopenharmony_ci { 2331141cc406Sopenharmony_ci /* Every byte read will be expanded into 2 bytes. */ 2332141cc406Sopenharmony_ci dev->real_bytes_left /= 2; 2333141cc406Sopenharmony_ci } 2334141cc406Sopenharmony_ci 2335141cc406Sopenharmony_ci dev->image_end = 0; 2336141cc406Sopenharmony_ci dev->image_begin = 0; 2337141cc406Sopenharmony_ci 2338141cc406Sopenharmony_ci dev->scanning = SANE_TRUE; 2339141cc406Sopenharmony_ci 2340141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit\n"); 2341141cc406Sopenharmony_ci 2342141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2343141cc406Sopenharmony_ci} 2344141cc406Sopenharmony_ci 2345141cc406Sopenharmony_ciSANE_Status 2346141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, 2347141cc406Sopenharmony_ci SANE_Int * len) 2348141cc406Sopenharmony_ci{ 2349141cc406Sopenharmony_ci SANE_Status status; 2350141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 2351141cc406Sopenharmony_ci size_t size; 2352141cc406Sopenharmony_ci int buf_offset; /* offset into buf */ 2353141cc406Sopenharmony_ci 2354141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: enter\n"); 2355141cc406Sopenharmony_ci 2356141cc406Sopenharmony_ci *len = 0; 2357141cc406Sopenharmony_ci 2358141cc406Sopenharmony_ci if (!(dev->scanning)) 2359141cc406Sopenharmony_ci { 2360141cc406Sopenharmony_ci /* OOPS, not scanning */ 2361141cc406Sopenharmony_ci return do_cancel (dev); 2362141cc406Sopenharmony_ci } 2363141cc406Sopenharmony_ci 2364141cc406Sopenharmony_ci if (dev->bytes_left <= 0) 2365141cc406Sopenharmony_ci { 2366141cc406Sopenharmony_ci return (SANE_STATUS_EOF); 2367141cc406Sopenharmony_ci } 2368141cc406Sopenharmony_ci 2369141cc406Sopenharmony_ci buf_offset = 0; 2370141cc406Sopenharmony_ci 2371141cc406Sopenharmony_ci do 2372141cc406Sopenharmony_ci { 2373141cc406Sopenharmony_ci if (dev->image_begin == dev->image_end) 2374141cc406Sopenharmony_ci { 2375141cc406Sopenharmony_ci /* Fill image */ 2376141cc406Sopenharmony_ci status = matsushita_fill_image (dev); 2377141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2378141cc406Sopenharmony_ci { 2379141cc406Sopenharmony_ci return (status); 2380141cc406Sopenharmony_ci } 2381141cc406Sopenharmony_ci } 2382141cc406Sopenharmony_ci 2383141cc406Sopenharmony_ci /* Something must have been read */ 2384141cc406Sopenharmony_ci if (dev->image_begin == dev->image_end) 2385141cc406Sopenharmony_ci { 2386141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: nothing read\n"); 2387141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 2388141cc406Sopenharmony_ci } 2389141cc406Sopenharmony_ci 2390141cc406Sopenharmony_ci /* Copy the data to the frontend buffer. */ 2391141cc406Sopenharmony_ci size = max_len - buf_offset; 2392141cc406Sopenharmony_ci if (size > dev->bytes_left) 2393141cc406Sopenharmony_ci { 2394141cc406Sopenharmony_ci size = dev->bytes_left; 2395141cc406Sopenharmony_ci } 2396141cc406Sopenharmony_ci matsushita_copy_raw_to_frontend (dev, buf + buf_offset, &size); 2397141cc406Sopenharmony_ci 2398141cc406Sopenharmony_ci buf_offset += size; 2399141cc406Sopenharmony_ci 2400141cc406Sopenharmony_ci dev->bytes_left -= size; 2401141cc406Sopenharmony_ci *len += size; 2402141cc406Sopenharmony_ci 2403141cc406Sopenharmony_ci } 2404141cc406Sopenharmony_ci while ((buf_offset != max_len) && dev->bytes_left); 2405141cc406Sopenharmony_ci 2406141cc406Sopenharmony_ci DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long)dev->bytes_left); 2407141cc406Sopenharmony_ci 2408141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2409141cc406Sopenharmony_ci} 2410141cc406Sopenharmony_ci 2411141cc406Sopenharmony_ciSANE_Status 2412141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) 2413141cc406Sopenharmony_ci{ 2414141cc406Sopenharmony_ci SANE_Status status; 2415141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 2416141cc406Sopenharmony_ci 2417141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: enter\n"); 2418141cc406Sopenharmony_ci 2419141cc406Sopenharmony_ci if (dev->scanning == SANE_FALSE) 2420141cc406Sopenharmony_ci { 2421141cc406Sopenharmony_ci return (SANE_STATUS_INVAL); 2422141cc406Sopenharmony_ci } 2423141cc406Sopenharmony_ci 2424141cc406Sopenharmony_ci if (non_blocking == SANE_FALSE) { 2425141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2426141cc406Sopenharmony_ci } else { 2427141cc406Sopenharmony_ci status = SANE_STATUS_UNSUPPORTED; 2428141cc406Sopenharmony_ci } 2429141cc406Sopenharmony_ci 2430141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: exit\n"); 2431141cc406Sopenharmony_ci 2432141cc406Sopenharmony_ci return status; 2433141cc406Sopenharmony_ci} 2434141cc406Sopenharmony_ci 2435141cc406Sopenharmony_ciSANE_Status 2436141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) 2437141cc406Sopenharmony_ci{ 2438141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: enter\n"); 2439141cc406Sopenharmony_ci 2440141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: exit\n"); 2441141cc406Sopenharmony_ci 2442141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2443141cc406Sopenharmony_ci} 2444141cc406Sopenharmony_ci 2445141cc406Sopenharmony_civoid 2446141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2447141cc406Sopenharmony_ci{ 2448141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 2449141cc406Sopenharmony_ci 2450141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: enter\n"); 2451141cc406Sopenharmony_ci 2452141cc406Sopenharmony_ci do_cancel (dev); 2453141cc406Sopenharmony_ci 2454141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: exit\n"); 2455141cc406Sopenharmony_ci} 2456141cc406Sopenharmony_ci 2457141cc406Sopenharmony_civoid 2458141cc406Sopenharmony_cisane_close (SANE_Handle handle) 2459141cc406Sopenharmony_ci{ 2460141cc406Sopenharmony_ci Matsushita_Scanner *dev = handle; 2461141cc406Sopenharmony_ci Matsushita_Scanner *dev_tmp; 2462141cc406Sopenharmony_ci 2463141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: enter\n"); 2464141cc406Sopenharmony_ci 2465141cc406Sopenharmony_ci do_cancel (dev); 2466141cc406Sopenharmony_ci matsushita_close (dev); 2467141cc406Sopenharmony_ci 2468141cc406Sopenharmony_ci /* Unlink dev. */ 2469141cc406Sopenharmony_ci if (first_dev == dev) 2470141cc406Sopenharmony_ci { 2471141cc406Sopenharmony_ci first_dev = dev->next; 2472141cc406Sopenharmony_ci } 2473141cc406Sopenharmony_ci else 2474141cc406Sopenharmony_ci { 2475141cc406Sopenharmony_ci dev_tmp = first_dev; 2476141cc406Sopenharmony_ci while (dev_tmp->next && dev_tmp->next != dev) 2477141cc406Sopenharmony_ci { 2478141cc406Sopenharmony_ci dev_tmp = dev_tmp->next; 2479141cc406Sopenharmony_ci } 2480141cc406Sopenharmony_ci if (dev_tmp->next != NULL) 2481141cc406Sopenharmony_ci { 2482141cc406Sopenharmony_ci dev_tmp->next = dev_tmp->next->next; 2483141cc406Sopenharmony_ci } 2484141cc406Sopenharmony_ci } 2485141cc406Sopenharmony_ci 2486141cc406Sopenharmony_ci matsushita_free (dev); 2487141cc406Sopenharmony_ci num_devices--; 2488141cc406Sopenharmony_ci 2489141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: exit\n"); 2490141cc406Sopenharmony_ci} 2491141cc406Sopenharmony_ci 2492141cc406Sopenharmony_civoid 2493141cc406Sopenharmony_cisane_exit (void) 2494141cc406Sopenharmony_ci{ 2495141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: enter\n"); 2496141cc406Sopenharmony_ci 2497141cc406Sopenharmony_ci while (first_dev) 2498141cc406Sopenharmony_ci { 2499141cc406Sopenharmony_ci sane_close (first_dev); 2500141cc406Sopenharmony_ci } 2501141cc406Sopenharmony_ci 2502141cc406Sopenharmony_ci if (devlist) 2503141cc406Sopenharmony_ci { 2504141cc406Sopenharmony_ci free (devlist); 2505141cc406Sopenharmony_ci devlist = NULL; 2506141cc406Sopenharmony_ci } 2507141cc406Sopenharmony_ci 2508141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: exit\n"); 2509141cc406Sopenharmony_ci} 2510