1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2007-2013 stef.dev@free.fr 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This file is part of the SANE package. 6141cc406Sopenharmony_ci 7141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 8141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 9141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 10141cc406Sopenharmony_ci License, or (at your option) any later version. 11141cc406Sopenharmony_ci 12141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 13141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 14141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15141cc406Sopenharmony_ci General Public License for more details. 16141cc406Sopenharmony_ci 17141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 18141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci As a special exception, the authors of SANE give permission for 21141cc406Sopenharmony_ci additional uses of the libraries contained in this release of SANE. 22141cc406Sopenharmony_ci 23141cc406Sopenharmony_ci The exception is that, if you link a SANE library with other files 24141cc406Sopenharmony_ci to produce an executable, this does not by itself cause the 25141cc406Sopenharmony_ci resulting executable to be covered by the GNU General Public 26141cc406Sopenharmony_ci License. Your use of that executable is in no way restricted on 27141cc406Sopenharmony_ci account of linking the SANE library code into it. 28141cc406Sopenharmony_ci 29141cc406Sopenharmony_ci This exception does not, however, invalidate any other reasons why 30141cc406Sopenharmony_ci the executable file might be covered by the GNU General Public 31141cc406Sopenharmony_ci License. 32141cc406Sopenharmony_ci 33141cc406Sopenharmony_ci If you submit changes to SANE to the maintainers to be included in 34141cc406Sopenharmony_ci a subsequent release, you agree by submitting the changes that 35141cc406Sopenharmony_ci those changes may be distributed with this exception intact. 36141cc406Sopenharmony_ci 37141cc406Sopenharmony_ci If you write modifications of your own for SANE, it is your choice 38141cc406Sopenharmony_ci whether to permit this exception to apply to your modifications. 39141cc406Sopenharmony_ci If you do not wish that, delete this exception notice. 40141cc406Sopenharmony_ci*/ 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci/* this file contains all the low level functions needed for the higher level 43141cc406Sopenharmony_ci * functions of the sane standard. They are put there to keep files smaller 44141cc406Sopenharmony_ci * and separate functions with different goals. 45141cc406Sopenharmony_ci */ 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#include "../include/sane/config.h" 48141cc406Sopenharmony_ci#include "../include/sane/sane.h" 49141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h" 50141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 51141cc406Sopenharmony_ci 52141cc406Sopenharmony_ci#include <stdio.h> 53141cc406Sopenharmony_ci#ifdef HAVE_SYS_TIME_H 54141cc406Sopenharmony_ci#include <sys/time.h> 55141cc406Sopenharmony_ci#endif 56141cc406Sopenharmony_ci#include "rts8891_low.h" 57141cc406Sopenharmony_ci 58141cc406Sopenharmony_ci#define RTS8891_BUILD 30 59141cc406Sopenharmony_ci#define RTS8891_MAX_REGISTERS 244 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci/* init rts8891 library */ 62141cc406Sopenharmony_cistatic void 63141cc406Sopenharmony_cirts8891_low_init (void) 64141cc406Sopenharmony_ci{ 65141cc406Sopenharmony_ci DBG_INIT (); 66141cc406Sopenharmony_ci DBG (DBG_info, "RTS8891 low-level functions, version %d.%d-%d\n", 67141cc406Sopenharmony_ci SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, RTS8891_BUILD); 68141cc406Sopenharmony_ci} 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci 71141cc406Sopenharmony_ci/****************************************************************/ 72141cc406Sopenharmony_ci/* ASIC specific functions */ 73141cc406Sopenharmony_ci/****************************************************************/ 74141cc406Sopenharmony_ci 75141cc406Sopenharmony_ci/* write all registers, taking care of the special 0xaa value which 76141cc406Sopenharmony_ci * must be escaped with a zero 77141cc406Sopenharmony_ci */ 78141cc406Sopenharmony_cistatic SANE_Status 79141cc406Sopenharmony_cirts8891_write_all (SANE_Int devnum, SANE_Byte * regs, SANE_Int count) 80141cc406Sopenharmony_ci{ 81141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 82141cc406Sopenharmony_ci SANE_Byte local_regs[RTS8891_MAX_REGISTERS]; 83141cc406Sopenharmony_ci size_t size = 0; 84141cc406Sopenharmony_ci SANE_Byte buffer[260]; 85141cc406Sopenharmony_ci unsigned int i, j; 86141cc406Sopenharmony_ci char message[256 * 5]; 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io) 89141cc406Sopenharmony_ci { 90141cc406Sopenharmony_ci for (i = 0; i < (unsigned int) count; i++) 91141cc406Sopenharmony_ci { 92141cc406Sopenharmony_ci if (i != 0xb3) 93141cc406Sopenharmony_ci sprintf (message + 5 * i, "0x%02x ", regs[i]); 94141cc406Sopenharmony_ci else 95141cc406Sopenharmony_ci sprintf (message + 5 * i, "---- "); 96141cc406Sopenharmony_ci } 97141cc406Sopenharmony_ci DBG (DBG_io, "rts8891_write_all : write_all(0x00,%d)=%s\n", count, 98141cc406Sopenharmony_ci message); 99141cc406Sopenharmony_ci } 100141cc406Sopenharmony_ci 101141cc406Sopenharmony_ci /* copy register set and escaping 0xaa values */ 102141cc406Sopenharmony_ci /* b0, b1 abd b3 values may be scribled, but that isn't important */ 103141cc406Sopenharmony_ci /* since they are read-only registers */ 104141cc406Sopenharmony_ci j = 0; 105141cc406Sopenharmony_ci for (i = 0; i < 0xb3; i++) 106141cc406Sopenharmony_ci { 107141cc406Sopenharmony_ci local_regs[j] = regs[i]; 108141cc406Sopenharmony_ci if (local_regs[j] == 0xaa && i < 0xb3) 109141cc406Sopenharmony_ci { 110141cc406Sopenharmony_ci j++; 111141cc406Sopenharmony_ci local_regs[j] = 0x00; 112141cc406Sopenharmony_ci } 113141cc406Sopenharmony_ci j++; 114141cc406Sopenharmony_ci } 115141cc406Sopenharmony_ci buffer[0] = 0x88; 116141cc406Sopenharmony_ci buffer[1] = 0; 117141cc406Sopenharmony_ci buffer[2] = 0x00; 118141cc406Sopenharmony_ci buffer[3] = 0xb3; 119141cc406Sopenharmony_ci for (i = 0; i < j; i++) 120141cc406Sopenharmony_ci buffer[i + 4] = local_regs[i]; 121141cc406Sopenharmony_ci /* the USB block is size + 4 bytes of header long */ 122141cc406Sopenharmony_ci size = j + 4; 123141cc406Sopenharmony_ci if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) 124141cc406Sopenharmony_ci { 125141cc406Sopenharmony_ci DBG (DBG_error, 126141cc406Sopenharmony_ci "rts88xx_write_all : write registers part 1 failed ...\n"); 127141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 128141cc406Sopenharmony_ci } 129141cc406Sopenharmony_ci 130141cc406Sopenharmony_ci size = count - 0xb4; /* we need to subtract one reg since b3 won't be written */ 131141cc406Sopenharmony_ci buffer[0] = 0x88; 132141cc406Sopenharmony_ci buffer[1] = 0xb4; 133141cc406Sopenharmony_ci buffer[2] = 0x00; 134141cc406Sopenharmony_ci buffer[3] = size; 135141cc406Sopenharmony_ci for (i = 0; i < size; i++) 136141cc406Sopenharmony_ci buffer[i + 4] = regs[0xb4 + i]; 137141cc406Sopenharmony_ci /* the USB block is size + 4 bytes of header long */ 138141cc406Sopenharmony_ci size += 4; 139141cc406Sopenharmony_ci if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) 140141cc406Sopenharmony_ci { 141141cc406Sopenharmony_ci DBG (DBG_error, 142141cc406Sopenharmony_ci "rts88xx_write_all : write registers part 2 failed ...\n"); 143141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 144141cc406Sopenharmony_ci } 145141cc406Sopenharmony_ci return status; 146141cc406Sopenharmony_ci} 147141cc406Sopenharmony_ci 148141cc406Sopenharmony_ci 149141cc406Sopenharmony_ci/* this functions "commits" pending scan command */ 150141cc406Sopenharmony_cistatic SANE_Status 151141cc406Sopenharmony_cirts8891_commit (SANE_Int devnum, SANE_Byte value) 152141cc406Sopenharmony_ci{ 153141cc406Sopenharmony_ci SANE_Status status; 154141cc406Sopenharmony_ci SANE_Byte reg; 155141cc406Sopenharmony_ci 156141cc406Sopenharmony_ci reg = value; 157141cc406Sopenharmony_ci sanei_rts88xx_write_reg (devnum, 0xd3, ®); 158141cc406Sopenharmony_ci sanei_rts88xx_cancel (devnum); 159141cc406Sopenharmony_ci sanei_rts88xx_write_control (devnum, 0x08); 160141cc406Sopenharmony_ci status = sanei_rts88xx_write_control (devnum, 0x08); 161141cc406Sopenharmony_ci return status; 162141cc406Sopenharmony_ci} 163141cc406Sopenharmony_ci 164141cc406Sopenharmony_ci/* this functions reads button status */ 165141cc406Sopenharmony_cistatic SANE_Status 166141cc406Sopenharmony_cirts8891_read_buttons (SANE_Int devnum, SANE_Int * mask) 167141cc406Sopenharmony_ci{ 168141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 169141cc406Sopenharmony_ci SANE_Byte reg; 170141cc406Sopenharmony_ci 171141cc406Sopenharmony_ci /* check CONTROL_REG */ 172141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, CONTROL_REG, ®); 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci /* read 'base' button status */ 175141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, 0x25, ®); 176141cc406Sopenharmony_ci DBG (DBG_io, "rts8891_read_buttons: r25=0x%02x\n", reg); 177141cc406Sopenharmony_ci *mask |= reg; 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci /* read 'extended' button status */ 180141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, 0x1a, ®); 181141cc406Sopenharmony_ci DBG (DBG_io, "rts8891_read_buttons: r1a=0x%02x\n", reg); 182141cc406Sopenharmony_ci *mask |= reg << 8; 183141cc406Sopenharmony_ci 184141cc406Sopenharmony_ci /* clear register r25 */ 185141cc406Sopenharmony_ci reg = 0x00; 186141cc406Sopenharmony_ci sanei_rts88xx_write_reg (devnum, 0x25, ®); 187141cc406Sopenharmony_ci 188141cc406Sopenharmony_ci /* clear register r1a */ 189141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, 0x1a, ®); 190141cc406Sopenharmony_ci reg = 0x00; 191141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (devnum, 0x1a, ®); 192141cc406Sopenharmony_ci 193141cc406Sopenharmony_ci DBG (DBG_info, "rts8891_read_buttons: mask=0x%04x\n", *mask); 194141cc406Sopenharmony_ci return status; 195141cc406Sopenharmony_ci} 196141cc406Sopenharmony_ci 197141cc406Sopenharmony_ci/* 198141cc406Sopenharmony_ci * Does a simple scan based on the given register set, returning data in a 199141cc406Sopenharmony_ci * preallocated buffer of the claimed size. 200141cc406Sopenharmony_ci * sanei_rts88xx_data_count cannot be made reliable, when the announced data 201141cc406Sopenharmony_ci * amount is read, it may no be ready, leading to errors. To work around 202141cc406Sopenharmony_ci * it, we read data count one more time before reading. 203141cc406Sopenharmony_ci */ 204141cc406Sopenharmony_cistatic SANE_Status 205141cc406Sopenharmony_cirts8891_simple_scan (SANE_Int devnum, SANE_Byte * regs, int regcount, 206141cc406Sopenharmony_ci SANE_Int format, SANE_Word total, unsigned char *image) 207141cc406Sopenharmony_ci{ 208141cc406Sopenharmony_ci SANE_Word count, read, len, dummy; 209141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 210141cc406Sopenharmony_ci SANE_Byte control; 211141cc406Sopenharmony_ci 212141cc406Sopenharmony_ci rts8891_write_all (devnum, regs, regcount); 213141cc406Sopenharmony_ci rts8891_commit (devnum, format); 214141cc406Sopenharmony_ci 215141cc406Sopenharmony_ci read = 0; 216141cc406Sopenharmony_ci count = 0; 217141cc406Sopenharmony_ci while (count == 0) 218141cc406Sopenharmony_ci { 219141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (devnum, &count); 220141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 221141cc406Sopenharmony_ci { 222141cc406Sopenharmony_ci DBG (DBG_error, "simple_scan: failed to wait for data\n"); 223141cc406Sopenharmony_ci return status; 224141cc406Sopenharmony_ci } 225141cc406Sopenharmony_ci if (count == 0) 226141cc406Sopenharmony_ci { 227141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); 228141cc406Sopenharmony_ci if (((control & 0x08) == 0) || (status != SANE_STATUS_GOOD)) 229141cc406Sopenharmony_ci { 230141cc406Sopenharmony_ci DBG (DBG_error, "simple_scan: failed to wait for data\n"); 231141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 232141cc406Sopenharmony_ci } 233141cc406Sopenharmony_ci } 234141cc406Sopenharmony_ci } 235141cc406Sopenharmony_ci 236141cc406Sopenharmony_ci /* data reading */ 237141cc406Sopenharmony_ci read = 0; 238141cc406Sopenharmony_ci while ((read < total) && (count != 0 || (control & 0x08) == 0x08)) 239141cc406Sopenharmony_ci { 240141cc406Sopenharmony_ci /* sync ? */ 241141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (devnum, &dummy); 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci /* read */ 244141cc406Sopenharmony_ci if (count > 0) 245141cc406Sopenharmony_ci { 246141cc406Sopenharmony_ci len = count; 247141cc406Sopenharmony_ci /* read even size unless last chunk */ 248141cc406Sopenharmony_ci if ((len & 1) && (read + len < total)) 249141cc406Sopenharmony_ci { 250141cc406Sopenharmony_ci len++; 251141cc406Sopenharmony_ci } 252141cc406Sopenharmony_ci if (len > RTS88XX_MAX_XFER_SIZE) 253141cc406Sopenharmony_ci { 254141cc406Sopenharmony_ci len = RTS88XX_MAX_XFER_SIZE; 255141cc406Sopenharmony_ci } 256141cc406Sopenharmony_ci if (len > 0) 257141cc406Sopenharmony_ci { 258141cc406Sopenharmony_ci status = sanei_rts88xx_read_data (devnum, &len, image + read); 259141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 260141cc406Sopenharmony_ci { 261141cc406Sopenharmony_ci DBG (DBG_error, 262141cc406Sopenharmony_ci "simple_scan: failed to read from scanner\n"); 263141cc406Sopenharmony_ci return status; 264141cc406Sopenharmony_ci } 265141cc406Sopenharmony_ci read += len; 266141cc406Sopenharmony_ci } 267141cc406Sopenharmony_ci } 268141cc406Sopenharmony_ci 269141cc406Sopenharmony_ci /* don't try to read data count if we have enough data */ 270141cc406Sopenharmony_ci if (read < total) 271141cc406Sopenharmony_ci { 272141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (devnum, &count); 273141cc406Sopenharmony_ci } 274141cc406Sopenharmony_ci else 275141cc406Sopenharmony_ci { 276141cc406Sopenharmony_ci count = 0; 277141cc406Sopenharmony_ci } 278141cc406Sopenharmony_ci if (count == 0) 279141cc406Sopenharmony_ci { 280141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); 281141cc406Sopenharmony_ci } 282141cc406Sopenharmony_ci } 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci /* sanity check */ 285141cc406Sopenharmony_ci if (read < total) 286141cc406Sopenharmony_ci { 287141cc406Sopenharmony_ci DBG (DBG_io2, "simple_scan: ERROR, %d bytes missing ... \n", 288141cc406Sopenharmony_ci total - read); 289141cc406Sopenharmony_ci } 290141cc406Sopenharmony_ci 291141cc406Sopenharmony_ci /* wait for the motor to stop */ 292141cc406Sopenharmony_ci do 293141cc406Sopenharmony_ci { 294141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); 295141cc406Sopenharmony_ci } 296141cc406Sopenharmony_ci while ((control & 0x08) == 0x08); 297141cc406Sopenharmony_ci 298141cc406Sopenharmony_ci return status; 299141cc406Sopenharmony_ci} 300141cc406Sopenharmony_ci 301141cc406Sopenharmony_ci /** 302141cc406Sopenharmony_ci * set the data format. Is part of the commit sequence. Then returned 303141cc406Sopenharmony_ci * value is the value used in d3 register for a scan. 304141cc406Sopenharmony_ci */ 305141cc406Sopenharmony_cistatic SANE_Int 306141cc406Sopenharmony_cirts8891_data_format (SANE_Int dpi, int sensor) 307141cc406Sopenharmony_ci{ 308141cc406Sopenharmony_ci SANE_Byte reg = 0x00; 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci /* it seems that lower nibble is a divisor */ 311141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_BARE || sensor == SENSOR_TYPE_XPA) 312141cc406Sopenharmony_ci { 313141cc406Sopenharmony_ci switch (dpi) 314141cc406Sopenharmony_ci { 315141cc406Sopenharmony_ci case 75: 316141cc406Sopenharmony_ci reg = 0x02; 317141cc406Sopenharmony_ci break; 318141cc406Sopenharmony_ci case 150: 319141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_BARE) 320141cc406Sopenharmony_ci reg = 0x0e; 321141cc406Sopenharmony_ci else 322141cc406Sopenharmony_ci reg = 0x0b; 323141cc406Sopenharmony_ci break; 324141cc406Sopenharmony_ci case 300: 325141cc406Sopenharmony_ci reg = 0x17; 326141cc406Sopenharmony_ci break; 327141cc406Sopenharmony_ci case 600: 328141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_BARE) 329141cc406Sopenharmony_ci reg = 0x02; 330141cc406Sopenharmony_ci else 331141cc406Sopenharmony_ci reg = 0x0e; 332141cc406Sopenharmony_ci break; 333141cc406Sopenharmony_ci case 1200: 334141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_BARE) 335141cc406Sopenharmony_ci reg = 0x17; 336141cc406Sopenharmony_ci else 337141cc406Sopenharmony_ci reg = 0x05; 338141cc406Sopenharmony_ci break; 339141cc406Sopenharmony_ci } 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_4400 || sensor == SENSOR_TYPE_4400_BARE) 342141cc406Sopenharmony_ci { 343141cc406Sopenharmony_ci switch (dpi) 344141cc406Sopenharmony_ci { 345141cc406Sopenharmony_ci case 75: 346141cc406Sopenharmony_ci reg = 0x02; 347141cc406Sopenharmony_ci break; 348141cc406Sopenharmony_ci case 150: 349141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_4400) 350141cc406Sopenharmony_ci reg = 0x0b; 351141cc406Sopenharmony_ci else 352141cc406Sopenharmony_ci reg = 0x17; 353141cc406Sopenharmony_ci break; 354141cc406Sopenharmony_ci case 300: 355141cc406Sopenharmony_ci reg = 0x17; 356141cc406Sopenharmony_ci break; 357141cc406Sopenharmony_ci case 600: 358141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_4400) 359141cc406Sopenharmony_ci reg = 0x0e; 360141cc406Sopenharmony_ci else 361141cc406Sopenharmony_ci reg = 0x02; 362141cc406Sopenharmony_ci break; 363141cc406Sopenharmony_ci case 1200: 364141cc406Sopenharmony_ci if (sensor == SENSOR_TYPE_4400) 365141cc406Sopenharmony_ci reg = 0x05; 366141cc406Sopenharmony_ci else 367141cc406Sopenharmony_ci reg = 0x17; 368141cc406Sopenharmony_ci break; 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci } 371141cc406Sopenharmony_ci return reg; 372141cc406Sopenharmony_ci} 373141cc406Sopenharmony_ci 374141cc406Sopenharmony_ci/** 375141cc406Sopenharmony_ci * set up default values for a 75xdpi, 150 ydpi scan 376141cc406Sopenharmony_ci */ 377141cc406Sopenharmony_cistatic void 378141cc406Sopenharmony_cirts8891_set_default_regs (SANE_Byte * scanner_regs) 379141cc406Sopenharmony_ci{ 380141cc406Sopenharmony_ci SANE_Byte default_75[RTS8891_MAX_REGISTERS] = 381141cc406Sopenharmony_ci { 0xe5, 0x41, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0a, 0x0a, 0x0a, 0x70, 382141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x28, 0x3f, 0xff, 0x20, 0xf8, 0x28, 0x07, 0x00, 383141cc406Sopenharmony_ci 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 384141cc406Sopenharmony_ci 0x00, 0x3a, 0xf2, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 385141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 386141cc406Sopenharmony_ci 0x00, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 387141cc406Sopenharmony_ci 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8c, 388141cc406Sopenharmony_ci 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 389141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 390141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 391141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 392141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x14, 0x18, 0x15, 0x00, 393141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 394141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395141cc406Sopenharmony_ci 0x00, 0xff, 0x3f, 0x80, 0x68, 0x00, 0x00, 396141cc406Sopenharmony_ci 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 398141cc406Sopenharmony_ci 0x27, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399141cc406Sopenharmony_ci 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 400141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 401141cc406Sopenharmony_ci 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 402141cc406Sopenharmony_ci 0x0e, 0x00, 0x00, 0xf0, 0xff, 0xf5, 0xf7, 0xea, 0x0b, 0x03, 0x05, 0x86, 403141cc406Sopenharmony_ci 0x1b, 0x30, 0xf6, 0xa2, 0x27, 0x00, 0x00, 404141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 405141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 406141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00 407141cc406Sopenharmony_ci }; 408141cc406Sopenharmony_ci unsigned int i; 409141cc406Sopenharmony_ci for (i = 0; i < RTS8891_MAX_REGISTERS; i++) 410141cc406Sopenharmony_ci scanner_regs[i] = default_75[i]; 411141cc406Sopenharmony_ci} 412141cc406Sopenharmony_ci 413141cc406Sopenharmony_cistatic SANE_Status 414141cc406Sopenharmony_cirts8891_move (struct Rts8891_Device *device, SANE_Byte * regs, 415141cc406Sopenharmony_ci SANE_Int distance, SANE_Bool forward) 416141cc406Sopenharmony_ci{ 417141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 418141cc406Sopenharmony_ci SANE_Byte regs10, regs11; 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci DBG (DBG_proc, "rts8891_move: start\n"); 421141cc406Sopenharmony_ci DBG (DBG_io, "rts8891_move: %d lines %s, sensor=%d\n", distance, 422141cc406Sopenharmony_ci forward == SANE_TRUE ? "forward" : "backward", device->sensor); 423141cc406Sopenharmony_ci 424141cc406Sopenharmony_ci /* prepare scan */ 425141cc406Sopenharmony_ci rts8891_set_default_regs (regs); 426141cc406Sopenharmony_ci if (device->sensor != SENSOR_TYPE_4400 427141cc406Sopenharmony_ci && device->sensor != SENSOR_TYPE_4400_BARE) 428141cc406Sopenharmony_ci { 429141cc406Sopenharmony_ci regs10 = 0x20; 430141cc406Sopenharmony_ci regs11 = 0x28; 431141cc406Sopenharmony_ci } 432141cc406Sopenharmony_ci else 433141cc406Sopenharmony_ci { 434141cc406Sopenharmony_ci regs10 = 0x10; 435141cc406Sopenharmony_ci regs11 = 0x2a; 436141cc406Sopenharmony_ci } 437141cc406Sopenharmony_ci 438141cc406Sopenharmony_ci regs[0x32] = 0x80; 439141cc406Sopenharmony_ci regs[0x33] = 0x81; 440141cc406Sopenharmony_ci regs[0x35] = 0x10; 441141cc406Sopenharmony_ci regs[0x36] = 0x24; 442141cc406Sopenharmony_ci regs[0x39] = 0x02; 443141cc406Sopenharmony_ci regs[0x3a] = 0x0e; 444141cc406Sopenharmony_ci 445141cc406Sopenharmony_ci regs[0x64] = 0x01; 446141cc406Sopenharmony_ci regs[0x65] = 0x20; 447141cc406Sopenharmony_ci 448141cc406Sopenharmony_ci regs[0x79] = 0x20; 449141cc406Sopenharmony_ci regs[0x7a] = 0x01; 450141cc406Sopenharmony_ci 451141cc406Sopenharmony_ci regs[0x80] = 0x32; 452141cc406Sopenharmony_ci regs[0x82] = 0x33; 453141cc406Sopenharmony_ci regs[0x85] = 0x46; 454141cc406Sopenharmony_ci regs[0x86] = 0x0b; 455141cc406Sopenharmony_ci regs[0x87] = 0x8c; 456141cc406Sopenharmony_ci regs[0x88] = 0x10; 457141cc406Sopenharmony_ci regs[0x89] = 0xb2; 458141cc406Sopenharmony_ci regs[0x8d] = 0x3b; 459141cc406Sopenharmony_ci regs[0x8e] = 0x60; 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci regs[0x90] = 0x1c; 462141cc406Sopenharmony_ci regs[0xb2] = 0x16; /* 0x10 : stop when at home, 0x04: no data */ 463141cc406Sopenharmony_ci regs[0xc0] = 0x00; 464141cc406Sopenharmony_ci regs[0xc1] = 0x00; 465141cc406Sopenharmony_ci regs[0xc3] = 0x00; 466141cc406Sopenharmony_ci regs[0xc4] = 0x00; 467141cc406Sopenharmony_ci regs[0xc5] = 0x00; 468141cc406Sopenharmony_ci regs[0xc6] = 0x00; 469141cc406Sopenharmony_ci regs[0xc7] = 0x00; 470141cc406Sopenharmony_ci regs[0xc8] = 0x00; 471141cc406Sopenharmony_ci regs[0xca] = 0x00; 472141cc406Sopenharmony_ci regs[0xcd] = 0x00; 473141cc406Sopenharmony_ci regs[0xce] = 0x00; 474141cc406Sopenharmony_ci regs[0xcf] = 0x00; 475141cc406Sopenharmony_ci regs[0xd0] = 0x00; 476141cc406Sopenharmony_ci regs[0xd1] = 0x00; 477141cc406Sopenharmony_ci regs[0xd2] = 0x00; 478141cc406Sopenharmony_ci regs[0xd3] = 0x00; 479141cc406Sopenharmony_ci regs[0xd4] = 0x00; 480141cc406Sopenharmony_ci regs[0xd6] = 0x6b; 481141cc406Sopenharmony_ci regs[0xd7] = 0x00; 482141cc406Sopenharmony_ci regs[0xd8] = 0x00; 483141cc406Sopenharmony_ci regs[0xd9] = 0xad; 484141cc406Sopenharmony_ci regs[0xda] = 0xa7; 485141cc406Sopenharmony_ci regs[0xe2] = 0x17; 486141cc406Sopenharmony_ci regs[0xe3] = 0x0d; 487141cc406Sopenharmony_ci regs[0xe4] = 0x06; 488141cc406Sopenharmony_ci regs[0xe5] = 0xf9; 489141cc406Sopenharmony_ci regs[0xe7] = 0x53; 490141cc406Sopenharmony_ci regs[0xe8] = 0x02; 491141cc406Sopenharmony_ci regs[0xe9] = 0x02; 492141cc406Sopenharmony_ci 493141cc406Sopenharmony_ci /* hp4400 sensors */ 494141cc406Sopenharmony_ci if (device->sensor == SENSOR_TYPE_4400 495141cc406Sopenharmony_ci || device->sensor == SENSOR_TYPE_4400_BARE) 496141cc406Sopenharmony_ci { 497141cc406Sopenharmony_ci regs[0x13] = 0x39; /* 0x20 */ 498141cc406Sopenharmony_ci regs[0x14] = 0xf0; /* 0xf8 */ 499141cc406Sopenharmony_ci regs[0x15] = 0x29; /* 0x28 */ 500141cc406Sopenharmony_ci regs[0x16] = 0x0f; /* 0x07 */ 501141cc406Sopenharmony_ci regs[0x17] = 0x10; /* 0x00 */ 502141cc406Sopenharmony_ci regs[0x23] = 0x00; /* 0xff */ 503141cc406Sopenharmony_ci regs[0x35] = 0x29; /* 0x10 */ 504141cc406Sopenharmony_ci regs[0x36] = 0x21; /* 0x24 */ 505141cc406Sopenharmony_ci regs[0x39] = 0x00; /* 0x02 */ 506141cc406Sopenharmony_ci regs[0x80] = 0xb0; /* 0x32 */ 507141cc406Sopenharmony_ci regs[0x82] = 0xb1; /* 0x33 */ 508141cc406Sopenharmony_ci regs[0xe2] = 0x0b; /* 0x17 */ 509141cc406Sopenharmony_ci regs[0xe5] = 0xf3; /* 0xf9 */ 510141cc406Sopenharmony_ci regs[0xe6] = 0x01; /* 0x00 */ 511141cc406Sopenharmony_ci } 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci /* disable CCD */ 514141cc406Sopenharmony_ci regs[0] = 0xf5; 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci sanei_rts88xx_set_status (device->devnum, regs, regs10, regs11); 517141cc406Sopenharmony_ci sanei_rts88xx_set_scan_area (regs, distance, distance + 1, 100, 200); 518141cc406Sopenharmony_ci sanei_rts88xx_set_gain (regs, 16, 16, 16); 519141cc406Sopenharmony_ci sanei_rts88xx_set_offset (regs, 127, 127, 127); 520141cc406Sopenharmony_ci 521141cc406Sopenharmony_ci /* forward/backward */ 522141cc406Sopenharmony_ci /* 0x2c is forward, 0x24 backward */ 523141cc406Sopenharmony_ci if (forward == SANE_TRUE) 524141cc406Sopenharmony_ci { /* forward */ 525141cc406Sopenharmony_ci regs[0x36] = regs[0x36] | 0x08; 526141cc406Sopenharmony_ci } 527141cc406Sopenharmony_ci else 528141cc406Sopenharmony_ci { /* backward */ 529141cc406Sopenharmony_ci regs[0x36] = regs[0x36] & 0xf7; 530141cc406Sopenharmony_ci } 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci /* write registers values */ 533141cc406Sopenharmony_ci status = rts8891_write_all (device->devnum, regs, RTS8891_MAX_REGISTERS); 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci /* commit it */ 536141cc406Sopenharmony_ci rts8891_commit (device->devnum, 0x00); 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci return status; 539141cc406Sopenharmony_ci} 540141cc406Sopenharmony_ci 541141cc406Sopenharmony_ci /** 542141cc406Sopenharmony_ci * wait for the scanning head to reach home position 543141cc406Sopenharmony_ci */ 544141cc406Sopenharmony_cistatic SANE_Status 545141cc406Sopenharmony_cirts8891_wait_for_home (struct Rts8891_Device *device, SANE_Byte * regs) 546141cc406Sopenharmony_ci{ 547141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 548141cc406Sopenharmony_ci SANE_Byte motor, sensor, reg; 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci DBG (DBG_proc, "rts8891_wait_for_home: start\n"); 551141cc406Sopenharmony_ci 552141cc406Sopenharmony_ci /* wait for controller home bit to raise, no timeout */ 553141cc406Sopenharmony_ci /* at each loop we check that motor is on, then that the sensor bit it cleared */ 554141cc406Sopenharmony_ci do 555141cc406Sopenharmony_ci { 556141cc406Sopenharmony_ci sanei_rts88xx_read_reg (device->devnum, CONTROL_REG, &motor); 557141cc406Sopenharmony_ci sanei_rts88xx_read_reg (device->devnum, CONTROLER_REG, &sensor); 558141cc406Sopenharmony_ci } 559141cc406Sopenharmony_ci while ((motor & 0x08) && ((sensor & 0x02) == 0)); 560141cc406Sopenharmony_ci 561141cc406Sopenharmony_ci /* flag that device has finished parking */ 562141cc406Sopenharmony_ci device->parking=SANE_FALSE; 563141cc406Sopenharmony_ci 564141cc406Sopenharmony_ci /* check for error */ 565141cc406Sopenharmony_ci if (((motor & 0x08) == 0x00) && ((sensor & 0x02) == 0)) 566141cc406Sopenharmony_ci { 567141cc406Sopenharmony_ci DBG (DBG_error, 568141cc406Sopenharmony_ci "rts8891_wait_for_home: error, motor stopped before head parked\n"); 569141cc406Sopenharmony_ci status = SANE_STATUS_INVAL; 570141cc406Sopenharmony_ci } 571141cc406Sopenharmony_ci 572141cc406Sopenharmony_ci /* re-enable CCD */ 573141cc406Sopenharmony_ci regs[0] = regs[0] & 0xef; 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ci sanei_rts88xx_cancel (device->devnum); 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci /* reset ? so we don't need to read data */ 578141cc406Sopenharmony_ci reg = 0; 579141cc406Sopenharmony_ci /* b7: movement on/off, b3-b0 : movement divisor */ 580141cc406Sopenharmony_ci sanei_rts88xx_write_reg (device->devnum, 0x33, ®); 581141cc406Sopenharmony_ci sanei_rts88xx_write_reg (device->devnum, 0x33, ®); 582141cc406Sopenharmony_ci /* movement direction */ 583141cc406Sopenharmony_ci sanei_rts88xx_write_reg (device->devnum, 0x36, ®); 584141cc406Sopenharmony_ci sanei_rts88xx_cancel (device->devnum); 585141cc406Sopenharmony_ci 586141cc406Sopenharmony_ci DBG (DBG_proc, "rts8891_wait_for_home: end\n"); 587141cc406Sopenharmony_ci return status; 588141cc406Sopenharmony_ci} 589141cc406Sopenharmony_ci 590141cc406Sopenharmony_ci /** 591141cc406Sopenharmony_ci * move the head backward by a huge line number then poll home sensor until 592141cc406Sopenharmony_ci * head has get back home. We have our own copy of the registers to avoid 593141cc406Sopenharmony_ci * messing scanner status 594141cc406Sopenharmony_ci */ 595141cc406Sopenharmony_cistatic SANE_Status 596141cc406Sopenharmony_cirts8891_park (struct Rts8891_Device *device, SANE_Byte *regs, SANE_Bool wait) 597141cc406Sopenharmony_ci{ 598141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci DBG (DBG_proc, "rts8891_park: start\n"); 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci device->parking=SANE_TRUE; 603141cc406Sopenharmony_ci rts8891_move (device, regs, 8000, SANE_FALSE); 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci if(wait==SANE_TRUE) 606141cc406Sopenharmony_ci { 607141cc406Sopenharmony_ci status = rts8891_wait_for_home (device,regs); 608141cc406Sopenharmony_ci } 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_ci DBG (DBG_proc, "rts8891_park: end\n"); 611141cc406Sopenharmony_ci return status; 612141cc406Sopenharmony_ci} 613141cc406Sopenharmony_ci 614141cc406Sopenharmony_ci/* reads data from scanner. 615141cc406Sopenharmony_ci * First we wait for some data to be available and then loop reading 616141cc406Sopenharmony_ci * from scanner until the required amount is reached. 617141cc406Sopenharmony_ci * We handle non blocking I/O by returning immediately (with SANE_STATUS_BUSY) 618141cc406Sopenharmony_ci * if there is no data available from scanner. But once read is started, 619141cc406Sopenharmony_ci * all the required amount is read. Once wait for data succeeded, we still poll 620141cc406Sopenharmony_ci * for data in order no to read it too fast, but we don' take care of non blocking 621141cc406Sopenharmony_ci * mode since we cope with it on first data wait. 622141cc406Sopenharmony_ci */ 623141cc406Sopenharmony_cistatic SANE_Status 624141cc406Sopenharmony_ciread_data (struct Rts8891_Session *session, SANE_Byte * dest, SANE_Int length) 625141cc406Sopenharmony_ci{ 626141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 627141cc406Sopenharmony_ci SANE_Int count, read, len, dummy; 628141cc406Sopenharmony_ci struct Rts8891_Device *dev = session->dev; 629141cc406Sopenharmony_ci static FILE *raw = NULL; /* for debugging purpose we need it static */ 630141cc406Sopenharmony_ci SANE_Byte control = 0x08; 631141cc406Sopenharmony_ci unsigned char buffer[RTS88XX_MAX_XFER_SIZE]; 632141cc406Sopenharmony_ci 633141cc406Sopenharmony_ci DBG (DBG_proc, "read_data: start\n"); 634141cc406Sopenharmony_ci DBG (DBG_proc, "read_data: requiring %d bytes\n", length); 635141cc406Sopenharmony_ci 636141cc406Sopenharmony_ci /* wait for data being available and handle non blocking mode */ 637141cc406Sopenharmony_ci /* only when data reading hasn't produce any data yet */ 638141cc406Sopenharmony_ci if (dev->read == 0) 639141cc406Sopenharmony_ci { 640141cc406Sopenharmony_ci do 641141cc406Sopenharmony_ci { 642141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (dev->devnum, &count); 643141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 644141cc406Sopenharmony_ci { 645141cc406Sopenharmony_ci DBG (DBG_error, "read_data: failed to wait for data\n"); 646141cc406Sopenharmony_ci return status; 647141cc406Sopenharmony_ci } 648141cc406Sopenharmony_ci if (count == 0) 649141cc406Sopenharmony_ci { 650141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 651141cc406Sopenharmony_ci if ((control & 0x08) == 0 && (count == 0)) 652141cc406Sopenharmony_ci { 653141cc406Sopenharmony_ci DBG (DBG_error, 654141cc406Sopenharmony_ci "read_data: scanner stopped being busy before data are available\n"); 655141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 656141cc406Sopenharmony_ci } 657141cc406Sopenharmony_ci } 658141cc406Sopenharmony_ci 659141cc406Sopenharmony_ci /* in case there is no data, we return BUSY since this mean */ 660141cc406Sopenharmony_ci /* that scanning head hasn't reach is position and data hasn't */ 661141cc406Sopenharmony_ci /* come yet */ 662141cc406Sopenharmony_ci if (session->non_blocking && count == 0) 663141cc406Sopenharmony_ci { 664141cc406Sopenharmony_ci 665141cc406Sopenharmony_ci dev->regs[LAMP_REG] = 0x8d; 666141cc406Sopenharmony_ci sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, 667141cc406Sopenharmony_ci &(dev->regs[LAMP_REG])); 668141cc406Sopenharmony_ci DBG (DBG_io, "read_data: no data available\n"); 669141cc406Sopenharmony_ci DBG (DBG_proc, "read_data: end\n"); 670141cc406Sopenharmony_ci return SANE_STATUS_DEVICE_BUSY; 671141cc406Sopenharmony_ci } 672141cc406Sopenharmony_ci } 673141cc406Sopenharmony_ci while (count == 0); 674141cc406Sopenharmony_ci } 675141cc406Sopenharmony_ci else 676141cc406Sopenharmony_ci { /* start of read for a new block */ 677141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (dev->devnum, &count); 678141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 679141cc406Sopenharmony_ci { 680141cc406Sopenharmony_ci DBG (DBG_error, "read_data: failed to wait for data\n"); 681141cc406Sopenharmony_ci return status; 682141cc406Sopenharmony_ci } 683141cc406Sopenharmony_ci if (count == 0) 684141cc406Sopenharmony_ci { 685141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 686141cc406Sopenharmony_ci if ((control & 0x08) == 0 && (count == 0)) 687141cc406Sopenharmony_ci { 688141cc406Sopenharmony_ci DBG (DBG_error, 689141cc406Sopenharmony_ci "read_data: scanner stopped being busy before data are available\n"); 690141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 691141cc406Sopenharmony_ci } 692141cc406Sopenharmony_ci } 693141cc406Sopenharmony_ci } 694141cc406Sopenharmony_ci 695141cc406Sopenharmony_ci /* fill scanned data buffer */ 696141cc406Sopenharmony_ci read = 0; 697141cc406Sopenharmony_ci 698141cc406Sopenharmony_ci /* now loop reading data until we have the amount requested */ 699141cc406Sopenharmony_ci /* we also take care of not reading too much data */ 700141cc406Sopenharmony_ci while (read < length && dev->read < dev->to_read 701141cc406Sopenharmony_ci && ((control & 0x08) == 0x08)) 702141cc406Sopenharmony_ci { 703141cc406Sopenharmony_ci /* used to sync */ 704141cc406Sopenharmony_ci if (dev->read == 0) 705141cc406Sopenharmony_ci { 706141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (dev->devnum, &dummy); 707141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 708141cc406Sopenharmony_ci { 709141cc406Sopenharmony_ci DBG (DBG_error, "read_data: failed to read data count\n"); 710141cc406Sopenharmony_ci return status; 711141cc406Sopenharmony_ci } 712141cc406Sopenharmony_ci } 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci /* if there is data to read, read it */ 715141cc406Sopenharmony_ci if (count > 0) 716141cc406Sopenharmony_ci { 717141cc406Sopenharmony_ci len = count; 718141cc406Sopenharmony_ci 719141cc406Sopenharmony_ci if (len > RTS88XX_MAX_XFER_SIZE) 720141cc406Sopenharmony_ci { 721141cc406Sopenharmony_ci len = RTS88XX_MAX_XFER_SIZE; 722141cc406Sopenharmony_ci } 723141cc406Sopenharmony_ci 724141cc406Sopenharmony_ci /* we only read even size blocks of data */ 725141cc406Sopenharmony_ci if (len & 1) 726141cc406Sopenharmony_ci { 727141cc406Sopenharmony_ci DBG (DBG_io, "read_data: round to next even number\n"); 728141cc406Sopenharmony_ci len++; 729141cc406Sopenharmony_ci } 730141cc406Sopenharmony_ci 731141cc406Sopenharmony_ci if (len > length - read) 732141cc406Sopenharmony_ci { 733141cc406Sopenharmony_ci len = length - read; 734141cc406Sopenharmony_ci } 735141cc406Sopenharmony_ci 736141cc406Sopenharmony_ci status = sanei_rts88xx_read_data (dev->devnum, &len, dest + read); 737141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 738141cc406Sopenharmony_ci { 739141cc406Sopenharmony_ci DBG (DBG_error, "read_data: failed to read from scanner\n"); 740141cc406Sopenharmony_ci return status; 741141cc406Sopenharmony_ci } 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci /* raw data tracing */ 744141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 745141cc406Sopenharmony_ci { 746141cc406Sopenharmony_ci /* open a new file only when no data scanned */ 747141cc406Sopenharmony_ci if (dev->read == 0) 748141cc406Sopenharmony_ci { 749141cc406Sopenharmony_ci raw = fopen ("raw_data.pnm", "wb"); 750141cc406Sopenharmony_ci if (raw != NULL) 751141cc406Sopenharmony_ci { 752141cc406Sopenharmony_ci /* PNM header */ 753141cc406Sopenharmony_ci fprintf (raw, "P%c\n%d %d\n255\n", 754141cc406Sopenharmony_ci session->params.format == 755141cc406Sopenharmony_ci SANE_FRAME_RGB 756141cc406Sopenharmony_ci || session->emulated_gray == 757141cc406Sopenharmony_ci SANE_TRUE ? '6' : '5', dev->pixels, 758141cc406Sopenharmony_ci dev->lines); 759141cc406Sopenharmony_ci } 760141cc406Sopenharmony_ci } 761141cc406Sopenharmony_ci if (raw != NULL) 762141cc406Sopenharmony_ci { 763141cc406Sopenharmony_ci fwrite (dest + read, 1, len, raw); 764141cc406Sopenharmony_ci } 765141cc406Sopenharmony_ci } 766141cc406Sopenharmony_ci 767141cc406Sopenharmony_ci /* move pointer and counter */ 768141cc406Sopenharmony_ci read += len; 769141cc406Sopenharmony_ci dev->read += len; 770141cc406Sopenharmony_ci DBG (DBG_io2, "read_data: %d/%d\n", dev->read, dev->to_read); 771141cc406Sopenharmony_ci } 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci /* in fast scan mode, read data count 774141cc406Sopenharmony_ci * in slow scan, head moves by the amount of data read */ 775141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (dev->devnum, &count); 776141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 777141cc406Sopenharmony_ci { 778141cc406Sopenharmony_ci DBG (DBG_error, "read_data: failed to read data count\n"); 779141cc406Sopenharmony_ci return status; 780141cc406Sopenharmony_ci } 781141cc406Sopenharmony_ci 782141cc406Sopenharmony_ci /* if no data, check if still scanning */ 783141cc406Sopenharmony_ci if (count == 0 && dev->read < dev->to_read) 784141cc406Sopenharmony_ci { 785141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 786141cc406Sopenharmony_ci if ((control & 0x08) == 0x00) 787141cc406Sopenharmony_ci { 788141cc406Sopenharmony_ci DBG (DBG_error, 789141cc406Sopenharmony_ci "read_data: scanner stopped being busy before data are available\n"); 790141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 791141cc406Sopenharmony_ci } 792141cc406Sopenharmony_ci } 793141cc406Sopenharmony_ci } 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci /* end of physical reads */ 796141cc406Sopenharmony_ci if (dev->read >= dev->to_read) 797141cc406Sopenharmony_ci { 798141cc406Sopenharmony_ci /* check there is no more data in case of a bug */ 799141cc406Sopenharmony_ci sanei_rts88xx_data_count (dev->devnum, &count); 800141cc406Sopenharmony_ci if (count > 0) 801141cc406Sopenharmony_ci { 802141cc406Sopenharmony_ci DBG (DBG_warn, 803141cc406Sopenharmony_ci "read_data: %d bytes are still available from scanner\n", 804141cc406Sopenharmony_ci count); 805141cc406Sopenharmony_ci 806141cc406Sopenharmony_ci /* flush left-over data */ 807141cc406Sopenharmony_ci while (count > 0) 808141cc406Sopenharmony_ci { 809141cc406Sopenharmony_ci len = count; 810141cc406Sopenharmony_ci if (len > RTS88XX_MAX_XFER_SIZE) 811141cc406Sopenharmony_ci { 812141cc406Sopenharmony_ci len = RTS88XX_MAX_XFER_SIZE; 813141cc406Sopenharmony_ci } 814141cc406Sopenharmony_ci 815141cc406Sopenharmony_ci /* we only read even size blocks of data */ 816141cc406Sopenharmony_ci if (len & 1) 817141cc406Sopenharmony_ci { 818141cc406Sopenharmony_ci len++; 819141cc406Sopenharmony_ci } 820141cc406Sopenharmony_ci sanei_rts88xx_read_data (dev->devnum, &len, buffer); 821141cc406Sopenharmony_ci sanei_rts88xx_data_count (dev->devnum, &count); 822141cc406Sopenharmony_ci } 823141cc406Sopenharmony_ci } 824141cc406Sopenharmony_ci 825141cc406Sopenharmony_ci /* wait for motor to stop at the end of the scan */ 826141cc406Sopenharmony_ci do 827141cc406Sopenharmony_ci { 828141cc406Sopenharmony_ci sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); 829141cc406Sopenharmony_ci } 830141cc406Sopenharmony_ci while ((control & 0x08) != 0); 831141cc406Sopenharmony_ci 832141cc406Sopenharmony_ci /* close log file if needed */ 833141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io2) 834141cc406Sopenharmony_ci { 835141cc406Sopenharmony_ci if (raw != NULL) 836141cc406Sopenharmony_ci { 837141cc406Sopenharmony_ci fclose (raw); 838141cc406Sopenharmony_ci raw = NULL; 839141cc406Sopenharmony_ci } 840141cc406Sopenharmony_ci } 841141cc406Sopenharmony_ci } 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci DBG (DBG_io, "read_data: read %d bytes from scanner\n", length); 844141cc406Sopenharmony_ci DBG (DBG_proc, "read_data: end\n"); 845141cc406Sopenharmony_ci return status; 846141cc406Sopenharmony_ci} 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci /** 849141cc406Sopenharmony_ci * set scanner idle before leaving xxx_quiet() 850141cc406Sopenharmony_ciwrite_reg(0x33,1)=0x00 851141cc406Sopenharmony_ciwrite_reg(0x33,1)=0x00 852141cc406Sopenharmony_ciwrite_reg(0x36,1)=0x00 853141cc406Sopenharmony_ciprepare(); 854141cc406Sopenharmony_ci------ 855141cc406Sopenharmony_ciwrite_reg(LAMP_REG,1)=0x80 856141cc406Sopenharmony_ciwrite_reg(LAMP_REG,1)=0xad 857141cc406Sopenharmony_ciread_reg(0x14,2)=0xf8 0x28 858141cc406Sopenharmony_ciwrite_reg(0x14,2)=0x78 0x28 859141cc406Sopenharmony_ciget_status()=0x20 0x3f 860141cc406Sopenharmony_ciread_reg(0xb1,1)=0x00 861141cc406Sopenharmony_ciread_control()=0x00 862141cc406Sopenharmony_cireset_lamp()=(0x20,0x3f) 863141cc406Sopenharmony_ciwrite_reg(LAMP_REG,1)=0x8d 864141cc406Sopenharmony_ciwrite_reg(LAMP_REG,1)=0xad 865141cc406Sopenharmony_ci */ 866141cc406Sopenharmony_ci 867141cc406Sopenharmony_ci/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ 868