1141cc406Sopenharmony_ci/* lexmark.c: SANE backend for Lexmark scanners. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci (C) 2003-2004 Lexmark International, Inc. (Original Source code) 4141cc406Sopenharmony_ci (C) 2005 Fred Odendaal 5141cc406Sopenharmony_ci (C) 2006-2013 Stéphane Voltz <stef.dev@free.fr> 6141cc406Sopenharmony_ci (C) 2010 "Torsten Houwaart" <ToHo@gmx.de> X74 support 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This file is part of the SANE package. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 11141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 12141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 13141cc406Sopenharmony_ci License, or (at your option) any later version. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 16141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 17141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18141cc406Sopenharmony_ci General Public License for more details. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 21141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 24141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 25141cc406Sopenharmony_ci 26141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 27141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 28141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 29141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 30141cc406Sopenharmony_ci account of linking the SANE library code into it. 31141cc406Sopenharmony_ci 32141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 33141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 34141cc406Sopenharmony_ci License. 35141cc406Sopenharmony_ci 36141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 37141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 38141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 41141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 42141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci **************************************************************************/ 45141cc406Sopenharmony_ci 46141cc406Sopenharmony_ci#include "lexmark.h" 47141cc406Sopenharmony_ci 48141cc406Sopenharmony_ci#define LEXMARK_CONFIG_FILE "lexmark.conf" 49141cc406Sopenharmony_ci#define BUILD 32 50141cc406Sopenharmony_ci#define MAX_OPTION_STRING_SIZE 255 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_cistatic Lexmark_Device *first_lexmark_device = 0; 53141cc406Sopenharmony_cistatic SANE_Int num_lexmark_device = 0; 54141cc406Sopenharmony_cistatic const SANE_Device **sane_device_list = NULL; 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci/* Program globals F.O - Should this be per device?*/ 57141cc406Sopenharmony_cistatic SANE_Bool initialized = SANE_FALSE; 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = { 60141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 61141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 62141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 63141cc406Sopenharmony_ci NULL 64141cc406Sopenharmony_ci}; 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci/* possible resolutions are: 75x75, 150x150, 300x300, 600x600, 600x1200 */ 67141cc406Sopenharmony_ci 68141cc406Sopenharmony_cistatic SANE_Int x1100_dpi_list[] = { 69141cc406Sopenharmony_ci 5, 75, 150, 300, 600, 1200 70141cc406Sopenharmony_ci}; 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_cistatic SANE_Int a920_dpi_list[] = { 73141cc406Sopenharmony_ci 4, 75, 150, 300, 600 74141cc406Sopenharmony_ci}; 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_cistatic SANE_Int x1200_dpi_list[] = { 77141cc406Sopenharmony_ci 4, 75, 150, 300, 600 78141cc406Sopenharmony_ci}; 79141cc406Sopenharmony_ci 80141cc406Sopenharmony_cistatic SANE_Int x74_dpi_list[] = { 81141cc406Sopenharmony_ci 75, 150, 300, 600 82141cc406Sopenharmony_ci}; 83141cc406Sopenharmony_ci 84141cc406Sopenharmony_cistatic SANE_Range threshold_range = { 85141cc406Sopenharmony_ci SANE_FIX (0.0), /* minimum */ 86141cc406Sopenharmony_ci SANE_FIX (100.0), /* maximum */ 87141cc406Sopenharmony_ci SANE_FIX (1.0) /* quantization */ 88141cc406Sopenharmony_ci}; 89141cc406Sopenharmony_ci 90141cc406Sopenharmony_cistatic const SANE_Range gain_range = { 91141cc406Sopenharmony_ci 0, /* minimum */ 92141cc406Sopenharmony_ci 31, /* maximum */ 93141cc406Sopenharmony_ci 0 /* quantization */ 94141cc406Sopenharmony_ci}; 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci/* for now known models (2 ...) have the same scan window geometry. 97141cc406Sopenharmony_ci coordinates are expressed in pixels, with a quantization factor of 98141cc406Sopenharmony_ci 8 to have 'even' coordinates at 75 dpi */ 99141cc406Sopenharmony_cistatic SANE_Range x_range = { 100141cc406Sopenharmony_ci 0, /* minimum */ 101141cc406Sopenharmony_ci 5104, /* maximum */ 102141cc406Sopenharmony_ci 16 /* quantization : 16 is required so we 103141cc406Sopenharmony_ci never have an odd width */ 104141cc406Sopenharmony_ci}; 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_cistatic SANE_Range y_range = { 107141cc406Sopenharmony_ci 0, /* minimum */ 108141cc406Sopenharmony_ci 6848, /* maximum */ 109141cc406Sopenharmony_ci /* 7032, for X74 */ 110141cc406Sopenharmony_ci 8 /* quantization */ 111141cc406Sopenharmony_ci}; 112141cc406Sopenharmony_ci 113141cc406Sopenharmony_ci/* static functions */ 114141cc406Sopenharmony_cistatic SANE_Status init_options (Lexmark_Device * lexmark_device); 115141cc406Sopenharmony_cistatic SANE_Status attachLexmark (SANE_String_Const devname); 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_ciSANE_Status 118141cc406Sopenharmony_ciinit_options (Lexmark_Device * dev) 119141cc406Sopenharmony_ci{ 120141cc406Sopenharmony_ci 121141cc406Sopenharmony_ci SANE_Option_Descriptor *od; 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci DBG (2, "init_options: dev = %p\n", (void *) dev); 124141cc406Sopenharmony_ci 125141cc406Sopenharmony_ci /* number of options */ 126141cc406Sopenharmony_ci od = &(dev->opt[OPT_NUM_OPTS]); 127141cc406Sopenharmony_ci od->name = SANE_NAME_NUM_OPTIONS; 128141cc406Sopenharmony_ci od->title = SANE_TITLE_NUM_OPTIONS; 129141cc406Sopenharmony_ci od->desc = SANE_DESC_NUM_OPTIONS; 130141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 131141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 132141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 133141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT; 134141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 135141cc406Sopenharmony_ci od->constraint.range = 0; 136141cc406Sopenharmony_ci dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 137141cc406Sopenharmony_ci 138141cc406Sopenharmony_ci /* mode - sets the scan mode: Color, Gray, or Line Art */ 139141cc406Sopenharmony_ci od = &(dev->opt[OPT_MODE]); 140141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_MODE; 141141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_MODE; 142141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_MODE;; 143141cc406Sopenharmony_ci od->type = SANE_TYPE_STRING; 144141cc406Sopenharmony_ci od->unit = SANE_UNIT_NONE; 145141cc406Sopenharmony_ci od->size = MAX_OPTION_STRING_SIZE; 146141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 147141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_STRING_LIST; 148141cc406Sopenharmony_ci od->constraint.string_list = mode_list; 149141cc406Sopenharmony_ci dev->val[OPT_MODE].s = malloc (od->size); 150141cc406Sopenharmony_ci if (!dev->val[OPT_MODE].s) 151141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 152141cc406Sopenharmony_ci strcpy (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR); 153141cc406Sopenharmony_ci 154141cc406Sopenharmony_ci /* resolution */ 155141cc406Sopenharmony_ci od = &(dev->opt[OPT_RESOLUTION]); 156141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_RESOLUTION; 157141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_RESOLUTION; 158141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_RESOLUTION; 159141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 160141cc406Sopenharmony_ci od->unit = SANE_UNIT_DPI; 161141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 162141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 163141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_WORD_LIST; 164141cc406Sopenharmony_ci switch (dev->model.sensor_type) 165141cc406Sopenharmony_ci { 166141cc406Sopenharmony_ci case X1100_2C_SENSOR: 167141cc406Sopenharmony_ci case A920_SENSOR: 168141cc406Sopenharmony_ci od->constraint.word_list = a920_dpi_list; 169141cc406Sopenharmony_ci break; 170141cc406Sopenharmony_ci case X1100_B2_SENSOR: 171141cc406Sopenharmony_ci od->constraint.word_list = x1100_dpi_list; 172141cc406Sopenharmony_ci break; 173141cc406Sopenharmony_ci case X1200_SENSOR: 174141cc406Sopenharmony_ci case X1200_USB2_SENSOR: 175141cc406Sopenharmony_ci od->constraint.word_list = x1200_dpi_list; 176141cc406Sopenharmony_ci break; 177141cc406Sopenharmony_ci case X74_SENSOR: 178141cc406Sopenharmony_ci od->constraint.word_list = x74_dpi_list; 179141cc406Sopenharmony_ci break; 180141cc406Sopenharmony_ci } 181141cc406Sopenharmony_ci dev->val[OPT_RESOLUTION].w = 75; 182141cc406Sopenharmony_ci 183141cc406Sopenharmony_ci /* preview mode */ 184141cc406Sopenharmony_ci od = &(dev->opt[OPT_PREVIEW]); 185141cc406Sopenharmony_ci od->name = SANE_NAME_PREVIEW; 186141cc406Sopenharmony_ci od->title = SANE_TITLE_PREVIEW; 187141cc406Sopenharmony_ci od->desc = SANE_DESC_PREVIEW; 188141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 189141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 190141cc406Sopenharmony_ci od->type = SANE_TYPE_BOOL; 191141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 192141cc406Sopenharmony_ci dev->val[OPT_PREVIEW].w = SANE_FALSE; 193141cc406Sopenharmony_ci 194141cc406Sopenharmony_ci /* "Geometry" group: */ 195141cc406Sopenharmony_ci od = &(dev->opt[OPT_GEOMETRY_GROUP]); 196141cc406Sopenharmony_ci od->name = ""; 197141cc406Sopenharmony_ci od->title = SANE_I18N ("Geometry"); 198141cc406Sopenharmony_ci od->desc = ""; 199141cc406Sopenharmony_ci od->type = SANE_TYPE_GROUP; 200141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 201141cc406Sopenharmony_ci od->size = 0; 202141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_NONE; 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci /* top-left x */ 205141cc406Sopenharmony_ci od = &(dev->opt[OPT_TL_X]); 206141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_TL_X; 207141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_TL_X; 208141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_TL_X; 209141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 210141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 211141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 212141cc406Sopenharmony_ci od->unit = SANE_UNIT_PIXEL; 213141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 214141cc406Sopenharmony_ci od->constraint.range = &x_range; 215141cc406Sopenharmony_ci dev->val[OPT_TL_X].w = 0; 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci /* top-left y */ 218141cc406Sopenharmony_ci od = &(dev->opt[OPT_TL_Y]); 219141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_TL_Y; 220141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_TL_Y; 221141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_TL_Y; 222141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 223141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 224141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 225141cc406Sopenharmony_ci od->unit = SANE_UNIT_PIXEL; 226141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 227141cc406Sopenharmony_ci od->constraint.range = &y_range; 228141cc406Sopenharmony_ci dev->val[OPT_TL_Y].w = 0; 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci /* bottom-right x */ 231141cc406Sopenharmony_ci od = &(dev->opt[OPT_BR_X]); 232141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_BR_X; 233141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_BR_X; 234141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_BR_X; 235141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 236141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 237141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 238141cc406Sopenharmony_ci od->unit = SANE_UNIT_PIXEL; 239141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 240141cc406Sopenharmony_ci od->constraint.range = &x_range; 241141cc406Sopenharmony_ci dev->val[OPT_BR_X].w = x_range.max; 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci /* bottom-right y */ 244141cc406Sopenharmony_ci od = &(dev->opt[OPT_BR_Y]); 245141cc406Sopenharmony_ci od->name = SANE_NAME_SCAN_BR_Y; 246141cc406Sopenharmony_ci od->title = SANE_TITLE_SCAN_BR_Y; 247141cc406Sopenharmony_ci od->desc = SANE_DESC_SCAN_BR_Y; 248141cc406Sopenharmony_ci od->type = SANE_TYPE_INT; 249141cc406Sopenharmony_ci od->size = sizeof (SANE_Word); 250141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; 251141cc406Sopenharmony_ci od->unit = SANE_UNIT_PIXEL; 252141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 253141cc406Sopenharmony_ci od->constraint.range = &y_range; 254141cc406Sopenharmony_ci dev->val[OPT_BR_Y].w = y_range.max; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_ci /* threshold */ 257141cc406Sopenharmony_ci od = &(dev->opt[OPT_THRESHOLD]); 258141cc406Sopenharmony_ci od->name = SANE_NAME_THRESHOLD; 259141cc406Sopenharmony_ci od->title = SANE_TITLE_THRESHOLD; 260141cc406Sopenharmony_ci od->desc = SANE_DESC_THRESHOLD; 261141cc406Sopenharmony_ci od->type = SANE_TYPE_FIXED; 262141cc406Sopenharmony_ci od->unit = SANE_UNIT_PERCENT; 263141cc406Sopenharmony_ci od->size = sizeof (SANE_Fixed); 264141cc406Sopenharmony_ci od->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; 265141cc406Sopenharmony_ci od->constraint_type = SANE_CONSTRAINT_RANGE; 266141cc406Sopenharmony_ci od->constraint.range = &threshold_range; 267141cc406Sopenharmony_ci dev->val[OPT_THRESHOLD].w = SANE_FIX (50.0); 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci /* gain group */ 270141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].name = "manual-channel-gain"; 271141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].title = SANE_I18N ("Gain"); 272141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].desc = SANE_I18N ("Color channels gain settings"); 273141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].type = SANE_TYPE_BOOL; 274141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].cap = 275141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; 276141cc406Sopenharmony_ci dev->opt[OPT_MANUAL_GAIN].size = sizeof (SANE_Bool); 277141cc406Sopenharmony_ci dev->val[OPT_MANUAL_GAIN].w = SANE_FALSE; 278141cc406Sopenharmony_ci 279141cc406Sopenharmony_ci /* gray gain */ 280141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].name = "gray-gain"; 281141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].title = SANE_I18N ("Gray gain"); 282141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].desc = SANE_I18N ("Sets gray channel gain"); 283141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].type = SANE_TYPE_INT; 284141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].cap = 285141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | 286141cc406Sopenharmony_ci SANE_CAP_ADVANCED; 287141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].unit = SANE_UNIT_NONE; 288141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].size = sizeof (SANE_Int); 289141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 290141cc406Sopenharmony_ci dev->opt[OPT_GRAY_GAIN].constraint.range = &gain_range; 291141cc406Sopenharmony_ci dev->val[OPT_GRAY_GAIN].w = 10; 292141cc406Sopenharmony_ci 293141cc406Sopenharmony_ci /* red gain */ 294141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].name = "red-gain"; 295141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].title = SANE_I18N ("Red gain"); 296141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].desc = SANE_I18N ("Sets red channel gain"); 297141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].type = SANE_TYPE_INT; 298141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].cap = 299141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | 300141cc406Sopenharmony_ci SANE_CAP_ADVANCED; 301141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].unit = SANE_UNIT_NONE; 302141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].size = sizeof (SANE_Int); 303141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 304141cc406Sopenharmony_ci dev->opt[OPT_RED_GAIN].constraint.range = &gain_range; 305141cc406Sopenharmony_ci dev->val[OPT_RED_GAIN].w = 10; 306141cc406Sopenharmony_ci 307141cc406Sopenharmony_ci /* green gain */ 308141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].name = "green-gain"; 309141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].title = SANE_I18N ("Green gain"); 310141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].desc = SANE_I18N ("Sets green channel gain"); 311141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].type = SANE_TYPE_INT; 312141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].cap = 313141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | 314141cc406Sopenharmony_ci SANE_CAP_ADVANCED; 315141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].unit = SANE_UNIT_NONE; 316141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].size = sizeof (SANE_Int); 317141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 318141cc406Sopenharmony_ci dev->opt[OPT_GREEN_GAIN].constraint.range = &gain_range; 319141cc406Sopenharmony_ci dev->val[OPT_GREEN_GAIN].w = 10; 320141cc406Sopenharmony_ci 321141cc406Sopenharmony_ci /* blue gain */ 322141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].name = "blue-gain"; 323141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].title = SANE_I18N ("Blue gain"); 324141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].desc = SANE_I18N ("Sets blue channel gain"); 325141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].type = SANE_TYPE_INT; 326141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].cap = 327141cc406Sopenharmony_ci SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | 328141cc406Sopenharmony_ci SANE_CAP_ADVANCED; 329141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].unit = SANE_UNIT_NONE; 330141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].size = sizeof (SANE_Int); 331141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; 332141cc406Sopenharmony_ci dev->opt[OPT_BLUE_GAIN].constraint.range = &gain_range; 333141cc406Sopenharmony_ci dev->val[OPT_BLUE_GAIN].w = 10; 334141cc406Sopenharmony_ci 335141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 336141cc406Sopenharmony_ci} 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci/***************************** SANE API ****************************/ 340141cc406Sopenharmony_ci 341141cc406Sopenharmony_ciSANE_Status 342141cc406Sopenharmony_ciattachLexmark (SANE_String_Const devname) 343141cc406Sopenharmony_ci{ 344141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 345141cc406Sopenharmony_ci SANE_Int dn, vendor, product, variant; 346141cc406Sopenharmony_ci SANE_Status status; 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci DBG (2, "attachLexmark: devname=%s\n", devname); 349141cc406Sopenharmony_ci 350141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 351141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 352141cc406Sopenharmony_ci { 353141cc406Sopenharmony_ci /* already attached devices */ 354141cc406Sopenharmony_ci if (strcmp (lexmark_device->sane.name, devname) == 0) 355141cc406Sopenharmony_ci { 356141cc406Sopenharmony_ci lexmark_device->missing = SANE_FALSE; 357141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 358141cc406Sopenharmony_ci } 359141cc406Sopenharmony_ci } 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci lexmark_device = (Lexmark_Device *) malloc (sizeof (Lexmark_Device)); 362141cc406Sopenharmony_ci if (lexmark_device == NULL) 363141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci#ifdef FAKE_USB 366141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 367141cc406Sopenharmony_ci#else 368141cc406Sopenharmony_ci status = sanei_usb_open (devname, &dn); 369141cc406Sopenharmony_ci#endif 370141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 371141cc406Sopenharmony_ci { 372141cc406Sopenharmony_ci DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname, 373141cc406Sopenharmony_ci sane_strstatus (status)); 374141cc406Sopenharmony_ci return status; 375141cc406Sopenharmony_ci } 376141cc406Sopenharmony_ci else 377141cc406Sopenharmony_ci DBG (2, "attachLexmark: device `%s' successfully opened\n", devname); 378141cc406Sopenharmony_ci 379141cc406Sopenharmony_ci#ifdef FAKE_USB 380141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 381141cc406Sopenharmony_ci /* put the id of the model you want to fake here */ 382141cc406Sopenharmony_ci vendor = 0x043d; 383141cc406Sopenharmony_ci product = 0x007c; /* X11xx */ 384141cc406Sopenharmony_ci variant = 0xb2; 385141cc406Sopenharmony_ci#else 386141cc406Sopenharmony_ci variant = 0; 387141cc406Sopenharmony_ci status = sanei_usb_get_vendor_product (dn, &vendor, &product); 388141cc406Sopenharmony_ci#endif 389141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 390141cc406Sopenharmony_ci { 391141cc406Sopenharmony_ci DBG (1, 392141cc406Sopenharmony_ci "attachLexmark: couldn't get vendor and product ids of device `%s': %s\n", 393141cc406Sopenharmony_ci devname, sane_strstatus (status)); 394141cc406Sopenharmony_ci#ifndef FAKE_USB 395141cc406Sopenharmony_ci sanei_usb_close (dn); 396141cc406Sopenharmony_ci#endif 397141cc406Sopenharmony_ci return status; 398141cc406Sopenharmony_ci } 399141cc406Sopenharmony_ci#ifndef FAKE_USB 400141cc406Sopenharmony_ci sanei_usb_close (dn); 401141cc406Sopenharmony_ci#endif 402141cc406Sopenharmony_ci 403141cc406Sopenharmony_ci DBG (2, "attachLexmark: testing device `%s': 0x%04x:0x%04x, variant=%d\n", 404141cc406Sopenharmony_ci devname, vendor, product, variant); 405141cc406Sopenharmony_ci if (sanei_lexmark_low_assign_model (lexmark_device, 406141cc406Sopenharmony_ci devname, 407141cc406Sopenharmony_ci vendor, 408141cc406Sopenharmony_ci product, variant) != SANE_STATUS_GOOD) 409141cc406Sopenharmony_ci { 410141cc406Sopenharmony_ci DBG (2, "attachLexmark: unsupported device `%s': 0x%04x:0x%04x\n", 411141cc406Sopenharmony_ci devname, vendor, product); 412141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 413141cc406Sopenharmony_ci } 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci /* add new device to device list */ 416141cc406Sopenharmony_ci 417141cc406Sopenharmony_ci /* there are two variant of the scanner with the same USB id, 418141cc406Sopenharmony_ci * so we need to read registers from scanner to detect which one 419141cc406Sopenharmony_ci * is really connected */ 420141cc406Sopenharmony_ci status = sanei_lexmark_low_open_device (lexmark_device); 421141cc406Sopenharmony_ci sanei_usb_close (lexmark_device->devnum); 422141cc406Sopenharmony_ci 423141cc406Sopenharmony_ci /* set up scanner start status */ 424141cc406Sopenharmony_ci sanei_lexmark_low_init (lexmark_device); 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci /* Set the default resolution here */ 427141cc406Sopenharmony_ci lexmark_device->x_dpi = 75; 428141cc406Sopenharmony_ci lexmark_device->y_dpi = 75; 429141cc406Sopenharmony_ci 430141cc406Sopenharmony_ci /* Make the pointer to the read buffer null here */ 431141cc406Sopenharmony_ci lexmark_device->read_buffer = NULL; 432141cc406Sopenharmony_ci 433141cc406Sopenharmony_ci /* Set the default threshold for lineart mode here */ 434141cc406Sopenharmony_ci lexmark_device->threshold = 0x80; 435141cc406Sopenharmony_ci 436141cc406Sopenharmony_ci lexmark_device->shading_coeff = NULL; 437141cc406Sopenharmony_ci 438141cc406Sopenharmony_ci /* mark device as present */ 439141cc406Sopenharmony_ci lexmark_device->missing = SANE_FALSE; 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci /* insert it a the start of the chained list */ 442141cc406Sopenharmony_ci lexmark_device->next = first_lexmark_device; 443141cc406Sopenharmony_ci first_lexmark_device = lexmark_device; 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci num_lexmark_device++; 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci return status; 448141cc406Sopenharmony_ci} 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci/** probe for supported lexmark devices 451141cc406Sopenharmony_ci * This function scan usb and try to attached to scanner 452141cc406Sopenharmony_ci * configured in lexmark.conf . 453141cc406Sopenharmony_ci */ 454141cc406Sopenharmony_cistatic SANE_Status 455141cc406Sopenharmony_ciprobe_lexmark_devices (void) 456141cc406Sopenharmony_ci{ 457141cc406Sopenharmony_ci FILE *fp; 458141cc406Sopenharmony_ci SANE_Char line[PATH_MAX]; 459141cc406Sopenharmony_ci const char *lp; 460141cc406Sopenharmony_ci SANE_Int vendor, product; 461141cc406Sopenharmony_ci size_t len; 462141cc406Sopenharmony_ci Lexmark_Device *dev; 463141cc406Sopenharmony_ci 464141cc406Sopenharmony_ci /* mark already detected devices as missing, during device probe 465141cc406Sopenharmony_ci * detected devices will clear this flag */ 466141cc406Sopenharmony_ci dev = first_lexmark_device; 467141cc406Sopenharmony_ci while (dev != NULL) 468141cc406Sopenharmony_ci { 469141cc406Sopenharmony_ci dev->missing = SANE_TRUE; 470141cc406Sopenharmony_ci dev = dev->next; 471141cc406Sopenharmony_ci } 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci /* open config file, parse option and try to open 474141cc406Sopenharmony_ci * any device configure in it */ 475141cc406Sopenharmony_ci fp = sanei_config_open (LEXMARK_CONFIG_FILE); 476141cc406Sopenharmony_ci if (!fp) 477141cc406Sopenharmony_ci { 478141cc406Sopenharmony_ci return SANE_STATUS_ACCESS_DENIED; 479141cc406Sopenharmony_ci } 480141cc406Sopenharmony_ci 481141cc406Sopenharmony_ci while (sanei_config_read (line, PATH_MAX, fp)) 482141cc406Sopenharmony_ci { 483141cc406Sopenharmony_ci /* ignore comments */ 484141cc406Sopenharmony_ci if (line[0] == '#') 485141cc406Sopenharmony_ci continue; 486141cc406Sopenharmony_ci len = strlen (line); 487141cc406Sopenharmony_ci 488141cc406Sopenharmony_ci /* delete newline characters at end */ 489141cc406Sopenharmony_ci if (line[len - 1] == '\n') 490141cc406Sopenharmony_ci line[--len] = '\0'; 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_ci lp = sanei_config_skip_whitespace (line); 493141cc406Sopenharmony_ci /* skip empty lines */ 494141cc406Sopenharmony_ci if (*lp == 0) 495141cc406Sopenharmony_ci continue; 496141cc406Sopenharmony_ci 497141cc406Sopenharmony_ci if (sscanf (lp, "usb %i %i", &vendor, &product) == 2) 498141cc406Sopenharmony_ci ; 499141cc406Sopenharmony_ci else if (strncmp ("libusb", lp, 6) == 0) 500141cc406Sopenharmony_ci ; 501141cc406Sopenharmony_ci else if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) 502141cc406Sopenharmony_ci { 503141cc406Sopenharmony_ci lp += 3; 504141cc406Sopenharmony_ci lp = sanei_config_skip_whitespace (lp); 505141cc406Sopenharmony_ci } 506141cc406Sopenharmony_ci else 507141cc406Sopenharmony_ci continue; 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci#ifdef FAKE_USB 510141cc406Sopenharmony_ci attachLexmark ("FAKE_USB"); 511141cc406Sopenharmony_ci#else 512141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (lp, attachLexmark); 513141cc406Sopenharmony_ci#endif 514141cc406Sopenharmony_ci } 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci fclose (fp); 517141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 518141cc406Sopenharmony_ci} 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_ciSANE_Status 521141cc406Sopenharmony_cisane_init (SANE_Int * version_code, 522141cc406Sopenharmony_ci SANE_Auth_Callback __sane_unused__ authorize) 523141cc406Sopenharmony_ci{ 524141cc406Sopenharmony_ci SANE_Status status; 525141cc406Sopenharmony_ci 526141cc406Sopenharmony_ci DBG_INIT (); 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_ci DBG (1, "SANE Lexmark backend version %d.%d.%d-devel\n", SANE_CURRENT_MAJOR, 529141cc406Sopenharmony_ci SANE_CURRENT_MINOR, BUILD); 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci DBG (2, "sane_init: version_code=%p\n", (void *) version_code); 532141cc406Sopenharmony_ci 533141cc406Sopenharmony_ci if (version_code) 534141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 535141cc406Sopenharmony_ci 536141cc406Sopenharmony_ci#ifndef FAKE_USB 537141cc406Sopenharmony_ci sanei_usb_init (); 538141cc406Sopenharmony_ci#endif 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci status = probe_lexmark_devices (); 541141cc406Sopenharmony_ci 542141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD) 543141cc406Sopenharmony_ci { 544141cc406Sopenharmony_ci initialized = SANE_TRUE; 545141cc406Sopenharmony_ci } 546141cc406Sopenharmony_ci else 547141cc406Sopenharmony_ci { 548141cc406Sopenharmony_ci initialized = SANE_FALSE; 549141cc406Sopenharmony_ci } 550141cc406Sopenharmony_ci 551141cc406Sopenharmony_ci return status; 552141cc406Sopenharmony_ci} 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_civoid 555141cc406Sopenharmony_cisane_exit (void) 556141cc406Sopenharmony_ci{ 557141cc406Sopenharmony_ci Lexmark_Device *lexmark_device, *next_lexmark_device; 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci DBG (2, "sane_exit\n"); 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci if (!initialized) 562141cc406Sopenharmony_ci return; 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 565141cc406Sopenharmony_ci lexmark_device = next_lexmark_device) 566141cc406Sopenharmony_ci { 567141cc406Sopenharmony_ci next_lexmark_device = lexmark_device->next; 568141cc406Sopenharmony_ci sanei_lexmark_low_destroy (lexmark_device); 569141cc406Sopenharmony_ci free (lexmark_device); 570141cc406Sopenharmony_ci } 571141cc406Sopenharmony_ci 572141cc406Sopenharmony_ci if (sane_device_list) 573141cc406Sopenharmony_ci free (sane_device_list); 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci sanei_usb_exit(); 576141cc406Sopenharmony_ci initialized = SANE_FALSE; 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_ci return; 579141cc406Sopenharmony_ci} 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ciSANE_Status 582141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 583141cc406Sopenharmony_ci{ 584141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 585141cc406Sopenharmony_ci SANE_Int index; 586141cc406Sopenharmony_ci 587141cc406Sopenharmony_ci DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", 588141cc406Sopenharmony_ci (void *) device_list, local_only); 589141cc406Sopenharmony_ci 590141cc406Sopenharmony_ci /* hot-plug case : detection of newly connected scanners */ 591141cc406Sopenharmony_ci sanei_usb_scan_devices (); 592141cc406Sopenharmony_ci probe_lexmark_devices (); 593141cc406Sopenharmony_ci 594141cc406Sopenharmony_ci if (sane_device_list) 595141cc406Sopenharmony_ci free (sane_device_list); 596141cc406Sopenharmony_ci 597141cc406Sopenharmony_ci sane_device_list = malloc ((num_lexmark_device + 1) * 598141cc406Sopenharmony_ci sizeof (sane_device_list[0])); 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci if (!sane_device_list) 601141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 602141cc406Sopenharmony_ci 603141cc406Sopenharmony_ci index = 0; 604141cc406Sopenharmony_ci lexmark_device = first_lexmark_device; 605141cc406Sopenharmony_ci while (lexmark_device != NULL) 606141cc406Sopenharmony_ci { 607141cc406Sopenharmony_ci if (lexmark_device->missing == SANE_FALSE) 608141cc406Sopenharmony_ci { 609141cc406Sopenharmony_ci sane_device_list[index] = &(lexmark_device->sane); 610141cc406Sopenharmony_ci index++; 611141cc406Sopenharmony_ci } 612141cc406Sopenharmony_ci lexmark_device = lexmark_device->next; 613141cc406Sopenharmony_ci } 614141cc406Sopenharmony_ci sane_device_list[index] = 0; 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_ci *device_list = sane_device_list; 617141cc406Sopenharmony_ci 618141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 619141cc406Sopenharmony_ci} 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci 622141cc406Sopenharmony_ci/** 623141cc406Sopenharmony_ci * Open the backend, ie return the struct handle of a detected scanner 624141cc406Sopenharmony_ci * The struct returned is choosne if it matches the name given, which is 625141cc406Sopenharmony_ci * useful when several scanners handled by the backend have been detected. 626141cc406Sopenharmony_ci * However, special case empty string "" and "lexmark" pick the first 627141cc406Sopenharmony_ci * available handle. 628141cc406Sopenharmony_ci */ 629141cc406Sopenharmony_ciSANE_Status 630141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle) 631141cc406Sopenharmony_ci{ 632141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 633141cc406Sopenharmony_ci SANE_Status status; 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci DBG (2, "sane_open: devicename=\"%s\", handle=%p\n", devicename, 636141cc406Sopenharmony_ci (void *) handle); 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_ci if (!initialized) 639141cc406Sopenharmony_ci { 640141cc406Sopenharmony_ci DBG (2, "sane_open: not initialized\n"); 641141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 642141cc406Sopenharmony_ci } 643141cc406Sopenharmony_ci 644141cc406Sopenharmony_ci if (!handle) 645141cc406Sopenharmony_ci { 646141cc406Sopenharmony_ci DBG (2, "sane_open: no handle\n"); 647141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 648141cc406Sopenharmony_ci } 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_ci /* walk the linked list of scanner device until there is a match 651141cc406Sopenharmony_ci * with the device name */ 652141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 653141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 654141cc406Sopenharmony_ci { 655141cc406Sopenharmony_ci DBG (2, "sane_open: devname from list: %s\n", 656141cc406Sopenharmony_ci lexmark_device->sane.name); 657141cc406Sopenharmony_ci if (strcmp (devicename, "") == 0 658141cc406Sopenharmony_ci || strcmp (devicename, "lexmark") == 0 659141cc406Sopenharmony_ci || strcmp (devicename, lexmark_device->sane.name) == 0) 660141cc406Sopenharmony_ci break; 661141cc406Sopenharmony_ci } 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_ci *handle = lexmark_device; 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci if (!lexmark_device) 666141cc406Sopenharmony_ci { 667141cc406Sopenharmony_ci DBG (2, "sane_open: Not a lexmark device\n"); 668141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 669141cc406Sopenharmony_ci } 670141cc406Sopenharmony_ci 671141cc406Sopenharmony_ci status = init_options (lexmark_device); 672141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 673141cc406Sopenharmony_ci return status; 674141cc406Sopenharmony_ci 675141cc406Sopenharmony_ci status = sanei_lexmark_low_open_device (lexmark_device); 676141cc406Sopenharmony_ci DBG (2, "sane_open: end.\n"); 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci return status; 679141cc406Sopenharmony_ci} 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_civoid 682141cc406Sopenharmony_cisane_close (SANE_Handle handle) 683141cc406Sopenharmony_ci{ 684141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ci DBG (2, "sane_close: handle=%p\n", (void *) handle); 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci if (!initialized) 689141cc406Sopenharmony_ci return; 690141cc406Sopenharmony_ci 691141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 692141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 693141cc406Sopenharmony_ci { 694141cc406Sopenharmony_ci if (lexmark_device == handle) 695141cc406Sopenharmony_ci break; 696141cc406Sopenharmony_ci } 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci if (!lexmark_device) 699141cc406Sopenharmony_ci return; 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci sanei_lexmark_low_close_device (lexmark_device); 702141cc406Sopenharmony_ci 703141cc406Sopenharmony_ci return; 704141cc406Sopenharmony_ci} 705141cc406Sopenharmony_ci 706141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 707141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 708141cc406Sopenharmony_ci{ 709141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 710141cc406Sopenharmony_ci 711141cc406Sopenharmony_ci DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n", 712141cc406Sopenharmony_ci (void *) handle, option); 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci if (!initialized) 715141cc406Sopenharmony_ci return NULL; 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci /* Check for valid option number */ 718141cc406Sopenharmony_ci if ((option < 0) || (option >= NUM_OPTIONS)) 719141cc406Sopenharmony_ci return NULL; 720141cc406Sopenharmony_ci 721141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 722141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 723141cc406Sopenharmony_ci { 724141cc406Sopenharmony_ci if (lexmark_device == handle) 725141cc406Sopenharmony_ci break; 726141cc406Sopenharmony_ci } 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci if (!lexmark_device) 729141cc406Sopenharmony_ci return NULL; 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci if (lexmark_device->opt[option].name) 732141cc406Sopenharmony_ci { 733141cc406Sopenharmony_ci DBG (2, "sane_get_option_descriptor: name=%s\n", 734141cc406Sopenharmony_ci lexmark_device->opt[option].name); 735141cc406Sopenharmony_ci } 736141cc406Sopenharmony_ci 737141cc406Sopenharmony_ci return &(lexmark_device->opt[option]); 738141cc406Sopenharmony_ci} 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci/* rebuilds parameters if needed, called each time SANE_INFO_RELOAD_OPTIONS 741141cc406Sopenharmony_ci is set */ 742141cc406Sopenharmony_cistatic void 743141cc406Sopenharmony_cicalc_parameters (Lexmark_Device * lexmark_device) 744141cc406Sopenharmony_ci{ 745141cc406Sopenharmony_ci if (strcmp (lexmark_device->val[OPT_MODE].s, 746141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART) == 0) 747141cc406Sopenharmony_ci { 748141cc406Sopenharmony_ci lexmark_device->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; 749141cc406Sopenharmony_ci } 750141cc406Sopenharmony_ci else 751141cc406Sopenharmony_ci { 752141cc406Sopenharmony_ci lexmark_device->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; 753141cc406Sopenharmony_ci } 754141cc406Sopenharmony_ci 755141cc406Sopenharmony_ci /* changing color mode implies changing gain setting */ 756141cc406Sopenharmony_ci if (lexmark_device->val[OPT_MANUAL_GAIN].w == SANE_TRUE) 757141cc406Sopenharmony_ci { 758141cc406Sopenharmony_ci if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) 759141cc406Sopenharmony_ci != 0) 760141cc406Sopenharmony_ci { 761141cc406Sopenharmony_ci lexmark_device->opt[OPT_GRAY_GAIN].cap &= ~SANE_CAP_INACTIVE; 762141cc406Sopenharmony_ci lexmark_device->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; 763141cc406Sopenharmony_ci lexmark_device->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; 764141cc406Sopenharmony_ci lexmark_device->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; 765141cc406Sopenharmony_ci } 766141cc406Sopenharmony_ci else 767141cc406Sopenharmony_ci { 768141cc406Sopenharmony_ci lexmark_device->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; 769141cc406Sopenharmony_ci lexmark_device->opt[OPT_RED_GAIN].cap &= ~SANE_CAP_INACTIVE; 770141cc406Sopenharmony_ci lexmark_device->opt[OPT_GREEN_GAIN].cap &= ~SANE_CAP_INACTIVE; 771141cc406Sopenharmony_ci lexmark_device->opt[OPT_BLUE_GAIN].cap &= ~SANE_CAP_INACTIVE; 772141cc406Sopenharmony_ci } 773141cc406Sopenharmony_ci } 774141cc406Sopenharmony_ci else 775141cc406Sopenharmony_ci { 776141cc406Sopenharmony_ci lexmark_device->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; 777141cc406Sopenharmony_ci lexmark_device->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; 778141cc406Sopenharmony_ci lexmark_device->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; 779141cc406Sopenharmony_ci lexmark_device->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; 780141cc406Sopenharmony_ci } 781141cc406Sopenharmony_ci} 782141cc406Sopenharmony_ci 783141cc406Sopenharmony_ciSANE_Status 784141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, 785141cc406Sopenharmony_ci void *value, SANE_Int * info) 786141cc406Sopenharmony_ci{ 787141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 788141cc406Sopenharmony_ci SANE_Status status; 789141cc406Sopenharmony_ci SANE_Word w; 790141cc406Sopenharmony_ci 791141cc406Sopenharmony_ci DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", 792141cc406Sopenharmony_ci (void *) handle, option, action, (void *) value, (void *) info); 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci if (!initialized) 795141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 796141cc406Sopenharmony_ci 797141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 798141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 799141cc406Sopenharmony_ci { 800141cc406Sopenharmony_ci if (lexmark_device == handle) 801141cc406Sopenharmony_ci break; 802141cc406Sopenharmony_ci } 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ci if (!lexmark_device) 805141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci if (value == NULL) 808141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 809141cc406Sopenharmony_ci 810141cc406Sopenharmony_ci if (info != NULL) 811141cc406Sopenharmony_ci *info = 0; 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci if (option < 0 || option >= NUM_OPTIONS) 814141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 815141cc406Sopenharmony_ci 816141cc406Sopenharmony_ci if (lexmark_device->opt[option].type == SANE_TYPE_GROUP) 817141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci switch (action) 820141cc406Sopenharmony_ci { 821141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 822141cc406Sopenharmony_ci 823141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) 824141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 825141cc406Sopenharmony_ci if (!(lexmark_device->opt[option].cap & SANE_CAP_AUTOMATIC)) 826141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 827141cc406Sopenharmony_ci break; 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) 832141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci /* Make sure boolean values are only TRUE or FALSE */ 835141cc406Sopenharmony_ci if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) 836141cc406Sopenharmony_ci { 837141cc406Sopenharmony_ci if (! 838141cc406Sopenharmony_ci ((*(SANE_Bool *) value == SANE_FALSE) 839141cc406Sopenharmony_ci || (*(SANE_Bool *) value == SANE_TRUE))) 840141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 841141cc406Sopenharmony_ci } 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci /* Check range constraints */ 844141cc406Sopenharmony_ci if (lexmark_device->opt[option].constraint_type == 845141cc406Sopenharmony_ci SANE_CONSTRAINT_RANGE) 846141cc406Sopenharmony_ci { 847141cc406Sopenharmony_ci status = 848141cc406Sopenharmony_ci sanei_constrain_value (&(lexmark_device->opt[option]), value, 849141cc406Sopenharmony_ci info); 850141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 851141cc406Sopenharmony_ci { 852141cc406Sopenharmony_ci DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n"); 853141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 854141cc406Sopenharmony_ci } 855141cc406Sopenharmony_ci } 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci switch (option) 858141cc406Sopenharmony_ci { 859141cc406Sopenharmony_ci case OPT_NUM_OPTS: 860141cc406Sopenharmony_ci case OPT_RESOLUTION: 861141cc406Sopenharmony_ci lexmark_device->val[option].w = *(SANE_Int *) value; 862141cc406Sopenharmony_ci sane_get_parameters (handle, 0); 863141cc406Sopenharmony_ci break; 864141cc406Sopenharmony_ci case OPT_TL_X: 865141cc406Sopenharmony_ci case OPT_TL_Y: 866141cc406Sopenharmony_ci case OPT_BR_X: 867141cc406Sopenharmony_ci case OPT_BR_Y: 868141cc406Sopenharmony_ci DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value, 869141cc406Sopenharmony_ci lexmark_device->opt[option].name); 870141cc406Sopenharmony_ci lexmark_device->val[option].w = *(SANE_Word *) value; 871141cc406Sopenharmony_ci if (lexmark_device->val[OPT_TL_X].w > 872141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_X].w) 873141cc406Sopenharmony_ci { 874141cc406Sopenharmony_ci w = lexmark_device->val[OPT_TL_X].w; 875141cc406Sopenharmony_ci lexmark_device->val[OPT_TL_X].w = 876141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_X].w; 877141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_X].w = w; 878141cc406Sopenharmony_ci if (info) 879141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 880141cc406Sopenharmony_ci } 881141cc406Sopenharmony_ci if (lexmark_device->val[OPT_TL_Y].w > 882141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_Y].w) 883141cc406Sopenharmony_ci { 884141cc406Sopenharmony_ci w = lexmark_device->val[OPT_TL_Y].w; 885141cc406Sopenharmony_ci lexmark_device->val[OPT_TL_Y].w = 886141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_Y].w; 887141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_Y].w = w; 888141cc406Sopenharmony_ci if (info) 889141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 890141cc406Sopenharmony_ci } 891141cc406Sopenharmony_ci break; 892141cc406Sopenharmony_ci case OPT_THRESHOLD: 893141cc406Sopenharmony_ci lexmark_device->val[option].w = *(SANE_Fixed *) value; 894141cc406Sopenharmony_ci lexmark_device->threshold = 895141cc406Sopenharmony_ci (0xFF * lexmark_device->val[option].w) / 100; 896141cc406Sopenharmony_ci break; 897141cc406Sopenharmony_ci case OPT_PREVIEW: 898141cc406Sopenharmony_ci lexmark_device->val[option].w = *(SANE_Int *) value; 899141cc406Sopenharmony_ci if (*(SANE_Word *) value) 900141cc406Sopenharmony_ci { 901141cc406Sopenharmony_ci lexmark_device->y_dpi = lexmark_device->val[OPT_RESOLUTION].w; 902141cc406Sopenharmony_ci lexmark_device->val[OPT_RESOLUTION].w = 75; 903141cc406Sopenharmony_ci } 904141cc406Sopenharmony_ci else 905141cc406Sopenharmony_ci { 906141cc406Sopenharmony_ci lexmark_device->val[OPT_RESOLUTION].w = lexmark_device->y_dpi; 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci if (info) 909141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 910141cc406Sopenharmony_ci sane_get_parameters (handle, 0); 911141cc406Sopenharmony_ci if (info) 912141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 913141cc406Sopenharmony_ci break; 914141cc406Sopenharmony_ci case OPT_GRAY_GAIN: 915141cc406Sopenharmony_ci case OPT_GREEN_GAIN: 916141cc406Sopenharmony_ci case OPT_RED_GAIN: 917141cc406Sopenharmony_ci case OPT_BLUE_GAIN: 918141cc406Sopenharmony_ci lexmark_device->val[option].w = *(SANE_Word *) value; 919141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 920141cc406Sopenharmony_ci break; 921141cc406Sopenharmony_ci case OPT_MODE: 922141cc406Sopenharmony_ci strcpy (lexmark_device->val[option].s, value); 923141cc406Sopenharmony_ci calc_parameters (lexmark_device); 924141cc406Sopenharmony_ci if (info) 925141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 926141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 927141cc406Sopenharmony_ci case OPT_MANUAL_GAIN: 928141cc406Sopenharmony_ci w = *(SANE_Word *) value; 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci if (w == lexmark_device->val[OPT_MANUAL_GAIN].w) 931141cc406Sopenharmony_ci return SANE_STATUS_GOOD; /* no change */ 932141cc406Sopenharmony_ci 933141cc406Sopenharmony_ci lexmark_device->val[OPT_MANUAL_GAIN].w = w; 934141cc406Sopenharmony_ci calc_parameters (lexmark_device); 935141cc406Sopenharmony_ci if (info) 936141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_OPTIONS; 937141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 938141cc406Sopenharmony_ci } 939141cc406Sopenharmony_ci 940141cc406Sopenharmony_ci if (info != NULL) 941141cc406Sopenharmony_ci *info |= SANE_INFO_RELOAD_PARAMS; 942141cc406Sopenharmony_ci 943141cc406Sopenharmony_ci break; 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 946141cc406Sopenharmony_ci 947141cc406Sopenharmony_ci switch (option) 948141cc406Sopenharmony_ci { 949141cc406Sopenharmony_ci case OPT_NUM_OPTS: 950141cc406Sopenharmony_ci case OPT_RESOLUTION: 951141cc406Sopenharmony_ci case OPT_PREVIEW: 952141cc406Sopenharmony_ci case OPT_MANUAL_GAIN: 953141cc406Sopenharmony_ci case OPT_GRAY_GAIN: 954141cc406Sopenharmony_ci case OPT_GREEN_GAIN: 955141cc406Sopenharmony_ci case OPT_RED_GAIN: 956141cc406Sopenharmony_ci case OPT_BLUE_GAIN: 957141cc406Sopenharmony_ci case OPT_TL_X: 958141cc406Sopenharmony_ci case OPT_TL_Y: 959141cc406Sopenharmony_ci case OPT_BR_X: 960141cc406Sopenharmony_ci case OPT_BR_Y: 961141cc406Sopenharmony_ci *(SANE_Word *) value = lexmark_device->val[option].w; 962141cc406Sopenharmony_ci DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value, 963141cc406Sopenharmony_ci lexmark_device->opt[option].name); 964141cc406Sopenharmony_ci break; 965141cc406Sopenharmony_ci case OPT_THRESHOLD: 966141cc406Sopenharmony_ci *(SANE_Fixed *) value = lexmark_device->val[option].w; 967141cc406Sopenharmony_ci DBG (2, "Option value = %f\n", SANE_UNFIX (*(SANE_Fixed *) value)); 968141cc406Sopenharmony_ci break; 969141cc406Sopenharmony_ci case OPT_MODE: 970141cc406Sopenharmony_ci strcpy (value, lexmark_device->val[option].s); 971141cc406Sopenharmony_ci break; 972141cc406Sopenharmony_ci default: 973141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 974141cc406Sopenharmony_ci } 975141cc406Sopenharmony_ci break; 976141cc406Sopenharmony_ci 977141cc406Sopenharmony_ci default: 978141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 979141cc406Sopenharmony_ci 980141cc406Sopenharmony_ci } 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 983141cc406Sopenharmony_ci} 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci 986141cc406Sopenharmony_ciSANE_Status 987141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 988141cc406Sopenharmony_ci{ 989141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 990141cc406Sopenharmony_ci SANE_Parameters *device_params; 991141cc406Sopenharmony_ci SANE_Int xres, yres, width_px, height_px; 992141cc406Sopenharmony_ci SANE_Int channels, bitsperchannel; 993141cc406Sopenharmony_ci 994141cc406Sopenharmony_ci DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle, 995141cc406Sopenharmony_ci (void *) params); 996141cc406Sopenharmony_ci 997141cc406Sopenharmony_ci if (!initialized) 998141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 999141cc406Sopenharmony_ci 1000141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 1001141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 1002141cc406Sopenharmony_ci { 1003141cc406Sopenharmony_ci if (lexmark_device == handle) 1004141cc406Sopenharmony_ci break; 1005141cc406Sopenharmony_ci } 1006141cc406Sopenharmony_ci 1007141cc406Sopenharmony_ci if (!lexmark_device) 1008141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci yres = lexmark_device->val[OPT_RESOLUTION].w; 1011141cc406Sopenharmony_ci if (yres == 1200) 1012141cc406Sopenharmony_ci xres = 600; 1013141cc406Sopenharmony_ci else 1014141cc406Sopenharmony_ci xres = yres; 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci /* 24 bit colour = 8 bits/channel for each of the RGB channels */ 1017141cc406Sopenharmony_ci channels = 3; 1018141cc406Sopenharmony_ci bitsperchannel = 8; 1019141cc406Sopenharmony_ci 1020141cc406Sopenharmony_ci /* If not color there is only 1 channel */ 1021141cc406Sopenharmony_ci if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) 1022141cc406Sopenharmony_ci != 0) 1023141cc406Sopenharmony_ci { 1024141cc406Sopenharmony_ci channels = 1; 1025141cc406Sopenharmony_ci bitsperchannel = 8; 1026141cc406Sopenharmony_ci } 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci /* geometry in pixels */ 1029141cc406Sopenharmony_ci width_px = 1030141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w; 1031141cc406Sopenharmony_ci height_px = 1032141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_Y].w - lexmark_device->val[OPT_TL_Y].w; 1033141cc406Sopenharmony_ci DBG (7, "sane_get_parameters: tl=(%d,%d) br=(%d,%d)\n", 1034141cc406Sopenharmony_ci lexmark_device->val[OPT_TL_X].w, lexmark_device->val[OPT_TL_Y].w, 1035141cc406Sopenharmony_ci lexmark_device->val[OPT_BR_X].w, lexmark_device->val[OPT_BR_Y].w); 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci /* we must tell the front end the bitsperchannel for lineart is really */ 1039141cc406Sopenharmony_ci /* only 1, so it can calculate the correct image size */ 1040141cc406Sopenharmony_ci /* If not color there is only 1 channel */ 1041141cc406Sopenharmony_ci if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) 1042141cc406Sopenharmony_ci == 0) 1043141cc406Sopenharmony_ci { 1044141cc406Sopenharmony_ci bitsperchannel = 1; 1045141cc406Sopenharmony_ci } 1046141cc406Sopenharmony_ci 1047141cc406Sopenharmony_ci device_params = &(lexmark_device->params); 1048141cc406Sopenharmony_ci device_params->format = SANE_FRAME_RGB; 1049141cc406Sopenharmony_ci if (channels == 1) 1050141cc406Sopenharmony_ci device_params->format = SANE_FRAME_GRAY; 1051141cc406Sopenharmony_ci device_params->last_frame = SANE_TRUE; 1052141cc406Sopenharmony_ci device_params->lines = (height_px * yres) / 600; 1053141cc406Sopenharmony_ci device_params->depth = bitsperchannel; 1054141cc406Sopenharmony_ci device_params->pixels_per_line = (width_px * xres) / 600; 1055141cc406Sopenharmony_ci /* we always read an even number of sensor pixels */ 1056141cc406Sopenharmony_ci if (device_params->pixels_per_line & 1) 1057141cc406Sopenharmony_ci device_params->pixels_per_line++; 1058141cc406Sopenharmony_ci 1059141cc406Sopenharmony_ci /* data_size is the size transferred from the scanner to the backend */ 1060141cc406Sopenharmony_ci /* therefore bitsperchannel is the same for gray and lineart */ 1061141cc406Sopenharmony_ci /* note: bytes_per_line has been divided by 8 in lineart mode */ 1062141cc406Sopenharmony_ci lexmark_device->data_size = 1063141cc406Sopenharmony_ci channels * device_params->pixels_per_line * device_params->lines; 1064141cc406Sopenharmony_ci 1065141cc406Sopenharmony_ci if (bitsperchannel == 1) 1066141cc406Sopenharmony_ci { 1067141cc406Sopenharmony_ci device_params->bytes_per_line = 1068141cc406Sopenharmony_ci (SANE_Int) ((7 + device_params->pixels_per_line) / 8); 1069141cc406Sopenharmony_ci } 1070141cc406Sopenharmony_ci else 1071141cc406Sopenharmony_ci { 1072141cc406Sopenharmony_ci device_params->bytes_per_line = 1073141cc406Sopenharmony_ci (SANE_Int) (channels * device_params->pixels_per_line); 1074141cc406Sopenharmony_ci } 1075141cc406Sopenharmony_ci DBG (2, "sane_get_parameters: Data size determined as %ld\n", 1076141cc406Sopenharmony_ci lexmark_device->data_size); 1077141cc406Sopenharmony_ci 1078141cc406Sopenharmony_ci DBG (2, "sane_get_parameters: \n"); 1079141cc406Sopenharmony_ci if (device_params->format == SANE_FRAME_GRAY) 1080141cc406Sopenharmony_ci DBG (2, " format: SANE_FRAME_GRAY\n"); 1081141cc406Sopenharmony_ci else if (device_params->format == SANE_FRAME_RGB) 1082141cc406Sopenharmony_ci DBG (2, " format: SANE_FRAME_RGB\n"); 1083141cc406Sopenharmony_ci else 1084141cc406Sopenharmony_ci DBG (2, " format: UNKNOWN\n"); 1085141cc406Sopenharmony_ci if (device_params->last_frame == SANE_TRUE) 1086141cc406Sopenharmony_ci DBG (2, " last_frame: TRUE\n"); 1087141cc406Sopenharmony_ci else 1088141cc406Sopenharmony_ci DBG (2, " last_frame: FALSE\n"); 1089141cc406Sopenharmony_ci DBG (2, " lines %d\n", device_params->lines); 1090141cc406Sopenharmony_ci DBG (2, " depth %d\n", device_params->depth); 1091141cc406Sopenharmony_ci DBG (2, " pixels_per_line %d\n", device_params->pixels_per_line); 1092141cc406Sopenharmony_ci DBG (2, " bytes_per_line %d\n", device_params->bytes_per_line); 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci if (params != 0) 1095141cc406Sopenharmony_ci { 1096141cc406Sopenharmony_ci params->format = device_params->format; 1097141cc406Sopenharmony_ci params->last_frame = device_params->last_frame; 1098141cc406Sopenharmony_ci params->lines = device_params->lines; 1099141cc406Sopenharmony_ci params->depth = device_params->depth; 1100141cc406Sopenharmony_ci params->pixels_per_line = device_params->pixels_per_line; 1101141cc406Sopenharmony_ci params->bytes_per_line = device_params->bytes_per_line; 1102141cc406Sopenharmony_ci } 1103141cc406Sopenharmony_ci 1104141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1105141cc406Sopenharmony_ci} 1106141cc406Sopenharmony_ci 1107141cc406Sopenharmony_ciSANE_Status 1108141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1109141cc406Sopenharmony_ci{ 1110141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 1111141cc406Sopenharmony_ci SANE_Int offset; 1112141cc406Sopenharmony_ci SANE_Status status; 1113141cc406Sopenharmony_ci int resolution; 1114141cc406Sopenharmony_ci 1115141cc406Sopenharmony_ci DBG (2, "sane_start: handle=%p\n", (void *) handle); 1116141cc406Sopenharmony_ci 1117141cc406Sopenharmony_ci if (!initialized) 1118141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1119141cc406Sopenharmony_ci 1120141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 1121141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 1122141cc406Sopenharmony_ci { 1123141cc406Sopenharmony_ci if (lexmark_device == handle) 1124141cc406Sopenharmony_ci break; 1125141cc406Sopenharmony_ci } 1126141cc406Sopenharmony_ci 1127141cc406Sopenharmony_ci sane_get_parameters (handle, 0); 1128141cc406Sopenharmony_ci 1129141cc406Sopenharmony_ci if ((lexmark_device->params.lines == 0) || 1130141cc406Sopenharmony_ci (lexmark_device->params.pixels_per_line == 0) || 1131141cc406Sopenharmony_ci (lexmark_device->params.bytes_per_line == 0)) 1132141cc406Sopenharmony_ci { 1133141cc406Sopenharmony_ci DBG (2, "sane_start: \n"); 1134141cc406Sopenharmony_ci DBG (2, " ERROR: Zero size encountered in:\n"); 1135141cc406Sopenharmony_ci DBG (2, 1136141cc406Sopenharmony_ci " number of lines, bytes per line, or pixels per line\n"); 1137141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1138141cc406Sopenharmony_ci } 1139141cc406Sopenharmony_ci 1140141cc406Sopenharmony_ci lexmark_device->device_cancelled = SANE_FALSE; 1141141cc406Sopenharmony_ci lexmark_device->data_ctr = 0; 1142141cc406Sopenharmony_ci lexmark_device->eof = SANE_FALSE; 1143141cc406Sopenharmony_ci 1144141cc406Sopenharmony_ci 1145141cc406Sopenharmony_ci /* Need this cancel_ctr to determine how many times sane_cancel is called 1146141cc406Sopenharmony_ci since it is called more than once. */ 1147141cc406Sopenharmony_ci lexmark_device->cancel_ctr = 0; 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci /* Find Home */ 1150141cc406Sopenharmony_ci if (sanei_lexmark_low_search_home_fwd (lexmark_device)) 1151141cc406Sopenharmony_ci { 1152141cc406Sopenharmony_ci DBG (2, "sane_start: Scan head initially at home position\n"); 1153141cc406Sopenharmony_ci } 1154141cc406Sopenharmony_ci else 1155141cc406Sopenharmony_ci { 1156141cc406Sopenharmony_ci /* We may have been rewound too far, so move forward the distance from 1157141cc406Sopenharmony_ci the edge to the home position */ 1158141cc406Sopenharmony_ci sanei_lexmark_low_move_fwd (0x01a8, lexmark_device, 1159141cc406Sopenharmony_ci lexmark_device->shadow_regs); 1160141cc406Sopenharmony_ci 1161141cc406Sopenharmony_ci /* Scan backwards until we find home */ 1162141cc406Sopenharmony_ci sanei_lexmark_low_search_home_bwd (lexmark_device); 1163141cc406Sopenharmony_ci } 1164141cc406Sopenharmony_ci /* do calibration before offset detection , use sensor max dpi, not motor's one */ 1165141cc406Sopenharmony_ci resolution = lexmark_device->val[OPT_RESOLUTION].w; 1166141cc406Sopenharmony_ci if (resolution > 600) 1167141cc406Sopenharmony_ci { 1168141cc406Sopenharmony_ci resolution = 600; 1169141cc406Sopenharmony_ci } 1170141cc406Sopenharmony_ci 1171141cc406Sopenharmony_ci 1172141cc406Sopenharmony_ci sanei_lexmark_low_set_scan_regs (lexmark_device, resolution, 0, SANE_FALSE); 1173141cc406Sopenharmony_ci status = sanei_lexmark_low_calibration (lexmark_device); 1174141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1175141cc406Sopenharmony_ci { 1176141cc406Sopenharmony_ci DBG (1, "sane_start: calibration failed : %s ! \n", 1177141cc406Sopenharmony_ci sane_strstatus (status)); 1178141cc406Sopenharmony_ci return status; 1179141cc406Sopenharmony_ci } 1180141cc406Sopenharmony_ci 1181141cc406Sopenharmony_ci /* At this point we're somewhere in the dot. We need to read a number of 1182141cc406Sopenharmony_ci lines greater than the diameter of the dot and determine how many lines 1183141cc406Sopenharmony_ci past the dot we've gone. We then use this information to see how far the 1184141cc406Sopenharmony_ci scan head must move before starting the scan. */ 1185141cc406Sopenharmony_ci /* offset is in 600 dpi unit */ 1186141cc406Sopenharmony_ci offset = sanei_lexmark_low_find_start_line (lexmark_device); 1187141cc406Sopenharmony_ci DBG (7, "start line offset=%d\n", offset); 1188141cc406Sopenharmony_ci 1189141cc406Sopenharmony_ci /* Set the shadow registers for scan with the options (resolution, mode, 1190141cc406Sopenharmony_ci size) set in the front end. Pass the offset so we can get the vert. 1191141cc406Sopenharmony_ci start. */ 1192141cc406Sopenharmony_ci sanei_lexmark_low_set_scan_regs (lexmark_device, 1193141cc406Sopenharmony_ci lexmark_device->val[OPT_RESOLUTION].w, 1194141cc406Sopenharmony_ci offset, SANE_TRUE); 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci if (sanei_lexmark_low_start_scan (lexmark_device) == SANE_STATUS_GOOD) 1197141cc406Sopenharmony_ci { 1198141cc406Sopenharmony_ci DBG (2, "sane_start: scan started\n"); 1199141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1200141cc406Sopenharmony_ci } 1201141cc406Sopenharmony_ci else 1202141cc406Sopenharmony_ci { 1203141cc406Sopenharmony_ci lexmark_device->device_cancelled = SANE_TRUE; 1204141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1205141cc406Sopenharmony_ci } 1206141cc406Sopenharmony_ci} 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_ci 1209141cc406Sopenharmony_ciSANE_Status 1210141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data, 1211141cc406Sopenharmony_ci SANE_Int max_length, SANE_Int * length) 1212141cc406Sopenharmony_ci{ 1213141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 1214141cc406Sopenharmony_ci long bytes_read; 1215141cc406Sopenharmony_ci 1216141cc406Sopenharmony_ci DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", 1217141cc406Sopenharmony_ci (void *) handle, (void *) data, max_length, (void *) length); 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci if (!initialized) 1220141cc406Sopenharmony_ci { 1221141cc406Sopenharmony_ci DBG (2, "sane_read: Not initialized\n"); 1222141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1223141cc406Sopenharmony_ci } 1224141cc406Sopenharmony_ci 1225141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 1226141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 1227141cc406Sopenharmony_ci { 1228141cc406Sopenharmony_ci if (lexmark_device == handle) 1229141cc406Sopenharmony_ci break; 1230141cc406Sopenharmony_ci } 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci if (lexmark_device->device_cancelled) 1233141cc406Sopenharmony_ci { 1234141cc406Sopenharmony_ci DBG (2, "sane_read: Device was cancelled\n"); 1235141cc406Sopenharmony_ci /* We don't know how far we've gone, so search for home. */ 1236141cc406Sopenharmony_ci sanei_lexmark_low_search_home_bwd (lexmark_device); 1237141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1238141cc406Sopenharmony_ci } 1239141cc406Sopenharmony_ci 1240141cc406Sopenharmony_ci if (!length) 1241141cc406Sopenharmony_ci { 1242141cc406Sopenharmony_ci DBG (2, "sane_read: NULL length pointer\n"); 1243141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1244141cc406Sopenharmony_ci } 1245141cc406Sopenharmony_ci 1246141cc406Sopenharmony_ci *length = 0; 1247141cc406Sopenharmony_ci 1248141cc406Sopenharmony_ci if (lexmark_device->eof) 1249141cc406Sopenharmony_ci { 1250141cc406Sopenharmony_ci DBG (2, "sane_read: Trying to read past EOF\n"); 1251141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1252141cc406Sopenharmony_ci } 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_ci if (!data) 1255141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1256141cc406Sopenharmony_ci 1257141cc406Sopenharmony_ci bytes_read = sanei_lexmark_low_read_scan_data (data, max_length, 1258141cc406Sopenharmony_ci lexmark_device); 1259141cc406Sopenharmony_ci if (bytes_read < 0) 1260141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 1261141cc406Sopenharmony_ci else if (bytes_read == 0) 1262141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1263141cc406Sopenharmony_ci else 1264141cc406Sopenharmony_ci { 1265141cc406Sopenharmony_ci *length = bytes_read; 1266141cc406Sopenharmony_ci lexmark_device->data_ctr += bytes_read; 1267141cc406Sopenharmony_ci } 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1270141cc406Sopenharmony_ci} 1271141cc406Sopenharmony_ci 1272141cc406Sopenharmony_civoid 1273141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 1274141cc406Sopenharmony_ci{ 1275141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 1276141cc406Sopenharmony_ci/* ssize_t bytes_read; */ 1277141cc406Sopenharmony_ci DBG (2, "sane_cancel: handle = %p\n", (void *) handle); 1278141cc406Sopenharmony_ci 1279141cc406Sopenharmony_ci if (!initialized) 1280141cc406Sopenharmony_ci return; 1281141cc406Sopenharmony_ci 1282141cc406Sopenharmony_ci 1283141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 1284141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 1285141cc406Sopenharmony_ci { 1286141cc406Sopenharmony_ci if (lexmark_device == handle) 1287141cc406Sopenharmony_ci break; 1288141cc406Sopenharmony_ci } 1289141cc406Sopenharmony_ci 1290141cc406Sopenharmony_ci /*If sane_cancel called more than once, return */ 1291141cc406Sopenharmony_ci if (++lexmark_device->cancel_ctr > 1) 1292141cc406Sopenharmony_ci return; 1293141cc406Sopenharmony_ci 1294141cc406Sopenharmony_ci /* Set the device flag so the next call to sane_read() can stop the scan. */ 1295141cc406Sopenharmony_ci lexmark_device->device_cancelled = SANE_TRUE; 1296141cc406Sopenharmony_ci 1297141cc406Sopenharmony_ci return; 1298141cc406Sopenharmony_ci} 1299141cc406Sopenharmony_ci 1300141cc406Sopenharmony_ciSANE_Status 1301141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 1302141cc406Sopenharmony_ci{ 1303141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 1304141cc406Sopenharmony_ci 1305141cc406Sopenharmony_ci DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", 1306141cc406Sopenharmony_ci (void *) handle, non_blocking); 1307141cc406Sopenharmony_ci 1308141cc406Sopenharmony_ci if (!initialized) 1309141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1310141cc406Sopenharmony_ci 1311141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 1312141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 1313141cc406Sopenharmony_ci { 1314141cc406Sopenharmony_ci if (lexmark_device == handle) 1315141cc406Sopenharmony_ci break; 1316141cc406Sopenharmony_ci } 1317141cc406Sopenharmony_ci 1318141cc406Sopenharmony_ci if (non_blocking) 1319141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1320141cc406Sopenharmony_ci 1321141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1322141cc406Sopenharmony_ci} 1323141cc406Sopenharmony_ci 1324141cc406Sopenharmony_ciSANE_Status 1325141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd) 1326141cc406Sopenharmony_ci{ 1327141cc406Sopenharmony_ci Lexmark_Device *lexmark_device; 1328141cc406Sopenharmony_ci 1329141cc406Sopenharmony_ci DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", (void *) handle, 1330141cc406Sopenharmony_ci fd ? "!=" : "="); 1331141cc406Sopenharmony_ci 1332141cc406Sopenharmony_ci if (!initialized) 1333141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci for (lexmark_device = first_lexmark_device; lexmark_device; 1336141cc406Sopenharmony_ci lexmark_device = lexmark_device->next) 1337141cc406Sopenharmony_ci { 1338141cc406Sopenharmony_ci if (lexmark_device == handle) 1339141cc406Sopenharmony_ci break; 1340141cc406Sopenharmony_ci } 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 1343141cc406Sopenharmony_ci} 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci/***************************** END OF SANE API ****************************/ 1346141cc406Sopenharmony_ci/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ 1347