1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 1999 Paul Mackerras 4141cc406Sopenharmony_ci Copyright (C) 2000 Adrian Perez Jorge 5141cc406Sopenharmony_ci Copyright (C) 2001 Frank Zago 6141cc406Sopenharmony_ci Copyright (C) 2001 Marcio Teixeira 7141cc406Sopenharmony_ci Parts copyright (C) 2006 Patrick Lessard 8141cc406Sopenharmony_ci 9141cc406Sopenharmony_ci This file is part of the SANE package. 10141cc406Sopenharmony_ci 11141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 12141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 13141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 14141cc406Sopenharmony_ci License, or (at your option) any later version. 15141cc406Sopenharmony_ci 16141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 17141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 18141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19141cc406Sopenharmony_ci General Public License for more details. 20141cc406Sopenharmony_ci 21141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 22141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 25141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 26141cc406Sopenharmony_ci 27141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 28141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 29141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 30141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 31141cc406Sopenharmony_ci account of linking the SANE library code into it. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 34141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 35141cc406Sopenharmony_ci License. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 38141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 39141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 40141cc406Sopenharmony_ci 41141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 42141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 43141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 44141cc406Sopenharmony_ci 45141cc406Sopenharmony_ci Defines a driver and API for accessing the UMAX Astra 1220U 46141cc406Sopenharmony_ci USB scanner. Based on the original command line tool by Paul 47141cc406Sopenharmony_ci Mackerras. 48141cc406Sopenharmony_ci 49141cc406Sopenharmony_ci The UMAX Astra 1220U scanner uses the PowerVision PV8630 50141cc406Sopenharmony_ci Parallel Port to USB bridge. This chip is also used 51141cc406Sopenharmony_ci by the HP4200C flatbed scanner. Adrian Perez Jorge wrote 52141cc406Sopenharmony_ci a nice interface file for that chip and Frank Zago adapted 53141cc406Sopenharmony_ci it to use the sanei_usb interface. Thanks, guys, for making 54141cc406Sopenharmony_ci my life easier! :) 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci */ 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#include <string.h> 60141cc406Sopenharmony_ci#include <errno.h> 61141cc406Sopenharmony_ci#include <fcntl.h> 62141cc406Sopenharmony_ci#include <sys/types.h> 63141cc406Sopenharmony_ci#include <sys/stat.h> 64141cc406Sopenharmony_ci#include <sys/ioctl.h> 65141cc406Sopenharmony_ci#include <math.h> 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci/* 68141cc406Sopenharmony_ci * The backend performs test scans in order to calibrate 69141cc406Sopenharmony_ci * the CCD and to find the zero location. If you would like 70141cc406Sopenharmony_ci * to look at those scans, define DEBUG_CALIBRATION to have 71141cc406Sopenharmony_ci * the backend save "find_zero.pgm" and "calibration.pgm" to 72141cc406Sopenharmony_ci * disk. 73141cc406Sopenharmony_ci */ 74141cc406Sopenharmony_ci/* #define DEBUG_CALIBRATION */ 75141cc406Sopenharmony_ci 76141cc406Sopenharmony_ci/* 77141cc406Sopenharmony_ci * Define DEBUG_BOUNDS to insert paranoid array bounds 78141cc406Sopenharmony_ci * overrun detection into the code. 79141cc406Sopenharmony_ci */ 80141cc406Sopenharmony_ci/* #define DEBUG_BOUNDS */ 81141cc406Sopenharmony_ci 82141cc406Sopenharmony_ci/* These values are empirically determined and are given 83141cc406Sopenharmony_ci * in 1/600 inch units. If UMAX_MAX_HEIGHT is too large, 84141cc406Sopenharmony_ci * the scanner may grind its gears. I assume there is a 85141cc406Sopenharmony_ci * physical limit to UMAX_MAX_WIDTH as well (based on the 86141cc406Sopenharmony_ci * sensor size) but I do not know what it is. The current 87141cc406Sopenharmony_ci * value can be increased beyond what it is now, but you 88141cc406Sopenharmony_ci * gain nothing in usable scan area (you only scan more 89141cc406Sopenharmony_ci * of the underside of the scanner's plastic lid). 90141cc406Sopenharmony_ci */ 91141cc406Sopenharmony_ci 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_ci#define UMAX_MAX_WIDTH 5400 94141cc406Sopenharmony_ci#define UMAX_MAX_HEIGHT 7040 95141cc406Sopenharmony_ci 96141cc406Sopenharmony_ci/* Buffer size. Specifies the size of the buffer that is 97141cc406Sopenharmony_ci * used to copy data from the scanner. The old command 98141cc406Sopenharmony_ci * line driver had this set at 0x80000 which is likely 99141cc406Sopenharmony_ci * the largest possible chunk of data that can be. 100141cc406Sopenharmony_ci * at once. This is probably most efficient, but using 101141cc406Sopenharmony_ci * a lower value for the SANE driver makes the driver 102141cc406Sopenharmony_ci * more responsive to interaction. 103141cc406Sopenharmony_ci */ 104141cc406Sopenharmony_ci#define BUFFER_SIZE 0x80000 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci/* Constants that can be used with set_lamp_state to 107141cc406Sopenharmony_ci * control the state of the scanner's lamp 108141cc406Sopenharmony_ci */ 109141cc406Sopenharmony_citypedef enum 110141cc406Sopenharmony_ci{ 111141cc406Sopenharmony_ci UMAX_LAMP_OFF = 0, 112141cc406Sopenharmony_ci UMAX_LAMP_ON = 1 113141cc406Sopenharmony_ci} 114141cc406Sopenharmony_ciUMAX_Lamp_State; 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci/* Constants that can be used with move to control 117141cc406Sopenharmony_ci * the rate of scanner head movement 118141cc406Sopenharmony_ci */ 119141cc406Sopenharmony_citypedef enum 120141cc406Sopenharmony_ci{ 121141cc406Sopenharmony_ci UMAX_NOT_FINE = 0, 122141cc406Sopenharmony_ci UMAX_FINE = 1 123141cc406Sopenharmony_ci} 124141cc406Sopenharmony_ciUMAX_Speed; 125141cc406Sopenharmony_ci 126141cc406Sopenharmony_ci/* If anyone knows some descriptive names for these, 127141cc406Sopenharmony_ci * please update 128141cc406Sopenharmony_ci */ 129141cc406Sopenharmony_citypedef enum 130141cc406Sopenharmony_ci{ 131141cc406Sopenharmony_ci CMD_0 = 0x00, 132141cc406Sopenharmony_ci CMD_1 = 0x01, 133141cc406Sopenharmony_ci CMD_2 = 0x02, 134141cc406Sopenharmony_ci CMD_4 = 0x04, 135141cc406Sopenharmony_ci CMD_8 = 0x08, 136141cc406Sopenharmony_ci CMD_40 = 0x40, 137141cc406Sopenharmony_ci CMD_WRITE = 0x80, 138141cc406Sopenharmony_ci CMD_READ = 0xc0 139141cc406Sopenharmony_ci} 140141cc406Sopenharmony_ciUMAX_Cmd; 141141cc406Sopenharmony_ci 142141cc406Sopenharmony_ci/* Product IDs for Astra scanners 143141cc406Sopenharmony_ci */ 144141cc406Sopenharmony_citypedef enum 145141cc406Sopenharmony_ci{ 146141cc406Sopenharmony_ci ASTRA_1220U = 0x0010, 147141cc406Sopenharmony_ci ASTRA_2000U = 0x0030, 148141cc406Sopenharmony_ci ASTRA_2100U = 0x0130 149141cc406Sopenharmony_ci} 150141cc406Sopenharmony_ciUMAX_Model; 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_ci/* The bytes UMAX_SYNC1 and UMAX_SYNC2 serve as a 153141cc406Sopenharmony_ci * synchronization signal. Unintentional sync bytes 154141cc406Sopenharmony_ci * in the data stream are escaped with UMAX_ESCAPE 155141cc406Sopenharmony_ci * character 156141cc406Sopenharmony_ci */ 157141cc406Sopenharmony_ci 158141cc406Sopenharmony_ci#define UMAX_SYNC1 0x55 159141cc406Sopenharmony_ci#define UMAX_SYNC2 0xaa 160141cc406Sopenharmony_ci#define UMAX_ESCAPE 0x1b 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci/* Status bits. These bits are active low. 163141cc406Sopenharmony_ci * In umax_pp, UMAX_REVERSE_BIT is called 164141cc406Sopenharmony_ci * MOTOR_BIT. 165141cc406Sopenharmony_ci */ 166141cc406Sopenharmony_ci 167141cc406Sopenharmony_ci#define UMAX_FORWARD_BIT 0x40 168141cc406Sopenharmony_ci#define UMAX_ERROR_BIT 0x20 169141cc406Sopenharmony_ci#define UMAX_MOTOR_OFF_BIT 0x08 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci#define UMAX_OK 0x48 /* Used to be 0xC8 */ 172141cc406Sopenharmony_ci#define UMAX_OK_WITH_MOTOR 0x40 /* Used to be 0xD0 */ 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci#define UMAX_STATUS_MASK 0x68 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci/* This byte is used as a placeholder for bytes that are parameterized 177141cc406Sopenharmony_ci * in the opcode strings */ 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci#define XXXX 0x00 180141cc406Sopenharmony_ci 181141cc406Sopenharmony_ci/* This macro is used to check the return code of 182141cc406Sopenharmony_ci * functions 183141cc406Sopenharmony_ci */ 184141cc406Sopenharmony_ci#define CHK(A) {if( (res = A) != SANE_STATUS_GOOD ) { \ 185141cc406Sopenharmony_ci DBG( 1, "Failure on line of %s: %d\n", __FILE__, \ 186141cc406Sopenharmony_ci __LINE__ ); return A; }} 187141cc406Sopenharmony_ci 188141cc406Sopenharmony_ci/* Macros that are used for array overrun detection 189141cc406Sopenharmony_ci * (when DEBUG_BOUNDS is defined) 190141cc406Sopenharmony_ci */ 191141cc406Sopenharmony_ci#ifdef DEBUG_BOUNDS 192141cc406Sopenharmony_ci#define PAD 10 193141cc406Sopenharmony_ci#define PAD_ARRAY( A, len ) {int i; \ 194141cc406Sopenharmony_ci for( i = 0; i < PAD; i++ ) {A[len+i]=0x55;}} 195141cc406Sopenharmony_ci 196141cc406Sopenharmony_ci#define CHK_ARRAY( A, len ) {int i;for( i = 0; i < PAD; i++ ) {\ 197141cc406Sopenharmony_ci if(A[len+i]!=0x55) { \ 198141cc406Sopenharmony_ci DBG( 1, "Array overrun detected on line %d\n", __LINE__ ); \ 199141cc406Sopenharmony_ci }}} 200141cc406Sopenharmony_ci#else 201141cc406Sopenharmony_ci#define PAD 0 202141cc406Sopenharmony_ci#define PAD_ARRAY( A, len ) 203141cc406Sopenharmony_ci#define CHK_ARRAY( A, len ) 204141cc406Sopenharmony_ci#endif 205141cc406Sopenharmony_ci 206141cc406Sopenharmony_ci 207141cc406Sopenharmony_ci/* This data structure contains data related 208141cc406Sopenharmony_ci * to the scanning process. 209141cc406Sopenharmony_ci */ 210141cc406Sopenharmony_citypedef struct 211141cc406Sopenharmony_ci{ 212141cc406Sopenharmony_ci /* Constant data */ 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci int color; 215141cc406Sopenharmony_ci int w; 216141cc406Sopenharmony_ci int h; 217141cc406Sopenharmony_ci int xo; 218141cc406Sopenharmony_ci int yo; 219141cc406Sopenharmony_ci int xdpi; /* Physical x dpi */ 220141cc406Sopenharmony_ci int ydpi; /* Physical y dpi */ 221141cc406Sopenharmony_ci int xsamp; 222141cc406Sopenharmony_ci int ysamp; 223141cc406Sopenharmony_ci 224141cc406Sopenharmony_ci int xskip; 225141cc406Sopenharmony_ci int yskip; 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci int fd; /* Device file handle */ 228141cc406Sopenharmony_ci UMAX_Model model; 229141cc406Sopenharmony_ci 230141cc406Sopenharmony_ci /* Raw scan data buffer */ 231141cc406Sopenharmony_ci 232141cc406Sopenharmony_ci unsigned char *p; 233141cc406Sopenharmony_ci int bh; /* Size of buffer in lines */ 234141cc406Sopenharmony_ci int hexp; /* Scan lines yet to be read */ 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci /* Decoding logic */ 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci int x, y, maxh; 239141cc406Sopenharmony_ci int done; /* Boolean, all lines decoded */ 240141cc406Sopenharmony_ci 241141cc406Sopenharmony_ci /* Calibration data */ 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci unsigned char caldata[16070 + PAD]; 244141cc406Sopenharmony_ci 245141cc406Sopenharmony_ci /* Scan head position */ 246141cc406Sopenharmony_ci 247141cc406Sopenharmony_ci int scanner_ypos; 248141cc406Sopenharmony_ci int scanner_yorg; 249141cc406Sopenharmony_ci} 250141cc406Sopenharmony_ciUMAX_Handle; 251141cc406Sopenharmony_ci 252141cc406Sopenharmony_citypedef unsigned char UMAX_Status_Byte; 253141cc406Sopenharmony_ci 254141cc406Sopenharmony_ci 255141cc406Sopenharmony_ci#if 0 256141cc406Sopenharmony_cistatic void 257141cc406Sopenharmony_ciunused_operations () 258141cc406Sopenharmony_ci{ 259141cc406Sopenharmony_ci /* These operations are unused anywhere in the driver */ 260141cc406Sopenharmony_ci 261141cc406Sopenharmony_ci unsigned char opb8[35] = { 262141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 263141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x18, 0x10, 0x03, 264141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 265141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x13, 0x1a 266141cc406Sopenharmony_ci }; 267141cc406Sopenharmony_ci 268141cc406Sopenharmony_ci unsigned char opb9[35] = { 269141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 270141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x41, 0x20, 0x24, 271141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 272141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x13, 0x1a 273141cc406Sopenharmony_ci }; 274141cc406Sopenharmony_ci 275141cc406Sopenharmony_ci unsigned char opb10[35] = { 276141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 277141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x41, 0x60, 0x4f, 278141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 279141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x93, 0x1a 280141cc406Sopenharmony_ci }; 281141cc406Sopenharmony_ci 282141cc406Sopenharmony_ci unsigned char opc5[16] = { 283141cc406Sopenharmony_ci 0x05, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00, 284141cc406Sopenharmony_ci 0x00, 0x30, 0x0c, 0xc3, 0xa4, 0x00 285141cc406Sopenharmony_ci }; 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci unsigned char opc6[16] = { 288141cc406Sopenharmony_ci 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00, 289141cc406Sopenharmony_ci 0x88, 0x48, 0x0c, 0x83, 0xa4, 0x00 290141cc406Sopenharmony_ci }; 291141cc406Sopenharmony_ci 292141cc406Sopenharmony_ci unsigned char opc7[16] = { 293141cc406Sopenharmony_ci 0x05, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00, 294141cc406Sopenharmony_ci 0xec, 0x4e, 0x0c, 0xc3, 0xa4, 0x00 295141cc406Sopenharmony_ci }; 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ci unsigned char opd2[8] = { 298141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, 0x00, 0x30 299141cc406Sopenharmony_ci }; 300141cc406Sopenharmony_ci} 301141cc406Sopenharmony_ci#endif 302141cc406Sopenharmony_ci 303141cc406Sopenharmony_ci#if 0 304141cc406Sopenharmony_cistatic SANE_Status 305141cc406Sopenharmony_cicalib (UMAX_Handle * scan) 306141cc406Sopenharmony_ci{ 307141cc406Sopenharmony_ci unsigned char buf[65536]; 308141cc406Sopenharmony_ci opc5[11] = 0x30; 309141cc406Sopenharmony_ci opd2[7] = 0x30; 310141cc406Sopenharmony_ci CHK (get_pixels (scan, opc5, opb8, opd2, ope, 24, 0, buff)); 311141cc406Sopenharmony_ci 312141cc406Sopenharmony_ci opc5[11] = 0x40; 313141cc406Sopenharmony_ci opd2[7] = 0x40; 314141cc406Sopenharmony_ci CHK (get_pixels (scan, opc5, opb8, opd2, ope, 24, 0, buff)); 315141cc406Sopenharmony_ci 316141cc406Sopenharmony_ci opd2[6] = 8; 317141cc406Sopenharmony_ci opd2[7] = 0x30; 318141cc406Sopenharmony_ci CHK (get_pixels (scan, opc6, opb9, opd2, ope, 0x200, 1, buff)); 319141cc406Sopenharmony_ci 320141cc406Sopenharmony_ci opc7[10] = 0xec; 321141cc406Sopenharmony_ci opd2[6] = 0xc; 322141cc406Sopenharmony_ci opd2[7] = 0x40; 323141cc406Sopenharmony_ci CHK (get_pixels (scan, opc7, opb10, opd2, ope, 5300, 1, buff)); 324141cc406Sopenharmony_ci 325141cc406Sopenharmony_ci opc7[10] = 0xed; 326141cc406Sopenharmony_ci opd2[6] = 0xd; 327141cc406Sopenharmony_ci CHK (get_pixels (scan, opc7, opb10, opd2, ope, 5300, 0, buff)); 328141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 329141cc406Sopenharmony_ci} 330141cc406Sopenharmony_ci#endif 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci 333141cc406Sopenharmony_ci/* This seems to configure the pv8630 chip somehow. I wish 334141cc406Sopenharmony_ci * all the magic numbers were defined as self-descriptive 335141cc406Sopenharmony_ci * constants somewhere. I made some guesses based on what 336141cc406Sopenharmony_ci * I found in "pv8630.c", but alas there wasn't enough in 337141cc406Sopenharmony_ci * there. If you know what this does, please let me know! 338141cc406Sopenharmony_ci */ 339141cc406Sopenharmony_cistatic SANE_Status 340141cc406Sopenharmony_cixxxops (UMAX_Handle * scan) 341141cc406Sopenharmony_ci{ 342141cc406Sopenharmony_ci SANE_Status res; 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci DBG (9, "doing xxxops\n"); 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RMODE, 0x02)); 347141cc406Sopenharmony_ci 348141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x0E)); 349141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RDATA, 0x40)); 350141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x06)); 351141cc406Sopenharmony_ci CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0x38, 0xFF)); 352141cc406Sopenharmony_ci 353141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x07)); 354141cc406Sopenharmony_ci CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0x38, 0xFF)); 355141cc406Sopenharmony_ci 356141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x04)); 357141cc406Sopenharmony_ci CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0xF8, 0xFF)); 358141cc406Sopenharmony_ci 359141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x05)); 360141cc406Sopenharmony_ci CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_UNKNOWN, 0x05, 0xFF)); 361141cc406Sopenharmony_ci 362141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x04)); 363141cc406Sopenharmony_ci 364141cc406Sopenharmony_ci CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RMODE, 0x1E)); 365141cc406Sopenharmony_ci 366141cc406Sopenharmony_ci return res; 367141cc406Sopenharmony_ci} 368141cc406Sopenharmony_ci 369141cc406Sopenharmony_ci/* 370141cc406Sopenharmony_ciApparently sends the two synchronization characters followed 371141cc406Sopenharmony_ciby the command length, followed by the command number 372141cc406Sopenharmony_ci*/ 373141cc406Sopenharmony_cistatic SANE_Status 374141cc406Sopenharmony_ciusync (UMAX_Handle * scan, UMAX_Cmd cmd, int len) 375141cc406Sopenharmony_ci{ 376141cc406Sopenharmony_ci UMAX_Status_Byte s0, s4; 377141cc406Sopenharmony_ci SANE_Status res; 378141cc406Sopenharmony_ci unsigned char buf[4]; 379141cc406Sopenharmony_ci size_t nb; 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci DBG (80, "usync: len = %d, cmd = %d\n", len, cmd); 382141cc406Sopenharmony_ci 383141cc406Sopenharmony_ci buf[0] = UMAX_SYNC1; 384141cc406Sopenharmony_ci buf[1] = UMAX_SYNC2; 385141cc406Sopenharmony_ci 386141cc406Sopenharmony_ci nb = 2; 387141cc406Sopenharmony_ci CHK (sanei_pv8630_flush_buffer (scan->fd)); 388141cc406Sopenharmony_ci CHK (sanei_pv8630_prep_bulkwrite (scan->fd, nb)); 389141cc406Sopenharmony_ci CHK (sanei_pv8630_bulkwrite (scan->fd, buf, &nb)); 390141cc406Sopenharmony_ci 391141cc406Sopenharmony_ci CHK (sanei_pv8630_wait_byte 392141cc406Sopenharmony_ci (scan->fd, PV8630_RSTATUS, UMAX_OK, UMAX_STATUS_MASK, 20)); 393141cc406Sopenharmony_ci 394141cc406Sopenharmony_ci buf[0] = len >> 16; 395141cc406Sopenharmony_ci buf[1] = len >> 8; 396141cc406Sopenharmony_ci buf[2] = len; 397141cc406Sopenharmony_ci buf[3] = cmd; 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci nb = 4; 400141cc406Sopenharmony_ci CHK (sanei_pv8630_flush_buffer (scan->fd)); 401141cc406Sopenharmony_ci CHK (sanei_pv8630_prep_bulkwrite (scan->fd, nb)); 402141cc406Sopenharmony_ci CHK (sanei_pv8630_bulkwrite (scan->fd, buf, &nb)); 403141cc406Sopenharmony_ci 404141cc406Sopenharmony_ci CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0)); 405141cc406Sopenharmony_ci CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4)); 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci DBG (90, "usync: s0 = %#x s4 = %#x\n", s0, s4); 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 410141cc406Sopenharmony_ci} 411141cc406Sopenharmony_ci 412141cc406Sopenharmony_ci/* 413141cc406Sopenharmony_ciThis function escapes any synchronization sequence that may be 414141cc406Sopenharmony_ciin data, storing the result in buf. In the worst case where 415141cc406Sopenharmony_cievery character gets escaped buf must be at least twice as 416141cc406Sopenharmony_cilarge as dlen. 417141cc406Sopenharmony_ci*/ 418141cc406Sopenharmony_cistatic int 419141cc406Sopenharmony_cibescape (const unsigned char *data, int dlen, unsigned char *buf, int blen) 420141cc406Sopenharmony_ci{ 421141cc406Sopenharmony_ci const unsigned char *p; 422141cc406Sopenharmony_ci unsigned char *q; 423141cc406Sopenharmony_ci int i, c; 424141cc406Sopenharmony_ci i = blen; /* Eliminate compiler warning about unused param */ 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci p = data; 427141cc406Sopenharmony_ci q = buf; 428141cc406Sopenharmony_ci for (i = 0; i < dlen; ++i) 429141cc406Sopenharmony_ci { 430141cc406Sopenharmony_ci c = *p++; 431141cc406Sopenharmony_ci if (c == UMAX_ESCAPE 432141cc406Sopenharmony_ci || (c == UMAX_SYNC2 && i > 0 && p[-2] == UMAX_SYNC1)) 433141cc406Sopenharmony_ci *q++ = UMAX_ESCAPE; 434141cc406Sopenharmony_ci *q++ = c; 435141cc406Sopenharmony_ci } 436141cc406Sopenharmony_ci return q - buf; 437141cc406Sopenharmony_ci} 438141cc406Sopenharmony_ci 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci 441141cc406Sopenharmony_ci/* Write */ 442141cc406Sopenharmony_ci 443141cc406Sopenharmony_cistatic SANE_Status 444141cc406Sopenharmony_cicwrite (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, const unsigned char *data, 445141cc406Sopenharmony_ci UMAX_Status_Byte * s) 446141cc406Sopenharmony_ci{ 447141cc406Sopenharmony_ci SANE_Status res; 448141cc406Sopenharmony_ci UMAX_Status_Byte s0, s4; 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci static unsigned char *escaped = NULL; 451141cc406Sopenharmony_ci static size_t escaped_size = 0; 452141cc406Sopenharmony_ci 453141cc406Sopenharmony_ci DBG (80, "cwrite: cmd = %d, len = %lu\n", cmd, (u_long) len); 454141cc406Sopenharmony_ci 455141cc406Sopenharmony_ci CHK (usync (scan, cmd | CMD_WRITE, len)); 456141cc406Sopenharmony_ci 457141cc406Sopenharmony_ci if (len <= 0) 458141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 459141cc406Sopenharmony_ci 460141cc406Sopenharmony_ci if (escaped_size < len * 2) 461141cc406Sopenharmony_ci { 462141cc406Sopenharmony_ci escaped_size = len * 2; 463141cc406Sopenharmony_ci if (escaped) 464141cc406Sopenharmony_ci free (escaped); 465141cc406Sopenharmony_ci escaped = malloc (escaped_size); 466141cc406Sopenharmony_ci if (escaped == NULL) 467141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 468141cc406Sopenharmony_ci } 469141cc406Sopenharmony_ci 470141cc406Sopenharmony_ci len = bescape (data, len, escaped, len * 2); 471141cc406Sopenharmony_ci 472141cc406Sopenharmony_ci CHK (sanei_pv8630_wait_byte 473141cc406Sopenharmony_ci (scan->fd, PV8630_RSTATUS, UMAX_OK, UMAX_STATUS_MASK, 20)); 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci CHK (sanei_pv8630_flush_buffer (scan->fd)); 476141cc406Sopenharmony_ci CHK (sanei_pv8630_prep_bulkwrite (scan->fd, len)); 477141cc406Sopenharmony_ci CHK (sanei_pv8630_bulkwrite (scan->fd, escaped, &len)); 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_ci CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4)); 480141cc406Sopenharmony_ci CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0)); 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci DBG (90, "cwrite: s0 = %#x s4 = %#x\n", s0, s4); 483141cc406Sopenharmony_ci 484141cc406Sopenharmony_ci if (s) 485141cc406Sopenharmony_ci *s = s0; 486141cc406Sopenharmony_ci 487141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 488141cc406Sopenharmony_ci} 489141cc406Sopenharmony_ci 490141cc406Sopenharmony_ci/* Read */ 491141cc406Sopenharmony_ci 492141cc406Sopenharmony_cistatic SANE_Status 493141cc406Sopenharmony_cicread (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, unsigned char *data, 494141cc406Sopenharmony_ci UMAX_Status_Byte * s) 495141cc406Sopenharmony_ci{ 496141cc406Sopenharmony_ci SANE_Status res; 497141cc406Sopenharmony_ci UMAX_Status_Byte s0, s4; 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci DBG (80, "cread: cmd = %d, len = %lu\n", cmd, (u_long) len); 500141cc406Sopenharmony_ci 501141cc406Sopenharmony_ci CHK (usync (scan, cmd | CMD_READ, len)); 502141cc406Sopenharmony_ci 503141cc406Sopenharmony_ci if (len > 0) 504141cc406Sopenharmony_ci { 505141cc406Sopenharmony_ci CHK (sanei_pv8630_wait_byte 506141cc406Sopenharmony_ci (scan->fd, PV8630_RSTATUS, UMAX_OK_WITH_MOTOR, UMAX_STATUS_MASK, 507141cc406Sopenharmony_ci 2000)); 508141cc406Sopenharmony_ci 509141cc406Sopenharmony_ci while (len > 0) 510141cc406Sopenharmony_ci { 511141cc406Sopenharmony_ci size_t req, n; 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci req = n = (len > 0xf000) ? 0xf000 : len; 514141cc406Sopenharmony_ci CHK (sanei_pv8630_prep_bulkread (scan->fd, n)); 515141cc406Sopenharmony_ci CHK (sanei_pv8630_bulkread (scan->fd, data, &n)); 516141cc406Sopenharmony_ci if (n < req) 517141cc406Sopenharmony_ci { 518141cc406Sopenharmony_ci DBG (1, "qread: Expecting to read %lu, only got %lu\n", (u_long) req, (u_long) n); 519141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 520141cc406Sopenharmony_ci } 521141cc406Sopenharmony_ci data += n; 522141cc406Sopenharmony_ci len -= n; 523141cc406Sopenharmony_ci } 524141cc406Sopenharmony_ci } 525141cc406Sopenharmony_ci 526141cc406Sopenharmony_ci CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4)); 527141cc406Sopenharmony_ci CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0)); 528141cc406Sopenharmony_ci 529141cc406Sopenharmony_ci DBG (90, "cwrite: s0 = %#x s4 = %#x\n", s0, s4); 530141cc406Sopenharmony_ci 531141cc406Sopenharmony_ci if (s) 532141cc406Sopenharmony_ci *s = s0; 533141cc406Sopenharmony_ci 534141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 535141cc406Sopenharmony_ci} 536141cc406Sopenharmony_ci 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci 539141cc406Sopenharmony_ci/* Seems to be like cwrite, with a verification option */ 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_cistatic SANE_Status 542141cc406Sopenharmony_cicwritev (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, const unsigned char *data, 543141cc406Sopenharmony_ci UMAX_Status_Byte * s) 544141cc406Sopenharmony_ci{ 545141cc406Sopenharmony_ci SANE_Status res; 546141cc406Sopenharmony_ci unsigned char buf[16384]; 547141cc406Sopenharmony_ci 548141cc406Sopenharmony_ci /* Write out the opcode */ 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci CHK (cwrite (scan, cmd, len, data, s)); 551141cc406Sopenharmony_ci if (len <= 0) 552141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 553141cc406Sopenharmony_ci 554141cc406Sopenharmony_ci /* Read the opcode back */ 555141cc406Sopenharmony_ci 556141cc406Sopenharmony_ci CHK (cread (scan, cmd, len, buf, NULL)); 557141cc406Sopenharmony_ci if (bcmp (buf, data, len)) 558141cc406Sopenharmony_ci { 559141cc406Sopenharmony_ci DBG (1, "cwritev: verification failed\n"); 560141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 561141cc406Sopenharmony_ci } 562141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 563141cc406Sopenharmony_ci} 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_ci 566141cc406Sopenharmony_ci/* Send command */ 567141cc406Sopenharmony_ci 568141cc406Sopenharmony_cistatic SANE_Status 569141cc406Sopenharmony_cicsend (UMAX_Handle * scan, UMAX_Cmd cmd) 570141cc406Sopenharmony_ci{ 571141cc406Sopenharmony_ci DBG (80, "csend: cmd = %d\n", cmd); 572141cc406Sopenharmony_ci 573141cc406Sopenharmony_ci return usync (scan, cmd, 0); 574141cc406Sopenharmony_ci} 575141cc406Sopenharmony_ci 576141cc406Sopenharmony_ci/* Lamp control */ 577141cc406Sopenharmony_ci 578141cc406Sopenharmony_cistatic SANE_Status 579141cc406Sopenharmony_cicwritev_opc1_lamp_ctrl (UMAX_Handle * scan, UMAX_Lamp_State state) 580141cc406Sopenharmony_ci{ 581141cc406Sopenharmony_ci unsigned char opc1[16] = { 582141cc406Sopenharmony_ci 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x13, 0x05, 583141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x80, 0xf0, 0x00 584141cc406Sopenharmony_ci }; 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci DBG (9, "cwritev_opc1: set lamp state = %s\n", 587141cc406Sopenharmony_ci (state == UMAX_LAMP_OFF) ? "off" : "on"); 588141cc406Sopenharmony_ci opc1[14] = (state == UMAX_LAMP_OFF) ? 0x90 : 0xf0; 589141cc406Sopenharmony_ci return cwritev (scan, CMD_2, 16, opc1, NULL); 590141cc406Sopenharmony_ci} 591141cc406Sopenharmony_ci 592141cc406Sopenharmony_ci 593141cc406Sopenharmony_ci/* Restore Head 1220U */ 594141cc406Sopenharmony_ci 595141cc406Sopenharmony_cistatic SANE_Status 596141cc406Sopenharmony_cicwritev_opb3_restore (UMAX_Handle * scan) 597141cc406Sopenharmony_ci{ 598141cc406Sopenharmony_ci unsigned char opb3[35] = { 599141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 600141cc406Sopenharmony_ci 0xc1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 601141cc406Sopenharmony_ci 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 602141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x1b, 0x1a, 603141cc406Sopenharmony_ci }; 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci SANE_Status res; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci DBG (9, "cwritev_opb3_restore:\n"); 608141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 35, opb3, NULL)); 609141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 610141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 611141cc406Sopenharmony_ci} 612141cc406Sopenharmony_ci 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ci/* Restore Head 2100U */ 615141cc406Sopenharmony_ci 616141cc406Sopenharmony_cistatic SANE_Status 617141cc406Sopenharmony_cicwritev_opb3_restore_2100U (UMAX_Handle * scan) 618141cc406Sopenharmony_ci{ 619141cc406Sopenharmony_ci unsigned char opb3[36] = { 620141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 621141cc406Sopenharmony_ci 0xc1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 622141cc406Sopenharmony_ci 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 623141cc406Sopenharmony_ci 0xe9, 0x68, 0xdf, 0x0b, 0x1a, 0x00 624141cc406Sopenharmony_ci }; 625141cc406Sopenharmony_ci 626141cc406Sopenharmony_ci SANE_Status res; 627141cc406Sopenharmony_ci 628141cc406Sopenharmony_ci DBG (9, "cwritev_opb3_restore:\n"); 629141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 36, opb3, NULL)); 630141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 631141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 632141cc406Sopenharmony_ci} 633141cc406Sopenharmony_ci 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci/* Initialize and turn lamp on 1220U */ 636141cc406Sopenharmony_ci 637141cc406Sopenharmony_ci/* 638141cc406Sopenharmony_ciThis function seems to perform various things. First, it loads a default 639141cc406Sopenharmony_cigamma information (which is used for the calibration scan), returns the 640141cc406Sopenharmony_cihead to the park position, and turns the lamp on. This function used to 641141cc406Sopenharmony_cibe split up into two parts, umaxinit and umaxinit2. 642141cc406Sopenharmony_ci*/ 643141cc406Sopenharmony_ci 644141cc406Sopenharmony_cistatic SANE_Status 645141cc406Sopenharmony_ciumaxinit (UMAX_Handle * scan) 646141cc406Sopenharmony_ci{ 647141cc406Sopenharmony_ci unsigned char opb[34] = { 648141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 649141cc406Sopenharmony_ci 0xc1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xe0, 0xac, 650141cc406Sopenharmony_ci 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 651141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0xf0 652141cc406Sopenharmony_ci }; 653141cc406Sopenharmony_ci unsigned char opb1[35] = { 654141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 655141cc406Sopenharmony_ci 0xc1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xe0, 0xac, 656141cc406Sopenharmony_ci 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 657141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x10, 0x1a 658141cc406Sopenharmony_ci }; 659141cc406Sopenharmony_ci unsigned char opb2[35] = { 660141cc406Sopenharmony_ci 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 661141cc406Sopenharmony_ci 0xc1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xe0, 0xac, 662141cc406Sopenharmony_ci 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 663141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x10, 0x1a 664141cc406Sopenharmony_ci }; 665141cc406Sopenharmony_ci unsigned char opb4[35] = { 666141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 667141cc406Sopenharmony_ci 0xc1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xe0, 0xac, 668141cc406Sopenharmony_ci 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 669141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0xf3, 0x1b 670141cc406Sopenharmony_ci }; 671141cc406Sopenharmony_ci unsigned char opbx[35]; 672141cc406Sopenharmony_ci unsigned char opc[16] = { 673141cc406Sopenharmony_ci 0x02, 0x80, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x07, 674141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x80, 0xf0, 0x00 675141cc406Sopenharmony_ci }; 676141cc406Sopenharmony_ci unsigned char opcx[16]; 677141cc406Sopenharmony_ci unsigned char opd[8] = { 678141cc406Sopenharmony_ci 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa 679141cc406Sopenharmony_ci }; 680141cc406Sopenharmony_ci 681141cc406Sopenharmony_ci SANE_Status res; 682141cc406Sopenharmony_ci UMAX_Status_Byte s; 683141cc406Sopenharmony_ci unsigned char ramp[800]; 684141cc406Sopenharmony_ci int i; 685141cc406Sopenharmony_ci unsigned char *p; 686141cc406Sopenharmony_ci 687141cc406Sopenharmony_ci DBG (3, "umaxinit called\n"); 688141cc406Sopenharmony_ci 689141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 690141cc406Sopenharmony_ci CHK (xxxops (scan)); 691141cc406Sopenharmony_ci 692141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 34, opb, &s)); 693141cc406Sopenharmony_ci CHK (cread (scan, CMD_8, 35, opbx, &s)); 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 35, opb1, &s)); 696141cc406Sopenharmony_ci 697141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 698141cc406Sopenharmony_ci 699141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 2:\n"); 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci /* The following code appears to send three 256 entry, 8-bit gamma tables 702141cc406Sopenharmony_ci * to the scanner 703141cc406Sopenharmony_ci */ 704141cc406Sopenharmony_ci p = ramp; 705141cc406Sopenharmony_ci *p++ = 0; 706141cc406Sopenharmony_ci *p++ = 0; 707141cc406Sopenharmony_ci *p++ = 0; 708141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 709141cc406Sopenharmony_ci *p++ = i; 710141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 711141cc406Sopenharmony_ci *p++ = i; 712141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 713141cc406Sopenharmony_ci *p++ = i; 714141cc406Sopenharmony_ci *p++ = 0xaa; 715141cc406Sopenharmony_ci *p++ = 0xaa; 716141cc406Sopenharmony_ci 717141cc406Sopenharmony_ci res = cwritev (scan, CMD_4, p - ramp, ramp, &s); 718141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 719141cc406Sopenharmony_ci { 720141cc406Sopenharmony_ci DBG (4, "umaxinit: Writing ramp 1 failed (is this a 2000U?)\n"); 721141cc406Sopenharmony_ci } 722141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 35, opb1, &s)); 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 3:\n"); 727141cc406Sopenharmony_ci 728141cc406Sopenharmony_ci /* The following code appears to send a 256 entry, 16-bit gamma table 729141cc406Sopenharmony_ci * to the scanner 730141cc406Sopenharmony_ci */ 731141cc406Sopenharmony_ci p = ramp; 732141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 733141cc406Sopenharmony_ci { 734141cc406Sopenharmony_ci *p++ = i; 735141cc406Sopenharmony_ci *p++ = 0; 736141cc406Sopenharmony_ci } 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci res = cwrite (scan, CMD_4, p - ramp, ramp, &s); 739141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 740141cc406Sopenharmony_ci { 741141cc406Sopenharmony_ci DBG (4, "umaxinit: Writing ramp 2 failed (is this a 2000U?)\n"); 742141cc406Sopenharmony_ci } 743141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 35, opb2, &s)); 744141cc406Sopenharmony_ci 745141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 4:\n"); 748141cc406Sopenharmony_ci 749141cc406Sopenharmony_ci /* The following code appears to send a 256 entry, 16-bit gamma table 750141cc406Sopenharmony_ci * to the scanner. 751141cc406Sopenharmony_ci */ 752141cc406Sopenharmony_ci p = ramp; 753141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 754141cc406Sopenharmony_ci { 755141cc406Sopenharmony_ci *p++ = i; 756141cc406Sopenharmony_ci *p++ = 4; 757141cc406Sopenharmony_ci } 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci res = cwritev (scan, CMD_4, p - ramp, ramp, &s); 760141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 761141cc406Sopenharmony_ci { 762141cc406Sopenharmony_ci DBG (4, "umaxinit: Writing ramp 3 failed (is this a 2000U?)\n"); 763141cc406Sopenharmony_ci } 764141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 35, opb1, &s)); 765141cc406Sopenharmony_ci 766141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_2, 16, opc, NULL)); 767141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_1, 8, opd, NULL)); 768141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 769141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 5: s = %#x\n", s); 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci if ((s & 0x40) == 0) 774141cc406Sopenharmony_ci { 775141cc406Sopenharmony_ci DBG (4, "umaxinit: turning on lamp and restoring\n"); 776141cc406Sopenharmony_ci CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON)); 777141cc406Sopenharmony_ci CHK (cwritev_opb3_restore (scan)); 778141cc406Sopenharmony_ci 779141cc406Sopenharmony_ci for (i = 0; i < 60; ++i) 780141cc406Sopenharmony_ci { 781141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 782141cc406Sopenharmony_ci DBG (4, "umaxinit: s = %#x\n", s); 783141cc406Sopenharmony_ci if ((s & 0x40) != 0) 784141cc406Sopenharmony_ci break; 785141cc406Sopenharmony_ci DBG (4, "umaxinit: sleeping\n"); 786141cc406Sopenharmony_ci usleep (500000); 787141cc406Sopenharmony_ci } 788141cc406Sopenharmony_ci } 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 6\n"); 791141cc406Sopenharmony_ci 792141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci /* The following stuff used to be in umaxinit2() */ 795141cc406Sopenharmony_ci 796141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 7\n"); 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci CHK (xxxops (scan)); 799141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 800141cc406Sopenharmony_ci CHK (xxxops (scan)); 801141cc406Sopenharmony_ci 802141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 34, opb4, &s)); 803141cc406Sopenharmony_ci CHK (cread (scan, CMD_8, 35, opbx, &s)); 804141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 16, opcx, &s)); 805141cc406Sopenharmony_ci 806141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_2, 16, opc, NULL)); 807141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_1, 8, opd, NULL)); 808141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 809141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci DBG (4, "umaxinit: checkpoint 8: s = %d\n", s); 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 814141cc406Sopenharmony_ci} 815141cc406Sopenharmony_ci 816141cc406Sopenharmony_ci/* Initialize and turn lamp on 2100U */ 817141cc406Sopenharmony_ci 818141cc406Sopenharmony_cistatic SANE_Status 819141cc406Sopenharmony_ciumaxinit_2100U (UMAX_Handle * scan) 820141cc406Sopenharmony_ci{ 821141cc406Sopenharmony_ci 822141cc406Sopenharmony_ci unsigned char opx[36]; 823141cc406Sopenharmony_ci unsigned char opy[16]; 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci 826141cc406Sopenharmony_ci SANE_Status res; 827141cc406Sopenharmony_ci UMAX_Status_Byte s; 828141cc406Sopenharmony_ci 829141cc406Sopenharmony_ci DBG (3, "umaxinit called\n"); 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci CHK (xxxops (scan)); 832141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 833141cc406Sopenharmony_ci 834141cc406Sopenharmony_ci /* Turn lamp on */ 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_ci cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci CHK (cread (scan, CMD_8, 36, opx, &s)); 839141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 16, opy, &s)); 840141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 841141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 842141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 843141cc406Sopenharmony_ci 844141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 845141cc406Sopenharmony_ci} 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci/* Move head 1220U */ 849141cc406Sopenharmony_ci 850141cc406Sopenharmony_cistatic SANE_Status 851141cc406Sopenharmony_cimove (UMAX_Handle * scan, int distance, UMAX_Speed fine) 852141cc406Sopenharmony_ci{ 853141cc406Sopenharmony_ci unsigned char opc4[16] = { 854141cc406Sopenharmony_ci 0x01, XXXX, XXXX, XXXX, 0x00, 0x00, 0x60, 0x2f, XXXX, XXXX, 855141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x80, XXXX, 0x00 856141cc406Sopenharmony_ci }; 857141cc406Sopenharmony_ci unsigned char opb5[35] = { 858141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 859141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 860141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 861141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x13, 0x1a 862141cc406Sopenharmony_ci }; 863141cc406Sopenharmony_ci unsigned char opb7[35] = { 864141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 865141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 866141cc406Sopenharmony_ci 0x01, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 867141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x13, 0x1a 868141cc406Sopenharmony_ci }; 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_ci unsigned char ope[8] = { 871141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff 872141cc406Sopenharmony_ci }; 873141cc406Sopenharmony_ci 874141cc406Sopenharmony_ci unsigned char ope2[3] = { 875141cc406Sopenharmony_ci 0x00, 0xff, 0x8f 876141cc406Sopenharmony_ci }; 877141cc406Sopenharmony_ci unsigned char buf[512 + PAD]; 878141cc406Sopenharmony_ci 879141cc406Sopenharmony_ci SANE_Status res; 880141cc406Sopenharmony_ci UMAX_Status_Byte s; 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_ci SANE_Bool rev = distance < 0; 883141cc406Sopenharmony_ci int skip = (rev ? -distance : distance) - 1; 884141cc406Sopenharmony_ci 885141cc406Sopenharmony_ci DBG (9, "move: distance = %d, scanner_ypos = %d\n", distance, 886141cc406Sopenharmony_ci scan->scanner_ypos); 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ci PAD_ARRAY (buf, 512); 889141cc406Sopenharmony_ci 890141cc406Sopenharmony_ci if (distance == 0) 891141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 892141cc406Sopenharmony_ci 893141cc406Sopenharmony_ci opc4[1] = skip << 6; 894141cc406Sopenharmony_ci opc4[2] = skip >> 2; 895141cc406Sopenharmony_ci opc4[3] = (rev ? 0x20 : 0x70) + ((skip >> 10) & 0xf); 896141cc406Sopenharmony_ci opc4[9] = rev ? 0x01 : 0x05; 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci if (fine == UMAX_FINE) 899141cc406Sopenharmony_ci { 900141cc406Sopenharmony_ci opc4[8] = 0x2f; 901141cc406Sopenharmony_ci opc4[14] = 0xa4; 902141cc406Sopenharmony_ci } 903141cc406Sopenharmony_ci else 904141cc406Sopenharmony_ci { 905141cc406Sopenharmony_ci opc4[8] = 0x17; 906141cc406Sopenharmony_ci opc4[14] = 0xac; 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci scan->scanner_ypos += 910141cc406Sopenharmony_ci (fine == UMAX_FINE ? distance : 2 * distance + (rev ? -1 : 1)); 911141cc406Sopenharmony_ci scan->scanner_ypos = (scan->scanner_ypos + (rev ? 0 : 3)) & ~3; 912141cc406Sopenharmony_ci 913141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_2, 16, opc4, &s)); 914141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_8, 35, rev ? opb7 : opb5, &s)); 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 917141cc406Sopenharmony_ci DBG (10, "move: checkpoint 1: s = %d\n", s); 918141cc406Sopenharmony_ci 919141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 920141cc406Sopenharmony_ci if (rev) 921141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 3, ope2, &s)) 922141cc406Sopenharmony_ci else 923141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 8, ope, &s)); 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci 926141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 929141cc406Sopenharmony_ci 930141cc406Sopenharmony_ci DBG (10, "move: checkpoint 2: s = %d\n", s); 931141cc406Sopenharmony_ci 932141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 933141cc406Sopenharmony_ci DBG (10, "move: checkpoint 3: s = %d\n", s); 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_ci CHK (cread (scan, CMD_4, 512, buf, &s)); 936141cc406Sopenharmony_ci 937141cc406Sopenharmony_ci CHK_ARRAY (buf, 512); 938141cc406Sopenharmony_ci 939141cc406Sopenharmony_ci return res; 940141cc406Sopenharmony_ci} 941141cc406Sopenharmony_ci 942141cc406Sopenharmony_ci 943141cc406Sopenharmony_ci 944141cc406Sopenharmony_ci/* Move head 2100U */ 945141cc406Sopenharmony_ci 946141cc406Sopenharmony_cistatic SANE_Status 947141cc406Sopenharmony_cimove_2100U (UMAX_Handle * scan, int distance, UMAX_Speed fine) 948141cc406Sopenharmony_ci{ 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci 951141cc406Sopenharmony_ci unsigned char opc4[16] = { 952141cc406Sopenharmony_ci 0x01, XXXX, XXXX, XXXX, 0x00, 0x00, 0x60, 0x2f, XXXX, XXXX, 953141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x80, XXXX, 0x00 954141cc406Sopenharmony_ci }; 955141cc406Sopenharmony_ci unsigned char opb5[36] = { 956141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 957141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 958141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 959141cc406Sopenharmony_ci 0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00 960141cc406Sopenharmony_ci }; 961141cc406Sopenharmony_ci unsigned char opb7[36] = { 962141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 963141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 964141cc406Sopenharmony_ci 0x01, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 965141cc406Sopenharmony_ci 0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00 966141cc406Sopenharmony_ci }; 967141cc406Sopenharmony_ci unsigned char ope[8] = { 968141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff 969141cc406Sopenharmony_ci }; 970141cc406Sopenharmony_ci unsigned char ope2[3] = { 971141cc406Sopenharmony_ci 0x00, 0xff, 0xff 972141cc406Sopenharmony_ci }; 973141cc406Sopenharmony_ci unsigned char buf[512]; 974141cc406Sopenharmony_ci 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci SANE_Status res; 977141cc406Sopenharmony_ci UMAX_Status_Byte s; 978141cc406Sopenharmony_ci 979141cc406Sopenharmony_ci SANE_Bool rev = distance < 0; 980141cc406Sopenharmony_ci int skip = (rev ? -distance : distance) - 1; 981141cc406Sopenharmony_ci 982141cc406Sopenharmony_ci DBG (9, "move: distance = %d, scanner_ypos = %d\n", distance, 983141cc406Sopenharmony_ci scan->scanner_ypos); 984141cc406Sopenharmony_ci 985141cc406Sopenharmony_ci PAD_ARRAY (buf, 512); 986141cc406Sopenharmony_ci 987141cc406Sopenharmony_ci if (distance == 0) 988141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 989141cc406Sopenharmony_ci 990141cc406Sopenharmony_ci opc4[1] = skip << 6; 991141cc406Sopenharmony_ci opc4[2] = skip >> 2; 992141cc406Sopenharmony_ci opc4[3] = (rev ? 0x20 : 0x70) + ((skip >> 10) & 0x0f); 993141cc406Sopenharmony_ci opc4[9] = rev ? 0x01 : 0x05; 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_ci if (fine == UMAX_FINE) 996141cc406Sopenharmony_ci { 997141cc406Sopenharmony_ci opc4[8] = 0x2b; 998141cc406Sopenharmony_ci opc4[14] = 0xa4; 999141cc406Sopenharmony_ci } 1000141cc406Sopenharmony_ci else 1001141cc406Sopenharmony_ci { 1002141cc406Sopenharmony_ci opc4[8] = 0x15; 1003141cc406Sopenharmony_ci opc4[14] = 0xac; 1004141cc406Sopenharmony_ci } 1005141cc406Sopenharmony_ci 1006141cc406Sopenharmony_ci scan->scanner_ypos += 1007141cc406Sopenharmony_ci (fine == UMAX_FINE ? distance : 2 * distance + (rev ? -1 : 1)); 1008141cc406Sopenharmony_ci scan->scanner_ypos = (scan->scanner_ypos + (rev ? 0 : 3)) & ~3; 1009141cc406Sopenharmony_ci 1010141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_2, 16, opc4, &s)); 1011141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_8, 36, rev ? opb7 : opb5, &s)); 1012141cc406Sopenharmony_ci 1013141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1014141cc406Sopenharmony_ci DBG (10, "move: checkpoint 1: s = %d\n", s); 1015141cc406Sopenharmony_ci 1016141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1017141cc406Sopenharmony_ci 1018141cc406Sopenharmony_ci if (rev) 1019141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 3, ope2, &s)) 1020141cc406Sopenharmony_ci else 1021141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 8, ope, &s)); 1022141cc406Sopenharmony_ci 1023141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 1024141cc406Sopenharmony_ci 1025141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci DBG (10, "move: checkpoint 2: s = %d\n", s); 1028141cc406Sopenharmony_ci 1029141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1030141cc406Sopenharmony_ci DBG (10, "move: checkpoint 3: s = %d\n", s); 1031141cc406Sopenharmony_ci 1032141cc406Sopenharmony_ci CHK (cread (scan, CMD_4, 512, buf, &s)); 1033141cc406Sopenharmony_ci 1034141cc406Sopenharmony_ci CHK_ARRAY (buf, 512); 1035141cc406Sopenharmony_ci 1036141cc406Sopenharmony_ci return res; 1037141cc406Sopenharmony_ci} 1038141cc406Sopenharmony_ci 1039141cc406Sopenharmony_ci 1040141cc406Sopenharmony_ci/* Get pixel image 1220U */ 1041141cc406Sopenharmony_ci 1042141cc406Sopenharmony_cistatic SANE_Status 1043141cc406Sopenharmony_ciget_pixels (UMAX_Handle * scan, unsigned char *op2, unsigned char *op8, 1044141cc406Sopenharmony_ci unsigned char *op1, unsigned char *op4, int len, int zpos, 1045141cc406Sopenharmony_ci unsigned char *buf) 1046141cc406Sopenharmony_ci{ 1047141cc406Sopenharmony_ci SANE_Status res; 1048141cc406Sopenharmony_ci UMAX_Status_Byte s; 1049141cc406Sopenharmony_ci 1050141cc406Sopenharmony_ci DBG (9, "get_pixels: len = %d, zpos = %d\n", len, zpos); 1051141cc406Sopenharmony_ci 1052141cc406Sopenharmony_ci if (zpos == 0) 1053141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1054141cc406Sopenharmony_ci 1055141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_2, 16, op2, &s)); 1056141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_8, 35, op8, &s)); 1057141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_1, 8, op1, &s)); 1058141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1059141cc406Sopenharmony_ci 1060141cc406Sopenharmony_ci if (zpos == 1) 1061141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1062141cc406Sopenharmony_ci 1063141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 8, op4, &s)); 1064141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 1065141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1068141cc406Sopenharmony_ci 1069141cc406Sopenharmony_ci CHK (cread (scan, CMD_4, len, buf, &s)); 1070141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1071141cc406Sopenharmony_ci} 1072141cc406Sopenharmony_ci 1073141cc406Sopenharmony_ci 1074141cc406Sopenharmony_ci/* Get pixel image 2100U */ 1075141cc406Sopenharmony_ci 1076141cc406Sopenharmony_cistatic SANE_Status 1077141cc406Sopenharmony_ciget_pixels_2100U (UMAX_Handle * scan, unsigned char *op2, unsigned char *op8, 1078141cc406Sopenharmony_ci unsigned char *op1, unsigned char *op4, int len, int zpos, 1079141cc406Sopenharmony_ci unsigned char *buf) 1080141cc406Sopenharmony_ci{ 1081141cc406Sopenharmony_ci SANE_Status res; 1082141cc406Sopenharmony_ci UMAX_Status_Byte s; 1083141cc406Sopenharmony_ci 1084141cc406Sopenharmony_ci DBG (9, "get_pixels: len = %d, zpos = %d\n", len, zpos); 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_2, 16, op2, &s)); 1087141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_8, 36, op8, &s)); 1088141cc406Sopenharmony_ci 1089141cc406Sopenharmony_ci if (zpos == 1) 1090141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_1, 8, op1, &s)) 1091141cc406Sopenharmony_ci else 1092141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_1, 8, op1, &s)); 1093141cc406Sopenharmony_ci 1094141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1095141cc406Sopenharmony_ci 1096141cc406Sopenharmony_ci if (zpos == 1) 1097141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1098141cc406Sopenharmony_ci 1099141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 8, op4, &s)); 1100141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 1101141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1102141cc406Sopenharmony_ci 1103141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1104141cc406Sopenharmony_ci 1105141cc406Sopenharmony_ci CHK (cread (scan, CMD_4, len, buf, &s)); 1106141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1107141cc406Sopenharmony_ci} 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci 1110141cc406Sopenharmony_ci/* This function locates the black stripe under scanner lid */ 1111141cc406Sopenharmony_ci 1112141cc406Sopenharmony_cistatic int 1113141cc406Sopenharmony_cilocate_black_stripe (unsigned char *img, int w, int h) 1114141cc406Sopenharmony_ci{ 1115141cc406Sopenharmony_ci int epos, ecnt, x, y; 1116141cc406Sopenharmony_ci unsigned char *p; 1117141cc406Sopenharmony_ci 1118141cc406Sopenharmony_ci epos = 0; 1119141cc406Sopenharmony_ci ecnt = 0; 1120141cc406Sopenharmony_ci p = img; 1121141cc406Sopenharmony_ci for (x = 0; x < w; ++x, ++p) 1122141cc406Sopenharmony_ci { 1123141cc406Sopenharmony_ci int d, dmax = 0, dpos = 0; 1124141cc406Sopenharmony_ci unsigned char *q = img + x; 1125141cc406Sopenharmony_ci for (y = 1; y < h; ++y, q += w) 1126141cc406Sopenharmony_ci { 1127141cc406Sopenharmony_ci d = q[0] - q[w]; 1128141cc406Sopenharmony_ci if (d > dmax) 1129141cc406Sopenharmony_ci { 1130141cc406Sopenharmony_ci dmax = d; 1131141cc406Sopenharmony_ci dpos = y; 1132141cc406Sopenharmony_ci } 1133141cc406Sopenharmony_ci } 1134141cc406Sopenharmony_ci if (dmax > 0) 1135141cc406Sopenharmony_ci { 1136141cc406Sopenharmony_ci epos += dpos; 1137141cc406Sopenharmony_ci ++ecnt; 1138141cc406Sopenharmony_ci } 1139141cc406Sopenharmony_ci } 1140141cc406Sopenharmony_ci if (ecnt == 0) 1141141cc406Sopenharmony_ci epos = 70; 1142141cc406Sopenharmony_ci else 1143141cc406Sopenharmony_ci epos = (epos + ecnt / 2) / ecnt; 1144141cc406Sopenharmony_ci return epos; 1145141cc406Sopenharmony_ci} 1146141cc406Sopenharmony_ci 1147141cc406Sopenharmony_ci 1148141cc406Sopenharmony_ci/* To find the lowest head position 1220U */ 1149141cc406Sopenharmony_ci 1150141cc406Sopenharmony_cistatic SANE_Status 1151141cc406Sopenharmony_cifind_zero (UMAX_Handle * scan) 1152141cc406Sopenharmony_ci{ 1153141cc406Sopenharmony_ci unsigned char opc3[16] = { 1154141cc406Sopenharmony_ci 0xb4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x05, 1155141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x80, 0xa4, 0x00 1156141cc406Sopenharmony_ci }; 1157141cc406Sopenharmony_ci unsigned char ope1[8] = { 1158141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0xaa, 0xcc, 0xee, 0x80, 0xff 1159141cc406Sopenharmony_ci }; 1160141cc406Sopenharmony_ci unsigned char opb6[35] = { 1161141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 1162141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xfb, 0xc4, 0xe5, 1163141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x60, 0x4d, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 1164141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x13, 0x1a 1165141cc406Sopenharmony_ci }; 1166141cc406Sopenharmony_ci unsigned char opd1[8] = { 1167141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, 0x08, 0x00 1168141cc406Sopenharmony_ci }; 1169141cc406Sopenharmony_ci 1170141cc406Sopenharmony_ci SANE_Status res; 1171141cc406Sopenharmony_ci int s; 1172141cc406Sopenharmony_ci unsigned char *img; 1173141cc406Sopenharmony_ci 1174141cc406Sopenharmony_ci DBG (9, "find_zero:\n"); 1175141cc406Sopenharmony_ci 1176141cc406Sopenharmony_ci img = malloc (54000); 1177141cc406Sopenharmony_ci if (img == 0) 1178141cc406Sopenharmony_ci { 1179141cc406Sopenharmony_ci DBG (1, "out of memory (need 54000)\n"); 1180141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1181141cc406Sopenharmony_ci } 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1184141cc406Sopenharmony_ci CHK (get_pixels (scan, opc3, opb6, opd1, ope1, 54000, 1, img)); 1185141cc406Sopenharmony_ci 1186141cc406Sopenharmony_ci#ifdef DEBUG_CALIBRATION 1187141cc406Sopenharmony_ci { 1188141cc406Sopenharmony_ci int w = 300, h = 180; 1189141cc406Sopenharmony_ci FILE *f2 = fopen ("find_zero.pgm", "wb"); 1190141cc406Sopenharmony_ci fprintf (f2, "P5\n%d %d\n255\n", w, h); 1191141cc406Sopenharmony_ci fwrite (img, 1, w * h, f2); 1192141cc406Sopenharmony_ci fclose (f2); 1193141cc406Sopenharmony_ci } 1194141cc406Sopenharmony_ci#endif 1195141cc406Sopenharmony_ci 1196141cc406Sopenharmony_ci s = locate_black_stripe (img, 300, 180); 1197141cc406Sopenharmony_ci scan->scanner_yorg = scan->scanner_ypos + s + 64; 1198141cc406Sopenharmony_ci scan->scanner_ypos += 180 + 3; 1199141cc406Sopenharmony_ci scan->scanner_ypos &= ~3; 1200141cc406Sopenharmony_ci 1201141cc406Sopenharmony_ci free (img); 1202141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1203141cc406Sopenharmony_ci} 1204141cc406Sopenharmony_ci 1205141cc406Sopenharmony_ci 1206141cc406Sopenharmony_ci/* To find the lowest head position 2100U */ 1207141cc406Sopenharmony_ci 1208141cc406Sopenharmony_cistatic SANE_Status 1209141cc406Sopenharmony_cifind_zero_2100U (UMAX_Handle * scan) 1210141cc406Sopenharmony_ci{ 1211141cc406Sopenharmony_ci unsigned char opc3[16] = { 1212141cc406Sopenharmony_ci 0xb4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2b, 0x05, 1213141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x80, 0xa4, 0x00 1214141cc406Sopenharmony_ci }; 1215141cc406Sopenharmony_ci unsigned char ope1[8] = { 1216141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0xaa, 0xcc, 0xee, 0x80, 0xff 1217141cc406Sopenharmony_ci }; 1218141cc406Sopenharmony_ci unsigned char opb6[36] = { 1219141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 1220141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xfb, 0xc4, 0xe5, 1221141cc406Sopenharmony_ci 0x06, 0x00, 0x00, 0x60, 0x4d, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 1222141cc406Sopenharmony_ci 0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00 1223141cc406Sopenharmony_ci }; 1224141cc406Sopenharmony_ci unsigned char opd1[8] = { 1225141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, 0x08, 0x00 1226141cc406Sopenharmony_ci }; 1227141cc406Sopenharmony_ci 1228141cc406Sopenharmony_ci SANE_Status res; 1229141cc406Sopenharmony_ci int s; 1230141cc406Sopenharmony_ci unsigned char *img; 1231141cc406Sopenharmony_ci 1232141cc406Sopenharmony_ci DBG (9, "find_zero:\n"); 1233141cc406Sopenharmony_ci 1234141cc406Sopenharmony_ci img = malloc (54000); 1235141cc406Sopenharmony_ci if (img == 0) 1236141cc406Sopenharmony_ci { 1237141cc406Sopenharmony_ci DBG (1, "out of memory (need 54000)\n"); 1238141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1239141cc406Sopenharmony_ci } 1240141cc406Sopenharmony_ci 1241141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1242141cc406Sopenharmony_ci CHK (get_pixels_2100U (scan, opc3, opb6, opd1, ope1, 54000, 1, img)); 1243141cc406Sopenharmony_ci 1244141cc406Sopenharmony_ci#ifdef DEBUG_CALIBRATION 1245141cc406Sopenharmony_ci { 1246141cc406Sopenharmony_ci int w = 300, h = 180; 1247141cc406Sopenharmony_ci FILE *f2 = fopen ("find_zero.pgm", "wb"); 1248141cc406Sopenharmony_ci fprintf (f2, "P5\n%d %d\n255\n", w, h); 1249141cc406Sopenharmony_ci fwrite (img, 1, w * h, f2); 1250141cc406Sopenharmony_ci fclose (f2); 1251141cc406Sopenharmony_ci } 1252141cc406Sopenharmony_ci#endif 1253141cc406Sopenharmony_ci 1254141cc406Sopenharmony_ci s = locate_black_stripe (img, 300, 180); 1255141cc406Sopenharmony_ci scan->scanner_yorg = scan->scanner_ypos + s + 64; 1256141cc406Sopenharmony_ci scan->scanner_ypos += 180 + 3; 1257141cc406Sopenharmony_ci scan->scanner_ypos &= ~3; 1258141cc406Sopenharmony_ci 1259141cc406Sopenharmony_ci free (img); 1260141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1261141cc406Sopenharmony_ci} 1262141cc406Sopenharmony_ci 1263141cc406Sopenharmony_ci 1264141cc406Sopenharmony_ci/* Calibration 1220U */ 1265141cc406Sopenharmony_ci 1266141cc406Sopenharmony_ci/* 1267141cc406Sopenharmony_ciFormat of caldata: 1268141cc406Sopenharmony_ci 1269141cc406Sopenharmony_ci 5100 bytes of CCD calibration values 1270141cc406Sopenharmony_ci 5100 bytes of CCD calibration values 1271141cc406Sopenharmony_ci 5100 bytes of CCD calibration values 1272141cc406Sopenharmony_ci 256 bytes of gamma data for blue 1273141cc406Sopenharmony_ci 256 bytes of gamma data for green 1274141cc406Sopenharmony_ci 256 bytes of gamma data for red 1275141cc406Sopenharmony_ci 2 bytes of extra information 1276141cc406Sopenharmony_ci 1277141cc406Sopenharmony_ci*/ 1278141cc406Sopenharmony_cistatic SANE_Status 1279141cc406Sopenharmony_ciget_caldata (UMAX_Handle * scan, int color) 1280141cc406Sopenharmony_ci{ 1281141cc406Sopenharmony_ci unsigned char opc9[16] = { 1282141cc406Sopenharmony_ci XXXX, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x17, 0x05, 1283141cc406Sopenharmony_ci 0xec, 0x4e, 0x0c, XXXX, 0xac 1284141cc406Sopenharmony_ci }; 1285141cc406Sopenharmony_ci unsigned char opb11[35] = { 1286141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 1287141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xad, 0xa0, 0x49, 1288141cc406Sopenharmony_ci 0x06, 0x00, 0x00, XXXX, XXXX, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 1289141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, 0x93, 0x1b 1290141cc406Sopenharmony_ci }; 1291141cc406Sopenharmony_ci 1292141cc406Sopenharmony_ci unsigned char ope[8] = { 1293141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff 1294141cc406Sopenharmony_ci }; 1295141cc406Sopenharmony_ci 1296141cc406Sopenharmony_ci unsigned char opd4[8] = { 1297141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, XXXX, XXXX 1298141cc406Sopenharmony_ci }; 1299141cc406Sopenharmony_ci SANE_Status res; 1300141cc406Sopenharmony_ci 1301141cc406Sopenharmony_ci unsigned char *p; 1302141cc406Sopenharmony_ci int h = 66; 1303141cc406Sopenharmony_ci int w = color ? 3 * 5100 : 5100; 1304141cc406Sopenharmony_ci int x0 = color ? 0 : 5100; 1305141cc406Sopenharmony_ci int l = w * h; 1306141cc406Sopenharmony_ci int i, x, y; 1307141cc406Sopenharmony_ci 1308141cc406Sopenharmony_ci PAD_ARRAY (scan->caldata, 16070); 1309141cc406Sopenharmony_ci 1310141cc406Sopenharmony_ci DBG (9, "get_caldata: color = %d\n", color); 1311141cc406Sopenharmony_ci 1312141cc406Sopenharmony_ci p = malloc (l); 1313141cc406Sopenharmony_ci if (p == 0) 1314141cc406Sopenharmony_ci { 1315141cc406Sopenharmony_ci DBG (1, "out of memory (need %d)\n", l); 1316141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1317141cc406Sopenharmony_ci } 1318141cc406Sopenharmony_ci memset (scan->caldata, 0, 3 * 5100); 1319141cc406Sopenharmony_ci 1320141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1321141cc406Sopenharmony_ci opc9[0] = h + 4; 1322141cc406Sopenharmony_ci if (color) 1323141cc406Sopenharmony_ci { 1324141cc406Sopenharmony_ci opc9[13] = 0x03; 1325141cc406Sopenharmony_ci opb11[23] = 0xc4; 1326141cc406Sopenharmony_ci opb11[24] = 0x5c; 1327141cc406Sopenharmony_ci opd4[6] = 0x08; 1328141cc406Sopenharmony_ci opd4[7] = 0x00; 1329141cc406Sopenharmony_ci } 1330141cc406Sopenharmony_ci else 1331141cc406Sopenharmony_ci { 1332141cc406Sopenharmony_ci opc9[13] = 0xc3; 1333141cc406Sopenharmony_ci opb11[23] = 0xec; 1334141cc406Sopenharmony_ci opb11[24] = 0x54; 1335141cc406Sopenharmony_ci opd4[6] = 0x0c; 1336141cc406Sopenharmony_ci opd4[7] = 0x40; 1337141cc406Sopenharmony_ci } 1338141cc406Sopenharmony_ci 1339141cc406Sopenharmony_ci /* Do a test scan of the calibration strip (which is located 1340141cc406Sopenharmony_ci * under the scanner's lid */ 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ci CHK (get_pixels (scan, opc9, opb11, opd4, ope, l, 0, p)); 1343141cc406Sopenharmony_ci 1344141cc406Sopenharmony_ci#ifdef DEBUG_CALIBRATION 1345141cc406Sopenharmony_ci { 1346141cc406Sopenharmony_ci FILE *f2 = fopen ("calibration.pgm", "wb"); 1347141cc406Sopenharmony_ci fprintf (f2, "P5\n%d %d\n255\n", w, h); 1348141cc406Sopenharmony_ci fwrite (p, 1, w * h, f2); 1349141cc406Sopenharmony_ci fclose (f2); 1350141cc406Sopenharmony_ci } 1351141cc406Sopenharmony_ci#endif 1352141cc406Sopenharmony_ci 1353141cc406Sopenharmony_ci scan->scanner_ypos += (h + 4) * 2 + 3; 1354141cc406Sopenharmony_ci scan->scanner_ypos &= ~3; 1355141cc406Sopenharmony_ci 1356141cc406Sopenharmony_ci /* The following loop computes the gain for each of the CCD pixel 1357141cc406Sopenharmony_ci * elements. 1358141cc406Sopenharmony_ci */ 1359141cc406Sopenharmony_ci for (x = 0; x < w; ++x) 1360141cc406Sopenharmony_ci { 1361141cc406Sopenharmony_ci int t = 0, gn; 1362141cc406Sopenharmony_ci double av, gain; 1363141cc406Sopenharmony_ci 1364141cc406Sopenharmony_ci for (y = 0; y < h; ++y) 1365141cc406Sopenharmony_ci t += p[x + y * w]; 1366141cc406Sopenharmony_ci av = (double) t / h; 1367141cc406Sopenharmony_ci gain = 250 / av; 1368141cc406Sopenharmony_ci gn = (int) ((gain - 0.984) * 102.547 + 0.5); 1369141cc406Sopenharmony_ci if (gn < 0) 1370141cc406Sopenharmony_ci gn = 0; 1371141cc406Sopenharmony_ci else if (gn > 255) 1372141cc406Sopenharmony_ci gn = 255; 1373141cc406Sopenharmony_ci scan->caldata[x + x0] = gn; 1374141cc406Sopenharmony_ci } 1375141cc406Sopenharmony_ci 1376141cc406Sopenharmony_ci /* Gamma table for blue */ 1377141cc406Sopenharmony_ci 1378141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 1379141cc406Sopenharmony_ci scan->caldata[i + 3 * 5100 + 0] = i; 1380141cc406Sopenharmony_ci 1381141cc406Sopenharmony_ci /* Gamma table for green */ 1382141cc406Sopenharmony_ci 1383141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 1384141cc406Sopenharmony_ci scan->caldata[i + 3 * 5100 + 256] = i; 1385141cc406Sopenharmony_ci 1386141cc406Sopenharmony_ci /* Gamma table for red */ 1387141cc406Sopenharmony_ci 1388141cc406Sopenharmony_ci for (i = 0; i < 256; ++i) 1389141cc406Sopenharmony_ci scan->caldata[i + 3 * 5100 + 512] = i; 1390141cc406Sopenharmony_ci 1391141cc406Sopenharmony_ci free (p); 1392141cc406Sopenharmony_ci 1393141cc406Sopenharmony_ci CHK_ARRAY (scan->caldata, 16070); 1394141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1395141cc406Sopenharmony_ci} 1396141cc406Sopenharmony_ci 1397141cc406Sopenharmony_ci/* Calibration 2100U */ 1398141cc406Sopenharmony_ci 1399141cc406Sopenharmony_ci/* 1400141cc406Sopenharmony_ciFormat of caldata: 1401141cc406Sopenharmony_ci 1402141cc406Sopenharmony_ci 5100 bytes of CCD calibration values 1403141cc406Sopenharmony_ci 5100 bytes of CCD calibration values 1404141cc406Sopenharmony_ci 5100 bytes of CCD calibration values 1405141cc406Sopenharmony_ci 256 bytes of gamma data for blue 1406141cc406Sopenharmony_ci 256 bytes of gamma data for green 1407141cc406Sopenharmony_ci 256 bytes of gamma data for red 1408141cc406Sopenharmony_ci 2 bytes of extra information 1409141cc406Sopenharmony_ci 1410141cc406Sopenharmony_ci*/ 1411141cc406Sopenharmony_cistatic SANE_Status 1412141cc406Sopenharmony_ciget_caldata_2100U (UMAX_Handle * scan, int color) 1413141cc406Sopenharmony_ci{ 1414141cc406Sopenharmony_ci unsigned char opc9[16] = { 1415141cc406Sopenharmony_ci XXXX, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x15, 0x05, 1416141cc406Sopenharmony_ci XXXX, XXXX, XXXX, XXXX, 0xac, 0x00 1417141cc406Sopenharmony_ci }; 1418141cc406Sopenharmony_ci unsigned char opb11[36] = { 1419141cc406Sopenharmony_ci 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 1420141cc406Sopenharmony_ci 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, 0x46, 1421141cc406Sopenharmony_ci 0x06, 0x00, 0x00, XXXX, XXXX, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 1422141cc406Sopenharmony_ci 0xe9, 0x68, 0xdf, 0x83, XXXX, 0x00 1423141cc406Sopenharmony_ci }; 1424141cc406Sopenharmony_ci unsigned char opd4[8] = { 1425141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, XXXX, XXXX 1426141cc406Sopenharmony_ci }; 1427141cc406Sopenharmony_ci unsigned char ope[8] = { 1428141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff 1429141cc406Sopenharmony_ci }; 1430141cc406Sopenharmony_ci 1431141cc406Sopenharmony_ci 1432141cc406Sopenharmony_ci/* default gamma translation table */ 1433141cc406Sopenharmony_ci unsigned char ggamma[256] = { 1434141cc406Sopenharmony_ci 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1B, 0x1D, 1435141cc406Sopenharmony_ci 0x1F, 0x21, 0x23, 0x24, 0x26, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 1436141cc406Sopenharmony_ci 0x31, 0x33, 0x34, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 1437141cc406Sopenharmony_ci 0x41, 0x42, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 1438141cc406Sopenharmony_ci 0x4F, 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 1439141cc406Sopenharmony_ci 0x5B, 0x5C, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 1440141cc406Sopenharmony_ci 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 1441141cc406Sopenharmony_ci 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 1442141cc406Sopenharmony_ci 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x86, 1443141cc406Sopenharmony_ci 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x90, 1444141cc406Sopenharmony_ci 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 1445141cc406Sopenharmony_ci 0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA2, 0xA3, 1446141cc406Sopenharmony_ci 0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC, 1447141cc406Sopenharmony_ci 0xAD, 0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5, 1448141cc406Sopenharmony_ci 0xB6, 0xB7, 0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 1449141cc406Sopenharmony_ci 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC5, 0xC5, 0xC6, 1450141cc406Sopenharmony_ci 0xC7, 0xC8, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCE, 1451141cc406Sopenharmony_ci 0xCF, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 0xD6, 1452141cc406Sopenharmony_ci 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 0xDE, 0xDE, 1453141cc406Sopenharmony_ci 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3, 0xE4, 0xE5, 0xE6, 0xE6, 1454141cc406Sopenharmony_ci 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC, 0xEC, 0xED, 0xEE, 1455141cc406Sopenharmony_ci 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4, 0xF5, 0xF5, 1456141cc406Sopenharmony_ci 0xF6, 0xF7, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC, 0xFD, 1457141cc406Sopenharmony_ci 0xFE, 0xFE, 0xFF 1458141cc406Sopenharmony_ci }; 1459141cc406Sopenharmony_ci 1460141cc406Sopenharmony_ci 1461141cc406Sopenharmony_ci SANE_Status res; 1462141cc406Sopenharmony_ci 1463141cc406Sopenharmony_ci unsigned char *p; 1464141cc406Sopenharmony_ci int h = 66; 1465141cc406Sopenharmony_ci int w = color ? 3 * 5100 : 5100; 1466141cc406Sopenharmony_ci int x0 = color ? 0 : 5100; 1467141cc406Sopenharmony_ci int l = w * h; 1468141cc406Sopenharmony_ci int i, x, y; 1469141cc406Sopenharmony_ci int t, gn; 1470141cc406Sopenharmony_ci double av, pct; 1471141cc406Sopenharmony_ci 1472141cc406Sopenharmony_ci PAD_ARRAY (scan->caldata, 16070); 1473141cc406Sopenharmony_ci 1474141cc406Sopenharmony_ci DBG (9, "get_caldata: color = %d\n", color); 1475141cc406Sopenharmony_ci 1476141cc406Sopenharmony_ci p = malloc (l); 1477141cc406Sopenharmony_ci if (p == 0) 1478141cc406Sopenharmony_ci { 1479141cc406Sopenharmony_ci DBG (1, "out of memory (need %d)\n", l); 1480141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1481141cc406Sopenharmony_ci } 1482141cc406Sopenharmony_ci memset (scan->caldata, 0, 3 * 5100); 1483141cc406Sopenharmony_ci 1484141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1485141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1486141cc406Sopenharmony_ci 1487141cc406Sopenharmony_ci opc9[0] = h + 4; 1488141cc406Sopenharmony_ci 1489141cc406Sopenharmony_ci if (color) 1490141cc406Sopenharmony_ci { 1491141cc406Sopenharmony_ci opc9[10] = 0xb6; 1492141cc406Sopenharmony_ci opc9[11] = 0x3b; 1493141cc406Sopenharmony_ci opc9[12] = 0x0c; 1494141cc406Sopenharmony_ci opc9[13] = 0x03; 1495141cc406Sopenharmony_ci opb11[17] = 0x7e; 1496141cc406Sopenharmony_ci opb11[18] = 0xb0; 1497141cc406Sopenharmony_ci opb11[23] = 0xc4; 1498141cc406Sopenharmony_ci opb11[24] = 0x5c; 1499141cc406Sopenharmony_ci opb11[34] = 0x1b; 1500141cc406Sopenharmony_ci opd4[6] = 0x0f; 1501141cc406Sopenharmony_ci opd4[7] = 0x40; 1502141cc406Sopenharmony_ci } 1503141cc406Sopenharmony_ci else 1504141cc406Sopenharmony_ci { 1505141cc406Sopenharmony_ci opc9[10] = 0xa6; 1506141cc406Sopenharmony_ci opc9[11] = 0x2a; 1507141cc406Sopenharmony_ci opc9[12] = 0x08; 1508141cc406Sopenharmony_ci opc9[13] = 0xc2; 1509141cc406Sopenharmony_ci opb11[17] = 0x7f; 1510141cc406Sopenharmony_ci opb11[18] = 0xc0; 1511141cc406Sopenharmony_ci opb11[23] = 0xec; 1512141cc406Sopenharmony_ci opb11[24] = 0x54; 1513141cc406Sopenharmony_ci opb11[34] = 0x1a; 1514141cc406Sopenharmony_ci opd4[6] = 0x06; 1515141cc406Sopenharmony_ci opd4[7] = 0x20; 1516141cc406Sopenharmony_ci } 1517141cc406Sopenharmony_ci 1518141cc406Sopenharmony_ci /* Do a test scan of the calibration strip (which is located 1519141cc406Sopenharmony_ci * under the scanner's lid */ 1520141cc406Sopenharmony_ci CHK (get_pixels_2100U (scan, opc9, opb11, opd4, ope, l, 0, p)); 1521141cc406Sopenharmony_ci 1522141cc406Sopenharmony_ci#ifdef DEBUG_CALIBRATION 1523141cc406Sopenharmony_ci { 1524141cc406Sopenharmony_ci FILE *f2 = fopen ("calibration.pgm", "wb"); 1525141cc406Sopenharmony_ci fprintf (f2, "P5\n%d %d\n255\n", w, h); 1526141cc406Sopenharmony_ci fwrite (p, 1, w * h, f2); 1527141cc406Sopenharmony_ci fclose (f2); 1528141cc406Sopenharmony_ci } 1529141cc406Sopenharmony_ci#endif 1530141cc406Sopenharmony_ci 1531141cc406Sopenharmony_ci scan->scanner_ypos += (h + 4) * 2 + 3; 1532141cc406Sopenharmony_ci scan->scanner_ypos &= ~3; 1533141cc406Sopenharmony_ci 1534141cc406Sopenharmony_ci /* The following loop computes the gain for each of the CCD pixel 1535141cc406Sopenharmony_ci * elements. 1536141cc406Sopenharmony_ci */ 1537141cc406Sopenharmony_ci for (x = 0; x < w; x++) 1538141cc406Sopenharmony_ci { 1539141cc406Sopenharmony_ci t = 0; 1540141cc406Sopenharmony_ci for (y = 0; y < h; y++) 1541141cc406Sopenharmony_ci t += p[x + y * w]; 1542141cc406Sopenharmony_ci av = (double) t / h; 1543141cc406Sopenharmony_ci pct = 100.0 - (av * 100.0) / 250; 1544141cc406Sopenharmony_ci gn = (int) (pct / 0.57); 1545141cc406Sopenharmony_ci 1546141cc406Sopenharmony_ci pct = gn; 1547141cc406Sopenharmony_ci av = exp((-pct)/50)*2.5+0.9; 1548141cc406Sopenharmony_ci gn = gn * av; 1549141cc406Sopenharmony_ci 1550141cc406Sopenharmony_ci 1551141cc406Sopenharmony_ci if (gn < 0) 1552141cc406Sopenharmony_ci gn = 0; 1553141cc406Sopenharmony_ci else if (gn > 127) 1554141cc406Sopenharmony_ci gn = 127; 1555141cc406Sopenharmony_ci scan->caldata[x + x0] = gn; 1556141cc406Sopenharmony_ci } 1557141cc406Sopenharmony_ci 1558141cc406Sopenharmony_ci /* Gamma table for blue */ 1559141cc406Sopenharmony_ci 1560141cc406Sopenharmony_ci for (i = 0; i < 256; i++) 1561141cc406Sopenharmony_ci scan->caldata[i + 3 * 5100 + 0] = ggamma[i]; 1562141cc406Sopenharmony_ci 1563141cc406Sopenharmony_ci /* Gamma table for green */ 1564141cc406Sopenharmony_ci 1565141cc406Sopenharmony_ci for (i = 0; i < 256; i++) 1566141cc406Sopenharmony_ci scan->caldata[i + 3 * 5100 + 256] = ggamma[i]; 1567141cc406Sopenharmony_ci 1568141cc406Sopenharmony_ci /* Gamma table for red */ 1569141cc406Sopenharmony_ci 1570141cc406Sopenharmony_ci for (i = 0; i < 256; i++) 1571141cc406Sopenharmony_ci scan->caldata[i + 3 * 5100 + 512] = ggamma[i]; 1572141cc406Sopenharmony_ci 1573141cc406Sopenharmony_ci free (p); 1574141cc406Sopenharmony_ci 1575141cc406Sopenharmony_ci CHK_ARRAY (scan->caldata, 16070); 1576141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1577141cc406Sopenharmony_ci} 1578141cc406Sopenharmony_ci 1579141cc406Sopenharmony_ci 1580141cc406Sopenharmony_ci 1581141cc406Sopenharmony_ci/* Sends scan user parameters from frontend 1220U */ 1582141cc406Sopenharmony_ci 1583141cc406Sopenharmony_cistatic SANE_Status 1584141cc406Sopenharmony_cisend_scan_parameters (UMAX_Handle * scan) 1585141cc406Sopenharmony_ci{ 1586141cc406Sopenharmony_ci SANE_Status res; 1587141cc406Sopenharmony_ci UMAX_Status_Byte s; 1588141cc406Sopenharmony_ci 1589141cc406Sopenharmony_ci /* Appears to correspond to opscan in umax_pp_low.c */ 1590141cc406Sopenharmony_ci unsigned char opbgo[35] = { 1591141cc406Sopenharmony_ci 0x00, 0x00, 0xb0, 0x4f, 0xd8, 0xe7, 0xfa, 0x10, 0xef, 0xc4, 1592141cc406Sopenharmony_ci 0x3c, 0x71, 0x0f, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, XXXX, 1593141cc406Sopenharmony_ci 0xc4, 0x7e, 0x00, XXXX, XXXX, 0xa0, 0x0a, 0x8b, 0x49, 0x4a, 1594141cc406Sopenharmony_ci 0xd0, 0x68, 0xdf, XXXX, 0x1a 1595141cc406Sopenharmony_ci }; 1596141cc406Sopenharmony_ci 1597141cc406Sopenharmony_ci /* Appears to correspond to opsc53 in umax_pp_low.c */ 1598141cc406Sopenharmony_ci unsigned char opcgo[16] = { 1599141cc406Sopenharmony_ci XXXX, XXXX, XXXX, XXXX, 0xec, 0x03, XXXX, XXXX, XXXX, XXXX, 1600141cc406Sopenharmony_ci 0xec, 0x4e, XXXX, XXXX, XXXX 1601141cc406Sopenharmony_ci }; 1602141cc406Sopenharmony_ci 1603141cc406Sopenharmony_ci /* Appears to correspond to opsc04 in umax_pp_low.c */ 1604141cc406Sopenharmony_ci unsigned char opdgo[8] = { 1605141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, XXXX, XXXX 1606141cc406Sopenharmony_ci }; 1607141cc406Sopenharmony_ci 1608141cc406Sopenharmony_ci unsigned char subsamp[9] = { 1609141cc406Sopenharmony_ci 0xff, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x80 1610141cc406Sopenharmony_ci }; 1611141cc406Sopenharmony_ci 1612141cc406Sopenharmony_ci const int xend = 1613141cc406Sopenharmony_ci scan->xskip + scan->w * scan->xsamp + (scan->xsamp + 1) / 2; 1614141cc406Sopenharmony_ci const int ytot = scan->hexp * scan->ysamp + 12; 1615141cc406Sopenharmony_ci 1616141cc406Sopenharmony_ci opbgo[17] = scan->xskip % 256; 1617141cc406Sopenharmony_ci opbgo[18] = ((scan->xskip >> 8) & 0xf) + (xend << 4); 1618141cc406Sopenharmony_ci opbgo[19] = xend >> 4; 1619141cc406Sopenharmony_ci opbgo[33] = 0x33 + ((xend & 0x1000) >> 5) + ((scan->xskip & 0x1000) >> 6); 1620141cc406Sopenharmony_ci 1621141cc406Sopenharmony_ci /* bytes per line */ 1622141cc406Sopenharmony_ci 1623141cc406Sopenharmony_ci opbgo[23] = scan->color ? 0xc6 : 0x77; 1624141cc406Sopenharmony_ci opbgo[24] = scan->color ? 0x5b : 0x4a; 1625141cc406Sopenharmony_ci 1626141cc406Sopenharmony_ci /* Scan height */ 1627141cc406Sopenharmony_ci 1628141cc406Sopenharmony_ci opcgo[0] = ytot; 1629141cc406Sopenharmony_ci opcgo[1] = ((ytot >> 8) & 0x3f) + (scan->yskip << 6); 1630141cc406Sopenharmony_ci opcgo[2] = scan->yskip >> 2; 1631141cc406Sopenharmony_ci opcgo[3] = 0x50 + ((scan->yskip >> 10) & 0xf); 1632141cc406Sopenharmony_ci 1633141cc406Sopenharmony_ci /* This is what used to be here: 1634141cc406Sopenharmony_ci 1635141cc406Sopenharmony_ci opcgo[6] = bh == h? 0: 0x60; // a guess 1636141cc406Sopenharmony_ci 1637141cc406Sopenharmony_ci I replaced it with what umax_pp_low.c uses, since it 1638141cc406Sopenharmony_ci made more sense 1639141cc406Sopenharmony_ci */ 1640141cc406Sopenharmony_ci opcgo[6] = (scan->ydpi <= 300) ? 0x00 : 0x60; 1641141cc406Sopenharmony_ci opcgo[8] = (scan->ydpi <= 300) ? 0x17 : 0x2F; 1642141cc406Sopenharmony_ci opcgo[9] = (scan->ydpi >= 300) ? 0x05 : 0x07; 1643141cc406Sopenharmony_ci opcgo[14] = (scan->ydpi == 600) ? 0xa4 : 0xac; 1644141cc406Sopenharmony_ci 1645141cc406Sopenharmony_ci opcgo[7] = scan->color ? 0x2F : 0x40; 1646141cc406Sopenharmony_ci opcgo[12] = scan->color ? 0x10 : 0x0C; 1647141cc406Sopenharmony_ci opcgo[13] = scan->color ? 0x04 : 0xc3; 1648141cc406Sopenharmony_ci 1649141cc406Sopenharmony_ci opdgo[6] = scan->color ? 0x88 : 0x8c; 1650141cc406Sopenharmony_ci opdgo[7] = scan->color ? 0x00 : 0x40; 1651141cc406Sopenharmony_ci 1652141cc406Sopenharmony_ci DBG (3, "send_scan_parameters: xskip = %d, yskip = %d\n", scan->xskip, 1653141cc406Sopenharmony_ci scan->yskip); 1654141cc406Sopenharmony_ci 1655141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1656141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1657141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_2, 16, opcgo, &s)); 1658141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 35, opbgo, &s)); 1659141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_1, 8, opdgo, &s)); 1660141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1661141cc406Sopenharmony_ci DBG (4, "send_scan_parameters: checkpoint 1: s = %d\n", s); 1662141cc406Sopenharmony_ci 1663141cc406Sopenharmony_ci /* Loads the new calibration data (that was computed by get_caldata) into the 1664141cc406Sopenharmony_ci scanner */ 1665141cc406Sopenharmony_ci 1666141cc406Sopenharmony_ci scan->caldata[16068] = subsamp[scan->xsamp]; 1667141cc406Sopenharmony_ci scan->caldata[16069] = subsamp[scan->ysamp]; 1668141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 16070, scan->caldata, &s)); 1669141cc406Sopenharmony_ci 1670141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 1671141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1672141cc406Sopenharmony_ci 1673141cc406Sopenharmony_ci DBG (4, "send_scan_parameters: checkpoint 2: s = %d\n", s); 1674141cc406Sopenharmony_ci 1675141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1676141cc406Sopenharmony_ci} 1677141cc406Sopenharmony_ci 1678141cc406Sopenharmony_ci/* Sends scan user parameters from frontend 2100U */ 1679141cc406Sopenharmony_ci 1680141cc406Sopenharmony_cistatic SANE_Status 1681141cc406Sopenharmony_cisend_scan_parameters_2100U (UMAX_Handle * scan) 1682141cc406Sopenharmony_ci{ 1683141cc406Sopenharmony_ci SANE_Status res; 1684141cc406Sopenharmony_ci UMAX_Status_Byte s; 1685141cc406Sopenharmony_ci int bpl; 1686141cc406Sopenharmony_ci 1687141cc406Sopenharmony_ci /* Appears to correspond to opscan in umax_pp_low.c */ 1688141cc406Sopenharmony_ci unsigned char opbgo[36] = { 1689141cc406Sopenharmony_ci 0x00, 0x00, 0xb0, 0x4f, 0xd8, 0xe7, 0xfa, 0x10, 0xef, 0xc4, 1690141cc406Sopenharmony_ci 0x3c, 0x71, 0x0f, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, XXXX, 1691141cc406Sopenharmony_ci 0xc4, 0x7e, 0x00, XXXX, XXXX, 0xa0, 0x0a, 0x8b, 0x49, 0x2a, 1692141cc406Sopenharmony_ci 0xe9, 0x68, 0xdf, XXXX, 0x1a, 0x00 1693141cc406Sopenharmony_ci }; 1694141cc406Sopenharmony_ci 1695141cc406Sopenharmony_ci /* Appears to correspond to opsc53 in umax_pp_low.c */ 1696141cc406Sopenharmony_ci unsigned char opcgo[16] = { 1697141cc406Sopenharmony_ci XXXX, XXXX, XXXX, XXXX, 0xec, 0x03, 0x60, XXXX, XXXX, XXXX, 1698141cc406Sopenharmony_ci XXXX, XXXX, XXXX, XXXX, XXXX, 0x00 1699141cc406Sopenharmony_ci }; 1700141cc406Sopenharmony_ci 1701141cc406Sopenharmony_ci /* Appears to correspond to opsc04 in umax_pp_low.c */ 1702141cc406Sopenharmony_ci unsigned char opdgo[8] = { 1703141cc406Sopenharmony_ci 0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, XXXX, XXXX 1704141cc406Sopenharmony_ci }; 1705141cc406Sopenharmony_ci 1706141cc406Sopenharmony_ci unsigned char subsamp[9] = { 1707141cc406Sopenharmony_ci 0xff, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x80 1708141cc406Sopenharmony_ci }; 1709141cc406Sopenharmony_ci 1710141cc406Sopenharmony_ci const int xend = 1711141cc406Sopenharmony_ci scan->xskip + scan->w * scan->xsamp + (scan->xsamp + 1) / 2; 1712141cc406Sopenharmony_ci const int ytot = scan->hexp * scan->ysamp + 12; 1713141cc406Sopenharmony_ci 1714141cc406Sopenharmony_ci opbgo[17] = scan->xskip % 256; 1715141cc406Sopenharmony_ci opbgo[18] = ((scan->xskip >> 8) & 0x0f) + (xend << 4); 1716141cc406Sopenharmony_ci opbgo[19] = xend >> 4; 1717141cc406Sopenharmony_ci opbgo[33] = 0x23 + ((xend & 0x1000) >> 5) + ((scan->xskip & 0x1000) >> 6); 1718141cc406Sopenharmony_ci 1719141cc406Sopenharmony_ci /* bytes per line */ 1720141cc406Sopenharmony_ci 1721141cc406Sopenharmony_ci bpl = (scan->color ? 3 : 1) * scan->w * scan->xdpi; 1722141cc406Sopenharmony_ci opbgo[23] = bpl % 256; 1723141cc406Sopenharmony_ci opbgo[24] = 0x41 + ((bpl / 256) & 0x1f); 1724141cc406Sopenharmony_ci 1725141cc406Sopenharmony_ci /* Scan height */ 1726141cc406Sopenharmony_ci 1727141cc406Sopenharmony_ci opcgo[0] = ytot; 1728141cc406Sopenharmony_ci opcgo[1] = ((ytot >> 8) & 0x3f) + (scan->yskip << 6); 1729141cc406Sopenharmony_ci opcgo[2] = (scan->yskip >> 2); 1730141cc406Sopenharmony_ci opcgo[3] = 0x50 + ((scan->yskip >> 10) & 0x0f); 1731141cc406Sopenharmony_ci 1732141cc406Sopenharmony_ci 1733141cc406Sopenharmony_ci opcgo[6] = (scan->ydpi <= 300) ? 0x00 : 0x60; 1734141cc406Sopenharmony_ci opcgo[8] = (scan->ydpi <= 300) ? 0x17 : 0x2F; 1735141cc406Sopenharmony_ci opcgo[9] = (scan->ydpi >= 300) ? 0x05 : 0x07; 1736141cc406Sopenharmony_ci opcgo[14] = (scan->ydpi == 600) ? 0xa4 : 0xac; 1737141cc406Sopenharmony_ci 1738141cc406Sopenharmony_ci 1739141cc406Sopenharmony_ci opcgo[7] = scan->color ? 0x2f : 0x40; 1740141cc406Sopenharmony_ci opcgo[10] = scan->color ? 0xb6 : 0xa6; 1741141cc406Sopenharmony_ci opcgo[11] = scan->color ? 0x3b : 0x2a; 1742141cc406Sopenharmony_ci opcgo[12] = scan->color ? 0x0c : 0x08; 1743141cc406Sopenharmony_ci opcgo[13] = scan->color ? 0x03 : 0xc2; 1744141cc406Sopenharmony_ci 1745141cc406Sopenharmony_ci opdgo[6] = scan->color ? 0x8f : 0x86; 1746141cc406Sopenharmony_ci opdgo[7] = scan->color ? 0x40 : 0x20; 1747141cc406Sopenharmony_ci 1748141cc406Sopenharmony_ci DBG (3, "send_scan_parameters: xskip = %d, yskip = %d\n", scan->xskip, 1749141cc406Sopenharmony_ci scan->yskip); 1750141cc406Sopenharmony_ci 1751141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1752141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 1753141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_2, 16, opcgo, &s)); 1754141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_8, 36, opbgo, &s)); 1755141cc406Sopenharmony_ci CHK (cwritev (scan, CMD_1, 8, opdgo, &s)); 1756141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1757141cc406Sopenharmony_ci DBG (4, "send_scan_parameters: checkpoint 1: s = %d\n", s); 1758141cc406Sopenharmony_ci 1759141cc406Sopenharmony_ci /* Loads the new calibration data (that was computed by get_caldata) into the 1760141cc406Sopenharmony_ci scanner */ 1761141cc406Sopenharmony_ci 1762141cc406Sopenharmony_ci scan->caldata[16068] = subsamp[scan->xsamp]; 1763141cc406Sopenharmony_ci scan->caldata[16069] = subsamp[scan->ysamp]; 1764141cc406Sopenharmony_ci CHK (cwrite (scan, CMD_4, 16070, scan->caldata, &s)); 1765141cc406Sopenharmony_ci 1766141cc406Sopenharmony_ci CHK (csend (scan, CMD_40)); 1767141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1768141cc406Sopenharmony_ci 1769141cc406Sopenharmony_ci DBG (4, "send_scan_parameters: checkpoint 2: s = %d\n", s); 1770141cc406Sopenharmony_ci 1771141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1772141cc406Sopenharmony_ci} 1773141cc406Sopenharmony_ci 1774141cc406Sopenharmony_ci/* Read raw data */ 1775141cc406Sopenharmony_ci 1776141cc406Sopenharmony_cistatic SANE_Status 1777141cc406Sopenharmony_ciread_raw_data (UMAX_Handle * scan, unsigned char *data, int len) 1778141cc406Sopenharmony_ci{ 1779141cc406Sopenharmony_ci SANE_Status res; 1780141cc406Sopenharmony_ci UMAX_Status_Byte s; 1781141cc406Sopenharmony_ci 1782141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 1783141cc406Sopenharmony_ci CHK (cread (scan, CMD_4, len, data, &s)); 1784141cc406Sopenharmony_ci 1785141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1786141cc406Sopenharmony_ci} 1787141cc406Sopenharmony_ci 1788141cc406Sopenharmony_ci/* Read raw strip color */ 1789141cc406Sopenharmony_ci 1790141cc406Sopenharmony_cistatic SANE_Status 1791141cc406Sopenharmony_ciread_raw_strip_color (UMAX_Handle * scan) 1792141cc406Sopenharmony_ci{ 1793141cc406Sopenharmony_ci /** 1794141cc406Sopenharmony_ci yres = 75 => ydpi = 150 => ysamp = 2 => yoff_scale = 8 1795141cc406Sopenharmony_ci yres = 150 => ydpi = 150 => ysamp = 1 => yoff_scale = 4 1796141cc406Sopenharmony_ci yres = 300 => ydpi = 300 => ysamp = 1 => yoff_scale = 2 1797141cc406Sopenharmony_ci yres = 600 => ydpi = 600 => ysamp = 1 => yoff_scale = 1 1798141cc406Sopenharmony_ci */ 1799141cc406Sopenharmony_ci 1800141cc406Sopenharmony_ci const int yoff_scale = 600 * scan->ysamp / scan->ydpi; 1801141cc406Sopenharmony_ci const int linelen = 3 * scan->w; 1802141cc406Sopenharmony_ci 1803141cc406Sopenharmony_ci /* 1804141cc406Sopenharmony_ci yoff_scale = 8 => roff = 5 * w, goff = 1 * w, boff = 0 * w, hextra = 1 1805141cc406Sopenharmony_ci yoff_scale = 4 => roff = 8 * w, goff = 4 * w, boff = 0 * w, hextra = 2 1806141cc406Sopenharmony_ci yoff_scale = 2 => roff = 14 * w, goff = 7 * w, boff = 0 * w, hextra = 4 1807141cc406Sopenharmony_ci yoff_scale = 1 => roff = 26 * w, goff = 13 * w, boff = 0 * w, hextra = 8 1808141cc406Sopenharmony_ci */ 1809141cc406Sopenharmony_ci 1810141cc406Sopenharmony_ci const int hextra = 8 / yoff_scale; 1811141cc406Sopenharmony_ci 1812141cc406Sopenharmony_ci SANE_Status res; 1813141cc406Sopenharmony_ci int lines_to_read = scan->hexp; 1814141cc406Sopenharmony_ci 1815141cc406Sopenharmony_ci DBG (9, "read_raw_strip_color: hexp = %d, bh = %d\n", scan->hexp, scan->bh); 1816141cc406Sopenharmony_ci 1817141cc406Sopenharmony_ci if (scan->maxh == -1) 1818141cc406Sopenharmony_ci { 1819141cc406Sopenharmony_ci DBG (10, "read_raw_strip_color: filling buffer for the first time\n"); 1820141cc406Sopenharmony_ci if (lines_to_read > scan->bh) 1821141cc406Sopenharmony_ci lines_to_read = scan->bh; 1822141cc406Sopenharmony_ci 1823141cc406Sopenharmony_ci CHK (read_raw_data (scan, scan->p, lines_to_read * linelen)); 1824141cc406Sopenharmony_ci scan->maxh = lines_to_read - hextra; 1825141cc406Sopenharmony_ci } 1826141cc406Sopenharmony_ci else 1827141cc406Sopenharmony_ci { 1828141cc406Sopenharmony_ci DBG (10, "read_raw_strip_color: reading new rows into buffer\n"); 1829141cc406Sopenharmony_ci memmove (scan->p, scan->p + (scan->bh - hextra) * linelen, 1830141cc406Sopenharmony_ci hextra * linelen); 1831141cc406Sopenharmony_ci 1832141cc406Sopenharmony_ci if (lines_to_read > (scan->bh - hextra)) 1833141cc406Sopenharmony_ci lines_to_read = scan->bh - hextra; 1834141cc406Sopenharmony_ci 1835141cc406Sopenharmony_ci CHK (read_raw_data 1836141cc406Sopenharmony_ci (scan, scan->p + hextra * linelen, lines_to_read * linelen)); 1837141cc406Sopenharmony_ci scan->maxh = lines_to_read; 1838141cc406Sopenharmony_ci } 1839141cc406Sopenharmony_ci 1840141cc406Sopenharmony_ci scan->hexp -= lines_to_read; 1841141cc406Sopenharmony_ci scan->x = 0; 1842141cc406Sopenharmony_ci scan->y = 0; 1843141cc406Sopenharmony_ci 1844141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1845141cc406Sopenharmony_ci} 1846141cc406Sopenharmony_ci 1847141cc406Sopenharmony_ci/* Read raw strip grey */ 1848141cc406Sopenharmony_ci 1849141cc406Sopenharmony_cistatic SANE_Status 1850141cc406Sopenharmony_ciread_raw_strip_gray (UMAX_Handle * scan) 1851141cc406Sopenharmony_ci{ 1852141cc406Sopenharmony_ci const int linelen = scan->w; 1853141cc406Sopenharmony_ci 1854141cc406Sopenharmony_ci SANE_Status res; 1855141cc406Sopenharmony_ci 1856141cc406Sopenharmony_ci int lines_to_read = scan->bh; 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci DBG (9, "read_raw_strip_gray: hexp = %d\n", scan->hexp); 1859141cc406Sopenharmony_ci 1860141cc406Sopenharmony_ci if (lines_to_read > scan->hexp) 1861141cc406Sopenharmony_ci lines_to_read = scan->hexp; 1862141cc406Sopenharmony_ci scan->hexp -= lines_to_read; 1863141cc406Sopenharmony_ci 1864141cc406Sopenharmony_ci CHK (read_raw_data (scan, scan->p, lines_to_read * linelen)); 1865141cc406Sopenharmony_ci 1866141cc406Sopenharmony_ci scan->maxh = lines_to_read; 1867141cc406Sopenharmony_ci scan->x = 0; 1868141cc406Sopenharmony_ci scan->y = 0; 1869141cc406Sopenharmony_ci 1870141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1871141cc406Sopenharmony_ci} 1872141cc406Sopenharmony_ci 1873141cc406Sopenharmony_ci 1874141cc406Sopenharmony_ci/* Read raw strip */ 1875141cc406Sopenharmony_ci 1876141cc406Sopenharmony_cistatic SANE_Status 1877141cc406Sopenharmony_ciread_raw_strip (UMAX_Handle * scan) 1878141cc406Sopenharmony_ci{ 1879141cc406Sopenharmony_ci if (scan->color) 1880141cc406Sopenharmony_ci return read_raw_strip_color (scan); 1881141cc406Sopenharmony_ci else 1882141cc406Sopenharmony_ci return read_raw_strip_gray (scan); 1883141cc406Sopenharmony_ci} 1884141cc406Sopenharmony_ci 1885141cc406Sopenharmony_ci/* Set scan user pamaters Frontend */ 1886141cc406Sopenharmony_ci 1887141cc406Sopenharmony_cistatic SANE_Status 1888141cc406Sopenharmony_ciUMAX_set_scan_parameters (UMAX_Handle * scan, 1889141cc406Sopenharmony_ci const int color, 1890141cc406Sopenharmony_ci const int xo, 1891141cc406Sopenharmony_ci const int yo, 1892141cc406Sopenharmony_ci const int w, 1893141cc406Sopenharmony_ci const int h, const int xres, const int yres) 1894141cc406Sopenharmony_ci{ 1895141cc406Sopenharmony_ci 1896141cc406Sopenharmony_ci /* Validate the input parameters */ 1897141cc406Sopenharmony_ci 1898141cc406Sopenharmony_ci int left = xo; 1899141cc406Sopenharmony_ci int top = yo; 1900141cc406Sopenharmony_ci int right = xo + w * 600 / xres; 1901141cc406Sopenharmony_ci int bottom = yo + h * 600 / yres; 1902141cc406Sopenharmony_ci 1903141cc406Sopenharmony_ci DBG (2, "UMAX_set_scan_parameters:\n"); 1904141cc406Sopenharmony_ci DBG (2, "color = %d \n", color); 1905141cc406Sopenharmony_ci DBG (2, "xo = %d, yo = %d\n", xo, yo); 1906141cc406Sopenharmony_ci DBG (2, "w = %d, h = %d\n", w, h); 1907141cc406Sopenharmony_ci DBG (2, "xres = %d, yres = %d\n", xres, yres); 1908141cc406Sopenharmony_ci DBG (2, "left = %d, top = %d\n", left, top); 1909141cc406Sopenharmony_ci DBG (2, "right = %d, bottom = %d\n", right, bottom); 1910141cc406Sopenharmony_ci 1911141cc406Sopenharmony_ci if ((left < 0) || (right > UMAX_MAX_WIDTH)) 1912141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1913141cc406Sopenharmony_ci 1914141cc406Sopenharmony_ci if ((top < 0) || (bottom > UMAX_MAX_HEIGHT)) 1915141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1916141cc406Sopenharmony_ci 1917141cc406Sopenharmony_ci if (((right - left) < 10) || ((bottom - top) < 10)) 1918141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1919141cc406Sopenharmony_ci 1920141cc406Sopenharmony_ci if ((xres != 75) && (xres != 150) && (xres != 300) && (xres != 600)) 1921141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1922141cc406Sopenharmony_ci 1923141cc406Sopenharmony_ci if ((yres != 75) && (yres != 150) && (yres != 300) && (yres != 600)) 1924141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 1925141cc406Sopenharmony_ci 1926141cc406Sopenharmony_ci /* If we get this far, begin initializing the data 1927141cc406Sopenharmony_ci structure 1928141cc406Sopenharmony_ci */ 1929141cc406Sopenharmony_ci 1930141cc406Sopenharmony_ci scan->color = color; 1931141cc406Sopenharmony_ci scan->w = w; 1932141cc406Sopenharmony_ci scan->h = h; 1933141cc406Sopenharmony_ci scan->xo = xo; 1934141cc406Sopenharmony_ci scan->yo = yo; 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci /* 1937141cc406Sopenharmony_ci The scanner has a fixed X resolution of 600 dpi, but 1938141cc406Sopenharmony_ci supports three choices for the Y resolution. We must 1939141cc406Sopenharmony_ci choose an appropriate physical resolution and the 1940141cc406Sopenharmony_ci corresponding sampling value. 1941141cc406Sopenharmony_ci 1942141cc406Sopenharmony_ci It is not clear to me why the choice depends on 1943141cc406Sopenharmony_ci whether we are scanning in color or not, but the 1944141cc406Sopenharmony_ci original code did this and I didn't want to mess 1945141cc406Sopenharmony_ci with it. 1946141cc406Sopenharmony_ci 1947141cc406Sopenharmony_ci Physical X resolution choice: 1948141cc406Sopenharmony_ci xres = 75 => xdpi = 600 (xsamp = 8) 1949141cc406Sopenharmony_ci xres = 150 => xdpi = 600 (xsamp = 4) 1950141cc406Sopenharmony_ci xres = 300 => xdpi = 600 (xsamp = 2) 1951141cc406Sopenharmony_ci xres = 600 => xdpi = 600 (xsamp = 1) 1952141cc406Sopenharmony_ci 1953141cc406Sopenharmony_ci Physical Y resolution choice (if color): 1954141cc406Sopenharmony_ci yres = 75 => ydpi = 150 (ysamp = 2) 1955141cc406Sopenharmony_ci yres = 150 => ydpi = 150 (ysamp = 1) 1956141cc406Sopenharmony_ci yres = 300 => ydpi = 300 (ysamp = 1) 1957141cc406Sopenharmony_ci yres = 600 => ydpi = 600 (ysamp = 1) 1958141cc406Sopenharmony_ci 1959141cc406Sopenharmony_ci Physical Y resolution choice (if not color): 1960141cc406Sopenharmony_ci yres = 75 => ydpi = 300 (ysamp = 4) 1961141cc406Sopenharmony_ci yres = 150 => ydpi = 300 (ysamp = 2) 1962141cc406Sopenharmony_ci yres = 300 => ydpi = 300 (ysamp = 1) 1963141cc406Sopenharmony_ci yres = 600 => ydpi = 600 (ysamp = 1) 1964141cc406Sopenharmony_ci */ 1965141cc406Sopenharmony_ci 1966141cc406Sopenharmony_ci scan->xdpi = 600; 1967141cc406Sopenharmony_ci if (yres <= 150 && color) 1968141cc406Sopenharmony_ci scan->ydpi = 150; 1969141cc406Sopenharmony_ci else if (yres > 300) 1970141cc406Sopenharmony_ci scan->ydpi = 600; 1971141cc406Sopenharmony_ci else 1972141cc406Sopenharmony_ci scan->ydpi = 300; 1973141cc406Sopenharmony_ci 1974141cc406Sopenharmony_ci scan->xsamp = scan->xdpi / xres; 1975141cc406Sopenharmony_ci scan->ysamp = scan->ydpi / yres; 1976141cc406Sopenharmony_ci 1977141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1978141cc406Sopenharmony_ci} 1979141cc406Sopenharmony_ci 1980141cc406Sopenharmony_ci/* Start actual scan 1220U */ 1981141cc406Sopenharmony_ci 1982141cc406Sopenharmony_cistatic SANE_Status 1983141cc406Sopenharmony_ciUMAX_start_scan (UMAX_Handle * scan) 1984141cc406Sopenharmony_ci{ 1985141cc406Sopenharmony_ci SANE_Status res; 1986141cc406Sopenharmony_ci int linelen; 1987141cc406Sopenharmony_ci int yd; 1988141cc406Sopenharmony_ci 1989141cc406Sopenharmony_ci DBG (3, "UMAX_start_scan called\n"); 1990141cc406Sopenharmony_ci 1991141cc406Sopenharmony_ci if (scan->color) 1992141cc406Sopenharmony_ci { 1993141cc406Sopenharmony_ci const int yoff_scale = 600 * scan->ysamp / scan->ydpi; 1994141cc406Sopenharmony_ci const int hextra = 8 / yoff_scale; 1995141cc406Sopenharmony_ci 1996141cc406Sopenharmony_ci linelen = 3 * scan->w; 1997141cc406Sopenharmony_ci scan->hexp = scan->h + hextra; 1998141cc406Sopenharmony_ci } 1999141cc406Sopenharmony_ci else 2000141cc406Sopenharmony_ci { 2001141cc406Sopenharmony_ci linelen = scan->w; 2002141cc406Sopenharmony_ci scan->hexp = scan->h; 2003141cc406Sopenharmony_ci } 2004141cc406Sopenharmony_ci 2005141cc406Sopenharmony_ci scan->bh = BUFFER_SIZE / linelen; 2006141cc406Sopenharmony_ci 2007141cc406Sopenharmony_ci scan->p = malloc (scan->bh * linelen); 2008141cc406Sopenharmony_ci if (scan->p == 0) 2009141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2010141cc406Sopenharmony_ci 2011141cc406Sopenharmony_ci DBG (4, "UMAX_start_scan: bh = %d, linelen = %d\n", scan->bh, linelen); 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci scan->maxh = -1; 2014141cc406Sopenharmony_ci scan->done = 0; 2015141cc406Sopenharmony_ci 2016141cc406Sopenharmony_ci /* Initialize the scanner and position the scan head */ 2017141cc406Sopenharmony_ci 2018141cc406Sopenharmony_ci CHK (umaxinit (scan)); 2019141cc406Sopenharmony_ci 2020141cc406Sopenharmony_ci /* This scans in the black and white calibration strip that 2021141cc406Sopenharmony_ci * is located under the scanner's lid. The scan of that strip 2022141cc406Sopenharmony_ci * is used to pick correct values for the CCD calibration 2023141cc406Sopenharmony_ci * values 2024141cc406Sopenharmony_ci */ 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci scan->scanner_ypos = 0; 2027141cc406Sopenharmony_ci CHK (move (scan, 196, UMAX_NOT_FINE)); 2028141cc406Sopenharmony_ci CHK (find_zero (scan)); 2029141cc406Sopenharmony_ci CHK (move (scan, scan->scanner_yorg - 232 - scan->scanner_ypos, UMAX_FINE)); 2030141cc406Sopenharmony_ci CHK (get_caldata (scan, scan->color)); 2031141cc406Sopenharmony_ci 2032141cc406Sopenharmony_ci /* This moves the head back to the starting position */ 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; 2035141cc406Sopenharmony_ci if (yd < 0) 2036141cc406Sopenharmony_ci CHK (move (scan, yd, UMAX_FINE)); 2037141cc406Sopenharmony_ci if (yd > 300) 2038141cc406Sopenharmony_ci CHK (move (scan, (yd - 20) / 2, UMAX_NOT_FINE)); 2039141cc406Sopenharmony_ci yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; 2040141cc406Sopenharmony_ci 2041141cc406Sopenharmony_ci scan->yskip = yd / (600 / scan->ydpi); 2042141cc406Sopenharmony_ci scan->xskip = scan->xo / (600 / scan->xdpi); 2043141cc406Sopenharmony_ci 2044141cc406Sopenharmony_ci /* Read in the first chunk of raw data */ 2045141cc406Sopenharmony_ci 2046141cc406Sopenharmony_ci CHK (send_scan_parameters (scan)); 2047141cc406Sopenharmony_ci CHK (read_raw_strip (scan)); 2048141cc406Sopenharmony_ci 2049141cc406Sopenharmony_ci DBG (4, "UMAX_start_scan successful\n"); 2050141cc406Sopenharmony_ci 2051141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2052141cc406Sopenharmony_ci} 2053141cc406Sopenharmony_ci 2054141cc406Sopenharmony_ci 2055141cc406Sopenharmony_ci/* Start actual scan 2100U */ 2056141cc406Sopenharmony_ci 2057141cc406Sopenharmony_cistatic SANE_Status 2058141cc406Sopenharmony_ciUMAX_start_scan_2100U (UMAX_Handle * scan) 2059141cc406Sopenharmony_ci{ 2060141cc406Sopenharmony_ci SANE_Status res; 2061141cc406Sopenharmony_ci int linelen; 2062141cc406Sopenharmony_ci int yd; 2063141cc406Sopenharmony_ci 2064141cc406Sopenharmony_ci DBG (3, "UMAX_start_scan called\n"); 2065141cc406Sopenharmony_ci 2066141cc406Sopenharmony_ci if (scan->color) 2067141cc406Sopenharmony_ci { 2068141cc406Sopenharmony_ci const int yoff_scale = 600 * scan->ysamp / scan->ydpi; 2069141cc406Sopenharmony_ci const int hextra = 8 / yoff_scale; 2070141cc406Sopenharmony_ci 2071141cc406Sopenharmony_ci linelen = 3 * scan->w; 2072141cc406Sopenharmony_ci scan->hexp = scan->h + hextra; 2073141cc406Sopenharmony_ci } 2074141cc406Sopenharmony_ci else 2075141cc406Sopenharmony_ci { 2076141cc406Sopenharmony_ci linelen = scan->w; 2077141cc406Sopenharmony_ci scan->hexp = scan->h; 2078141cc406Sopenharmony_ci } 2079141cc406Sopenharmony_ci 2080141cc406Sopenharmony_ci scan->bh = BUFFER_SIZE / linelen; 2081141cc406Sopenharmony_ci 2082141cc406Sopenharmony_ci scan->p = malloc (scan->bh * linelen); 2083141cc406Sopenharmony_ci if (scan->p == 0) 2084141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 2085141cc406Sopenharmony_ci 2086141cc406Sopenharmony_ci DBG (4, "UMAX_start_scan: bh = %d, linelen = %d\n", scan->bh, linelen); 2087141cc406Sopenharmony_ci 2088141cc406Sopenharmony_ci scan->maxh = -1; 2089141cc406Sopenharmony_ci scan->done = 0; 2090141cc406Sopenharmony_ci 2091141cc406Sopenharmony_ci /* Initialize the scanner and position the scan head */ 2092141cc406Sopenharmony_ci 2093141cc406Sopenharmony_ci CHK (umaxinit_2100U (scan)); 2094141cc406Sopenharmony_ci 2095141cc406Sopenharmony_ci /* This scans in the black and white calibration strip that 2096141cc406Sopenharmony_ci * is located under the scanner's lid. The scan of that strip 2097141cc406Sopenharmony_ci * is used to pick correct values for the CCD calibration 2098141cc406Sopenharmony_ci * values 2099141cc406Sopenharmony_ci */ 2100141cc406Sopenharmony_ci 2101141cc406Sopenharmony_ci scan->scanner_ypos = 0; 2102141cc406Sopenharmony_ci CHK (move_2100U (scan, 196, UMAX_NOT_FINE)); 2103141cc406Sopenharmony_ci CHK (find_zero_2100U (scan)); 2104141cc406Sopenharmony_ci CHK (move_2100U (scan, scan->scanner_yorg - 232 - scan->scanner_ypos, UMAX_FINE)); 2105141cc406Sopenharmony_ci CHK (get_caldata_2100U (scan, scan->color)); 2106141cc406Sopenharmony_ci 2107141cc406Sopenharmony_ci /* This moves the head back to the starting position */ 2108141cc406Sopenharmony_ci 2109141cc406Sopenharmony_ci yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; 2110141cc406Sopenharmony_ci if (yd < 0) 2111141cc406Sopenharmony_ci CHK (move_2100U (scan, yd, UMAX_FINE)); 2112141cc406Sopenharmony_ci if (yd > 300) 2113141cc406Sopenharmony_ci CHK (move_2100U (scan, (yd - 20) / 2, UMAX_NOT_FINE)); 2114141cc406Sopenharmony_ci yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; 2115141cc406Sopenharmony_ci 2116141cc406Sopenharmony_ci scan->yskip = yd / (600 / scan->ydpi); 2117141cc406Sopenharmony_ci scan->xskip = scan->xo / (600 / scan->xdpi); 2118141cc406Sopenharmony_ci 2119141cc406Sopenharmony_ci /* Read in the first chunk of raw data */ 2120141cc406Sopenharmony_ci 2121141cc406Sopenharmony_ci CHK (send_scan_parameters_2100U (scan)); 2122141cc406Sopenharmony_ci CHK (read_raw_strip (scan)); 2123141cc406Sopenharmony_ci 2124141cc406Sopenharmony_ci DBG (4, "UMAX_start_scan successful\n"); 2125141cc406Sopenharmony_ci 2126141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2127141cc406Sopenharmony_ci} 2128141cc406Sopenharmony_ci 2129141cc406Sopenharmony_ci/* Set lamp state */ 2130141cc406Sopenharmony_ci 2131141cc406Sopenharmony_cistatic SANE_Status 2132141cc406Sopenharmony_ciUMAX_set_lamp_state (UMAX_Handle * scan, UMAX_Lamp_State state) 2133141cc406Sopenharmony_ci{ 2134141cc406Sopenharmony_ci SANE_Status res; 2135141cc406Sopenharmony_ci 2136141cc406Sopenharmony_ci DBG (3, "UMAX_set_lamp_state: state = %d\n", (int) state); 2137141cc406Sopenharmony_ci 2138141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 2139141cc406Sopenharmony_ci CHK (cwritev_opc1_lamp_ctrl (scan, state)); 2140141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2141141cc406Sopenharmony_ci} 2142141cc406Sopenharmony_ci 2143141cc406Sopenharmony_ci/* Park head 1220U */ 2144141cc406Sopenharmony_ci 2145141cc406Sopenharmony_cistatic SANE_Status 2146141cc406Sopenharmony_ciUMAX_park_head (UMAX_Handle * scan) 2147141cc406Sopenharmony_ci{ 2148141cc406Sopenharmony_ci SANE_Status res; 2149141cc406Sopenharmony_ci UMAX_Status_Byte s; 2150141cc406Sopenharmony_ci int i; 2151141cc406Sopenharmony_ci 2152141cc406Sopenharmony_ci DBG (3, "UMAX_park_head called\n"); 2153141cc406Sopenharmony_ci 2154141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 2155141cc406Sopenharmony_ci /* WARNING: Must call cwritev_opc1_lamp_ctrl before cwritev_opb3_restore, 2156141cc406Sopenharmony_ci * otherwise the head moves the wrong way and makes ugly grinding noises. */ 2157141cc406Sopenharmony_ci 2158141cc406Sopenharmony_ci CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON)); 2159141cc406Sopenharmony_ci CHK (cwritev_opb3_restore (scan)); 2160141cc406Sopenharmony_ci 2161141cc406Sopenharmony_ci for (i = 0; i < 60; ++i) 2162141cc406Sopenharmony_ci { 2163141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 2164141cc406Sopenharmony_ci DBG (4, "UMAX_park_head: s = %#x\n", s); 2165141cc406Sopenharmony_ci if ((s & 0x40) != 0) 2166141cc406Sopenharmony_ci break; 2167141cc406Sopenharmony_ci DBG (4, "UMAX_park_head: sleeping\n"); 2168141cc406Sopenharmony_ci usleep (500000); 2169141cc406Sopenharmony_ci } 2170141cc406Sopenharmony_ci 2171141cc406Sopenharmony_ci scan->scanner_ypos = 0; 2172141cc406Sopenharmony_ci 2173141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2174141cc406Sopenharmony_ci} 2175141cc406Sopenharmony_ci 2176141cc406Sopenharmony_ci 2177141cc406Sopenharmony_ci/* Park head 2100U */ 2178141cc406Sopenharmony_ci 2179141cc406Sopenharmony_cistatic SANE_Status 2180141cc406Sopenharmony_ciUMAX_park_head_2100U (UMAX_Handle * scan) 2181141cc406Sopenharmony_ci{ 2182141cc406Sopenharmony_ci SANE_Status res; 2183141cc406Sopenharmony_ci UMAX_Status_Byte s; 2184141cc406Sopenharmony_ci int i; 2185141cc406Sopenharmony_ci 2186141cc406Sopenharmony_ci DBG (3, "UMAX_park_head called\n"); 2187141cc406Sopenharmony_ci 2188141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); 2189141cc406Sopenharmony_ci /* WARNING: Must call cwritev_opc1_lamp_ctrl before cwritev_opb3_restore, 2190141cc406Sopenharmony_ci * otherwise the head moves the wrong way and makes ugly grinding noises. */ 2191141cc406Sopenharmony_ci 2192141cc406Sopenharmony_ci CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON)); 2193141cc406Sopenharmony_ci CHK (cwritev_opb3_restore_2100U (scan)); 2194141cc406Sopenharmony_ci 2195141cc406Sopenharmony_ci for (i = 0; i < 60; ++i) 2196141cc406Sopenharmony_ci { 2197141cc406Sopenharmony_ci CHK (cread (scan, CMD_2, 0, NULL, &s)); 2198141cc406Sopenharmony_ci DBG (4, "UMAX_park_head: s = %#x\n", s); 2199141cc406Sopenharmony_ci if ((s & 0x40) != 0) 2200141cc406Sopenharmony_ci break; 2201141cc406Sopenharmony_ci DBG (4, "UMAX_park_head: sleeping\n"); 2202141cc406Sopenharmony_ci usleep (500000); 2203141cc406Sopenharmony_ci } 2204141cc406Sopenharmony_ci 2205141cc406Sopenharmony_ci /* CHK (csend (scan, CMD_0)); 2206141cc406Sopenharmony_ci CHK (csend (scan, CMD_0)); */ 2207141cc406Sopenharmony_ci 2208141cc406Sopenharmony_ci scan->scanner_ypos = 0; 2209141cc406Sopenharmony_ci 2210141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2211141cc406Sopenharmony_ci} 2212141cc406Sopenharmony_ci 2213141cc406Sopenharmony_ci 2214141cc406Sopenharmony_ci/* Finish scan */ 2215141cc406Sopenharmony_ci 2216141cc406Sopenharmony_cistatic SANE_Status 2217141cc406Sopenharmony_ciUMAX_finish_scan (UMAX_Handle * scan) 2218141cc406Sopenharmony_ci{ 2219141cc406Sopenharmony_ci DBG (3, "UMAX_finish_scan:\n"); 2220141cc406Sopenharmony_ci 2221141cc406Sopenharmony_ci if (scan->p) 2222141cc406Sopenharmony_ci free (scan->p); 2223141cc406Sopenharmony_ci scan->p = NULL; 2224141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2225141cc406Sopenharmony_ci} 2226141cc406Sopenharmony_ci 2227141cc406Sopenharmony_ci 2228141cc406Sopenharmony_ci/* RGB decoding for a color scan */ 2229141cc406Sopenharmony_ci 2230141cc406Sopenharmony_cistatic SANE_Status 2231141cc406Sopenharmony_ciUMAX_get_rgb (UMAX_Handle * scan, unsigned char *rgb) 2232141cc406Sopenharmony_ci{ 2233141cc406Sopenharmony_ci 2234141cc406Sopenharmony_ci if (scan->color) 2235141cc406Sopenharmony_ci { 2236141cc406Sopenharmony_ci const int linelen = 3 * scan->w; 2237141cc406Sopenharmony_ci const int yoff_scale = 600 * scan->ysamp / scan->ydpi; 2238141cc406Sopenharmony_ci const int roff = (8 / yoff_scale * 3 + 2) * scan->w; 2239141cc406Sopenharmony_ci const int goff = (4 / yoff_scale * 3 + 1) * scan->w; 2240141cc406Sopenharmony_ci const int boff = 0; 2241141cc406Sopenharmony_ci 2242141cc406Sopenharmony_ci unsigned char *base = scan->p + (scan->y * linelen) + scan->x; 2243141cc406Sopenharmony_ci 2244141cc406Sopenharmony_ci rgb[0] = base[roff]; 2245141cc406Sopenharmony_ci rgb[1] = base[goff]; 2246141cc406Sopenharmony_ci rgb[2] = base[boff]; 2247141cc406Sopenharmony_ci } 2248141cc406Sopenharmony_ci else 2249141cc406Sopenharmony_ci { 2250141cc406Sopenharmony_ci const int linelen = scan->w; 2251141cc406Sopenharmony_ci unsigned char *base = scan->p + (scan->y * linelen) + (scan->x); 2252141cc406Sopenharmony_ci 2253141cc406Sopenharmony_ci rgb[0] = base[0]; 2254141cc406Sopenharmony_ci rgb[1] = base[0]; 2255141cc406Sopenharmony_ci rgb[2] = base[0]; 2256141cc406Sopenharmony_ci } 2257141cc406Sopenharmony_ci 2258141cc406Sopenharmony_ci if (!(((scan->x + 1) == scan->w) && ((scan->y + 1) == scan->maxh))) 2259141cc406Sopenharmony_ci { 2260141cc406Sopenharmony_ci ++scan->x; 2261141cc406Sopenharmony_ci if (scan->x == scan->w) 2262141cc406Sopenharmony_ci { 2263141cc406Sopenharmony_ci ++scan->y; 2264141cc406Sopenharmony_ci scan->x = 0; 2265141cc406Sopenharmony_ci } 2266141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2267141cc406Sopenharmony_ci } 2268141cc406Sopenharmony_ci 2269141cc406Sopenharmony_ci if (scan->hexp <= 0) 2270141cc406Sopenharmony_ci { 2271141cc406Sopenharmony_ci DBG (4, "UMAX_get_rgb: setting done flag\n"); 2272141cc406Sopenharmony_ci scan->done = 1; 2273141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2274141cc406Sopenharmony_ci } 2275141cc406Sopenharmony_ci 2276141cc406Sopenharmony_ci return read_raw_strip (scan); 2277141cc406Sopenharmony_ci} 2278141cc406Sopenharmony_ci 2279141cc406Sopenharmony_ci/* Close device */ 2280141cc406Sopenharmony_ci 2281141cc406Sopenharmony_cistatic SANE_Status 2282141cc406Sopenharmony_ciUMAX_close_device (UMAX_Handle * scan) 2283141cc406Sopenharmony_ci{ 2284141cc406Sopenharmony_ci DBG (3, "UMAX_close_device:\n"); 2285141cc406Sopenharmony_ci sanei_usb_close (scan->fd); 2286141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2287141cc406Sopenharmony_ci} 2288141cc406Sopenharmony_ci 2289141cc406Sopenharmony_ci/* Open device */ 2290141cc406Sopenharmony_ci 2291141cc406Sopenharmony_cistatic SANE_Status 2292141cc406Sopenharmony_ciUMAX_open_device (UMAX_Handle * scan, const char *dev) 2293141cc406Sopenharmony_ci{ 2294141cc406Sopenharmony_ci SANE_Word vendor; 2295141cc406Sopenharmony_ci SANE_Word product; 2296141cc406Sopenharmony_ci SANE_Status res; 2297141cc406Sopenharmony_ci 2298141cc406Sopenharmony_ci DBG (3, "UMAX_open_device: `%s'\n", dev); 2299141cc406Sopenharmony_ci 2300141cc406Sopenharmony_ci res = sanei_usb_open (dev, &scan->fd); 2301141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 2302141cc406Sopenharmony_ci { 2303141cc406Sopenharmony_ci DBG (1, "UMAX_open_device: couldn't open device `%s': %s\n", dev, 2304141cc406Sopenharmony_ci sane_strstatus (res)); 2305141cc406Sopenharmony_ci return res; 2306141cc406Sopenharmony_ci } 2307141cc406Sopenharmony_ci 2308141cc406Sopenharmony_ci#ifndef NO_AUTODETECT 2309141cc406Sopenharmony_ci /* We have opened the device. Check that it is a USB scanner. */ 2310141cc406Sopenharmony_ci if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) != 2311141cc406Sopenharmony_ci SANE_STATUS_GOOD) 2312141cc406Sopenharmony_ci { 2313141cc406Sopenharmony_ci DBG (1, "UMAX_open_device: sanei_usb_get_vendor_product failed\n"); 2314141cc406Sopenharmony_ci /* This is not a USB scanner, or SANE or the OS doesn't support it. */ 2315141cc406Sopenharmony_ci sanei_usb_close (scan->fd); 2316141cc406Sopenharmony_ci scan->fd = -1; 2317141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2318141cc406Sopenharmony_ci } 2319141cc406Sopenharmony_ci 2320141cc406Sopenharmony_ci /* Make sure we have a UMAX scanner */ 2321141cc406Sopenharmony_ci if (vendor != 0x1606) 2322141cc406Sopenharmony_ci { 2323141cc406Sopenharmony_ci DBG (1, "UMAX_open_device: incorrect vendor\n"); 2324141cc406Sopenharmony_ci sanei_usb_close (scan->fd); 2325141cc406Sopenharmony_ci scan->fd = -1; 2326141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2327141cc406Sopenharmony_ci } 2328141cc406Sopenharmony_ci 2329141cc406Sopenharmony_ci /* Now check whether it is a scanner we know about */ 2330141cc406Sopenharmony_ci switch (product) 2331141cc406Sopenharmony_ci { 2332141cc406Sopenharmony_ci case ASTRA_2000U: 2333141cc406Sopenharmony_ci /* The UMAX Astra 2000U is only partially supported by 2334141cc406Sopenharmony_ci this driver. Expect severe color problems! :) 2335141cc406Sopenharmony_ci */ 2336141cc406Sopenharmony_ci DBG (1, 2337141cc406Sopenharmony_ci "UMAX_open_device: Scanner is a 2000U. Expect color problems :)\n"); 2338141cc406Sopenharmony_ci scan->model = ASTRA_2000U; 2339141cc406Sopenharmony_ci break; 2340141cc406Sopenharmony_ci case ASTRA_2100U: 2341141cc406Sopenharmony_ci scan->model = ASTRA_2100U; 2342141cc406Sopenharmony_ci break; 2343141cc406Sopenharmony_ci case ASTRA_1220U: 2344141cc406Sopenharmony_ci scan->model = ASTRA_1220U; 2345141cc406Sopenharmony_ci break; 2346141cc406Sopenharmony_ci default: 2347141cc406Sopenharmony_ci DBG (1, "UMAX_open_device: unknown product number\n"); 2348141cc406Sopenharmony_ci sanei_usb_close (scan->fd); 2349141cc406Sopenharmony_ci scan->fd = -1; 2350141cc406Sopenharmony_ci return SANE_STATUS_UNSUPPORTED; 2351141cc406Sopenharmony_ci } 2352141cc406Sopenharmony_ci#endif 2353141cc406Sopenharmony_ci 2354141cc406Sopenharmony_ci res = csend (scan, CMD_0); 2355141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 2356141cc406Sopenharmony_ci UMAX_close_device (scan); 2357141cc406Sopenharmony_ci CHK (res); 2358141cc406Sopenharmony_ci 2359141cc406Sopenharmony_ci res = xxxops (scan); 2360141cc406Sopenharmony_ci if (res != SANE_STATUS_GOOD) 2361141cc406Sopenharmony_ci UMAX_close_device (scan); 2362141cc406Sopenharmony_ci CHK (res); 2363141cc406Sopenharmony_ci 2364141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 2365141cc406Sopenharmony_ci} 2366141cc406Sopenharmony_ci 2367141cc406Sopenharmony_ci/* Get scanner model name */ 2368141cc406Sopenharmony_ci 2369141cc406Sopenharmony_cistatic const char * 2370141cc406Sopenharmony_ciUMAX_get_device_name (UMAX_Handle * scan) 2371141cc406Sopenharmony_ci{ 2372141cc406Sopenharmony_ci switch (scan->model) 2373141cc406Sopenharmony_ci { 2374141cc406Sopenharmony_ci case ASTRA_1220U: 2375141cc406Sopenharmony_ci return "Astra 1220U"; 2376141cc406Sopenharmony_ci case ASTRA_2000U: 2377141cc406Sopenharmony_ci return "Astra 2000U"; 2378141cc406Sopenharmony_ci case ASTRA_2100U: 2379141cc406Sopenharmony_ci return "Astra 2100U"; 2380141cc406Sopenharmony_ci } 2381141cc406Sopenharmony_ci return "Unknown"; 2382141cc406Sopenharmony_ci} 2383141cc406Sopenharmony_ci 2384141cc406Sopenharmony_ci/* End */ 2385