1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2007-2013 stef.dev@free.fr 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This file is part of the SANE package. 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 8141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 9141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 10141cc406Sopenharmony_ci License, or (at your option) any later version. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 13141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 14141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15141cc406Sopenharmony_ci General Public License for more details. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 18141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 21141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 24141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 25141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 26141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 27141cc406Sopenharmony_ci account of linking the SANE library code into it. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 30141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 31141cc406Sopenharmony_ci License. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 34141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 35141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 38141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 39141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci -------------------------------------------------------------------------- 42141cc406Sopenharmony_ci 43141cc406Sopenharmony_ci SANE FLOW DIAGRAM 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci - sane_init() : initialize backend, attach scanners 46141cc406Sopenharmony_ci . - sane_get_devices() : query list of scanner devices 47141cc406Sopenharmony_ci . - sane_open() : open a particular scanner device, adding a handle 48141cc406Sopenharmony_ci to the opened device 49141cc406Sopenharmony_ci . . - sane_set_io_mode : set blocking mode 50141cc406Sopenharmony_ci . . - sane_get_select_fd : get scanner fd 51141cc406Sopenharmony_ci . . - sane_get_option_descriptor() : get option information 52141cc406Sopenharmony_ci . . - sane_control_option() : change option values 53141cc406Sopenharmony_ci . . 54141cc406Sopenharmony_ci . . - sane_start() : start image acquisition 55141cc406Sopenharmony_ci . . - sane_get_parameters() : returns actual scan parameters 56141cc406Sopenharmony_ci . . - sane_read() : read image data 57141cc406Sopenharmony_ci . . 58141cc406Sopenharmony_ci . . - sane_cancel() : cancel operation 59141cc406Sopenharmony_ci . - sane_close() : close opened scanner device, freeing scanner handle 60141cc406Sopenharmony_ci - sane_exit() : terminate use of backend, freeing all resources for attached 61141cc406Sopenharmony_ci devices 62141cc406Sopenharmony_ci 63141cc406Sopenharmony_ci BACKEND USB locking policy 64141cc406Sopenharmony_ci - interface is released at the end of sane_open() to allow 65141cc406Sopenharmony_ci multiple usage by fronteds 66141cc406Sopenharmony_ci - if free, interface is claimed at sane_start(), and held until 67141cc406Sopenharmony_ci sane_cancel() is called 68141cc406Sopenharmony_ci - if free interface is claimed then released just during the access 69141cc406Sopenharmony_ci to buttons registers 70141cc406Sopenharmony_ci*/ 71141cc406Sopenharmony_ci 72141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_ci#include "../include/sane/config.h" 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci#include <errno.h> 77141cc406Sopenharmony_ci#include <fcntl.h> 78141cc406Sopenharmony_ci#include <limits.h> 79141cc406Sopenharmony_ci#include <math.h> 80141cc406Sopenharmony_ci#include <signal.h> 81141cc406Sopenharmony_ci#include <stdio.h> 82141cc406Sopenharmony_ci#include <stdlib.h> 83141cc406Sopenharmony_ci#include <string.h> 84141cc406Sopenharmony_ci#include <ctype.h> 85141cc406Sopenharmony_ci#include <time.h> 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_ci#include <sys/types.h> 88141cc406Sopenharmony_ci#include <unistd.h> 89141cc406Sopenharmony_ci#ifdef HAVE_LIBC_H 90141cc406Sopenharmony_ci# include <libc.h> 91141cc406Sopenharmony_ci#endif 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci#include "../include/sane/sane.h" 94141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 95141cc406Sopenharmony_ci#include "../include/sane/saneopts.h" 96141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 97141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 98141cc406Sopenharmony_ci 99141cc406Sopenharmony_ci#define DARK_TARGET 3.1 /* 3.5 target average for dark calibration */ 100141cc406Sopenharmony_ci#define DARK_MARGIN 0.3 /* acceptable margin for dark average */ 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci#define OFFSET_TARGET 3.5 /* target average for offset calibration */ 103141cc406Sopenharmony_ci#define OFFSET_MARGIN 0.3 /* acceptable margin for offset average */ 104141cc406Sopenharmony_ci 105141cc406Sopenharmony_ci#define RED_GAIN_TARGET 170 /* target average for gain calibration for blue color */ 106141cc406Sopenharmony_ci#define GREEN_GAIN_TARGET 170 /* target average for gain calibration for blue color */ 107141cc406Sopenharmony_ci#define BLUE_GAIN_TARGET 180 /* target average for gain calibration for blue color */ 108141cc406Sopenharmony_ci#define GAIN_MARGIN 2 /* acceptable margin for gain average */ 109141cc406Sopenharmony_ci 110141cc406Sopenharmony_ci#define MARGIN_LEVEL 128 /* white level for margin detection */ 111141cc406Sopenharmony_ci 112141cc406Sopenharmony_ci/* width used for calibration */ 113141cc406Sopenharmony_ci#define CALIBRATION_WIDTH 637 114141cc406Sopenharmony_ci 115141cc406Sopenharmony_ci/* data size for calibration: one RGB line*/ 116141cc406Sopenharmony_ci#define CALIBRATION_SIZE CALIBRATION_WIDTH*3 117141cc406Sopenharmony_ci 118141cc406Sopenharmony_ci/* #define FAST_INIT 1 */ 119141cc406Sopenharmony_ci 120141cc406Sopenharmony_ci#define BUILD 2401 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ci#define MOVE_DPI 100 123141cc406Sopenharmony_ci 124141cc406Sopenharmony_ci#include "rts8891.h" 125141cc406Sopenharmony_ci#include "rts88xx_lib.h" 126141cc406Sopenharmony_ci#include "rts8891_low.c" 127141cc406Sopenharmony_ci#include "rts8891_devices.c" 128141cc406Sopenharmony_ci 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci#define DEEP_DEBUG 1 131141cc406Sopenharmony_ci 132141cc406Sopenharmony_ci/** 133141cc406Sopenharmony_ci * Pointer to the first Rts8891_Session in the linked list of 134141cc406Sopenharmony_ci * opened device. Sessions are inserted here on sane_open() and 135141cc406Sopenharmony_ci * removed on sane_close(). 136141cc406Sopenharmony_ci */ 137141cc406Sopenharmony_cistatic Rts8891_Session *first_handle = NULL; 138141cc406Sopenharmony_ci 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_ci/* pointer to the first device attached to the backend 141141cc406Sopenharmony_ci * the same device may be opened several time 142141cc406Sopenharmony_ci * entry are inserted here by attach_rts8891 */ 143141cc406Sopenharmony_cistatic Rts8891_Device *first_device = NULL; 144141cc406Sopenharmony_cistatic SANE_Int num_devices = 0; 145141cc406Sopenharmony_ci 146141cc406Sopenharmony_ci/* 147141cc406Sopenharmony_ci * needed by sane_get_devices 148141cc406Sopenharmony_ci */ 149141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0; 150141cc406Sopenharmony_ci 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = { 153141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_COLOR, 154141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_GRAY, 155141cc406Sopenharmony_ci SANE_VALUE_SCAN_MODE_LINEART, 156141cc406Sopenharmony_ci 0 157141cc406Sopenharmony_ci}; 158141cc406Sopenharmony_ci 159141cc406Sopenharmony_cistatic SANE_Range x_range = { 160141cc406Sopenharmony_ci SANE_FIX (0.0), /* minimum */ 161141cc406Sopenharmony_ci SANE_FIX (216.0), /* maximum */ 162141cc406Sopenharmony_ci SANE_FIX (0.0) /* quantization */ 163141cc406Sopenharmony_ci}; 164141cc406Sopenharmony_ci 165141cc406Sopenharmony_cistatic SANE_Range y_range = { 166141cc406Sopenharmony_ci SANE_FIX (0.0), /* minimum */ 167141cc406Sopenharmony_ci SANE_FIX (299.0), /* maximum */ 168141cc406Sopenharmony_ci SANE_FIX (0.0) /* no quantization */ 169141cc406Sopenharmony_ci}; 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci/* model number ranges from 0 to 2, must be changed if 172141cc406Sopenharmony_ci * Rts8891_USB_Device_Entry changes */ 173141cc406Sopenharmony_cistatic const SANE_Range model_range = { 174141cc406Sopenharmony_ci 0, /* minimum */ 175141cc406Sopenharmony_ci 2, /* maximum */ 176141cc406Sopenharmony_ci 0 /* no quantization */ 177141cc406Sopenharmony_ci}; 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci/* sensor number ranges from 0 to SENSOR_TYPE_MAX, must be changed if */ 180141cc406Sopenharmony_cistatic const SANE_Range sensor_range = { 181141cc406Sopenharmony_ci 0, /* minimum */ 182141cc406Sopenharmony_ci SENSOR_TYPE_MAX, /* maximum */ 183141cc406Sopenharmony_ci 0 /* no quantization */ 184141cc406Sopenharmony_ci}; 185141cc406Sopenharmony_ci 186141cc406Sopenharmony_cistatic const SANE_Range u8_range = { 187141cc406Sopenharmony_ci 0, /* minimum */ 188141cc406Sopenharmony_ci 255, /* maximum */ 189141cc406Sopenharmony_ci 0 /* no quantization */ 190141cc406Sopenharmony_ci}; 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_cistatic const SANE_Range threshold_percentage_range = { 193141cc406Sopenharmony_ci SANE_FIX (0), /* minimum */ 194141cc406Sopenharmony_ci SANE_FIX (100), /* maximum */ 195141cc406Sopenharmony_ci SANE_FIX (1) /* quantization */ 196141cc406Sopenharmony_ci}; 197141cc406Sopenharmony_ci 198141cc406Sopenharmony_cistatic size_t 199141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[]) 200141cc406Sopenharmony_ci{ 201141cc406Sopenharmony_ci size_t size, max_size = 0; 202141cc406Sopenharmony_ci SANE_Int i; 203141cc406Sopenharmony_ci 204141cc406Sopenharmony_ci for (i = 0; strings[i]; ++i) 205141cc406Sopenharmony_ci { 206141cc406Sopenharmony_ci size = strlen (strings[i]) + 1; 207141cc406Sopenharmony_ci if (size > max_size) 208141cc406Sopenharmony_ci max_size = size; 209141cc406Sopenharmony_ci } 210141cc406Sopenharmony_ci return max_size; 211141cc406Sopenharmony_ci} 212141cc406Sopenharmony_ci 213141cc406Sopenharmony_ci /**> placeholders for decoded configuration values */ 214141cc406Sopenharmony_cistatic Rts8891_Config rtscfg; 215141cc406Sopenharmony_ci 216141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 217141cc406Sopenharmony_cistatic SANE_Status probe_rts8891_devices (void); 218141cc406Sopenharmony_cistatic SANE_Status config_attach_rts8891 (SANEI_Config * config, 219141cc406Sopenharmony_ci const char *devname, void *data); 220141cc406Sopenharmony_cistatic SANE_Status attach_rts8891 (const char *name); 221141cc406Sopenharmony_cistatic SANE_Status set_lamp_brightness (struct Rts8891_Device *dev, 222141cc406Sopenharmony_ci int level); 223141cc406Sopenharmony_cistatic SANE_Status init_options (struct Rts8891_Session *session); 224141cc406Sopenharmony_ci#ifndef FAST_INIT 225141cc406Sopenharmony_cistatic SANE_Status init_device (struct Rts8891_Device *dev); 226141cc406Sopenharmony_ci#else 227141cc406Sopenharmony_cistatic SANE_Status detect_device (struct Rts8891_Device *dev); 228141cc406Sopenharmony_cistatic SANE_Status initialize_device (struct Rts8891_Device *dev); 229141cc406Sopenharmony_ci#endif 230141cc406Sopenharmony_cistatic SANE_Status init_lamp (struct Rts8891_Device *dev); 231141cc406Sopenharmony_cistatic SANE_Status find_origin (struct Rts8891_Device *dev, 232141cc406Sopenharmony_ci SANE_Bool * changed); 233141cc406Sopenharmony_cistatic SANE_Status find_margin (struct Rts8891_Device *dev); 234141cc406Sopenharmony_cistatic SANE_Status dark_calibration (struct Rts8891_Device *dev, int mode, 235141cc406Sopenharmony_ci int light); 236141cc406Sopenharmony_cistatic SANE_Status gain_calibration (struct Rts8891_Device *dev, int mode, 237141cc406Sopenharmony_ci int light); 238141cc406Sopenharmony_cistatic SANE_Status offset_calibration (struct Rts8891_Device *dev, int mode, 239141cc406Sopenharmony_ci int light); 240141cc406Sopenharmony_cistatic SANE_Status shading_calibration (struct Rts8891_Device *dev, 241141cc406Sopenharmony_ci SANE_Bool color, int mode, int light); 242141cc406Sopenharmony_cistatic SANE_Status send_calibration_data (struct Rts8891_Session *session); 243141cc406Sopenharmony_cistatic SANE_Status write_scan_registers (struct Rts8891_Session *session); 244141cc406Sopenharmony_cistatic SANE_Status read_data (struct Rts8891_Session *session, 245141cc406Sopenharmony_ci SANE_Byte * dest, SANE_Int length); 246141cc406Sopenharmony_cistatic SANE_Status compute_parameters (struct Rts8891_Session *session); 247141cc406Sopenharmony_cistatic SANE_Status move_to_scan_area (struct Rts8891_Session *session); 248141cc406Sopenharmony_cistatic SANE_Status park_head (struct Rts8891_Device *dev, SANE_Bool wait); 249141cc406Sopenharmony_cistatic SANE_Status update_button_status (struct Rts8891_Session *session); 250141cc406Sopenharmony_cistatic SANE_Status set_lamp_state (struct Rts8891_Session *session, int on); 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_ci 253141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 254141cc406Sopenharmony_ci/* writes gray data to a pnm file */ 255141cc406Sopenharmony_cistatic void 256141cc406Sopenharmony_ciwrite_gray_data (unsigned char *image, char *name, SANE_Int width, 257141cc406Sopenharmony_ci SANE_Int height) 258141cc406Sopenharmony_ci{ 259141cc406Sopenharmony_ci FILE *fdbg = NULL; 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci fdbg = fopen (name, "wb"); 262141cc406Sopenharmony_ci if (fdbg == NULL) 263141cc406Sopenharmony_ci return; 264141cc406Sopenharmony_ci fprintf (fdbg, "P5\n%d %d\n255\n", width, height); 265141cc406Sopenharmony_ci fwrite (image, width, height, fdbg); 266141cc406Sopenharmony_ci fclose (fdbg); 267141cc406Sopenharmony_ci} 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 270141cc406Sopenharmony_ci/* writes rgb data to a pnm file */ 271141cc406Sopenharmony_cistatic void 272141cc406Sopenharmony_ciwrite_rgb_data (char *name, unsigned char *image, SANE_Int width, 273141cc406Sopenharmony_ci SANE_Int height) 274141cc406Sopenharmony_ci{ 275141cc406Sopenharmony_ci FILE *fdbg = NULL; 276141cc406Sopenharmony_ci 277141cc406Sopenharmony_ci fdbg = fopen (name, "wb"); 278141cc406Sopenharmony_ci if (fdbg == NULL) 279141cc406Sopenharmony_ci return; 280141cc406Sopenharmony_ci fprintf (fdbg, "P6\n%d %d\n255\n", width, height); 281141cc406Sopenharmony_ci fwrite (image, width * 3, height, fdbg); 282141cc406Sopenharmony_ci fclose (fdbg); 283141cc406Sopenharmony_ci} 284141cc406Sopenharmony_ci 285141cc406Sopenharmony_ci/* ------------------------------------------------------------------------- */ 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci/* 288141cc406Sopenharmony_ci * SANE Interface 289141cc406Sopenharmony_ci */ 290141cc406Sopenharmony_ci 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci/** 293141cc406Sopenharmony_ci * Called by SANE initially. 294141cc406Sopenharmony_ci * 295141cc406Sopenharmony_ci * From the SANE spec: 296141cc406Sopenharmony_ci * This function must be called before any other SANE function can be 297141cc406Sopenharmony_ci * called. The behavior of a SANE backend is undefined if this 298141cc406Sopenharmony_ci * function is not called first. The version code of the backend is 299141cc406Sopenharmony_ci * returned in the value pointed to by version_code. If that pointer 300141cc406Sopenharmony_ci * is NULL, no version code is returned. Argument authorize is either 301141cc406Sopenharmony_ci * a pointer to a function that is invoked when the backend requires 302141cc406Sopenharmony_ci * authentication for a specific resource or NULL if the frontend does 303141cc406Sopenharmony_ci * not support authentication. 304141cc406Sopenharmony_ci */ 305141cc406Sopenharmony_ciSANE_Status 306141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) 307141cc406Sopenharmony_ci{ 308141cc406Sopenharmony_ci SANE_Status status; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci (void) authorize; /* get rid of compiler warning */ 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci /* init ASIC libraries */ 313141cc406Sopenharmony_ci sanei_rts88xx_lib_init (); 314141cc406Sopenharmony_ci rts8891_low_init (); 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_ci /* init backend debug */ 317141cc406Sopenharmony_ci DBG_INIT (); 318141cc406Sopenharmony_ci DBG (DBG_info, "SANE Rts8891 backend version %d.%d-%d\n", 319141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 320141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: start\n"); 321141cc406Sopenharmony_ci 322141cc406Sopenharmony_ci if (version_code) 323141cc406Sopenharmony_ci *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci /* cold-plugging case : probe for already plugged devices */ 326141cc406Sopenharmony_ci status = probe_rts8891_devices (); 327141cc406Sopenharmony_ci 328141cc406Sopenharmony_ci DBG (DBG_proc, "sane_init: exit\n"); 329141cc406Sopenharmony_ci return status; 330141cc406Sopenharmony_ci} 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci/** 334141cc406Sopenharmony_ci * Called by SANE to find out about supported devices. 335141cc406Sopenharmony_ci * 336141cc406Sopenharmony_ci * From the SANE spec: 337141cc406Sopenharmony_ci * This function can be used to query the list of devices that are 338141cc406Sopenharmony_ci * available. If the function executes successfully, it stores a 339141cc406Sopenharmony_ci * pointer to a NULL terminated array of pointers to SANE_Device 340141cc406Sopenharmony_ci * structures in *device_list. The returned list is guaranteed to 341141cc406Sopenharmony_ci * remain unchanged and valid until (a) another call to this function 342141cc406Sopenharmony_ci * is performed or (b) a call to sane_exit() is performed. This 343141cc406Sopenharmony_ci * function can be called repeatedly to detect when new devices become 344141cc406Sopenharmony_ci * available. If argument local_only is true, only local devices are 345141cc406Sopenharmony_ci * returned (devices directly attached to the machine that SANE is 346141cc406Sopenharmony_ci * running on). If it is false, the device list includes all remote 347141cc406Sopenharmony_ci * devices that are accessible to the SANE library. 348141cc406Sopenharmony_ci * 349141cc406Sopenharmony_ci * SANE does not require that this function is called before a 350141cc406Sopenharmony_ci * sane_open() call is performed. A device name may be specified 351141cc406Sopenharmony_ci * explicitly by a user which would make it unnecessary and 352141cc406Sopenharmony_ci * undesirable to call this function first. 353141cc406Sopenharmony_ci */ 354141cc406Sopenharmony_ciSANE_Status 355141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) 356141cc406Sopenharmony_ci{ 357141cc406Sopenharmony_ci SANE_Int dev_num; 358141cc406Sopenharmony_ci struct Rts8891_Device *device; 359141cc406Sopenharmony_ci SANE_Device *sane_device; 360141cc406Sopenharmony_ci int i; 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: start: local_only = %s\n", 363141cc406Sopenharmony_ci local_only == SANE_TRUE ? "true" : "false"); 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci /* hot-plugging case : probe for devices plugged since sane_init called */ 366141cc406Sopenharmony_ci probe_rts8891_devices (); 367141cc406Sopenharmony_ci 368141cc406Sopenharmony_ci /* reset devlist first if needed */ 369141cc406Sopenharmony_ci if (devlist) 370141cc406Sopenharmony_ci { 371141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 372141cc406Sopenharmony_ci free ((char *) devlist[i]); 373141cc406Sopenharmony_ci free (devlist); 374141cc406Sopenharmony_ci devlist = NULL; 375141cc406Sopenharmony_ci } 376141cc406Sopenharmony_ci devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); 377141cc406Sopenharmony_ci if (!devlist) 378141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 379141cc406Sopenharmony_ci 380141cc406Sopenharmony_ci *device_list = devlist; 381141cc406Sopenharmony_ci 382141cc406Sopenharmony_ci dev_num = 0; 383141cc406Sopenharmony_ci 384141cc406Sopenharmony_ci /* we build a list of SANE_Device from the list of attached devices */ 385141cc406Sopenharmony_ci for (device = first_device; dev_num < num_devices; device = device->next) 386141cc406Sopenharmony_ci { 387141cc406Sopenharmony_ci sane_device = malloc (sizeof (*sane_device)); 388141cc406Sopenharmony_ci if (!sane_device) 389141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 390141cc406Sopenharmony_ci sane_device->name = device->file_name; 391141cc406Sopenharmony_ci sane_device->vendor = device->model->vendor; 392141cc406Sopenharmony_ci sane_device->model = device->model->product; 393141cc406Sopenharmony_ci sane_device->type = device->model->type; 394141cc406Sopenharmony_ci devlist[dev_num++] = sane_device; 395141cc406Sopenharmony_ci } 396141cc406Sopenharmony_ci devlist[dev_num++] = 0; 397141cc406Sopenharmony_ci 398141cc406Sopenharmony_ci *device_list = devlist; 399141cc406Sopenharmony_ci 400141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_devices: exit\n"); 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 403141cc406Sopenharmony_ci} 404141cc406Sopenharmony_ci 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci/** 407141cc406Sopenharmony_ci * Called to establish connection with the session. This function will 408141cc406Sopenharmony_ci * also establish meaningful defaults and initialize the options. 409141cc406Sopenharmony_ci * 410141cc406Sopenharmony_ci * From the SANE spec: 411141cc406Sopenharmony_ci * This function is used to establish a connection to a particular 412141cc406Sopenharmony_ci * device. The name of the device to be opened is passed in argument 413141cc406Sopenharmony_ci * name. If the call completes successfully, a handle for the device 414141cc406Sopenharmony_ci * is returned in *h. As a special case, specifying a zero-length 415141cc406Sopenharmony_ci * string as the device requests opening the first available device 416141cc406Sopenharmony_ci * (if there is such a device). 417141cc406Sopenharmony_ci * TODO handle SANE_STATUS_BUSY 418141cc406Sopenharmony_ci */ 419141cc406Sopenharmony_ciSANE_Status 420141cc406Sopenharmony_cisane_open (SANE_String_Const name, SANE_Handle * handle) 421141cc406Sopenharmony_ci{ 422141cc406Sopenharmony_ci struct Rts8891_Session *session = NULL; 423141cc406Sopenharmony_ci struct Rts8891_Device *device = NULL; 424141cc406Sopenharmony_ci SANE_Status status; 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: start (devicename=%s)\n", name); 427141cc406Sopenharmony_ci if (name[0] == 0 || strncmp (name, "rts8891", 7) == 0) 428141cc406Sopenharmony_ci { 429141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: no device requested, using default\n"); 430141cc406Sopenharmony_ci if (first_device) 431141cc406Sopenharmony_ci { 432141cc406Sopenharmony_ci device = first_device; 433141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s used as default device\n", 434141cc406Sopenharmony_ci device->file_name); 435141cc406Sopenharmony_ci } 436141cc406Sopenharmony_ci } 437141cc406Sopenharmony_ci else 438141cc406Sopenharmony_ci { 439141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s requested\n", name); 440141cc406Sopenharmony_ci /* walk the device list until we find a matching name */ 441141cc406Sopenharmony_ci device = first_device; 442141cc406Sopenharmony_ci while (device && strcmp (device->file_name, name) != 0) 443141cc406Sopenharmony_ci { 444141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s doesn't match\n", 445141cc406Sopenharmony_ci device->file_name); 446141cc406Sopenharmony_ci device = device->next; 447141cc406Sopenharmony_ci } 448141cc406Sopenharmony_ci } 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci /* check whether we have found a match or reach the end of the device list */ 451141cc406Sopenharmony_ci if (!device) 452141cc406Sopenharmony_ci { 453141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: no device found\n"); 454141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci 457141cc406Sopenharmony_ci /* now we have a device, duplicate it and return it in handle */ 458141cc406Sopenharmony_ci DBG (DBG_info, "sane_open: device %s found\n", name); 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci if (device->model->flags & RTS8891_FLAG_UNTESTED) 461141cc406Sopenharmony_ci { 462141cc406Sopenharmony_ci DBG (DBG_error0, 463141cc406Sopenharmony_ci "WARNING: Your scanner is not fully supported or at least \n"); 464141cc406Sopenharmony_ci DBG (DBG_error0, 465141cc406Sopenharmony_ci " had only limited testing. Please be careful and \n"); 466141cc406Sopenharmony_ci DBG (DBG_error0, " report any failure/success to \n"); 467141cc406Sopenharmony_ci DBG (DBG_error0, 468141cc406Sopenharmony_ci " sane-devel@alioth-lists.debian.net. Please provide as many\n"); 469141cc406Sopenharmony_ci DBG (DBG_error0, 470141cc406Sopenharmony_ci " details as possible, e.g. the exact name of your\n"); 471141cc406Sopenharmony_ci DBG (DBG_error0, " scanner and what does (not) work.\n"); 472141cc406Sopenharmony_ci 473141cc406Sopenharmony_ci } 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci /* open USB link */ 476141cc406Sopenharmony_ci status = sanei_usb_open (device->file_name, &device->devnum); 477141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 478141cc406Sopenharmony_ci { 479141cc406Sopenharmony_ci DBG (DBG_warn, "sane_open: couldn't open device `%s': %s\n", 480141cc406Sopenharmony_ci device->file_name, sane_strstatus (status)); 481141cc406Sopenharmony_ci return status; 482141cc406Sopenharmony_ci } 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci /* device initialization */ 485141cc406Sopenharmony_ci if (device->initialized == SANE_FALSE) 486141cc406Sopenharmony_ci { 487141cc406Sopenharmony_ci#ifdef FAST_INIT 488141cc406Sopenharmony_ci status = detect_device (device); 489141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 490141cc406Sopenharmony_ci { 491141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: detect_device failed\n"); 492141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit on error\n"); 493141cc406Sopenharmony_ci return status; 494141cc406Sopenharmony_ci } 495141cc406Sopenharmony_ci status = initialize_device (device); 496141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 497141cc406Sopenharmony_ci { 498141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: initialize_device failed\n"); 499141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit on error\n"); 500141cc406Sopenharmony_ci return status; 501141cc406Sopenharmony_ci } 502141cc406Sopenharmony_ci#else 503141cc406Sopenharmony_ci status = init_device (device); 504141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 505141cc406Sopenharmony_ci { 506141cc406Sopenharmony_ci DBG (DBG_error, "sane_open: init_device failed\n"); 507141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit on error\n"); 508141cc406Sopenharmony_ci return status; 509141cc406Sopenharmony_ci } 510141cc406Sopenharmony_ci device->initialized = SANE_TRUE; 511141cc406Sopenharmony_ci#endif 512141cc406Sopenharmony_ci } 513141cc406Sopenharmony_ci 514141cc406Sopenharmony_ci /* prepare handle to return */ 515141cc406Sopenharmony_ci session = (Rts8891_Session *) malloc (sizeof (Rts8891_Session)); 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci session->scanning = SANE_FALSE; 518141cc406Sopenharmony_ci session->dev = device; 519141cc406Sopenharmony_ci 520141cc406Sopenharmony_ci init_options (session); 521141cc406Sopenharmony_ci session->scanning = SANE_FALSE; 522141cc406Sopenharmony_ci session->non_blocking = SANE_FALSE; 523141cc406Sopenharmony_ci *handle = session; 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci /* add the handle to the list */ 526141cc406Sopenharmony_ci session->next = first_handle; 527141cc406Sopenharmony_ci first_handle = session; 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci /* release the interface to allow device sharing */ 530141cc406Sopenharmony_ci if (session->dev->conf.allowsharing == SANE_TRUE) 531141cc406Sopenharmony_ci { 532141cc406Sopenharmony_ci sanei_usb_release_interface (device->devnum, 0); 533141cc406Sopenharmony_ci } 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci DBG (DBG_proc, "sane_open: exit\n"); 536141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 537141cc406Sopenharmony_ci} 538141cc406Sopenharmony_ci 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci/** 541141cc406Sopenharmony_ci * Set non blocking mode. In this mode, read return immediately when 542141cc406Sopenharmony_ci * no data is available, instead of polling the scanner. 543141cc406Sopenharmony_ci */ 544141cc406Sopenharmony_ciSANE_Status 545141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) 546141cc406Sopenharmony_ci{ 547141cc406Sopenharmony_ci Rts8891_Session *session = (Rts8891_Session *) handle; 548141cc406Sopenharmony_ci 549141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: start\n"); 550141cc406Sopenharmony_ci if (session->scanning != SANE_TRUE) 551141cc406Sopenharmony_ci { 552141cc406Sopenharmony_ci DBG (DBG_error, "sane_set_io_mode: called out of a scan\n"); 553141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 554141cc406Sopenharmony_ci } 555141cc406Sopenharmony_ci session->non_blocking = non_blocking; 556141cc406Sopenharmony_ci DBG (DBG_warn, "sane_set_io_mode: I/O mode set to %sblocking.\n", 557141cc406Sopenharmony_ci non_blocking ? "non " : " "); 558141cc406Sopenharmony_ci DBG (DBG_proc, "sane_set_io_mode: exit\n"); 559141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 560141cc406Sopenharmony_ci} 561141cc406Sopenharmony_ci 562141cc406Sopenharmony_ci 563141cc406Sopenharmony_ci/** 564141cc406Sopenharmony_ci * An advanced method we don't support but have to define. 565141cc406Sopenharmony_ci */ 566141cc406Sopenharmony_ciSANE_Status 567141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fdp) 568141cc406Sopenharmony_ci{ 569141cc406Sopenharmony_ci 570141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: start\n"); 571141cc406Sopenharmony_ci if(handle==0 || fdp==NULL) 572141cc406Sopenharmony_ci { 573141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 574141cc406Sopenharmony_ci } 575141cc406Sopenharmony_ci DBG (DBG_warn, "sane_get_select_fd: unsupported ...\n"); 576141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_select_fd: exit\n"); 577141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 578141cc406Sopenharmony_ci} 579141cc406Sopenharmony_ci 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci/** 582141cc406Sopenharmony_ci * Returns the options we know. 583141cc406Sopenharmony_ci * 584141cc406Sopenharmony_ci * From the SANE spec: 585141cc406Sopenharmony_ci * This function is used to access option descriptors. The function 586141cc406Sopenharmony_ci * returns the option descriptor for option number n of the device 587141cc406Sopenharmony_ci * represented by handle h. Option number 0 is guaranteed to be a 588141cc406Sopenharmony_ci * valid option. Its value is an integer that specifies the number of 589141cc406Sopenharmony_ci * options that are available for device handle h (the count includes 590141cc406Sopenharmony_ci * option 0). If n is not a valid option index, the function returns 591141cc406Sopenharmony_ci * NULL. The returned option descriptor is guaranteed to remain valid 592141cc406Sopenharmony_ci * (and at the returned address) until the device is closed. 593141cc406Sopenharmony_ci */ 594141cc406Sopenharmony_ciconst SANE_Option_Descriptor * 595141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option) 596141cc406Sopenharmony_ci{ 597141cc406Sopenharmony_ci struct Rts8891_Session *session = handle; 598141cc406Sopenharmony_ci 599141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: start\n"); 600141cc406Sopenharmony_ci 601141cc406Sopenharmony_ci if ((unsigned) option >= NUM_OPTIONS) 602141cc406Sopenharmony_ci return NULL; 603141cc406Sopenharmony_ci 604141cc406Sopenharmony_ci DBG (DBG_info, "sane_get_option_descriptor: \"%s\"\n", 605141cc406Sopenharmony_ci session->opt[option].name); 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); 608141cc406Sopenharmony_ci return &(session->opt[option]); 609141cc406Sopenharmony_ci} 610141cc406Sopenharmony_ci 611141cc406Sopenharmony_ci/** 612141cc406Sopenharmony_ci * sets automatic value for an option , called by sane_control_option after 613141cc406Sopenharmony_ci * all checks have been done */ 614141cc406Sopenharmony_cistatic SANE_Status 615141cc406Sopenharmony_ciset_automatic_value (Rts8891_Session * s, int option, SANE_Int * myinfo) 616141cc406Sopenharmony_ci{ 617141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 618141cc406Sopenharmony_ci SANE_Int i, min; 619141cc406Sopenharmony_ci const SANE_Word *dpi_list; 620141cc406Sopenharmony_ci 621141cc406Sopenharmony_ci switch (option) 622141cc406Sopenharmony_ci { 623141cc406Sopenharmony_ci case OPT_TL_X: 624141cc406Sopenharmony_ci s->val[OPT_TL_X].w = x_range.min; 625141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 626141cc406Sopenharmony_ci break; 627141cc406Sopenharmony_ci case OPT_TL_Y: 628141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = y_range.min; 629141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 630141cc406Sopenharmony_ci break; 631141cc406Sopenharmony_ci case OPT_BR_X: 632141cc406Sopenharmony_ci s->val[OPT_BR_X].w = x_range.max; 633141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 634141cc406Sopenharmony_ci break; 635141cc406Sopenharmony_ci case OPT_BR_Y: 636141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = y_range.max; 637141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 638141cc406Sopenharmony_ci break; 639141cc406Sopenharmony_ci case OPT_RESOLUTION: 640141cc406Sopenharmony_ci /* we set up to the lowest available dpi value */ 641141cc406Sopenharmony_ci dpi_list = s->opt[OPT_RESOLUTION].constraint.word_list; 642141cc406Sopenharmony_ci min = 65536; 643141cc406Sopenharmony_ci for (i = 1; i < dpi_list[0]; i++) 644141cc406Sopenharmony_ci { 645141cc406Sopenharmony_ci if (dpi_list[i] < min) 646141cc406Sopenharmony_ci min = dpi_list[i]; 647141cc406Sopenharmony_ci } 648141cc406Sopenharmony_ci s->val[OPT_RESOLUTION].w = min; 649141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 650141cc406Sopenharmony_ci break; 651141cc406Sopenharmony_ci case OPT_THRESHOLD: 652141cc406Sopenharmony_ci s->val[OPT_THRESHOLD].w = SANE_FIX (50); 653141cc406Sopenharmony_ci break; 654141cc406Sopenharmony_ci case OPT_PREVIEW: 655141cc406Sopenharmony_ci s->val[OPT_PREVIEW].w = SANE_FALSE; 656141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 657141cc406Sopenharmony_ci break; 658141cc406Sopenharmony_ci case OPT_MODE: 659141cc406Sopenharmony_ci if (s->val[OPT_MODE].s) 660141cc406Sopenharmony_ci free (s->val[OPT_MODE].s); 661141cc406Sopenharmony_ci s->val[OPT_MODE].s = strdup (mode_list[0]); 662141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_OPTIONS; 663141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 664141cc406Sopenharmony_ci break; 665141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 666141cc406Sopenharmony_ci s->val[option].b = SANE_FALSE; 667141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR); 668141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_R); 669141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_G); 670141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_B); 671141cc406Sopenharmony_ci break; 672141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 673141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 674141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 675141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 676141cc406Sopenharmony_ci if (s->dev->model->gamma != s->val[option].wa) 677141cc406Sopenharmony_ci free (s->val[option].wa); 678141cc406Sopenharmony_ci s->val[option].wa = s->dev->model->gamma; 679141cc406Sopenharmony_ci break; 680141cc406Sopenharmony_ci default: 681141cc406Sopenharmony_ci DBG (DBG_warn, "set_automatic_value: can't set unknown option %d\n", 682141cc406Sopenharmony_ci option); 683141cc406Sopenharmony_ci } 684141cc406Sopenharmony_ci 685141cc406Sopenharmony_ci return status; 686141cc406Sopenharmony_ci} 687141cc406Sopenharmony_ci 688141cc406Sopenharmony_ci/** 689141cc406Sopenharmony_ci * sets an option , called by sane_control_option after all 690141cc406Sopenharmony_ci * checks have been done */ 691141cc406Sopenharmony_cistatic SANE_Status 692141cc406Sopenharmony_ciset_option_value (Rts8891_Session * s, int option, void *val, 693141cc406Sopenharmony_ci SANE_Int * myinfo) 694141cc406Sopenharmony_ci{ 695141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 696141cc406Sopenharmony_ci SANE_Int i; 697141cc406Sopenharmony_ci SANE_Word tmpw; 698141cc406Sopenharmony_ci 699141cc406Sopenharmony_ci switch (option) 700141cc406Sopenharmony_ci { 701141cc406Sopenharmony_ci case OPT_TL_X: 702141cc406Sopenharmony_ci case OPT_TL_Y: 703141cc406Sopenharmony_ci case OPT_BR_X: 704141cc406Sopenharmony_ci case OPT_BR_Y: 705141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 706141cc406Sopenharmony_ci /* we ensure geometry is coherent */ 707141cc406Sopenharmony_ci /* this happens when user drags TL corner right or below the BR point */ 708141cc406Sopenharmony_ci if (s->val[OPT_BR_Y].w < s->val[OPT_TL_Y].w) 709141cc406Sopenharmony_ci { 710141cc406Sopenharmony_ci tmpw = s->val[OPT_BR_Y].w; 711141cc406Sopenharmony_ci s->val[OPT_BR_Y].w = s->val[OPT_TL_Y].w; 712141cc406Sopenharmony_ci s->val[OPT_TL_Y].w = tmpw; 713141cc406Sopenharmony_ci } 714141cc406Sopenharmony_ci if (s->val[OPT_BR_X].w < s->val[OPT_TL_X].w) 715141cc406Sopenharmony_ci { 716141cc406Sopenharmony_ci tmpw = s->val[OPT_BR_X].w; 717141cc406Sopenharmony_ci s->val[OPT_BR_X].w = s->val[OPT_TL_X].w; 718141cc406Sopenharmony_ci s->val[OPT_TL_X].w = tmpw; 719141cc406Sopenharmony_ci } 720141cc406Sopenharmony_ci 721141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 722141cc406Sopenharmony_ci break; 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci case OPT_RESOLUTION: 725141cc406Sopenharmony_ci case OPT_THRESHOLD: 726141cc406Sopenharmony_ci case OPT_PREVIEW: 727141cc406Sopenharmony_ci s->val[option].w = *(SANE_Word *) val; 728141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS; 729141cc406Sopenharmony_ci break; 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci case OPT_MODE: 732141cc406Sopenharmony_ci if (s->val[option].s) 733141cc406Sopenharmony_ci free (s->val[option].s); 734141cc406Sopenharmony_ci s->val[option].s = strdup (val); 735141cc406Sopenharmony_ci if (strcmp (s->val[option].s, LINEART_MODE) == 0) 736141cc406Sopenharmony_ci { 737141cc406Sopenharmony_ci ENABLE (OPT_THRESHOLD); 738141cc406Sopenharmony_ci } 739141cc406Sopenharmony_ci else 740141cc406Sopenharmony_ci { 741141cc406Sopenharmony_ci DISABLE (OPT_THRESHOLD); 742141cc406Sopenharmony_ci } 743141cc406Sopenharmony_ci 744141cc406Sopenharmony_ci /* if custom gamma, toggle gamma table options according to the mode */ 745141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE) 746141cc406Sopenharmony_ci { 747141cc406Sopenharmony_ci if (strcmp (s->val[option].s, COLOR_MODE) == 0) 748141cc406Sopenharmony_ci { 749141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR); 750141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR_R); 751141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR_G); 752141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR_B); 753141cc406Sopenharmony_ci } 754141cc406Sopenharmony_ci else 755141cc406Sopenharmony_ci { 756141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR); 757141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_R); 758141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_G); 759141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_B); 760141cc406Sopenharmony_ci } 761141cc406Sopenharmony_ci } 762141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 763141cc406Sopenharmony_ci break; 764141cc406Sopenharmony_ci 765141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 766141cc406Sopenharmony_ci *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; 767141cc406Sopenharmony_ci s->val[OPT_CUSTOM_GAMMA].b = *(SANE_Bool *) val; 768141cc406Sopenharmony_ci 769141cc406Sopenharmony_ci if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE) 770141cc406Sopenharmony_ci { 771141cc406Sopenharmony_ci if (strcmp (s->val[OPT_MODE].s, COLOR_MODE) == 0) 772141cc406Sopenharmony_ci { 773141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR); 774141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR_R); 775141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR_G); 776141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR_B); 777141cc406Sopenharmony_ci } 778141cc406Sopenharmony_ci else 779141cc406Sopenharmony_ci { 780141cc406Sopenharmony_ci ENABLE (OPT_GAMMA_VECTOR); 781141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_R); 782141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_G); 783141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_B); 784141cc406Sopenharmony_ci } 785141cc406Sopenharmony_ci } 786141cc406Sopenharmony_ci else 787141cc406Sopenharmony_ci { 788141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR); 789141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_R); 790141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_G); 791141cc406Sopenharmony_ci DISABLE (OPT_GAMMA_VECTOR_B); 792141cc406Sopenharmony_ci } 793141cc406Sopenharmony_ci break; 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 796141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 797141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 798141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 799141cc406Sopenharmony_ci /* sanity checks */ 800141cc406Sopenharmony_ci for (i = 0; i < (int) (s->opt[option].size / sizeof (SANE_Word)); i++) 801141cc406Sopenharmony_ci { 802141cc406Sopenharmony_ci /* avoid 0xaa values since they will be problematic */ 803141cc406Sopenharmony_ci if (((SANE_Int *) val)[i] == 0xaa) 804141cc406Sopenharmony_ci ((SANE_Int *) val)[i] = 0xab; 805141cc406Sopenharmony_ci } 806141cc406Sopenharmony_ci 807141cc406Sopenharmony_ci /* free memory from previous set */ 808141cc406Sopenharmony_ci if (s->dev->model->gamma != s->val[option].wa) 809141cc406Sopenharmony_ci free (s->val[option].wa); 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci /* then alloc memory */ 812141cc406Sopenharmony_ci s->val[option].wa = (SANE_Word *) malloc (256 * sizeof (SANE_Word)); 813141cc406Sopenharmony_ci if (s->val[option].wa == NULL) 814141cc406Sopenharmony_ci { 815141cc406Sopenharmony_ci s->val[option].wa = s->dev->model->gamma; 816141cc406Sopenharmony_ci DBG (DBG_error0, 817141cc406Sopenharmony_ci "set_option_value: not enough memory for %lu bytes!\n", 818141cc406Sopenharmony_ci (u_long) (256 * sizeof (SANE_Word))); 819141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 820141cc406Sopenharmony_ci } 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci /* data copy */ 823141cc406Sopenharmony_ci memcpy (s->val[option].wa, val, s->opt[option].size); 824141cc406Sopenharmony_ci break; 825141cc406Sopenharmony_ci 826141cc406Sopenharmony_ci case OPT_LAMP_ON: 827141cc406Sopenharmony_ci return set_lamp_state (s, 1); 828141cc406Sopenharmony_ci break; 829141cc406Sopenharmony_ci 830141cc406Sopenharmony_ci case OPT_LAMP_OFF: 831141cc406Sopenharmony_ci return set_lamp_state (s, 0); 832141cc406Sopenharmony_ci break; 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci default: 835141cc406Sopenharmony_ci DBG (DBG_warn, "set_option_value: can't set unknown option %d\n", 836141cc406Sopenharmony_ci option); 837141cc406Sopenharmony_ci } 838141cc406Sopenharmony_ci return status; 839141cc406Sopenharmony_ci} 840141cc406Sopenharmony_ci 841141cc406Sopenharmony_ci/** 842141cc406Sopenharmony_ci * gets an option , called by sane_control_option after all checks 843141cc406Sopenharmony_ci * have been done */ 844141cc406Sopenharmony_cistatic SANE_Status 845141cc406Sopenharmony_ciget_option_value (Rts8891_Session * s, int option, void *val) 846141cc406Sopenharmony_ci{ 847141cc406Sopenharmony_ci switch (option) 848141cc406Sopenharmony_ci { 849141cc406Sopenharmony_ci /* word or word equivalent options: */ 850141cc406Sopenharmony_ci case OPT_NUM_OPTS: 851141cc406Sopenharmony_ci case OPT_RESOLUTION: 852141cc406Sopenharmony_ci case OPT_PREVIEW: 853141cc406Sopenharmony_ci case OPT_TL_X: 854141cc406Sopenharmony_ci case OPT_TL_Y: 855141cc406Sopenharmony_ci case OPT_BR_X: 856141cc406Sopenharmony_ci case OPT_BR_Y: 857141cc406Sopenharmony_ci case OPT_THRESHOLD: 858141cc406Sopenharmony_ci case OPT_CUSTOM_GAMMA: 859141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 860141cc406Sopenharmony_ci break; 861141cc406Sopenharmony_ci case OPT_BUTTON_1: 862141cc406Sopenharmony_ci case OPT_BUTTON_2: 863141cc406Sopenharmony_ci case OPT_BUTTON_3: 864141cc406Sopenharmony_ci case OPT_BUTTON_4: 865141cc406Sopenharmony_ci case OPT_BUTTON_5: 866141cc406Sopenharmony_ci case OPT_BUTTON_6: 867141cc406Sopenharmony_ci case OPT_BUTTON_7: 868141cc406Sopenharmony_ci case OPT_BUTTON_8: 869141cc406Sopenharmony_ci case OPT_BUTTON_9: 870141cc406Sopenharmony_ci case OPT_BUTTON_10: 871141cc406Sopenharmony_ci case OPT_BUTTON_11: 872141cc406Sopenharmony_ci /* no button pressed by default */ 873141cc406Sopenharmony_ci *(SANE_Word *) val = SANE_FALSE; 874141cc406Sopenharmony_ci if (option - OPT_BUTTON_1 > s->dev->model->buttons) 875141cc406Sopenharmony_ci { 876141cc406Sopenharmony_ci DBG (DBG_warn, 877141cc406Sopenharmony_ci "get_option_value: invalid button option %d\n", option); 878141cc406Sopenharmony_ci } 879141cc406Sopenharmony_ci else 880141cc406Sopenharmony_ci { 881141cc406Sopenharmony_ci update_button_status (s); 882141cc406Sopenharmony_ci /* copy the button state */ 883141cc406Sopenharmony_ci *(SANE_Word *) val = s->val[option].w; 884141cc406Sopenharmony_ci /* clear the button state */ 885141cc406Sopenharmony_ci s->val[option].w = SANE_FALSE; 886141cc406Sopenharmony_ci DBG (DBG_io, 887141cc406Sopenharmony_ci "get_option_value: button option %d=%d\n", option, 888141cc406Sopenharmony_ci *(SANE_Word *) val); 889141cc406Sopenharmony_ci } 890141cc406Sopenharmony_ci break; 891141cc406Sopenharmony_ci /* string options: */ 892141cc406Sopenharmony_ci case OPT_MODE: 893141cc406Sopenharmony_ci strcpy (val, s->val[option].s); 894141cc406Sopenharmony_ci break; 895141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR: 896141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_R: 897141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_G: 898141cc406Sopenharmony_ci case OPT_GAMMA_VECTOR_B: 899141cc406Sopenharmony_ci memcpy (val, s->val[option].wa, s->opt[option].size); 900141cc406Sopenharmony_ci break; 901141cc406Sopenharmony_ci default: 902141cc406Sopenharmony_ci DBG (DBG_warn, "get_option_value: can't get unknown option %d\n", 903141cc406Sopenharmony_ci option); 904141cc406Sopenharmony_ci } 905141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 906141cc406Sopenharmony_ci} 907141cc406Sopenharmony_ci 908141cc406Sopenharmony_ci/** 909141cc406Sopenharmony_ci * Gets or sets an option value. 910141cc406Sopenharmony_ci * 911141cc406Sopenharmony_ci * From the SANE spec: 912141cc406Sopenharmony_ci * This function is used to set or inquire the current value of option 913141cc406Sopenharmony_ci * number n of the device represented by handle h. The manner in which 914141cc406Sopenharmony_ci * the option is controlled is specified by parameter action. The 915141cc406Sopenharmony_ci * possible values of this parameter are described in more detail 916141cc406Sopenharmony_ci * below. The value of the option is passed through argument val. It 917141cc406Sopenharmony_ci * is a pointer to the memory that holds the option value. The memory 918141cc406Sopenharmony_ci * area pointed to by v must be big enough to hold the entire option 919141cc406Sopenharmony_ci * value (determined by member size in the corresponding option 920141cc406Sopenharmony_ci * descriptor). 921141cc406Sopenharmony_ci * 922141cc406Sopenharmony_ci * The only exception to this rule is that when setting the value of a 923141cc406Sopenharmony_ci * string option, the string pointed to by argument v may be shorter 924141cc406Sopenharmony_ci * since the backend will stop reading the option value upon 925141cc406Sopenharmony_ci * encountering the first NUL terminator in the string. If argument i 926141cc406Sopenharmony_ci * is not NULL, the value of *i will be set to provide details on how 927141cc406Sopenharmony_ci * well the request has been met. 928141cc406Sopenharmony_ci * action is SANE_ACTION_GET_VALUE, SANE_ACTION_SET_VALUE or SANE_ACTION_SET_AUTO 929141cc406Sopenharmony_ci */ 930141cc406Sopenharmony_ciSANE_Status 931141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, 932141cc406Sopenharmony_ci SANE_Action action, void *val, SANE_Int * info) 933141cc406Sopenharmony_ci{ 934141cc406Sopenharmony_ci Rts8891_Session *s = handle; 935141cc406Sopenharmony_ci SANE_Status status; 936141cc406Sopenharmony_ci SANE_Word cap; 937141cc406Sopenharmony_ci SANE_Int myinfo = 0; 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci DBG (DBG_io2, 940141cc406Sopenharmony_ci "sane_control_option: start: action = %s, option = %s (%d)\n", 941141cc406Sopenharmony_ci (action == SANE_ACTION_GET_VALUE) ? "get" : (action == 942141cc406Sopenharmony_ci SANE_ACTION_SET_VALUE) ? 943141cc406Sopenharmony_ci "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", 944141cc406Sopenharmony_ci s->opt[option].name, option); 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_ci if (info) 947141cc406Sopenharmony_ci *info = 0; 948141cc406Sopenharmony_ci 949141cc406Sopenharmony_ci /* do checks before trying to apply action */ 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ci if (s->scanning) 952141cc406Sopenharmony_ci { 953141cc406Sopenharmony_ci DBG (DBG_warn, "sane_control_option: don't call this function while " 954141cc406Sopenharmony_ci "scanning (option = %s (%d))\n", s->opt[option].name, option); 955141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 956141cc406Sopenharmony_ci } 957141cc406Sopenharmony_ci 958141cc406Sopenharmony_ci /* option must be within existing range */ 959141cc406Sopenharmony_ci if (option >= NUM_OPTIONS || option < 0) 960141cc406Sopenharmony_ci { 961141cc406Sopenharmony_ci DBG (DBG_warn, 962141cc406Sopenharmony_ci "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", 963141cc406Sopenharmony_ci option); 964141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 965141cc406Sopenharmony_ci } 966141cc406Sopenharmony_ci 967141cc406Sopenharmony_ci /* don't access an inactive option */ 968141cc406Sopenharmony_ci cap = s->opt[option].cap; 969141cc406Sopenharmony_ci if (!SANE_OPTION_IS_ACTIVE (cap)) 970141cc406Sopenharmony_ci { 971141cc406Sopenharmony_ci DBG (DBG_warn, "sane_control_option: option %d is inactive\n", option); 972141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 973141cc406Sopenharmony_ci } 974141cc406Sopenharmony_ci 975141cc406Sopenharmony_ci /* now checks have been done, apply action */ 976141cc406Sopenharmony_ci switch (action) 977141cc406Sopenharmony_ci { 978141cc406Sopenharmony_ci case SANE_ACTION_GET_VALUE: 979141cc406Sopenharmony_ci status = get_option_value (s, option, val); 980141cc406Sopenharmony_ci break; 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci case SANE_ACTION_SET_VALUE: 983141cc406Sopenharmony_ci if (!SANE_OPTION_IS_SETTABLE (cap)) 984141cc406Sopenharmony_ci { 985141cc406Sopenharmony_ci DBG (DBG_warn, "sane_control_option: option %d is not settable\n", 986141cc406Sopenharmony_ci option); 987141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 988141cc406Sopenharmony_ci } 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci status = sanei_constrain_value (s->opt + option, val, &myinfo); 991141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 992141cc406Sopenharmony_ci { 993141cc406Sopenharmony_ci DBG (DBG_warn, 994141cc406Sopenharmony_ci "sane_control_option: sanei_constrain_value returned %s\n", 995141cc406Sopenharmony_ci sane_strstatus (status)); 996141cc406Sopenharmony_ci return status; 997141cc406Sopenharmony_ci } 998141cc406Sopenharmony_ci 999141cc406Sopenharmony_ci /* return immediately if no change */ 1000141cc406Sopenharmony_ci if (s->opt[option].type == SANE_TYPE_INT 1001141cc406Sopenharmony_ci && *(SANE_Word *) val == s->val[option].w) 1002141cc406Sopenharmony_ci { 1003141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 1004141cc406Sopenharmony_ci } 1005141cc406Sopenharmony_ci else 1006141cc406Sopenharmony_ci { /* apply change */ 1007141cc406Sopenharmony_ci status = set_option_value (s, option, val, &myinfo); 1008141cc406Sopenharmony_ci } 1009141cc406Sopenharmony_ci break; 1010141cc406Sopenharmony_ci 1011141cc406Sopenharmony_ci case SANE_ACTION_SET_AUTO: 1012141cc406Sopenharmony_ci /* sets automatic values */ 1013141cc406Sopenharmony_ci if (!(cap & SANE_CAP_AUTOMATIC)) 1014141cc406Sopenharmony_ci { 1015141cc406Sopenharmony_ci DBG (DBG_warn, 1016141cc406Sopenharmony_ci "sane_control_option: option %d is not autosettable\n", 1017141cc406Sopenharmony_ci option); 1018141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1019141cc406Sopenharmony_ci } 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ci status = set_automatic_value (s, option, &myinfo); 1022141cc406Sopenharmony_ci break; 1023141cc406Sopenharmony_ci 1024141cc406Sopenharmony_ci default: 1025141cc406Sopenharmony_ci DBG (DBG_error, "sane_control_option: invalid action %d\n", action); 1026141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 1027141cc406Sopenharmony_ci break; 1028141cc406Sopenharmony_ci } 1029141cc406Sopenharmony_ci 1030141cc406Sopenharmony_ci if (info) 1031141cc406Sopenharmony_ci *info = myinfo; 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci DBG (DBG_io2, "sane_control_option: exit\n"); 1034141cc406Sopenharmony_ci return status; 1035141cc406Sopenharmony_ci} 1036141cc406Sopenharmony_ci 1037141cc406Sopenharmony_ci/** 1038141cc406Sopenharmony_ci * returns the name of the sensor 1039141cc406Sopenharmony_ci * @param sensor sensor numnber 1040141cc406Sopenharmony_ci * @return string holding the name of the sensor 1041141cc406Sopenharmony_ci */ 1042141cc406Sopenharmony_cistatic char *sensor_name (int sensor) 1043141cc406Sopenharmony_ci{ 1044141cc406Sopenharmony_ci switch (sensor) 1045141cc406Sopenharmony_ci { 1046141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 1047141cc406Sopenharmony_ci return "SENSOR_TYPE_BARE"; 1048141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 1049141cc406Sopenharmony_ci return "SENSOR_TYPE_XPA"; 1050141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 1051141cc406Sopenharmony_ci return "SENSOR_TYPE_4400"; 1052141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 1053141cc406Sopenharmony_ci return "SENSOR_TYPE_4400_BARE"; 1054141cc406Sopenharmony_ci default: 1055141cc406Sopenharmony_ci return "BOGUS"; 1056141cc406Sopenharmony_ci } 1057141cc406Sopenharmony_ci} 1058141cc406Sopenharmony_ci 1059141cc406Sopenharmony_ci/** 1060141cc406Sopenharmony_ci * Called by SANE when a page acquisition operation is to be started. 1061141cc406Sopenharmony_ci * @param handle opaque handle to a frontend session 1062141cc406Sopenharmony_ci * @return SANE_STATUS_GOOD on success, SANE_STATUS_BUSY if the device is 1063141cc406Sopenharmony_ci * in use by another session or SANE_STATUS_WARMING_UP if the device is 1064141cc406Sopenharmony_ci * warming up. In this case the fronted as to call sane_start again until 1065141cc406Sopenharmony_ci * warming up is done. Any other values returned are error status. 1066141cc406Sopenharmony_ci */ 1067141cc406Sopenharmony_ciSANE_Status 1068141cc406Sopenharmony_cisane_start (SANE_Handle handle) 1069141cc406Sopenharmony_ci{ 1070141cc406Sopenharmony_ci struct Rts8891_Session *session = handle; 1071141cc406Sopenharmony_ci int light, mode; 1072141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 1073141cc406Sopenharmony_ci SANE_Status status; 1074141cc406Sopenharmony_ci SANE_Bool changed; 1075141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 1076141cc406Sopenharmony_ci struct timeval current; 1077141cc406Sopenharmony_ci#endif 1078141cc406Sopenharmony_ci 1079141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: start\n"); 1080141cc406Sopenharmony_ci 1081141cc406Sopenharmony_ci /* if already scanning, tell we're busy */ 1082141cc406Sopenharmony_ci if (session->scanning == SANE_TRUE) 1083141cc406Sopenharmony_ci { 1084141cc406Sopenharmony_ci DBG (DBG_warn, "sane_start: device is already scanning\n"); 1085141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1086141cc406Sopenharmony_ci } 1087141cc406Sopenharmony_ci 1088141cc406Sopenharmony_ci /* claim the interface reserve device */ 1089141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1090141cc406Sopenharmony_ci { 1091141cc406Sopenharmony_ci status = sanei_usb_claim_interface (dev->devnum, 0); 1092141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1093141cc406Sopenharmony_ci { 1094141cc406Sopenharmony_ci DBG (DBG_warn, "sane_start: cannot claim usb interface\n"); 1095141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 1096141cc406Sopenharmony_ci } 1097141cc406Sopenharmony_ci } 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci /* check if we need warming-up */ 1100141cc406Sopenharmony_ci sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); 1101141cc406Sopenharmony_ci if ((dev->regs[0x8e] & 0x60) != 0x60) 1102141cc406Sopenharmony_ci { 1103141cc406Sopenharmony_ci DBG (DBG_info, "sane_start: lamp needs warming (0x%02x)\n", 1104141cc406Sopenharmony_ci dev->regs[0x8e]); 1105141cc406Sopenharmony_ci dev->needs_warming = SANE_TRUE; 1106141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 1107141cc406Sopenharmony_ci dev->start_time.tv_sec = current.tv_sec; 1108141cc406Sopenharmony_ci dev->last_scan.tv_sec = current.tv_sec; 1109141cc406Sopenharmony_ci#endif 1110141cc406Sopenharmony_ci } 1111141cc406Sopenharmony_ci 1112141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 1113141cc406Sopenharmony_ci /* if last scan time is more than 10 minutes ago, scanner also needs 1114141cc406Sopenharmony_ci * warming-up */ 1115141cc406Sopenharmony_ci gettimeofday (¤t, NULL); 1116141cc406Sopenharmony_ci if ((current.tv_sec - dev->last_scan.tv_sec) / 60 > 10) 1117141cc406Sopenharmony_ci { 1118141cc406Sopenharmony_ci DBG (DBG_info, 1119141cc406Sopenharmony_ci "sane_start: more than 10 minutes without scanning, lamp needs warming\n"); 1120141cc406Sopenharmony_ci dev->needs_warming = SANE_TRUE; 1121141cc406Sopenharmony_ci dev->start_time.tv_sec = current.tv_sec; 1122141cc406Sopenharmony_ci dev->last_scan.tv_sec = current.tv_sec; 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci#endif 1125141cc406Sopenharmony_ci 1126141cc406Sopenharmony_ci /* if parking, wait for head to stop */ 1127141cc406Sopenharmony_ci if(dev->parking==SANE_TRUE) 1128141cc406Sopenharmony_ci { 1129141cc406Sopenharmony_ci rts8891_wait_for_home (dev, dev->regs); 1130141cc406Sopenharmony_ci } 1131141cc406Sopenharmony_ci 1132141cc406Sopenharmony_ci /* reinit registers to start values */ 1133141cc406Sopenharmony_ci rts8891_set_default_regs (dev->regs); 1134141cc406Sopenharmony_ci 1135141cc406Sopenharmony_ci /* step 0: light up */ 1136141cc406Sopenharmony_ci init_lamp (dev); 1137141cc406Sopenharmony_ci 1138141cc406Sopenharmony_ci /* do warming up if needed: just detected or at sane_open() */ 1139141cc406Sopenharmony_ci if (dev->needs_warming == SANE_TRUE) 1140141cc406Sopenharmony_ci { 1141141cc406Sopenharmony_ci DBG (DBG_info, "sane_start: warming lamp ...\n"); 1142141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 1143141cc406Sopenharmony_ci /* check if current time is >15s after warming-up start */ 1144141cc406Sopenharmony_ci gettimeofday (¤t, NULL); 1145141cc406Sopenharmony_ci if ((current.tv_sec - dev->start_time.tv_sec) < 15) 1146141cc406Sopenharmony_ci { 1147141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP 1148141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1149141cc406Sopenharmony_ci { 1150141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1151141cc406Sopenharmony_ci } 1152141cc406Sopenharmony_ci return SANE_STATUS_WARMING_UP; 1153141cc406Sopenharmony_ci#else 1154141cc406Sopenharmony_ci DBG (DBG_info, 1155141cc406Sopenharmony_ci "sane_start: waiting to let lamp get warm enough ...\n"); 1156141cc406Sopenharmony_ci sleep (15 - (current.tv_sec - dev->start_time.tv_sec)); 1157141cc406Sopenharmony_ci#endif 1158141cc406Sopenharmony_ci } 1159141cc406Sopenharmony_ci#else 1160141cc406Sopenharmony_ci DBG (DBG_info, 1161141cc406Sopenharmony_ci "sane_start: waiting 15s to let lamp get warm enough ...\n"); 1162141cc406Sopenharmony_ci sleep (15); 1163141cc406Sopenharmony_ci#endif 1164141cc406Sopenharmony_ci } 1165141cc406Sopenharmony_ci dev->needs_warming = SANE_FALSE; 1166141cc406Sopenharmony_ci 1167141cc406Sopenharmony_ci /* restore default brightness */ 1168141cc406Sopenharmony_ci dev->regs[LAMP_BRIGHT_REG] = 0xA7; 1169141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, 1170141cc406Sopenharmony_ci dev->regs + LAMP_BRIGHT_REG); 1171141cc406Sopenharmony_ci DBG (DBG_info, "sane_start: sensor initial type is %s (%d)\n", 1172141cc406Sopenharmony_ci sensor_name (dev->sensor), dev->sensor); 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci /* step 1: locate scan area by doing a scan, then goto calibration area */ 1175141cc406Sopenharmony_ci /* we also detect if the sensor type is inadequate and then change it */ 1176141cc406Sopenharmony_ci do 1177141cc406Sopenharmony_ci { 1178141cc406Sopenharmony_ci changed = SANE_FALSE; 1179141cc406Sopenharmony_ci status = find_origin (dev, &changed); 1180141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1181141cc406Sopenharmony_ci { 1182141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1183141cc406Sopenharmony_ci { 1184141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1185141cc406Sopenharmony_ci } 1186141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to find origin!\n"); 1187141cc406Sopenharmony_ci return status; 1188141cc406Sopenharmony_ci } 1189141cc406Sopenharmony_ci 1190141cc406Sopenharmony_ci /* in case find_origin detected we need to change sensor */ 1191141cc406Sopenharmony_ci if (changed) 1192141cc406Sopenharmony_ci { 1193141cc406Sopenharmony_ci /* for a sensor 'pair', we switch */ 1194141cc406Sopenharmony_ci switch (dev->sensor) 1195141cc406Sopenharmony_ci { 1196141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 1197141cc406Sopenharmony_ci DBG (DBG_info, 1198141cc406Sopenharmony_ci "sane_start: sensor changed to type 'SENSOR_TYPE_XPA'!\n"); 1199141cc406Sopenharmony_ci dev->sensor = SENSOR_TYPE_XPA; 1200141cc406Sopenharmony_ci break; 1201141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 1202141cc406Sopenharmony_ci DBG (DBG_info, 1203141cc406Sopenharmony_ci "sane_start: sensor changed to type 'SENSOR_TYPE_BARE'!\n"); 1204141cc406Sopenharmony_ci dev->sensor = SENSOR_TYPE_BARE; 1205141cc406Sopenharmony_ci break; 1206141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 1207141cc406Sopenharmony_ci DBG (DBG_info, 1208141cc406Sopenharmony_ci "sane_start: sensor changed to type '4400 SENSOR_TYPE_4400_BARE'!\n"); 1209141cc406Sopenharmony_ci dev->sensor = SENSOR_TYPE_4400_BARE; 1210141cc406Sopenharmony_ci break; 1211141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 1212141cc406Sopenharmony_ci DBG (DBG_info, 1213141cc406Sopenharmony_ci "sane_start: sensor changed to type 'SENSOR_TYPE_4400'!\n"); 1214141cc406Sopenharmony_ci dev->sensor = SENSOR_TYPE_4400; 1215141cc406Sopenharmony_ci break; 1216141cc406Sopenharmony_ci } 1217141cc406Sopenharmony_ci } 1218141cc406Sopenharmony_ci } 1219141cc406Sopenharmony_ci while (changed); 1220141cc406Sopenharmony_ci 1221141cc406Sopenharmony_ci /* light source to use */ 1222141cc406Sopenharmony_ci switch (dev->sensor) 1223141cc406Sopenharmony_ci { 1224141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 1225141cc406Sopenharmony_ci light = 0x3f; 1226141cc406Sopenharmony_ci mode = 0x20; 1227141cc406Sopenharmony_ci break; 1228141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 1229141cc406Sopenharmony_ci light = 0x3b; 1230141cc406Sopenharmony_ci mode = 0x20; 1231141cc406Sopenharmony_ci break; 1232141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 1233141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 1234141cc406Sopenharmony_ci light = 0x2a; 1235141cc406Sopenharmony_ci mode = 0x10; 1236141cc406Sopenharmony_ci break; 1237141cc406Sopenharmony_ci default: 1238141cc406Sopenharmony_ci light = 0x3b; 1239141cc406Sopenharmony_ci mode = 0x20; 1240141cc406Sopenharmony_ci break; 1241141cc406Sopenharmony_ci } 1242141cc406Sopenharmony_ci DBG (DBG_info, "sane_start: sensor final type is %s (%d)\n", 1243141cc406Sopenharmony_ci sensor_name (dev->sensor), dev->sensor); 1244141cc406Sopenharmony_ci DBG (DBG_info, "sane_start: mode=0x%02x, light=0x%02x\n", mode, light); 1245141cc406Sopenharmony_ci 1246141cc406Sopenharmony_ci /* step 2: dark calibration */ 1247141cc406Sopenharmony_ci status = dark_calibration (dev, mode, light); 1248141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1249141cc406Sopenharmony_ci { 1250141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1251141cc406Sopenharmony_ci { 1252141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1253141cc406Sopenharmony_ci } 1254141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to do dark calibration!\n"); 1255141cc406Sopenharmony_ci return status; 1256141cc406Sopenharmony_ci } 1257141cc406Sopenharmony_ci 1258141cc406Sopenharmony_ci /* step 3: find left margin */ 1259141cc406Sopenharmony_ci status = find_margin (dev); 1260141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1261141cc406Sopenharmony_ci { 1262141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1263141cc406Sopenharmony_ci { 1264141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1265141cc406Sopenharmony_ci } 1266141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed find left margin!\n"); 1267141cc406Sopenharmony_ci return status; 1268141cc406Sopenharmony_ci } 1269141cc406Sopenharmony_ci 1270141cc406Sopenharmony_ci /* restore brightness */ 1271141cc406Sopenharmony_ci dev->regs[LAMP_BRIGHT_REG] = 0xA7; 1272141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, 1273141cc406Sopenharmony_ci dev->regs + LAMP_BRIGHT_REG); 1274141cc406Sopenharmony_ci 1275141cc406Sopenharmony_ci /* step 4: gain calibration */ 1276141cc406Sopenharmony_ci status = gain_calibration (dev, mode, light); 1277141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1278141cc406Sopenharmony_ci { 1279141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1280141cc406Sopenharmony_ci { 1281141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1282141cc406Sopenharmony_ci } 1283141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to do gain calibration!\n"); 1284141cc406Sopenharmony_ci return status; 1285141cc406Sopenharmony_ci } 1286141cc406Sopenharmony_ci 1287141cc406Sopenharmony_ci /* step 5: fine offset calibration */ 1288141cc406Sopenharmony_ci status = offset_calibration (dev, mode, light); 1289141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1290141cc406Sopenharmony_ci { 1291141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1292141cc406Sopenharmony_ci { 1293141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1294141cc406Sopenharmony_ci } 1295141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to do offset calibration!\n"); 1296141cc406Sopenharmony_ci return status; 1297141cc406Sopenharmony_ci } 1298141cc406Sopenharmony_ci 1299141cc406Sopenharmony_ci /* we compute all the scan parameters so that */ 1300141cc406Sopenharmony_ci /* we will be able to set up the registers correctly */ 1301141cc406Sopenharmony_ci compute_parameters (session); 1302141cc406Sopenharmony_ci 1303141cc406Sopenharmony_ci /* allocate buffer and compute start pointer */ 1304141cc406Sopenharmony_ci if (dev->scanned_data != NULL) 1305141cc406Sopenharmony_ci free (dev->scanned_data); 1306141cc406Sopenharmony_ci dev->scanned_data = 1307141cc406Sopenharmony_ci (SANE_Byte *) malloc (dev->data_size + dev->lds_max + dev->ripple); 1308141cc406Sopenharmony_ci dev->start = dev->scanned_data + dev->lds_max + dev->ripple; 1309141cc406Sopenharmony_ci 1310141cc406Sopenharmony_ci /* computes data end pointer */ 1311141cc406Sopenharmony_ci dev->end = dev->start + dev->data_size; 1312141cc406Sopenharmony_ci 1313141cc406Sopenharmony_ci /* no bytes sent yet to frontend */ 1314141cc406Sopenharmony_ci session->sent = 0; 1315141cc406Sopenharmony_ci 1316141cc406Sopenharmony_ci sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset, 1317141cc406Sopenharmony_ci dev->blue_offset); 1318141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain, 1319141cc406Sopenharmony_ci dev->blue_gain); 1320141cc406Sopenharmony_ci 1321141cc406Sopenharmony_ci /* step 6: shading calibration */ 1322141cc406Sopenharmony_ci status = 1323141cc406Sopenharmony_ci shading_calibration (dev, session->params.format == SANE_FRAME_RGB 1324141cc406Sopenharmony_ci || session->emulated_gray == SANE_TRUE, mode, light); 1325141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1326141cc406Sopenharmony_ci { 1327141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1328141cc406Sopenharmony_ci { 1329141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1330141cc406Sopenharmony_ci } 1331141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to do shading calibration!\n"); 1332141cc406Sopenharmony_ci return status; 1333141cc406Sopenharmony_ci } 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci /* step 6b: move at dev->model->min_ydpi to target area */ 1336141cc406Sopenharmony_ci if (dev->ydpi > dev->model->min_ydpi 1337141cc406Sopenharmony_ci && (dev->ystart * MOVE_DPI) / dev->ydpi > 150) 1338141cc406Sopenharmony_ci { 1339141cc406Sopenharmony_ci status = move_to_scan_area (session); 1340141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1341141cc406Sopenharmony_ci { 1342141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1343141cc406Sopenharmony_ci { 1344141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1345141cc406Sopenharmony_ci } 1346141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to move to scan area!\n"); 1347141cc406Sopenharmony_ci return status; 1348141cc406Sopenharmony_ci } 1349141cc406Sopenharmony_ci } 1350141cc406Sopenharmony_ci 1351141cc406Sopenharmony_ci /* step 7: effective scan start */ 1352141cc406Sopenharmony_ci /* build register set and send it */ 1353141cc406Sopenharmony_ci status = write_scan_registers (session); 1354141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1355141cc406Sopenharmony_ci { 1356141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1357141cc406Sopenharmony_ci { 1358141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1359141cc406Sopenharmony_ci } 1360141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to write scan registers!\n"); 1361141cc406Sopenharmony_ci return status; 1362141cc406Sopenharmony_ci } 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci /* step 8: send calibration data */ 1365141cc406Sopenharmony_ci status = send_calibration_data (session); 1366141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1367141cc406Sopenharmony_ci { 1368141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 1369141cc406Sopenharmony_ci { 1370141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 1371141cc406Sopenharmony_ci } 1372141cc406Sopenharmony_ci DBG (DBG_error, "sane_start: failed to send calibration data!\n"); 1373141cc406Sopenharmony_ci return status; 1374141cc406Sopenharmony_ci } 1375141cc406Sopenharmony_ci 1376141cc406Sopenharmony_ci /* commit the scan */ 1377141cc406Sopenharmony_ci /* TODO send_calibration seems to embbed its commit */ 1378141cc406Sopenharmony_ci sanei_rts88xx_cancel (dev->devnum); 1379141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x08); 1380141cc406Sopenharmony_ci status = sanei_rts88xx_write_control (dev->devnum, 0x08); 1381141cc406Sopenharmony_ci 1382141cc406Sopenharmony_ci session->scanning = SANE_TRUE; 1383141cc406Sopenharmony_ci 1384141cc406Sopenharmony_ci DBG (DBG_proc, "sane_start: exit\n"); 1385141cc406Sopenharmony_ci return status; 1386141cc406Sopenharmony_ci} 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci/** 1389141cc406Sopenharmony_ci * This function computes two set of parameters. The one for the SANE's standard 1390141cc406Sopenharmony_ci * and the other for the hardware. Among these parameters are the bit depth, total 1391141cc406Sopenharmony_ci * number of lines, total number of columns, extra line to read for data reordering... 1392141cc406Sopenharmony_ci */ 1393141cc406Sopenharmony_cistatic SANE_Status 1394141cc406Sopenharmony_cicompute_parameters (Rts8891_Session * session) 1395141cc406Sopenharmony_ci{ 1396141cc406Sopenharmony_ci Rts8891_Device *dev = session->dev; 1397141cc406Sopenharmony_ci SANE_Int dpi; /* dpi for scan */ 1398141cc406Sopenharmony_ci SANE_String mode; 1399141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 1400141cc406Sopenharmony_ci SANE_Int yshift; 1401141cc406Sopenharmony_ci SANE_Int xshift; 1402141cc406Sopenharmony_ci 1403141cc406Sopenharmony_ci int tl_x, tl_y, br_x, br_y; 1404141cc406Sopenharmony_ci 1405141cc406Sopenharmony_ci mode = session->val[OPT_MODE].s; 1406141cc406Sopenharmony_ci dpi = session->val[OPT_RESOLUTION].w; 1407141cc406Sopenharmony_ci 1408141cc406Sopenharmony_ci /* scan coordinates */ 1409141cc406Sopenharmony_ci tl_x = SANE_UNFIX (session->val[OPT_TL_X].w); 1410141cc406Sopenharmony_ci tl_y = SANE_UNFIX (session->val[OPT_TL_Y].w); 1411141cc406Sopenharmony_ci br_x = SANE_UNFIX (session->val[OPT_BR_X].w); 1412141cc406Sopenharmony_ci br_y = SANE_UNFIX (session->val[OPT_BR_Y].w); 1413141cc406Sopenharmony_ci 1414141cc406Sopenharmony_ci /* only single pass scanning supported */ 1415141cc406Sopenharmony_ci session->params.last_frame = SANE_TRUE; 1416141cc406Sopenharmony_ci session->emulated_gray = SANE_FALSE; 1417141cc406Sopenharmony_ci 1418141cc406Sopenharmony_ci /* gray modes */ 1419141cc406Sopenharmony_ci dev->threshold = (255 * SANE_UNFIX (session->val[OPT_THRESHOLD].w)) / 100; 1420141cc406Sopenharmony_ci if (strcmp (mode, GRAY_MODE) == 0 || strcmp (mode, LINEART_MODE) == 0) 1421141cc406Sopenharmony_ci { 1422141cc406Sopenharmony_ci session->params.format = SANE_FRAME_GRAY; 1423141cc406Sopenharmony_ci if (dev->model->flags & RTS8891_FLAG_EMULATED_GRAY_MODE) 1424141cc406Sopenharmony_ci session->emulated_gray = SANE_TRUE; 1425141cc406Sopenharmony_ci } 1426141cc406Sopenharmony_ci else 1427141cc406Sopenharmony_ci { 1428141cc406Sopenharmony_ci /* Color */ 1429141cc406Sopenharmony_ci session->params.format = SANE_FRAME_RGB; 1430141cc406Sopenharmony_ci } 1431141cc406Sopenharmony_ci 1432141cc406Sopenharmony_ci /* SANE level values */ 1433141cc406Sopenharmony_ci session->params.lines = ((br_y - tl_y) * dpi) / MM_PER_INCH; 1434141cc406Sopenharmony_ci if (session->params.lines == 0) 1435141cc406Sopenharmony_ci session->params.lines = 1; 1436141cc406Sopenharmony_ci session->params.pixels_per_line = ((br_x - tl_x) * dpi) / MM_PER_INCH; 1437141cc406Sopenharmony_ci if (session->params.pixels_per_line == 0) 1438141cc406Sopenharmony_ci session->params.pixels_per_line = 1; 1439141cc406Sopenharmony_ci 1440141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n", 1441141cc406Sopenharmony_ci session->params.pixels_per_line); 1442141cc406Sopenharmony_ci 1443141cc406Sopenharmony_ci if (strcmp (mode, LINEART_MODE) == 0) 1444141cc406Sopenharmony_ci { 1445141cc406Sopenharmony_ci session->params.depth = 1; 1446141cc406Sopenharmony_ci /* in lineart, having pixels multiple of 8 avoids a costly test */ 1447141cc406Sopenharmony_ci /* at each bit to see we must go to the next byte */ 1448141cc406Sopenharmony_ci /* TODO : implement this requirement in sane_control_option */ 1449141cc406Sopenharmony_ci session->params.pixels_per_line = 1450141cc406Sopenharmony_ci ((session->params.pixels_per_line + 7) / 8) * 8; 1451141cc406Sopenharmony_ci } 1452141cc406Sopenharmony_ci else 1453141cc406Sopenharmony_ci session->params.depth = 8; 1454141cc406Sopenharmony_ci 1455141cc406Sopenharmony_ci /* width needs to be even */ 1456141cc406Sopenharmony_ci if (session->params.pixels_per_line & 1) 1457141cc406Sopenharmony_ci session->params.pixels_per_line++; 1458141cc406Sopenharmony_ci 1459141cc406Sopenharmony_ci /* Hardware settings : they can differ from the ones at SANE level */ 1460141cc406Sopenharmony_ci /* for instance the effective DPI used by a sensor may be higher */ 1461141cc406Sopenharmony_ci /* than the one needed for the SANE scan parameters */ 1462141cc406Sopenharmony_ci dev->lines = session->params.lines; 1463141cc406Sopenharmony_ci dev->pixels = session->params.pixels_per_line; 1464141cc406Sopenharmony_ci 1465141cc406Sopenharmony_ci /* motor and sensor DPI */ 1466141cc406Sopenharmony_ci dev->xdpi = dpi; 1467141cc406Sopenharmony_ci dev->ydpi = dpi; 1468141cc406Sopenharmony_ci 1469141cc406Sopenharmony_ci /* handle bounds of motor's dpi range */ 1470141cc406Sopenharmony_ci if (dev->ydpi > dev->model->max_ydpi) 1471141cc406Sopenharmony_ci { 1472141cc406Sopenharmony_ci dev->ydpi = dev->model->max_ydpi; 1473141cc406Sopenharmony_ci dev->lines = (dev->lines * dev->model->max_ydpi) / dpi; 1474141cc406Sopenharmony_ci if (dev->lines == 0) 1475141cc406Sopenharmony_ci dev->lines = 1; 1476141cc406Sopenharmony_ci 1477141cc406Sopenharmony_ci /* round number of lines */ 1478141cc406Sopenharmony_ci session->params.lines = 1479141cc406Sopenharmony_ci (session->params.lines / dev->lines) * dev->lines; 1480141cc406Sopenharmony_ci if (session->params.lines == 0) 1481141cc406Sopenharmony_ci session->params.lines = 1; 1482141cc406Sopenharmony_ci } 1483141cc406Sopenharmony_ci if (dev->ydpi < dev->model->min_ydpi) 1484141cc406Sopenharmony_ci { 1485141cc406Sopenharmony_ci dev->ydpi = dev->model->min_ydpi; 1486141cc406Sopenharmony_ci dev->lines = (dev->lines * dev->model->min_ydpi) / dpi; 1487141cc406Sopenharmony_ci } 1488141cc406Sopenharmony_ci 1489141cc406Sopenharmony_ci /* hardware values */ 1490141cc406Sopenharmony_ci dev->xstart = 1491141cc406Sopenharmony_ci ((SANE_UNFIX (dev->model->x_offset) + tl_x) * dev->xdpi) / MM_PER_INCH; 1492141cc406Sopenharmony_ci dev->ystart = 1493141cc406Sopenharmony_ci ((SANE_UNFIX (dev->model->y_offset) + tl_y) * dev->ydpi) / MM_PER_INCH; 1494141cc406Sopenharmony_ci 1495141cc406Sopenharmony_ci /* xstart needs to be even */ 1496141cc406Sopenharmony_ci if (dev->xstart & 1) 1497141cc406Sopenharmony_ci dev->xstart++; 1498141cc406Sopenharmony_ci 1499141cc406Sopenharmony_ci /* computes bytes per line */ 1500141cc406Sopenharmony_ci session->params.bytes_per_line = session->params.pixels_per_line; 1501141cc406Sopenharmony_ci dev->bytes_per_line = dev->pixels; 1502141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_RGB 1503141cc406Sopenharmony_ci || session->emulated_gray == SANE_TRUE) 1504141cc406Sopenharmony_ci { 1505141cc406Sopenharmony_ci if (session->emulated_gray != SANE_TRUE) 1506141cc406Sopenharmony_ci { 1507141cc406Sopenharmony_ci session->params.bytes_per_line *= 3; 1508141cc406Sopenharmony_ci } 1509141cc406Sopenharmony_ci dev->bytes_per_line *= 3; 1510141cc406Sopenharmony_ci } 1511141cc406Sopenharmony_ci session->to_send = session->params.bytes_per_line * session->params.lines; 1512141cc406Sopenharmony_ci 1513141cc406Sopenharmony_ci /* in lineart mode we adjust bytes_per_line needed by frontend */ 1514141cc406Sopenharmony_ci /* we do that here because we needed sent/to_send to be as if */ 1515141cc406Sopenharmony_ci /* there was no lineart */ 1516141cc406Sopenharmony_ci if (session->params.depth == 1) 1517141cc406Sopenharmony_ci { 1518141cc406Sopenharmony_ci session->params.bytes_per_line = 1519141cc406Sopenharmony_ci (session->params.bytes_per_line + 7) / 8; 1520141cc406Sopenharmony_ci } 1521141cc406Sopenharmony_ci 1522141cc406Sopenharmony_ci /* compute how many extra bytes we need to reorder data */ 1523141cc406Sopenharmony_ci dev->ripple = 0; 1524141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_RGB 1525141cc406Sopenharmony_ci || session->emulated_gray == SANE_TRUE) 1526141cc406Sopenharmony_ci { 1527141cc406Sopenharmony_ci dev->lds_r 1528141cc406Sopenharmony_ci = ((dev->model->ld_shift_r * dev->ydpi) / dev->model->max_ydpi) 1529141cc406Sopenharmony_ci * dev->bytes_per_line; 1530141cc406Sopenharmony_ci dev->lds_g 1531141cc406Sopenharmony_ci = ((dev->model->ld_shift_g * dev->ydpi) / dev->model->max_ydpi) 1532141cc406Sopenharmony_ci * dev->bytes_per_line; 1533141cc406Sopenharmony_ci dev->lds_b 1534141cc406Sopenharmony_ci = ((dev->model->ld_shift_b * dev->ydpi) / dev->model->max_ydpi) 1535141cc406Sopenharmony_ci * dev->bytes_per_line; 1536141cc406Sopenharmony_ci if (dev->xdpi == dev->model->max_xdpi) 1537141cc406Sopenharmony_ci { 1538141cc406Sopenharmony_ci dev->ripple = 2 * dev->bytes_per_line; 1539141cc406Sopenharmony_ci } 1540141cc406Sopenharmony_ci } 1541141cc406Sopenharmony_ci else 1542141cc406Sopenharmony_ci { 1543141cc406Sopenharmony_ci dev->lds_r = 0; 1544141cc406Sopenharmony_ci dev->lds_g = 0; 1545141cc406Sopenharmony_ci dev->lds_b = 0; 1546141cc406Sopenharmony_ci } 1547141cc406Sopenharmony_ci 1548141cc406Sopenharmony_ci /* pick max lds value */ 1549141cc406Sopenharmony_ci dev->lds_max = dev->lds_r; 1550141cc406Sopenharmony_ci if (dev->lds_g > dev->lds_max) 1551141cc406Sopenharmony_ci dev->lds_max = dev->lds_g; 1552141cc406Sopenharmony_ci if (dev->lds_b > dev->lds_max) 1553141cc406Sopenharmony_ci dev->lds_max = dev->lds_b; 1554141cc406Sopenharmony_ci 1555141cc406Sopenharmony_ci /* since the extra lines for reordering are before data */ 1556141cc406Sopenharmony_ci /* we subtract lds_max */ 1557141cc406Sopenharmony_ci dev->lds_r -= dev->lds_max; 1558141cc406Sopenharmony_ci dev->lds_g -= dev->lds_max; 1559141cc406Sopenharmony_ci dev->lds_b -= dev->lds_max; 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ci /* we need to add extra line to handle line distance reordering */ 1562141cc406Sopenharmony_ci /* highest correction value is the blue one for our case */ 1563141cc406Sopenharmony_ci /* decrease y start to take these extra lines into account */ 1564141cc406Sopenharmony_ci dev->lines += (dev->lds_max + dev->ripple) / dev->bytes_per_line; 1565141cc406Sopenharmony_ci 1566141cc406Sopenharmony_ci /* shading calibration is always 66 lines regardless of ydpi, so */ 1567141cc406Sopenharmony_ci /* we take this into account to compute ystart */ 1568141cc406Sopenharmony_ci if (dev->ydpi > dev->model->min_ydpi) 1569141cc406Sopenharmony_ci { 1570141cc406Sopenharmony_ci /* no that clean, but works ... */ 1571141cc406Sopenharmony_ci switch (dev->ydpi) 1572141cc406Sopenharmony_ci { 1573141cc406Sopenharmony_ci case 300: 1574141cc406Sopenharmony_ci yshift = 0; 1575141cc406Sopenharmony_ci break; 1576141cc406Sopenharmony_ci case 600: 1577141cc406Sopenharmony_ci yshift = 33; 1578141cc406Sopenharmony_ci break; 1579141cc406Sopenharmony_ci default: 1580141cc406Sopenharmony_ci yshift = 0; 1581141cc406Sopenharmony_ci } 1582141cc406Sopenharmony_ci dev->ystart += yshift; 1583141cc406Sopenharmony_ci } 1584141cc406Sopenharmony_ci dev->ystart -= (dev->lds_max + dev->ripple) / dev->bytes_per_line; 1585141cc406Sopenharmony_ci 1586141cc406Sopenharmony_ci /* 1200 and 600 dpi scans seems to have other timings that 1587141cc406Sopenharmony_ci * need their own xstart */ 1588141cc406Sopenharmony_ci /* no that clean, but works ... */ 1589141cc406Sopenharmony_ci switch (dev->xdpi) 1590141cc406Sopenharmony_ci { 1591141cc406Sopenharmony_ci case 600: 1592141cc406Sopenharmony_ci xshift = -38; 1593141cc406Sopenharmony_ci break; 1594141cc406Sopenharmony_ci case 1200: 1595141cc406Sopenharmony_ci xshift = -76; 1596141cc406Sopenharmony_ci break; 1597141cc406Sopenharmony_ci default: 1598141cc406Sopenharmony_ci xshift = 0; 1599141cc406Sopenharmony_ci } 1600141cc406Sopenharmony_ci dev->xstart += xshift; 1601141cc406Sopenharmony_ci 1602141cc406Sopenharmony_ci dev->read = 0; 1603141cc406Sopenharmony_ci dev->to_read = dev->lines * dev->bytes_per_line; 1604141cc406Sopenharmony_ci 1605141cc406Sopenharmony_ci /* compute best size for scanned data buffer */ 1606141cc406Sopenharmony_ci /* we must have a round number of lines, with */ 1607141cc406Sopenharmony_ci /* enough space to handle line distance shift */ 1608141cc406Sopenharmony_ci if (dev->xdpi < dev->model->max_ydpi) 1609141cc406Sopenharmony_ci { 1610141cc406Sopenharmony_ci dev->data_size = 1611141cc406Sopenharmony_ci (PREFERED_BUFFER_SIZE / dev->bytes_per_line) * (dev->bytes_per_line); 1612141cc406Sopenharmony_ci } 1613141cc406Sopenharmony_ci else 1614141cc406Sopenharmony_ci { 1615141cc406Sopenharmony_ci dev->data_size = 1616141cc406Sopenharmony_ci (((PREFERED_BUFFER_SIZE / 2) - dev->lds_max - 1617141cc406Sopenharmony_ci dev->ripple) / dev->bytes_per_line) * dev->bytes_per_line; 1618141cc406Sopenharmony_ci } 1619141cc406Sopenharmony_ci 1620141cc406Sopenharmony_ci /* 32 lines minimum in buffer */ 1621141cc406Sopenharmony_ci if (dev->data_size < 32 * dev->bytes_per_line) 1622141cc406Sopenharmony_ci dev->data_size = 32 * dev->bytes_per_line; 1623141cc406Sopenharmony_ci 1624141cc406Sopenharmony_ci /* buffer must be smaller than total amount to read from session */ 1625141cc406Sopenharmony_ci if (dev->data_size > dev->to_read) 1626141cc406Sopenharmony_ci dev->data_size = dev->to_read; 1627141cc406Sopenharmony_ci 1628141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: bytes_per_line =%d\n", 1629141cc406Sopenharmony_ci session->params.bytes_per_line); 1630141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: depth =%d\n", 1631141cc406Sopenharmony_ci session->params.depth); 1632141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: lines =%d\n", 1633141cc406Sopenharmony_ci session->params.lines); 1634141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n", 1635141cc406Sopenharmony_ci session->params.pixels_per_line); 1636141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: image size =%d\n", 1637141cc406Sopenharmony_ci session->to_send); 1638141cc406Sopenharmony_ci 1639141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: xstart =%d\n", dev->xstart); 1640141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: ystart =%d\n", dev->ystart); 1641141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev lines =%d\n", dev->lines); 1642141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev extra lines =%d\n", 1643141cc406Sopenharmony_ci (dev->lds_max + dev->ripple) / dev->bytes_per_line); 1644141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev bytes per line=%d\n", 1645141cc406Sopenharmony_ci dev->bytes_per_line); 1646141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: dev pixels =%d\n", dev->pixels); 1647141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: data size =%d\n", 1648141cc406Sopenharmony_ci dev->data_size); 1649141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: to read =%d\n", dev->to_read); 1650141cc406Sopenharmony_ci DBG (DBG_data, "compute_parameters: threshold =%d\n", 1651141cc406Sopenharmony_ci dev->threshold); 1652141cc406Sopenharmony_ci 1653141cc406Sopenharmony_ci return status; 1654141cc406Sopenharmony_ci} 1655141cc406Sopenharmony_ci 1656141cc406Sopenharmony_ci 1657141cc406Sopenharmony_ci/** 1658141cc406Sopenharmony_ci * Called by SANE to retrieve information about the type of data 1659141cc406Sopenharmony_ci * that the current scan will return. 1660141cc406Sopenharmony_ci * 1661141cc406Sopenharmony_ci * From the SANE spec: 1662141cc406Sopenharmony_ci * This function is used to obtain the current scan parameters. The 1663141cc406Sopenharmony_ci * returned parameters are guaranteed to be accurate between the time 1664141cc406Sopenharmony_ci * a scan has been started (sane_start() has been called) and the 1665141cc406Sopenharmony_ci * completion of that request. Outside of that window, the returned 1666141cc406Sopenharmony_ci * values are best-effort estimates of what the parameters will be 1667141cc406Sopenharmony_ci * when sane_start() gets invoked. 1668141cc406Sopenharmony_ci * 1669141cc406Sopenharmony_ci * Calling this function before a scan has actually started allows, 1670141cc406Sopenharmony_ci * for example, to get an estimate of how big the scanned image will 1671141cc406Sopenharmony_ci * be. The parameters passed to this function are the handle of the 1672141cc406Sopenharmony_ci * device for which the parameters should be obtained and a pointer 1673141cc406Sopenharmony_ci * to a parameter structure. 1674141cc406Sopenharmony_ci */ 1675141cc406Sopenharmony_ciSANE_Status 1676141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params) 1677141cc406Sopenharmony_ci{ 1678141cc406Sopenharmony_ci SANE_Status status; 1679141cc406Sopenharmony_ci struct Rts8891_Session *session = (struct Rts8891_Session *) handle; 1680141cc406Sopenharmony_ci 1681141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: start\n"); 1682141cc406Sopenharmony_ci 1683141cc406Sopenharmony_ci /* call parameters computing function */ 1684141cc406Sopenharmony_ci status = compute_parameters (session); 1685141cc406Sopenharmony_ci if (status == SANE_STATUS_GOOD && params) 1686141cc406Sopenharmony_ci *params = session->params; 1687141cc406Sopenharmony_ci 1688141cc406Sopenharmony_ci DBG (DBG_proc, "sane_get_parameters: exit\n"); 1689141cc406Sopenharmony_ci return status; 1690141cc406Sopenharmony_ci} 1691141cc406Sopenharmony_ci 1692141cc406Sopenharmony_ci 1693141cc406Sopenharmony_ci/** 1694141cc406Sopenharmony_ci * Called by SANE to read data. 1695141cc406Sopenharmony_ci * 1696141cc406Sopenharmony_ci * From the SANE spec: 1697141cc406Sopenharmony_ci * This function is used to read image data from the device 1698141cc406Sopenharmony_ci * represented by handle h. Argument buf is a pointer to a memory 1699141cc406Sopenharmony_ci * area that is at least maxlen bytes long. The number of bytes 1700141cc406Sopenharmony_ci * returned is stored in *len. A backend must set this to zero when 1701141cc406Sopenharmony_ci * the call fails (i.e., when a status other than SANE_STATUS_GOOD is 1702141cc406Sopenharmony_ci * returned). 1703141cc406Sopenharmony_ci * 1704141cc406Sopenharmony_ci * When the call succeeds, the number of bytes returned can be 1705141cc406Sopenharmony_ci * anywhere in the range from 0 to maxlen bytes. 1706141cc406Sopenharmony_ci */ 1707141cc406Sopenharmony_ciSANE_Status 1708141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, 1709141cc406Sopenharmony_ci SANE_Int max_len, SANE_Int * len) 1710141cc406Sopenharmony_ci{ 1711141cc406Sopenharmony_ci struct Rts8891_Session *session; 1712141cc406Sopenharmony_ci struct Rts8891_Device *dev; 1713141cc406Sopenharmony_ci SANE_Status status; 1714141cc406Sopenharmony_ci SANE_Int length; 1715141cc406Sopenharmony_ci SANE_Int data_size; 1716141cc406Sopenharmony_ci SANE_Byte val = 0; 1717141cc406Sopenharmony_ci SANE_Int bit; 1718141cc406Sopenharmony_ci 1719141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: start\n"); 1720141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: up to %d bytes required by frontend\n", max_len); 1721141cc406Sopenharmony_ci 1722141cc406Sopenharmony_ci /* some sanity checks first to protect from would be buggy frontends */ 1723141cc406Sopenharmony_ci if (!handle) 1724141cc406Sopenharmony_ci { 1725141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: handle is null!\n"); 1726141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1727141cc406Sopenharmony_ci } 1728141cc406Sopenharmony_ci 1729141cc406Sopenharmony_ci session = (struct Rts8891_Session *) handle; 1730141cc406Sopenharmony_ci if (!session) 1731141cc406Sopenharmony_ci { 1732141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: session is null!\n"); 1733141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1734141cc406Sopenharmony_ci } 1735141cc406Sopenharmony_ci dev = session->dev; 1736141cc406Sopenharmony_ci 1737141cc406Sopenharmony_ci if (!buf) 1738141cc406Sopenharmony_ci { 1739141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: buf is null!\n"); 1740141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1741141cc406Sopenharmony_ci } 1742141cc406Sopenharmony_ci 1743141cc406Sopenharmony_ci if (!len) 1744141cc406Sopenharmony_ci { 1745141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: len is null!\n"); 1746141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1747141cc406Sopenharmony_ci } 1748141cc406Sopenharmony_ci 1749141cc406Sopenharmony_ci /* no data read yet */ 1750141cc406Sopenharmony_ci *len = 0; 1751141cc406Sopenharmony_ci buf[*len] = 0; 1752141cc406Sopenharmony_ci 1753141cc406Sopenharmony_ci /* check if session is scanning */ 1754141cc406Sopenharmony_ci if (!session->scanning) 1755141cc406Sopenharmony_ci { 1756141cc406Sopenharmony_ci DBG (DBG_warn, 1757141cc406Sopenharmony_ci "sane_read: scan was cancelled, is over or has not been initiated yet\n"); 1758141cc406Sopenharmony_ci return SANE_STATUS_CANCELLED; 1759141cc406Sopenharmony_ci } 1760141cc406Sopenharmony_ci 1761141cc406Sopenharmony_ci /* check for EOF, must be done before any physical read */ 1762141cc406Sopenharmony_ci if (session->sent >= session->to_send) 1763141cc406Sopenharmony_ci { 1764141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: end of scan reached\n"); 1765141cc406Sopenharmony_ci 1766141cc406Sopenharmony_ci /* signal end of scanning */ 1767141cc406Sopenharmony_ci session->scanning=SANE_FALSE; 1768141cc406Sopenharmony_ci 1769141cc406Sopenharmony_ci /* send asynchronous head parking command then return */ 1770141cc406Sopenharmony_ci park_head (session->dev, SANE_FALSE); 1771141cc406Sopenharmony_ci return SANE_STATUS_EOF; 1772141cc406Sopenharmony_ci } 1773141cc406Sopenharmony_ci 1774141cc406Sopenharmony_ci dev->regs[LAMP_REG] = 0xad; 1775141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); 1776141cc406Sopenharmony_ci 1777141cc406Sopenharmony_ci /* byte length for high dpi mode */ 1778141cc406Sopenharmony_ci length = (session->params.bytes_per_line * 8) / session->params.depth; 1779141cc406Sopenharmony_ci 1780141cc406Sopenharmony_ci /* checks if buffer has been pre filled with the extra data needed for */ 1781141cc406Sopenharmony_ci /* line distance reordering */ 1782141cc406Sopenharmony_ci if (dev->read == 0 1783141cc406Sopenharmony_ci && (session->params.format == SANE_FRAME_RGB 1784141cc406Sopenharmony_ci || session->emulated_gray == SANE_TRUE)) 1785141cc406Sopenharmony_ci { 1786141cc406Sopenharmony_ci /* the data need if the size of the highest line distance shift */ 1787141cc406Sopenharmony_ci /* we must only read what's needed */ 1788141cc406Sopenharmony_ci data_size = dev->data_size + dev->lds_max + dev->ripple; 1789141cc406Sopenharmony_ci if (dev->to_read - dev->read < data_size) 1790141cc406Sopenharmony_ci data_size = dev->to_read - dev->read; 1791141cc406Sopenharmony_ci 1792141cc406Sopenharmony_ci status = read_data (session, dev->scanned_data, data_size); 1793141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY) 1794141cc406Sopenharmony_ci { 1795141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: no data currently available\n"); 1796141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1797141cc406Sopenharmony_ci } 1798141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1799141cc406Sopenharmony_ci { 1800141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: failed to read data from scanner\n"); 1801141cc406Sopenharmony_ci return status; 1802141cc406Sopenharmony_ci } 1803141cc406Sopenharmony_ci 1804141cc406Sopenharmony_ci /* now buffer is filled with data and an extra amount for line reordering */ 1805141cc406Sopenharmony_ci dev->current = dev->start; 1806141cc406Sopenharmony_ci } 1807141cc406Sopenharmony_ci 1808141cc406Sopenharmony_ci /* if all buffer has been used, get the next block of data from scanner */ 1809141cc406Sopenharmony_ci if (dev->read == 0 || dev->current >= dev->end) 1810141cc406Sopenharmony_ci { 1811141cc406Sopenharmony_ci /* effective buffer filling */ 1812141cc406Sopenharmony_ci /* we must only read what's needed */ 1813141cc406Sopenharmony_ci data_size = dev->data_size; 1814141cc406Sopenharmony_ci if (dev->to_read - dev->read < data_size) 1815141cc406Sopenharmony_ci data_size = dev->to_read - dev->read; 1816141cc406Sopenharmony_ci 1817141cc406Sopenharmony_ci status = read_data (session, dev->start, data_size); 1818141cc406Sopenharmony_ci if (status == SANE_STATUS_DEVICE_BUSY) 1819141cc406Sopenharmony_ci { 1820141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: no data currently available\n"); 1821141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1822141cc406Sopenharmony_ci } 1823141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 1824141cc406Sopenharmony_ci { 1825141cc406Sopenharmony_ci DBG (DBG_error, "sane_read: failed to read data from scanner\n"); 1826141cc406Sopenharmony_ci return status; 1827141cc406Sopenharmony_ci } 1828141cc406Sopenharmony_ci 1829141cc406Sopenharmony_ci /* reset current pointer */ 1830141cc406Sopenharmony_ci dev->current = dev->start; 1831141cc406Sopenharmony_ci } 1832141cc406Sopenharmony_ci 1833141cc406Sopenharmony_ci dev->regs[LAMP_REG] = 0x8d; 1834141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); 1835141cc406Sopenharmony_ci 1836141cc406Sopenharmony_ci /* it seems there is no gray or lineart hardware mode for the rts8891 */ 1837141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_GRAY 1838141cc406Sopenharmony_ci && session->emulated_gray == SANE_FALSE) 1839141cc406Sopenharmony_ci { 1840141cc406Sopenharmony_ci DBG (DBG_error0, "sane_read: unimplemented native gray scanning\n"); 1841141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1842141cc406Sopenharmony_ci } 1843141cc406Sopenharmony_ci else /* hardware data is 3 bytes/per pixels */ 1844141cc406Sopenharmony_ci { 1845141cc406Sopenharmony_ci /* we return as much data as possible from current buffer */ 1846141cc406Sopenharmony_ci /* if buffer is smaller than what is asked, we only return */ 1847141cc406Sopenharmony_ci 1848141cc406Sopenharmony_ci /* here we have made sure there is something to read from data buffers */ 1849141cc406Sopenharmony_ci /* data from scanner is in R,G,B format, but we have to cope with line */ 1850141cc406Sopenharmony_ci /* distance correction. We also take care that motor resolution may be */ 1851141cc406Sopenharmony_ci /* higher than the scan resolution asked for some modes. */ 1852141cc406Sopenharmony_ci /* We also handle emulated color mode */ 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci /* we loop until we reach max_len or end of data buffer */ 1855141cc406Sopenharmony_ci /* or we sent what we advised to frontend */ 1856141cc406Sopenharmony_ci while (dev->current < dev->end && *len < max_len 1857141cc406Sopenharmony_ci && session->sent < session->to_send) 1858141cc406Sopenharmony_ci { 1859141cc406Sopenharmony_ci /* data is received in RGB format */ 1860141cc406Sopenharmony_ci /* these switches are there to handle reads not aligned 1861141cc406Sopenharmony_ci * on pixels that are allowed by the SANE standard */ 1862141cc406Sopenharmony_ci if (dev->xdpi == dev->model->max_xdpi) 1863141cc406Sopenharmony_ci { /* at max xdpi, data received is distorted and ydpi is half of xdpi */ 1864141cc406Sopenharmony_ci if (session->emulated_gray == SANE_TRUE) 1865141cc406Sopenharmony_ci { 1866141cc406Sopenharmony_ci /* in emulated gray mode we are always reading 3 bytes of raw data */ 1867141cc406Sopenharmony_ci /* at a time */ 1868141cc406Sopenharmony_ci switch (((session->sent * 3) % dev->bytes_per_line) % 6) 1869141cc406Sopenharmony_ci { 1870141cc406Sopenharmony_ci case 0: 1871141cc406Sopenharmony_ci case 1: 1872141cc406Sopenharmony_ci case 2: 1873141cc406Sopenharmony_ci val = dev->current[dev->lds_g]; 1874141cc406Sopenharmony_ci break; 1875141cc406Sopenharmony_ci case 3: 1876141cc406Sopenharmony_ci case 4: 1877141cc406Sopenharmony_ci case 5: 1878141cc406Sopenharmony_ci val = dev->current[dev->lds_g - dev->ripple]; 1879141cc406Sopenharmony_ci break; 1880141cc406Sopenharmony_ci } 1881141cc406Sopenharmony_ci 1882141cc406Sopenharmony_ci if (session->params.depth == 1) 1883141cc406Sopenharmony_ci { 1884141cc406Sopenharmony_ci bit = 7 - (session->sent) % 8; 1885141cc406Sopenharmony_ci if (val <= dev->threshold) 1886141cc406Sopenharmony_ci { 1887141cc406Sopenharmony_ci buf[*len] |= 1 << bit; 1888141cc406Sopenharmony_ci } 1889141cc406Sopenharmony_ci if (bit == 0) 1890141cc406Sopenharmony_ci { 1891141cc406Sopenharmony_ci (*len)++; 1892141cc406Sopenharmony_ci buf[*len] = 0; 1893141cc406Sopenharmony_ci } 1894141cc406Sopenharmony_ci } 1895141cc406Sopenharmony_ci else 1896141cc406Sopenharmony_ci { 1897141cc406Sopenharmony_ci buf[*len] = val; 1898141cc406Sopenharmony_ci (*len)++; 1899141cc406Sopenharmony_ci } 1900141cc406Sopenharmony_ci session->sent++; 1901141cc406Sopenharmony_ci dev->current += 3; 1902141cc406Sopenharmony_ci } 1903141cc406Sopenharmony_ci else 1904141cc406Sopenharmony_ci { 1905141cc406Sopenharmony_ci switch ((session->sent % dev->bytes_per_line) % 6) 1906141cc406Sopenharmony_ci { 1907141cc406Sopenharmony_ci case 0: 1908141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_r]; 1909141cc406Sopenharmony_ci break; 1910141cc406Sopenharmony_ci case 1: 1911141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_g]; 1912141cc406Sopenharmony_ci break; 1913141cc406Sopenharmony_ci case 2: 1914141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_b]; 1915141cc406Sopenharmony_ci break; 1916141cc406Sopenharmony_ci case 3: 1917141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_r - dev->ripple]; 1918141cc406Sopenharmony_ci break; 1919141cc406Sopenharmony_ci case 4: 1920141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_g - dev->ripple]; 1921141cc406Sopenharmony_ci break; 1922141cc406Sopenharmony_ci case 5: 1923141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_b - dev->ripple]; 1924141cc406Sopenharmony_ci break; 1925141cc406Sopenharmony_ci } 1926141cc406Sopenharmony_ci (*len)++; 1927141cc406Sopenharmony_ci session->sent++; 1928141cc406Sopenharmony_ci dev->current++; 1929141cc406Sopenharmony_ci } 1930141cc406Sopenharmony_ci 1931141cc406Sopenharmony_ci /* we currently double lines to have match xdpy */ 1932141cc406Sopenharmony_ci /* so we logically rewind for each odd line */ 1933141cc406Sopenharmony_ci /* we test at start of a scanned picture line */ 1934141cc406Sopenharmony_ci if (((session->sent / length) % 2 == 1) 1935141cc406Sopenharmony_ci && (session->sent % length == 0)) 1936141cc406Sopenharmony_ci { 1937141cc406Sopenharmony_ci DBG (DBG_io, 1938141cc406Sopenharmony_ci "sane_read: rewind by %d bytes after %d bytes sent\n", 1939141cc406Sopenharmony_ci dev->bytes_per_line, session->sent); 1940141cc406Sopenharmony_ci dev->current -= dev->bytes_per_line; 1941141cc406Sopenharmony_ci } 1942141cc406Sopenharmony_ci } 1943141cc406Sopenharmony_ci else if (dev->ydpi == session->val[OPT_RESOLUTION].w) 1944141cc406Sopenharmony_ci { 1945141cc406Sopenharmony_ci if (session->emulated_gray == SANE_TRUE) 1946141cc406Sopenharmony_ci { 1947141cc406Sopenharmony_ci /* in emulated gray mode we are always reading 3 bytes of raw data */ 1948141cc406Sopenharmony_ci /* at a time, so we know where we are */ 1949141cc406Sopenharmony_ci val = dev->current[dev->lds_g]; 1950141cc406Sopenharmony_ci if (session->params.depth == 1) 1951141cc406Sopenharmony_ci { 1952141cc406Sopenharmony_ci bit = 7 - (session->sent) % 8; 1953141cc406Sopenharmony_ci if (val <= dev->threshold) 1954141cc406Sopenharmony_ci { 1955141cc406Sopenharmony_ci buf[*len] |= 1 << bit; 1956141cc406Sopenharmony_ci } 1957141cc406Sopenharmony_ci else 1958141cc406Sopenharmony_ci { 1959141cc406Sopenharmony_ci buf[*len] &= ~(1 << bit); 1960141cc406Sopenharmony_ci } 1961141cc406Sopenharmony_ci if (bit == 0) 1962141cc406Sopenharmony_ci { 1963141cc406Sopenharmony_ci (*len)++; 1964141cc406Sopenharmony_ci } 1965141cc406Sopenharmony_ci } 1966141cc406Sopenharmony_ci else 1967141cc406Sopenharmony_ci { 1968141cc406Sopenharmony_ci buf[*len] = val; 1969141cc406Sopenharmony_ci (*len)++; 1970141cc406Sopenharmony_ci } 1971141cc406Sopenharmony_ci session->sent++; 1972141cc406Sopenharmony_ci dev->current += 3; 1973141cc406Sopenharmony_ci } 1974141cc406Sopenharmony_ci else 1975141cc406Sopenharmony_ci { 1976141cc406Sopenharmony_ci switch ((dev->current - dev->start) % 3) 1977141cc406Sopenharmony_ci { 1978141cc406Sopenharmony_ci case 0: 1979141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_r]; 1980141cc406Sopenharmony_ci break; 1981141cc406Sopenharmony_ci case 1: 1982141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_g]; 1983141cc406Sopenharmony_ci break; 1984141cc406Sopenharmony_ci case 2: 1985141cc406Sopenharmony_ci buf[*len] = dev->current[dev->lds_b]; 1986141cc406Sopenharmony_ci break; 1987141cc406Sopenharmony_ci } 1988141cc406Sopenharmony_ci (*len)++; 1989141cc406Sopenharmony_ci session->sent++; 1990141cc406Sopenharmony_ci dev->current++; 1991141cc406Sopenharmony_ci } 1992141cc406Sopenharmony_ci } 1993141cc406Sopenharmony_ci else 1994141cc406Sopenharmony_ci { 1995141cc406Sopenharmony_ci /* we currently handle ydi=2*dpi */ 1996141cc406Sopenharmony_ci if (session->emulated_gray == SANE_TRUE) 1997141cc406Sopenharmony_ci { 1998141cc406Sopenharmony_ci /* in emulated gray mode we are always reading 3 bytes of raw data */ 1999141cc406Sopenharmony_ci /* at a time, so we know where we are */ 2000141cc406Sopenharmony_ci val = (dev->current[dev->lds_g] 2001141cc406Sopenharmony_ci + dev->current[dev->lds_g + 2002141cc406Sopenharmony_ci dev->bytes_per_line]) / 2; 2003141cc406Sopenharmony_ci if (session->params.depth == 1) 2004141cc406Sopenharmony_ci { 2005141cc406Sopenharmony_ci bit = 7 - (session->sent) % 8; 2006141cc406Sopenharmony_ci if (val <= dev->threshold) 2007141cc406Sopenharmony_ci { 2008141cc406Sopenharmony_ci buf[*len] |= 1 << bit; 2009141cc406Sopenharmony_ci } 2010141cc406Sopenharmony_ci else 2011141cc406Sopenharmony_ci { 2012141cc406Sopenharmony_ci buf[*len] &= ~(1 << bit); 2013141cc406Sopenharmony_ci } 2014141cc406Sopenharmony_ci if (bit == 0) 2015141cc406Sopenharmony_ci { 2016141cc406Sopenharmony_ci (*len)++; 2017141cc406Sopenharmony_ci } 2018141cc406Sopenharmony_ci } 2019141cc406Sopenharmony_ci else 2020141cc406Sopenharmony_ci { 2021141cc406Sopenharmony_ci buf[*len] = val; 2022141cc406Sopenharmony_ci (*len)++; 2023141cc406Sopenharmony_ci } 2024141cc406Sopenharmony_ci dev->current += 3; 2025141cc406Sopenharmony_ci } 2026141cc406Sopenharmony_ci else 2027141cc406Sopenharmony_ci { 2028141cc406Sopenharmony_ci switch ((dev->current - dev->start) % 3) 2029141cc406Sopenharmony_ci { 2030141cc406Sopenharmony_ci case 0: 2031141cc406Sopenharmony_ci buf[*len] = (dev->current[dev->lds_r] 2032141cc406Sopenharmony_ci + dev->current[dev->lds_r + 2033141cc406Sopenharmony_ci dev->bytes_per_line]) / 2; 2034141cc406Sopenharmony_ci break; 2035141cc406Sopenharmony_ci case 1: 2036141cc406Sopenharmony_ci buf[*len] = (dev->current[dev->lds_g] 2037141cc406Sopenharmony_ci + dev->current[dev->lds_g + 2038141cc406Sopenharmony_ci dev->bytes_per_line]) / 2; 2039141cc406Sopenharmony_ci break; 2040141cc406Sopenharmony_ci case 2: 2041141cc406Sopenharmony_ci buf[*len] = (dev->current[dev->lds_b] 2042141cc406Sopenharmony_ci + dev->current[dev->lds_b + 2043141cc406Sopenharmony_ci dev->bytes_per_line]) / 2; 2044141cc406Sopenharmony_ci break; 2045141cc406Sopenharmony_ci } 2046141cc406Sopenharmony_ci (*len)++; 2047141cc406Sopenharmony_ci dev->current++; 2048141cc406Sopenharmony_ci } 2049141cc406Sopenharmony_ci session->sent++; 2050141cc406Sopenharmony_ci 2051141cc406Sopenharmony_ci /* at the end of each line, we must count another one because */ 2052141cc406Sopenharmony_ci /* 2 lines are used to produce one */ 2053141cc406Sopenharmony_ci if ((dev->current - dev->start) % dev->bytes_per_line == 0) 2054141cc406Sopenharmony_ci dev->current += dev->bytes_per_line; 2055141cc406Sopenharmony_ci } 2056141cc406Sopenharmony_ci } 2057141cc406Sopenharmony_ci } 2058141cc406Sopenharmony_ci 2059141cc406Sopenharmony_ci /* if we exhausted data buffer, we prepare for the next read */ 2060141cc406Sopenharmony_ci /* in color mode, we need to copy the remainder of the */ 2061141cc406Sopenharmony_ci /* buffer because of line distance handling, when blue data */ 2062141cc406Sopenharmony_ci /* is exhausted, read and green haven't been fully read yet */ 2063141cc406Sopenharmony_ci if (dev->current >= dev->end 2064141cc406Sopenharmony_ci && (session->params.format == SANE_FRAME_RGB 2065141cc406Sopenharmony_ci || session->emulated_gray == SANE_TRUE)) 2066141cc406Sopenharmony_ci { 2067141cc406Sopenharmony_ci memcpy (dev->scanned_data, dev->end - (dev->lds_max + dev->ripple), 2068141cc406Sopenharmony_ci dev->lds_max + dev->ripple); 2069141cc406Sopenharmony_ci } 2070141cc406Sopenharmony_ci 2071141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 2072141cc406Sopenharmony_ci DBG (DBG_io, "sane_read: sent %d bytes to frontend\n", *len); 2073141cc406Sopenharmony_ci DBG (DBG_proc, "sane_read: exit\n"); 2074141cc406Sopenharmony_ci return status; 2075141cc406Sopenharmony_ci} 2076141cc406Sopenharmony_ci 2077141cc406Sopenharmony_ci 2078141cc406Sopenharmony_ci/** 2079141cc406Sopenharmony_ci * Cancels a scan. 2080141cc406Sopenharmony_ci * 2081141cc406Sopenharmony_ci * From the SANE spec: 2082141cc406Sopenharmony_ci * This function is used to immediately or as quickly as possible 2083141cc406Sopenharmony_ci * cancel the currently pending operation of the device represented by 2084141cc406Sopenharmony_ci * handle h. This function can be called at any time (as long as 2085141cc406Sopenharmony_ci * handle h is a valid handle) but usually affects long-running 2086141cc406Sopenharmony_ci * operations only (such as image is acquisition). It is safe to call 2087141cc406Sopenharmony_ci * this function asynchronously (e.g., from within a signal handler). 2088141cc406Sopenharmony_ci * It is important to note that completion of this operation does not 2089141cc406Sopenharmony_ci * imply that the currently pending operation has been cancelled. It 2090141cc406Sopenharmony_ci * only guarantees that cancellation has been initiated. Cancellation 2091141cc406Sopenharmony_ci * completes only when the cancelled call returns (typically with a 2092141cc406Sopenharmony_ci * status value of SANE_STATUS_CANCELLED). Since the SANE API does 2093141cc406Sopenharmony_ci * not require any other operations to be re-entrant, this implies 2094141cc406Sopenharmony_ci * that a frontend must not call any other operation until the 2095141cc406Sopenharmony_ci * cancelled operation has returned. 2096141cc406Sopenharmony_ci */ 2097141cc406Sopenharmony_civoid 2098141cc406Sopenharmony_cisane_cancel (SANE_Handle handle) 2099141cc406Sopenharmony_ci{ 2100141cc406Sopenharmony_ci Rts8891_Session *session = handle; 2101141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 2102141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 2103141cc406Sopenharmony_ci struct timeval current; 2104141cc406Sopenharmony_ci#endif 2105141cc406Sopenharmony_ci 2106141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: start\n"); 2107141cc406Sopenharmony_ci 2108141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 2109141cc406Sopenharmony_ci /* store last scan time for the device */ 2110141cc406Sopenharmony_ci gettimeofday (¤t, NULL); 2111141cc406Sopenharmony_ci dev->last_scan.tv_sec = current.tv_sec; 2112141cc406Sopenharmony_ci#endif 2113141cc406Sopenharmony_ci 2114141cc406Sopenharmony_ci /* if scanning, abort and park head */ 2115141cc406Sopenharmony_ci if (session->scanning == SANE_TRUE) 2116141cc406Sopenharmony_ci { 2117141cc406Sopenharmony_ci /* canceling while all data hasn't bee read */ 2118141cc406Sopenharmony_ci if (dev->read < dev->to_read) 2119141cc406Sopenharmony_ci { 2120141cc406Sopenharmony_ci sanei_rts88xx_cancel (dev->devnum); 2121141cc406Sopenharmony_ci usleep (500000); 2122141cc406Sopenharmony_ci sanei_rts88xx_cancel (dev->devnum); 2123141cc406Sopenharmony_ci } 2124141cc406Sopenharmony_ci session->scanning = SANE_FALSE; 2125141cc406Sopenharmony_ci 2126141cc406Sopenharmony_ci /* head parking */ 2127141cc406Sopenharmony_ci if (park_head (dev, SANE_FALSE) != SANE_STATUS_GOOD) 2128141cc406Sopenharmony_ci { 2129141cc406Sopenharmony_ci DBG (DBG_error, "sane_cancel: failed to park head!\n"); 2130141cc406Sopenharmony_ci } 2131141cc406Sopenharmony_ci } 2132141cc406Sopenharmony_ci 2133141cc406Sopenharmony_ci /* free resources used by scanning */ 2134141cc406Sopenharmony_ci if (dev->scanned_data != NULL) 2135141cc406Sopenharmony_ci { 2136141cc406Sopenharmony_ci free (dev->scanned_data); 2137141cc406Sopenharmony_ci dev->scanned_data = NULL; 2138141cc406Sopenharmony_ci } 2139141cc406Sopenharmony_ci if (dev->shading_data != NULL) 2140141cc406Sopenharmony_ci { 2141141cc406Sopenharmony_ci free (dev->shading_data); 2142141cc406Sopenharmony_ci dev->shading_data = NULL; 2143141cc406Sopenharmony_ci } 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_ci /* release the interface to allow device sharing */ 2146141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 2147141cc406Sopenharmony_ci { 2148141cc406Sopenharmony_ci sanei_usb_release_interface (dev->devnum, 0); 2149141cc406Sopenharmony_ci } 2150141cc406Sopenharmony_ci 2151141cc406Sopenharmony_ci DBG (DBG_proc, "sane_cancel: exit\n"); 2152141cc406Sopenharmony_ci} 2153141cc406Sopenharmony_ci 2154141cc406Sopenharmony_ci 2155141cc406Sopenharmony_ci/** 2156141cc406Sopenharmony_ci * Ends use of the session. 2157141cc406Sopenharmony_ci * 2158141cc406Sopenharmony_ci * From the SANE spec: 2159141cc406Sopenharmony_ci * This function terminates the association between the device handle 2160141cc406Sopenharmony_ci * passed in argument h and the device it represents. If the device is 2161141cc406Sopenharmony_ci * presently active, a call to sane_cancel() is performed first. After 2162141cc406Sopenharmony_ci * this function returns, handle h must not be used anymore. 2163141cc406Sopenharmony_ci * 2164141cc406Sopenharmony_ci * Handle resources are free'd before disposing the handle. But devices 2165141cc406Sopenharmony_ci * resources must not be mdofied, since it could be used or reused until 2166141cc406Sopenharmony_ci * sane_exit() is called. 2167141cc406Sopenharmony_ci */ 2168141cc406Sopenharmony_civoid 2169141cc406Sopenharmony_cisane_close (SANE_Handle handle) 2170141cc406Sopenharmony_ci{ 2171141cc406Sopenharmony_ci Rts8891_Session *prev, *session; 2172141cc406Sopenharmony_ci Rts8891_Device *dev; 2173141cc406Sopenharmony_ci int i; 2174141cc406Sopenharmony_ci 2175141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: start\n"); 2176141cc406Sopenharmony_ci 2177141cc406Sopenharmony_ci /* remove handle from list of open handles: */ 2178141cc406Sopenharmony_ci prev = NULL; 2179141cc406Sopenharmony_ci for (session = first_handle; session; session = session->next) 2180141cc406Sopenharmony_ci { 2181141cc406Sopenharmony_ci if (session == handle) 2182141cc406Sopenharmony_ci break; 2183141cc406Sopenharmony_ci prev = session; 2184141cc406Sopenharmony_ci } 2185141cc406Sopenharmony_ci if (!session) 2186141cc406Sopenharmony_ci { 2187141cc406Sopenharmony_ci DBG (DBG_error, "close: invalid handle %p\n", handle); 2188141cc406Sopenharmony_ci return; /* oops, not a handle we know about */ 2189141cc406Sopenharmony_ci } 2190141cc406Sopenharmony_ci 2191141cc406Sopenharmony_ci dev=session->dev; 2192141cc406Sopenharmony_ci 2193141cc406Sopenharmony_ci /* cancel any active scan */ 2194141cc406Sopenharmony_ci if (session->scanning == SANE_TRUE) 2195141cc406Sopenharmony_ci { 2196141cc406Sopenharmony_ci sane_cancel (handle); 2197141cc406Sopenharmony_ci } 2198141cc406Sopenharmony_ci /* if head is parking, wait for completion */ 2199141cc406Sopenharmony_ci if(dev->parking==SANE_TRUE) 2200141cc406Sopenharmony_ci { 2201141cc406Sopenharmony_ci rts8891_wait_for_home (dev, dev->regs); 2202141cc406Sopenharmony_ci } 2203141cc406Sopenharmony_ci set_lamp_brightness (dev, 0); 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci 2206141cc406Sopenharmony_ci if (prev) 2207141cc406Sopenharmony_ci prev->next = session->next; 2208141cc406Sopenharmony_ci else 2209141cc406Sopenharmony_ci first_handle = session->next; 2210141cc406Sopenharmony_ci 2211141cc406Sopenharmony_ci /* switch off lamp and close usb */ 2212141cc406Sopenharmony_ci if (dev->conf.allowsharing == SANE_TRUE) 2213141cc406Sopenharmony_ci { 2214141cc406Sopenharmony_ci SANE_Status status = sanei_usb_claim_interface (dev->devnum, 0); 2215141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2216141cc406Sopenharmony_ci { 2217141cc406Sopenharmony_ci DBG (DBG_warn, "sane_close: cannot claim usb interface: %s\n", 2218141cc406Sopenharmony_ci sane_strstatus(status)); 2219141cc406Sopenharmony_ci DBG (DBG_warn, "sane_close: continuing anyway\n"); 2220141cc406Sopenharmony_ci } 2221141cc406Sopenharmony_ci } 2222141cc406Sopenharmony_ci set_lamp_state (session, 0); 2223141cc406Sopenharmony_ci sanei_usb_close (dev->devnum); 2224141cc406Sopenharmony_ci 2225141cc406Sopenharmony_ci /* free per session data */ 2226141cc406Sopenharmony_ci if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR].wa) 2227141cc406Sopenharmony_ci free (session->val[OPT_GAMMA_VECTOR].wa); 2228141cc406Sopenharmony_ci if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_R].wa) 2229141cc406Sopenharmony_ci free (session->val[OPT_GAMMA_VECTOR_R].wa); 2230141cc406Sopenharmony_ci if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_G].wa) 2231141cc406Sopenharmony_ci free (session->val[OPT_GAMMA_VECTOR_G].wa); 2232141cc406Sopenharmony_ci if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_B].wa) 2233141cc406Sopenharmony_ci free (session->val[OPT_GAMMA_VECTOR_B].wa); 2234141cc406Sopenharmony_ci free (session->val[OPT_MODE].s); 2235141cc406Sopenharmony_ci free ((void *) session->opt[OPT_RESOLUTION].constraint.word_list); 2236141cc406Sopenharmony_ci for (i = OPT_BUTTON_1; i <= OPT_BUTTON_11; i++) 2237141cc406Sopenharmony_ci { 2238141cc406Sopenharmony_ci free ((void *) session->opt[i].name); 2239141cc406Sopenharmony_ci free ((void *) session->opt[i].title); 2240141cc406Sopenharmony_ci } 2241141cc406Sopenharmony_ci 2242141cc406Sopenharmony_ci free (session); 2243141cc406Sopenharmony_ci 2244141cc406Sopenharmony_ci DBG (DBG_proc, "sane_close: exit\n"); 2245141cc406Sopenharmony_ci} 2246141cc406Sopenharmony_ci 2247141cc406Sopenharmony_ci 2248141cc406Sopenharmony_ci/** 2249141cc406Sopenharmony_ci * Terminates the backend. 2250141cc406Sopenharmony_ci * 2251141cc406Sopenharmony_ci * From the SANE spec: 2252141cc406Sopenharmony_ci * This function must be called to terminate use of a backend. The 2253141cc406Sopenharmony_ci * function will first close all device handles that still might be 2254141cc406Sopenharmony_ci * open (it is recommended to close device handles explicitly through 2255141cc406Sopenharmony_ci * a call to sane_close(), but backends are required to release all 2256141cc406Sopenharmony_ci * resources upon a call to this function). After this function 2257141cc406Sopenharmony_ci * returns, no function other than sane_init() may be called 2258141cc406Sopenharmony_ci * (regardless of the status value returned by sane_exit(). Neglecting 2259141cc406Sopenharmony_ci * to call this function may result in some resources not being 2260141cc406Sopenharmony_ci * released properly. 2261141cc406Sopenharmony_ci */ 2262141cc406Sopenharmony_civoid 2263141cc406Sopenharmony_cisane_exit (void) 2264141cc406Sopenharmony_ci{ 2265141cc406Sopenharmony_ci struct Rts8891_Session *session, *next; 2266141cc406Sopenharmony_ci struct Rts8891_Device *dev, *nextdev; 2267141cc406Sopenharmony_ci int i; 2268141cc406Sopenharmony_ci 2269141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: start\n"); 2270141cc406Sopenharmony_ci 2271141cc406Sopenharmony_ci /* free session structs */ 2272141cc406Sopenharmony_ci for (session = first_handle; session; session = next) 2273141cc406Sopenharmony_ci { 2274141cc406Sopenharmony_ci next = session->next; 2275141cc406Sopenharmony_ci sane_close ((SANE_Handle *) session); 2276141cc406Sopenharmony_ci free (session); 2277141cc406Sopenharmony_ci } 2278141cc406Sopenharmony_ci first_handle = NULL; 2279141cc406Sopenharmony_ci 2280141cc406Sopenharmony_ci /* free devices structs */ 2281141cc406Sopenharmony_ci for (dev = first_device; dev; dev = nextdev) 2282141cc406Sopenharmony_ci { 2283141cc406Sopenharmony_ci nextdev = dev->next; 2284141cc406Sopenharmony_ci free (dev->file_name); 2285141cc406Sopenharmony_ci free (dev); 2286141cc406Sopenharmony_ci } 2287141cc406Sopenharmony_ci first_device = NULL; 2288141cc406Sopenharmony_ci 2289141cc406Sopenharmony_ci /* now list of devices */ 2290141cc406Sopenharmony_ci if (devlist) 2291141cc406Sopenharmony_ci { 2292141cc406Sopenharmony_ci for (i = 0; i < num_devices; i++) 2293141cc406Sopenharmony_ci { 2294141cc406Sopenharmony_ci free ((SANE_Device *) devlist[i]); 2295141cc406Sopenharmony_ci } 2296141cc406Sopenharmony_ci free (devlist); 2297141cc406Sopenharmony_ci devlist = NULL; 2298141cc406Sopenharmony_ci } 2299141cc406Sopenharmony_ci num_devices = 0; 2300141cc406Sopenharmony_ci 2301141cc406Sopenharmony_ci DBG (DBG_proc, "sane_exit: exit\n"); 2302141cc406Sopenharmony_ci} 2303141cc406Sopenharmony_ci 2304141cc406Sopenharmony_ci 2305141cc406Sopenharmony_ci/** This function tries to find plugged relevant devices 2306141cc406Sopenharmony_ci */ 2307141cc406Sopenharmony_cistatic SANE_Status 2308141cc406Sopenharmony_ciprobe_rts8891_devices (void) 2309141cc406Sopenharmony_ci{ 2310141cc406Sopenharmony_ci /**> configuration structure used during attach */ 2311141cc406Sopenharmony_ci SANEI_Config config; 2312141cc406Sopenharmony_ci /**> list of configuration options */ 2313141cc406Sopenharmony_ci SANE_Option_Descriptor *options[NUM_CFG_OPTIONS]; 2314141cc406Sopenharmony_ci /**> placeholders pointers for option values */ 2315141cc406Sopenharmony_ci void *values[NUM_CFG_OPTIONS]; 2316141cc406Sopenharmony_ci int i; 2317141cc406Sopenharmony_ci SANE_Status status; 2318141cc406Sopenharmony_ci 2319141cc406Sopenharmony_ci DBG (DBG_proc, "probe_rts8891_devices: start\n"); 2320141cc406Sopenharmony_ci 2321141cc406Sopenharmony_ci /* sharing is off by default and no model option */ 2322141cc406Sopenharmony_ci rtscfg.allowsharing = SANE_FALSE; 2323141cc406Sopenharmony_ci rtscfg.modelnumber = -1; 2324141cc406Sopenharmony_ci rtscfg.sensornumber = -1; 2325141cc406Sopenharmony_ci 2326141cc406Sopenharmony_ci /* initialize configuration options */ 2327141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER] = 2328141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 2329141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->name = "modelnumber"; 2330141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->desc = 2331141cc406Sopenharmony_ci "user provided scanner's internal model number"; 2332141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->type = SANE_TYPE_INT; 2333141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->unit = SANE_UNIT_NONE; 2334141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->size = sizeof (SANE_Word); 2335141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->cap = SANE_CAP_SOFT_SELECT; 2336141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->constraint_type = SANE_CONSTRAINT_RANGE; 2337141cc406Sopenharmony_ci options[CFG_MODEL_NUMBER]->constraint.range = &model_range; 2338141cc406Sopenharmony_ci values[CFG_MODEL_NUMBER] = &rtscfg.modelnumber; 2339141cc406Sopenharmony_ci 2340141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING] = 2341141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 2342141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->name = "allowsharing"; 2343141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->desc = 2344141cc406Sopenharmony_ci "allow sharing of the scanner by several frontends"; 2345141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->type = SANE_TYPE_BOOL; 2346141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->unit = SANE_UNIT_NONE; 2347141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->size = sizeof (SANE_Bool); 2348141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->cap = SANE_CAP_SOFT_SELECT; 2349141cc406Sopenharmony_ci options[CFG_ALLOW_SHARING]->constraint_type = SANE_CONSTRAINT_NONE; 2350141cc406Sopenharmony_ci values[CFG_ALLOW_SHARING] = &rtscfg.allowsharing; 2351141cc406Sopenharmony_ci 2352141cc406Sopenharmony_ci /* sensor type override */ 2353141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER] = 2354141cc406Sopenharmony_ci (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); 2355141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->name = "sensornumber"; 2356141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->desc = 2357141cc406Sopenharmony_ci "user provided scanner's internal sensor number"; 2358141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->type = SANE_TYPE_INT; 2359141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->unit = SANE_UNIT_NONE; 2360141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->size = sizeof (SANE_Word); 2361141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->cap = SANE_CAP_SOFT_SELECT; 2362141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->constraint_type = SANE_CONSTRAINT_RANGE; 2363141cc406Sopenharmony_ci options[CFG_SENSOR_NUMBER]->constraint.range = &sensor_range; 2364141cc406Sopenharmony_ci values[CFG_SENSOR_NUMBER] = &rtscfg.sensornumber; 2365141cc406Sopenharmony_ci 2366141cc406Sopenharmony_ci /* set configuration options structure */ 2367141cc406Sopenharmony_ci config.descriptors = options; 2368141cc406Sopenharmony_ci config.values = values; 2369141cc406Sopenharmony_ci config.count = NUM_CFG_OPTIONS; 2370141cc406Sopenharmony_ci 2371141cc406Sopenharmony_ci /* init usb use */ 2372141cc406Sopenharmony_ci sanei_usb_init (); 2373141cc406Sopenharmony_ci 2374141cc406Sopenharmony_ci /* generic configure and attach function */ 2375141cc406Sopenharmony_ci status = sanei_configure_attach (RTS8891_CONFIG_FILE, &config, 2376141cc406Sopenharmony_ci config_attach_rts8891, NULL); 2377141cc406Sopenharmony_ci /* free allocated options */ 2378141cc406Sopenharmony_ci for (i = 0; i < NUM_CFG_OPTIONS; i++) 2379141cc406Sopenharmony_ci { 2380141cc406Sopenharmony_ci free (options[i]); 2381141cc406Sopenharmony_ci } 2382141cc406Sopenharmony_ci 2383141cc406Sopenharmony_ci DBG (DBG_proc, "probe_rts8891_devices: end\n"); 2384141cc406Sopenharmony_ci return status; 2385141cc406Sopenharmony_ci} 2386141cc406Sopenharmony_ci 2387141cc406Sopenharmony_ci/** This function is called by sanei_configure_attach to try 2388141cc406Sopenharmony_ci * to attach the backend to a device specified by the configuration file. 2389141cc406Sopenharmony_ci * 2390141cc406Sopenharmony_ci * @param config configuration structure filled with values read 2391141cc406Sopenharmony_ci * from configuration file 2392141cc406Sopenharmony_ci * @param devname name of the device to try to attach to, it is 2393141cc406Sopenharmony_ci * the unprocessed line of the configuration file 2394141cc406Sopenharmony_ci * 2395141cc406Sopenharmony_ci * @return status SANE_STATUS_GOOD if no errors (even if no matching 2396141cc406Sopenharmony_ci * devices found) 2397141cc406Sopenharmony_ci * SANE_STATUS_INVAL in case of error 2398141cc406Sopenharmony_ci */ 2399141cc406Sopenharmony_cistatic SANE_Status 2400141cc406Sopenharmony_ciconfig_attach_rts8891 (SANEI_Config * config, const char *devname, 2401141cc406Sopenharmony_ci void __sane_unused__ *data) 2402141cc406Sopenharmony_ci{ 2403141cc406Sopenharmony_ci /* currently, the config is a global variable so config is useless here */ 2404141cc406Sopenharmony_ci /* the correct thing would be to have a generic sanei_attach_matching_devices 2405141cc406Sopenharmony_ci * using an attach function with a config parameter */ 2406141cc406Sopenharmony_ci if(config==NULL) 2407141cc406Sopenharmony_ci { 2408141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 2409141cc406Sopenharmony_ci } 2410141cc406Sopenharmony_ci 2411141cc406Sopenharmony_ci /* the devname has been processed and is ready to be used 2412141cc406Sopenharmony_ci * directly. Since the backend is an USB only one, we can 2413141cc406Sopenharmony_ci * call sanei_usb_attach_matching_devices straight */ 2414141cc406Sopenharmony_ci sanei_usb_attach_matching_devices (devname, attach_rts8891); 2415141cc406Sopenharmony_ci 2416141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2417141cc406Sopenharmony_ci} 2418141cc406Sopenharmony_ci 2419141cc406Sopenharmony_ci/** 2420141cc406Sopenharmony_ci * The attach tries to open the given usb device and match it 2421141cc406Sopenharmony_ci * with devices handled by the backend. The configuration parameter 2422141cc406Sopenharmony_ci * contains the values of the already parsed configuration options 2423141cc406Sopenharmony_ci * from the conf file. 2424141cc406Sopenharmony_ci * @param config configuration structure filled with values read 2425141cc406Sopenharmony_ci * from configuration file 2426141cc406Sopenharmony_ci * @param devicename name of the device to try to attach to, it is 2427141cc406Sopenharmony_ci * the unprocessed line of the configuration file 2428141cc406Sopenharmony_ci * 2429141cc406Sopenharmony_ci * @return status SANE_STATUS_GOOD if no errors (even if no matching 2430141cc406Sopenharmony_ci * devices found) 2431141cc406Sopenharmony_ci * SANE_STATUS_NOM_MEM if there isn't enough memory to allocate the 2432141cc406Sopenharmony_ci * device structure 2433141cc406Sopenharmony_ci * SANE_STATUS_UNSUPPORTED if the device if unknown by the backend 2434141cc406Sopenharmony_ci * SANE_STATUS_INVAL in case of other error 2435141cc406Sopenharmony_ci */ 2436141cc406Sopenharmony_cistatic SANE_Status 2437141cc406Sopenharmony_ciattach_rts8891 (const char *devicename) 2438141cc406Sopenharmony_ci{ 2439141cc406Sopenharmony_ci struct Rts8891_Device *device; 2440141cc406Sopenharmony_ci SANE_Int dn, vendor, product; 2441141cc406Sopenharmony_ci SANE_Status status; 2442141cc406Sopenharmony_ci 2443141cc406Sopenharmony_ci DBG (DBG_proc, "attach_rts8891(%s): start\n", devicename); 2444141cc406Sopenharmony_ci 2445141cc406Sopenharmony_ci /* search if we already have it attached */ 2446141cc406Sopenharmony_ci for (device = first_device; device; device = device->next) 2447141cc406Sopenharmony_ci { 2448141cc406Sopenharmony_ci if (strcmp (device->file_name, devicename) == 0) 2449141cc406Sopenharmony_ci { 2450141cc406Sopenharmony_ci DBG (DBG_warn, 2451141cc406Sopenharmony_ci "attach_rts8891: device already attached (is ok)!\n"); 2452141cc406Sopenharmony_ci DBG (DBG_proc, "attach_rts8891: exit\n"); 2453141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2454141cc406Sopenharmony_ci } 2455141cc406Sopenharmony_ci } 2456141cc406Sopenharmony_ci 2457141cc406Sopenharmony_ci /* open usb device */ 2458141cc406Sopenharmony_ci status = sanei_usb_open (devicename, &dn); 2459141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2460141cc406Sopenharmony_ci { 2461141cc406Sopenharmony_ci DBG (DBG_error, "attach_rts8891: couldn't open device `%s': %s\n", 2462141cc406Sopenharmony_ci devicename, sane_strstatus (status)); 2463141cc406Sopenharmony_ci return status; 2464141cc406Sopenharmony_ci } 2465141cc406Sopenharmony_ci else 2466141cc406Sopenharmony_ci { 2467141cc406Sopenharmony_ci DBG (DBG_info, "attach_rts8891: device `%s' successfully opened\n", 2468141cc406Sopenharmony_ci devicename); 2469141cc406Sopenharmony_ci } 2470141cc406Sopenharmony_ci 2471141cc406Sopenharmony_ci /* get vendor and product id */ 2472141cc406Sopenharmony_ci status = sanei_usb_get_vendor_product (dn, &vendor, &product); 2473141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 2474141cc406Sopenharmony_ci { 2475141cc406Sopenharmony_ci DBG (DBG_error, 2476141cc406Sopenharmony_ci "attach_rts8891: couldn't get vendor and product ids of device `%s': %s\n", 2477141cc406Sopenharmony_ci devicename, sane_strstatus (status)); 2478141cc406Sopenharmony_ci sanei_usb_close (dn); 2479141cc406Sopenharmony_ci DBG (DBG_proc, "attach_rts8891: exit\n"); 2480141cc406Sopenharmony_ci return status; 2481141cc406Sopenharmony_ci } 2482141cc406Sopenharmony_ci sanei_usb_close (dn); 2483141cc406Sopenharmony_ci 2484141cc406Sopenharmony_ci /* get the index of the device in the device description table */ 2485141cc406Sopenharmony_ci /* if the value is provided by configuration option, just use it */ 2486141cc406Sopenharmony_ci if (rtscfg.modelnumber < 0) 2487141cc406Sopenharmony_ci { 2488141cc406Sopenharmony_ci /* walk the list of devices to find matching entry */ 2489141cc406Sopenharmony_ci dn = 0; 2490141cc406Sopenharmony_ci while ((vendor != rts8891_usb_device_list[dn].vendor_id 2491141cc406Sopenharmony_ci || product != rts8891_usb_device_list[dn].product_id) 2492141cc406Sopenharmony_ci && (rts8891_usb_device_list[dn].vendor_id != 0)) 2493141cc406Sopenharmony_ci dn++; 2494141cc406Sopenharmony_ci /* if we reach the list termination entry, the device is unknown */ 2495141cc406Sopenharmony_ci if (rts8891_usb_device_list[dn].vendor_id == 0) 2496141cc406Sopenharmony_ci { 2497141cc406Sopenharmony_ci DBG (DBG_info, 2498141cc406Sopenharmony_ci "attach_rts8891: unknown device `%s': 0x%04x:0x%04x\n", 2499141cc406Sopenharmony_ci devicename, vendor, product); 2500141cc406Sopenharmony_ci DBG (DBG_proc, "attach_rts8891: exit\n"); 2501141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2502141cc406Sopenharmony_ci } 2503141cc406Sopenharmony_ci } 2504141cc406Sopenharmony_ci else 2505141cc406Sopenharmony_ci { 2506141cc406Sopenharmony_ci /* user provided value */ 2507141cc406Sopenharmony_ci dn = rtscfg.modelnumber; 2508141cc406Sopenharmony_ci } 2509141cc406Sopenharmony_ci 2510141cc406Sopenharmony_ci /* allocate device struct */ 2511141cc406Sopenharmony_ci device = malloc (sizeof (*device)); 2512141cc406Sopenharmony_ci if (device == NULL) 2513141cc406Sopenharmony_ci { 2514141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2515141cc406Sopenharmony_ci } 2516141cc406Sopenharmony_ci memset (device, 0, sizeof (*device)); 2517141cc406Sopenharmony_ci 2518141cc406Sopenharmony_ci /* struct describing low lvel device */ 2519141cc406Sopenharmony_ci device->model = rts8891_usb_device_list[dn].model; 2520141cc406Sopenharmony_ci 2521141cc406Sopenharmony_ci /* name of the device */ 2522141cc406Sopenharmony_ci device->file_name = strdup (devicename); 2523141cc406Sopenharmony_ci 2524141cc406Sopenharmony_ci DBG (DBG_info, "attach_rts8891: found %s %s %s at %s\n", 2525141cc406Sopenharmony_ci device->model->vendor, 2526141cc406Sopenharmony_ci device->model->product, device->model->type, device->file_name); 2527141cc406Sopenharmony_ci 2528141cc406Sopenharmony_ci /* we insert new device at start of the chained list */ 2529141cc406Sopenharmony_ci /* head of the list becomes the next, and start is replaced */ 2530141cc406Sopenharmony_ci /* with the new session struct */ 2531141cc406Sopenharmony_ci num_devices++; 2532141cc406Sopenharmony_ci device->next = first_device; 2533141cc406Sopenharmony_ci first_device = device; 2534141cc406Sopenharmony_ci 2535141cc406Sopenharmony_ci device->reg_count = 244; 2536141cc406Sopenharmony_ci /* initialization is done at sane_open */ 2537141cc406Sopenharmony_ci device->initialized = SANE_FALSE; 2538141cc406Sopenharmony_ci device->needs_warming = SANE_TRUE; 2539141cc406Sopenharmony_ci device->parking = SANE_FALSE; 2540141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 2541141cc406Sopenharmony_ci device->last_scan.tv_sec = 0; 2542141cc406Sopenharmony_ci device->start_time.tv_sec = 0; 2543141cc406Sopenharmony_ci#endif 2544141cc406Sopenharmony_ci 2545141cc406Sopenharmony_ci /* in case autodection au sensor doesn't work, use the given override */ 2546141cc406Sopenharmony_ci device->sensor = rtscfg.sensornumber; 2547141cc406Sopenharmony_ci 2548141cc406Sopenharmony_ci /* copy configuration settings to device */ 2549141cc406Sopenharmony_ci device->conf.modelnumber = dn; 2550141cc406Sopenharmony_ci device->conf.allowsharing = rtscfg.allowsharing; 2551141cc406Sopenharmony_ci 2552141cc406Sopenharmony_ci DBG (DBG_proc, "attach_rts8891: exit\n"); 2553141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2554141cc406Sopenharmony_ci} 2555141cc406Sopenharmony_ci 2556141cc406Sopenharmony_ci 2557141cc406Sopenharmony_ci/* set initial value for the scanning options */ 2558141cc406Sopenharmony_cistatic SANE_Status 2559141cc406Sopenharmony_ciinit_options (struct Rts8891_Session *session) 2560141cc406Sopenharmony_ci{ 2561141cc406Sopenharmony_ci SANE_Int option, count, i, min, idx; 2562141cc406Sopenharmony_ci SANE_Word *dpi_list; 2563141cc406Sopenharmony_ci Rts8891_Model *model = session->dev->model; 2564141cc406Sopenharmony_ci 2565141cc406Sopenharmony_ci DBG (DBG_proc, "init_options: start\n"); 2566141cc406Sopenharmony_ci 2567141cc406Sopenharmony_ci /* we first initialize each options with a default value */ 2568141cc406Sopenharmony_ci memset (session->opt, 0, sizeof (session->opt)); 2569141cc406Sopenharmony_ci memset (session->val, 0, sizeof (session->val)); 2570141cc406Sopenharmony_ci 2571141cc406Sopenharmony_ci for (option = 0; option < NUM_OPTIONS; option++) 2572141cc406Sopenharmony_ci { 2573141cc406Sopenharmony_ci session->opt[option].size = sizeof (SANE_Word); 2574141cc406Sopenharmony_ci session->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; 2575141cc406Sopenharmony_ci } 2576141cc406Sopenharmony_ci 2577141cc406Sopenharmony_ci /* we set up all the options listed in the Rts8891_Option enum */ 2578141cc406Sopenharmony_ci 2579141cc406Sopenharmony_ci /* last option / end of list marker */ 2580141cc406Sopenharmony_ci session->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; 2581141cc406Sopenharmony_ci session->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; 2582141cc406Sopenharmony_ci session->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; 2583141cc406Sopenharmony_ci session->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; 2584141cc406Sopenharmony_ci session->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; 2585141cc406Sopenharmony_ci session->val[OPT_NUM_OPTS].w = NUM_OPTIONS; 2586141cc406Sopenharmony_ci 2587141cc406Sopenharmony_ci /* "Standard" group: */ 2588141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].title = SANE_TITLE_STANDARD; 2589141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].name = SANE_NAME_STANDARD; 2590141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].desc = SANE_DESC_STANDARD; 2591141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].type = SANE_TYPE_GROUP; 2592141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].size = 0; 2593141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].cap = 0; 2594141cc406Sopenharmony_ci session->opt[OPT_STANDARD_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2595141cc406Sopenharmony_ci 2596141cc406Sopenharmony_ci /* scan mode */ 2597141cc406Sopenharmony_ci session->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; 2598141cc406Sopenharmony_ci session->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; 2599141cc406Sopenharmony_ci session->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; 2600141cc406Sopenharmony_ci session->opt[OPT_MODE].type = SANE_TYPE_STRING; 2601141cc406Sopenharmony_ci session->opt[OPT_MODE].cap |= SANE_CAP_AUTOMATIC; 2602141cc406Sopenharmony_ci session->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; 2603141cc406Sopenharmony_ci session->opt[OPT_MODE].size = max_string_size (mode_list); 2604141cc406Sopenharmony_ci session->opt[OPT_MODE].constraint.string_list = mode_list; 2605141cc406Sopenharmony_ci session->val[OPT_MODE].s = strdup (mode_list[0]); 2606141cc406Sopenharmony_ci 2607141cc406Sopenharmony_ci /* preview */ 2608141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; 2609141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; 2610141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; 2611141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; 2612141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].cap |= SANE_CAP_AUTOMATIC; 2613141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; 2614141cc406Sopenharmony_ci session->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; 2615141cc406Sopenharmony_ci session->val[OPT_PREVIEW].w = SANE_FALSE; 2616141cc406Sopenharmony_ci 2617141cc406Sopenharmony_ci /* build resolution list */ 2618141cc406Sopenharmony_ci /* TODO we build it from xdpi, one could prefer building it from 2619141cc406Sopenharmony_ci * ydpi list, or even allow for independent X and Y dpi (with 2 options then) 2620141cc406Sopenharmony_ci */ 2621141cc406Sopenharmony_ci for (count = 0; model->xdpi_values[count] != 0; count++); 2622141cc406Sopenharmony_ci dpi_list = malloc ((count + 1) * sizeof (SANE_Word)); 2623141cc406Sopenharmony_ci if (!dpi_list) 2624141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2625141cc406Sopenharmony_ci dpi_list[0] = count; 2626141cc406Sopenharmony_ci for (count = 0; model->xdpi_values[count] != 0; count++) 2627141cc406Sopenharmony_ci dpi_list[count + 1] = model->xdpi_values[count]; 2628141cc406Sopenharmony_ci 2629141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; 2630141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; 2631141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; 2632141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; 2633141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].cap |= SANE_CAP_AUTOMATIC; 2634141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; 2635141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; 2636141cc406Sopenharmony_ci session->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; 2637141cc406Sopenharmony_ci 2638141cc406Sopenharmony_ci /* initial value is lowest available dpi */ 2639141cc406Sopenharmony_ci min = 65536; 2640141cc406Sopenharmony_ci for (i = 1; i < count; i++) 2641141cc406Sopenharmony_ci { 2642141cc406Sopenharmony_ci if (dpi_list[i] < min) 2643141cc406Sopenharmony_ci min = dpi_list[i]; 2644141cc406Sopenharmony_ci } 2645141cc406Sopenharmony_ci session->val[OPT_RESOLUTION].w = min; 2646141cc406Sopenharmony_ci 2647141cc406Sopenharmony_ci /* "Geometry" group: */ 2648141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY; 2649141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY; 2650141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY; 2651141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; 2652141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; 2653141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].size = 0; 2654141cc406Sopenharmony_ci session->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2655141cc406Sopenharmony_ci 2656141cc406Sopenharmony_ci /* adapt the constraint range to the detected model */ 2657141cc406Sopenharmony_ci x_range.max = model->x_size; 2658141cc406Sopenharmony_ci y_range.max = model->y_size; 2659141cc406Sopenharmony_ci 2660141cc406Sopenharmony_ci /* top-left x */ 2661141cc406Sopenharmony_ci session->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; 2662141cc406Sopenharmony_ci session->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; 2663141cc406Sopenharmony_ci session->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; 2664141cc406Sopenharmony_ci session->opt[OPT_TL_X].type = SANE_TYPE_FIXED; 2665141cc406Sopenharmony_ci session->opt[OPT_TL_X].cap |= SANE_CAP_AUTOMATIC; 2666141cc406Sopenharmony_ci session->opt[OPT_TL_X].unit = SANE_UNIT_MM; 2667141cc406Sopenharmony_ci session->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; 2668141cc406Sopenharmony_ci session->opt[OPT_TL_X].constraint.range = &x_range; 2669141cc406Sopenharmony_ci session->val[OPT_TL_X].w = 0; 2670141cc406Sopenharmony_ci 2671141cc406Sopenharmony_ci /* top-left y */ 2672141cc406Sopenharmony_ci session->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; 2673141cc406Sopenharmony_ci session->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; 2674141cc406Sopenharmony_ci session->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; 2675141cc406Sopenharmony_ci session->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; 2676141cc406Sopenharmony_ci session->opt[OPT_TL_Y].cap |= SANE_CAP_AUTOMATIC; 2677141cc406Sopenharmony_ci session->opt[OPT_TL_Y].unit = SANE_UNIT_MM; 2678141cc406Sopenharmony_ci session->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2679141cc406Sopenharmony_ci session->opt[OPT_TL_Y].constraint.range = &y_range; 2680141cc406Sopenharmony_ci session->val[OPT_TL_Y].w = 0; 2681141cc406Sopenharmony_ci 2682141cc406Sopenharmony_ci /* bottom-right x */ 2683141cc406Sopenharmony_ci session->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; 2684141cc406Sopenharmony_ci session->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; 2685141cc406Sopenharmony_ci session->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; 2686141cc406Sopenharmony_ci session->opt[OPT_BR_X].type = SANE_TYPE_FIXED; 2687141cc406Sopenharmony_ci session->opt[OPT_BR_X].cap |= SANE_CAP_AUTOMATIC; 2688141cc406Sopenharmony_ci session->opt[OPT_BR_X].unit = SANE_UNIT_MM; 2689141cc406Sopenharmony_ci session->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; 2690141cc406Sopenharmony_ci session->opt[OPT_BR_X].constraint.range = &x_range; 2691141cc406Sopenharmony_ci session->val[OPT_BR_X].w = x_range.max; 2692141cc406Sopenharmony_ci 2693141cc406Sopenharmony_ci /* bottom-right y */ 2694141cc406Sopenharmony_ci session->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; 2695141cc406Sopenharmony_ci session->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; 2696141cc406Sopenharmony_ci session->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; 2697141cc406Sopenharmony_ci session->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; 2698141cc406Sopenharmony_ci session->opt[OPT_BR_Y].cap |= SANE_CAP_AUTOMATIC; 2699141cc406Sopenharmony_ci session->opt[OPT_BR_Y].unit = SANE_UNIT_MM; 2700141cc406Sopenharmony_ci session->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; 2701141cc406Sopenharmony_ci session->opt[OPT_BR_Y].constraint.range = &y_range; 2702141cc406Sopenharmony_ci session->val[OPT_BR_Y].w = y_range.max; 2703141cc406Sopenharmony_ci 2704141cc406Sopenharmony_ci /* "Enhancement" group: */ 2705141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT; 2706141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].name = SANE_NAME_ENHANCEMENT; 2707141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].desc = SANE_DESC_ENHANCEMENT; 2708141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; 2709141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; 2710141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].size = 0; 2711141cc406Sopenharmony_ci session->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2712141cc406Sopenharmony_ci 2713141cc406Sopenharmony_ci /* BW threshold */ 2714141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; 2715141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; 2716141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; 2717141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; 2718141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; 2719141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].cap |= 2720141cc406Sopenharmony_ci SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_EMULATED; 2721141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; 2722141cc406Sopenharmony_ci session->opt[OPT_THRESHOLD].constraint.range = &threshold_percentage_range; 2723141cc406Sopenharmony_ci session->val[OPT_THRESHOLD].w = SANE_FIX (50); 2724141cc406Sopenharmony_ci 2725141cc406Sopenharmony_ci /* custom-gamma table */ 2726141cc406Sopenharmony_ci session->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; 2727141cc406Sopenharmony_ci session->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; 2728141cc406Sopenharmony_ci session->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; 2729141cc406Sopenharmony_ci session->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; 2730141cc406Sopenharmony_ci session->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED; 2731141cc406Sopenharmony_ci session->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE; 2732141cc406Sopenharmony_ci 2733141cc406Sopenharmony_ci /* grayscale gamma vector */ 2734141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; 2735141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; 2736141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; 2737141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; 2738141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].cap |= 2739141cc406Sopenharmony_ci SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; 2740141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; 2741141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); 2742141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; 2743141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; 2744141cc406Sopenharmony_ci session->val[OPT_GAMMA_VECTOR].wa = model->gamma; 2745141cc406Sopenharmony_ci 2746141cc406Sopenharmony_ci /* red gamma vector */ 2747141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; 2748141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; 2749141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; 2750141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; 2751141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].cap |= 2752141cc406Sopenharmony_ci SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; 2753141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; 2754141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); 2755141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; 2756141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; 2757141cc406Sopenharmony_ci session->val[OPT_GAMMA_VECTOR_R].wa = model->gamma; 2758141cc406Sopenharmony_ci 2759141cc406Sopenharmony_ci /* green gamma vector */ 2760141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; 2761141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; 2762141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; 2763141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; 2764141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].cap |= 2765141cc406Sopenharmony_ci SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; 2766141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; 2767141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); 2768141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; 2769141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; 2770141cc406Sopenharmony_ci session->val[OPT_GAMMA_VECTOR_G].wa = model->gamma; 2771141cc406Sopenharmony_ci 2772141cc406Sopenharmony_ci /* blue gamma vector */ 2773141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; 2774141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; 2775141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; 2776141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; 2777141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].cap |= 2778141cc406Sopenharmony_ci SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; 2779141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; 2780141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); 2781141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; 2782141cc406Sopenharmony_ci session->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; 2783141cc406Sopenharmony_ci session->val[OPT_GAMMA_VECTOR_B].wa = model->gamma; 2784141cc406Sopenharmony_ci 2785141cc406Sopenharmony_ci /* "Sensors" group */ 2786141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].title = SANE_TITLE_SENSORS; 2787141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].name = SANE_NAME_SENSORS; 2788141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].desc = SANE_DESC_SENSORS; 2789141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].type = SANE_TYPE_GROUP; 2790141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].cap = SANE_CAP_ADVANCED; 2791141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].size = 0; 2792141cc406Sopenharmony_ci session->opt[OPT_SENSOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2793141cc406Sopenharmony_ci 2794141cc406Sopenharmony_ci /* scanner buttons */ 2795141cc406Sopenharmony_ci for (i = OPT_BUTTON_1; i <= OPT_BUTTON_11; i++) 2796141cc406Sopenharmony_ci { 2797141cc406Sopenharmony_ci char name[39]; 2798141cc406Sopenharmony_ci char title[64]; 2799141cc406Sopenharmony_ci 2800141cc406Sopenharmony_ci idx = i - OPT_BUTTON_1; 2801141cc406Sopenharmony_ci 2802141cc406Sopenharmony_ci if (idx < model->buttons) 2803141cc406Sopenharmony_ci { 2804141cc406Sopenharmony_ci sprintf (name, "button-%s", model->button_name[idx]); 2805141cc406Sopenharmony_ci sprintf (title, "%s", model->button_title[idx]); 2806141cc406Sopenharmony_ci 2807141cc406Sopenharmony_ci session->opt[i].name = strdup (name); 2808141cc406Sopenharmony_ci session->opt[i].title = strdup (title); 2809141cc406Sopenharmony_ci session->opt[i].desc = SANE_I18N ("This option reflects the status " 2810141cc406Sopenharmony_ci "of a scanner button."); 2811141cc406Sopenharmony_ci session->opt[i].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; 2812141cc406Sopenharmony_ci } 2813141cc406Sopenharmony_ci else 2814141cc406Sopenharmony_ci { 2815141cc406Sopenharmony_ci session->opt[i].name = strdup ("unused"); 2816141cc406Sopenharmony_ci session->opt[i].title = strdup ("unused button"); 2817141cc406Sopenharmony_ci session->opt[i].cap |= SANE_CAP_INACTIVE; 2818141cc406Sopenharmony_ci } 2819141cc406Sopenharmony_ci 2820141cc406Sopenharmony_ci session->opt[i].type = SANE_TYPE_BOOL; 2821141cc406Sopenharmony_ci session->opt[i].unit = SANE_UNIT_NONE; 2822141cc406Sopenharmony_ci session->opt[i].size = sizeof (SANE_Bool); 2823141cc406Sopenharmony_ci session->opt[i].constraint_type = SANE_CONSTRAINT_NONE; 2824141cc406Sopenharmony_ci session->opt[i].constraint.range = 0; 2825141cc406Sopenharmony_ci session->val[i].w = SANE_FALSE; 2826141cc406Sopenharmony_ci } 2827141cc406Sopenharmony_ci 2828141cc406Sopenharmony_ci update_button_status (session); 2829141cc406Sopenharmony_ci 2830141cc406Sopenharmony_ci /* "Advanced" group: */ 2831141cc406Sopenharmony_ci session->opt[OPT_ADVANCED_GROUP].title = SANE_I18N ("Advanced"); 2832141cc406Sopenharmony_ci session->opt[OPT_ADVANCED_GROUP].desc = ""; 2833141cc406Sopenharmony_ci session->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; 2834141cc406Sopenharmony_ci session->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; 2835141cc406Sopenharmony_ci session->opt[OPT_ADVANCED_GROUP].size = 0; 2836141cc406Sopenharmony_ci session->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; 2837141cc406Sopenharmony_ci 2838141cc406Sopenharmony_ci /* lamp on */ 2839141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].name = "lamp-on"; 2840141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].title = SANE_I18N ("Lamp on"); 2841141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].desc = SANE_I18N ("Turn on scanner lamp"); 2842141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].type = SANE_TYPE_BUTTON; 2843141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].cap |= SANE_CAP_ADVANCED; 2844141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].unit = SANE_UNIT_NONE; 2845141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].size = 0; 2846141cc406Sopenharmony_ci session->opt[OPT_LAMP_ON].constraint_type = SANE_CONSTRAINT_NONE; 2847141cc406Sopenharmony_ci session->val[OPT_LAMP_ON].w = 0; 2848141cc406Sopenharmony_ci 2849141cc406Sopenharmony_ci /* lamp off */ 2850141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].name = "lamp-off"; 2851141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].title = SANE_I18N ("Lamp off"); 2852141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].desc = SANE_I18N ("Turn off scanner lamp"); 2853141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].type = SANE_TYPE_BUTTON; 2854141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].cap |= SANE_CAP_ADVANCED; 2855141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].unit = SANE_UNIT_NONE; 2856141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].size = 0; 2857141cc406Sopenharmony_ci session->opt[OPT_LAMP_OFF].constraint_type = SANE_CONSTRAINT_NONE; 2858141cc406Sopenharmony_ci session->val[OPT_LAMP_OFF].w = 0; 2859141cc406Sopenharmony_ci 2860141cc406Sopenharmony_ci DBG (DBG_proc, "init_options: exit\n"); 2861141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2862141cc406Sopenharmony_ci} 2863141cc406Sopenharmony_ci 2864141cc406Sopenharmony_ci/** 2865141cc406Sopenharmony_ci * average scanned rgb data, returns the global average. Each channel avearge is also 2866141cc406Sopenharmony_ci * returned. 2867141cc406Sopenharmony_ci */ 2868141cc406Sopenharmony_cistatic float 2869141cc406Sopenharmony_ciaverage_area (int color, SANE_Byte * data, int width, int height, 2870141cc406Sopenharmony_ci float *ra, float *ga, float *ba) 2871141cc406Sopenharmony_ci{ 2872141cc406Sopenharmony_ci int x, y; 2873141cc406Sopenharmony_ci float global, pixels; 2874141cc406Sopenharmony_ci float rc, gc, bc; 2875141cc406Sopenharmony_ci pixels = width * height; 2876141cc406Sopenharmony_ci *ra = 0; 2877141cc406Sopenharmony_ci *ga = 0; 2878141cc406Sopenharmony_ci *ba = 0; 2879141cc406Sopenharmony_ci rc = 0; 2880141cc406Sopenharmony_ci gc = 0; 2881141cc406Sopenharmony_ci bc = 0; 2882141cc406Sopenharmony_ci if (color == SANE_TRUE) 2883141cc406Sopenharmony_ci { 2884141cc406Sopenharmony_ci for (y = 0; y < height; y++) 2885141cc406Sopenharmony_ci { 2886141cc406Sopenharmony_ci for (x = 0; x < width; x++) 2887141cc406Sopenharmony_ci { 2888141cc406Sopenharmony_ci rc += data[3 * width * y + x]; 2889141cc406Sopenharmony_ci gc += data[3 * width * y + x + 1]; 2890141cc406Sopenharmony_ci bc += data[3 * width * y + x + 2]; 2891141cc406Sopenharmony_ci } 2892141cc406Sopenharmony_ci } 2893141cc406Sopenharmony_ci global = (rc + gc + bc) / (3 * pixels); 2894141cc406Sopenharmony_ci *ra = rc / pixels; 2895141cc406Sopenharmony_ci *ga = gc / pixels; 2896141cc406Sopenharmony_ci *ba = bc / pixels; 2897141cc406Sopenharmony_ci } 2898141cc406Sopenharmony_ci else 2899141cc406Sopenharmony_ci { 2900141cc406Sopenharmony_ci for (y = 0; y < height; y++) 2901141cc406Sopenharmony_ci { 2902141cc406Sopenharmony_ci for (x = 0; x < width; x++) 2903141cc406Sopenharmony_ci { 2904141cc406Sopenharmony_ci gc += data[width * y + x]; 2905141cc406Sopenharmony_ci } 2906141cc406Sopenharmony_ci } 2907141cc406Sopenharmony_ci global = gc / pixels; 2908141cc406Sopenharmony_ci *ga = gc / pixels; 2909141cc406Sopenharmony_ci } 2910141cc406Sopenharmony_ci DBG (7, "average_area: global=%.2f, red=%.2f, green=%.2f, blue=%.2f\n", 2911141cc406Sopenharmony_ci global, *ra, *ga, *ba); 2912141cc406Sopenharmony_ci return global; 2913141cc406Sopenharmony_ci} 2914141cc406Sopenharmony_ci 2915141cc406Sopenharmony_ci 2916141cc406Sopenharmony_ci/** 2917141cc406Sopenharmony_ci * Sets lamp brightness (hum, maybe some timing before light off) 2918141cc406Sopenharmony_ci */ 2919141cc406Sopenharmony_cistatic SANE_Status 2920141cc406Sopenharmony_ciset_lamp_brightness (struct Rts8891_Device *dev, int level) 2921141cc406Sopenharmony_ci{ 2922141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 2923141cc406Sopenharmony_ci SANE_Byte reg; 2924141cc406Sopenharmony_ci 2925141cc406Sopenharmony_ci reg = 0xA0 | (level & 0x0F); 2926141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®); 2927141cc406Sopenharmony_ci switch (level) 2928141cc406Sopenharmony_ci { 2929141cc406Sopenharmony_ci case 0: 2930141cc406Sopenharmony_ci reg = 0x8d; 2931141cc406Sopenharmony_ci break; 2932141cc406Sopenharmony_ci case 7: 2933141cc406Sopenharmony_ci reg = 0x82; 2934141cc406Sopenharmony_ci break; 2935141cc406Sopenharmony_ci default: 2936141cc406Sopenharmony_ci reg = 0x8d; 2937141cc406Sopenharmony_ci break; 2938141cc406Sopenharmony_ci } 2939141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 2940141cc406Sopenharmony_ci reg = (reg & 0xF0) | 0x20 | ((~reg) & 0x0F); 2941141cc406Sopenharmony_ci dev->regs[LAMP_REG] = reg; 2942141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 2943141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 2944141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 2945141cc406Sopenharmony_ci sanei_rts88xx_get_status (dev->devnum, dev->regs); 2946141cc406Sopenharmony_ci DBG (DBG_io, "set_lamp_brightness: status=0x%02x 0x%02x\n", dev->regs[0x10], 2947141cc406Sopenharmony_ci dev->regs[0x11]); 2948141cc406Sopenharmony_ci if (dev->sensor != SENSOR_TYPE_4400) 2949141cc406Sopenharmony_ci { 2950141cc406Sopenharmony_ci dev->regs[0x10] = 0x28; 2951141cc406Sopenharmony_ci dev->regs[0x11] = 0x3f; 2952141cc406Sopenharmony_ci } 2953141cc406Sopenharmony_ci else 2954141cc406Sopenharmony_ci { 2955141cc406Sopenharmony_ci dev->regs[0x10] = 0x10; 2956141cc406Sopenharmony_ci dev->regs[0x11] = 0x2f; 2957141cc406Sopenharmony_ci } 2958141cc406Sopenharmony_ci reg = dev->regs[LAMP_REG]; 2959141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 2960141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, ®); 2961141cc406Sopenharmony_ci if (reg != 0x00) 2962141cc406Sopenharmony_ci { 2963141cc406Sopenharmony_ci DBG (DBG_warn, 2964141cc406Sopenharmony_ci "set_lamp_brightness: unexpected CONTROL_REG value, 0x%02x instead of 0x00\n", 2965141cc406Sopenharmony_ci reg); 2966141cc406Sopenharmony_ci } 2967141cc406Sopenharmony_ci return status; 2968141cc406Sopenharmony_ci} 2969141cc406Sopenharmony_ci 2970141cc406Sopenharmony_ci 2971141cc406Sopenharmony_ci/** 2972141cc406Sopenharmony_ci * Sets the lamp to half brightness and standard parameters 2973141cc406Sopenharmony_ci */ 2974141cc406Sopenharmony_cistatic SANE_Status 2975141cc406Sopenharmony_ciinit_lamp (struct Rts8891_Device *dev) 2976141cc406Sopenharmony_ci{ 2977141cc406Sopenharmony_ci SANE_Byte reg; 2978141cc406Sopenharmony_ci 2979141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x01); 2980141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x01); 2981141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 2982141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 2983141cc406Sopenharmony_ci sanei_rts88xx_cancel (dev->devnum); 2984141cc406Sopenharmony_ci dev->regs[0x12] = 0xff; 2985141cc406Sopenharmony_ci dev->regs[0x13] = 0x20; 2986141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2); 2987141cc406Sopenharmony_ci /* 0xF8/0x28 expected */ 2988141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); 2989141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 2990141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 2991141cc406Sopenharmony_ci if (dev->sensor != SENSOR_TYPE_4400 && dev->sensor != SENSOR_TYPE_4400_BARE) 2992141cc406Sopenharmony_ci { 2993141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3f); 2994141cc406Sopenharmony_ci dev->regs[0x11] = 0x3f; 2995141cc406Sopenharmony_ci } 2996141cc406Sopenharmony_ci else 2997141cc406Sopenharmony_ci { 2998141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22); 2999141cc406Sopenharmony_ci dev->regs[0x11] = 0x22; 3000141cc406Sopenharmony_ci } 3001141cc406Sopenharmony_ci reg = 0x8d; 3002141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 3003141cc406Sopenharmony_ci dev->regs[LAMP_REG] = 0xa2; 3004141cc406Sopenharmony_ci dev->regs[LAMP_BRIGHT_REG] = 0xa0; 3005141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 3006141cc406Sopenharmony_ci return set_lamp_brightness (dev, 7); 3007141cc406Sopenharmony_ci} 3008141cc406Sopenharmony_ci 3009141cc406Sopenharmony_ci/** 3010141cc406Sopenharmony_ci * This function detects physical start of scanning area find finding a black area below the "roof" 3011141cc406Sopenharmony_ci * if during scan we detect that sensor is inadequate, changed is set to SANE_TRUE 3012141cc406Sopenharmony_ci */ 3013141cc406Sopenharmony_cistatic SANE_Status 3014141cc406Sopenharmony_cifind_origin (struct Rts8891_Device *dev, SANE_Bool * changed) 3015141cc406Sopenharmony_ci{ 3016141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 3017141cc406Sopenharmony_ci SANE_Byte control, reg; 3018141cc406Sopenharmony_ci unsigned int max = 0; 3019141cc406Sopenharmony_ci unsigned char *image = NULL; 3020141cc406Sopenharmony_ci unsigned char *data = NULL; 3021141cc406Sopenharmony_ci SANE_Word total; 3022141cc406Sopenharmony_ci int startx = 300; 3023141cc406Sopenharmony_ci int width = 1200; 3024141cc406Sopenharmony_ci int x, y, sum, current; 3025141cc406Sopenharmony_ci int starty = 18; 3026141cc406Sopenharmony_ci int height = 180; 3027141cc406Sopenharmony_ci int timing; 3028141cc406Sopenharmony_ci 3029141cc406Sopenharmony_ci DBG (DBG_proc, "find_origin: start\n"); 3030141cc406Sopenharmony_ci 3031141cc406Sopenharmony_ci /* check if head is at home 3032141cc406Sopenharmony_ci * once sensor is correctly set up, we are always park here, 3033141cc406Sopenharmony_ci * but in case sensor has just changed, we are not so we park head */ 3034141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®); 3035141cc406Sopenharmony_ci if ((reg & 0x02) == 0) 3036141cc406Sopenharmony_ci { 3037141cc406Sopenharmony_ci if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD) 3038141cc406Sopenharmony_ci { 3039141cc406Sopenharmony_ci DBG (DBG_error, "find_origin: failed to park head!\n"); 3040141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3041141cc406Sopenharmony_ci } 3042141cc406Sopenharmony_ci DBG (DBG_info, "find_origin: head parked\n"); 3043141cc406Sopenharmony_ci } 3044141cc406Sopenharmony_ci 3045141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 3046141cc406Sopenharmony_ci if (control != 0) 3047141cc406Sopenharmony_ci { 3048141cc406Sopenharmony_ci DBG (DBG_warn, "find_origin: unexpected control value 0x%02x\n", 3049141cc406Sopenharmony_ci control); 3050141cc406Sopenharmony_ci } 3051141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 3052141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 3053141cc406Sopenharmony_ci if (control != 0) 3054141cc406Sopenharmony_ci { 3055141cc406Sopenharmony_ci DBG (DBG_warn, "find_origin: unexpected control value 0x%02x\n", 3056141cc406Sopenharmony_ci control); 3057141cc406Sopenharmony_ci } 3058141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 3059141cc406Sopenharmony_ci 3060141cc406Sopenharmony_ci /* set lamp to standard settings */ 3061141cc406Sopenharmony_ci init_lamp (dev); 3062141cc406Sopenharmony_ci 3063141cc406Sopenharmony_ci /* set scan parameters */ 3064141cc406Sopenharmony_ci dev->regs[0x00] = 0xe5; 3065141cc406Sopenharmony_ci dev->regs[0x32] = 0x80; 3066141cc406Sopenharmony_ci dev->regs[0x33] = 0x81; 3067141cc406Sopenharmony_ci dev->regs[0x39] = 0x02; 3068141cc406Sopenharmony_ci dev->regs[0x64] = 0x01; 3069141cc406Sopenharmony_ci dev->regs[0x65] = 0x20; 3070141cc406Sopenharmony_ci dev->regs[0x79] = 0x20; 3071141cc406Sopenharmony_ci dev->regs[0x7a] = 0x01; 3072141cc406Sopenharmony_ci dev->regs[0x90] = 0x1c; 3073141cc406Sopenharmony_ci 3074141cc406Sopenharmony_ci dev->regs[0x35] = 0x1b; 3075141cc406Sopenharmony_ci dev->regs[0x36] = 0x29; 3076141cc406Sopenharmony_ci dev->regs[0x3a] = 0x1b; 3077141cc406Sopenharmony_ci timing=0x32; 3078141cc406Sopenharmony_ci dev->regs[0x85] = 0x00; 3079141cc406Sopenharmony_ci dev->regs[0x86] = 0x06; 3080141cc406Sopenharmony_ci dev->regs[0x87] = 0x00; 3081141cc406Sopenharmony_ci dev->regs[0x88] = 0x06; 3082141cc406Sopenharmony_ci dev->regs[0x8d] = 0x80; 3083141cc406Sopenharmony_ci dev->regs[0x8e] = 0x68; 3084141cc406Sopenharmony_ci 3085141cc406Sopenharmony_ci dev->regs[0xb2] = 0x02; /* 0x04 -> no data */ 3086141cc406Sopenharmony_ci 3087141cc406Sopenharmony_ci dev->regs[0xc0] = 0xff; 3088141cc406Sopenharmony_ci dev->regs[0xc1] = 0x0f; 3089141cc406Sopenharmony_ci dev->regs[0xc3] = 0xff; 3090141cc406Sopenharmony_ci dev->regs[0xc4] = 0xff; 3091141cc406Sopenharmony_ci dev->regs[0xc5] = 0xff; 3092141cc406Sopenharmony_ci dev->regs[0xc6] = 0xff; 3093141cc406Sopenharmony_ci dev->regs[0xc7] = 0xff; 3094141cc406Sopenharmony_ci dev->regs[0xc8] = 0xff; 3095141cc406Sopenharmony_ci dev->regs[0xc9] = 0x00; 3096141cc406Sopenharmony_ci dev->regs[0xca] = 0x0e; 3097141cc406Sopenharmony_ci dev->regs[0xcb] = 0x00; 3098141cc406Sopenharmony_ci dev->regs[0xcd] = 0xf0; 3099141cc406Sopenharmony_ci dev->regs[0xce] = 0xff; 3100141cc406Sopenharmony_ci dev->regs[0xcf] = 0xf5; 3101141cc406Sopenharmony_ci dev->regs[0xd0] = 0xf7; 3102141cc406Sopenharmony_ci dev->regs[0xd1] = 0xea; 3103141cc406Sopenharmony_ci dev->regs[0xd2] = 0x0b; 3104141cc406Sopenharmony_ci dev->regs[0xd3] = 0x03; 3105141cc406Sopenharmony_ci dev->regs[0xd4] = 0x05; 3106141cc406Sopenharmony_ci dev->regs[0xd6] = 0xab; 3107141cc406Sopenharmony_ci dev->regs[0xd7] = 0x30; 3108141cc406Sopenharmony_ci dev->regs[0xd8] = 0xf6; 3109141cc406Sopenharmony_ci dev->regs[0xe2] = 0x01; 3110141cc406Sopenharmony_ci dev->regs[0xe3] = 0x00; 3111141cc406Sopenharmony_ci dev->regs[0xe4] = 0x00; 3112141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 4124); 3113141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x1c; 3114141cc406Sopenharmony_ci dev->regs[0xe6] = 0x10; 101c=4124 */ 3115141cc406Sopenharmony_ci dev->regs[0xe7] = 0x00; 3116141cc406Sopenharmony_ci dev->regs[0xe8] = 0x00; 3117141cc406Sopenharmony_ci dev->regs[0xe9] = 0x00; 3118141cc406Sopenharmony_ci 3119141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 3120141cc406Sopenharmony_ci { 3121141cc406Sopenharmony_ci dev->regs[0xc3] = 0x00; 3122141cc406Sopenharmony_ci dev->regs[0xc4] = 0xf0; 3123141cc406Sopenharmony_ci dev->regs[0xc7] = 0x0f; 3124141cc406Sopenharmony_ci dev->regs[0xc8] = 0x00; 3125141cc406Sopenharmony_ci dev->regs[0xc9] = 0xff; 3126141cc406Sopenharmony_ci dev->regs[0xca] = 0xf1; 3127141cc406Sopenharmony_ci dev->regs[0xcb] = 0xff; 3128141cc406Sopenharmony_ci dev->regs[0xd7] = 0x10; 3129141cc406Sopenharmony_ci } 3130141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400 || dev->sensor == SENSOR_TYPE_4400_BARE) 3131141cc406Sopenharmony_ci { 3132141cc406Sopenharmony_ci /* 4400 values / 'XPA' values */ 3133141cc406Sopenharmony_ci dev->regs[0x13] = 0x39; /* 0x20 */ 3134141cc406Sopenharmony_ci dev->regs[0x14] = 0xf0; /* 0xf8 */ 3135141cc406Sopenharmony_ci dev->regs[0x15] = 0x29; /* 0x28 */ 3136141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; /* 0x07 */ 3137141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; /* 0x00 */ 3138141cc406Sopenharmony_ci 3139141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; /* 0xff */ 3140141cc406Sopenharmony_ci 3141141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; /* 0x02 */ 3142141cc406Sopenharmony_ci } 3143141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 3144141cc406Sopenharmony_ci { 3145141cc406Sopenharmony_ci dev->regs[0xc3] = 0xff; /* 0x00 */ 3146141cc406Sopenharmony_ci dev->regs[0xc4] = 0xff; /* 0xf0 */ 3147141cc406Sopenharmony_ci dev->regs[0xc7] = 0xff; /* 0x0f */ 3148141cc406Sopenharmony_ci dev->regs[0xc8] = 0xff; /* 0x00 */ 3149141cc406Sopenharmony_ci dev->regs[0xc9] = 0x00; /* 0xff */ 3150141cc406Sopenharmony_ci dev->regs[0xca] = 0x0e; /* 0xf1 */ 3151141cc406Sopenharmony_ci dev->regs[0xcb] = 0x00; /* 0xff */ 3152141cc406Sopenharmony_ci dev->regs[0xd7] = 0x30; /* 0x10 */ 3153141cc406Sopenharmony_ci dev->regs[0xda] = 0xa7; /* 0xa0 */ 3154141cc406Sopenharmony_ci } 3155141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING_REG, timing); 3156141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); 3157141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); 3158141cc406Sopenharmony_ci 3159141cc406Sopenharmony_ci 3160141cc406Sopenharmony_ci /* allocate memory for the data */ 3161141cc406Sopenharmony_ci total = width * height; 3162141cc406Sopenharmony_ci data = (unsigned char *) malloc (total); 3163141cc406Sopenharmony_ci if (data == NULL) 3164141cc406Sopenharmony_ci { 3165141cc406Sopenharmony_ci DBG (DBG_error, "find_origin: failed to allocate %d bytes\n", total); 3166141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3167141cc406Sopenharmony_ci } 3168141cc406Sopenharmony_ci image = (unsigned char *) malloc (total); 3169141cc406Sopenharmony_ci if (image == NULL) 3170141cc406Sopenharmony_ci { 3171141cc406Sopenharmony_ci free(data); 3172141cc406Sopenharmony_ci DBG (DBG_error, "find_origin: failed to allocate %d bytes\n", total); 3173141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3174141cc406Sopenharmony_ci } 3175141cc406Sopenharmony_ci 3176141cc406Sopenharmony_ci /* set vertical and horizontal start/end positions */ 3177141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (dev->regs, starty, starty + height, startx, 3178141cc406Sopenharmony_ci startx + width); 3179141cc406Sopenharmony_ci sanei_rts88xx_set_offset (dev->regs, 0x7f, 0x7f, 0x7f); 3180141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, 0x10, 0x10, 0x10); 3181141cc406Sopenharmony_ci 3182141cc406Sopenharmony_ci /* gray level scan */ 3183141cc406Sopenharmony_ci dev->regs[LAMP_REG] = 0xad; 3184141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, dev->regs + LAMP_REG); 3185141cc406Sopenharmony_ci if (dev->sensor != SENSOR_TYPE_4400 3186141cc406Sopenharmony_ci && (dev->sensor != SENSOR_TYPE_4400_BARE)) 3187141cc406Sopenharmony_ci { 3188141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x3b); 3189141cc406Sopenharmony_ci } 3190141cc406Sopenharmony_ci else 3191141cc406Sopenharmony_ci { 3192141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22); 3193141cc406Sopenharmony_ci } 3194141cc406Sopenharmony_ci 3195141cc406Sopenharmony_ci status = 3196141cc406Sopenharmony_ci rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x03, 3197141cc406Sopenharmony_ci total, data); 3198141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3199141cc406Sopenharmony_ci { 3200141cc406Sopenharmony_ci free(image); 3201141cc406Sopenharmony_ci free(data); 3202141cc406Sopenharmony_ci DBG (DBG_error, "find_origin: failed to scan\n"); 3203141cc406Sopenharmony_ci return status; 3204141cc406Sopenharmony_ci } 3205141cc406Sopenharmony_ci 3206141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io2) 3207141cc406Sopenharmony_ci { 3208141cc406Sopenharmony_ci write_gray_data (data, "find_origin.pnm", width, height); 3209141cc406Sopenharmony_ci } 3210141cc406Sopenharmony_ci 3211141cc406Sopenharmony_ci /* now we have the data, search for the black area so that we can */ 3212141cc406Sopenharmony_ci /* deduce start of scan area */ 3213141cc406Sopenharmony_ci /* we apply an Y direction sobel filter to get reliable edge detection */ 3214141cc406Sopenharmony_ci /* Meanwhile we check that picture is correct, if not, sensor needs to */ 3215141cc406Sopenharmony_ci /* be changed . */ 3216141cc406Sopenharmony_ci /* TODO possibly check for insufficient warming */ 3217141cc406Sopenharmony_ci for (y = 1; y < height - 1; y++) 3218141cc406Sopenharmony_ci for (x = 1; x < width - 1; x++) 3219141cc406Sopenharmony_ci { 3220141cc406Sopenharmony_ci /* if sensor is wrong, picture is black, so max will be low */ 3221141cc406Sopenharmony_ci if (data[y * width + x] > max) 3222141cc406Sopenharmony_ci max = data[y * width + x]; 3223141cc406Sopenharmony_ci 3224141cc406Sopenharmony_ci /* sobel y filter */ 3225141cc406Sopenharmony_ci current = 3226141cc406Sopenharmony_ci -data[(y - 1) * width + x + 1] - 2 * data[(y - 1) * width + x] - 3227141cc406Sopenharmony_ci data[(y - 1) * width + x - 1] + data[(y + 1) * width + x + 1] + 3228141cc406Sopenharmony_ci 2 * data[(y + 1) * width + x] + data[(y + 1) * width + x - 1]; 3229141cc406Sopenharmony_ci if (current < 0) 3230141cc406Sopenharmony_ci current = -current; 3231141cc406Sopenharmony_ci image[y * width + x] = current; 3232141cc406Sopenharmony_ci } 3233141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io2) 3234141cc406Sopenharmony_ci { 3235141cc406Sopenharmony_ci write_gray_data (image, "find_origin_ysobel.pnm", width, height); 3236141cc406Sopenharmony_ci } 3237141cc406Sopenharmony_ci 3238141cc406Sopenharmony_ci /* sensor test */ 3239141cc406Sopenharmony_ci if (max < 10) 3240141cc406Sopenharmony_ci { 3241141cc406Sopenharmony_ci DBG (DBG_info, 3242141cc406Sopenharmony_ci "find_origin: sensor type needs to be changed (max=%d)\n", max); 3243141cc406Sopenharmony_ci *changed = SANE_TRUE; 3244141cc406Sopenharmony_ci } 3245141cc406Sopenharmony_ci else 3246141cc406Sopenharmony_ci { 3247141cc406Sopenharmony_ci *changed = SANE_FALSE; 3248141cc406Sopenharmony_ci } 3249141cc406Sopenharmony_ci 3250141cc406Sopenharmony_ci /* the edge will be where the white area stops */ 3251141cc406Sopenharmony_ci /* we average y position of white->black transition on each column */ 3252141cc406Sopenharmony_ci sum = 0; 3253141cc406Sopenharmony_ci for (x = 1; x < width - 1; x++) 3254141cc406Sopenharmony_ci { 3255141cc406Sopenharmony_ci for (y = 1; y < height - 2; y++) 3256141cc406Sopenharmony_ci { 3257141cc406Sopenharmony_ci /* edge detection on each line */ 3258141cc406Sopenharmony_ci if (image[x + (y + 1) * width] - image[x + y * width] >= 20) 3259141cc406Sopenharmony_ci { 3260141cc406Sopenharmony_ci sum += y; 3261141cc406Sopenharmony_ci break; 3262141cc406Sopenharmony_ci } 3263141cc406Sopenharmony_ci } 3264141cc406Sopenharmony_ci } 3265141cc406Sopenharmony_ci sum /= width; 3266141cc406Sopenharmony_ci DBG (DBG_info, "find_origin: scan area offset=%d lines\n", sum); 3267141cc406Sopenharmony_ci 3268141cc406Sopenharmony_ci /* convert the detected value into max ydpi */ 3269141cc406Sopenharmony_ci dev->top_offset = (48 * dev->model->max_ydpi) / 300; 3270141cc406Sopenharmony_ci 3271141cc406Sopenharmony_ci /* no we're done */ 3272141cc406Sopenharmony_ci free (image); 3273141cc406Sopenharmony_ci free (data); 3274141cc406Sopenharmony_ci 3275141cc406Sopenharmony_ci /* safe guard test against moving to far toward the top */ 3276141cc406Sopenharmony_ci if (sum > 11) 3277141cc406Sopenharmony_ci { 3278141cc406Sopenharmony_ci /* now go back to the white area so that calibration can work on it */ 3279141cc406Sopenharmony_ci dev->regs[0x35] = 0x0e; 3280141cc406Sopenharmony_ci dev->regs[0x3a] = 0x0e; 3281141cc406Sopenharmony_ci 3282141cc406Sopenharmony_ci dev->regs[0xb2] = 0x06; /* no data (0x04) */ 3283141cc406Sopenharmony_ci 3284141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 3285141cc406Sopenharmony_ci { 3286141cc406Sopenharmony_ci dev->regs[0x36] = 0x21; /* direction reverse (& ~0x08) */ 3287141cc406Sopenharmony_ci 3288141cc406Sopenharmony_ci dev->regs[0xe2] = 0x03; /* 0x01 */ 3289141cc406Sopenharmony_ci 3290141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x0d; 0x1c 3291141cc406Sopenharmony_ci dev->regs[0xe6] = 0x08; 0x10 080d=2061=1030*2+1 */ 3292141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 2061); 3293141cc406Sopenharmony_ci } 3294141cc406Sopenharmony_ci else 3295141cc406Sopenharmony_ci { 3296141cc406Sopenharmony_ci dev->regs[0x11] = 0x3f; /* 0x3b */ 3297141cc406Sopenharmony_ci 3298141cc406Sopenharmony_ci dev->regs[0x36] = 0x24; /* direction reverse (& ~0x08) */ 3299141cc406Sopenharmony_ci 3300141cc406Sopenharmony_ci dev->regs[0xe2] = 0x07; 3301141cc406Sopenharmony_ci 3302141cc406Sopenharmony_ci /* 3303141cc406Sopenharmony_ci dev->regs[0xe5] = 0x06; 3304141cc406Sopenharmony_ci dev->regs[0xe6] = 0x04; 406=1030 */ 3305141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 1030); 3306141cc406Sopenharmony_ci } 3307141cc406Sopenharmony_ci 3308141cc406Sopenharmony_ci /* move by a fixed amount relative to the 'top' of the scanner */ 3309141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (dev->regs, height - sum + 10, 3310141cc406Sopenharmony_ci height - sum + 11, 637, 893); 3311141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 3312141cc406Sopenharmony_ci rts8891_commit (dev->devnum, 0x03); 3313141cc406Sopenharmony_ci 3314141cc406Sopenharmony_ci /* wait for the motor to stop */ 3315141cc406Sopenharmony_ci do 3316141cc406Sopenharmony_ci { 3317141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, ®); 3318141cc406Sopenharmony_ci } 3319141cc406Sopenharmony_ci while ((reg & 0x08) == 0x08); 3320141cc406Sopenharmony_ci } 3321141cc406Sopenharmony_ci 3322141cc406Sopenharmony_ci DBG (DBG_proc, "find_origin: exit\n"); 3323141cc406Sopenharmony_ci return status; 3324141cc406Sopenharmony_ci} 3325141cc406Sopenharmony_ci 3326141cc406Sopenharmony_ci/** 3327141cc406Sopenharmony_ci * This function detects the left margin (ie x offset of scanning area) by doing 3328141cc406Sopenharmony_ci * a grey scan of the very beginning of the sensor and finding the start of the 3329141cc406Sopenharmony_ci * white area of calibration zone, which is start of usable pixels. 3330141cc406Sopenharmony_ci */ 3331141cc406Sopenharmony_cistatic SANE_Status 3332141cc406Sopenharmony_cifind_margin (struct Rts8891_Device *dev) 3333141cc406Sopenharmony_ci{ 3334141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 3335141cc406Sopenharmony_ci unsigned char *data = NULL; 3336141cc406Sopenharmony_ci SANE_Word total; 3337141cc406Sopenharmony_ci int startx = 33; 3338141cc406Sopenharmony_ci int width = 250; 3339141cc406Sopenharmony_ci int x; 3340141cc406Sopenharmony_ci int starty = 1; 3341141cc406Sopenharmony_ci int height = 1; 3342141cc406Sopenharmony_ci SANE_Byte reg = 0xa2; 3343141cc406Sopenharmony_ci int timing=0; 3344141cc406Sopenharmony_ci 3345141cc406Sopenharmony_ci DBG (DBG_proc, "find_margin: start\n"); 3346141cc406Sopenharmony_ci 3347141cc406Sopenharmony_ci /* increase brightness to have better margin detection */ 3348141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®); 3349141cc406Sopenharmony_ci 3350141cc406Sopenharmony_ci /* maximum gain, offsets untouched */ 3351141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400 || dev->sensor == SENSOR_TYPE_4400_BARE) 3352141cc406Sopenharmony_ci { 3353141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x23); 3354141cc406Sopenharmony_ci } 3355141cc406Sopenharmony_ci else 3356141cc406Sopenharmony_ci { 3357141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3b); 3358141cc406Sopenharmony_ci } 3359141cc406Sopenharmony_ci 3360141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, 0x3f, 0x3f, 0x3f); 3361141cc406Sopenharmony_ci 3362141cc406Sopenharmony_ci /* set scan parameters */ 3363141cc406Sopenharmony_ci dev->regs[0x33] = 0x01; 3364141cc406Sopenharmony_ci dev->regs[0x34] = 0x10; 3365141cc406Sopenharmony_ci dev->regs[0x35] = 0x1b; 3366141cc406Sopenharmony_ci dev->regs[0x3a] = 0x1b; 3367141cc406Sopenharmony_ci 3368141cc406Sopenharmony_ci dev->regs[0x72] = 0x3a; 3369141cc406Sopenharmony_ci dev->regs[0x73] = 0x15; 3370141cc406Sopenharmony_ci dev->regs[0x74] = 0x62; 3371141cc406Sopenharmony_ci 3372141cc406Sopenharmony_ci timing=0; 3373141cc406Sopenharmony_ci 3374141cc406Sopenharmony_ci dev->regs[0xc0] = 0xff; 3375141cc406Sopenharmony_ci dev->regs[0xc1] = 0xff; 3376141cc406Sopenharmony_ci dev->regs[0xc2] = 0xff; 3377141cc406Sopenharmony_ci dev->regs[0xc3] = 0x00; 3378141cc406Sopenharmony_ci dev->regs[0xc4] = 0xf0; 3379141cc406Sopenharmony_ci dev->regs[0xc7] = 0x0f; 3380141cc406Sopenharmony_ci dev->regs[0xc8] = 0x00; 3381141cc406Sopenharmony_ci dev->regs[0xcb] = 0xe0; 3382141cc406Sopenharmony_ci dev->regs[0xcc] = 0xff; 3383141cc406Sopenharmony_ci dev->regs[0xcd] = 0xff; 3384141cc406Sopenharmony_ci dev->regs[0xce] = 0xff; 3385141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe9; 3386141cc406Sopenharmony_ci dev->regs[0xd0] = 0xeb; 3387141cc406Sopenharmony_ci dev->regs[0xd3] = 0x0c; 3388141cc406Sopenharmony_ci dev->regs[0xd4] = 0x0e; 3389141cc406Sopenharmony_ci dev->regs[0xd6] = 0xab; 3390141cc406Sopenharmony_ci dev->regs[0xd7] = 0x14; 3391141cc406Sopenharmony_ci dev->regs[0xd8] = 0xf6; 3392141cc406Sopenharmony_ci 3393141cc406Sopenharmony_ci dev->regs[0xda] = 0xa7; /* XXX STEF XXX à l'origine, pas 'bare' */ 3394141cc406Sopenharmony_ci 3395141cc406Sopenharmony_ci dev->regs[0xe2] = 0x01; 3396141cc406Sopenharmony_ci 3397141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x7b; 3398141cc406Sopenharmony_ci dev->regs[0xe6] = 0x15; 157b=5499 */ 3399141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 5499); 3400141cc406Sopenharmony_ci 3401141cc406Sopenharmony_ci dev->regs[0xe7] = 0x00; 3402141cc406Sopenharmony_ci dev->regs[0xe8] = 0x00; 3403141cc406Sopenharmony_ci dev->regs[0xe9] = 0x00; 3404141cc406Sopenharmony_ci dev->regs[0xea] = 0x00; 3405141cc406Sopenharmony_ci dev->regs[0xeb] = 0x00; 3406141cc406Sopenharmony_ci dev->regs[0xec] = 0x00; 3407141cc406Sopenharmony_ci dev->regs[0xed] = 0x00; 3408141cc406Sopenharmony_ci dev->regs[0xef] = 0x00; 3409141cc406Sopenharmony_ci dev->regs[0xf0] = 0x00; 3410141cc406Sopenharmony_ci dev->regs[0xf2] = 0x00; 3411141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 3412141cc406Sopenharmony_ci { 3413141cc406Sopenharmony_ci dev->regs[0xc0] = 0x00; 3414141cc406Sopenharmony_ci dev->regs[0xc1] = 0xf8; 3415141cc406Sopenharmony_ci dev->regs[0xc2] = 0x7f; 3416141cc406Sopenharmony_ci dev->regs[0xc4] = 0xf8; 3417141cc406Sopenharmony_ci dev->regs[0xc5] = 0x7f; 3418141cc406Sopenharmony_ci dev->regs[0xc6] = 0x00; 3419141cc406Sopenharmony_ci dev->regs[0xc7] = 0xf8; 3420141cc406Sopenharmony_ci dev->regs[0xc8] = 0x7f; 3421141cc406Sopenharmony_ci dev->regs[0xc9] = 0xff; 3422141cc406Sopenharmony_ci dev->regs[0xca] = 0xff; 3423141cc406Sopenharmony_ci dev->regs[0xcb] = 0x8f; 3424141cc406Sopenharmony_ci dev->regs[0xcd] = 0x07; 3425141cc406Sopenharmony_ci dev->regs[0xce] = 0x80; 3426141cc406Sopenharmony_ci dev->regs[0xcf] = 0xea; 3427141cc406Sopenharmony_ci dev->regs[0xd0] = 0xec; 3428141cc406Sopenharmony_ci dev->regs[0xd1] = 0xf7; 3429141cc406Sopenharmony_ci dev->regs[0xd2] = 0x00; 3430141cc406Sopenharmony_ci dev->regs[0xd3] = 0x10; 3431141cc406Sopenharmony_ci dev->regs[0xd4] = 0x12; 3432141cc406Sopenharmony_ci dev->regs[0xd7] = 0x31; 3433141cc406Sopenharmony_ci } 3434141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 3435141cc406Sopenharmony_ci { 3436141cc406Sopenharmony_ci dev->regs[0x13] = 0x39; /* 0x20 */ 3437141cc406Sopenharmony_ci dev->regs[0x14] = 0xf0; /* 0xf8 */ 3438141cc406Sopenharmony_ci dev->regs[0x15] = 0x29; /* 0x28 */ 3439141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; /* 0x07 */ 3440141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; /* 0x00 */ 3441141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; /* 0xff */ 3442141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; /* 0x02 */ 3443141cc406Sopenharmony_ci dev->regs[0x85] = 0x46; /* 0x00 */ 3444141cc406Sopenharmony_ci dev->regs[0x86] = 0x0b; /* 0x06 */ 3445141cc406Sopenharmony_ci dev->regs[0x87] = 0x8c; /* 0x00 */ 3446141cc406Sopenharmony_ci dev->regs[0x88] = 0x10; /* 0x06 */ 3447141cc406Sopenharmony_ci dev->regs[0x8d] = 0x3b; /* 0x00 */ 3448141cc406Sopenharmony_ci timing=0x00b0; 3449141cc406Sopenharmony_ci } 3450141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING_REG, timing); 3451141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); 3452141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); 3453141cc406Sopenharmony_ci 3454141cc406Sopenharmony_ci /* set vertical and horizontal start/end positions */ 3455141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (dev->regs, starty, starty + height, startx, 3456141cc406Sopenharmony_ci startx + width); 3457141cc406Sopenharmony_ci 3458141cc406Sopenharmony_ci /* allocate memory for the data */ 3459141cc406Sopenharmony_ci total = width * height; 3460141cc406Sopenharmony_ci data = (unsigned char *) malloc (total); 3461141cc406Sopenharmony_ci if (data == NULL) 3462141cc406Sopenharmony_ci { 3463141cc406Sopenharmony_ci DBG (DBG_error, "find_margin: failed to allocate %d bytes\n", total); 3464141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 3465141cc406Sopenharmony_ci } 3466141cc406Sopenharmony_ci 3467141cc406Sopenharmony_ci /* gray level scan */ 3468141cc406Sopenharmony_ci status = 3469141cc406Sopenharmony_ci rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x0c, 3470141cc406Sopenharmony_ci total, data); 3471141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3472141cc406Sopenharmony_ci { 3473141cc406Sopenharmony_ci free(data); 3474141cc406Sopenharmony_ci DBG (DBG_error, "find_margin: failed to scan\n"); 3475141cc406Sopenharmony_ci return status; 3476141cc406Sopenharmony_ci } 3477141cc406Sopenharmony_ci 3478141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io2) 3479141cc406Sopenharmony_ci { 3480141cc406Sopenharmony_ci write_gray_data (data, "find_margin.pnm", width, height); 3481141cc406Sopenharmony_ci } 3482141cc406Sopenharmony_ci 3483141cc406Sopenharmony_ci /* we search from left to right the first white pixel */ 3484141cc406Sopenharmony_ci x = 0; 3485141cc406Sopenharmony_ci while (x < width && data[x] < MARGIN_LEVEL) 3486141cc406Sopenharmony_ci x++; 3487141cc406Sopenharmony_ci if (x == width) 3488141cc406Sopenharmony_ci { 3489141cc406Sopenharmony_ci DBG (DBG_warn, "find_margin: failed to find left margin!\n"); 3490141cc406Sopenharmony_ci DBG (DBG_warn, "find_margin: using default...\n"); 3491141cc406Sopenharmony_ci x = 48 + 40; 3492141cc406Sopenharmony_ci } 3493141cc406Sopenharmony_ci DBG (DBG_info, "find_margin: scan area margin=%d pixels\n", x); 3494141cc406Sopenharmony_ci 3495141cc406Sopenharmony_ci /* convert the detected value into max ydpi */ 3496141cc406Sopenharmony_ci dev->left_offset = ((x - 40) * dev->model->max_xdpi) / 150; 3497141cc406Sopenharmony_ci DBG (DBG_info, "find_margin: left_offset=%d pixels\n", x); 3498141cc406Sopenharmony_ci 3499141cc406Sopenharmony_ci /* no we're done */ 3500141cc406Sopenharmony_ci free (data); 3501141cc406Sopenharmony_ci 3502141cc406Sopenharmony_ci DBG (DBG_proc, "find_margin: exit\n"); 3503141cc406Sopenharmony_ci return status; 3504141cc406Sopenharmony_ci} 3505141cc406Sopenharmony_ci 3506141cc406Sopenharmony_ci#ifdef FAST_INIT 3507141cc406Sopenharmony_ci/* 3508141cc406Sopenharmony_ci * This function initializes the device: 3509141cc406Sopenharmony_ci * - initial registers values 3510141cc406Sopenharmony_ci * - test if at home 3511141cc406Sopenharmony_ci * - head parking if needed 3512141cc406Sopenharmony_ci */ 3513141cc406Sopenharmony_cistatic SANE_Status 3514141cc406Sopenharmony_ciinitialize_device (struct Rts8891_Device *dev) 3515141cc406Sopenharmony_ci{ 3516141cc406Sopenharmony_ci SANE_Status status; 3517141cc406Sopenharmony_ci SANE_Byte reg, control; 3518141cc406Sopenharmony_ci 3519141cc406Sopenharmony_ci DBG (DBG_proc, "initialize_device: start\n"); 3520141cc406Sopenharmony_ci if (dev->initialized == SANE_TRUE) 3521141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 3522141cc406Sopenharmony_ci 3523141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x28); 3524141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x01); 3525141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x01); 3526141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 3527141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 3528141cc406Sopenharmony_ci 3529141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control); 3530141cc406Sopenharmony_ci DBG (DBG_io, "initialize_device: reg[0xb0]=0x%02x\n", control); 3531141cc406Sopenharmony_ci 3532141cc406Sopenharmony_ci /* we expect to get 0x80 */ 3533141cc406Sopenharmony_ci if (control != 0x80) 3534141cc406Sopenharmony_ci { 3535141cc406Sopenharmony_ci DBG (DBG_warn, 3536141cc406Sopenharmony_ci "initialize_device: expected reg[0xb0]=0x80, got 0x%02x\n", 3537141cc406Sopenharmony_ci control); 3538141cc406Sopenharmony_ci /* TODO fail here ??? */ 3539141cc406Sopenharmony_ci } 3540141cc406Sopenharmony_ci 3541141cc406Sopenharmony_ci /* get lamp status */ 3542141cc406Sopenharmony_ci status = sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); 3543141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 3544141cc406Sopenharmony_ci { 3545141cc406Sopenharmony_ci DBG (DBG_error, "initialize_device: failed to read lamp status!\n"); 3546141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3547141cc406Sopenharmony_ci } 3548141cc406Sopenharmony_ci DBG (DBG_io, "initialize_device: lamp status=0x%02x\n", dev->regs[0x8e]); 3549141cc406Sopenharmony_ci 3550141cc406Sopenharmony_ci /* sensor type the one for 4470c sold with XPA is slightly different 3551141cc406Sopenharmony_ci * than those sold bare, for this model we always start with xpa type sensor, 3552141cc406Sopenharmony_ci * and change it later if we detect black scans in find_origin(). In case the 3553141cc406Sopenharmony_ci * attach function set up the sensor type, we don't modify it */ 3554141cc406Sopenharmony_ci if (dev->sensor == -1) 3555141cc406Sopenharmony_ci { 3556141cc406Sopenharmony_ci dev->sensor = device->model->sensor; 3557141cc406Sopenharmony_ci } 3558141cc406Sopenharmony_ci DBG (DBG_info, "initialize_device: initial sensor type is %d\n", dev->sensor); 3559141cc406Sopenharmony_ci DBG (DBG_info, "initialize_device: reg[8e]=0x%02x\n", dev->regs[0x8e]); 3560141cc406Sopenharmony_ci 3561141cc406Sopenharmony_ci /* detects if warming up is needed */ 3562141cc406Sopenharmony_ci if ((dev->regs[0x8e] & 0x60) != 0x60) 3563141cc406Sopenharmony_ci { 3564141cc406Sopenharmony_ci DBG (DBG_info, "initialize_device: lamp needs warming\n"); 3565141cc406Sopenharmony_ci dev->needs_warming = SANE_TRUE; 3566141cc406Sopenharmony_ci } 3567141cc406Sopenharmony_ci else 3568141cc406Sopenharmony_ci { 3569141cc406Sopenharmony_ci dev->needs_warming = SANE_FALSE; 3570141cc406Sopenharmony_ci } 3571141cc406Sopenharmony_ci 3572141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LAMP_REG, ®); 3573141cc406Sopenharmony_ci 3574141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 3575141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 3576141cc406Sopenharmony_ci 3577141cc406Sopenharmony_ci /* read scanner present register */ 3578141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); 3579141cc406Sopenharmony_ci if (control != 0x00 && control != 0x01) 3580141cc406Sopenharmony_ci { 3581141cc406Sopenharmony_ci DBG (DBG_warn, 3582141cc406Sopenharmony_ci "initialize_device: unexpected LINK_REG=0x%02x\n", control); 3583141cc406Sopenharmony_ci } 3584141cc406Sopenharmony_ci 3585141cc406Sopenharmony_ci /* head parking if needed */ 3586141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &control); 3587141cc406Sopenharmony_ci if (!(control & 0x02)) 3588141cc406Sopenharmony_ci { 3589141cc406Sopenharmony_ci if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD) 3590141cc406Sopenharmony_ci { 3591141cc406Sopenharmony_ci DBG (DBG_error, "initialize_device: failed to park head!\n"); 3592141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 3593141cc406Sopenharmony_ci } 3594141cc406Sopenharmony_ci } 3595141cc406Sopenharmony_ci 3596141cc406Sopenharmony_ci /* writes initial register set */ 3597141cc406Sopenharmony_ci dev->regs[0x00] = 0xe5; /* 0xf5 */ 3598141cc406Sopenharmony_ci dev->regs[0x02] = 0x1f; /* 0x00 */ 3599141cc406Sopenharmony_ci dev->regs[0x03] = 0x1f; /* 0x00 */ 3600141cc406Sopenharmony_ci dev->regs[0x04] = 0x1f; /* 0x00 */ 3601141cc406Sopenharmony_ci dev->regs[0x05] = 0x1f; /* 0x00 */ 3602141cc406Sopenharmony_ci dev->regs[0x06] = 0x1f; /* 0x00 */ 3603141cc406Sopenharmony_ci dev->regs[0x07] = 0x1f; /* 0x00 */ 3604141cc406Sopenharmony_ci dev->regs[0x08] = 0x0a; /* 0x00 */ 3605141cc406Sopenharmony_ci dev->regs[0x09] = 0x0a; /* 0x00 */ 3606141cc406Sopenharmony_ci dev->regs[0x0a] = 0x0a; /* 0x00 */ 3607141cc406Sopenharmony_ci dev->regs[0x10] = 0x28; /* 0x60 */ 3608141cc406Sopenharmony_ci dev->regs[0x11] = 0x28; /* 0x1b */ 3609141cc406Sopenharmony_ci dev->regs[0x13] = 0x20; /* 0x3e */ 3610141cc406Sopenharmony_ci dev->regs[0x14] = 0xf8; /* 0x00 */ 3611141cc406Sopenharmony_ci dev->regs[0x15] = 0x28; /* 0x00 */ 3612141cc406Sopenharmony_ci dev->regs[0x16] = 0x07; /* 0xff */ 3613141cc406Sopenharmony_ci dev->regs[0x17] = 0x00; /* 0x3e */ 3614141cc406Sopenharmony_ci dev->regs[0x18] = 0xff; /* 0x00 */ 3615141cc406Sopenharmony_ci dev->regs[0x1d] = 0x20; /* 0x22 */ 3616141cc406Sopenharmony_ci 3617141cc406Sopenharmony_ci /* LCD display */ 3618141cc406Sopenharmony_ci dev->regs[0x20] = 0x3a; /* 0x00 */ 3619141cc406Sopenharmony_ci dev->regs[0x21] = 0xf2; /* 0x00 */ 3620141cc406Sopenharmony_ci dev->regs[0x24] = 0xff; /* 0x00 */ 3621141cc406Sopenharmony_ci dev->regs[0x25] = 0x00; /* 0xff */ 3622141cc406Sopenharmony_ci 3623141cc406Sopenharmony_ci dev->regs[0x30] = 0x00; /* 0x01 */ 3624141cc406Sopenharmony_ci dev->regs[0x31] = 0x00; /* 0x42 */ 3625141cc406Sopenharmony_ci dev->regs[0x36] = 0x07; /* 0x00 */ 3626141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; /* 0x02 */ 3627141cc406Sopenharmony_ci dev->regs[0x40] = 0x20; /* 0x80 */ 3628141cc406Sopenharmony_ci dev->regs[0x44] = 0x8c; /* 0x18 */ 3629141cc406Sopenharmony_ci dev->regs[0x45] = 0x76; /* 0x00 */ 3630141cc406Sopenharmony_ci dev->regs[0x50] = 0x00; /* 0x20 */ 3631141cc406Sopenharmony_ci dev->regs[0x51] = 0x00; /* 0x24 */ 3632141cc406Sopenharmony_ci dev->regs[0x52] = 0x00; /* 0x04 */ 3633141cc406Sopenharmony_ci dev->regs[0x64] = 0x00; /* 0x10 */ 3634141cc406Sopenharmony_ci dev->regs[0x68] = 0x00; /* 0x10 */ 3635141cc406Sopenharmony_ci dev->regs[0x6a] = 0x00; /* 0x01 */ 3636141cc406Sopenharmony_ci dev->regs[0x70] = 0x00; /* 0x20 */ 3637141cc406Sopenharmony_ci dev->regs[0x71] = 0x00; /* 0x20 */ 3638141cc406Sopenharmony_ci dev->regs[0x72] = 0xe1; /* 0x00 */ 3639141cc406Sopenharmony_ci dev->regs[0x73] = 0x14; /* 0x00 */ 3640141cc406Sopenharmony_ci dev->regs[0x74] = 0x18; /* 0x00 */ 3641141cc406Sopenharmony_ci dev->regs[0x75] = 0x15; /* 0x00 */ 3642141cc406Sopenharmony_ci dev->regs[0x76] = 0x00; /* 0x20 */ 3643141cc406Sopenharmony_ci dev->regs[0x77] = 0x00; /* 0x01 */ 3644141cc406Sopenharmony_ci dev->regs[0x79] = 0x00; /* 0x02 */ 3645141cc406Sopenharmony_ci dev->regs[0x81] = 0x00; /* 0x41 */ 3646141cc406Sopenharmony_ci dev->regs[0x83] = 0x00; /* 0x10 */ 3647141cc406Sopenharmony_ci dev->regs[0x84] = 0x00; /* 0x21 */ 3648141cc406Sopenharmony_ci dev->regs[0x85] = 0x00; /* 0x20 */ 3649141cc406Sopenharmony_ci dev->regs[0x87] = 0x00; /* 0x20 */ 3650141cc406Sopenharmony_ci dev->regs[0x88] = 0x00; /* 0x81 */ 3651141cc406Sopenharmony_ci dev->regs[0x89] = 0x00; /* 0x20 */ 3652141cc406Sopenharmony_ci dev->regs[0x8a] = 0x00; /* 0x01 */ 3653141cc406Sopenharmony_ci dev->regs[0x8b] = 0x00; /* 0x01 */ 3654141cc406Sopenharmony_ci dev->regs[0x8d] = 0x80; /* 0x22 */ 3655141cc406Sopenharmony_ci dev->regs[0x8e] = 0x68; /* 0x00 */ 3656141cc406Sopenharmony_ci dev->regs[0x8f] = 0x00; /* 0x40 */ 3657141cc406Sopenharmony_ci dev->regs[0x90] = 0x00; /* 0x05 */ 3658141cc406Sopenharmony_ci dev->regs[0x93] = 0x02; /* 0x01 */ 3659141cc406Sopenharmony_ci dev->regs[0x94] = 0x0e; /* 0x1e */ 3660141cc406Sopenharmony_ci dev->regs[0xb0] = 0x00; /* 0x80 */ 3661141cc406Sopenharmony_ci dev->regs[0xb2] = 0x02; /* 0x06 */ 3662141cc406Sopenharmony_ci dev->regs[0xc0] = 0xff; /* 0x00 */ 3663141cc406Sopenharmony_ci dev->regs[0xc1] = 0x0f; /* 0x00 */ 3664141cc406Sopenharmony_ci dev->regs[0xc3] = 0xff; /* 0x00 */ 3665141cc406Sopenharmony_ci dev->regs[0xc4] = 0xff; /* 0x00 */ 3666141cc406Sopenharmony_ci dev->regs[0xc5] = 0xff; /* 0x00 */ 3667141cc406Sopenharmony_ci dev->regs[0xc6] = 0xff; /* 0x00 */ 3668141cc406Sopenharmony_ci dev->regs[0xc7] = 0xff; /* 0x00 */ 3669141cc406Sopenharmony_ci dev->regs[0xc8] = 0xff; /* 0x00 */ 3670141cc406Sopenharmony_ci dev->regs[0xca] = 0x0e; /* 0x00 */ 3671141cc406Sopenharmony_ci dev->regs[0xcd] = 0xf0; /* 0x00 */ 3672141cc406Sopenharmony_ci dev->regs[0xce] = 0xff; /* 0x00 */ 3673141cc406Sopenharmony_ci dev->regs[0xcf] = 0xf5; /* 0x00 */ 3674141cc406Sopenharmony_ci dev->regs[0xd0] = 0xf7; /* 0x00 */ 3675141cc406Sopenharmony_ci dev->regs[0xd1] = 0xea; /* 0x00 */ 3676141cc406Sopenharmony_ci dev->regs[0xd2] = 0x0b; /* 0x00 */ 3677141cc406Sopenharmony_ci dev->regs[0xd3] = 0x03; /* 0x00 */ 3678141cc406Sopenharmony_ci dev->regs[0xd4] = 0x05; /* 0x01 */ 3679141cc406Sopenharmony_ci dev->regs[0xd5] = 0x86; /* 0x06 */ 3680141cc406Sopenharmony_ci dev->regs[0xd7] = 0x30; /* 0x10 */ 3681141cc406Sopenharmony_ci dev->regs[0xd8] = 0xf6; /* 0x7a */ 3682141cc406Sopenharmony_ci dev->regs[0xd9] = 0x80; /* 0x00 */ 3683141cc406Sopenharmony_ci dev->regs[0xda] = 0x00; /* 0x15 */ 3684141cc406Sopenharmony_ci dev->regs[0xe2] = 0x01; /* 0x00 */ 3685141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x14; 0x0f */ 3686141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 20); 3687141cc406Sopenharmony_ci 3688141cc406Sopenharmony_ci status = rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 3689141cc406Sopenharmony_ci 3690141cc406Sopenharmony_ci DBG (DBG_proc, "initialize_device: exit\n"); 3691141cc406Sopenharmony_ci dev->initialized = SANE_TRUE; 3692141cc406Sopenharmony_ci 3693141cc406Sopenharmony_ci return status; 3694141cc406Sopenharmony_ci} 3695141cc406Sopenharmony_ci#else /* FAST_INIT */ 3696141cc406Sopenharmony_ci 3697141cc406Sopenharmony_cistatic SANE_Status 3698141cc406Sopenharmony_ciinit_registers (struct Rts8891_Device *dev) 3699141cc406Sopenharmony_ci{ 3700141cc406Sopenharmony_ciint i; 3701141cc406Sopenharmony_ci 3702141cc406Sopenharmony_ci /* initial set written to scanner 3703141cc406Sopenharmony_ci * 0xe5 0x41 0x1f 0x1f 0x1f 0x1f 0x1f 0x1f 0x0a 0x0a 0x0a 0x70 0x00 0x00 0x00 0x00 0x60 0x1b 0x08 0x20 0x00 0x20 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x3a 0xf2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x10 0x00 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x00 0x8c 0x76 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x68 0x00 0x00 0x00 0x00 0x02 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xcc 0x27 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 ---- 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x00 0x86 0x1b 0x00 0xff 0x00 0x27 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 3704141cc406Sopenharmony_ci */ 3705141cc406Sopenharmony_ci /* lengthy set up to make register content obvious, may be some day I will 3706141cc406Sopenharmony_ci * group corresponding values between models */ 3707141cc406Sopenharmony_ci switch (dev->sensor) 3708141cc406Sopenharmony_ci { 3709141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 3710141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 3711141cc406Sopenharmony_ci dev->regs[0x01] = 0x41; 3712141cc406Sopenharmony_ci dev->regs[0x0b] = 0x70; 3713141cc406Sopenharmony_ci dev->regs[0x0c] = 0x00; 3714141cc406Sopenharmony_ci dev->regs[0x0d] = 0x00; 3715141cc406Sopenharmony_ci dev->regs[0x0e] = 0x00; 3716141cc406Sopenharmony_ci dev->regs[0x0f] = 0x00; 3717141cc406Sopenharmony_ci 3718141cc406Sopenharmony_ci dev->regs[0x12] = 0x00; 3719141cc406Sopenharmony_ci dev->regs[0x13] = 0x20; 3720141cc406Sopenharmony_ci dev->regs[0x14] = 0x00; 3721141cc406Sopenharmony_ci dev->regs[0x15] = 0x20; 3722141cc406Sopenharmony_ci dev->regs[0x16] = 0x00; 3723141cc406Sopenharmony_ci dev->regs[0x17] = 0x00; 3724141cc406Sopenharmony_ci dev->regs[0x18] = 0x00; 3725141cc406Sopenharmony_ci dev->regs[0x19] = 0x00; 3726141cc406Sopenharmony_ci dev->regs[0x1a] = 0x00; 3727141cc406Sopenharmony_ci dev->regs[0x1b] = 0x00; 3728141cc406Sopenharmony_ci dev->regs[0x1c] = 0x00; 3729141cc406Sopenharmony_ci dev->regs[0x1d] = 0x20; 3730141cc406Sopenharmony_ci dev->regs[0x1e] = 0x00; 3731141cc406Sopenharmony_ci dev->regs[0x1f] = 0x00; 3732141cc406Sopenharmony_ci 3733141cc406Sopenharmony_ci /* LCD display */ 3734141cc406Sopenharmony_ci dev->regs[0x20] = 0x3a; 3735141cc406Sopenharmony_ci dev->regs[0x21] = 0xf2; 3736141cc406Sopenharmony_ci dev->regs[0x22] = 0x00; 3737141cc406Sopenharmony_ci 3738141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; 3739141cc406Sopenharmony_ci dev->regs[0x24] = 0x00; 3740141cc406Sopenharmony_ci dev->regs[0x25] = 0x00; 3741141cc406Sopenharmony_ci dev->regs[0x26] = 0x00; 3742141cc406Sopenharmony_ci dev->regs[0x27] = 0x00; 3743141cc406Sopenharmony_ci dev->regs[0x28] = 0x00; 3744141cc406Sopenharmony_ci dev->regs[0x29] = 0x00; 3745141cc406Sopenharmony_ci dev->regs[0x2a] = 0x00; 3746141cc406Sopenharmony_ci dev->regs[0x2b] = 0x00; 3747141cc406Sopenharmony_ci dev->regs[0x2c] = 0x00; 3748141cc406Sopenharmony_ci dev->regs[0x2d] = 0x00; 3749141cc406Sopenharmony_ci dev->regs[0x2e] = 0x00; 3750141cc406Sopenharmony_ci dev->regs[0x2f] = 0x00; 3751141cc406Sopenharmony_ci dev->regs[0x30] = 0x00; 3752141cc406Sopenharmony_ci dev->regs[0x31] = 0x00; 3753141cc406Sopenharmony_ci dev->regs[0x32] = 0x00; 3754141cc406Sopenharmony_ci dev->regs[0x33] = 0x00; 3755141cc406Sopenharmony_ci dev->regs[0x34] = 0x10; 3756141cc406Sopenharmony_ci dev->regs[0x35] = 0x00; 3757141cc406Sopenharmony_ci dev->regs[0x36] = 0x07; 3758141cc406Sopenharmony_ci dev->regs[0x37] = 0x00; 3759141cc406Sopenharmony_ci dev->regs[0x38] = 0x00; 3760141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; 3761141cc406Sopenharmony_ci dev->regs[0x3a] = 0x00; 3762141cc406Sopenharmony_ci dev->regs[0x3b] = 0x00; 3763141cc406Sopenharmony_ci dev->regs[0x3c] = 0x00; 3764141cc406Sopenharmony_ci dev->regs[0x3d] = 0x00; 3765141cc406Sopenharmony_ci dev->regs[0x3e] = 0x00; 3766141cc406Sopenharmony_ci dev->regs[0x3f] = 0x00; 3767141cc406Sopenharmony_ci dev->regs[0x40] = 0x20; 3768141cc406Sopenharmony_ci dev->regs[0x41] = 0x00; 3769141cc406Sopenharmony_ci dev->regs[0x42] = 0x00; 3770141cc406Sopenharmony_ci dev->regs[0x43] = 0x00; 3771141cc406Sopenharmony_ci dev->regs[0x44] = 0x8c; 3772141cc406Sopenharmony_ci dev->regs[0x45] = 0x76; 3773141cc406Sopenharmony_ci dev->regs[0x46] = 0x00; 3774141cc406Sopenharmony_ci dev->regs[0x47] = 0x00; 3775141cc406Sopenharmony_ci dev->regs[0x48] = 0x00; 3776141cc406Sopenharmony_ci dev->regs[0x49] = 0x00; 3777141cc406Sopenharmony_ci dev->regs[0x4a] = 0x00; 3778141cc406Sopenharmony_ci dev->regs[0x4b] = 0x00; 3779141cc406Sopenharmony_ci dev->regs[0x4c] = 0x00; 3780141cc406Sopenharmony_ci dev->regs[0x4d] = 0x00; 3781141cc406Sopenharmony_ci dev->regs[0x4e] = 0x00; 3782141cc406Sopenharmony_ci dev->regs[0x4f] = 0x00; 3783141cc406Sopenharmony_ci dev->regs[0x50] = 0x00; 3784141cc406Sopenharmony_ci dev->regs[0x51] = 0x00; 3785141cc406Sopenharmony_ci dev->regs[0x52] = 0x00; 3786141cc406Sopenharmony_ci dev->regs[0x53] = 0x00; 3787141cc406Sopenharmony_ci dev->regs[0x54] = 0x00; 3788141cc406Sopenharmony_ci dev->regs[0x55] = 0x00; 3789141cc406Sopenharmony_ci dev->regs[0x56] = 0x00; 3790141cc406Sopenharmony_ci dev->regs[0x57] = 0x00; 3791141cc406Sopenharmony_ci dev->regs[0x58] = 0x00; 3792141cc406Sopenharmony_ci dev->regs[0x59] = 0x00; 3793141cc406Sopenharmony_ci dev->regs[0x5a] = 0x00; 3794141cc406Sopenharmony_ci dev->regs[0x5b] = 0x00; 3795141cc406Sopenharmony_ci dev->regs[0x5c] = 0x00; 3796141cc406Sopenharmony_ci dev->regs[0x5d] = 0x00; 3797141cc406Sopenharmony_ci dev->regs[0x5e] = 0x00; 3798141cc406Sopenharmony_ci dev->regs[0x5f] = 0x00; 3799141cc406Sopenharmony_ci dev->regs[0x64] = 0x00; 3800141cc406Sopenharmony_ci dev->regs[0x65] = 0x00; 3801141cc406Sopenharmony_ci dev->regs[0x66] = 0x00; 3802141cc406Sopenharmony_ci dev->regs[0x67] = 0x00; 3803141cc406Sopenharmony_ci dev->regs[0x68] = 0x00; 3804141cc406Sopenharmony_ci dev->regs[0x69] = 0x00; 3805141cc406Sopenharmony_ci dev->regs[0x6a] = 0x00; 3806141cc406Sopenharmony_ci dev->regs[0x6b] = 0x00; 3807141cc406Sopenharmony_ci dev->regs[0x6e] = 0x00; 3808141cc406Sopenharmony_ci dev->regs[0x6f] = 0x00; 3809141cc406Sopenharmony_ci dev->regs[0x70] = 0x00; 3810141cc406Sopenharmony_ci dev->regs[0x71] = 0x00; 3811141cc406Sopenharmony_ci dev->regs[0x72] = 0x00; 3812141cc406Sopenharmony_ci dev->regs[0x73] = 0x00; 3813141cc406Sopenharmony_ci dev->regs[0x74] = 0x00; 3814141cc406Sopenharmony_ci dev->regs[0x75] = 0x00; 3815141cc406Sopenharmony_ci dev->regs[0x76] = 0x00; 3816141cc406Sopenharmony_ci dev->regs[0x77] = 0x00; 3817141cc406Sopenharmony_ci dev->regs[0x78] = 0x00; 3818141cc406Sopenharmony_ci dev->regs[0x79] = 0x00; 3819141cc406Sopenharmony_ci dev->regs[0x7a] = 0x00; 3820141cc406Sopenharmony_ci dev->regs[0x7b] = 0x00; 3821141cc406Sopenharmony_ci dev->regs[0x7c] = 0x00; 3822141cc406Sopenharmony_ci dev->regs[0x7d] = 0x00; 3823141cc406Sopenharmony_ci dev->regs[0x7e] = 0x00; 3824141cc406Sopenharmony_ci dev->regs[0x7f] = 0x00; 3825141cc406Sopenharmony_ci dev->regs[0x80] = 0x00; 3826141cc406Sopenharmony_ci dev->regs[0x81] = 0x00; 3827141cc406Sopenharmony_ci dev->regs[0x82] = 0x00; 3828141cc406Sopenharmony_ci dev->regs[0x83] = 0x00; 3829141cc406Sopenharmony_ci dev->regs[0x84] = 0x00; 3830141cc406Sopenharmony_ci dev->regs[0x85] = 0x00; 3831141cc406Sopenharmony_ci dev->regs[0x86] = 0x00; 3832141cc406Sopenharmony_ci dev->regs[0x87] = 0x00; 3833141cc406Sopenharmony_ci dev->regs[0x88] = 0x00; 3834141cc406Sopenharmony_ci dev->regs[0x89] = 0x00; 3835141cc406Sopenharmony_ci dev->regs[0x8a] = 0x00; 3836141cc406Sopenharmony_ci dev->regs[0x8b] = 0x00; 3837141cc406Sopenharmony_ci dev->regs[0x8c] = 0x00; 3838141cc406Sopenharmony_ci dev->regs[0x8d] = 0x80; 3839141cc406Sopenharmony_ci dev->regs[0x8e] = 0x68; 3840141cc406Sopenharmony_ci dev->regs[0x8f] = 0x00; 3841141cc406Sopenharmony_ci dev->regs[0x90] = 0x00; 3842141cc406Sopenharmony_ci dev->regs[0x91] = 0x00; 3843141cc406Sopenharmony_ci dev->regs[0x92] = 0x00; 3844141cc406Sopenharmony_ci dev->regs[0x93] = 0x02; 3845141cc406Sopenharmony_ci dev->regs[0x94] = 0x0e; 3846141cc406Sopenharmony_ci dev->regs[0x95] = 0x00; 3847141cc406Sopenharmony_ci dev->regs[0x96] = 0x00; 3848141cc406Sopenharmony_ci dev->regs[0x97] = 0x00; 3849141cc406Sopenharmony_ci dev->regs[0x98] = 0x00; 3850141cc406Sopenharmony_ci dev->regs[0x99] = 0x00; 3851141cc406Sopenharmony_ci dev->regs[0x9a] = 0x00; 3852141cc406Sopenharmony_ci dev->regs[0x9b] = 0x00; 3853141cc406Sopenharmony_ci dev->regs[0x9c] = 0x00; 3854141cc406Sopenharmony_ci dev->regs[0x9d] = 0x00; 3855141cc406Sopenharmony_ci dev->regs[0x9e] = 0x00; 3856141cc406Sopenharmony_ci dev->regs[0x9f] = 0x00; 3857141cc406Sopenharmony_ci dev->regs[0xa0] = 0x00; 3858141cc406Sopenharmony_ci dev->regs[0xa1] = 0x00; 3859141cc406Sopenharmony_ci dev->regs[0xa2] = 0x00; 3860141cc406Sopenharmony_ci dev->regs[0xa3] = 0xcc; 3861141cc406Sopenharmony_ci dev->regs[0xa4] = 0x27; 3862141cc406Sopenharmony_ci dev->regs[0xa5] = 0x64; 3863141cc406Sopenharmony_ci dev->regs[0xa6] = 0x00; 3864141cc406Sopenharmony_ci dev->regs[0xa7] = 0x00; 3865141cc406Sopenharmony_ci dev->regs[0xa8] = 0x00; 3866141cc406Sopenharmony_ci dev->regs[0xa9] = 0x00; 3867141cc406Sopenharmony_ci dev->regs[0xaa] = 0x00; 3868141cc406Sopenharmony_ci dev->regs[0xab] = 0x00; 3869141cc406Sopenharmony_ci dev->regs[0xac] = 0x00; 3870141cc406Sopenharmony_ci dev->regs[0xad] = 0x00; 3871141cc406Sopenharmony_ci dev->regs[0xae] = 0x00; 3872141cc406Sopenharmony_ci dev->regs[0xaf] = 0x00; 3873141cc406Sopenharmony_ci dev->regs[0xb0] = 0x00; 3874141cc406Sopenharmony_ci dev->regs[0xb1] = 0x00; 3875141cc406Sopenharmony_ci dev->regs[0xb2] = 0x02; 3876141cc406Sopenharmony_ci dev->regs[0xb4] = 0x00; 3877141cc406Sopenharmony_ci dev->regs[0xb5] = 0x00; 3878141cc406Sopenharmony_ci dev->regs[0xb6] = 0x00; 3879141cc406Sopenharmony_ci dev->regs[0xb7] = 0x00; 3880141cc406Sopenharmony_ci dev->regs[0xb8] = 0x00; 3881141cc406Sopenharmony_ci dev->regs[0xb9] = 0x00; 3882141cc406Sopenharmony_ci dev->regs[0xba] = 0x00; 3883141cc406Sopenharmony_ci dev->regs[0xbb] = 0x00; 3884141cc406Sopenharmony_ci dev->regs[0xbc] = 0x00; 3885141cc406Sopenharmony_ci dev->regs[0xbd] = 0x00; 3886141cc406Sopenharmony_ci dev->regs[0xbe] = 0x00; 3887141cc406Sopenharmony_ci dev->regs[0xbf] = 0x00; 3888141cc406Sopenharmony_ci dev->regs[0xc0] = 0x00; 3889141cc406Sopenharmony_ci dev->regs[0xc1] = 0x00; 3890141cc406Sopenharmony_ci dev->regs[0xc2] = 0x00; 3891141cc406Sopenharmony_ci dev->regs[0xc3] = 0x00; 3892141cc406Sopenharmony_ci dev->regs[0xc4] = 0x00; 3893141cc406Sopenharmony_ci dev->regs[0xc5] = 0x00; 3894141cc406Sopenharmony_ci dev->regs[0xc6] = 0x00; 3895141cc406Sopenharmony_ci dev->regs[0xc7] = 0x00; 3896141cc406Sopenharmony_ci dev->regs[0xc8] = 0x00; 3897141cc406Sopenharmony_ci dev->regs[0xc9] = 0x00; 3898141cc406Sopenharmony_ci dev->regs[0xca] = 0x00; 3899141cc406Sopenharmony_ci dev->regs[0xcb] = 0x00; 3900141cc406Sopenharmony_ci dev->regs[0xcc] = 0x00; 3901141cc406Sopenharmony_ci dev->regs[0xcd] = 0x00; 3902141cc406Sopenharmony_ci dev->regs[0xce] = 0x00; 3903141cc406Sopenharmony_ci dev->regs[0xcf] = 0x00; 3904141cc406Sopenharmony_ci dev->regs[0xd0] = 0x00; 3905141cc406Sopenharmony_ci dev->regs[0xd1] = 0x00; 3906141cc406Sopenharmony_ci dev->regs[0xd2] = 0x00; 3907141cc406Sopenharmony_ci dev->regs[0xd3] = 0x00; 3908141cc406Sopenharmony_ci dev->regs[0xd4] = 0x00; 3909141cc406Sopenharmony_ci dev->regs[0xd5] = 0x86; 3910141cc406Sopenharmony_ci dev->regs[0xd6] = 0x1b; 3911141cc406Sopenharmony_ci dev->regs[0xd7] = 0x00; 3912141cc406Sopenharmony_ci dev->regs[0xd8] = 0xff; 3913141cc406Sopenharmony_ci dev->regs[0xd9] = 0x00; 3914141cc406Sopenharmony_ci dev->regs[0xda] = 0x27; 3915141cc406Sopenharmony_ci dev->regs[0xdb] = 0x00; 3916141cc406Sopenharmony_ci dev->regs[0xdc] = 0x00; 3917141cc406Sopenharmony_ci dev->regs[0xdd] = 0x00; 3918141cc406Sopenharmony_ci dev->regs[0xde] = 0x00; 3919141cc406Sopenharmony_ci dev->regs[0xdf] = 0x00; 3920141cc406Sopenharmony_ci dev->regs[0xe0] = 0x00; 3921141cc406Sopenharmony_ci dev->regs[0xe1] = 0x00; 3922141cc406Sopenharmony_ci dev->regs[0xe2] = 0x01; 3923141cc406Sopenharmony_ci dev->regs[0xe3] = 0x00; 3924141cc406Sopenharmony_ci dev->regs[0xe4] = 0x00; 3925141cc406Sopenharmony_ci 3926141cc406Sopenharmony_ci /*dev->regs[0xe5] = 0x14; 3927141cc406Sopenharmony_ci dev->regs[0xe6] = 0x00; 14=20 */ 3928141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 20); 3929141cc406Sopenharmony_ci 3930141cc406Sopenharmony_ci dev->regs[0xe7] = 0x00; 3931141cc406Sopenharmony_ci dev->regs[0xe8] = 0x00; 3932141cc406Sopenharmony_ci dev->regs[0xe9] = 0x00; 3933141cc406Sopenharmony_ci dev->regs[0xea] = 0x00; 3934141cc406Sopenharmony_ci dev->regs[0xeb] = 0x00; 3935141cc406Sopenharmony_ci dev->regs[0xec] = 0x00; 3936141cc406Sopenharmony_ci dev->regs[0xed] = 0x00; 3937141cc406Sopenharmony_ci dev->regs[0xee] = 0x00; 3938141cc406Sopenharmony_ci dev->regs[0xef] = 0x00; 3939141cc406Sopenharmony_ci dev->regs[0xf0] = 0x00; 3940141cc406Sopenharmony_ci dev->regs[0xf1] = 0x00; 3941141cc406Sopenharmony_ci dev->regs[0xf2] = 0x00; 3942141cc406Sopenharmony_ci dev->regs[0xf3] = 0x00; 3943141cc406Sopenharmony_ci break; 3944141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 3945141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 3946141cc406Sopenharmony_ci for (i = 0; i < dev->reg_count; i++) 3947141cc406Sopenharmony_ci dev->regs[i] = 0x00; 3948141cc406Sopenharmony_ci /* 2d may be 0x20 or 0x22: signals something */ 3949141cc406Sopenharmony_ci dev->regs[0x00] = 0xf5; 3950141cc406Sopenharmony_ci dev->regs[0x01] = 0x41; 3951141cc406Sopenharmony_ci dev->regs[0x0b] = 0x70; 3952141cc406Sopenharmony_ci dev->regs[0x10] = 0x50; 3953141cc406Sopenharmony_ci dev->regs[0x11] = 0x03; 3954141cc406Sopenharmony_ci dev->regs[0x12] = 0xff; 3955141cc406Sopenharmony_ci dev->regs[0x13] = 0x3e; 3956141cc406Sopenharmony_ci dev->regs[0x16] = 0xff; 3957141cc406Sopenharmony_ci dev->regs[0x17] = 0x3e; 3958141cc406Sopenharmony_ci dev->regs[0x1d] = 0x22; 3959141cc406Sopenharmony_ci dev->regs[0x22] = 0x01; 3960141cc406Sopenharmony_ci dev->regs[0x23] = 0xff; 3961141cc406Sopenharmony_ci dev->regs[0x25] = 0xfe; 3962141cc406Sopenharmony_ci dev->regs[0x34] = 0x10; 3963141cc406Sopenharmony_ci dev->regs[0x39] = 0x02; 3964141cc406Sopenharmony_ci dev->regs[0x40] = 0x80; 3965141cc406Sopenharmony_ci dev->regs[0x44] = 0x8c; 3966141cc406Sopenharmony_ci dev->regs[0x45] = 0x76; 3967141cc406Sopenharmony_ci dev->regs[0x50] = 0x20; 3968141cc406Sopenharmony_ci dev->regs[0x8b] = 0xff; 3969141cc406Sopenharmony_ci dev->regs[0x8c] = 0x3f; 3970141cc406Sopenharmony_ci dev->regs[0x8d] = 0x80; 3971141cc406Sopenharmony_ci dev->regs[0x8e] = 0x68; 3972141cc406Sopenharmony_ci dev->regs[0x93] = 0x01; 3973141cc406Sopenharmony_ci dev->regs[0x94] = 0x1e; 3974141cc406Sopenharmony_ci dev->regs[0xa3] = 0xcc; 3975141cc406Sopenharmony_ci dev->regs[0xa4] = 0x27; 3976141cc406Sopenharmony_ci dev->regs[0xa5] = 0x64; 3977141cc406Sopenharmony_ci dev->regs[0xb0] = 0x80; 3978141cc406Sopenharmony_ci dev->regs[0xb1] = 0x01; 3979141cc406Sopenharmony_ci dev->regs[0xb2] = 0x06; 3980141cc406Sopenharmony_ci dev->regs[0xd4] = 0x01; 3981141cc406Sopenharmony_ci dev->regs[0xd5] = 0x06; 3982141cc406Sopenharmony_ci dev->regs[0xd6] = 0x1b; 3983141cc406Sopenharmony_ci dev->regs[0xd7] = 0x10; 3984141cc406Sopenharmony_ci dev->regs[0xd8] = 0x7a; 3985141cc406Sopenharmony_ci dev->regs[0xda] = 0xa7; 3986141cc406Sopenharmony_ci dev->regs[0xe5] = 0x0f; 3987141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 3988141cc406Sopenharmony_ci { 3989141cc406Sopenharmony_ci dev->regs[0x30] = 0x40; /* 0x00 */ 3990141cc406Sopenharmony_ci dev->regs[0x31] = 0x80; /* 0x00 */ 3991141cc406Sopenharmony_ci dev->regs[0x44] = 0x00; /* 0x8c */ 3992141cc406Sopenharmony_ci dev->regs[0x45] = 0x00; /* 0x76 */ 3993141cc406Sopenharmony_ci dev->regs[0x52] = 0x04; /* 0x00 */ 3994141cc406Sopenharmony_ci dev->regs[0x69] = 0x01; /* 0x00 */ 3995141cc406Sopenharmony_ci dev->regs[0x6a] = 0x10; /* 0x00 */ 3996141cc406Sopenharmony_ci dev->regs[0x6e] = 0x08; /* 0x00 */ 3997141cc406Sopenharmony_ci dev->regs[0x70] = 0x40; /* 0x00 */ 3998141cc406Sopenharmony_ci dev->regs[0x71] = 0x08; /* 0x00 */ 3999141cc406Sopenharmony_ci dev->regs[0x78] = 0x08; /* 0x00 */ 4000141cc406Sopenharmony_ci dev->regs[0x79] = 0x11; /* 0x00 */ 4001141cc406Sopenharmony_ci dev->regs[0x82] = 0x40; /* 0x00 */ 4002141cc406Sopenharmony_ci dev->regs[0x83] = 0x30; /* 0x00 */ 4003141cc406Sopenharmony_ci dev->regs[0x84] = 0x45; /* 0x00 */ 4004141cc406Sopenharmony_ci dev->regs[0x87] = 0x02; /* 0x00 */ 4005141cc406Sopenharmony_ci dev->regs[0x88] = 0x05; /* 0x00 */ 4006141cc406Sopenharmony_ci dev->regs[0x8b] = 0x01; /* 0xff */ 4007141cc406Sopenharmony_ci dev->regs[0x8c] = 0x80; /* 0x3f */ 4008141cc406Sopenharmony_ci dev->regs[0x8d] = 0x04; /* 0x80 */ 4009141cc406Sopenharmony_ci dev->regs[0x8e] = 0x10; /* 0x68 */ 4010141cc406Sopenharmony_ci dev->regs[0x8f] = 0x01; /* 0x00 */ 4011141cc406Sopenharmony_ci dev->regs[0x90] = 0x80; /* 0x00 */ 4012141cc406Sopenharmony_ci } 4013141cc406Sopenharmony_ci break; 4014141cc406Sopenharmony_ci } 4015141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4016141cc406Sopenharmony_ci} 4017141cc406Sopenharmony_ci 4018141cc406Sopenharmony_ci/* 4019141cc406Sopenharmony_ci * This function initializes the device: 4020141cc406Sopenharmony_ci * - initial registers values 4021141cc406Sopenharmony_ci * - test if at home 4022141cc406Sopenharmony_ci * - head parking if needed 4023141cc406Sopenharmony_ci */ 4024141cc406Sopenharmony_cistatic SANE_Status 4025141cc406Sopenharmony_ciinit_device (struct Rts8891_Device *dev) 4026141cc406Sopenharmony_ci{ 4027141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 4028141cc406Sopenharmony_ci SANE_Byte control, reg, id; 4029141cc406Sopenharmony_ci SANE_Int i, page; 4030141cc406Sopenharmony_ci SANE_Byte buffer[2072]; 4031141cc406Sopenharmony_ci char message[256 * 6]; 4032141cc406Sopenharmony_ci SANE_Int val; 4033141cc406Sopenharmony_ci 4034141cc406Sopenharmony_ci /* these commands are used to access NVRAM through a serial manner */ 4035141cc406Sopenharmony_ci /* we ignore NVRAM settingsd for now */ 4036141cc406Sopenharmony_ci SANE_Byte nv_cmd1[21] = 4037141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 4038141cc406Sopenharmony_ci 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08 4039141cc406Sopenharmony_ci }; 4040141cc406Sopenharmony_ci SANE_Byte nv_cmd2[21] = 4041141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 4042141cc406Sopenharmony_ci 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08 4043141cc406Sopenharmony_ci }; 4044141cc406Sopenharmony_ci SANE_Byte nv_cmd3[21] = 4045141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 4046141cc406Sopenharmony_ci 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08 4047141cc406Sopenharmony_ci }; 4048141cc406Sopenharmony_ci SANE_Byte nv_cmd4[21] = 4049141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 4050141cc406Sopenharmony_ci 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08 4051141cc406Sopenharmony_ci }; 4052141cc406Sopenharmony_ci SANE_Byte nv_cmd5[21] = 4053141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 4054141cc406Sopenharmony_ci 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08 4055141cc406Sopenharmony_ci }; 4056141cc406Sopenharmony_ci SANE_Byte nv_cmd6[21] = 4057141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 4058141cc406Sopenharmony_ci 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08 4059141cc406Sopenharmony_ci }; 4060141cc406Sopenharmony_ci SANE_Byte nv_cmd7[21] = 4061141cc406Sopenharmony_ci { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 4062141cc406Sopenharmony_ci 0x28, 0x38, 0x08, 0x18, 0x08, 0x18, 0x08, 0x18, 0x08 4063141cc406Sopenharmony_ci }; 4064141cc406Sopenharmony_ci 4065141cc406Sopenharmony_ci DBG (DBG_proc, "init_device: start\n"); 4066141cc406Sopenharmony_ci if (dev->initialized == SANE_TRUE) 4067141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 4068141cc406Sopenharmony_ci 4069141cc406Sopenharmony_ci /* read control register, if busy, something will have to be done ... */ 4070141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4071141cc406Sopenharmony_ci DBG (DBG_io, "init_device: control=0x%02x\n", control); 4072141cc406Sopenharmony_ci 4073141cc406Sopenharmony_ci /* when just plugged, we expect to get 0x04 */ 4074141cc406Sopenharmony_ci if (control != 0x04) 4075141cc406Sopenharmony_ci { 4076141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: expected control=0x04, got 0x%02x\n", 4077141cc406Sopenharmony_ci control); 4078141cc406Sopenharmony_ci } 4079141cc406Sopenharmony_ci 4080141cc406Sopenharmony_ci /* then read "link" register */ 4081141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control); 4082141cc406Sopenharmony_ci DBG (DBG_io, "init_device: link=0x%02x\n", control); 4083141cc406Sopenharmony_ci 4084141cc406Sopenharmony_ci /* we expect to get 0x80 */ 4085141cc406Sopenharmony_ci if (control != 0x80) 4086141cc406Sopenharmony_ci { 4087141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: expected link=0x80, got 0x%02x\n", 4088141cc406Sopenharmony_ci control); 4089141cc406Sopenharmony_ci } 4090141cc406Sopenharmony_ci 4091141cc406Sopenharmony_ci /* reads scanner status */ 4092141cc406Sopenharmony_ci sanei_rts88xx_get_status (dev->devnum, dev->regs); 4093141cc406Sopenharmony_ci DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10], 4094141cc406Sopenharmony_ci dev->regs[0x11]); 4095141cc406Sopenharmony_ci 4096141cc406Sopenharmony_ci /* reads lamp status and sensor information */ 4097141cc406Sopenharmony_ci sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); 4098141cc406Sopenharmony_ci DBG (DBG_io, "init_device: lamp status=0x%02x\n", dev->regs[0x8e]); 4099141cc406Sopenharmony_ci 4100141cc406Sopenharmony_ci /* initialize sensor with default from model */ 4101141cc406Sopenharmony_ci dev->sensor = dev->model->sensor; 4102141cc406Sopenharmony_ci DBG (DBG_info, "init_device: reg[8e]=0x%02x\n", dev->regs[0x8e]); 4103141cc406Sopenharmony_ci 4104141cc406Sopenharmony_ci /* reset lamp */ 4105141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 4106141cc406Sopenharmony_ci if ((dev->regs[0x8e] & 0x60) != 0x60) 4107141cc406Sopenharmony_ci { 4108141cc406Sopenharmony_ci DBG (DBG_info, "init_device: lamp needs warming\n"); 4109141cc406Sopenharmony_ci dev->needs_warming = SANE_TRUE; 4110141cc406Sopenharmony_ci } 4111141cc406Sopenharmony_ci else 4112141cc406Sopenharmony_ci { 4113141cc406Sopenharmony_ci dev->needs_warming = SANE_FALSE; 4114141cc406Sopenharmony_ci } 4115141cc406Sopenharmony_ci 4116141cc406Sopenharmony_ci /* reads lcd panel status */ 4117141cc406Sopenharmony_ci sanei_rts88xx_get_lcd (dev->devnum, dev->regs); 4118141cc406Sopenharmony_ci DBG (DBG_io, "init_device: lcd panel=0x%02x 0x%02x 0x%02x\n", 4119141cc406Sopenharmony_ci dev->regs[0x20], dev->regs[0x21], dev->regs[0x22]); 4120141cc406Sopenharmony_ci 4121141cc406Sopenharmony_ci /* read mainboard ID/scanner present register */ 4122141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &id); 4123141cc406Sopenharmony_ci DBG (DBG_io, "init_device: link=0x%02x\n", id); 4124141cc406Sopenharmony_ci 4125141cc406Sopenharmony_ci /* only known ID is currently 0x00 or 0x01 */ 4126141cc406Sopenharmony_ci if (id != 0x00 && id != 0x01) 4127141cc406Sopenharmony_ci { 4128141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: expected id=0x00 or 0x01, got 0x%02x\n", 4129141cc406Sopenharmony_ci id); 4130141cc406Sopenharmony_ci } 4131141cc406Sopenharmony_ci 4132141cc406Sopenharmony_ci /* write 0x00 twice to control */ 4133141cc406Sopenharmony_ci control = 0x00; 4134141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, control); 4135141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, control); 4136141cc406Sopenharmony_ci 4137141cc406Sopenharmony_ci /* read initial register set */ 4138141cc406Sopenharmony_ci sanei_rts88xx_read_regs (dev->devnum, 0, dev->regs, dev->reg_count); 4139141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io2) 4140141cc406Sopenharmony_ci { 4141141cc406Sopenharmony_ci sprintf (message, "init_device: initial register settings: "); 4142141cc406Sopenharmony_ci for (i = 0; i < dev->reg_count; i++) 4143141cc406Sopenharmony_ci sprintf (message + strlen (message), "0x%02x ", dev->regs[i]); 4144141cc406Sopenharmony_ci 4145141cc406Sopenharmony_ci DBG (DBG_io2, "%s\n", message); 4146141cc406Sopenharmony_ci } 4147141cc406Sopenharmony_ci 4148141cc406Sopenharmony_ci /* initial sensor guess */ 4149141cc406Sopenharmony_ci val = dev->regs[0x44] + 256 * dev->regs[0x45]; 4150141cc406Sopenharmony_ci DBG (DBG_io, "init_device: R44/45=0x%04x\n", val); 4151141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 4152141cc406Sopenharmony_ci { 4153141cc406Sopenharmony_ci if(val != 0x00) 4154141cc406Sopenharmony_ci { 4155141cc406Sopenharmony_ci DBG (DBG_info, "init_device: SENSOR_TYPE_4400 detected\n"); 4156141cc406Sopenharmony_ci } 4157141cc406Sopenharmony_ci else 4158141cc406Sopenharmony_ci { 4159141cc406Sopenharmony_ci DBG (DBG_info, "init_device: SENSOR_TYPE_4400_BARE detected\n"); 4160141cc406Sopenharmony_ci dev->sensor = SENSOR_TYPE_4400_BARE; 4161141cc406Sopenharmony_ci } 4162141cc406Sopenharmony_ci } 4163141cc406Sopenharmony_ci 4164141cc406Sopenharmony_ci init_registers(dev); 4165141cc406Sopenharmony_ci 4166141cc406Sopenharmony_ci sanei_rts88xx_set_offset (dev->regs, 31, 31, 31); 4167141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, 10, 10, 10); 4168141cc406Sopenharmony_ci dev->regs[0] = dev->regs[0] & 0xef; 4169141cc406Sopenharmony_ci 4170141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 4171141cc406Sopenharmony_ci /* now read button status read_reg(0x1a,2)=0x00 0x00 */ 4172141cc406Sopenharmony_ci sanei_rts88xx_read_regs (dev->devnum, 0x1a, dev->regs + 0x1a, 2); 4173141cc406Sopenharmony_ci /* we expect 0x00 0x00 here */ 4174141cc406Sopenharmony_ci DBG (DBG_io, "init_device: 0x%02x 0x%02x\n", dev->regs[0x1a], 4175141cc406Sopenharmony_ci dev->regs[0x1b]); 4176141cc406Sopenharmony_ci 4177141cc406Sopenharmony_ci dev->regs[0xcf] = 0x00; 4178141cc406Sopenharmony_ci dev->regs[0xd0] = 0xe0; 4179141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 4180141cc406Sopenharmony_ci sanei_rts88xx_read_regs (dev->devnum, 0x1a, dev->regs + 0x1a, 2); 4181141cc406Sopenharmony_ci /* we expect 0x08 0x00 here */ 4182141cc406Sopenharmony_ci DBG (DBG_io, "init_device: 0x%02x 0x%02x\n", dev->regs[0x1a], 4183141cc406Sopenharmony_ci dev->regs[0x1b]); 4184141cc406Sopenharmony_ci 4185141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x28); 4186141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); 4187141cc406Sopenharmony_ci sanei_rts88xx_cancel (dev->devnum); 4188141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LAMP_REG, &control); 4189141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 4190141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 4191141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &id); 4192141cc406Sopenharmony_ci if (id != 0x00 && id != 0x01) 4193141cc406Sopenharmony_ci { 4194141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: got unexpected id 0x%02x\n", id); 4195141cc406Sopenharmony_ci } 4196141cc406Sopenharmony_ci 4197141cc406Sopenharmony_ci 4198141cc406Sopenharmony_ci dev->regs[0x12] = 0xff; 4199141cc406Sopenharmony_ci dev->regs[0x14] = 0xf8; 4200141cc406Sopenharmony_ci dev->regs[0x15] = 0x28; 4201141cc406Sopenharmony_ci dev->regs[0x16] = 0x07; 4202141cc406Sopenharmony_ci dev->regs[0x18] = 0xff; 4203141cc406Sopenharmony_ci dev->regs[0x23] = 0xff; 4204141cc406Sopenharmony_ci dev->regs[0x24] = 0xff; 4205141cc406Sopenharmony_ci 4206141cc406Sopenharmony_ci dev->regs[0x72] = 0xe1; 4207141cc406Sopenharmony_ci dev->regs[0x73] = 0x14; 4208141cc406Sopenharmony_ci dev->regs[0x74] = 0x18; 4209141cc406Sopenharmony_ci dev->regs[0x75] = 0x15; 4210141cc406Sopenharmony_ci dev->regs[0xc0] = 0xff; 4211141cc406Sopenharmony_ci dev->regs[0xc1] = 0x0f; 4212141cc406Sopenharmony_ci dev->regs[0xc3] = 0xff; 4213141cc406Sopenharmony_ci dev->regs[0xc4] = 0xff; 4214141cc406Sopenharmony_ci dev->regs[0xc5] = 0xff; 4215141cc406Sopenharmony_ci dev->regs[0xc6] = 0xff; 4216141cc406Sopenharmony_ci dev->regs[0xc7] = 0xff; 4217141cc406Sopenharmony_ci dev->regs[0xc8] = 0xff; 4218141cc406Sopenharmony_ci dev->regs[0xca] = 0x0e; 4219141cc406Sopenharmony_ci dev->regs[0xcd] = 0xf0; 4220141cc406Sopenharmony_ci dev->regs[0xce] = 0xff; 4221141cc406Sopenharmony_ci dev->regs[0xcf] = 0xf5; 4222141cc406Sopenharmony_ci dev->regs[0xd0] = 0xf7; 4223141cc406Sopenharmony_ci dev->regs[0xd1] = 0xea; 4224141cc406Sopenharmony_ci dev->regs[0xd2] = 0x0b; 4225141cc406Sopenharmony_ci dev->regs[0xd3] = 0x03; 4226141cc406Sopenharmony_ci dev->regs[0xd4] = 0x05; 4227141cc406Sopenharmony_ci dev->regs[0xd7] = 0x30; 4228141cc406Sopenharmony_ci dev->regs[0xd8] = 0xf6; 4229141cc406Sopenharmony_ci dev->regs[0xd9] = 0x80; 4230141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 4231141cc406Sopenharmony_ci 4232141cc406Sopenharmony_ci /* now we are writing and reading back from memory, it is surely a memory test since the written data 4233141cc406Sopenharmony_ci * don't look useful at first glance 4234141cc406Sopenharmony_ci */ 4235141cc406Sopenharmony_ci reg = 0x06; 4236141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x93, ®); 4237141cc406Sopenharmony_ci for (i = 0; i < 2072; i++) 4238141cc406Sopenharmony_ci { 4239141cc406Sopenharmony_ci buffer[i] = i % 97; 4240141cc406Sopenharmony_ci } 4241141cc406Sopenharmony_ci sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer); 4242141cc406Sopenharmony_ci sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer); 4243141cc406Sopenharmony_ci /* check the data returned */ 4244141cc406Sopenharmony_ci for (i = 0; i < 2072; i++) 4245141cc406Sopenharmony_ci { 4246141cc406Sopenharmony_ci if (buffer[i] != id) 4247141cc406Sopenharmony_ci { 4248141cc406Sopenharmony_ci DBG (DBG_error, 4249141cc406Sopenharmony_ci "init_device: memory at %d is not 0x%02d (0x%02x)\n", i, id, 4250141cc406Sopenharmony_ci buffer[i]); 4251141cc406Sopenharmony_ci /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */ 4252141cc406Sopenharmony_ci } 4253141cc406Sopenharmony_ci } 4254141cc406Sopenharmony_ci DBG (DBG_info, "init_device: memory set #1 passed\n"); 4255141cc406Sopenharmony_ci 4256141cc406Sopenharmony_ci /* now test (or set?) #2 */ 4257141cc406Sopenharmony_ci reg = 0x02; 4258141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x93, ®); 4259141cc406Sopenharmony_ci for (i = 0; i < 2072; i++) 4260141cc406Sopenharmony_ci { 4261141cc406Sopenharmony_ci buffer[i] = i % 97; 4262141cc406Sopenharmony_ci } 4263141cc406Sopenharmony_ci sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer); 4264141cc406Sopenharmony_ci sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer); 4265141cc406Sopenharmony_ci /* check the data returned */ 4266141cc406Sopenharmony_ci for (i = 0; i < 970; i++) 4267141cc406Sopenharmony_ci { 4268141cc406Sopenharmony_ci if (buffer[i] != (i + 0x36) % 97) 4269141cc406Sopenharmony_ci { 4270141cc406Sopenharmony_ci DBG (DBG_error, 4271141cc406Sopenharmony_ci "init_device: memory at %d is not 0x%02x (0x%02x)\n", i, 4272141cc406Sopenharmony_ci (i + 0x36) % 97, buffer[i]); 4273141cc406Sopenharmony_ci /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */ 4274141cc406Sopenharmony_ci } 4275141cc406Sopenharmony_ci } 4276141cc406Sopenharmony_ci for (i = 993; i < 2072; i++) 4277141cc406Sopenharmony_ci { 4278141cc406Sopenharmony_ci if (buffer[i] != i % 97) 4279141cc406Sopenharmony_ci { 4280141cc406Sopenharmony_ci DBG (DBG_error, 4281141cc406Sopenharmony_ci "init_device: memory at %d is invalid 0x%02x, instead of 0x%02x\n", 4282141cc406Sopenharmony_ci i, buffer[i], i % 97); 4283141cc406Sopenharmony_ci /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */ 4284141cc406Sopenharmony_ci } 4285141cc406Sopenharmony_ci } 4286141cc406Sopenharmony_ci DBG (DBG_info, "init_device: memory set #2 passed\n"); 4287141cc406Sopenharmony_ci 4288141cc406Sopenharmony_ci 4289141cc406Sopenharmony_ci /* now test (or set?) #3 */ 4290141cc406Sopenharmony_ci reg = 0x01; 4291141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x93, ®); 4292141cc406Sopenharmony_ci for (i = 0; i < 2072; i++) 4293141cc406Sopenharmony_ci { 4294141cc406Sopenharmony_ci buffer[i] = i % 97; 4295141cc406Sopenharmony_ci } 4296141cc406Sopenharmony_ci sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer); 4297141cc406Sopenharmony_ci sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer); 4298141cc406Sopenharmony_ci /* check the data returned */ 4299141cc406Sopenharmony_ci for (i = 0; i < 2072; i++) 4300141cc406Sopenharmony_ci { 4301141cc406Sopenharmony_ci if (buffer[i] != i % 97) 4302141cc406Sopenharmony_ci { 4303141cc406Sopenharmony_ci DBG (DBG_error, 4304141cc406Sopenharmony_ci "init_device: memory at %d is invalid 0x%02x, instead of 0x%02x\n", 4305141cc406Sopenharmony_ci i, buffer[i], i % 97); 4306141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4307141cc406Sopenharmony_ci } 4308141cc406Sopenharmony_ci } 4309141cc406Sopenharmony_ci DBG (DBG_info, "init_device: memory set #3 passed\n"); 4310141cc406Sopenharmony_ci 4311141cc406Sopenharmony_ci /* we are writing page after page the same pattern, and reading at page 0 until we find we have 'wrapped' */ 4312141cc406Sopenharmony_ci /* this is surely some memory amount/number pages detection */ 4313141cc406Sopenharmony_ci dev->regs[0x91] = 0x00; /* page 0 ? */ 4314141cc406Sopenharmony_ci dev->regs[0x92] = 0x00; 4315141cc406Sopenharmony_ci dev->regs[0x93] = 0x01; 4316141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 4317141cc406Sopenharmony_ci 4318141cc406Sopenharmony_ci /* write pattern at page 0 */ 4319141cc406Sopenharmony_ci for (i = 0; i < 32; i += 2) 4320141cc406Sopenharmony_ci { 4321141cc406Sopenharmony_ci buffer[i] = i; 4322141cc406Sopenharmony_ci buffer[i + 1] = 0x00; 4323141cc406Sopenharmony_ci } 4324141cc406Sopenharmony_ci sanei_rts88xx_set_mem (dev->devnum, 0x00, 0x00, 32, buffer); 4325141cc406Sopenharmony_ci 4326141cc406Sopenharmony_ci page = 0; 4327141cc406Sopenharmony_ci do 4328141cc406Sopenharmony_ci { 4329141cc406Sopenharmony_ci /* next page */ 4330141cc406Sopenharmony_ci page++; 4331141cc406Sopenharmony_ci 4332141cc406Sopenharmony_ci /* fill buffer with pattern for page */ 4333141cc406Sopenharmony_ci for (i = 0; i < 32; i += 2) 4334141cc406Sopenharmony_ci { 4335141cc406Sopenharmony_ci buffer[i] = i; 4336141cc406Sopenharmony_ci buffer[i + 1] = page; 4337141cc406Sopenharmony_ci } 4338141cc406Sopenharmony_ci /* write it to memory */ 4339141cc406Sopenharmony_ci sanei_rts88xx_set_mem (dev->devnum, 0x00, page * 16, 32, buffer); 4340141cc406Sopenharmony_ci /* read memory from page 0 */ 4341141cc406Sopenharmony_ci sanei_rts88xx_get_mem (dev->devnum, 0x00, 0x00, 32, buffer); 4342141cc406Sopenharmony_ci for (i = 0; i < 32; i += 2) 4343141cc406Sopenharmony_ci { 4344141cc406Sopenharmony_ci if (buffer[i] != i) 4345141cc406Sopenharmony_ci { 4346141cc406Sopenharmony_ci DBG (DBG_error, 4347141cc406Sopenharmony_ci "init_device: memory at %d is invalid: 0x%02x instead of 0x%02x\n", 4348141cc406Sopenharmony_ci i, buffer[i], i); 4349141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4350141cc406Sopenharmony_ci } 4351141cc406Sopenharmony_ci if (buffer[i + 1] != page && buffer[i + 1] != 0) 4352141cc406Sopenharmony_ci { 4353141cc406Sopenharmony_ci DBG (DBG_error, 4354141cc406Sopenharmony_ci "init_device: page %d, memory at %d is invalid: 0x%02x instead of 0x%02x\n", 4355141cc406Sopenharmony_ci page, i + 1, buffer[i + 1], 0); 4356141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4357141cc406Sopenharmony_ci } 4358141cc406Sopenharmony_ci } 4359141cc406Sopenharmony_ci } 4360141cc406Sopenharmony_ci while (buffer[1] == 0); 4361141cc406Sopenharmony_ci DBG (DBG_info, "init_device: %d pages detected\n", page - 1); 4362141cc406Sopenharmony_ci 4363141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4364141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &control); 4365141cc406Sopenharmony_ci if (!(control & 0x02)) 4366141cc406Sopenharmony_ci { 4367141cc406Sopenharmony_ci if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD) 4368141cc406Sopenharmony_ci { 4369141cc406Sopenharmony_ci DBG (DBG_error, "init_device: failed to park head!\n"); 4370141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 4371141cc406Sopenharmony_ci } 4372141cc406Sopenharmony_ci } 4373141cc406Sopenharmony_ci reg = 0x80; 4374141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 4375141cc406Sopenharmony_ci reg = 0xad; 4376141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 4377141cc406Sopenharmony_ci sanei_rts88xx_read_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); 4378141cc406Sopenharmony_ci /* we expect 0xF8 0x28 here */ 4379141cc406Sopenharmony_ci dev->regs[0x14] = dev->regs[0x14] & 0x7F; 4380141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); 4381141cc406Sopenharmony_ci 4382141cc406Sopenharmony_ci /* reads scanner status */ 4383141cc406Sopenharmony_ci sanei_rts88xx_get_status (dev->devnum, dev->regs); 4384141cc406Sopenharmony_ci DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10], 4385141cc406Sopenharmony_ci dev->regs[0x11]); 4386141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); 4387141cc406Sopenharmony_ci DBG (DBG_io, "init_device: link=0x%02x\n", control); 4388141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4389141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 4390141cc406Sopenharmony_ci reg = 0x8d; 4391141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 4392141cc406Sopenharmony_ci reg = 0xad; 4393141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 4394141cc406Sopenharmony_ci 4395141cc406Sopenharmony_ci /* here, we are in iddle state */ 4396141cc406Sopenharmony_ci 4397141cc406Sopenharmony_ci /* check link status (scanner still plugged) */ 4398141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); 4399141cc406Sopenharmony_ci DBG (DBG_io, "init_device: link=0x%02x\n", control); 4400141cc406Sopenharmony_ci 4401141cc406Sopenharmony_ci /* this block appears twice */ 4402141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4403141cc406Sopenharmony_ci if (control != 0) 4404141cc406Sopenharmony_ci { 4405141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", 4406141cc406Sopenharmony_ci control); 4407141cc406Sopenharmony_ci } 4408141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 4409141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); 4410141cc406Sopenharmony_ci reg |= 0x80; 4411141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); 4412141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x10, ®); 4413141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x14, ®); 4414141cc406Sopenharmony_ci reg = 0x78; 4415141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); 4416141cc406Sopenharmony_ci reg = 0x38; 4417141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x14, ®); 4418141cc406Sopenharmony_ci reg = 0x78; 4419141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); 4420141cc406Sopenharmony_ci reg = 0x01; 4421141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, ®); 4422141cc406Sopenharmony_ci 4423141cc406Sopenharmony_ci /* now we init nvram */ 4424141cc406Sopenharmony_ci /* this is highly dangerous and thus deactivated 4425141cc406Sopenharmony_ci * in sanei_rts88xx_setup_nvram (HAZARDOUS_EXPERIMENT #define) */ 4426141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd1); 4427141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd2); 4428141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd3); 4429141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); 4430141cc406Sopenharmony_ci 4431141cc406Sopenharmony_ci /* second occurrence of this block */ 4432141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4433141cc406Sopenharmony_ci if (control != 0) 4434141cc406Sopenharmony_ci { 4435141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", 4436141cc406Sopenharmony_ci control); 4437141cc406Sopenharmony_ci } 4438141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 4439141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); 4440141cc406Sopenharmony_ci reg |= 0x80; 4441141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); 4442141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x10, ®); 4443141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0x14, ®); 4444141cc406Sopenharmony_ci reg = 0x78; 4445141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); 4446141cc406Sopenharmony_ci reg = 0x38; 4447141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x14, ®); 4448141cc406Sopenharmony_ci reg = 0x78; 4449141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); 4450141cc406Sopenharmony_ci reg = 0x01; 4451141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, ®); 4452141cc406Sopenharmony_ci 4453141cc406Sopenharmony_ci /* nvram again */ 4454141cc406Sopenharmony_ci /* this is highly dangerous and commented out in rts88xx_lib */ 4455141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd4); 4456141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd5); 4457141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd6); 4458141cc406Sopenharmony_ci sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd7); 4459141cc406Sopenharmony_ci 4460141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); 4461141cc406Sopenharmony_ci 4462141cc406Sopenharmony_ci /* then we do a simple scan to detect a black zone to locate scan area */ 4463141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4464141cc406Sopenharmony_ci if (control != 0) 4465141cc406Sopenharmony_ci { 4466141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", 4467141cc406Sopenharmony_ci control); 4468141cc406Sopenharmony_ci } 4469141cc406Sopenharmony_ci sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); 4470141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4471141cc406Sopenharmony_ci if (control != 0) 4472141cc406Sopenharmony_ci { 4473141cc406Sopenharmony_ci DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", 4474141cc406Sopenharmony_ci control); 4475141cc406Sopenharmony_ci } 4476141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x01); 4477141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x01); 4478141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 4479141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 4480141cc406Sopenharmony_ci dev->regs[0x12] = 0xff; 4481141cc406Sopenharmony_ci dev->regs[0x13] = 0x20; 4482141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2); 4483141cc406Sopenharmony_ci dev->regs[0x14] = 0xf8; 4484141cc406Sopenharmony_ci dev->regs[0x15] = 0x28; 4485141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); 4486141cc406Sopenharmony_ci reg = 0; 4487141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 4488141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, 0x00); 4489141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); 4490141cc406Sopenharmony_ci reg = 0x80; 4491141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 4492141cc406Sopenharmony_ci 4493141cc406Sopenharmony_ci dev->regs[0x8b] = 0xff; 4494141cc406Sopenharmony_ci dev->regs[0x8c] = 0x3f; 4495141cc406Sopenharmony_ci dev->regs[LAMP_REG] = 0xad; 4496141cc406Sopenharmony_ci rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 4497141cc406Sopenharmony_ci 4498141cc406Sopenharmony_ci set_lamp_brightness (dev, 0); 4499141cc406Sopenharmony_ci dev->initialized = SANE_TRUE; 4500141cc406Sopenharmony_ci DBG (DBG_proc, "init_device: exit\n"); 4501141cc406Sopenharmony_ci return status; 4502141cc406Sopenharmony_ci} 4503141cc406Sopenharmony_ci#endif /* FAST_INIT */ 4504141cc406Sopenharmony_ci 4505141cc406Sopenharmony_ci#ifdef FAST_INIT 4506141cc406Sopenharmony_ci/* 4507141cc406Sopenharmony_ci * This function detects the scanner 4508141cc406Sopenharmony_ci */ 4509141cc406Sopenharmony_cistatic SANE_Status 4510141cc406Sopenharmony_cidetect_device (struct Rts8891_Device *dev) 4511141cc406Sopenharmony_ci{ 4512141cc406Sopenharmony_ci/* 4513141cc406Sopenharmony_ci--- 5 74945 bulk_out len 4 wrote 0x80 0xb0 0x00 0x01 4514141cc406Sopenharmony_ci--- 6 74946 bulk_in len 1 read 0x80 4515141cc406Sopenharmony_ci--- 7 74947 bulk_out len 4 wrote 0x80 0xb3 0x00 0x01 4516141cc406Sopenharmony_ci--- 8 74948 bulk_in len 1 read 0x04 4517141cc406Sopenharmony_ci--- 9 74949 bulk_out len 4 wrote 0x80 0xb1 0x00 0x01 4518141cc406Sopenharmony_ci--- 10 74950 bulk_in len 1 read 0x00 4519141cc406Sopenharmony_ci--- 11 74951 bulk_out len 5 wrote 0x88 0xb3 0x00 0x01 0x00 4520141cc406Sopenharmony_ci--- 12 74952 bulk_out len 5 wrote 0x88 0xb3 0x00 0x01 0x00 4521141cc406Sopenharmony_ci--- 13 74953 bulk_out len 4 wrote 0x80 0x00 0x00 0xf4 4522141cc406Sopenharmony_ci--- 14 74954 bulk_in len 192 read 0xf5 0x41 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x70 0x00 0x00 0x00 0x00 0x60 0x1b 0xff 0x3e 0x00 0x00 0xff 0x3e 0x00 0x00 0x00 0x00 0x00 0x22 0x00 0x00 0x00 0x00 0x00 0xff 0x00 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x42 0x00 0x00 0x10 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x24 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x10 0x00 0x80 0x00 0x10 0x00 0x01 0x00 0x00 0x10 0x00 0x00 0x20 0x20 0x00 0x00 0x00 0x00 0x20 0x01 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x41 0x00 0x10 0x21 0x20 0x00 0x20 0x81 0x20 0x01 0x01 0x00 0x22 0x00 0x40 0x05 0x00 0x00 0x01 0x1e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xcc 0x27 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 4523141cc406Sopenharmony_ci--- 15 74955 bulk_in len 52 read 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x06 0x1b 0x10 0x7a 0x00 0x15 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 4524141cc406Sopenharmony_ci*/ 4525141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 4526141cc406Sopenharmony_ci SANE_Byte control; 4527141cc406Sopenharmony_ci char message[256 * 5]; 4528141cc406Sopenharmony_ci int i; 4529141cc406Sopenharmony_ci 4530141cc406Sopenharmony_ci DBG (DBG_proc, "detect_device: start\n"); 4531141cc406Sopenharmony_ci 4532141cc406Sopenharmony_ci /* read "b0" register */ 4533141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control); 4534141cc406Sopenharmony_ci DBG (DBG_io, "detect_device: reg[b0]=0x%02x\n", control); 4535141cc406Sopenharmony_ci 4536141cc406Sopenharmony_ci /* we expect to get 0x80 */ 4537141cc406Sopenharmony_ci if (control != 0x80) 4538141cc406Sopenharmony_ci { 4539141cc406Sopenharmony_ci DBG (DBG_warn, "detect_device: expected reg[b0]=0x80, got 0x%02x\n", 4540141cc406Sopenharmony_ci control); 4541141cc406Sopenharmony_ci /* TODO : fail here ? */ 4542141cc406Sopenharmony_ci } 4543141cc406Sopenharmony_ci 4544141cc406Sopenharmony_ci /* read control register, if busy, something will have to be done ... */ 4545141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 4546141cc406Sopenharmony_ci 4547141cc406Sopenharmony_ci /* when just plugged, we expect to get 0x04 */ 4548141cc406Sopenharmony_ci if (control != 0x04) 4549141cc406Sopenharmony_ci { 4550141cc406Sopenharmony_ci DBG (DBG_warn, "detect_device: expected control=0x04, got 0x%02x\n", 4551141cc406Sopenharmony_ci control); 4552141cc406Sopenharmony_ci /* TODO ok if re-run without plugging */ 4553141cc406Sopenharmony_ci } 4554141cc406Sopenharmony_ci 4555141cc406Sopenharmony_ci /* read "LINK" register */ 4556141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); 4557141cc406Sopenharmony_ci DBG (DBG_io, "detect_device: LINK_REG=0x%02x\n", control); 4558141cc406Sopenharmony_ci 4559141cc406Sopenharmony_ci /* we expect to get 0x00 */ 4560141cc406Sopenharmony_ci if (control != 0x00) 4561141cc406Sopenharmony_ci { 4562141cc406Sopenharmony_ci DBG (DBG_warn, "detect_device: expected LINK_REG=0x00, got 0x%02x\n", 4563141cc406Sopenharmony_ci control); 4564141cc406Sopenharmony_ci } 4565141cc406Sopenharmony_ci 4566141cc406Sopenharmony_ci /* write 0x00 twice to control: cancel/stop ? */ 4567141cc406Sopenharmony_ci control = 0x00; 4568141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, control); 4569141cc406Sopenharmony_ci sanei_rts88xx_write_control (dev->devnum, control); 4570141cc406Sopenharmony_ci 4571141cc406Sopenharmony_ci /* read initial register set */ 4572141cc406Sopenharmony_ci sanei_rts88xx_read_regs (dev->devnum, 0, dev->regs, dev->reg_count); 4573141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 4574141cc406Sopenharmony_ci { 4575141cc406Sopenharmony_ci sprintf (message, "init_device: initial register settings: "); 4576141cc406Sopenharmony_ci for (i = 0; i < dev->reg_count; i++) 4577141cc406Sopenharmony_ci sprintf (message + strlen (message), "0x%02x ", dev->regs[i]); 4578141cc406Sopenharmony_ci sprintf (message + strlen (message), "\n"); 4579141cc406Sopenharmony_ci DBG (DBG_io2, message); 4580141cc406Sopenharmony_ci } 4581141cc406Sopenharmony_ci 4582141cc406Sopenharmony_ci /* initial sensor guess */ 4583141cc406Sopenharmony_ci val = dev->regs[0x44] + 256 * dev->regs[0x45]; 4584141cc406Sopenharmony_ci DBG (DBG_io, "detect_device: R44/45=0x%04x\n", val); 4585141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400 && val == 0x00) 4586141cc406Sopenharmony_ci { 4587141cc406Sopenharmony_ci dev->sensor = SENSOR_TYPE_4400_BARE; 4588141cc406Sopenharmony_ci DBG (DBG_info, "detect_device: changing to SENSOR_TYPE_4400_BARE\n"); 4589141cc406Sopenharmony_ci } 4590141cc406Sopenharmony_ci 4591141cc406Sopenharmony_ci DBG (DBG_io, "detect_device: status=0x%02x 0x%02x\n", dev->regs[0x10], 4592141cc406Sopenharmony_ci dev->regs[0x11]); 4593141cc406Sopenharmony_ci DBG (DBG_io, "detect_device: lamp status=0x%02x\n", dev->regs[0x8e]); 4594141cc406Sopenharmony_ci 4595141cc406Sopenharmony_ci dev->initialized = SANE_FALSE; 4596141cc406Sopenharmony_ci DBG (DBG_proc, "detect_device: exit\n"); 4597141cc406Sopenharmony_ci return status; 4598141cc406Sopenharmony_ci} 4599141cc406Sopenharmony_ci#endif 4600141cc406Sopenharmony_ci 4601141cc406Sopenharmony_ci/** 4602141cc406Sopenharmony_ci * Do dark calibration. We scan a well defined area until average pixel value 4603141cc406Sopenharmony_ci * of the black area is about 0x03 for each color channel. This calibration is 4604141cc406Sopenharmony_ci * currently done at 75 dpi regardless of the final scan dpi. 4605141cc406Sopenharmony_ci */ 4606141cc406Sopenharmony_cistatic SANE_Status 4607141cc406Sopenharmony_cidark_calibration (struct Rts8891_Device *dev, int mode, int light) 4608141cc406Sopenharmony_ci{ 4609141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 4610141cc406Sopenharmony_ci/* red, green and blue offset, within a 't'op and 'b'ottom value */ 4611141cc406Sopenharmony_ci int ro = 250, tro = 250, bro = 0; 4612141cc406Sopenharmony_ci int bo = 250, tbo = 250, bbo = 0; 4613141cc406Sopenharmony_ci int go = 250, tgo = 250, bgo = 0; 4614141cc406Sopenharmony_ci unsigned char image[CALIBRATION_SIZE]; 4615141cc406Sopenharmony_ci float global, ra, ga, ba; 4616141cc406Sopenharmony_ci int num = 0; 4617141cc406Sopenharmony_ci char name[32]; 4618141cc406Sopenharmony_ci 4619141cc406Sopenharmony_ci DBG (DBG_proc, "dark_calibration: start\n"); 4620141cc406Sopenharmony_ci 4621141cc406Sopenharmony_ci /* set up sensor specific bottom values */ 4622141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 4623141cc406Sopenharmony_ci { 4624141cc406Sopenharmony_ci bro = 128; 4625141cc406Sopenharmony_ci bgo = 128; 4626141cc406Sopenharmony_ci bbo = 128; 4627141cc406Sopenharmony_ci } 4628141cc406Sopenharmony_ci 4629141cc406Sopenharmony_ci /* set up starting values */ 4630141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, 0, 0, 0); 4631141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH); 4632141cc406Sopenharmony_ci 4633141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); 4634141cc406Sopenharmony_ci 4635141cc406Sopenharmony_ci dev->regs[0x00] = 0xe5; /* scan */ 4636141cc406Sopenharmony_ci dev->regs[0x32] = 0x00; 4637141cc406Sopenharmony_ci dev->regs[0x33] = 0x03; 4638141cc406Sopenharmony_ci dev->regs[0x35] = 0x45; 4639141cc406Sopenharmony_ci dev->regs[0x36] = 0x22; 4640141cc406Sopenharmony_ci dev->regs[0x3a] = 0x43; 4641141cc406Sopenharmony_ci 4642141cc406Sopenharmony_ci dev->regs[0x8d] = 0x00; 4643141cc406Sopenharmony_ci dev->regs[0x8e] = 0x60; 4644141cc406Sopenharmony_ci 4645141cc406Sopenharmony_ci dev->regs[0xb2] = 0x02; 4646141cc406Sopenharmony_ci 4647141cc406Sopenharmony_ci dev->regs[0xc0] = 0x06; 4648141cc406Sopenharmony_ci dev->regs[0xc1] = 0xe6; 4649141cc406Sopenharmony_ci dev->regs[0xc2] = 0x67; 4650141cc406Sopenharmony_ci dev->regs[0xc9] = 0x07; 4651141cc406Sopenharmony_ci dev->regs[0xca] = 0x00; 4652141cc406Sopenharmony_ci dev->regs[0xcb] = 0xfe; 4653141cc406Sopenharmony_ci dev->regs[0xcc] = 0xf9; 4654141cc406Sopenharmony_ci dev->regs[0xcd] = 0x19; 4655141cc406Sopenharmony_ci dev->regs[0xce] = 0x98; 4656141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe8; 4657141cc406Sopenharmony_ci dev->regs[0xd0] = 0xea; 4658141cc406Sopenharmony_ci dev->regs[0xd1] = 0xf3; 4659141cc406Sopenharmony_ci dev->regs[0xd2] = 0x14; 4660141cc406Sopenharmony_ci dev->regs[0xd3] = 0x02; 4661141cc406Sopenharmony_ci dev->regs[0xd4] = 0x04; 4662141cc406Sopenharmony_ci dev->regs[0xd6] = 0x0f; 4663141cc406Sopenharmony_ci dev->regs[0xd8] = 0x52; 4664141cc406Sopenharmony_ci dev->regs[0xe2] = 0x1f; 4665141cc406Sopenharmony_ci 4666141cc406Sopenharmony_ci /*dev->regs[0xe5] = 0x28; 28=40 4667141cc406Sopenharmony_ci dev->regs[0xe6] = 0x00; */ 4668141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); 4669141cc406Sopenharmony_ci 4670141cc406Sopenharmony_ci dev->regs[0xe7] = 0x75; 4671141cc406Sopenharmony_ci dev->regs[0xe8] = 0x01; 4672141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0b; 4673141cc406Sopenharmony_ci dev->regs[0xea] = 0x54; 4674141cc406Sopenharmony_ci dev->regs[0xeb] = 0x01; 4675141cc406Sopenharmony_ci dev->regs[0xec] = 0x04; 4676141cc406Sopenharmony_ci dev->regs[0xed] = 0xb8; 4677141cc406Sopenharmony_ci dev->regs[0xef] = 0x03; 4678141cc406Sopenharmony_ci dev->regs[0xf0] = 0x70; 4679141cc406Sopenharmony_ci dev->regs[0xf2] = 0x01; 4680141cc406Sopenharmony_ci 4681141cc406Sopenharmony_ci /* handling of different sensors */ 4682141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 4683141cc406Sopenharmony_ci { 4684141cc406Sopenharmony_ci dev->regs[0xc0] = 0x67; 4685141cc406Sopenharmony_ci dev->regs[0xc1] = 0x06; 4686141cc406Sopenharmony_ci dev->regs[0xc2] = 0xe6; 4687141cc406Sopenharmony_ci dev->regs[0xc3] = 0x98; 4688141cc406Sopenharmony_ci dev->regs[0xc4] = 0xf9; 4689141cc406Sopenharmony_ci dev->regs[0xc5] = 0x19; 4690141cc406Sopenharmony_ci dev->regs[0xc6] = 0x67; 4691141cc406Sopenharmony_ci dev->regs[0xc7] = 0x06; 4692141cc406Sopenharmony_ci dev->regs[0xc8] = 0xe6; 4693141cc406Sopenharmony_ci dev->regs[0xc9] = 0x01; 4694141cc406Sopenharmony_ci dev->regs[0xca] = 0xf8; 4695141cc406Sopenharmony_ci dev->regs[0xcb] = 0xff; 4696141cc406Sopenharmony_ci dev->regs[0xcc] = 0x98; 4697141cc406Sopenharmony_ci dev->regs[0xcd] = 0xf9; 4698141cc406Sopenharmony_ci dev->regs[0xce] = 0x19; 4699141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe0; 4700141cc406Sopenharmony_ci dev->regs[0xd0] = 0xe2; 4701141cc406Sopenharmony_ci dev->regs[0xd1] = 0xeb; 4702141cc406Sopenharmony_ci dev->regs[0xd2] = 0x0c; 4703141cc406Sopenharmony_ci dev->regs[0xd7] = 0x10; 4704141cc406Sopenharmony_ci dev->regs[0xda] = 0xa7; 4705141cc406Sopenharmony_ci } 4706141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 4707141cc406Sopenharmony_ci { 4708141cc406Sopenharmony_ci dev->regs[0x13] = 0x39; /* 0x20 */ 4709141cc406Sopenharmony_ci dev->regs[0x14] = 0xf0; /* 0xf8 */ 4710141cc406Sopenharmony_ci dev->regs[0x15] = 0x29; /* 0x28 */ 4711141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; /* 0x07 */ 4712141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; /* 0x00 */ 4713141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; /* 0xff */ 4714141cc406Sopenharmony_ci dev->regs[0x35] = 0x48; /* 0x45 */ 4715141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; /* 0x02 */ 4716141cc406Sopenharmony_ci dev->regs[0xe2] = 0x0f; /* 0x1f */ 4717141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x52; 0x28 */ 4718141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ 4719141cc406Sopenharmony_ci dev->regs[0xe7] = 0x0e; /* 0x75 */ 4720141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0a; /* 0x0b */ 4721141cc406Sopenharmony_ci dev->regs[0xea] = 0xc2; /* 0x54 */ 4722141cc406Sopenharmony_ci dev->regs[0xed] = 0xf6; /* 0xb8 */ 4723141cc406Sopenharmony_ci dev->regs[0xef] = 0x02; /* 0x03 */ 4724141cc406Sopenharmony_ci dev->regs[0xf0] = 0xa8; /* 0x70 */ 4725141cc406Sopenharmony_ci } 4726141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 4727141cc406Sopenharmony_ci { 4728141cc406Sopenharmony_ci dev->regs[0x13] = 0x39; /* 0x20 */ 4729141cc406Sopenharmony_ci dev->regs[0x14] = 0xf0; /* 0xf8 */ 4730141cc406Sopenharmony_ci dev->regs[0x15] = 0x29; /* 0x28 */ 4731141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; /* 0x07 */ 4732141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; /* 0x00 */ 4733141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; /* 0xff */ 4734141cc406Sopenharmony_ci dev->regs[0x35] = 0x48; /* 0x45 */ 4735141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; /* 0x02 */ 4736141cc406Sopenharmony_ci dev->regs[0xda] = 0xa7; /* 0xa0 */ 4737141cc406Sopenharmony_ci dev->regs[0xe2] = 0x0f; /* 0x1f */ 4738141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); 4739141cc406Sopenharmony_ci dev->regs[0xe7] = 0x0e; /* 0x75 */ 4740141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0a; /* 0x0b */ 4741141cc406Sopenharmony_ci dev->regs[0xea] = 0xc2; /* 0x54 */ 4742141cc406Sopenharmony_ci dev->regs[0xed] = 0xf6; /* 0xb8 */ 4743141cc406Sopenharmony_ci dev->regs[0xef] = 0x02; /* 0x03 */ 4744141cc406Sopenharmony_ci dev->regs[0xf0] = 0xa8; /* 0x70 */ 4745141cc406Sopenharmony_ci } 4746141cc406Sopenharmony_ci 4747141cc406Sopenharmony_ci /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode 4748141cc406Sopenharmony_ci * until each black average reaches the desired value */ 4749141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); 4750141cc406Sopenharmony_ci do 4751141cc406Sopenharmony_ci { 4752141cc406Sopenharmony_ci /* set scan with the values to try */ 4753141cc406Sopenharmony_ci sanei_rts88xx_set_offset (dev->regs, ro, go, bo); 4754141cc406Sopenharmony_ci DBG (DBG_info, "dark_calibration: trying offsets=(%d,%d,%d)\n", ro, go, 4755141cc406Sopenharmony_ci bo); 4756141cc406Sopenharmony_ci 4757141cc406Sopenharmony_ci /* do scan */ 4758141cc406Sopenharmony_ci status = 4759141cc406Sopenharmony_ci rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, 4760141cc406Sopenharmony_ci CALIBRATION_SIZE, image); 4761141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 4762141cc406Sopenharmony_ci { 4763141cc406Sopenharmony_ci DBG (DBG_error, "dark_calibration: failed to scan\n"); 4764141cc406Sopenharmony_ci return status; 4765141cc406Sopenharmony_ci } 4766141cc406Sopenharmony_ci 4767141cc406Sopenharmony_ci /* save scanned picture for data debugging */ 4768141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 4769141cc406Sopenharmony_ci { 4770141cc406Sopenharmony_ci sprintf (name, "dark%03d.pnm", num); 4771141cc406Sopenharmony_ci write_rgb_data (name, image, CALIBRATION_WIDTH, 1); 4772141cc406Sopenharmony_ci num++; 4773141cc406Sopenharmony_ci } 4774141cc406Sopenharmony_ci 4775141cc406Sopenharmony_ci /* we now compute the average of red pixels from the first 15 pixels */ 4776141cc406Sopenharmony_ci global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba); 4777141cc406Sopenharmony_ci DBG (DBG_info, 4778141cc406Sopenharmony_ci "dark_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", 4779141cc406Sopenharmony_ci global, ra, ga, ba); 4780141cc406Sopenharmony_ci 4781141cc406Sopenharmony_ci /* dichotomie ... */ 4782141cc406Sopenharmony_ci if (fabs (ra - DARK_TARGET) < DARK_MARGIN) 4783141cc406Sopenharmony_ci { 4784141cc406Sopenharmony_ci /* offset is OK */ 4785141cc406Sopenharmony_ci tro = ro; 4786141cc406Sopenharmony_ci bro = ro; 4787141cc406Sopenharmony_ci } 4788141cc406Sopenharmony_ci else 4789141cc406Sopenharmony_ci { /* NOK */ 4790141cc406Sopenharmony_ci if (ra > DARK_TARGET) 4791141cc406Sopenharmony_ci { 4792141cc406Sopenharmony_ci tro = ro; 4793141cc406Sopenharmony_ci ro = (tro + bro) / 2; 4794141cc406Sopenharmony_ci } 4795141cc406Sopenharmony_ci if (ra < DARK_TARGET) 4796141cc406Sopenharmony_ci { 4797141cc406Sopenharmony_ci bro = ro; 4798141cc406Sopenharmony_ci ro = (tro + bro + 1) / 2; 4799141cc406Sopenharmony_ci } 4800141cc406Sopenharmony_ci 4801141cc406Sopenharmony_ci } 4802141cc406Sopenharmony_ci 4803141cc406Sopenharmony_ci /* same for blue channel */ 4804141cc406Sopenharmony_ci if (fabs (ba - DARK_TARGET) < DARK_MARGIN) 4805141cc406Sopenharmony_ci { 4806141cc406Sopenharmony_ci bbo = bo; 4807141cc406Sopenharmony_ci tbo = bo; 4808141cc406Sopenharmony_ci } 4809141cc406Sopenharmony_ci else 4810141cc406Sopenharmony_ci { /* NOK */ 4811141cc406Sopenharmony_ci if (ba > DARK_TARGET) 4812141cc406Sopenharmony_ci { 4813141cc406Sopenharmony_ci tbo = bo; 4814141cc406Sopenharmony_ci bo = (tbo + bbo) / 2; 4815141cc406Sopenharmony_ci } 4816141cc406Sopenharmony_ci if (ba < DARK_TARGET) 4817141cc406Sopenharmony_ci { 4818141cc406Sopenharmony_ci bbo = bo; 4819141cc406Sopenharmony_ci bo = (tbo + bbo + 1) / 2; 4820141cc406Sopenharmony_ci } 4821141cc406Sopenharmony_ci 4822141cc406Sopenharmony_ci } 4823141cc406Sopenharmony_ci 4824141cc406Sopenharmony_ci /* and for green channel */ 4825141cc406Sopenharmony_ci if (fabs (ga - DARK_TARGET) < DARK_MARGIN) 4826141cc406Sopenharmony_ci { 4827141cc406Sopenharmony_ci tgo = go; 4828141cc406Sopenharmony_ci bgo = go; 4829141cc406Sopenharmony_ci } 4830141cc406Sopenharmony_ci else 4831141cc406Sopenharmony_ci { /* NOK */ 4832141cc406Sopenharmony_ci if (ga > DARK_TARGET) 4833141cc406Sopenharmony_ci { 4834141cc406Sopenharmony_ci tgo = go; 4835141cc406Sopenharmony_ci go = (tgo + bgo) / 2; 4836141cc406Sopenharmony_ci } 4837141cc406Sopenharmony_ci if (ga < DARK_TARGET) 4838141cc406Sopenharmony_ci { 4839141cc406Sopenharmony_ci bgo = go; 4840141cc406Sopenharmony_ci go = (tgo + bgo + 1) / 2; 4841141cc406Sopenharmony_ci } 4842141cc406Sopenharmony_ci } 4843141cc406Sopenharmony_ci } 4844141cc406Sopenharmony_ci while ((tro != bro) || (tgo != bgo) || (tbo != bbo)); 4845141cc406Sopenharmony_ci 4846141cc406Sopenharmony_ci /* store detected values in device struct */ 4847141cc406Sopenharmony_ci dev->red_offset = bro; 4848141cc406Sopenharmony_ci dev->green_offset = bgo; 4849141cc406Sopenharmony_ci dev->blue_offset = bbo; 4850141cc406Sopenharmony_ci 4851141cc406Sopenharmony_ci DBG (DBG_info, "dark_calibration: final offsets=(%d,%d,%d)\n", bro, bgo, 4852141cc406Sopenharmony_ci bbo); 4853141cc406Sopenharmony_ci DBG (DBG_proc, "dark_calibration: exit\n"); 4854141cc406Sopenharmony_ci return status; 4855141cc406Sopenharmony_ci} 4856141cc406Sopenharmony_ci 4857141cc406Sopenharmony_ci/* 4858141cc406Sopenharmony_ci * do gain calibration. We do scans until averaged values of the area match 4859141cc406Sopenharmony_ci * the target code. We're doing a dichotomy again. 4860141cc406Sopenharmony_ci */ 4861141cc406Sopenharmony_cistatic SANE_Status 4862141cc406Sopenharmony_cigain_calibration (struct Rts8891_Device *dev, int mode, int light) 4863141cc406Sopenharmony_ci{ 4864141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 4865141cc406Sopenharmony_ci float global, ra, ga, ba; 4866141cc406Sopenharmony_ci /* previous values */ 4867141cc406Sopenharmony_ci int xrg, xbg, xgg; 4868141cc406Sopenharmony_ci/* current gains */ 4869141cc406Sopenharmony_ci int rg, bg, gg; 4870141cc406Sopenharmony_ci/* intervals for dichotomy */ 4871141cc406Sopenharmony_ci int trg, tbg, tgg, bgg, brg, bbg; 4872141cc406Sopenharmony_ci int num = 0; 4873141cc406Sopenharmony_ci char name[32]; 4874141cc406Sopenharmony_ci int width = CALIBRATION_WIDTH; 4875141cc406Sopenharmony_ci int length = CALIBRATION_SIZE; 4876141cc406Sopenharmony_ci unsigned char image[CALIBRATION_SIZE]; 4877141cc406Sopenharmony_ci int pass = 0; 4878141cc406Sopenharmony_ci int timing=0; 4879141cc406Sopenharmony_ci 4880141cc406Sopenharmony_ci int xstart = (dev->left_offset * 75) / dev->model->max_xdpi; 4881141cc406Sopenharmony_ci 4882141cc406Sopenharmony_ci DBG (DBG_proc, "gain_calibration: start\n"); 4883141cc406Sopenharmony_ci 4884141cc406Sopenharmony_ci /* set up starting values */ 4885141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (dev->regs, 1, 2, xstart, xstart + width); 4886141cc406Sopenharmony_ci sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset, 4887141cc406Sopenharmony_ci dev->blue_offset); 4888141cc406Sopenharmony_ci 4889141cc406Sopenharmony_ci /* same register set than dark calibration */ 4890141cc406Sopenharmony_ci dev->regs[0x32] = 0x00; 4891141cc406Sopenharmony_ci dev->regs[0x33] = 0x03; 4892141cc406Sopenharmony_ci dev->regs[0x35] = 0x45; 4893141cc406Sopenharmony_ci dev->regs[0x36] = 0x22; 4894141cc406Sopenharmony_ci dev->regs[0x3a] = 0x43; 4895141cc406Sopenharmony_ci 4896141cc406Sopenharmony_ci dev->regs[0x8d] = 0x00; 4897141cc406Sopenharmony_ci dev->regs[0x8e] = 0x60; 4898141cc406Sopenharmony_ci 4899141cc406Sopenharmony_ci dev->regs[0xb2] = 0x02; 4900141cc406Sopenharmony_ci 4901141cc406Sopenharmony_ci dev->regs[0xc0] = 0x06; 4902141cc406Sopenharmony_ci dev->regs[0xc1] = 0xe6; 4903141cc406Sopenharmony_ci dev->regs[0xc2] = 0x67; 4904141cc406Sopenharmony_ci dev->regs[0xc9] = 0x07; 4905141cc406Sopenharmony_ci dev->regs[0xca] = 0x00; 4906141cc406Sopenharmony_ci dev->regs[0xcb] = 0xfe; 4907141cc406Sopenharmony_ci dev->regs[0xcc] = 0xf9; 4908141cc406Sopenharmony_ci dev->regs[0xcd] = 0x19; 4909141cc406Sopenharmony_ci dev->regs[0xce] = 0x98; 4910141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe8; 4911141cc406Sopenharmony_ci dev->regs[0xd0] = 0xea; 4912141cc406Sopenharmony_ci dev->regs[0xd1] = 0xf3; 4913141cc406Sopenharmony_ci dev->regs[0xd2] = 0x14; 4914141cc406Sopenharmony_ci dev->regs[0xd3] = 0x02; 4915141cc406Sopenharmony_ci dev->regs[0xd4] = 0x04; 4916141cc406Sopenharmony_ci dev->regs[0xd6] = 0x0f; 4917141cc406Sopenharmony_ci dev->regs[0xd8] = 0x52; 4918141cc406Sopenharmony_ci dev->regs[0xe2] = 0x1f; 4919141cc406Sopenharmony_ci 4920141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x28; 4921141cc406Sopenharmony_ci dev->regs[0xe6] = 0x00; 28=40 */ 4922141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); 4923141cc406Sopenharmony_ci 4924141cc406Sopenharmony_ci dev->regs[0xe7] = 0x75; 4925141cc406Sopenharmony_ci dev->regs[0xe8] = 0x01; 4926141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0b; 4927141cc406Sopenharmony_ci dev->regs[0xea] = 0x54; 4928141cc406Sopenharmony_ci dev->regs[0xeb] = 0x01; 4929141cc406Sopenharmony_ci dev->regs[0xec] = 0x04; 4930141cc406Sopenharmony_ci dev->regs[0xed] = 0xb8; 4931141cc406Sopenharmony_ci dev->regs[0xef] = 0x03; 4932141cc406Sopenharmony_ci dev->regs[0xf0] = 0x70; 4933141cc406Sopenharmony_ci dev->regs[0xf2] = 0x01; 4934141cc406Sopenharmony_ci 4935141cc406Sopenharmony_ci dev->regs[0x72] = 0xe1; 4936141cc406Sopenharmony_ci dev->regs[0x73] = 0x14; 4937141cc406Sopenharmony_ci dev->regs[0x74] = 0x18; 4938141cc406Sopenharmony_ci 4939141cc406Sopenharmony_ci dev->regs[0xc3] = 0xff; 4940141cc406Sopenharmony_ci dev->regs[0xc4] = 0xff; 4941141cc406Sopenharmony_ci dev->regs[0xc7] = 0xff; 4942141cc406Sopenharmony_ci dev->regs[0xc8] = 0xff; 4943141cc406Sopenharmony_ci 4944141cc406Sopenharmony_ci dev->regs[0xd7] = 0x30; 4945141cc406Sopenharmony_ci 4946141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 4947141cc406Sopenharmony_ci { 4948141cc406Sopenharmony_ci dev->regs[0xc0] = 0x67; 4949141cc406Sopenharmony_ci dev->regs[0xc1] = 0x06; 4950141cc406Sopenharmony_ci dev->regs[0xc2] = 0xe6; 4951141cc406Sopenharmony_ci dev->regs[0xc3] = 0x98; 4952141cc406Sopenharmony_ci dev->regs[0xc4] = 0xf9; 4953141cc406Sopenharmony_ci dev->regs[0xc5] = 0x19; 4954141cc406Sopenharmony_ci dev->regs[0xc6] = 0x67; 4955141cc406Sopenharmony_ci dev->regs[0xc7] = 0x06; 4956141cc406Sopenharmony_ci dev->regs[0xc8] = 0xe6; 4957141cc406Sopenharmony_ci dev->regs[0xc9] = 0x01; 4958141cc406Sopenharmony_ci dev->regs[0xca] = 0xf8; 4959141cc406Sopenharmony_ci dev->regs[0xcb] = 0xff; 4960141cc406Sopenharmony_ci dev->regs[0xcc] = 0x98; 4961141cc406Sopenharmony_ci dev->regs[0xcd] = 0xf9; 4962141cc406Sopenharmony_ci dev->regs[0xce] = 0x19; 4963141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe0; 4964141cc406Sopenharmony_ci dev->regs[0xd0] = 0xe2; 4965141cc406Sopenharmony_ci dev->regs[0xd1] = 0xeb; 4966141cc406Sopenharmony_ci dev->regs[0xd2] = 0x0c; 4967141cc406Sopenharmony_ci dev->regs[0xd3] = 0x02; 4968141cc406Sopenharmony_ci dev->regs[0xd4] = 0x04; 4969141cc406Sopenharmony_ci dev->regs[0xd6] = 0x0f; 4970141cc406Sopenharmony_ci dev->regs[0xd7] = 0x10; 4971141cc406Sopenharmony_ci dev->regs[0xd8] = 0x52; 4972141cc406Sopenharmony_ci dev->regs[0xe2] = 0x1f; 4973141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x28; 0028 -> 40 4974141cc406Sopenharmony_ci dev->regs[0xe6] = 0x00; */ 4975141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); 4976141cc406Sopenharmony_ci dev->regs[0xe7] = 0x75; 4977141cc406Sopenharmony_ci dev->regs[0xe8] = 0x01; 4978141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0b; 4979141cc406Sopenharmony_ci dev->regs[0xea] = 0x54; 4980141cc406Sopenharmony_ci dev->regs[0xeb] = 0x01; 4981141cc406Sopenharmony_ci dev->regs[0xec] = 0x04; 4982141cc406Sopenharmony_ci dev->regs[0xed] = 0xb8; 4983141cc406Sopenharmony_ci dev->regs[0xef] = 0x03; 4984141cc406Sopenharmony_ci dev->regs[0xf0] = 0x70; 4985141cc406Sopenharmony_ci dev->regs[0xf2] = 0x01; 4986141cc406Sopenharmony_ci } 4987141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 4988141cc406Sopenharmony_ci { 4989141cc406Sopenharmony_ci dev->regs[0x35] = 0x48; /* 0x45 */ 4990141cc406Sopenharmony_ci /* c5, c6 ? : untouched from previous scan ... */ 4991141cc406Sopenharmony_ci dev->regs[0xe2] = 0x0f; /* 0x1f */ 4992141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x52; */ 4993141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ 4994141cc406Sopenharmony_ci dev->regs[0xe7] = 0x0e; /* 0x75 */ 4995141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0a; /* 0x0b */ 4996141cc406Sopenharmony_ci dev->regs[0xea] = 0xc2; /* 0x54 */ 4997141cc406Sopenharmony_ci dev->regs[0xed] = 0xf6; /* 0xb8 */ 4998141cc406Sopenharmony_ci dev->regs[0xef] = 0x02; /* 0x03 */ 4999141cc406Sopenharmony_ci dev->regs[0xf0] = 0xa8; /* 0x70 */ 5000141cc406Sopenharmony_ci } 5001141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 5002141cc406Sopenharmony_ci { 5003141cc406Sopenharmony_ci dev->regs[0x13] = 0x39; 5004141cc406Sopenharmony_ci dev->regs[0x14] = 0xf0; 5005141cc406Sopenharmony_ci dev->regs[0x15] = 0x29; 5006141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; 5007141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; 5008141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; 5009141cc406Sopenharmony_ci dev->regs[0x35] = 0x48; 5010141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; 5011141cc406Sopenharmony_ci dev->regs[0xe2] = 0x0f; 5012141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); 5013141cc406Sopenharmony_ci dev->regs[0xe7] = 0x0e; 5014141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0a; 5015141cc406Sopenharmony_ci dev->regs[0xea] = 0xc2; 5016141cc406Sopenharmony_ci dev->regs[0xed] = 0xf6; 5017141cc406Sopenharmony_ci dev->regs[0xef] = 0x02; 5018141cc406Sopenharmony_ci dev->regs[0xf0] = 0xa8; 5019141cc406Sopenharmony_ci 5020141cc406Sopenharmony_ci timing=0x32; 5021141cc406Sopenharmony_ci dev->regs[0x85] = 0x00; 5022141cc406Sopenharmony_ci dev->regs[0x86] = 0x06; 5023141cc406Sopenharmony_ci dev->regs[0x87] = 0x00; 5024141cc406Sopenharmony_ci dev->regs[0x88] = 0x06; 5025141cc406Sopenharmony_ci } 5026141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING_REG, timing); 5027141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); 5028141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); 5029141cc406Sopenharmony_ci 5030141cc406Sopenharmony_ci 5031141cc406Sopenharmony_ci /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each white average 5032141cc406Sopenharmony_ci * reaches the desired value, doing a dichotomy */ 5033141cc406Sopenharmony_ci rg = 0x1f; 5034141cc406Sopenharmony_ci bg = 0x1f; 5035141cc406Sopenharmony_ci gg = 0x1f; 5036141cc406Sopenharmony_ci /* dichotomy interval */ 5037141cc406Sopenharmony_ci /* bottom values */ 5038141cc406Sopenharmony_ci brg = 0; 5039141cc406Sopenharmony_ci bgg = 0; 5040141cc406Sopenharmony_ci bbg = 0; 5041141cc406Sopenharmony_ci /* top values */ 5042141cc406Sopenharmony_ci trg = 0x1f; 5043141cc406Sopenharmony_ci tgg = 0x1f; 5044141cc406Sopenharmony_ci tbg = 0x1f; 5045141cc406Sopenharmony_ci 5046141cc406Sopenharmony_ci /* loop on gain calibration until we find until we find stable value 5047141cc406Sopenharmony_ci * or we do more than 20 tries */ 5048141cc406Sopenharmony_ci do 5049141cc406Sopenharmony_ci { 5050141cc406Sopenharmony_ci /* store current values as previous */ 5051141cc406Sopenharmony_ci xrg = rg; 5052141cc406Sopenharmony_ci xbg = bg; 5053141cc406Sopenharmony_ci xgg = gg; 5054141cc406Sopenharmony_ci 5055141cc406Sopenharmony_ci /* set up for scan */ 5056141cc406Sopenharmony_ci DBG (DBG_info, 5057141cc406Sopenharmony_ci "gain_calibration: trying gains=(0x%02x,0x%02x,0x%02x)\n", rg, gg, 5058141cc406Sopenharmony_ci bg); 5059141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, rg, gg, bg); 5060141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); 5061141cc406Sopenharmony_ci 5062141cc406Sopenharmony_ci /* scan on line in RGB */ 5063141cc406Sopenharmony_ci status = 5064141cc406Sopenharmony_ci rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, 5065141cc406Sopenharmony_ci length, image); 5066141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 5067141cc406Sopenharmony_ci { 5068141cc406Sopenharmony_ci DBG (DBG_error, "gain_calibration: failed scan data\n"); 5069141cc406Sopenharmony_ci return status; 5070141cc406Sopenharmony_ci } 5071141cc406Sopenharmony_ci 5072141cc406Sopenharmony_ci /* save scanned picture for data debugging */ 5073141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 5074141cc406Sopenharmony_ci { 5075141cc406Sopenharmony_ci sprintf (name, "gain%03d.pnm", num); 5076141cc406Sopenharmony_ci write_rgb_data (name, image, width, 1); 5077141cc406Sopenharmony_ci num++; 5078141cc406Sopenharmony_ci } 5079141cc406Sopenharmony_ci 5080141cc406Sopenharmony_ci /* we now compute the average pixel value on the scanned line */ 5081141cc406Sopenharmony_ci /* TODO use computed left margin */ 5082141cc406Sopenharmony_ci global = average_area (SANE_TRUE, image, width, 1, &ra, &ga, &ba); 5083141cc406Sopenharmony_ci DBG (DBG_info, 5084141cc406Sopenharmony_ci "gain_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", 5085141cc406Sopenharmony_ci global, ra, ga, ba); 5086141cc406Sopenharmony_ci 5087141cc406Sopenharmony_ci /* dichotomy again ... */ 5088141cc406Sopenharmony_ci if (fabs (ra - RED_GAIN_TARGET) < GAIN_MARGIN) 5089141cc406Sopenharmony_ci { 5090141cc406Sopenharmony_ci /* gain is OK, it is whitin the tolerance margin */ 5091141cc406Sopenharmony_ci trg = rg; 5092141cc406Sopenharmony_ci brg = rg; 5093141cc406Sopenharmony_ci } 5094141cc406Sopenharmony_ci else 5095141cc406Sopenharmony_ci { /* average is higher than the desired value */ 5096141cc406Sopenharmony_ci if (ra > RED_GAIN_TARGET) 5097141cc406Sopenharmony_ci { 5098141cc406Sopenharmony_ci /* changing gain for another channel alters other output */ 5099141cc406Sopenharmony_ci /* a stable value is shown by top value == bottom value */ 5100141cc406Sopenharmony_ci if (trg == brg) 5101141cc406Sopenharmony_ci { 5102141cc406Sopenharmony_ci brg--; 5103141cc406Sopenharmony_ci rg = brg; 5104141cc406Sopenharmony_ci } 5105141cc406Sopenharmony_ci else 5106141cc406Sopenharmony_ci { 5107141cc406Sopenharmony_ci /* since we'ra above target value, current gain becomes top value */ 5108141cc406Sopenharmony_ci trg = rg; 5109141cc406Sopenharmony_ci rg = (trg + brg) / 2; 5110141cc406Sopenharmony_ci } 5111141cc406Sopenharmony_ci } 5112141cc406Sopenharmony_ci else /* below target value */ 5113141cc406Sopenharmony_ci { 5114141cc406Sopenharmony_ci if (trg == brg) 5115141cc406Sopenharmony_ci { 5116141cc406Sopenharmony_ci trg++; 5117141cc406Sopenharmony_ci rg = trg; 5118141cc406Sopenharmony_ci } 5119141cc406Sopenharmony_ci else 5120141cc406Sopenharmony_ci { 5121141cc406Sopenharmony_ci /* since we are below target, current value is assigned to bottom value */ 5122141cc406Sopenharmony_ci brg = rg; 5123141cc406Sopenharmony_ci rg = (trg + brg + 1) / 2; 5124141cc406Sopenharmony_ci } 5125141cc406Sopenharmony_ci } 5126141cc406Sopenharmony_ci } 5127141cc406Sopenharmony_ci 5128141cc406Sopenharmony_ci /* same for blue channel */ 5129141cc406Sopenharmony_ci if (fabs (ba - BLUE_GAIN_TARGET) < GAIN_MARGIN) 5130141cc406Sopenharmony_ci { 5131141cc406Sopenharmony_ci bbg = bg; 5132141cc406Sopenharmony_ci tbg = bg; 5133141cc406Sopenharmony_ci } 5134141cc406Sopenharmony_ci else 5135141cc406Sopenharmony_ci { /* NOK */ 5136141cc406Sopenharmony_ci if (ba > BLUE_GAIN_TARGET) 5137141cc406Sopenharmony_ci { 5138141cc406Sopenharmony_ci if (tbg == bbg) 5139141cc406Sopenharmony_ci { 5140141cc406Sopenharmony_ci bbg--; 5141141cc406Sopenharmony_ci bg = bbg; 5142141cc406Sopenharmony_ci } 5143141cc406Sopenharmony_ci else 5144141cc406Sopenharmony_ci { 5145141cc406Sopenharmony_ci tbg = bg; 5146141cc406Sopenharmony_ci bg = (tbg + bbg) / 2; 5147141cc406Sopenharmony_ci } 5148141cc406Sopenharmony_ci } 5149141cc406Sopenharmony_ci else 5150141cc406Sopenharmony_ci { 5151141cc406Sopenharmony_ci if (tbg == bbg) 5152141cc406Sopenharmony_ci { 5153141cc406Sopenharmony_ci tbg++; 5154141cc406Sopenharmony_ci bg = tbg; 5155141cc406Sopenharmony_ci } 5156141cc406Sopenharmony_ci else 5157141cc406Sopenharmony_ci { 5158141cc406Sopenharmony_ci bbg = bg; 5159141cc406Sopenharmony_ci bg = (tbg + bbg + 1) / 2; 5160141cc406Sopenharmony_ci } 5161141cc406Sopenharmony_ci } 5162141cc406Sopenharmony_ci } 5163141cc406Sopenharmony_ci 5164141cc406Sopenharmony_ci /* and for green channel */ 5165141cc406Sopenharmony_ci if (fabs (ga - GREEN_GAIN_TARGET) < GAIN_MARGIN) 5166141cc406Sopenharmony_ci { 5167141cc406Sopenharmony_ci tgg = gg; 5168141cc406Sopenharmony_ci bgg = gg; 5169141cc406Sopenharmony_ci } 5170141cc406Sopenharmony_ci else 5171141cc406Sopenharmony_ci { /* NOK */ 5172141cc406Sopenharmony_ci if (ga > GREEN_GAIN_TARGET) 5173141cc406Sopenharmony_ci { 5174141cc406Sopenharmony_ci if (tgg == bgg) 5175141cc406Sopenharmony_ci { 5176141cc406Sopenharmony_ci bgg--; 5177141cc406Sopenharmony_ci gg = bgg; 5178141cc406Sopenharmony_ci } 5179141cc406Sopenharmony_ci else 5180141cc406Sopenharmony_ci { 5181141cc406Sopenharmony_ci tgg = gg; 5182141cc406Sopenharmony_ci gg = (tgg + bgg) / 2; 5183141cc406Sopenharmony_ci } 5184141cc406Sopenharmony_ci } 5185141cc406Sopenharmony_ci else 5186141cc406Sopenharmony_ci { 5187141cc406Sopenharmony_ci if (tgg == bgg) 5188141cc406Sopenharmony_ci { 5189141cc406Sopenharmony_ci tgg++; 5190141cc406Sopenharmony_ci gg = tgg; 5191141cc406Sopenharmony_ci } 5192141cc406Sopenharmony_ci else 5193141cc406Sopenharmony_ci { 5194141cc406Sopenharmony_ci bgg = gg; 5195141cc406Sopenharmony_ci gg = (tgg + bgg + 1) / 2; 5196141cc406Sopenharmony_ci } 5197141cc406Sopenharmony_ci } 5198141cc406Sopenharmony_ci } 5199141cc406Sopenharmony_ci pass++; 5200141cc406Sopenharmony_ci } 5201141cc406Sopenharmony_ci while ((pass < 20) 5202141cc406Sopenharmony_ci && ((trg != brg && xrg != rg) 5203141cc406Sopenharmony_ci || (tgg != bgg && xgg != gg) || (tbg != bbg && xbg != bg))); 5204141cc406Sopenharmony_ci 5205141cc406Sopenharmony_ci /* store detected values in device struct */ 5206141cc406Sopenharmony_ci dev->red_gain = brg; 5207141cc406Sopenharmony_ci dev->green_gain = bgg; 5208141cc406Sopenharmony_ci dev->blue_gain = bbg; 5209141cc406Sopenharmony_ci DBG (DBG_info, "gain_calibration: gain=(0x%02x,0x%02x,0x%02x)\n", brg, bgg, 5210141cc406Sopenharmony_ci bbg); 5211141cc406Sopenharmony_ci 5212141cc406Sopenharmony_ci DBG (DBG_proc, "gain_calibration: exit\n"); 5213141cc406Sopenharmony_ci return status; 5214141cc406Sopenharmony_ci} 5215141cc406Sopenharmony_ci 5216141cc406Sopenharmony_ci/** 5217141cc406Sopenharmony_ci * Do fine offset calibration. Scans are done with gains from gain calibration 5218141cc406Sopenharmony_ci * at 75 dpi regardless of the dpi of the final scan. We loop scanning a 637 5219141cc406Sopenharmony_ci * (1911 bytes) pixels wide area in color mode until each black average 5220141cc406Sopenharmony_ci * reaches the desired value (OFFSET_TARGET). 5221141cc406Sopenharmony_ci */ 5222141cc406Sopenharmony_cistatic SANE_Status 5223141cc406Sopenharmony_cioffset_calibration (struct Rts8891_Device *dev, int mode, int light) 5224141cc406Sopenharmony_ci{ 5225141cc406Sopenharmony_ci 5226141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 5227141cc406Sopenharmony_ci /* red, green and blue offset, within a 't'op and 'b'ottom value */ 5228141cc406Sopenharmony_ci int ro = 250, tro = 250, bro = 123; 5229141cc406Sopenharmony_ci int go = 250, tgo = 250, bgo = 123; 5230141cc406Sopenharmony_ci int bo = 250, tbo = 250, bbo = 123; 5231141cc406Sopenharmony_ci unsigned char image[CALIBRATION_SIZE]; 5232141cc406Sopenharmony_ci float global, ra, ga, ba; 5233141cc406Sopenharmony_ci int num = 0; 5234141cc406Sopenharmony_ci char name[32]; 5235141cc406Sopenharmony_ci 5236141cc406Sopenharmony_ci DBG (DBG_proc, "offset_calibration: start\n"); 5237141cc406Sopenharmony_ci 5238141cc406Sopenharmony_ci /* set up starting values */ 5239141cc406Sopenharmony_ci /* gains from previous step are a little higher than the one used */ 5240141cc406Sopenharmony_ci sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain, 5241141cc406Sopenharmony_ci dev->blue_gain); 5242141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH); 5243141cc406Sopenharmony_ci 5244141cc406Sopenharmony_ci dev->regs[0x32] = 0x00; 5245141cc406Sopenharmony_ci dev->regs[0x33] = 0x03; 5246141cc406Sopenharmony_ci dev->regs[0x35] = 0x45; 5247141cc406Sopenharmony_ci dev->regs[0x36] = 0x22; 5248141cc406Sopenharmony_ci dev->regs[0x3a] = 0x43; 5249141cc406Sopenharmony_ci 5250141cc406Sopenharmony_ci dev->regs[0x8d] = 0x00; 5251141cc406Sopenharmony_ci dev->regs[0x8e] = 0x60; 5252141cc406Sopenharmony_ci dev->regs[0xb2] = 0x02; 5253141cc406Sopenharmony_ci dev->regs[0xc0] = 0x06; 5254141cc406Sopenharmony_ci dev->regs[0xc1] = 0xe6; 5255141cc406Sopenharmony_ci dev->regs[0xc2] = 0x67; 5256141cc406Sopenharmony_ci dev->regs[0xc9] = 0x07; 5257141cc406Sopenharmony_ci dev->regs[0xca] = 0x00; 5258141cc406Sopenharmony_ci dev->regs[0xcb] = 0xfe; 5259141cc406Sopenharmony_ci dev->regs[0xcc] = 0xf9; 5260141cc406Sopenharmony_ci dev->regs[0xcd] = 0x19; 5261141cc406Sopenharmony_ci dev->regs[0xce] = 0x98; 5262141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe8; 5263141cc406Sopenharmony_ci dev->regs[0xd0] = 0xea; 5264141cc406Sopenharmony_ci dev->regs[0xd1] = 0xf3; 5265141cc406Sopenharmony_ci dev->regs[0xd2] = 0x14; 5266141cc406Sopenharmony_ci dev->regs[0xd3] = 0x02; 5267141cc406Sopenharmony_ci dev->regs[0xd4] = 0x04; 5268141cc406Sopenharmony_ci dev->regs[0xd6] = 0x0f; 5269141cc406Sopenharmony_ci dev->regs[0xd8] = 0x52; 5270141cc406Sopenharmony_ci dev->regs[0xe2] = 0x1f; 5271141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x28; 5272141cc406Sopenharmony_ci dev->regs[0xe6] = 0x00; 0x0028=40 */ 5273141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); 5274141cc406Sopenharmony_ci dev->regs[0xe7] = 0x75; 5275141cc406Sopenharmony_ci dev->regs[0xe8] = 0x01; 5276141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0b; 5277141cc406Sopenharmony_ci dev->regs[0xea] = 0x54; 5278141cc406Sopenharmony_ci dev->regs[0xeb] = 0x01; 5279141cc406Sopenharmony_ci dev->regs[0xec] = 0x04; 5280141cc406Sopenharmony_ci dev->regs[0xed] = 0xb8; 5281141cc406Sopenharmony_ci dev->regs[0xef] = 0x03; 5282141cc406Sopenharmony_ci dev->regs[0xf0] = 0x70; 5283141cc406Sopenharmony_ci dev->regs[0xf2] = 0x01; 5284141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 5285141cc406Sopenharmony_ci { 5286141cc406Sopenharmony_ci dev->regs[0x72] = 0xe1; 5287141cc406Sopenharmony_ci dev->regs[0x73] = 0x14; 5288141cc406Sopenharmony_ci dev->regs[0x74] = 0x18; 5289141cc406Sopenharmony_ci 5290141cc406Sopenharmony_ci dev->regs[0xc0] = 0x67; 5291141cc406Sopenharmony_ci dev->regs[0xc1] = 0x06; 5292141cc406Sopenharmony_ci dev->regs[0xc2] = 0xe6; 5293141cc406Sopenharmony_ci dev->regs[0xc3] = 0x98; 5294141cc406Sopenharmony_ci dev->regs[0xc4] = 0xf9; 5295141cc406Sopenharmony_ci dev->regs[0xc5] = 0x19; 5296141cc406Sopenharmony_ci dev->regs[0xc6] = 0x67; 5297141cc406Sopenharmony_ci dev->regs[0xc7] = 0x06; 5298141cc406Sopenharmony_ci dev->regs[0xc8] = 0xe6; 5299141cc406Sopenharmony_ci dev->regs[0xc9] = 0x01; 5300141cc406Sopenharmony_ci dev->regs[0xca] = 0xf8; 5301141cc406Sopenharmony_ci dev->regs[0xcb] = 0xff; 5302141cc406Sopenharmony_ci dev->regs[0xcc] = 0x98; 5303141cc406Sopenharmony_ci dev->regs[0xcd] = 0xf9; 5304141cc406Sopenharmony_ci dev->regs[0xce] = 0x19; 5305141cc406Sopenharmony_ci dev->regs[0xcf] = 0xe0; 5306141cc406Sopenharmony_ci dev->regs[0xd0] = 0xe2; 5307141cc406Sopenharmony_ci dev->regs[0xd1] = 0xeb; 5308141cc406Sopenharmony_ci dev->regs[0xd2] = 0x0c; 5309141cc406Sopenharmony_ci dev->regs[0xd7] = 0x10; 5310141cc406Sopenharmony_ci } 5311141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 5312141cc406Sopenharmony_ci { 5313141cc406Sopenharmony_ci dev->regs[0x35] = 0x48; /* 0x45 */ 5314141cc406Sopenharmony_ci /* c5,c6 ?? */ 5315141cc406Sopenharmony_ci dev->regs[0xe2] = 0x0f; /* 0x1f */ 5316141cc406Sopenharmony_ci /* dev->regs[0xe5] = 0x52; 0x28 */ 5317141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ 5318141cc406Sopenharmony_ci dev->regs[0xe7] = 0x0e; /* 0x75 */ 5319141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0a; /* 0x0b */ 5320141cc406Sopenharmony_ci dev->regs[0xea] = 0xc2; /* 0x54 */ 5321141cc406Sopenharmony_ci dev->regs[0xed] = 0xf6; /* 0xb8 */ 5322141cc406Sopenharmony_ci dev->regs[0xef] = 0x02; /* 0x03 */ 5323141cc406Sopenharmony_ci dev->regs[0xf0] = 0xa8; /* 0x70 */ 5324141cc406Sopenharmony_ci } 5325141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 5326141cc406Sopenharmony_ci { 5327141cc406Sopenharmony_ci dev->regs[0x13] = 0x39; /* 0x20 */ 5328141cc406Sopenharmony_ci dev->regs[0x14] = 0xf0; /* 0xf8 */ 5329141cc406Sopenharmony_ci dev->regs[0x15] = 0x29; /* 0x28 */ 5330141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; /* 0x07 */ 5331141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; /* 0x00 */ 5332141cc406Sopenharmony_ci dev->regs[0x23] = 0x00; /* 0xff */ 5333141cc406Sopenharmony_ci dev->regs[0x35] = 0x48; /* 0x45 */ 5334141cc406Sopenharmony_ci dev->regs[0x39] = 0x00; /* 0x02 */ 5335141cc406Sopenharmony_ci dev->regs[0xe2] = 0x0f; /* 0x1f */ 5336141cc406Sopenharmony_ci SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ 5337141cc406Sopenharmony_ci dev->regs[0xe7] = 0x0e; /* 0x75 */ 5338141cc406Sopenharmony_ci dev->regs[0xe9] = 0x0a; /* 0x0b */ 5339141cc406Sopenharmony_ci dev->regs[0xea] = 0xc2; /* 0x54 */ 5340141cc406Sopenharmony_ci dev->regs[0xed] = 0xf6; /* 0xb8 */ 5341141cc406Sopenharmony_ci dev->regs[0xef] = 0x02; /* 0x03 */ 5342141cc406Sopenharmony_ci dev->regs[0xf0] = 0xa8; /* 0x70 */ 5343141cc406Sopenharmony_ci } 5344141cc406Sopenharmony_ci 5345141cc406Sopenharmony_ci /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each black average 5346141cc406Sopenharmony_ci * reaches the desired value */ 5347141cc406Sopenharmony_ci do 5348141cc406Sopenharmony_ci { 5349141cc406Sopenharmony_ci DBG (DBG_info, "offset_calibration: trying offsets=(%d,%d,%d) ...\n", 5350141cc406Sopenharmony_ci ro, go, bo); 5351141cc406Sopenharmony_ci sanei_rts88xx_set_offset (dev->regs, ro, go, bo); 5352141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); 5353141cc406Sopenharmony_ci rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, 5354141cc406Sopenharmony_ci CALIBRATION_SIZE, image); 5355141cc406Sopenharmony_ci 5356141cc406Sopenharmony_ci /* save scanned picture for data debugging */ 5357141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 5358141cc406Sopenharmony_ci { 5359141cc406Sopenharmony_ci sprintf (name, "offset%03d.pnm", num); 5360141cc406Sopenharmony_ci write_rgb_data (name, image, CALIBRATION_WIDTH, 1); 5361141cc406Sopenharmony_ci num++; 5362141cc406Sopenharmony_ci } 5363141cc406Sopenharmony_ci 5364141cc406Sopenharmony_ci /* we now compute the average of red pixels from the first 15 pixels */ 5365141cc406Sopenharmony_ci global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba); 5366141cc406Sopenharmony_ci DBG (DBG_info, 5367141cc406Sopenharmony_ci "offset_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", 5368141cc406Sopenharmony_ci global, ra, ga, ba); 5369141cc406Sopenharmony_ci 5370141cc406Sopenharmony_ci /* dichotomie ... */ 5371141cc406Sopenharmony_ci if (fabs (ra - OFFSET_TARGET) < OFFSET_MARGIN) 5372141cc406Sopenharmony_ci { 5373141cc406Sopenharmony_ci /* offset is OK */ 5374141cc406Sopenharmony_ci tro = ro; 5375141cc406Sopenharmony_ci bro = ro; 5376141cc406Sopenharmony_ci } 5377141cc406Sopenharmony_ci else 5378141cc406Sopenharmony_ci { /* NOK */ 5379141cc406Sopenharmony_ci if (ra > OFFSET_TARGET) 5380141cc406Sopenharmony_ci { 5381141cc406Sopenharmony_ci tro = ro; 5382141cc406Sopenharmony_ci ro = (tro + bro) / 2; 5383141cc406Sopenharmony_ci } 5384141cc406Sopenharmony_ci if (ra < OFFSET_TARGET) 5385141cc406Sopenharmony_ci { 5386141cc406Sopenharmony_ci bro = ro; 5387141cc406Sopenharmony_ci ro = (tro + bro + 1) / 2; 5388141cc406Sopenharmony_ci } 5389141cc406Sopenharmony_ci 5390141cc406Sopenharmony_ci } 5391141cc406Sopenharmony_ci 5392141cc406Sopenharmony_ci /* same for blue channel */ 5393141cc406Sopenharmony_ci if (fabs (ba - OFFSET_TARGET) < OFFSET_MARGIN) 5394141cc406Sopenharmony_ci { 5395141cc406Sopenharmony_ci bbo = bo; 5396141cc406Sopenharmony_ci tbo = bo; 5397141cc406Sopenharmony_ci } 5398141cc406Sopenharmony_ci else 5399141cc406Sopenharmony_ci { 5400141cc406Sopenharmony_ci if (ba > OFFSET_TARGET) 5401141cc406Sopenharmony_ci { 5402141cc406Sopenharmony_ci tbo = bo; 5403141cc406Sopenharmony_ci bo = (tbo + bbo) / 2; 5404141cc406Sopenharmony_ci } 5405141cc406Sopenharmony_ci if (ba < OFFSET_TARGET) 5406141cc406Sopenharmony_ci { 5407141cc406Sopenharmony_ci bbo = bo; 5408141cc406Sopenharmony_ci bo = (tbo + bbo + 1) / 2; 5409141cc406Sopenharmony_ci } 5410141cc406Sopenharmony_ci 5411141cc406Sopenharmony_ci } 5412141cc406Sopenharmony_ci 5413141cc406Sopenharmony_ci /* and for green channel */ 5414141cc406Sopenharmony_ci if (fabs (ga - OFFSET_TARGET) < OFFSET_MARGIN) 5415141cc406Sopenharmony_ci { 5416141cc406Sopenharmony_ci tgo = go; 5417141cc406Sopenharmony_ci bgo = go; 5418141cc406Sopenharmony_ci } 5419141cc406Sopenharmony_ci else 5420141cc406Sopenharmony_ci { 5421141cc406Sopenharmony_ci if (ga > OFFSET_TARGET) 5422141cc406Sopenharmony_ci { 5423141cc406Sopenharmony_ci tgo = go; 5424141cc406Sopenharmony_ci go = (tgo + bgo) / 2; 5425141cc406Sopenharmony_ci } 5426141cc406Sopenharmony_ci if (ga < OFFSET_TARGET) 5427141cc406Sopenharmony_ci { 5428141cc406Sopenharmony_ci bgo = go; 5429141cc406Sopenharmony_ci go = (tgo + bgo + 1) / 2; 5430141cc406Sopenharmony_ci } 5431141cc406Sopenharmony_ci } 5432141cc406Sopenharmony_ci } 5433141cc406Sopenharmony_ci while ((tro != bro) || (tgo != bgo) || (tbo != bbo)); 5434141cc406Sopenharmony_ci 5435141cc406Sopenharmony_ci /* store detected values in device struct */ 5436141cc406Sopenharmony_ci dev->red_offset = bro; 5437141cc406Sopenharmony_ci dev->green_offset = bgo; 5438141cc406Sopenharmony_ci dev->blue_offset = bbo; 5439141cc406Sopenharmony_ci 5440141cc406Sopenharmony_ci DBG (DBG_proc, "offset_calibration: exit\n"); 5441141cc406Sopenharmony_ci return status; 5442141cc406Sopenharmony_ci} 5443141cc406Sopenharmony_ci 5444141cc406Sopenharmony_ci/* 5445141cc406Sopenharmony_ci * do shading calibration 5446141cc406Sopenharmony_ci * We scan a 637 pixels by 66 linesxoffset=24 , xend=661, pixels=637 5447141cc406Sopenharmony_ciy offset=1 , yend=67, lines =66 5448141cc406Sopenharmony_ci */ 5449141cc406Sopenharmony_cistatic SANE_Status 5450141cc406Sopenharmony_cisetup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int *status1, SANE_Byte * regs) 5451141cc406Sopenharmony_ci{ 5452141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 5453141cc406Sopenharmony_ci int lines = 66; 5454141cc406Sopenharmony_ci int exposure=0; 5455141cc406Sopenharmony_ci int timing=0; 5456141cc406Sopenharmony_ci 5457141cc406Sopenharmony_ci DBG (DBG_proc, "setup_shading_calibration: start\n"); 5458141cc406Sopenharmony_ci DBG (DBG_info, "setup_shading_calibration: sensor type is %s (%d)\n", sensor_name (dev->sensor), dev->sensor); 5459141cc406Sopenharmony_ci 5460141cc406Sopenharmony_ci /* set up registers */ 5461141cc406Sopenharmony_ci /* 0x20/0x28 0x3b/0x3f seen in logs */ 5462141cc406Sopenharmony_ci *status1 = mode; 5463141cc406Sopenharmony_ci if (dev->xdpi > 300) 5464141cc406Sopenharmony_ci { 5465141cc406Sopenharmony_ci *status1 |= 0x08; 5466141cc406Sopenharmony_ci } 5467141cc406Sopenharmony_ci 5468141cc406Sopenharmony_ci /* we default to 75 dpi then override needed registers */ 5469141cc406Sopenharmony_ci timing=0x00b0; 5470141cc406Sopenharmony_ci regs[0x32] = 0x20; 5471141cc406Sopenharmony_ci regs[0x33] = 0x83; 5472141cc406Sopenharmony_ci regs[0x35] = 0x0e; 5473141cc406Sopenharmony_ci regs[0x36] = 0x2c; 5474141cc406Sopenharmony_ci regs[0x3a] = 0x0e; 5475141cc406Sopenharmony_ci 5476141cc406Sopenharmony_ci regs[0xe2] = 0x05; 5477141cc406Sopenharmony_ci regs[0xe7] = 0x00; 5478141cc406Sopenharmony_ci regs[0xe8] = 0x00; 5479141cc406Sopenharmony_ci regs[0xe9] = 0x00; 5480141cc406Sopenharmony_ci regs[0xea] = 0x00; 5481141cc406Sopenharmony_ci regs[0xeb] = 0x00; 5482141cc406Sopenharmony_ci regs[0xec] = 0x00; 5483141cc406Sopenharmony_ci regs[0xed] = 0x00; 5484141cc406Sopenharmony_ci regs[0xef] = 0x00; 5485141cc406Sopenharmony_ci regs[0xf0] = 0x00; 5486141cc406Sopenharmony_ci regs[0xf2] = 0x00; 5487141cc406Sopenharmony_ci /* regs[0xe5] = 0xdd; */ 5488141cc406Sopenharmony_ci 5489141cc406Sopenharmony_ci exposure=221; 5490141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 5491141cc406Sopenharmony_ci { 5492141cc406Sopenharmony_ci regs[0xc0] = 0x67; 5493141cc406Sopenharmony_ci regs[0xc1] = 0x06; 5494141cc406Sopenharmony_ci regs[0xc2] = 0xe6; 5495141cc406Sopenharmony_ci regs[0xc3] = 0x98; 5496141cc406Sopenharmony_ci regs[0xc4] = 0xf9; 5497141cc406Sopenharmony_ci regs[0xc5] = 0x19; 5498141cc406Sopenharmony_ci regs[0xc6] = 0x67; 5499141cc406Sopenharmony_ci regs[0xc7] = 0x06; 5500141cc406Sopenharmony_ci regs[0xc8] = 0xe6; 5501141cc406Sopenharmony_ci regs[0xc9] = 0x01; 5502141cc406Sopenharmony_ci regs[0xca] = 0xf8; 5503141cc406Sopenharmony_ci regs[0xcb] = 0xff; 5504141cc406Sopenharmony_ci regs[0xcc] = 0x98; 5505141cc406Sopenharmony_ci regs[0xcd] = 0xf9; 5506141cc406Sopenharmony_ci regs[0xce] = 0x19; 5507141cc406Sopenharmony_ci regs[0xcf] = 0xe0; 5508141cc406Sopenharmony_ci regs[0xd0] = 0xe2; 5509141cc406Sopenharmony_ci 5510141cc406Sopenharmony_ci regs[0xd1] = 0xeb; 5511141cc406Sopenharmony_ci regs[0xd2] = 0x0c; 5512141cc406Sopenharmony_ci 5513141cc406Sopenharmony_ci regs[0xd7] = 0x10; 5514141cc406Sopenharmony_ci } 5515141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 5516141cc406Sopenharmony_ci { 5517141cc406Sopenharmony_ci *light &= 0xf7; /* clear bit 3 */ 5518141cc406Sopenharmony_ci regs[0x36] = 0x29; /* 0x2c */ 5519141cc406Sopenharmony_ci timing=0x0032; 5520141cc406Sopenharmony_ci regs[0x85] = 0x00; /* 0x8c */ 5521141cc406Sopenharmony_ci regs[0x86] = 0x06; /* 0x10 */ 5522141cc406Sopenharmony_ci regs[0x87] = 0x00; /* 0x18 */ 5523141cc406Sopenharmony_ci regs[0x88] = 0x06; /* 0x1b */ 5524141cc406Sopenharmony_ci regs[0x8d] = 0x00; /* 0x77 */ 5525141cc406Sopenharmony_ci /* c5,c6 ?? */ 5526141cc406Sopenharmony_ci /* regs[0xd3] = 0x02; 0x0e */ 5527141cc406Sopenharmony_ci regs[0xd4] = 0x04; /* 0x10 */ 5528141cc406Sopenharmony_ci regs[0xe2] = 0x02; /* 0x05 */ 5529141cc406Sopenharmony_ci /* regs[0xe5] = 0xbb; 5530141cc406Sopenharmony_ci regs[0xe6] = 0x01; 1bb =443 */ 5531141cc406Sopenharmony_ci exposure=443; 5532141cc406Sopenharmony_ci } 5533141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 5534141cc406Sopenharmony_ci { 5535141cc406Sopenharmony_ci regs[0x13] = 0x39; /* 0x20 */ 5536141cc406Sopenharmony_ci regs[0x14] = 0xf0; /* 0xf8 */ 5537141cc406Sopenharmony_ci regs[0x15] = 0x29; /* 0x28 */ 5538141cc406Sopenharmony_ci regs[0x16] = 0x0f; /* 0x07 */ 5539141cc406Sopenharmony_ci regs[0x17] = 0x10; /* 0x00 */ 5540141cc406Sopenharmony_ci regs[0x23] = 0x00; /* 0xff */ 5541141cc406Sopenharmony_ci regs[0x36] = 0x29; /* 0x2c */ 5542141cc406Sopenharmony_ci regs[0x39] = 0x00; /* 0x02 */ 5543141cc406Sopenharmony_ci regs[0xe2] = 0x02; /* 0x05 */ 5544141cc406Sopenharmony_ci exposure=443; 5545141cc406Sopenharmony_ci } 5546141cc406Sopenharmony_ci 5547141cc406Sopenharmony_ci switch (dev->xdpi) 5548141cc406Sopenharmony_ci { 5549141cc406Sopenharmony_ci case 75: 5550141cc406Sopenharmony_ci break; 5551141cc406Sopenharmony_ci 5552141cc406Sopenharmony_ci case 150: 5553141cc406Sopenharmony_ci /* X resolution related registers */ 5554141cc406Sopenharmony_ci switch (dev->sensor) 5555141cc406Sopenharmony_ci { 5556141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 5557141cc406Sopenharmony_ci DBG (DBG_io, 5558141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 150 dpi\n"); 5559141cc406Sopenharmony_ci timing=0x022b; 5560141cc406Sopenharmony_ci regs[0x85] = 0x18; 5561141cc406Sopenharmony_ci regs[0x86] = 0x1b; 5562141cc406Sopenharmony_ci regs[0x87] = 0x30; 5563141cc406Sopenharmony_ci regs[0x88] = 0x30; 5564141cc406Sopenharmony_ci regs[0x8d] = 0xef; 5565141cc406Sopenharmony_ci regs[0xc0] = 0x00; 5566141cc406Sopenharmony_ci regs[0xc1] = 0x8e; 5567141cc406Sopenharmony_ci regs[0xc2] = 0xff; 5568141cc406Sopenharmony_ci regs[0xc3] = 0xff; 5569141cc406Sopenharmony_ci regs[0xc4] = 0x71; 5570141cc406Sopenharmony_ci regs[0xc5] = 0x00; 5571141cc406Sopenharmony_ci regs[0xc6] = 0x00; 5572141cc406Sopenharmony_ci regs[0xc7] = 0x8e; 5573141cc406Sopenharmony_ci regs[0xc8] = 0xff; 5574141cc406Sopenharmony_ci regs[0xc9] = 0xff; 5575141cc406Sopenharmony_ci regs[0xca] = 0xff; 5576141cc406Sopenharmony_ci regs[0xcb] = 0x1f; 5577141cc406Sopenharmony_ci regs[0xcc] = 0xff; 5578141cc406Sopenharmony_ci regs[0xcd] = 0x71; 5579141cc406Sopenharmony_ci regs[0xce] = 0x00; 5580141cc406Sopenharmony_ci regs[0xcf] = 0xe6; 5581141cc406Sopenharmony_ci regs[0xd0] = 0xe8; 5582141cc406Sopenharmony_ci regs[0xd1] = 0xf6; 5583141cc406Sopenharmony_ci regs[0xd2] = 0x17; 5584141cc406Sopenharmony_ci /* regs[0xd3] = 0x0b; */ 5585141cc406Sopenharmony_ci regs[0xd4] = 0x0d; 5586141cc406Sopenharmony_ci /* regs[0xe5] = 0xe4; */ 5587141cc406Sopenharmony_ci exposure=228; 5588141cc406Sopenharmony_ci break; 5589141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 5590141cc406Sopenharmony_ci DBG (DBG_io, 5591141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 150 dpi\n"); 5592141cc406Sopenharmony_ci timing=0x012e; 5593141cc406Sopenharmony_ci regs[0x85] = 0x8c; 5594141cc406Sopenharmony_ci regs[0x86] = 0x10; 5595141cc406Sopenharmony_ci regs[0x87] = 0x18; 5596141cc406Sopenharmony_ci regs[0x88] = 0x1b; 5597141cc406Sopenharmony_ci regs[0x8d] = 0x77; 5598141cc406Sopenharmony_ci regs[0xc0] = 0x80; 5599141cc406Sopenharmony_ci regs[0xc1] = 0x87; 5600141cc406Sopenharmony_ci regs[0xc2] = 0x7f; 5601141cc406Sopenharmony_ci regs[0xc9] = 0x00; 5602141cc406Sopenharmony_ci regs[0xcb] = 0x78; 5603141cc406Sopenharmony_ci regs[0xcc] = 0x7f; 5604141cc406Sopenharmony_ci regs[0xcd] = 0x78; 5605141cc406Sopenharmony_ci regs[0xce] = 0x80; 5606141cc406Sopenharmony_ci regs[0xcf] = 0xe6; 5607141cc406Sopenharmony_ci regs[0xd0] = 0xe8; 5608141cc406Sopenharmony_ci 5609141cc406Sopenharmony_ci regs[0xd1] = 0xf7; 5610141cc406Sopenharmony_ci regs[0xd2] = 0x00; 5611141cc406Sopenharmony_ci 5612141cc406Sopenharmony_ci /* regs[0xd3] = 0x0e; */ 5613141cc406Sopenharmony_ci regs[0xd4] = 0x10; 5614141cc406Sopenharmony_ci 5615141cc406Sopenharmony_ci /* regs[0xe5] = 0xe4; */ 5616141cc406Sopenharmony_ci exposure=228; 5617141cc406Sopenharmony_ci break; 5618141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 5619141cc406Sopenharmony_ci DBG (DBG_io, 5620141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 150 dpi\n"); 5621141cc406Sopenharmony_ci timing=0x012e; 5622141cc406Sopenharmony_ci regs[0x85] = 0x8c; 5623141cc406Sopenharmony_ci regs[0x86] = 0x10; 5624141cc406Sopenharmony_ci regs[0x87] = 0x18; 5625141cc406Sopenharmony_ci regs[0x88] = 0x1b; 5626141cc406Sopenharmony_ci regs[0x8d] = 0x77; 5627141cc406Sopenharmony_ci regs[0xc0] = 0x00; 5628141cc406Sopenharmony_ci regs[0xc1] = 0x8e; 5629141cc406Sopenharmony_ci regs[0xc2] = 0xff; 5630141cc406Sopenharmony_ci regs[0xc3] = 0xff; 5631141cc406Sopenharmony_ci regs[0xc4] = 0x71; 5632141cc406Sopenharmony_ci regs[0xc5] = 0x00; 5633141cc406Sopenharmony_ci regs[0xc6] = 0x00; 5634141cc406Sopenharmony_ci regs[0xc7] = 0x8e; 5635141cc406Sopenharmony_ci regs[0xc8] = 0xff; 5636141cc406Sopenharmony_ci regs[0xc9] = 0xff; 5637141cc406Sopenharmony_ci regs[0xca] = 0xff; 5638141cc406Sopenharmony_ci regs[0xcb] = 0x1f; 5639141cc406Sopenharmony_ci regs[0xcc] = 0xff; 5640141cc406Sopenharmony_ci regs[0xcd] = 0x71; 5641141cc406Sopenharmony_ci regs[0xce] = 0x00; 5642141cc406Sopenharmony_ci regs[0xcf] = 0xe6; 5643141cc406Sopenharmony_ci regs[0xd0] = 0xe8; 5644141cc406Sopenharmony_ci regs[0xd1] = 0xf6; 5645141cc406Sopenharmony_ci regs[0xd2] = 0x17; 5646141cc406Sopenharmony_ci /* regs[0xd3] = 0x0b; */ 5647141cc406Sopenharmony_ci regs[0xd4] = 0x0d; 5648141cc406Sopenharmony_ci exposure=457; 5649141cc406Sopenharmony_ci break; 5650141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 5651141cc406Sopenharmony_ci DBG (DBG_io, 5652141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 150 dpi\n"); 5653141cc406Sopenharmony_ci regs[0x13] = 0x39; /* 0x20 */ 5654141cc406Sopenharmony_ci regs[0x14] = 0xf0; /* 0xf8 */ 5655141cc406Sopenharmony_ci regs[0x15] = 0x29; /* 0x28 */ 5656141cc406Sopenharmony_ci regs[0x16] = 0x0f; /* 0x07 */ 5657141cc406Sopenharmony_ci regs[0x17] = 0x10; /* 0x00 */ 5658141cc406Sopenharmony_ci regs[0x23] = 0x00; /* 0xff */ 5659141cc406Sopenharmony_ci regs[0x36] = 0x29; /* 0x2c */ 5660141cc406Sopenharmony_ci regs[0x39] = 0x00; /* 0x02 */ 5661141cc406Sopenharmony_ci timing=0x00b0; 5662141cc406Sopenharmony_ci regs[0x85] = 0x46; /* 0x00 */ 5663141cc406Sopenharmony_ci regs[0x86] = 0x0b; /* 0x06 */ 5664141cc406Sopenharmony_ci regs[0x87] = 0x8c; /* 0x00 */ 5665141cc406Sopenharmony_ci regs[0x88] = 0x10; /* 0x06 */ 5666141cc406Sopenharmony_ci regs[0x8d] = 0x3b; /* 0x00 */ 5667141cc406Sopenharmony_ci regs[0xc0] = 0xff; /* 0x06 */ 5668141cc406Sopenharmony_ci regs[0xc1] = 0x0f; /* 0xe6 */ 5669141cc406Sopenharmony_ci regs[0xc2] = 0x00; /* 0x67 */ 5670141cc406Sopenharmony_ci regs[0xc9] = 0x00; /* 0x07 */ 5671141cc406Sopenharmony_ci regs[0xca] = 0x0e; /* 0x00 */ 5672141cc406Sopenharmony_ci regs[0xcb] = 0x00; /* 0xfe */ 5673141cc406Sopenharmony_ci regs[0xcc] = 0x00; /* 0xf9 */ 5674141cc406Sopenharmony_ci regs[0xcd] = 0xf0; /* 0x19 */ 5675141cc406Sopenharmony_ci regs[0xce] = 0xff; /* 0x98 */ 5676141cc406Sopenharmony_ci regs[0xcf] = 0xf5; /* 0xe8 */ 5677141cc406Sopenharmony_ci regs[0xd0] = 0xf7; /* 0xea */ 5678141cc406Sopenharmony_ci regs[0xd1] = 0xea; /* 0xf3 */ 5679141cc406Sopenharmony_ci regs[0xd2] = 0x0b; /* 0x14 */ 5680141cc406Sopenharmony_ci /* regs[0xd3] = 0x17; 0x02 */ 5681141cc406Sopenharmony_ci regs[0xd4] = 0x01; /* 0x04 */ 5682141cc406Sopenharmony_ci regs[0xe2] = 0x02; /* 0x05 */ 5683141cc406Sopenharmony_ci /* regs[0xe5] = 0x93; regs[0xe6] = 0x03; */ 5684141cc406Sopenharmony_ci exposure=915; 5685141cc406Sopenharmony_ci break; 5686141cc406Sopenharmony_ci } 5687141cc406Sopenharmony_ci break; 5688141cc406Sopenharmony_ci 5689141cc406Sopenharmony_ci case 300: 5690141cc406Sopenharmony_ci switch (dev->sensor) 5691141cc406Sopenharmony_ci { 5692141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 5693141cc406Sopenharmony_ci DBG (DBG_io, 5694141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 300 dpi\n"); 5695141cc406Sopenharmony_ci timing=0x00b0; 5696141cc406Sopenharmony_ci regs[0x85] = 0x46; 5697141cc406Sopenharmony_ci regs[0x86] = 0x0b; 5698141cc406Sopenharmony_ci regs[0x87] = 0x8c; 5699141cc406Sopenharmony_ci regs[0x88] = 0x10; 5700141cc406Sopenharmony_ci regs[0x8d] = 0x3b; 5701141cc406Sopenharmony_ci regs[0xc0] = 0x00; 5702141cc406Sopenharmony_ci regs[0xc1] = 0xff; 5703141cc406Sopenharmony_ci regs[0xc2] = 0x0f; 5704141cc406Sopenharmony_ci regs[0xc3] = 0xff; 5705141cc406Sopenharmony_ci regs[0xc4] = 0x00; 5706141cc406Sopenharmony_ci regs[0xc5] = 0xf0; 5707141cc406Sopenharmony_ci regs[0xc6] = 0x00; 5708141cc406Sopenharmony_ci regs[0xc7] = 0xff; 5709141cc406Sopenharmony_ci regs[0xc8] = 0x0f; 5710141cc406Sopenharmony_ci regs[0xc9] = 0xff; 5711141cc406Sopenharmony_ci regs[0xca] = 0xff; 5712141cc406Sopenharmony_ci regs[0xcb] = 0xf1; 5713141cc406Sopenharmony_ci regs[0xcc] = 0xff; 5714141cc406Sopenharmony_ci regs[0xcd] = 0x00; 5715141cc406Sopenharmony_ci regs[0xce] = 0xf0; 5716141cc406Sopenharmony_ci regs[0xcf] = 0xed; 5717141cc406Sopenharmony_ci regs[0xd0] = 0xef; 5718141cc406Sopenharmony_ci regs[0xd1] = 0xe2; 5719141cc406Sopenharmony_ci regs[0xd2] = 0x03; 5720141cc406Sopenharmony_ci /* regs[0xd3] = 0x17; */ 5721141cc406Sopenharmony_ci regs[0xd4] = 0x01; 5722141cc406Sopenharmony_ci /* regs[0xe5] = 0xc9; 5723141cc406Sopenharmony_ci regs[0xe6] = 0x01; 0x01c9=457 */ 5724141cc406Sopenharmony_ci exposure=457; 5725141cc406Sopenharmony_ci break; 5726141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 5727141cc406Sopenharmony_ci DBG (DBG_io, 5728141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 300 dpi\n"); 5729141cc406Sopenharmony_ci timing=0x012e; 5730141cc406Sopenharmony_ci regs[0x85] = 0x8c; 5731141cc406Sopenharmony_ci regs[0x86] = 0x10; 5732141cc406Sopenharmony_ci regs[0x87] = 0x18; 5733141cc406Sopenharmony_ci regs[0x88] = 0x1b; 5734141cc406Sopenharmony_ci 5735141cc406Sopenharmony_ci regs[0x8d] = 0xde; 5736141cc406Sopenharmony_ci regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to 5737141cc406Sopenharmony_ci the scanned width 1de => 5100 wide scan */ 5738141cc406Sopenharmony_ci 5739141cc406Sopenharmony_ci regs[0xc0] = 0xff; 5740141cc406Sopenharmony_ci regs[0xc1] = 0x0f; 5741141cc406Sopenharmony_ci regs[0xc2] = 0x00; 5742141cc406Sopenharmony_ci regs[0xc9] = 0x00; 5743141cc406Sopenharmony_ci regs[0xca] = 0x0e; 5744141cc406Sopenharmony_ci regs[0xcb] = 0x00; 5745141cc406Sopenharmony_ci regs[0xcc] = 0x00; 5746141cc406Sopenharmony_ci regs[0xcd] = 0xf0; 5747141cc406Sopenharmony_ci regs[0xce] = 0xff; 5748141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 5749141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 5750141cc406Sopenharmony_ci 5751141cc406Sopenharmony_ci regs[0xd1] = 0xea; 5752141cc406Sopenharmony_ci regs[0xd2] = 0x0b; 5753141cc406Sopenharmony_ci 5754141cc406Sopenharmony_ci /* regs[0xd3] = 0x17; */ 5755141cc406Sopenharmony_ci regs[0xd4] = 0x01; 5756141cc406Sopenharmony_ci /* regs[0xe5] = 0xc9; 5757141cc406Sopenharmony_ci regs[0xe6] = 0x01; 0x1c9=457 */ 5758141cc406Sopenharmony_ci exposure=457; 5759141cc406Sopenharmony_ci break; 5760141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 5761141cc406Sopenharmony_ci DBG (DBG_io, 5762141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 300 dpi\n"); 5763141cc406Sopenharmony_ci timing=0x022b; 5764141cc406Sopenharmony_ci regs[0x85] = 0x18; 5765141cc406Sopenharmony_ci regs[0x86] = 0x1b; 5766141cc406Sopenharmony_ci regs[0x87] = 0x30; 5767141cc406Sopenharmony_ci regs[0x88] = 0x30; 5768141cc406Sopenharmony_ci regs[0x8d] = 0xef; 5769141cc406Sopenharmony_ci regs[0xc0] = 0x00; 5770141cc406Sopenharmony_ci regs[0xc1] = 0xff; 5771141cc406Sopenharmony_ci regs[0xc2] = 0x0f; 5772141cc406Sopenharmony_ci regs[0xc3] = 0xff; 5773141cc406Sopenharmony_ci regs[0xc4] = 0x00; 5774141cc406Sopenharmony_ci regs[0xc5] = 0xf0; 5775141cc406Sopenharmony_ci regs[0xc6] = 0x00; 5776141cc406Sopenharmony_ci regs[0xc7] = 0xff; 5777141cc406Sopenharmony_ci regs[0xc8] = 0x0f; 5778141cc406Sopenharmony_ci regs[0xc9] = 0xff; 5779141cc406Sopenharmony_ci regs[0xca] = 0xff; 5780141cc406Sopenharmony_ci regs[0xcb] = 0xf1; 5781141cc406Sopenharmony_ci regs[0xcc] = 0xff; 5782141cc406Sopenharmony_ci regs[0xcd] = 0x00; 5783141cc406Sopenharmony_ci regs[0xce] = 0xf0; 5784141cc406Sopenharmony_ci regs[0xcf] = 0xed; 5785141cc406Sopenharmony_ci regs[0xd0] = 0xef; 5786141cc406Sopenharmony_ci regs[0xd1] = 0xe2; 5787141cc406Sopenharmony_ci regs[0xd2] = 0x03; 5788141cc406Sopenharmony_ci /* regs[0xd3] = 0x17; */ 5789141cc406Sopenharmony_ci regs[0xd4] = 0x01; 5790141cc406Sopenharmony_ci /* 0x0393 = 915 = 2*457+1 */ 5791141cc406Sopenharmony_ci exposure=915; 5792141cc406Sopenharmony_ci break; 5793141cc406Sopenharmony_ci 5794141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 5795141cc406Sopenharmony_ci DBG (DBG_io, 5796141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 300 dpi\n"); 5797141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5798141cc406Sopenharmony_ci break; 5799141cc406Sopenharmony_ci } 5800141cc406Sopenharmony_ci break; 5801141cc406Sopenharmony_ci 5802141cc406Sopenharmony_ci case 600: 5803141cc406Sopenharmony_ci switch (dev->sensor) 5804141cc406Sopenharmony_ci { 5805141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 5806141cc406Sopenharmony_ci DBG (DBG_io, 5807141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 600 dpi\n"); 5808141cc406Sopenharmony_ci regs[0x34] = 0x10; 5809141cc406Sopenharmony_ci 5810141cc406Sopenharmony_ci regs[0x72] = 0x3a; 5811141cc406Sopenharmony_ci regs[0x73] = 0x15; 5812141cc406Sopenharmony_ci regs[0x74] = 0x62; 5813141cc406Sopenharmony_ci 5814141cc406Sopenharmony_ci timing=0x022b; 5815141cc406Sopenharmony_ci 5816141cc406Sopenharmony_ci regs[0x85] = 0x18; 5817141cc406Sopenharmony_ci regs[0x86] = 0x1b; 5818141cc406Sopenharmony_ci 5819141cc406Sopenharmony_ci regs[0x87] = 0x30; 5820141cc406Sopenharmony_ci regs[0x88] = 0x30; 5821141cc406Sopenharmony_ci 5822141cc406Sopenharmony_ci regs[0x8d] = 0xde; 5823141cc406Sopenharmony_ci regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to 5824141cc406Sopenharmony_ci the scanned width 1de => 5100 wide scan */ 5825141cc406Sopenharmony_ci regs[0xc0] = 0xff; 5826141cc406Sopenharmony_ci regs[0xc1] = 0xff; 5827141cc406Sopenharmony_ci regs[0xc2] = 0xff; 5828141cc406Sopenharmony_ci regs[0xc3] = 0x00; 5829141cc406Sopenharmony_ci regs[0xc4] = 0xf0; 5830141cc406Sopenharmony_ci regs[0xc7] = 0x0f; 5831141cc406Sopenharmony_ci regs[0xc8] = 0x00; 5832141cc406Sopenharmony_ci regs[0xcb] = 0xe0; 5833141cc406Sopenharmony_ci regs[0xcc] = 0xff; 5834141cc406Sopenharmony_ci regs[0xcd] = 0xff; 5835141cc406Sopenharmony_ci regs[0xce] = 0xff; 5836141cc406Sopenharmony_ci regs[0xcf] = 0xe9; 5837141cc406Sopenharmony_ci regs[0xd0] = 0xeb; 5838141cc406Sopenharmony_ci 5839141cc406Sopenharmony_ci regs[0xd7] = 0x14; 5840141cc406Sopenharmony_ci 5841141cc406Sopenharmony_ci /* regs[0xe5] = 0x93; 5842141cc406Sopenharmony_ci regs[0xe6] = 0x03; 0x393=915 = 457*2+1 */ 5843141cc406Sopenharmony_ci exposure=915; 5844141cc406Sopenharmony_ci break; 5845141cc406Sopenharmony_ci 5846141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 5847141cc406Sopenharmony_ci DBG (DBG_io, 5848141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 600 dpi\n"); 5849141cc406Sopenharmony_ci *light &= 0xfb; /* clear bit 2 */ 5850141cc406Sopenharmony_ci regs[0x16] = 0x07; 5851141cc406Sopenharmony_ci regs[0x33] = 0x83; /* 0x86 */ 5852141cc406Sopenharmony_ci regs[0x34] = 0x10; 5853141cc406Sopenharmony_ci regs[0x50] = 0x00; /* 0x18 */ 5854141cc406Sopenharmony_ci regs[0x64] = 0x01; /* 0x02 */ 5855141cc406Sopenharmony_ci regs[0x65] = 0x20; /* 0x10 */ 5856141cc406Sopenharmony_ci 5857141cc406Sopenharmony_ci regs[0x72] = 0x3a; 5858141cc406Sopenharmony_ci regs[0x73] = 0x15; 5859141cc406Sopenharmony_ci regs[0x74] = 0x62; 5860141cc406Sopenharmony_ci 5861141cc406Sopenharmony_ci regs[0x85] = 0x00; 5862141cc406Sopenharmony_ci regs[0x86] = 0x06; 5863141cc406Sopenharmony_ci 5864141cc406Sopenharmony_ci regs[0x87] = 0x00; 5865141cc406Sopenharmony_ci regs[0x88] = 0x06; 5866141cc406Sopenharmony_ci 5867141cc406Sopenharmony_ci regs[0x8d] = 0x00; 5868141cc406Sopenharmony_ci regs[0x8e] = 0x60; /* XXX STEF XXX */ 5869141cc406Sopenharmony_ci 5870141cc406Sopenharmony_ci regs[0xc0] = 0xf8; 5871141cc406Sopenharmony_ci regs[0xc1] = 0x7f; 5872141cc406Sopenharmony_ci regs[0xc2] = 0x00; 5873141cc406Sopenharmony_ci regs[0xc3] = 0xf8; 5874141cc406Sopenharmony_ci regs[0xc4] = 0x7f; 5875141cc406Sopenharmony_ci regs[0xc5] = 0x00; 5876141cc406Sopenharmony_ci regs[0xc6] = 0xf8; 5877141cc406Sopenharmony_ci regs[0xc7] = 0x7f; 5878141cc406Sopenharmony_ci regs[0xc8] = 0x00; 5879141cc406Sopenharmony_ci regs[0xc9] = 0xff; 5880141cc406Sopenharmony_ci regs[0xca] = 0x8f; 5881141cc406Sopenharmony_ci regs[0xcb] = 0xff; 5882141cc406Sopenharmony_ci regs[0xcc] = 0x07; 5883141cc406Sopenharmony_ci regs[0xcd] = 0x80; 5884141cc406Sopenharmony_ci regs[0xce] = 0xff; 5885141cc406Sopenharmony_ci regs[0xcf] = 0xf2; 5886141cc406Sopenharmony_ci regs[0xd0] = 0xf4; 5887141cc406Sopenharmony_ci regs[0xd1] = 0xe7; 5888141cc406Sopenharmony_ci regs[0xd2] = 0x08; 5889141cc406Sopenharmony_ci regs[0xd3] = 0x0e; 5890141cc406Sopenharmony_ci regs[0xd4] = 0x10; 5891141cc406Sopenharmony_ci regs[0xd7] = 0x31; 5892141cc406Sopenharmony_ci 5893141cc406Sopenharmony_ci timing=0x0032; 5894141cc406Sopenharmony_ci exposure=915; 5895141cc406Sopenharmony_ci break; 5896141cc406Sopenharmony_ci 5897141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 5898141cc406Sopenharmony_ci DBG (DBG_io, 5899141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 600 dpi\n"); 5900141cc406Sopenharmony_ci *light = 0x23; 5901141cc406Sopenharmony_ci 5902141cc406Sopenharmony_ci regs[0x13] = 0x39; 5903141cc406Sopenharmony_ci regs[0x14] = 0xf0; 5904141cc406Sopenharmony_ci regs[0x15] = 0x29; 5905141cc406Sopenharmony_ci regs[0x16] = 0x0f; 5906141cc406Sopenharmony_ci regs[0x17] = 0x10; 5907141cc406Sopenharmony_ci regs[0x23] = 0x00; 5908141cc406Sopenharmony_ci regs[0x34] = 0xf0; 5909141cc406Sopenharmony_ci regs[0x36] = 0x29; 5910141cc406Sopenharmony_ci regs[0x39] = 0x00; 5911141cc406Sopenharmony_ci regs[0x72] = 0x3a; 5912141cc406Sopenharmony_ci regs[0x73] = 0x15; 5913141cc406Sopenharmony_ci regs[0x74] = 0x62; 5914141cc406Sopenharmony_ci timing=0x0426; 5915141cc406Sopenharmony_ci regs[0x85] = 0x30; 5916141cc406Sopenharmony_ci regs[0x86] = 0x30; 5917141cc406Sopenharmony_ci regs[0x87] = 0x60; 5918141cc406Sopenharmony_ci regs[0x88] = 0x5a; 5919141cc406Sopenharmony_ci regs[0x8d] = 0xde; 5920141cc406Sopenharmony_ci regs[0x8e] = 0x61; 5921141cc406Sopenharmony_ci regs[0xc0] = 0xf8; 5922141cc406Sopenharmony_ci regs[0xc1] = 0x7f; 5923141cc406Sopenharmony_ci regs[0xc2] = 0x00; 5924141cc406Sopenharmony_ci regs[0xc3] = 0xf8; 5925141cc406Sopenharmony_ci regs[0xc4] = 0x7f; 5926141cc406Sopenharmony_ci regs[0xc5] = 0x00; 5927141cc406Sopenharmony_ci regs[0xc6] = 0xf8; 5928141cc406Sopenharmony_ci regs[0xc7] = 0x7f; 5929141cc406Sopenharmony_ci regs[0xc8] = 0x00; 5930141cc406Sopenharmony_ci regs[0xc9] = 0xff; 5931141cc406Sopenharmony_ci regs[0xca] = 0x8f; 5932141cc406Sopenharmony_ci regs[0xcb] = 0xff; 5933141cc406Sopenharmony_ci regs[0xcc] = 0x07; 5934141cc406Sopenharmony_ci regs[0xcd] = 0x80; 5935141cc406Sopenharmony_ci regs[0xce] = 0xff; 5936141cc406Sopenharmony_ci regs[0xcf] = 0xf2; 5937141cc406Sopenharmony_ci regs[0xd0] = 0xf4; 5938141cc406Sopenharmony_ci regs[0xd1] = 0xe7; 5939141cc406Sopenharmony_ci regs[0xd2] = 0x08; 5940141cc406Sopenharmony_ci regs[0xd3] = 0x0e; 5941141cc406Sopenharmony_ci regs[0xd4] = 0x10; 5942141cc406Sopenharmony_ci regs[0xd7] = 0x31; 5943141cc406Sopenharmony_ci regs[0xe2] = 0x02; 5944141cc406Sopenharmony_ci exposure=1832; 5945141cc406Sopenharmony_ci 5946141cc406Sopenharmony_ci break; 5947141cc406Sopenharmony_ci 5948141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 5949141cc406Sopenharmony_ci DBG (DBG_io, 5950141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n"); 5951141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 5952141cc406Sopenharmony_ci break; 5953141cc406Sopenharmony_ci } 5954141cc406Sopenharmony_ci break; 5955141cc406Sopenharmony_ci 5956141cc406Sopenharmony_ci case 1200: 5957141cc406Sopenharmony_ci switch (dev->sensor) 5958141cc406Sopenharmony_ci { 5959141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 5960141cc406Sopenharmony_ci DBG (DBG_io, 5961141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 1200 dpi\n"); 5962141cc406Sopenharmony_ci regs[0x34] = 0xf0; 5963141cc406Sopenharmony_ci regs[0x40] = 0xa0; 5964141cc406Sopenharmony_ci 5965141cc406Sopenharmony_ci timing=0x0426; 5966141cc406Sopenharmony_ci 5967141cc406Sopenharmony_ci regs[0x85] = 0x30; 5968141cc406Sopenharmony_ci regs[0x86] = 0x30; 5969141cc406Sopenharmony_ci 5970141cc406Sopenharmony_ci regs[0x87] = 0x60; 5971141cc406Sopenharmony_ci regs[0x88] = 0x5a; 5972141cc406Sopenharmony_ci 5973141cc406Sopenharmony_ci regs[0x8d] = 0xbd; 5974141cc406Sopenharmony_ci regs[0x8e] = 0x63; 5975141cc406Sopenharmony_ci 5976141cc406Sopenharmony_ci regs[0xc0] = 0xff; 5977141cc406Sopenharmony_ci regs[0xc1] = 0xff; 5978141cc406Sopenharmony_ci regs[0xc2] = 0xff; 5979141cc406Sopenharmony_ci regs[0xc4] = 0x0f; 5980141cc406Sopenharmony_ci regs[0xc5] = 0x00; 5981141cc406Sopenharmony_ci regs[0xc6] = 0x00; 5982141cc406Sopenharmony_ci regs[0xc7] = 0xf0; 5983141cc406Sopenharmony_ci regs[0xc9] = 0x00; 5984141cc406Sopenharmony_ci regs[0xca] = 0x0e; 5985141cc406Sopenharmony_ci regs[0xcb] = 0x00; 5986141cc406Sopenharmony_ci regs[0xcc] = 0xff; 5987141cc406Sopenharmony_ci regs[0xcd] = 0xff; 5988141cc406Sopenharmony_ci regs[0xce] = 0xff; 5989141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 5990141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 5991141cc406Sopenharmony_ci regs[0xd1] = 0xea; 5992141cc406Sopenharmony_ci regs[0xd2] = 0x0b; 5993141cc406Sopenharmony_ci /* regs[0xd3] = 0x17; */ 5994141cc406Sopenharmony_ci regs[0xd4] = 0xc1; 5995141cc406Sopenharmony_ci regs[0xd7] = 0x14; 5996141cc406Sopenharmony_ci regs[0xd8] = 0xa4; 5997141cc406Sopenharmony_ci /* regs[0xe5] = 0x28; 5998141cc406Sopenharmony_ci regs[0xe6] = 0x07; 0x728=1832=915*2+2 */ 5999141cc406Sopenharmony_ci exposure=1832; 6000141cc406Sopenharmony_ci break; 6001141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 6002141cc406Sopenharmony_ci DBG (DBG_io, 6003141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 1200 dpi\n"); 6004141cc406Sopenharmony_ci regs[0x34] = 0x10; 6005141cc406Sopenharmony_ci regs[0x40] = 0xa0; 6006141cc406Sopenharmony_ci 6007141cc406Sopenharmony_ci timing=0x00b0; 6008141cc406Sopenharmony_ci exposure=1832; 6009141cc406Sopenharmony_ci 6010141cc406Sopenharmony_ci /* XXX STEF XXX */ 6011141cc406Sopenharmony_ci regs[0x85] = 0x46; 6012141cc406Sopenharmony_ci regs[0x86] = 0x0b; 6013141cc406Sopenharmony_ci 6014141cc406Sopenharmony_ci regs[0x87] = 0x8c; 6015141cc406Sopenharmony_ci regs[0x88] = 0x10; 6016141cc406Sopenharmony_ci 6017141cc406Sopenharmony_ci regs[0x8e] = 0x3b; 6018141cc406Sopenharmony_ci regs[0x8d] = 0x60; 6019141cc406Sopenharmony_ci 6020141cc406Sopenharmony_ci regs[0xc1] = 0xff; 6021141cc406Sopenharmony_ci regs[0xce] = 0xff; 6022141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 6023141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 6024141cc406Sopenharmony_ci regs[0x33] = 0x83; 6025141cc406Sopenharmony_ci regs[0x50] = 0x00; 6026141cc406Sopenharmony_ci regs[0x64] = 0x01; 6027141cc406Sopenharmony_ci regs[0x65] = 0x20; 6028141cc406Sopenharmony_ci regs[0x8d] = 0xbc; 6029141cc406Sopenharmony_ci regs[0xc0] = 0xe0; 6030141cc406Sopenharmony_ci regs[0xc2] = 0x01; 6031141cc406Sopenharmony_ci regs[0xc3] = 0x1f; 6032141cc406Sopenharmony_ci regs[0xc4] = 0x00; 6033141cc406Sopenharmony_ci regs[0xc5] = 0xfe; 6034141cc406Sopenharmony_ci regs[0xc6] = 0xff; 6035141cc406Sopenharmony_ci regs[0xc7] = 0xff; 6036141cc406Sopenharmony_ci regs[0xc8] = 0x00; 6037141cc406Sopenharmony_ci regs[0xc9] = 0x3f; 6038141cc406Sopenharmony_ci regs[0xca] = 0xfe; 6039141cc406Sopenharmony_ci regs[0xcb] = 0xff; 6040141cc406Sopenharmony_ci regs[0xcc] = 0x00; 6041141cc406Sopenharmony_ci regs[0xcd] = 0x00; 6042141cc406Sopenharmony_ci regs[0xd1] = 0xec; 6043141cc406Sopenharmony_ci regs[0xd2] = 0x0d; 6044141cc406Sopenharmony_ci regs[0xd3] = 0x05; 6045141cc406Sopenharmony_ci regs[0xd4] = 0x67; 6046141cc406Sopenharmony_ci regs[0xd7] = 0x10; 6047141cc406Sopenharmony_ci regs[0xd8] = 0x52; 6048141cc406Sopenharmony_ci break; 6049141cc406Sopenharmony_ci 6050141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 6051141cc406Sopenharmony_ci DBG (DBG_io, 6052141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 1200 dpi\n"); 6053141cc406Sopenharmony_ci regs[0x13] = 0x39; 6054141cc406Sopenharmony_ci regs[0x14] = 0xf0; 6055141cc406Sopenharmony_ci regs[0x15] = 0x29; 6056141cc406Sopenharmony_ci regs[0x16] = 0x0f; 6057141cc406Sopenharmony_ci regs[0x17] = 0x10; 6058141cc406Sopenharmony_ci regs[0x23] = 0x00; 6059141cc406Sopenharmony_ci regs[0x34] = 0xf0; 6060141cc406Sopenharmony_ci regs[0x36] = 0x29; 6061141cc406Sopenharmony_ci regs[0x39] = 0x00; 6062141cc406Sopenharmony_ci regs[0x40] = 0xa0; 6063141cc406Sopenharmony_ci timing=0x0426; 6064141cc406Sopenharmony_ci regs[0x85] = 0x30; 6065141cc406Sopenharmony_ci regs[0x86] = 0x30; 6066141cc406Sopenharmony_ci regs[0x87] = 0x60; 6067141cc406Sopenharmony_ci regs[0x88] = 0x5a; 6068141cc406Sopenharmony_ci regs[0x8d] = 0xde; 6069141cc406Sopenharmony_ci regs[0x8e] = 0x61; 6070141cc406Sopenharmony_ci regs[0xc0] = 0xe0; 6071141cc406Sopenharmony_ci regs[0xc1] = 0xff; 6072141cc406Sopenharmony_ci regs[0xc2] = 0x01; 6073141cc406Sopenharmony_ci regs[0xc3] = 0x1f; 6074141cc406Sopenharmony_ci regs[0xc4] = 0x00; 6075141cc406Sopenharmony_ci regs[0xc5] = 0xfe; 6076141cc406Sopenharmony_ci regs[0xc6] = 0xff; 6077141cc406Sopenharmony_ci regs[0xc7] = 0xff; 6078141cc406Sopenharmony_ci regs[0xc8] = 0x00; 6079141cc406Sopenharmony_ci regs[0xc9] = 0x3f; 6080141cc406Sopenharmony_ci regs[0xca] = 0xfe; 6081141cc406Sopenharmony_ci regs[0xcb] = 0xff; 6082141cc406Sopenharmony_ci regs[0xcc] = 0x00; 6083141cc406Sopenharmony_ci regs[0xcd] = 0x00; 6084141cc406Sopenharmony_ci regs[0xce] = 0xff; 6085141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 6086141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 6087141cc406Sopenharmony_ci regs[0xd1] = 0xec; 6088141cc406Sopenharmony_ci regs[0xd2] = 0x0d; 6089141cc406Sopenharmony_ci /* regs[0xd3] = 0x05; */ 6090141cc406Sopenharmony_ci regs[0xd4] = 0x67; 6091141cc406Sopenharmony_ci regs[0xd7] = 0x10; 6092141cc406Sopenharmony_ci regs[0xd8] = 0x52; 6093141cc406Sopenharmony_ci regs[0xe2] = 0x02; 6094141cc406Sopenharmony_ci *light = 0x23; 6095141cc406Sopenharmony_ci exposure=3665; 6096141cc406Sopenharmony_ci break; 6097141cc406Sopenharmony_ci 6098141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 6099141cc406Sopenharmony_ci DBG (DBG_io, 6100141cc406Sopenharmony_ci "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n"); 6101141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 6102141cc406Sopenharmony_ci break; 6103141cc406Sopenharmony_ci } 6104141cc406Sopenharmony_ci break; 6105141cc406Sopenharmony_ci } 6106141cc406Sopenharmony_ci 6107141cc406Sopenharmony_ci /* apply computed settings */ 6108141cc406Sopenharmony_ci SET_DOUBLE (regs, EXPOSURE_REG, exposure); 6109141cc406Sopenharmony_ci SET_DOUBLE (regs, TIMING_REG, timing); 6110141cc406Sopenharmony_ci SET_DOUBLE (regs, TIMING1_REG, timing+1); 6111141cc406Sopenharmony_ci SET_DOUBLE (regs, TIMING2_REG, timing+2); 6112141cc406Sopenharmony_ci 6113141cc406Sopenharmony_ci /* in logs, the driver use the computed offset minus 2 */ 6114141cc406Sopenharmony_ci sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset); 6115141cc406Sopenharmony_ci sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain); 6116141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (regs, 1, 1 + lines, dev->xstart, dev->xstart + dev->pixels); 6117141cc406Sopenharmony_ci 6118141cc406Sopenharmony_ci DBG (DBG_proc, "setup_shading_calibration: exit\n"); 6119141cc406Sopenharmony_ci return status; 6120141cc406Sopenharmony_ci} 6121141cc406Sopenharmony_ci 6122141cc406Sopenharmony_ci/* 6123141cc406Sopenharmony_ci * do shading calibration 6124141cc406Sopenharmony_ci * We scan a 637 pixels by 66 linesxoffset=24 , xend=661, pixels=637 6125141cc406Sopenharmony_ciy offset=1 , yend=67, lines =66 6126141cc406Sopenharmony_ci */ 6127141cc406Sopenharmony_cistatic SANE_Status 6128141cc406Sopenharmony_cishading_calibration (struct Rts8891_Device *dev, SANE_Bool color, int mode, int light) 6129141cc406Sopenharmony_ci{ 6130141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 6131141cc406Sopenharmony_ci int width; 6132141cc406Sopenharmony_ci int lines = 66; 6133141cc406Sopenharmony_ci SANE_Byte format; 6134141cc406Sopenharmony_ci int size; 6135141cc406Sopenharmony_ci int status1; 6136141cc406Sopenharmony_ci int x, y, sum; 6137141cc406Sopenharmony_ci SANE_Byte *image = NULL; 6138141cc406Sopenharmony_ci FILE *dbg = NULL; 6139141cc406Sopenharmony_ci 6140141cc406Sopenharmony_ci DBG (DBG_proc, "shading_calibration: start\n"); 6141141cc406Sopenharmony_ci DBG (DBG_info, "shading_calibration: sensor type is %s (%d)\n", 6142141cc406Sopenharmony_ci sensor_name (dev->sensor), dev->sensor); 6143141cc406Sopenharmony_ci 6144141cc406Sopenharmony_ci width = dev->pixels; 6145141cc406Sopenharmony_ci size = lines * dev->bytes_per_line; 6146141cc406Sopenharmony_ci 6147141cc406Sopenharmony_ci image = (SANE_Byte *) malloc (size); 6148141cc406Sopenharmony_ci if (image == NULL) 6149141cc406Sopenharmony_ci { 6150141cc406Sopenharmony_ci DBG (DBG_error, 6151141cc406Sopenharmony_ci "shading_calibration: failed to allocate memory for image\n"); 6152141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6153141cc406Sopenharmony_ci } 6154141cc406Sopenharmony_ci if (dev->shading_data != NULL) 6155141cc406Sopenharmony_ci free (dev->shading_data); 6156141cc406Sopenharmony_ci dev->shading_data = (unsigned char *) malloc (dev->bytes_per_line); 6157141cc406Sopenharmony_ci if (dev->shading_data == NULL) 6158141cc406Sopenharmony_ci { 6159141cc406Sopenharmony_ci free (image); 6160141cc406Sopenharmony_ci DBG (DBG_error, 6161141cc406Sopenharmony_ci "shading_calibration: failed to allocate memory for data\n"); 6162141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6163141cc406Sopenharmony_ci } 6164141cc406Sopenharmony_ci 6165141cc406Sopenharmony_ci /* set up registers */ 6166141cc406Sopenharmony_ci status=setup_shading_calibration(dev, mode, &light, &status1, dev->regs); 6167141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 6168141cc406Sopenharmony_ci { 6169141cc406Sopenharmony_ci DBG (DBG_error, "shading_calibration: failed to set up registers\n"); 6170141cc406Sopenharmony_ci free (dev->shading_data); 6171141cc406Sopenharmony_ci dev->shading_data = NULL; 6172141cc406Sopenharmony_ci free (image); 6173141cc406Sopenharmony_ci return status; 6174141cc406Sopenharmony_ci } 6175141cc406Sopenharmony_ci 6176141cc406Sopenharmony_ci /* scan shading area */ 6177141cc406Sopenharmony_ci sanei_rts88xx_set_status (dev->devnum, dev->regs, status1, light); 6178141cc406Sopenharmony_ci format = rts8891_data_format (dev->xdpi, dev->sensor); 6179141cc406Sopenharmony_ci status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, format, size, image); 6180141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 6181141cc406Sopenharmony_ci { 6182141cc406Sopenharmony_ci DBG (DBG_error, "shading_calibration: failed scan shading area\n"); 6183141cc406Sopenharmony_ci free (dev->shading_data); 6184141cc406Sopenharmony_ci dev->shading_data = NULL; 6185141cc406Sopenharmony_ci free (image); 6186141cc406Sopenharmony_ci return status; 6187141cc406Sopenharmony_ci } 6188141cc406Sopenharmony_ci 6189141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 6190141cc406Sopenharmony_ci { 6191141cc406Sopenharmony_ci dbg = fopen ("shading.pnm", "wb"); 6192141cc406Sopenharmony_ci if (color) 6193141cc406Sopenharmony_ci { 6194141cc406Sopenharmony_ci fprintf (dbg, "P6\n%d %d\n255\n", width, lines); 6195141cc406Sopenharmony_ci fwrite (image, width * 3, lines, dbg); 6196141cc406Sopenharmony_ci } 6197141cc406Sopenharmony_ci else 6198141cc406Sopenharmony_ci { 6199141cc406Sopenharmony_ci fprintf (dbg, "P5\n%d %d\n255\n", width, lines); 6200141cc406Sopenharmony_ci fwrite (image, width, lines, dbg); 6201141cc406Sopenharmony_ci } 6202141cc406Sopenharmony_ci fclose (dbg); 6203141cc406Sopenharmony_ci } 6204141cc406Sopenharmony_ci 6205141cc406Sopenharmony_ci /* now we can compute shading calibration data */ 6206141cc406Sopenharmony_ci /* we average each row */ 6207141cc406Sopenharmony_ci /* we take the maximum of each row */ 6208141cc406Sopenharmony_ci /* we skip first 3 lines and last 10 lines due to some bugs */ 6209141cc406Sopenharmony_ci if (color) 6210141cc406Sopenharmony_ci { 6211141cc406Sopenharmony_ci width = width * 3; 6212141cc406Sopenharmony_ci } 6213141cc406Sopenharmony_ci for (x = 0; x < width; x++) 6214141cc406Sopenharmony_ci { 6215141cc406Sopenharmony_ci sum = 0; 6216141cc406Sopenharmony_ci for (y = 3; y < lines - 10; y++) 6217141cc406Sopenharmony_ci { 6218141cc406Sopenharmony_ci sum += image[x + y * width]; 6219141cc406Sopenharmony_ci } 6220141cc406Sopenharmony_ci dev->shading_data[x] = sum / (lines - 13); 6221141cc406Sopenharmony_ci } 6222141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 6223141cc406Sopenharmony_ci { 6224141cc406Sopenharmony_ci dbg = fopen ("shading_data.pnm", "wb"); 6225141cc406Sopenharmony_ci if (color) 6226141cc406Sopenharmony_ci { 6227141cc406Sopenharmony_ci fprintf (dbg, "P6\n%d %d\n255\n", width / 3, 1); 6228141cc406Sopenharmony_ci fwrite (dev->shading_data, width, 1, dbg); 6229141cc406Sopenharmony_ci } 6230141cc406Sopenharmony_ci else 6231141cc406Sopenharmony_ci { 6232141cc406Sopenharmony_ci fprintf (dbg, "P5\n%d %d\n255\n", width, 1); 6233141cc406Sopenharmony_ci fwrite (dev->shading_data, width, 1, dbg); 6234141cc406Sopenharmony_ci } 6235141cc406Sopenharmony_ci fclose (dbg); 6236141cc406Sopenharmony_ci } 6237141cc406Sopenharmony_ci 6238141cc406Sopenharmony_ci free (image); 6239141cc406Sopenharmony_ci DBG (DBG_proc, "shading_calibration: exit\n"); 6240141cc406Sopenharmony_ci return status; 6241141cc406Sopenharmony_ci} 6242141cc406Sopenharmony_ci 6243141cc406Sopenharmony_cistatic void 6244141cc406Sopenharmony_cifill_gamma (SANE_Byte * calibration, int *idx, SANE_Word * gamma) 6245141cc406Sopenharmony_ci{ 6246141cc406Sopenharmony_ci int i; 6247141cc406Sopenharmony_ci 6248141cc406Sopenharmony_ci calibration[*idx] = 0; 6249141cc406Sopenharmony_ci (*idx)++; 6250141cc406Sopenharmony_ci for (i = 0; i < 255; i++) 6251141cc406Sopenharmony_ci { 6252141cc406Sopenharmony_ci calibration[*idx] = gamma[i]; 6253141cc406Sopenharmony_ci /* escape 0xaa with 0 */ 6254141cc406Sopenharmony_ci if (calibration[*idx] == 0xaa) 6255141cc406Sopenharmony_ci { 6256141cc406Sopenharmony_ci (*idx)++; 6257141cc406Sopenharmony_ci calibration[*idx] = 0; 6258141cc406Sopenharmony_ci } 6259141cc406Sopenharmony_ci (*idx)++; 6260141cc406Sopenharmony_ci calibration[*idx] = gamma[i]; 6261141cc406Sopenharmony_ci /* escape 0xaa with 0 */ 6262141cc406Sopenharmony_ci if (calibration[*idx] == 0xaa) 6263141cc406Sopenharmony_ci { 6264141cc406Sopenharmony_ci (*idx)++; 6265141cc406Sopenharmony_ci calibration[*idx] = 0; 6266141cc406Sopenharmony_ci } 6267141cc406Sopenharmony_ci (*idx)++; 6268141cc406Sopenharmony_ci } 6269141cc406Sopenharmony_ci calibration[*idx] = 0xff; 6270141cc406Sopenharmony_ci (*idx)++; 6271141cc406Sopenharmony_ci} 6272141cc406Sopenharmony_ci 6273141cc406Sopenharmony_ci/* 6274141cc406Sopenharmony_ci * build and send calibration data which contains gamma table and 6275141cc406Sopenharmony_ci * shading correction coefficient 6276141cc406Sopenharmony_ci * 6277141cc406Sopenharmony_ci */ 6278141cc406Sopenharmony_cistatic SANE_Status 6279141cc406Sopenharmony_cisend_calibration_data (struct Rts8891_Session *session) 6280141cc406Sopenharmony_ci{ 6281141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 6282141cc406Sopenharmony_ci int size, width, data_size; 6283141cc406Sopenharmony_ci SANE_Byte *calibration = NULL, format, val; 6284141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 6285141cc406Sopenharmony_ci int i, idx; 6286141cc406Sopenharmony_ci unsigned int value, red_code, blue_code, green_code; 6287141cc406Sopenharmony_ci FILE *calib = NULL; 6288141cc406Sopenharmony_ci SANE_Word *gamma_r, *gamma_g, *gamma_b; 6289141cc406Sopenharmony_ci 6290141cc406Sopenharmony_ci DBG (DBG_proc, "send_calibration_data: start\n"); 6291141cc406Sopenharmony_ci 6292141cc406Sopenharmony_ci /* 675 pixels at 75 DPI, 16 bits values, 3 color channels */ 6293141cc406Sopenharmony_ci /* 5400 pixels at max sensor 600 dpi */ 6294141cc406Sopenharmony_ci /* 3 16bits 256 value gamma tables plus start/end markers */ 6295141cc406Sopenharmony_ci /* must multiple of 32 */ 6296141cc406Sopenharmony_ci data_size = (675 * dev->xdpi) / 75; 6297141cc406Sopenharmony_ci 6298141cc406Sopenharmony_ci width = dev->pixels; 6299141cc406Sopenharmony_ci 6300141cc406Sopenharmony_ci /* effective data calibration size */ 6301141cc406Sopenharmony_ci size = data_size * 2 * 3 + 3 * (512 + 2); 6302141cc406Sopenharmony_ci size = ((size + 31) / 32) * 32; 6303141cc406Sopenharmony_ci 6304141cc406Sopenharmony_ci DBG (DBG_io, "send_calibration_data: size=%d\n", size); 6305141cc406Sopenharmony_ci 6306141cc406Sopenharmony_ci /* 6307141cc406Sopenharmony_ci * FORMAT: 6308141cc406Sopenharmony_ci * 00 6309141cc406Sopenharmony_ci * 512 bytes gamma table (256 16 bit entry) 6310141cc406Sopenharmony_ci * FF 6311141cc406Sopenharmony_ci * 00 6312141cc406Sopenharmony_ci * 512 bytes gamma table (256 16 bit entry) 6313141cc406Sopenharmony_ci * FF 6314141cc406Sopenharmony_ci * 00 6315141cc406Sopenharmony_ci * 512 bytes gamma table (256 16 bit entry) 6316141cc406Sopenharmony_ci * FF 6317141cc406Sopenharmony_ci * 5400 max shading coefficients at 600 dpi repeated 3 times 6318141cc406Sopenharmony_ci * overall size rounded at 32 bytes multiple 6319141cc406Sopenharmony_ci * 675 CCD elements at 75 DPI. 16 bit per element. 1 or 3 channels. 6320141cc406Sopenharmony_ci * there is a 0xFF marker at end of each coefficients row. 6321141cc406Sopenharmony_ci * a gamma table comes first 6322141cc406Sopenharmony_ci * 75 DPI: 5600=1542+(675)*2*3+8 ->size rounded to 'upper 32' 6323141cc406Sopenharmony_ci * 150 DPI: 9664=675*2*2*3=1542+(675*2)*2*3+22 6324141cc406Sopenharmony_ci * 17760 4 +18 6325141cc406Sopenharmony_ci * 33952 8 +10 6326141cc406Sopenharmony_ci * 65472+896=66368= 16 +26 6327141cc406Sopenharmony_ci * 6328141cc406Sopenharmony_ci * COEFFICIENT 16 bit value 6329141cc406Sopenharmony_ci * first is 00, 0x40, 0x80 or 0xC0 => 10 significant bit 6330141cc406Sopenharmony_ci * coeff*average=K => coeff=K/average 6331141cc406Sopenharmony_ci */ 6332141cc406Sopenharmony_ci 6333141cc406Sopenharmony_ci calibration = (SANE_Byte *) malloc (size); 6334141cc406Sopenharmony_ci if (calibration == NULL) 6335141cc406Sopenharmony_ci { 6336141cc406Sopenharmony_ci DBG (DBG_error, 6337141cc406Sopenharmony_ci "send_calibration_data: failed to allocate memory for calibration data\n"); 6338141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 6339141cc406Sopenharmony_ci } 6340141cc406Sopenharmony_ci memset (calibration, 0x00, size); 6341141cc406Sopenharmony_ci 6342141cc406Sopenharmony_ci /* fill gamma tables first, markers and static gamma table */ 6343141cc406Sopenharmony_ci idx = 0; 6344141cc406Sopenharmony_ci 6345141cc406Sopenharmony_ci /* select red gamma table */ 6346141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_RGB) 6347141cc406Sopenharmony_ci { 6348141cc406Sopenharmony_ci /* 3 different gamma table */ 6349141cc406Sopenharmony_ci gamma_r = session->val[OPT_GAMMA_VECTOR_R].wa; 6350141cc406Sopenharmony_ci gamma_g = session->val[OPT_GAMMA_VECTOR_G].wa; 6351141cc406Sopenharmony_ci gamma_b = session->val[OPT_GAMMA_VECTOR_B].wa; 6352141cc406Sopenharmony_ci } 6353141cc406Sopenharmony_ci else 6354141cc406Sopenharmony_ci { 6355141cc406Sopenharmony_ci /* 3 time the same gamma table */ 6356141cc406Sopenharmony_ci gamma_r = session->val[OPT_GAMMA_VECTOR].wa; 6357141cc406Sopenharmony_ci gamma_g = session->val[OPT_GAMMA_VECTOR].wa; 6358141cc406Sopenharmony_ci gamma_b = session->val[OPT_GAMMA_VECTOR].wa; 6359141cc406Sopenharmony_ci } 6360141cc406Sopenharmony_ci 6361141cc406Sopenharmony_ci fill_gamma (calibration, &idx, gamma_r); 6362141cc406Sopenharmony_ci fill_gamma (calibration, &idx, gamma_g); 6363141cc406Sopenharmony_ci fill_gamma (calibration, &idx, gamma_b); 6364141cc406Sopenharmony_ci 6365141cc406Sopenharmony_ci /* compute calibration coefficients */ 6366141cc406Sopenharmony_ci /* real width != 675 --> 637 6367141cc406Sopenharmony_ci * shading data calibration starts at 1542. There are 3 rows of 16 bits values 6368141cc406Sopenharmony_ci * first row is green calibration 6369141cc406Sopenharmony_ci */ 6370141cc406Sopenharmony_ci 6371141cc406Sopenharmony_ci /* to avoid problems with 0xaa values which must be escaped, we change them 6372141cc406Sopenharmony_ci * into 0xab values, which unnoticeable on scans */ 6373141cc406Sopenharmony_ci for (i = 0; i < width; i++) 6374141cc406Sopenharmony_ci { 6375141cc406Sopenharmony_ci /* average TARGET CODE 3431046 */ 6376141cc406Sopenharmony_ci/* #define RED_SHADING_TARGET_CODE 3000000 6377141cc406Sopenharmony_ci #define GREEN_SHADING_TARGET_CODE 300000 6378141cc406Sopenharmony_ci #define BLUE_SHADING_TARGET_CODE 2800000*/ 6379141cc406Sopenharmony_ci#define RED_SHADING_TARGET_CODE 2800000 6380141cc406Sopenharmony_ci#define GREEN_SHADING_TARGET_CODE 2800000 6381141cc406Sopenharmony_ci#define BLUE_SHADING_TARGET_CODE 2700000 6382141cc406Sopenharmony_ci 6383141cc406Sopenharmony_ci red_code = RED_SHADING_TARGET_CODE; 6384141cc406Sopenharmony_ci green_code = GREEN_SHADING_TARGET_CODE; 6385141cc406Sopenharmony_ci blue_code = BLUE_SHADING_TARGET_CODE; 6386141cc406Sopenharmony_ci 6387141cc406Sopenharmony_ci /* target code debug, will be removed for the release */ 6388141cc406Sopenharmony_ci if (getenv ("RED_CODE") != NULL) 6389141cc406Sopenharmony_ci { 6390141cc406Sopenharmony_ci red_code = atoi (getenv ("RED_CODE")); 6391141cc406Sopenharmony_ci } 6392141cc406Sopenharmony_ci if (getenv ("GREEN_CODE") != NULL) 6393141cc406Sopenharmony_ci { 6394141cc406Sopenharmony_ci blue_code = atoi (getenv ("GREEN_CODE")); 6395141cc406Sopenharmony_ci } 6396141cc406Sopenharmony_ci if (getenv ("BLUE_CODE") != NULL) 6397141cc406Sopenharmony_ci { 6398141cc406Sopenharmony_ci green_code = atoi (getenv ("BLUE_CODE")); 6399141cc406Sopenharmony_ci } 6400141cc406Sopenharmony_ci 6401141cc406Sopenharmony_ci /* correction coefficient is target code divided by average scanned value 6402141cc406Sopenharmony_ci * but it is put in a 16 bits number. Only 10 first bits are significants. 6403141cc406Sopenharmony_ci */ 6404141cc406Sopenharmony_ci /* first color component red data */ 6405141cc406Sopenharmony_ci if (gamma_r[dev->shading_data[i * 3]] < 5) 6406141cc406Sopenharmony_ci value = 0x8000; 6407141cc406Sopenharmony_ci else 6408141cc406Sopenharmony_ci value = red_code / gamma_r[dev->shading_data[i * 3]]; 6409141cc406Sopenharmony_ci val = (SANE_Byte) (value / 256); 6410141cc406Sopenharmony_ci if (val == 0xaa) 6411141cc406Sopenharmony_ci val++; 6412141cc406Sopenharmony_ci calibration[idx + i * 2 + 1] = val; 6413141cc406Sopenharmony_ci calibration[idx + i * 2] = (SANE_Byte) (value % 256) & 0xC0; 6414141cc406Sopenharmony_ci 6415141cc406Sopenharmony_ci /* second color component: green data */ 6416141cc406Sopenharmony_ci if (gamma_r[dev->shading_data[i * 3 + 1]] < 5) 6417141cc406Sopenharmony_ci value = 0x8000; 6418141cc406Sopenharmony_ci else 6419141cc406Sopenharmony_ci value = green_code / gamma_g[dev->shading_data[i * 3 + 1]]; 6420141cc406Sopenharmony_ci val = (SANE_Byte) (value / 256); 6421141cc406Sopenharmony_ci if (val == 0xaa) 6422141cc406Sopenharmony_ci val++; 6423141cc406Sopenharmony_ci calibration[idx + data_size * 2 + i * 2 + 1] = val; 6424141cc406Sopenharmony_ci calibration[idx + data_size * 2 + i * 2] = 6425141cc406Sopenharmony_ci (SANE_Byte) (value % 256) & 0xC0; 6426141cc406Sopenharmony_ci 6427141cc406Sopenharmony_ci /* third color component: blue data */ 6428141cc406Sopenharmony_ci if (gamma_r[dev->shading_data[i * 3 + 2]] < 5) 6429141cc406Sopenharmony_ci value = 0x8000; 6430141cc406Sopenharmony_ci else 6431141cc406Sopenharmony_ci value = blue_code / gamma_b[dev->shading_data[i * 3 + 2]]; 6432141cc406Sopenharmony_ci val = (SANE_Byte) (value / 256); 6433141cc406Sopenharmony_ci if (val == 0xaa) 6434141cc406Sopenharmony_ci val++; 6435141cc406Sopenharmony_ci calibration[idx + data_size * 4 + i * 2 + 1] = val; 6436141cc406Sopenharmony_ci calibration[idx + data_size * 4 + i * 2] = 6437141cc406Sopenharmony_ci (SANE_Byte) (value % 256) & 0xC0; 6438141cc406Sopenharmony_ci } 6439141cc406Sopenharmony_ci 6440141cc406Sopenharmony_ci /* DEEP TRACING */ 6441141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 6442141cc406Sopenharmony_ci { 6443141cc406Sopenharmony_ci calib = fopen ("calibration.hex", "wb"); 6444141cc406Sopenharmony_ci fprintf (calib, "shading_data(%d)=", width); 6445141cc406Sopenharmony_ci for (i = 0; i < width * 3; i++) 6446141cc406Sopenharmony_ci { 6447141cc406Sopenharmony_ci fprintf (calib, "%02x ", dev->shading_data[i]); 6448141cc406Sopenharmony_ci } 6449141cc406Sopenharmony_ci fprintf (calib, "\n"); 6450141cc406Sopenharmony_ci fprintf (calib, "write_mem(0x00,%d)=", size); 6451141cc406Sopenharmony_ci for (i = 0; i < size; i++) 6452141cc406Sopenharmony_ci { 6453141cc406Sopenharmony_ci fprintf (calib, "%02x ", calibration[i]); 6454141cc406Sopenharmony_ci } 6455141cc406Sopenharmony_ci fclose (calib); 6456141cc406Sopenharmony_ci } 6457141cc406Sopenharmony_ci 6458141cc406Sopenharmony_ci /* signals color format/divisor from hardware */ 6459141cc406Sopenharmony_ci format = rts8891_data_format (dev->xdpi, dev->sensor); 6460141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (dev->devnum, 0xd3, &format); 6461141cc406Sopenharmony_ci 6462141cc406Sopenharmony_ci /* for some reason, we have to add 6 to the size for the first write */ 6463141cc406Sopenharmony_ci /* related to the 6 0xaa in gamma table ? */ 6464141cc406Sopenharmony_ci if (size > RTS88XX_MAX_XFER_SIZE) 6465141cc406Sopenharmony_ci { 6466141cc406Sopenharmony_ci status = 6467141cc406Sopenharmony_ci sanei_rts88xx_write_mem (dev->devnum, RTS88XX_MAX_XFER_SIZE, 6, 6468141cc406Sopenharmony_ci calibration); 6469141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 6470141cc406Sopenharmony_ci { 6471141cc406Sopenharmony_ci DBG (DBG_error, 6472141cc406Sopenharmony_ci "send_calibration_data: failed to write calibration data (part 1)\n"); 6473141cc406Sopenharmony_ci return status; 6474141cc406Sopenharmony_ci } 6475141cc406Sopenharmony_ci size -= RTS88XX_MAX_XFER_SIZE; 6476141cc406Sopenharmony_ci status = 6477141cc406Sopenharmony_ci sanei_rts88xx_write_mem (dev->devnum, size, 0, 6478141cc406Sopenharmony_ci calibration + RTS88XX_MAX_XFER_SIZE); 6479141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 6480141cc406Sopenharmony_ci { 6481141cc406Sopenharmony_ci DBG (DBG_error, 6482141cc406Sopenharmony_ci "send_calibration_data: failed to write calibration data (part 2)\n"); 6483141cc406Sopenharmony_ci return status; 6484141cc406Sopenharmony_ci } 6485141cc406Sopenharmony_ci } 6486141cc406Sopenharmony_ci else 6487141cc406Sopenharmony_ci { 6488141cc406Sopenharmony_ci status = sanei_rts88xx_write_mem (dev->devnum, size, 6, calibration); 6489141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 6490141cc406Sopenharmony_ci { 6491141cc406Sopenharmony_ci DBG (DBG_error, 6492141cc406Sopenharmony_ci "send_calibration_data: failed to write calibration data\n"); 6493141cc406Sopenharmony_ci return status; 6494141cc406Sopenharmony_ci } 6495141cc406Sopenharmony_ci } 6496141cc406Sopenharmony_ci 6497141cc406Sopenharmony_ci /* set mem start */ 6498141cc406Sopenharmony_ci dev->regs[0x91] = 0x00; 6499141cc406Sopenharmony_ci dev->regs[0x92] = 0x00; 6500141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x91, dev->regs + 0x91, 2); 6501141cc406Sopenharmony_ci 6502141cc406Sopenharmony_ci free (calibration); 6503141cc406Sopenharmony_ci DBG (DBG_proc, "send_calibration_data: exit\n"); 6504141cc406Sopenharmony_ci return status; 6505141cc406Sopenharmony_ci} 6506141cc406Sopenharmony_ci 6507141cc406Sopenharmony_ci/* move at dev->model->min_ydpi dpi up to the scanning area. Which speeds 6508141cc406Sopenharmony_ci * up scanning 6509141cc406Sopenharmony_ci */ 6510141cc406Sopenharmony_cistatic SANE_Status 6511141cc406Sopenharmony_cimove_to_scan_area (struct Rts8891_Session *session) 6512141cc406Sopenharmony_ci{ 6513141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 6514141cc406Sopenharmony_ci SANE_Byte control; 6515141cc406Sopenharmony_ci SANE_Byte regs[RTS8891_MAX_REGISTERS]; 6516141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 6517141cc406Sopenharmony_ci SANE_Int distance; 6518141cc406Sopenharmony_ci 6519141cc406Sopenharmony_ci DBG (DBG_proc, "move_to_scan_area: start\n"); 6520141cc406Sopenharmony_ci 6521141cc406Sopenharmony_ci /* compute line number to move and fix scan values */ 6522141cc406Sopenharmony_ci distance = ((dev->ystart - 1) * MOVE_DPI) / dev->ydpi; 6523141cc406Sopenharmony_ci dev->ystart = dev->ystart - (distance * dev->ydpi) / MOVE_DPI; 6524141cc406Sopenharmony_ci /* extra lines to let head stop */ 6525141cc406Sopenharmony_ci distance -= 30; 6526141cc406Sopenharmony_ci 6527141cc406Sopenharmony_ci DBG (DBG_proc, "move_to_scan_area: distance=%d, ystart=%d\n", distance, 6528141cc406Sopenharmony_ci dev->ystart); 6529141cc406Sopenharmony_ci 6530141cc406Sopenharmony_ci /* then send move command */ 6531141cc406Sopenharmony_ci rts8891_move (dev, regs, distance, SANE_TRUE); 6532141cc406Sopenharmony_ci 6533141cc406Sopenharmony_ci /* wait for completion */ 6534141cc406Sopenharmony_ci do 6535141cc406Sopenharmony_ci { 6536141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 6537141cc406Sopenharmony_ci } 6538141cc406Sopenharmony_ci while ((control & 0x08) == 0x08); 6539141cc406Sopenharmony_ci 6540141cc406Sopenharmony_ci DBG (DBG_proc, "move_to_scan_area: exit\n"); 6541141cc406Sopenharmony_ci return status; 6542141cc406Sopenharmony_ci} 6543141cc406Sopenharmony_ci 6544141cc406Sopenharmony_ci/* set up the shadow registers for scan, depending on scan parameters */ 6545141cc406Sopenharmony_ci/* the ultimate goal is to have no direct access to registers, but to */ 6546141cc406Sopenharmony_ci/* set them through helper functions */ 6547141cc406Sopenharmony_ci/* NOTE : I couldn't manage to get scans that really uses gray settings. */ 6548141cc406Sopenharmony_ci/* The windows driver is always scanning in color, so we do the same. */ 6549141cc406Sopenharmony_ci/* For now, the only mode that could be done would be 300 dpi gray scan, */ 6550141cc406Sopenharmony_ci/* based on the register settings of find_origin() */ 6551141cc406Sopenharmony_cistatic SANE_Status 6552141cc406Sopenharmony_cisetup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_Byte *status2, SANE_Byte *regs) 6553141cc406Sopenharmony_ci{ 6554141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 6555141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 6556141cc406Sopenharmony_ci int exposure=0; 6557141cc406Sopenharmony_ci int timing=0; 6558141cc406Sopenharmony_ci 6559141cc406Sopenharmony_ci /* only software gray modes for now */ 6560141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_GRAY 6561141cc406Sopenharmony_ci && (session->dev->model->flags & RTS8891_FLAG_EMULATED_GRAY_MODE) == 0) 6562141cc406Sopenharmony_ci { 6563141cc406Sopenharmony_ci DBG (DBG_warn, 6564141cc406Sopenharmony_ci "setup_scan_registers: native gray modes not implemented for this model, failure expected\n"); 6565141cc406Sopenharmony_ci } 6566141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (regs, dev->ystart, dev->ystart + dev->lines, dev->xstart, dev->xstart + dev->pixels); 6567141cc406Sopenharmony_ci DBG (DBG_info, "setup_scan_registers: xstart=%d, pixels=%d\n", dev->xstart, dev->pixels); 6568141cc406Sopenharmony_ci DBG (DBG_info, "setup_scan_registers: ystart=%d, lines =%d\n", dev->ystart, dev->lines); 6569141cc406Sopenharmony_ci 6570141cc406Sopenharmony_ci /* this is full register set from a color preview */ 6571141cc406Sopenharmony_ci regs[0x00] = regs[0x00] & 0xef; 6572141cc406Sopenharmony_ci regs[0x01] = 0x41; 6573141cc406Sopenharmony_ci 6574141cc406Sopenharmony_ci sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset); 6575141cc406Sopenharmony_ci sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain); 6576141cc406Sopenharmony_ci 6577141cc406Sopenharmony_ci switch (dev->sensor) 6578141cc406Sopenharmony_ci { 6579141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 6580141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 6581141cc406Sopenharmony_ci *status1 = 0x10; 6582141cc406Sopenharmony_ci *status2 = 0x2a; 6583141cc406Sopenharmony_ci break; 6584141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 6585141cc406Sopenharmony_ci *status1 = 0x20; 6586141cc406Sopenharmony_ci *status2 = 0x3f; 6587141cc406Sopenharmony_ci break; 6588141cc406Sopenharmony_ci default: 6589141cc406Sopenharmony_ci *status1 = 0x20; 6590141cc406Sopenharmony_ci *status2 = 0x3b; 6591141cc406Sopenharmony_ci } 6592141cc406Sopenharmony_ci 6593141cc406Sopenharmony_ci /* default to 75 dpi color scan */ 6594141cc406Sopenharmony_ci regs[0x0b] = 0x70; 6595141cc406Sopenharmony_ci regs[0x0c] = 0x00; 6596141cc406Sopenharmony_ci regs[0x0d] = 0x00; 6597141cc406Sopenharmony_ci regs[0x0e] = 0x00; 6598141cc406Sopenharmony_ci regs[0x0f] = 0x00; 6599141cc406Sopenharmony_ci 6600141cc406Sopenharmony_ci regs[0x12] = 0xff; 6601141cc406Sopenharmony_ci regs[0x13] = 0x20; 6602141cc406Sopenharmony_ci regs[0x14] = 0xf8; 6603141cc406Sopenharmony_ci regs[0x15] = 0x28; 6604141cc406Sopenharmony_ci regs[0x16] = 0x01; 6605141cc406Sopenharmony_ci regs[0x17] = 0x00; 6606141cc406Sopenharmony_ci regs[0x18] = 0xff; 6607141cc406Sopenharmony_ci regs[0x19] = 0x00; 6608141cc406Sopenharmony_ci regs[0x1a] = 0x00; 6609141cc406Sopenharmony_ci regs[0x1b] = 0x00; 6610141cc406Sopenharmony_ci regs[0x1c] = 0x00; 6611141cc406Sopenharmony_ci regs[0x1d] = 0x20; 6612141cc406Sopenharmony_ci regs[0x1e] = 0x00; 6613141cc406Sopenharmony_ci regs[0x1f] = 0x00; 6614141cc406Sopenharmony_ci 6615141cc406Sopenharmony_ci /* LCD display */ 6616141cc406Sopenharmony_ci regs[0x20] = 0x3a; 6617141cc406Sopenharmony_ci regs[0x21] = 0xf2; 6618141cc406Sopenharmony_ci regs[0x22] = 0x00; 6619141cc406Sopenharmony_ci 6620141cc406Sopenharmony_ci regs[0x23] = 0x80; 6621141cc406Sopenharmony_ci regs[0x24] = 0xff; 6622141cc406Sopenharmony_ci regs[0x25] = 0x00; 6623141cc406Sopenharmony_ci regs[0x26] = 0x00; 6624141cc406Sopenharmony_ci regs[0x27] = 0x00; 6625141cc406Sopenharmony_ci regs[0x28] = 0x00; 6626141cc406Sopenharmony_ci regs[0x29] = 0x00; 6627141cc406Sopenharmony_ci regs[0x2a] = 0x00; 6628141cc406Sopenharmony_ci regs[0x2b] = 0x00; 6629141cc406Sopenharmony_ci regs[0x2c] = 0x00; 6630141cc406Sopenharmony_ci regs[0x2d] = 0x00; 6631141cc406Sopenharmony_ci regs[0x2e] = 0x00; 6632141cc406Sopenharmony_ci regs[0x2f] = 0x00; 6633141cc406Sopenharmony_ci regs[0x30] = 0x00; 6634141cc406Sopenharmony_ci regs[0x31] = 0x00; 6635141cc406Sopenharmony_ci regs[0x32] = 0x20; 6636141cc406Sopenharmony_ci regs[0x33] = 0x83; 6637141cc406Sopenharmony_ci regs[0x34] = 0x10; 6638141cc406Sopenharmony_ci regs[0x35] = 0x47; 6639141cc406Sopenharmony_ci regs[0x36] = 0x2c; 6640141cc406Sopenharmony_ci regs[0x37] = 0x00; 6641141cc406Sopenharmony_ci regs[0x38] = 0x00; 6642141cc406Sopenharmony_ci regs[0x39] = 0x02; 6643141cc406Sopenharmony_ci regs[0x3a] = 0x43; 6644141cc406Sopenharmony_ci regs[0x3b] = 0x00; 6645141cc406Sopenharmony_ci regs[0x3c] = 0x00; 6646141cc406Sopenharmony_ci regs[0x3d] = 0x00; 6647141cc406Sopenharmony_ci regs[0x3e] = 0x00; 6648141cc406Sopenharmony_ci regs[0x3f] = 0x00; 6649141cc406Sopenharmony_ci regs[0x40] = 0x2c; /* 0x0c -> use shading data */ 6650141cc406Sopenharmony_ci regs[0x41] = 0x00; 6651141cc406Sopenharmony_ci regs[0x42] = 0x00; 6652141cc406Sopenharmony_ci regs[0x43] = 0x00; 6653141cc406Sopenharmony_ci regs[0x44] = 0x8c; 6654141cc406Sopenharmony_ci regs[0x45] = 0x76; 6655141cc406Sopenharmony_ci regs[0x46] = 0x00; 6656141cc406Sopenharmony_ci regs[0x47] = 0x00; 6657141cc406Sopenharmony_ci regs[0x48] = 0x00; 6658141cc406Sopenharmony_ci regs[0x49] = 0x00; 6659141cc406Sopenharmony_ci regs[0x4a] = 0x00; 6660141cc406Sopenharmony_ci regs[0x4b] = 0x00; 6661141cc406Sopenharmony_ci regs[0x4c] = 0x00; 6662141cc406Sopenharmony_ci regs[0x4d] = 0x00; 6663141cc406Sopenharmony_ci regs[0x4e] = 0x00; 6664141cc406Sopenharmony_ci regs[0x4f] = 0x00; 6665141cc406Sopenharmony_ci regs[0x50] = 0x00; 6666141cc406Sopenharmony_ci regs[0x51] = 0x00; 6667141cc406Sopenharmony_ci regs[0x52] = 0x00; 6668141cc406Sopenharmony_ci regs[0x53] = 0x00; 6669141cc406Sopenharmony_ci regs[0x54] = 0x00; 6670141cc406Sopenharmony_ci regs[0x55] = 0x00; 6671141cc406Sopenharmony_ci regs[0x56] = 0x00; 6672141cc406Sopenharmony_ci regs[0x57] = 0x00; 6673141cc406Sopenharmony_ci regs[0x58] = 0x00; 6674141cc406Sopenharmony_ci regs[0x59] = 0x00; 6675141cc406Sopenharmony_ci regs[0x5a] = 0x00; 6676141cc406Sopenharmony_ci regs[0x5b] = 0x00; 6677141cc406Sopenharmony_ci regs[0x5c] = 0x00; 6678141cc406Sopenharmony_ci regs[0x5d] = 0x00; 6679141cc406Sopenharmony_ci regs[0x5e] = 0x00; 6680141cc406Sopenharmony_ci regs[0x5f] = 0x00; 6681141cc406Sopenharmony_ci 6682141cc406Sopenharmony_ci regs[0x64] = 0x01; 6683141cc406Sopenharmony_ci regs[0x65] = 0x20; 6684141cc406Sopenharmony_ci 6685141cc406Sopenharmony_ci regs[0x68] = 0x00; 6686141cc406Sopenharmony_ci regs[0x69] = 0x00; 6687141cc406Sopenharmony_ci regs[0x6a] = 0x00; 6688141cc406Sopenharmony_ci regs[0x6b] = 0x00; 6689141cc406Sopenharmony_ci 6690141cc406Sopenharmony_ci regs[0x6e] = 0x00; 6691141cc406Sopenharmony_ci regs[0x6f] = 0x00; 6692141cc406Sopenharmony_ci regs[0x70] = 0x00; 6693141cc406Sopenharmony_ci regs[0x71] = 0x00; 6694141cc406Sopenharmony_ci 6695141cc406Sopenharmony_ci regs[0x72] = 0xe1; 6696141cc406Sopenharmony_ci regs[0x73] = 0x14; 6697141cc406Sopenharmony_ci regs[0x74] = 0x18; 6698141cc406Sopenharmony_ci regs[0x75] = 0x15; 6699141cc406Sopenharmony_ci 6700141cc406Sopenharmony_ci regs[0x76] = 0x00; 6701141cc406Sopenharmony_ci regs[0x77] = 0x00; 6702141cc406Sopenharmony_ci regs[0x78] = 0x00; 6703141cc406Sopenharmony_ci regs[0x79] = 0x20; 6704141cc406Sopenharmony_ci regs[0x7a] = 0x01; 6705141cc406Sopenharmony_ci regs[0x7b] = 0x00; 6706141cc406Sopenharmony_ci regs[0x7c] = 0x00; 6707141cc406Sopenharmony_ci regs[0x7d] = 0x00; 6708141cc406Sopenharmony_ci regs[0x7e] = 0x00; 6709141cc406Sopenharmony_ci regs[0x7f] = 0x00; 6710141cc406Sopenharmony_ci timing=0x00af; 6711141cc406Sopenharmony_ci regs[0x84] = 0x00; 6712141cc406Sopenharmony_ci regs[0x85] = 0x46; 6713141cc406Sopenharmony_ci regs[0x86] = 0x0b; 6714141cc406Sopenharmony_ci regs[0x87] = 0x8c; 6715141cc406Sopenharmony_ci regs[0x88] = 0x10; 6716141cc406Sopenharmony_ci regs[0x8b] = 0xff; 6717141cc406Sopenharmony_ci regs[0x8c] = 0x3f; 6718141cc406Sopenharmony_ci regs[0x8d] = 0x3b; 6719141cc406Sopenharmony_ci 6720141cc406Sopenharmony_ci regs[0x8e] = 0x60; 6721141cc406Sopenharmony_ci regs[0x8f] = 0x00; 6722141cc406Sopenharmony_ci regs[0x90] = 0x18; /* 0x1c when shading calibration */ 6723141cc406Sopenharmony_ci 6724141cc406Sopenharmony_ci /* overwritten when calibration data is sent */ 6725141cc406Sopenharmony_ci regs[0x91] = 0x00; 6726141cc406Sopenharmony_ci regs[0x92] = 0x00; 6727141cc406Sopenharmony_ci 6728141cc406Sopenharmony_ci regs[0x93] = 0x01; 6729141cc406Sopenharmony_ci 6730141cc406Sopenharmony_ci regs[0x94] = 0x0e; 6731141cc406Sopenharmony_ci regs[0x95] = 0x00; 6732141cc406Sopenharmony_ci regs[0x96] = 0x00; 6733141cc406Sopenharmony_ci regs[0x97] = 0x00; 6734141cc406Sopenharmony_ci regs[0x98] = 0x00; 6735141cc406Sopenharmony_ci regs[0x99] = 0x00; 6736141cc406Sopenharmony_ci regs[0x9a] = 0x00; 6737141cc406Sopenharmony_ci regs[0x9b] = 0x00; 6738141cc406Sopenharmony_ci regs[0x9c] = 0x00; 6739141cc406Sopenharmony_ci regs[0x9d] = 0x00; 6740141cc406Sopenharmony_ci regs[0x9e] = 0x00; 6741141cc406Sopenharmony_ci regs[0x9f] = 0x00; 6742141cc406Sopenharmony_ci regs[0xa0] = 0x00; 6743141cc406Sopenharmony_ci regs[0xa1] = 0x00; 6744141cc406Sopenharmony_ci regs[0xa2] = 0x00; 6745141cc406Sopenharmony_ci regs[0xa3] = 0xcc; 6746141cc406Sopenharmony_ci regs[0xa4] = 0x27; 6747141cc406Sopenharmony_ci regs[0xa5] = 0x64; 6748141cc406Sopenharmony_ci regs[0xa6] = 0x00; 6749141cc406Sopenharmony_ci regs[0xa7] = 0x00; 6750141cc406Sopenharmony_ci regs[0xa8] = 0x00; 6751141cc406Sopenharmony_ci regs[0xa9] = 0x00; 6752141cc406Sopenharmony_ci regs[0xaa] = 0x00; 6753141cc406Sopenharmony_ci regs[0xab] = 0x00; 6754141cc406Sopenharmony_ci regs[0xac] = 0x00; 6755141cc406Sopenharmony_ci regs[0xad] = 0x00; 6756141cc406Sopenharmony_ci regs[0xae] = 0x00; 6757141cc406Sopenharmony_ci regs[0xaf] = 0x00; 6758141cc406Sopenharmony_ci regs[0xb0] = 0x00; 6759141cc406Sopenharmony_ci regs[0xb1] = 0x00; 6760141cc406Sopenharmony_ci regs[0xb2] = 0x02; 6761141cc406Sopenharmony_ci 6762141cc406Sopenharmony_ci regs[0xb4] = 0x00; 6763141cc406Sopenharmony_ci regs[0xb5] = 0x00; 6764141cc406Sopenharmony_ci regs[0xb6] = 0x00; 6765141cc406Sopenharmony_ci regs[0xb7] = 0x00; 6766141cc406Sopenharmony_ci regs[0xb8] = 0x00; 6767141cc406Sopenharmony_ci regs[0xb9] = 0x00; 6768141cc406Sopenharmony_ci regs[0xba] = 0x00; 6769141cc406Sopenharmony_ci regs[0xbb] = 0x00; 6770141cc406Sopenharmony_ci regs[0xbc] = 0x00; 6771141cc406Sopenharmony_ci regs[0xbd] = 0x00; 6772141cc406Sopenharmony_ci regs[0xbe] = 0x00; 6773141cc406Sopenharmony_ci regs[0xbf] = 0x00; 6774141cc406Sopenharmony_ci regs[0xc0] = 0x06; 6775141cc406Sopenharmony_ci regs[0xc1] = 0xe6; 6776141cc406Sopenharmony_ci regs[0xc2] = 0x67; 6777141cc406Sopenharmony_ci regs[0xc3] = 0xff; 6778141cc406Sopenharmony_ci regs[0xc4] = 0xff; 6779141cc406Sopenharmony_ci regs[0xc5] = 0xff; 6780141cc406Sopenharmony_ci regs[0xc6] = 0xff; 6781141cc406Sopenharmony_ci regs[0xc7] = 0xff; 6782141cc406Sopenharmony_ci regs[0xc8] = 0xff; 6783141cc406Sopenharmony_ci regs[0xc9] = 0x07; 6784141cc406Sopenharmony_ci regs[0xca] = 0x00; 6785141cc406Sopenharmony_ci regs[0xcb] = 0xfe; 6786141cc406Sopenharmony_ci regs[0xcc] = 0xf9; 6787141cc406Sopenharmony_ci regs[0xcd] = 0x19; 6788141cc406Sopenharmony_ci regs[0xce] = 0x98; 6789141cc406Sopenharmony_ci regs[0xcf] = 0xe8; 6790141cc406Sopenharmony_ci regs[0xd0] = 0xea; 6791141cc406Sopenharmony_ci 6792141cc406Sopenharmony_ci regs[0xd1] = 0xf3; 6793141cc406Sopenharmony_ci regs[0xd2] = 0x14; 6794141cc406Sopenharmony_ci 6795141cc406Sopenharmony_ci regs[0xd3] = 0x02; 6796141cc406Sopenharmony_ci regs[0xd4] = 0x04; 6797141cc406Sopenharmony_ci regs[0xd5] = 0x86; 6798141cc406Sopenharmony_ci 6799141cc406Sopenharmony_ci regs[0xd6] = 0x0f; 6800141cc406Sopenharmony_ci regs[0xd7] = 0x30; /* 12303 */ 6801141cc406Sopenharmony_ci 6802141cc406Sopenharmony_ci regs[0xd8] = 0x52; /* 0x5230=21040 */ 6803141cc406Sopenharmony_ci 6804141cc406Sopenharmony_ci regs[0xd9] = 0xad; 6805141cc406Sopenharmony_ci regs[0xda] = 0xa7; 6806141cc406Sopenharmony_ci regs[0xdb] = 0x00; 6807141cc406Sopenharmony_ci regs[0xdc] = 0x00; 6808141cc406Sopenharmony_ci regs[0xdd] = 0x00; 6809141cc406Sopenharmony_ci regs[0xde] = 0x00; 6810141cc406Sopenharmony_ci regs[0xdf] = 0x00; 6811141cc406Sopenharmony_ci regs[0xe0] = 0x00; 6812141cc406Sopenharmony_ci regs[0xe1] = 0x00; 6813141cc406Sopenharmony_ci regs[0xe2] = 0x0f; 6814141cc406Sopenharmony_ci regs[0xe3] = 0x85; 6815141cc406Sopenharmony_ci regs[0xe4] = 0x03; 6816141cc406Sopenharmony_ci 6817141cc406Sopenharmony_ci /* regs[0xe5] = 0x52; 6818141cc406Sopenharmony_ci regs[0xe6] = 0x00; exposure time 0x0052=82 */ 6819141cc406Sopenharmony_ci exposure=82; 6820141cc406Sopenharmony_ci 6821141cc406Sopenharmony_ci regs[0xe7] = 0x75; 6822141cc406Sopenharmony_ci regs[0xe8] = 0x01; 6823141cc406Sopenharmony_ci regs[0xe9] = 0x0b; 6824141cc406Sopenharmony_ci regs[0xea] = 0x54; 6825141cc406Sopenharmony_ci regs[0xeb] = 0x01; 6826141cc406Sopenharmony_ci regs[0xec] = 0x04; 6827141cc406Sopenharmony_ci regs[0xed] = 0xb8; 6828141cc406Sopenharmony_ci regs[0xee] = 0x00; 6829141cc406Sopenharmony_ci regs[0xef] = 0x03; 6830141cc406Sopenharmony_ci regs[0xf0] = 0x70; 6831141cc406Sopenharmony_ci regs[0xf1] = 0x00; 6832141cc406Sopenharmony_ci regs[0xf2] = 0x01; 6833141cc406Sopenharmony_ci regs[0xf3] = 0x00; 6834141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) 6835141cc406Sopenharmony_ci { 6836141cc406Sopenharmony_ci regs[0xc0] = 0x67; 6837141cc406Sopenharmony_ci regs[0xc1] = 0x06; 6838141cc406Sopenharmony_ci regs[0xc2] = 0xe6; 6839141cc406Sopenharmony_ci regs[0xc3] = 0x98; 6840141cc406Sopenharmony_ci regs[0xc4] = 0xf9; 6841141cc406Sopenharmony_ci regs[0xc5] = 0x19; 6842141cc406Sopenharmony_ci regs[0xc6] = 0x67; 6843141cc406Sopenharmony_ci regs[0xc7] = 0x06; 6844141cc406Sopenharmony_ci regs[0xc8] = 0xe6; 6845141cc406Sopenharmony_ci regs[0xc9] = 0x01; 6846141cc406Sopenharmony_ci regs[0xca] = 0xf8; 6847141cc406Sopenharmony_ci regs[0xcb] = 0xff; 6848141cc406Sopenharmony_ci regs[0xcc] = 0x98; 6849141cc406Sopenharmony_ci regs[0xcd] = 0xf9; 6850141cc406Sopenharmony_ci regs[0xce] = 0x19; 6851141cc406Sopenharmony_ci regs[0xcf] = 0xe0; 6852141cc406Sopenharmony_ci regs[0xd0] = 0xe2; 6853141cc406Sopenharmony_ci 6854141cc406Sopenharmony_ci regs[0xd1] = 0xeb; 6855141cc406Sopenharmony_ci regs[0xd2] = 0x0c; 6856141cc406Sopenharmony_ci 6857141cc406Sopenharmony_ci regs[0xd7] = 0x10; 6858141cc406Sopenharmony_ci } 6859141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400) 6860141cc406Sopenharmony_ci { 6861141cc406Sopenharmony_ci regs[0x13] = 0x39; /* 0x20 */ 6862141cc406Sopenharmony_ci regs[0x14] = 0xf0; /* 0xf8 */ 6863141cc406Sopenharmony_ci regs[0x15] = 0x29; /* 0x28 */ 6864141cc406Sopenharmony_ci regs[0x16] = 0x00; /* 0x01 */ 6865141cc406Sopenharmony_ci regs[0x17] = 0x10; /* 0x00 */ 6866141cc406Sopenharmony_ci regs[0x23] = 0x00; /* 0x80 */ 6867141cc406Sopenharmony_ci regs[0x35] = 0x47; /* 0x45 */ 6868141cc406Sopenharmony_ci regs[0x36] = 0x29; /* 0x2c */ 6869141cc406Sopenharmony_ci regs[0x39] = 0x00; /* 0x02 */ 6870141cc406Sopenharmony_ci timing=0x00af; 6871141cc406Sopenharmony_ci regs[0x85] = 0x46; /* 0x8c */ 6872141cc406Sopenharmony_ci regs[0x86] = 0x0b; /* 0x10 */ 6873141cc406Sopenharmony_ci regs[0x87] = 0x8c; /* 0x18 */ 6874141cc406Sopenharmony_ci regs[0x88] = 0x10; /* 0x1b */ 6875141cc406Sopenharmony_ci regs[0x8d] = 0x3b; /* 0x77 */ 6876141cc406Sopenharmony_ci 6877141cc406Sopenharmony_ci regs[0xd3] = 0x02; /* 0x0e */ 6878141cc406Sopenharmony_ci regs[0xd4] = 0x04; /* 0x10 */ 6879141cc406Sopenharmony_ci regs[0xe2] = 0x07; /* 0x0f */ 6880141cc406Sopenharmony_ci regs[0xe3] = 0x84; /* 0x87 */ 6881141cc406Sopenharmony_ci /*regs[0xe5] = 0xa5; 0x54 */ 6882141cc406Sopenharmony_ci exposure=165; 6883141cc406Sopenharmony_ci regs[0xe7] = 0x0e; /* 0xa8 */ 6884141cc406Sopenharmony_ci regs[0xe8] = 0x01; /* 0x00 */ 6885141cc406Sopenharmony_ci regs[0xe9] = 0x0a; /* 0x0b */ 6886141cc406Sopenharmony_ci regs[0xea] = 0xc2; /* 0x56 */ 6887141cc406Sopenharmony_ci regs[0xed] = 0xf6; /* 0xba */ 6888141cc406Sopenharmony_ci regs[0xef] = 0x02; /* 0x03 */ 6889141cc406Sopenharmony_ci regs[0xf0] = 0xa8; /* 0x72 */ 6890141cc406Sopenharmony_ci } 6891141cc406Sopenharmony_ci if (dev->sensor == SENSOR_TYPE_4400_BARE) 6892141cc406Sopenharmony_ci { 6893141cc406Sopenharmony_ci regs[0x13] = 0x39; /* 0x20 */ 6894141cc406Sopenharmony_ci regs[0x14] = 0xf0; /* 0xf8 */ 6895141cc406Sopenharmony_ci regs[0x15] = 0x29; /* 0x28 */ 6896141cc406Sopenharmony_ci regs[0x16] = 0x00; /* 0x07 */ 6897141cc406Sopenharmony_ci regs[0x17] = 0x10; /* 0x00 */ 6898141cc406Sopenharmony_ci regs[0x23] = 0x00; /* 0xff */ 6899141cc406Sopenharmony_ci regs[0x35] = 0x47; /* 0x0e */ 6900141cc406Sopenharmony_ci regs[0x36] = 0x29; /* 0x2c */ 6901141cc406Sopenharmony_ci regs[0x39] = 0x00; /* 0x02 */ 6902141cc406Sopenharmony_ci regs[0x3a] = 0x43; /* 0x0e */ 6903141cc406Sopenharmony_ci regs[0x40] = 0x2c; /* 0x20 */ 6904141cc406Sopenharmony_ci regs[0x85] = 0x46; /* 0x00 */ 6905141cc406Sopenharmony_ci regs[0x86] = 0x0b; /* 0x06 */ 6906141cc406Sopenharmony_ci regs[0x87] = 0x8c; /* 0x00 */ 6907141cc406Sopenharmony_ci regs[0x88] = 0x10; /* 0x06 */ 6908141cc406Sopenharmony_ci regs[0x8d] = 0x3b; /* 0x00 */ 6909141cc406Sopenharmony_ci regs[0x90] = 0x18; /* 0x1c */ 6910141cc406Sopenharmony_ci regs[0xe2] = 0x07; /* 0x05 */ 6911141cc406Sopenharmony_ci regs[0xe3] = 0x84; /* 0x00 */ 6912141cc406Sopenharmony_ci regs[0xe4] = 0x03; /* 0x00 */ 6913141cc406Sopenharmony_ci timing=0x00af; 6914141cc406Sopenharmony_ci exposure=165; 6915141cc406Sopenharmony_ci regs[0xe7] = 0x0e; /* 0x00 */ 6916141cc406Sopenharmony_ci regs[0xe8] = 0x01; /* 0x00 */ 6917141cc406Sopenharmony_ci regs[0xe9] = 0x0a; /* 0x00 */ 6918141cc406Sopenharmony_ci regs[0xea] = 0xc2; /* 0x00 */ 6919141cc406Sopenharmony_ci regs[0xeb] = 0x01; /* 0x00 */ 6920141cc406Sopenharmony_ci regs[0xec] = 0x04; /* 0x00 */ 6921141cc406Sopenharmony_ci regs[0xed] = 0xf6; /* 0x00 */ 6922141cc406Sopenharmony_ci regs[0xef] = 0x02; /* 0x00 */ 6923141cc406Sopenharmony_ci regs[0xf0] = 0xa8; /* 0x00 */ 6924141cc406Sopenharmony_ci regs[0xf2] = 0x01; /* 0x00 */ 6925141cc406Sopenharmony_ci } 6926141cc406Sopenharmony_ci switch (dev->xdpi) 6927141cc406Sopenharmony_ci { 6928141cc406Sopenharmony_ci case 75: 6929141cc406Sopenharmony_ci break; 6930141cc406Sopenharmony_ci case 150: 6931141cc406Sopenharmony_ci regs[0x35] = 0x45; 6932141cc406Sopenharmony_ci 6933141cc406Sopenharmony_ci 6934141cc406Sopenharmony_ci regs[0x85] = 0x8c; 6935141cc406Sopenharmony_ci regs[0x86] = 0x10; 6936141cc406Sopenharmony_ci 6937141cc406Sopenharmony_ci regs[0x87] = 0x18; 6938141cc406Sopenharmony_ci regs[0x88] = 0x1b; 6939141cc406Sopenharmony_ci 6940141cc406Sopenharmony_ci regs[0x8d] = 0x77; 6941141cc406Sopenharmony_ci 6942141cc406Sopenharmony_ci regs[0xe3] = 0x87; 6943141cc406Sopenharmony_ci 6944141cc406Sopenharmony_ci /* regs[0xe5] = 0x54; 6945141cc406Sopenharmony_ci regs[0xe6] = 0x00; exposure time 0x0054=84 */ 6946141cc406Sopenharmony_ci exposure=84; 6947141cc406Sopenharmony_ci timing=0x012e; 6948141cc406Sopenharmony_ci 6949141cc406Sopenharmony_ci regs[0xe7] = 0xa8; 6950141cc406Sopenharmony_ci regs[0xe8] = 0x00; 6951141cc406Sopenharmony_ci regs[0xea] = 0x56; 6952141cc406Sopenharmony_ci regs[0xed] = 0xba; 6953141cc406Sopenharmony_ci 6954141cc406Sopenharmony_ci regs[0xf0] = 0x72; 6955141cc406Sopenharmony_ci switch (dev->sensor) 6956141cc406Sopenharmony_ci { 6957141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 6958141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 150 dpi\n"); 6959141cc406Sopenharmony_ci regs[0xc0] = 0x00; 6960141cc406Sopenharmony_ci regs[0xc1] = 0x8e; 6961141cc406Sopenharmony_ci regs[0xc2] = 0xff; 6962141cc406Sopenharmony_ci regs[0xc3] = 0xff; 6963141cc406Sopenharmony_ci regs[0xc4] = 0x71; 6964141cc406Sopenharmony_ci regs[0xc5] = 0x00; 6965141cc406Sopenharmony_ci regs[0xc6] = 0x00; 6966141cc406Sopenharmony_ci regs[0xc7] = 0x8e; 6967141cc406Sopenharmony_ci regs[0xc8] = 0xff; 6968141cc406Sopenharmony_ci regs[0xc9] = 0xff; 6969141cc406Sopenharmony_ci regs[0xca] = 0xff; 6970141cc406Sopenharmony_ci regs[0xcb] = 0x1f; 6971141cc406Sopenharmony_ci regs[0xcc] = 0xff; 6972141cc406Sopenharmony_ci regs[0xcd] = 0x71; 6973141cc406Sopenharmony_ci regs[0xce] = 0x00; 6974141cc406Sopenharmony_ci regs[0xcf] = 0xe6; 6975141cc406Sopenharmony_ci regs[0xd0] = 0xe8; 6976141cc406Sopenharmony_ci regs[0xd1] = 0xf6; 6977141cc406Sopenharmony_ci regs[0xd2] = 0x17; 6978141cc406Sopenharmony_ci regs[0xd3] = 0x0b; 6979141cc406Sopenharmony_ci regs[0xd4] = 0x0d; 6980141cc406Sopenharmony_ci break; 6981141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 6982141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 150 dpi\n"); 6983141cc406Sopenharmony_ci regs[0xc0] = 0x80; 6984141cc406Sopenharmony_ci regs[0xc1] = 0x87; 6985141cc406Sopenharmony_ci regs[0xc2] = 0x7f; 6986141cc406Sopenharmony_ci regs[0xc9] = 0x00; 6987141cc406Sopenharmony_ci regs[0xcb] = 0x78; 6988141cc406Sopenharmony_ci regs[0xcc] = 0x7f; 6989141cc406Sopenharmony_ci regs[0xcd] = 0x78; 6990141cc406Sopenharmony_ci regs[0xce] = 0x80; 6991141cc406Sopenharmony_ci regs[0xcf] = 0xe6; 6992141cc406Sopenharmony_ci regs[0xd0] = 0xe8; 6993141cc406Sopenharmony_ci 6994141cc406Sopenharmony_ci regs[0xd1] = 0xf7; 6995141cc406Sopenharmony_ci regs[0xd2] = 0x00; 6996141cc406Sopenharmony_ci 6997141cc406Sopenharmony_ci regs[0xd3] = 0x0e; 6998141cc406Sopenharmony_ci regs[0xd4] = 0x10; 6999141cc406Sopenharmony_ci break; 7000141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 7001141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 150 dpi\n"); 7002141cc406Sopenharmony_ci regs[0x35] = 0x47; 7003141cc406Sopenharmony_ci 7004141cc406Sopenharmony_ci exposure=170; 7005141cc406Sopenharmony_ci timing=0x012e; 7006141cc406Sopenharmony_ci regs[0x85] = 0x8c; 7007141cc406Sopenharmony_ci regs[0x86] = 0x10; 7008141cc406Sopenharmony_ci regs[0x87] = 0x18; 7009141cc406Sopenharmony_ci regs[0x88] = 0x1b; 7010141cc406Sopenharmony_ci regs[0x8d] = 0x77; 7011141cc406Sopenharmony_ci regs[0xc0] = 0x00; 7012141cc406Sopenharmony_ci regs[0xc1] = 0x8e; 7013141cc406Sopenharmony_ci regs[0xc2] = 0xff; 7014141cc406Sopenharmony_ci regs[0xc3] = 0xff; 7015141cc406Sopenharmony_ci regs[0xc4] = 0x71; 7016141cc406Sopenharmony_ci regs[0xc5] = 0x00; 7017141cc406Sopenharmony_ci regs[0xc6] = 0x00; 7018141cc406Sopenharmony_ci regs[0xc7] = 0x8e; 7019141cc406Sopenharmony_ci regs[0xc8] = 0xff; 7020141cc406Sopenharmony_ci regs[0xc9] = 0xff; 7021141cc406Sopenharmony_ci regs[0xca] = 0xff; 7022141cc406Sopenharmony_ci regs[0xcb] = 0x1f; 7023141cc406Sopenharmony_ci regs[0xcc] = 0xff; 7024141cc406Sopenharmony_ci regs[0xcd] = 0x71; 7025141cc406Sopenharmony_ci regs[0xce] = 0x00; 7026141cc406Sopenharmony_ci regs[0xcf] = 0xe6; 7027141cc406Sopenharmony_ci regs[0xd0] = 0xe8; 7028141cc406Sopenharmony_ci regs[0xd1] = 0xf6; 7029141cc406Sopenharmony_ci regs[0xd2] = 0x17; 7030141cc406Sopenharmony_ci regs[0xd3] = 0x0b; 7031141cc406Sopenharmony_ci regs[0xd4] = 0x0d; 7032141cc406Sopenharmony_ci regs[0xe3] = 0x86; 7033141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7034141cc406Sopenharmony_ci regs[0xe8] = 0x1c; 7035141cc406Sopenharmony_ci regs[0xe9] = 0x01; 7036141cc406Sopenharmony_ci regs[0xea] = 0x0a; 7037141cc406Sopenharmony_ci regs[0xeb] = 0xc4; 7038141cc406Sopenharmony_ci regs[0xec] = 0x01; 7039141cc406Sopenharmony_ci regs[0xed] = 0x04; 7040141cc406Sopenharmony_ci regs[0xee] = 0xf8; 7041141cc406Sopenharmony_ci regs[0xef] = 0x00; 7042141cc406Sopenharmony_ci regs[0xf0] = 0x02; 7043141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7044141cc406Sopenharmony_ci break; 7045141cc406Sopenharmony_ci } 7046141cc406Sopenharmony_ci break; 7047141cc406Sopenharmony_ci 7048141cc406Sopenharmony_ci case 300: 7049141cc406Sopenharmony_ci switch (dev->sensor) 7050141cc406Sopenharmony_ci { 7051141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 7052141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 300 dpi\n"); 7053141cc406Sopenharmony_ci regs[0x35] = 0x0e; /* fast ? */ 7054141cc406Sopenharmony_ci regs[0x3a] = 0x0e; 7055141cc406Sopenharmony_ci 7056141cc406Sopenharmony_ci 7057141cc406Sopenharmony_ci regs[0x85] = 0x18; 7058141cc406Sopenharmony_ci regs[0x86] = 0x1b; 7059141cc406Sopenharmony_ci 7060141cc406Sopenharmony_ci regs[0x87] = 0x30; 7061141cc406Sopenharmony_ci regs[0x88] = 0x30; 7062141cc406Sopenharmony_ci 7063141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7064141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7065141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7066141cc406Sopenharmony_ci regs[0xea] = 0x00; 7067141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7068141cc406Sopenharmony_ci regs[0xec] = 0x00; 7069141cc406Sopenharmony_ci regs[0xed] = 0x00; 7070141cc406Sopenharmony_ci regs[0xef] = 0x00; 7071141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7072141cc406Sopenharmony_ci regs[0x8d] = 0xef; 7073141cc406Sopenharmony_ci regs[0xc0] = 0x00; 7074141cc406Sopenharmony_ci regs[0xc1] = 0xff; 7075141cc406Sopenharmony_ci regs[0xc2] = 0x0f; 7076141cc406Sopenharmony_ci regs[0xc3] = 0xff; 7077141cc406Sopenharmony_ci regs[0xc4] = 0x00; 7078141cc406Sopenharmony_ci regs[0xc5] = 0xf0; 7079141cc406Sopenharmony_ci regs[0xc6] = 0x00; 7080141cc406Sopenharmony_ci regs[0xc7] = 0xff; 7081141cc406Sopenharmony_ci regs[0xc8] = 0x0f; 7082141cc406Sopenharmony_ci regs[0xc9] = 0xff; 7083141cc406Sopenharmony_ci regs[0xca] = 0xff; 7084141cc406Sopenharmony_ci regs[0xcb] = 0xf1; 7085141cc406Sopenharmony_ci regs[0xcc] = 0xff; 7086141cc406Sopenharmony_ci regs[0xcd] = 0x00; 7087141cc406Sopenharmony_ci regs[0xce] = 0xf0; 7088141cc406Sopenharmony_ci regs[0xcf] = 0xed; 7089141cc406Sopenharmony_ci regs[0xd0] = 0xef; 7090141cc406Sopenharmony_ci regs[0xd1] = 0xe2; 7091141cc406Sopenharmony_ci regs[0xd2] = 0x03; 7092141cc406Sopenharmony_ci regs[0xd3] = 0x17; 7093141cc406Sopenharmony_ci regs[0xd4] = 0x01; 7094141cc406Sopenharmony_ci regs[0xe2] = 0x07; 7095141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7096141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7097141cc406Sopenharmony_ci timing=0x022b; 7098141cc406Sopenharmony_ci exposure=342; 7099141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7100141cc406Sopenharmony_ci break; 7101141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 7102141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 300 dpi\n"); 7103141cc406Sopenharmony_ci regs[0x35] = 0x0e; /* fast ? */ 7104141cc406Sopenharmony_ci regs[0x3a] = 0x0e; 7105141cc406Sopenharmony_ci 7106141cc406Sopenharmony_ci timing=0x022b; 7107141cc406Sopenharmony_ci 7108141cc406Sopenharmony_ci regs[0x85] = 0x18; 7109141cc406Sopenharmony_ci regs[0x86] = 0x1b; 7110141cc406Sopenharmony_ci 7111141cc406Sopenharmony_ci regs[0x87] = 0x30; 7112141cc406Sopenharmony_ci regs[0x88] = 0x30; 7113141cc406Sopenharmony_ci 7114141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7115141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7116141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7117141cc406Sopenharmony_ci regs[0xea] = 0x00; 7118141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7119141cc406Sopenharmony_ci regs[0xec] = 0x00; 7120141cc406Sopenharmony_ci regs[0xed] = 0x00; 7121141cc406Sopenharmony_ci regs[0xef] = 0x00; 7122141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7123141cc406Sopenharmony_ci regs[0x8d] = 0xf0; 7124141cc406Sopenharmony_ci regs[0x8e] = 0x60; /* low nibble of 8e and 8d are proportional to 7125141cc406Sopenharmony_ci the scanned width 1de => 5100 wide scan */ 7126141cc406Sopenharmony_ci 7127141cc406Sopenharmony_ci regs[0xc0] = 0xff; 7128141cc406Sopenharmony_ci regs[0xc1] = 0x0f; 7129141cc406Sopenharmony_ci regs[0xc2] = 0x00; 7130141cc406Sopenharmony_ci regs[0xc9] = 0x00; 7131141cc406Sopenharmony_ci regs[0xca] = 0x0e; 7132141cc406Sopenharmony_ci regs[0xcb] = 0x00; 7133141cc406Sopenharmony_ci regs[0xcc] = 0x00; 7134141cc406Sopenharmony_ci regs[0xcd] = 0xf0; 7135141cc406Sopenharmony_ci regs[0xce] = 0xff; 7136141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 7137141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 7138141cc406Sopenharmony_ci regs[0xd1] = 0xea; 7139141cc406Sopenharmony_ci regs[0xd2] = 0x0b; 7140141cc406Sopenharmony_ci 7141141cc406Sopenharmony_ci regs[0xd3] = 0x17; 7142141cc406Sopenharmony_ci regs[0xd4] = 0x01; 7143141cc406Sopenharmony_ci 7144141cc406Sopenharmony_ci regs[0xe2] = 0x07; 7145141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7146141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7147141cc406Sopenharmony_ci 7148141cc406Sopenharmony_ci exposure=342; 7149141cc406Sopenharmony_ci break; 7150141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 7151141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 300 dpi\n"); 7152141cc406Sopenharmony_ci regs[0x11] = 0x22; 7153141cc406Sopenharmony_ci regs[0x35] = 0x0e; 7154141cc406Sopenharmony_ci regs[0x3a] = 0x0e; 7155141cc406Sopenharmony_ci regs[0x85] = 0x18; 7156141cc406Sopenharmony_ci regs[0x86] = 0x1b; 7157141cc406Sopenharmony_ci regs[0x87] = 0x30; 7158141cc406Sopenharmony_ci regs[0x88] = 0x30; 7159141cc406Sopenharmony_ci regs[0x8d] = 0xef; 7160141cc406Sopenharmony_ci regs[0xc0] = 0x00; 7161141cc406Sopenharmony_ci regs[0xc1] = 0xff; 7162141cc406Sopenharmony_ci regs[0xc2] = 0x0f; 7163141cc406Sopenharmony_ci regs[0xc3] = 0xff; 7164141cc406Sopenharmony_ci regs[0xc4] = 0x00; 7165141cc406Sopenharmony_ci regs[0xc5] = 0xf0; 7166141cc406Sopenharmony_ci regs[0xc6] = 0x00; 7167141cc406Sopenharmony_ci regs[0xc7] = 0xff; 7168141cc406Sopenharmony_ci regs[0xc8] = 0x0f; 7169141cc406Sopenharmony_ci regs[0xc9] = 0xff; 7170141cc406Sopenharmony_ci regs[0xca] = 0xff; 7171141cc406Sopenharmony_ci regs[0xcb] = 0xf1; 7172141cc406Sopenharmony_ci regs[0xcc] = 0xff; 7173141cc406Sopenharmony_ci regs[0xcd] = 0x00; 7174141cc406Sopenharmony_ci regs[0xce] = 0xf0; 7175141cc406Sopenharmony_ci regs[0xcf] = 0xed; 7176141cc406Sopenharmony_ci regs[0xd0] = 0xef; 7177141cc406Sopenharmony_ci regs[0xd1] = 0xe2; 7178141cc406Sopenharmony_ci regs[0xd2] = 0x03; 7179141cc406Sopenharmony_ci regs[0xd3] = 0x17; 7180141cc406Sopenharmony_ci regs[0xd4] = 0x01; 7181141cc406Sopenharmony_ci regs[0xe2] = 0x03; 7182141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7183141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7184141cc406Sopenharmony_ci timing=0x022b; 7185141cc406Sopenharmony_ci exposure=686; 7186141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7187141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7188141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7189141cc406Sopenharmony_ci regs[0xea] = 0x00; 7190141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7191141cc406Sopenharmony_ci regs[0xec] = 0x00; 7192141cc406Sopenharmony_ci regs[0xed] = 0x00; 7193141cc406Sopenharmony_ci regs[0xef] = 0x00; 7194141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7195141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7196141cc406Sopenharmony_ci break; 7197141cc406Sopenharmony_ci } 7198141cc406Sopenharmony_ci break; 7199141cc406Sopenharmony_ci case 600: 7200141cc406Sopenharmony_ci *status1 = 0x28; 7201141cc406Sopenharmony_ci switch (dev->sensor) 7202141cc406Sopenharmony_ci { 7203141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 7204141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 600 dpi\n"); 7205141cc406Sopenharmony_ci 7206141cc406Sopenharmony_ci regs[0x34] = 0xf0; 7207141cc406Sopenharmony_ci regs[0x35] = 0x1b; 7208141cc406Sopenharmony_ci regs[0x36] = 0x29; 7209141cc406Sopenharmony_ci regs[0x3a] = 0x1b; 7210141cc406Sopenharmony_ci 7211141cc406Sopenharmony_ci regs[0x72] = 0x3a; 7212141cc406Sopenharmony_ci regs[0x73] = 0x15; 7213141cc406Sopenharmony_ci regs[0x74] = 0x62; 7214141cc406Sopenharmony_ci 7215141cc406Sopenharmony_ci timing=0x0425; 7216141cc406Sopenharmony_ci regs[0x85] = 0x30; 7217141cc406Sopenharmony_ci regs[0x86] = 0x30; 7218141cc406Sopenharmony_ci regs[0x87] = 0x60; 7219141cc406Sopenharmony_ci regs[0x88] = 0x5a; 7220141cc406Sopenharmony_ci 7221141cc406Sopenharmony_ci regs[0x8d] = 0xde; 7222141cc406Sopenharmony_ci regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to 7223141cc406Sopenharmony_ci the scanned width 1de => 5100 wide scan */ 7224141cc406Sopenharmony_ci 7225141cc406Sopenharmony_ci regs[0xc0] = 0xff; 7226141cc406Sopenharmony_ci regs[0xc1] = 0xff; 7227141cc406Sopenharmony_ci regs[0xc2] = 0xff; 7228141cc406Sopenharmony_ci regs[0xc3] = 0x00; 7229141cc406Sopenharmony_ci regs[0xc4] = 0xf0; 7230141cc406Sopenharmony_ci regs[0xc7] = 0x0f; 7231141cc406Sopenharmony_ci regs[0xc8] = 0x00; 7232141cc406Sopenharmony_ci regs[0xcb] = 0xe0; 7233141cc406Sopenharmony_ci regs[0xcc] = 0xff; 7234141cc406Sopenharmony_ci regs[0xcd] = 0xff; 7235141cc406Sopenharmony_ci regs[0xce] = 0xff; 7236141cc406Sopenharmony_ci regs[0xcf] = 0xe9; 7237141cc406Sopenharmony_ci regs[0xd0] = 0xeb; 7238141cc406Sopenharmony_ci 7239141cc406Sopenharmony_ci regs[0xd7] = 0x14; 7240141cc406Sopenharmony_ci 7241141cc406Sopenharmony_ci regs[0xe2] = 0x01; 7242141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7243141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7244141cc406Sopenharmony_ci /* regs[0xe5] = 0xbd; 7245141cc406Sopenharmony_ci regs[0xe6] = 0x0a; exposure time = 0x0abd=2749 (5500/2-1) */ 7246141cc406Sopenharmony_ci exposure=2749; 7247141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7248141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7249141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7250141cc406Sopenharmony_ci regs[0xea] = 0x00; 7251141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7252141cc406Sopenharmony_ci regs[0xec] = 0x00; 7253141cc406Sopenharmony_ci regs[0xed] = 0x00; 7254141cc406Sopenharmony_ci regs[0xef] = 0x00; 7255141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7256141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7257141cc406Sopenharmony_ci break; 7258141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 7259141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 600 dpi\n"); 7260141cc406Sopenharmony_ci 7261141cc406Sopenharmony_ci *status2 = 0x3b; 7262141cc406Sopenharmony_ci regs[0x33] = 0x83; /* 0x86 */ 7263141cc406Sopenharmony_ci regs[0x34] = 0xf0; 7264141cc406Sopenharmony_ci regs[0x35] = 0x1b; 7265141cc406Sopenharmony_ci regs[0x36] = 0x29; 7266141cc406Sopenharmony_ci regs[0x3a] = 0x1b; 7267141cc406Sopenharmony_ci regs[0x40] = 0x2c; /* 0x24 */ 7268141cc406Sopenharmony_ci regs[0x50] = 0x00; /* 0x18 */ 7269141cc406Sopenharmony_ci 7270141cc406Sopenharmony_ci regs[0x64] = 0x01; /* 0x02 */ 7271141cc406Sopenharmony_ci regs[0x65] = 0x20; /* 0x10 */ 7272141cc406Sopenharmony_ci 7273141cc406Sopenharmony_ci regs[0x72] = 0x3a; 7274141cc406Sopenharmony_ci regs[0x73] = 0x15; 7275141cc406Sopenharmony_ci regs[0x74] = 0x62; 7276141cc406Sopenharmony_ci 7277141cc406Sopenharmony_ci 7278141cc406Sopenharmony_ci regs[0x85] = 0x30; 7279141cc406Sopenharmony_ci regs[0x86] = 0x30; 7280141cc406Sopenharmony_ci 7281141cc406Sopenharmony_ci regs[0x87] = 0x60; 7282141cc406Sopenharmony_ci regs[0x88] = 0x5a; 7283141cc406Sopenharmony_ci 7284141cc406Sopenharmony_ci regs[0x8d] = 0xde; 7285141cc406Sopenharmony_ci regs[0x8e] = 0x61; /* 25054 */ 7286141cc406Sopenharmony_ci 7287141cc406Sopenharmony_ci regs[0xc0] = 0xf8; 7288141cc406Sopenharmony_ci regs[0xc1] = 0x7f; 7289141cc406Sopenharmony_ci regs[0xc2] = 0x00; 7290141cc406Sopenharmony_ci regs[0xc3] = 0xf8; 7291141cc406Sopenharmony_ci regs[0xc4] = 0x7f; 7292141cc406Sopenharmony_ci regs[0xc5] = 0x00; 7293141cc406Sopenharmony_ci regs[0xc6] = 0xf8; 7294141cc406Sopenharmony_ci regs[0xc7] = 0x7f; 7295141cc406Sopenharmony_ci regs[0xc8] = 0x00; 7296141cc406Sopenharmony_ci regs[0xc9] = 0xff; 7297141cc406Sopenharmony_ci regs[0xca] = 0x8f; 7298141cc406Sopenharmony_ci regs[0xcb] = 0xff; 7299141cc406Sopenharmony_ci regs[0xcc] = 0x07; 7300141cc406Sopenharmony_ci regs[0xcd] = 0x80; 7301141cc406Sopenharmony_ci regs[0xce] = 0xff; 7302141cc406Sopenharmony_ci regs[0xcf] = 0xf2; 7303141cc406Sopenharmony_ci regs[0xd0] = 0xf4; 7304141cc406Sopenharmony_ci regs[0xd1] = 0xe7; 7305141cc406Sopenharmony_ci regs[0xd2] = 0x08; 7306141cc406Sopenharmony_ci regs[0xd3] = 0x02; 7307141cc406Sopenharmony_ci regs[0xd4] = 0x10; 7308141cc406Sopenharmony_ci regs[0xd7] = 0x31; 7309141cc406Sopenharmony_ci regs[0xe2] = 0x01; 7310141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7311141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7312141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7313141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7314141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7315141cc406Sopenharmony_ci regs[0xea] = 0x00; 7316141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7317141cc406Sopenharmony_ci regs[0xec] = 0x00; 7318141cc406Sopenharmony_ci regs[0xed] = 0x00; 7319141cc406Sopenharmony_ci regs[0xef] = 0x00; 7320141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7321141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7322141cc406Sopenharmony_ci exposure=2749; 7323141cc406Sopenharmony_ci timing=0x0425; 7324141cc406Sopenharmony_ci break; 7325141cc406Sopenharmony_ci 7326141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 7327141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 600 dpi\n"); 7328141cc406Sopenharmony_ci *status1 = 0x10; 7329141cc406Sopenharmony_ci *status2 = 0x23; 7330141cc406Sopenharmony_ci 7331141cc406Sopenharmony_ci regs[0x13] = 0x39; 7332141cc406Sopenharmony_ci regs[0x14] = 0xf0; 7333141cc406Sopenharmony_ci regs[0x15] = 0x29; 7334141cc406Sopenharmony_ci regs[0x16] = 0x00; 7335141cc406Sopenharmony_ci regs[0x17] = 0x10; 7336141cc406Sopenharmony_ci regs[0x23] = 0x00; 7337141cc406Sopenharmony_ci regs[0x34] = 0xf0; 7338141cc406Sopenharmony_ci regs[0x35] = 0x1b; 7339141cc406Sopenharmony_ci regs[0x36] = 0x29; 7340141cc406Sopenharmony_ci regs[0x39] = 0x00; 7341141cc406Sopenharmony_ci regs[0x3a] = 0x1b; 7342141cc406Sopenharmony_ci regs[0x72] = 0x3a; 7343141cc406Sopenharmony_ci regs[0x73] = 0x15; 7344141cc406Sopenharmony_ci regs[0x74] = 0x62; 7345141cc406Sopenharmony_ci regs[0x85] = 0x30; 7346141cc406Sopenharmony_ci regs[0x86] = 0x30; 7347141cc406Sopenharmony_ci regs[0x87] = 0x60; 7348141cc406Sopenharmony_ci regs[0x88] = 0x5a; 7349141cc406Sopenharmony_ci regs[0x8d] = 0xde; 7350141cc406Sopenharmony_ci regs[0x8e] = 0x61; 7351141cc406Sopenharmony_ci regs[0xc0] = 0xf8; 7352141cc406Sopenharmony_ci regs[0xc1] = 0x7f; 7353141cc406Sopenharmony_ci regs[0xc2] = 0x00; 7354141cc406Sopenharmony_ci regs[0xc3] = 0xf8; 7355141cc406Sopenharmony_ci regs[0xc4] = 0x7f; 7356141cc406Sopenharmony_ci regs[0xc5] = 0x00; 7357141cc406Sopenharmony_ci regs[0xc6] = 0xf8; 7358141cc406Sopenharmony_ci regs[0xc7] = 0x7f; 7359141cc406Sopenharmony_ci regs[0xc8] = 0x00; 7360141cc406Sopenharmony_ci regs[0xc9] = 0xff; 7361141cc406Sopenharmony_ci regs[0xca] = 0x8f; 7362141cc406Sopenharmony_ci regs[0xcb] = 0xff; 7363141cc406Sopenharmony_ci regs[0xcc] = 0x07; 7364141cc406Sopenharmony_ci regs[0xcd] = 0x80; 7365141cc406Sopenharmony_ci regs[0xce] = 0xff; 7366141cc406Sopenharmony_ci regs[0xcf] = 0xf2; 7367141cc406Sopenharmony_ci regs[0xd0] = 0xf4; 7368141cc406Sopenharmony_ci regs[0xd1] = 0xe7; 7369141cc406Sopenharmony_ci regs[0xd2] = 0x08; 7370141cc406Sopenharmony_ci regs[0xd3] = 0x0e; 7371141cc406Sopenharmony_ci regs[0xd4] = 0x10; 7372141cc406Sopenharmony_ci regs[0xd7] = 0x31; 7373141cc406Sopenharmony_ci regs[0xe2] = 0x01; 7374141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7375141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7376141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7377141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7378141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7379141cc406Sopenharmony_ci regs[0xea] = 0x00; 7380141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7381141cc406Sopenharmony_ci regs[0xec] = 0x00; 7382141cc406Sopenharmony_ci regs[0xed] = 0x00; 7383141cc406Sopenharmony_ci regs[0xef] = 0x00; 7384141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7385141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7386141cc406Sopenharmony_ci timing=0x0425; 7387141cc406Sopenharmony_ci exposure=2749; 7388141cc406Sopenharmony_ci break; 7389141cc406Sopenharmony_ci 7390141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 7391141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n"); 7392141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 7393141cc406Sopenharmony_ci break; 7394141cc406Sopenharmony_ci } 7395141cc406Sopenharmony_ci break; 7396141cc406Sopenharmony_ci case 1200: 7397141cc406Sopenharmony_ci *status1 = 0x28; 7398141cc406Sopenharmony_ci switch (dev->sensor) 7399141cc406Sopenharmony_ci { 7400141cc406Sopenharmony_ci case SENSOR_TYPE_BARE: 7401141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 1200 dpi\n"); 7402141cc406Sopenharmony_ci 7403141cc406Sopenharmony_ci regs[0x34] = 0xf0; 7404141cc406Sopenharmony_ci regs[0x35] = 0x1b; 7405141cc406Sopenharmony_ci regs[0x36] = 0x29; 7406141cc406Sopenharmony_ci regs[0x3a] = 0x1b; 7407141cc406Sopenharmony_ci regs[0x40] = 0xac; 7408141cc406Sopenharmony_ci timing=0x081a; 7409141cc406Sopenharmony_ci regs[0x85] = 0x60; 7410141cc406Sopenharmony_ci regs[0x86] = 0x5a; 7411141cc406Sopenharmony_ci regs[0x87] = 0xc0; 7412141cc406Sopenharmony_ci regs[0x88] = 0xae; 7413141cc406Sopenharmony_ci 7414141cc406Sopenharmony_ci regs[0x8d] = 0xbd; /* about twice the 600 dpi values */ 7415141cc406Sopenharmony_ci regs[0x8e] = 0x63; /* low nibble of 8e and 8d are proportional to 7416141cc406Sopenharmony_ci the scanned width 3b5 => 10124 wide scan */ 7417141cc406Sopenharmony_ci regs[0xc0] = 0xff; 7418141cc406Sopenharmony_ci regs[0xc1] = 0xff; 7419141cc406Sopenharmony_ci regs[0xc2] = 0xff; 7420141cc406Sopenharmony_ci regs[0xc4] = 0x0f; 7421141cc406Sopenharmony_ci regs[0xc5] = 0x00; 7422141cc406Sopenharmony_ci regs[0xc6] = 0x00; 7423141cc406Sopenharmony_ci regs[0xc7] = 0xf0; 7424141cc406Sopenharmony_ci regs[0xc9] = 0x00; 7425141cc406Sopenharmony_ci regs[0xca] = 0x0e; 7426141cc406Sopenharmony_ci regs[0xcb] = 0x00; 7427141cc406Sopenharmony_ci regs[0xcc] = 0xff; 7428141cc406Sopenharmony_ci regs[0xcd] = 0xff; 7429141cc406Sopenharmony_ci regs[0xce] = 0xff; 7430141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 7431141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 7432141cc406Sopenharmony_ci regs[0xd1] = 0xea; 7433141cc406Sopenharmony_ci regs[0xd2] = 0x0b; 7434141cc406Sopenharmony_ci regs[0xd3] = 0x17; 7435141cc406Sopenharmony_ci regs[0xd4] = 0xc1; 7436141cc406Sopenharmony_ci 7437141cc406Sopenharmony_ci regs[0xd7] = 0x14; 7438141cc406Sopenharmony_ci regs[0xd8] = 0xa4; 7439141cc406Sopenharmony_ci 7440141cc406Sopenharmony_ci regs[0xe2] = 0x01; 7441141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7442141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7443141cc406Sopenharmony_ci /* regs[0xe5] = 0x7b; 7444141cc406Sopenharmony_ci regs[0xe6] = 0x15; exposure time = 0x157b=5499 */ 7445141cc406Sopenharmony_ci exposure=5499; 7446141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7447141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7448141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7449141cc406Sopenharmony_ci regs[0xea] = 0x00; 7450141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7451141cc406Sopenharmony_ci regs[0xec] = 0x00; 7452141cc406Sopenharmony_ci regs[0xed] = 0x00; 7453141cc406Sopenharmony_ci regs[0xef] = 0x00; 7454141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7455141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7456141cc406Sopenharmony_ci break; 7457141cc406Sopenharmony_ci case SENSOR_TYPE_XPA: 7458141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 1200 dpi\n"); 7459141cc406Sopenharmony_ci *status2 = 0x3f; 7460141cc406Sopenharmony_ci 7461141cc406Sopenharmony_ci regs[0x34] = 0xf0; 7462141cc406Sopenharmony_ci regs[0x35] = 0x1b; 7463141cc406Sopenharmony_ci regs[0x36] = 0x29; 7464141cc406Sopenharmony_ci regs[0x3a] = 0x1b; 7465141cc406Sopenharmony_ci regs[0x85] = 0x60; 7466141cc406Sopenharmony_ci regs[0x86] = 0x5a; 7467141cc406Sopenharmony_ci regs[0x87] = 0xc0; 7468141cc406Sopenharmony_ci regs[0x8a] = 0x08; /* 81c=2076 */ 7469141cc406Sopenharmony_ci 7470141cc406Sopenharmony_ci regs[0xc1] = 0xff; 7471141cc406Sopenharmony_ci regs[0xce] = 0xff; 7472141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 7473141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 7474141cc406Sopenharmony_ci 7475141cc406Sopenharmony_ci regs[0xe2] = 0x01; 7476141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7477141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7478141cc406Sopenharmony_ci timing=0x081a; 7479141cc406Sopenharmony_ci exposure=5499; 7480141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7481141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7482141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7483141cc406Sopenharmony_ci regs[0xea] = 0x00; 7484141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7485141cc406Sopenharmony_ci regs[0xec] = 0x00; 7486141cc406Sopenharmony_ci regs[0xed] = 0x00; 7487141cc406Sopenharmony_ci regs[0xef] = 0x00; 7488141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7489141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7490141cc406Sopenharmony_ci regs[0x33] = 0x83; 7491141cc406Sopenharmony_ci regs[0x40] = 0xac; 7492141cc406Sopenharmony_ci regs[0x50] = 0x00; 7493141cc406Sopenharmony_ci regs[0x64] = 0x01; 7494141cc406Sopenharmony_ci regs[0x65] = 0x20; 7495141cc406Sopenharmony_ci regs[0x88] = 0xae; 7496141cc406Sopenharmony_ci regs[0x8d] = 0xbc; 7497141cc406Sopenharmony_ci regs[0x8e] = 0x63; 7498141cc406Sopenharmony_ci regs[0xc0] = 0xe0; 7499141cc406Sopenharmony_ci regs[0xc2] = 0x01; 7500141cc406Sopenharmony_ci regs[0xc3] = 0x1f; 7501141cc406Sopenharmony_ci regs[0xc4] = 0x00; 7502141cc406Sopenharmony_ci regs[0xc5] = 0xfe; 7503141cc406Sopenharmony_ci regs[0xc6] = 0xff; 7504141cc406Sopenharmony_ci regs[0xc7] = 0xff; 7505141cc406Sopenharmony_ci regs[0xc8] = 0x00; 7506141cc406Sopenharmony_ci regs[0xc9] = 0x3f; 7507141cc406Sopenharmony_ci regs[0xca] = 0xfe; 7508141cc406Sopenharmony_ci regs[0xcb] = 0xff; 7509141cc406Sopenharmony_ci regs[0xcc] = 0x00; 7510141cc406Sopenharmony_ci regs[0xcd] = 0x00; 7511141cc406Sopenharmony_ci regs[0xd1] = 0xec; 7512141cc406Sopenharmony_ci regs[0xd2] = 0x0d; 7513141cc406Sopenharmony_ci regs[0xd3] = 0x05; 7514141cc406Sopenharmony_ci regs[0xd4] = 0x67; 7515141cc406Sopenharmony_ci regs[0xd7] = 0x10; 7516141cc406Sopenharmony_ci regs[0xd8] = 0x52; 7517141cc406Sopenharmony_ci break; 7518141cc406Sopenharmony_ci 7519141cc406Sopenharmony_ci case SENSOR_TYPE_4400: 7520141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 1200 dpi\n"); 7521141cc406Sopenharmony_ci regs[0x13] = 0x39; 7522141cc406Sopenharmony_ci regs[0x14] = 0xf0; 7523141cc406Sopenharmony_ci regs[0x15] = 0x29; 7524141cc406Sopenharmony_ci regs[0x16] = 0x00; 7525141cc406Sopenharmony_ci regs[0x17] = 0x10; 7526141cc406Sopenharmony_ci regs[0x23] = 0x00; 7527141cc406Sopenharmony_ci regs[0x33] = 0x86; 7528141cc406Sopenharmony_ci regs[0x34] = 0xf0; 7529141cc406Sopenharmony_ci regs[0x35] = 0x0e; 7530141cc406Sopenharmony_ci regs[0x39] = 0x00; 7531141cc406Sopenharmony_ci regs[0x3a] = 0x0e; 7532141cc406Sopenharmony_ci regs[0x40] = 0xac; 7533141cc406Sopenharmony_ci regs[0x64] = 0x02; 7534141cc406Sopenharmony_ci regs[0x65] = 0x10; 7535141cc406Sopenharmony_ci timing=0x081a; 7536141cc406Sopenharmony_ci regs[0x85] = 0x60; 7537141cc406Sopenharmony_ci regs[0x86] = 0x5a; 7538141cc406Sopenharmony_ci regs[0x87] = 0xc0; 7539141cc406Sopenharmony_ci regs[0x88] = 0xae; 7540141cc406Sopenharmony_ci regs[0x8d] = 0xbc; 7541141cc406Sopenharmony_ci regs[0x8e] = 0x63; 7542141cc406Sopenharmony_ci regs[0xc0] = 0xe0; 7543141cc406Sopenharmony_ci regs[0xc1] = 0xff; 7544141cc406Sopenharmony_ci regs[0xc2] = 0x01; 7545141cc406Sopenharmony_ci regs[0xc3] = 0x1f; 7546141cc406Sopenharmony_ci regs[0xc4] = 0x00; 7547141cc406Sopenharmony_ci regs[0xc5] = 0xfe; 7548141cc406Sopenharmony_ci regs[0xc6] = 0xff; 7549141cc406Sopenharmony_ci regs[0xc7] = 0xff; 7550141cc406Sopenharmony_ci regs[0xc8] = 0x00; 7551141cc406Sopenharmony_ci regs[0xc9] = 0x3f; 7552141cc406Sopenharmony_ci regs[0xca] = 0xfe; 7553141cc406Sopenharmony_ci regs[0xcb] = 0xff; 7554141cc406Sopenharmony_ci regs[0xcc] = 0x00; 7555141cc406Sopenharmony_ci regs[0xcd] = 0x00; 7556141cc406Sopenharmony_ci regs[0xce] = 0xff; 7557141cc406Sopenharmony_ci regs[0xcf] = 0xf5; 7558141cc406Sopenharmony_ci regs[0xd0] = 0xf7; 7559141cc406Sopenharmony_ci regs[0xd1] = 0xec; 7560141cc406Sopenharmony_ci regs[0xd2] = 0x0d; 7561141cc406Sopenharmony_ci regs[0xd3] = 0x05; 7562141cc406Sopenharmony_ci regs[0xd4] = 0x67; 7563141cc406Sopenharmony_ci regs[0xd7] = 0x10; 7564141cc406Sopenharmony_ci regs[0xd8] = 0x52; 7565141cc406Sopenharmony_ci regs[0xe2] = 0x00; 7566141cc406Sopenharmony_ci regs[0xe3] = 0x00; 7567141cc406Sopenharmony_ci regs[0xe4] = 0x00; 7568141cc406Sopenharmony_ci regs[0xe7] = 0x00; 7569141cc406Sopenharmony_ci regs[0xe8] = 0x00; 7570141cc406Sopenharmony_ci regs[0xe9] = 0x00; 7571141cc406Sopenharmony_ci regs[0xea] = 0x00; 7572141cc406Sopenharmony_ci regs[0xeb] = 0x00; 7573141cc406Sopenharmony_ci regs[0xec] = 0x00; 7574141cc406Sopenharmony_ci regs[0xed] = 0x00; 7575141cc406Sopenharmony_ci regs[0xef] = 0x00; 7576141cc406Sopenharmony_ci regs[0xf0] = 0x00; 7577141cc406Sopenharmony_ci regs[0xf2] = 0x00; 7578141cc406Sopenharmony_ci exposure=10999; 7579141cc406Sopenharmony_ci *status1 = 0x10; 7580141cc406Sopenharmony_ci *status2 = 0x23; 7581141cc406Sopenharmony_ci break; 7582141cc406Sopenharmony_ci 7583141cc406Sopenharmony_ci case SENSOR_TYPE_4400_BARE: 7584141cc406Sopenharmony_ci DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n"); 7585141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 7586141cc406Sopenharmony_ci break; 7587141cc406Sopenharmony_ci } 7588141cc406Sopenharmony_ci break; 7589141cc406Sopenharmony_ci } 7590141cc406Sopenharmony_ci 7591141cc406Sopenharmony_ci /* apply computed settings */ 7592141cc406Sopenharmony_ci SET_DOUBLE (regs, EXPOSURE_REG, exposure); 7593141cc406Sopenharmony_ci SET_DOUBLE (regs, TIMING_REG, timing); 7594141cc406Sopenharmony_ci SET_DOUBLE (regs, TIMING1_REG, timing+1); 7595141cc406Sopenharmony_ci SET_DOUBLE (regs, TIMING2_REG, timing+2); 7596141cc406Sopenharmony_ci 7597141cc406Sopenharmony_ci /* sets divisor */ 7598141cc406Sopenharmony_ci regs[0xd3] = rts8891_data_format (dev->xdpi, dev->sensor); 7599141cc406Sopenharmony_ci 7600141cc406Sopenharmony_ci /* toggle front panel light to signal gray scan */ 7601141cc406Sopenharmony_ci if (session->params.format == SANE_FRAME_GRAY) 7602141cc406Sopenharmony_ci { 7603141cc406Sopenharmony_ci *status1 = (*status1 & 0x0F) | 0x10; 7604141cc406Sopenharmony_ci } 7605141cc406Sopenharmony_ci 7606141cc406Sopenharmony_ci return status; 7607141cc406Sopenharmony_ci} 7608141cc406Sopenharmony_ci 7609141cc406Sopenharmony_ci/* set up the shadow registers for scan, depending on scan parameters */ 7610141cc406Sopenharmony_ci/* the ultimate goal is to have no direct access to registers, but to */ 7611141cc406Sopenharmony_ci/* set them through helper functions */ 7612141cc406Sopenharmony_ci/* NOTE : I couldn't manage to get scans that really uses gray settings. */ 7613141cc406Sopenharmony_ci/* The windows driver is always scanning in color, so we do the same. */ 7614141cc406Sopenharmony_ci/* For now, the only mode that could be done would be 300 dpi gray scan, */ 7615141cc406Sopenharmony_ci/* based on the register settings of find_origin() */ 7616141cc406Sopenharmony_cistatic SANE_Status 7617141cc406Sopenharmony_ciwrite_scan_registers (struct Rts8891_Session *session) 7618141cc406Sopenharmony_ci{ 7619141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 7620141cc406Sopenharmony_ci SANE_Byte control; 7621141cc406Sopenharmony_ci SANE_Byte status1, status2; 7622141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 7623141cc406Sopenharmony_ci 7624141cc406Sopenharmony_ci /* setup registers for scan */ 7625141cc406Sopenharmony_ci status=setup_scan_registers (session, &status1, &status2, dev->regs); 7626141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 7627141cc406Sopenharmony_ci { 7628141cc406Sopenharmony_ci DBG (DBG_error0, "write_scan_registers: failed to setup registers\n"); 7629141cc406Sopenharmony_ci return status; 7630141cc406Sopenharmony_ci } 7631141cc406Sopenharmony_ci 7632141cc406Sopenharmony_ci /* check if session is idle */ 7633141cc406Sopenharmony_ci control = 0x00; 7634141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 7635141cc406Sopenharmony_ci if (control != 0) 7636141cc406Sopenharmony_ci { 7637141cc406Sopenharmony_ci DBG (DBG_error0, "write_scan_registers: scanner is not idle!\n"); 7638141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 7639141cc406Sopenharmony_ci } 7640141cc406Sopenharmony_ci 7641141cc406Sopenharmony_ci /* effective write of register set for scan */ 7642141cc406Sopenharmony_ci status = rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); 7643141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 7644141cc406Sopenharmony_ci { 7645141cc406Sopenharmony_ci DBG (DBG_error0, "write_scan_registers: failed to write registers\n"); 7646141cc406Sopenharmony_ci } 7647141cc406Sopenharmony_ci return status; 7648141cc406Sopenharmony_ci} 7649141cc406Sopenharmony_ci 7650141cc406Sopenharmony_ci/** 7651141cc406Sopenharmony_ci * This function parks head relying by moving head backward by a 7652141cc406Sopenharmony_ci * very large amount without scanning 7653141cc406Sopenharmony_ci */ 7654141cc406Sopenharmony_cistatic SANE_Status 7655141cc406Sopenharmony_cipark_head (struct Rts8891_Device *dev, SANE_Bool wait) 7656141cc406Sopenharmony_ci{ 7657141cc406Sopenharmony_ci SANE_Status status; 7658141cc406Sopenharmony_ci SANE_Byte reg, control; 7659141cc406Sopenharmony_ci /* the hammer way : set all regs */ 7660141cc406Sopenharmony_ci SANE_Byte regs[244]; 7661141cc406Sopenharmony_ci 7662141cc406Sopenharmony_ci DBG (DBG_proc, "park_head: start\n"); 7663141cc406Sopenharmony_ci 7664141cc406Sopenharmony_ci reg = 0x8d; 7665141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 7666141cc406Sopenharmony_ci reg = 0xad; 7667141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 7668141cc406Sopenharmony_ci 7669141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 7670141cc406Sopenharmony_ci 7671141cc406Sopenharmony_ci reg = 0xff; 7672141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, 0x23, ®); 7673141cc406Sopenharmony_ci 7674141cc406Sopenharmony_ci /* TODO create write_double_reg */ 7675141cc406Sopenharmony_ci if (dev->sensor != SENSOR_TYPE_4400) 7676141cc406Sopenharmony_ci { 7677141cc406Sopenharmony_ci dev->regs[0x16] = 0x07; 7678141cc406Sopenharmony_ci dev->regs[0x17] = 0x00; 7679141cc406Sopenharmony_ci } 7680141cc406Sopenharmony_ci else 7681141cc406Sopenharmony_ci { 7682141cc406Sopenharmony_ci dev->regs[0x16] = 0x0f; 7683141cc406Sopenharmony_ci dev->regs[0x17] = 0x10; 7684141cc406Sopenharmony_ci } 7685141cc406Sopenharmony_ci sanei_rts88xx_write_regs (dev->devnum, 0x16, dev->regs + 0x16, 2); 7686141cc406Sopenharmony_ci 7687141cc406Sopenharmony_ci reg = 0x8d; 7688141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 7689141cc406Sopenharmony_ci reg = 0xad; 7690141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); 7691141cc406Sopenharmony_ci 7692141cc406Sopenharmony_ci /* 0x20 expected */ 7693141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®); 7694141cc406Sopenharmony_ci if (reg != 0x20) 7695141cc406Sopenharmony_ci { 7696141cc406Sopenharmony_ci DBG (DBG_warn, "park_head: unexpected controller value 0x%02x\n", reg); 7697141cc406Sopenharmony_ci } 7698141cc406Sopenharmony_ci 7699141cc406Sopenharmony_ci /* head parking */ 7700141cc406Sopenharmony_ci status = rts8891_park (dev, regs, wait); 7701141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 7702141cc406Sopenharmony_ci { 7703141cc406Sopenharmony_ci DBG (DBG_error, "park_head: failed to park head!\n"); 7704141cc406Sopenharmony_ci } 7705141cc406Sopenharmony_ci 7706141cc406Sopenharmony_ci DBG (DBG_proc, "park_head: end\n"); 7707141cc406Sopenharmony_ci return status; 7708141cc406Sopenharmony_ci} 7709141cc406Sopenharmony_ci 7710141cc406Sopenharmony_ci/* update button status 7711141cc406Sopenharmony_ci * button access is allowed during scan, which is useful for 'cancel' button 7712141cc406Sopenharmony_ci */ 7713141cc406Sopenharmony_cistatic SANE_Status 7714141cc406Sopenharmony_ciupdate_button_status (struct Rts8891_Session *session) 7715141cc406Sopenharmony_ci{ 7716141cc406Sopenharmony_ci SANE_Int mask = 0, i; 7717141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 7718141cc406Sopenharmony_ci SANE_Bool lock = SANE_FALSE; 7719141cc406Sopenharmony_ci 7720141cc406Sopenharmony_ci /* while scanning, interface is reserved, so don't claim/release it */ 7721141cc406Sopenharmony_ci if (session->scanning != SANE_TRUE) 7722141cc406Sopenharmony_ci { 7723141cc406Sopenharmony_ci lock = SANE_TRUE; 7724141cc406Sopenharmony_ci 7725141cc406Sopenharmony_ci /* claim the interface to reserve device */ 7726141cc406Sopenharmony_ci if (session->dev->conf.allowsharing == SANE_TRUE) 7727141cc406Sopenharmony_ci { 7728141cc406Sopenharmony_ci status = sanei_usb_claim_interface (session->dev->devnum, 0); 7729141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 7730141cc406Sopenharmony_ci { 7731141cc406Sopenharmony_ci DBG (DBG_warn, 7732141cc406Sopenharmony_ci "update_button_status: cannot claim usb interface\n"); 7733141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 7734141cc406Sopenharmony_ci } 7735141cc406Sopenharmony_ci } 7736141cc406Sopenharmony_ci } 7737141cc406Sopenharmony_ci 7738141cc406Sopenharmony_ci /* effective button reading */ 7739141cc406Sopenharmony_ci status = rts8891_read_buttons (session->dev->devnum, &mask); 7740141cc406Sopenharmony_ci 7741141cc406Sopenharmony_ci /* release interface if needed */ 7742141cc406Sopenharmony_ci if (lock == SANE_TRUE) 7743141cc406Sopenharmony_ci { 7744141cc406Sopenharmony_ci if (session->dev->conf.allowsharing == SANE_TRUE) 7745141cc406Sopenharmony_ci { 7746141cc406Sopenharmony_ci sanei_usb_release_interface (session->dev->devnum, 0); 7747141cc406Sopenharmony_ci } 7748141cc406Sopenharmony_ci } 7749141cc406Sopenharmony_ci 7750141cc406Sopenharmony_ci for (i = 0; i < session->dev->model->buttons; i++) 7751141cc406Sopenharmony_ci { 7752141cc406Sopenharmony_ci if (mask & (1 << i)) 7753141cc406Sopenharmony_ci { 7754141cc406Sopenharmony_ci session->val[OPT_BUTTON_1 + i].w = SANE_TRUE; 7755141cc406Sopenharmony_ci DBG (DBG_io2, "update_button_status: setting button %d to TRUE\n", 7756141cc406Sopenharmony_ci i + 1); 7757141cc406Sopenharmony_ci } 7758141cc406Sopenharmony_ci } 7759141cc406Sopenharmony_ci return status; 7760141cc406Sopenharmony_ci} 7761141cc406Sopenharmony_ci 7762141cc406Sopenharmony_ci/* set lamp status, 0 for lamp off 7763141cc406Sopenharmony_ci * other values set lamp on */ 7764141cc406Sopenharmony_cistatic SANE_Status 7765141cc406Sopenharmony_ciset_lamp_state (struct Rts8891_Session *session, int on) 7766141cc406Sopenharmony_ci{ 7767141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 7768141cc406Sopenharmony_ci SANE_Byte reg; 7769141cc406Sopenharmony_ci 7770141cc406Sopenharmony_ci /* claim the interface reserve device */ 7771141cc406Sopenharmony_ci if (session->dev->conf.allowsharing == SANE_TRUE) 7772141cc406Sopenharmony_ci { 7773141cc406Sopenharmony_ci status = sanei_usb_claim_interface (session->dev->devnum, 0); 7774141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 7775141cc406Sopenharmony_ci { 7776141cc406Sopenharmony_ci DBG (DBG_warn, "set_lamp_state: cannot claim usb interface\n"); 7777141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 7778141cc406Sopenharmony_ci } 7779141cc406Sopenharmony_ci } 7780141cc406Sopenharmony_ci 7781141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (session->dev->devnum, LAMP_REG, ®); 7782141cc406Sopenharmony_ci if (on) 7783141cc406Sopenharmony_ci { 7784141cc406Sopenharmony_ci DBG (DBG_info, "set_lamp_state: lamp on\n"); 7785141cc406Sopenharmony_ci reg = session->dev->regs[LAMP_REG] | 0x80; 7786141cc406Sopenharmony_ci } 7787141cc406Sopenharmony_ci else 7788141cc406Sopenharmony_ci { 7789141cc406Sopenharmony_ci DBG (DBG_info, "set_lamp_state: lamp off\n"); 7790141cc406Sopenharmony_ci reg = session->dev->regs[LAMP_REG] & 0x7F; 7791141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 7792141cc406Sopenharmony_ci /* if lamp is switched off, warming up will be needed */ 7793141cc406Sopenharmony_ci session->dev->last_scan.tv_sec = 0; 7794141cc406Sopenharmony_ci#endif 7795141cc406Sopenharmony_ci } 7796141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (session->dev->devnum, LAMP_REG, ®); 7797141cc406Sopenharmony_ci 7798141cc406Sopenharmony_ci /* release interface and return status from lamp setting */ 7799141cc406Sopenharmony_ci if (session->dev->conf.allowsharing == SANE_TRUE) 7800141cc406Sopenharmony_ci { 7801141cc406Sopenharmony_ci sanei_usb_release_interface (session->dev->devnum, 0); 7802141cc406Sopenharmony_ci } 7803141cc406Sopenharmony_ci return status; 7804141cc406Sopenharmony_ci} 7805141cc406Sopenharmony_ci 7806141cc406Sopenharmony_ci/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ 7807