1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2007-2012 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 functions common to rts88xx ASICs */ 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci#undef BACKEND_NAME 45141cc406Sopenharmony_ci#define BACKEND_NAME rts88xx_lib 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#include "rts88xx_lib.h" 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci#include <stdio.h> 54141cc406Sopenharmony_ci#include <sys/time.h> 55141cc406Sopenharmony_ci#include <sys/types.h> 56141cc406Sopenharmony_ci 57141cc406Sopenharmony_ci#include "../include/_stdint.h" 58141cc406Sopenharmony_ci 59141cc406Sopenharmony_ci#define RTS88XX_LIB_BUILD 30 60141cc406Sopenharmony_ci 61141cc406Sopenharmony_ci/* init rts88xx library */ 62141cc406Sopenharmony_civoid 63141cc406Sopenharmony_cisanei_rts88xx_lib_init (void) 64141cc406Sopenharmony_ci{ 65141cc406Sopenharmony_ci DBG_INIT (); 66141cc406Sopenharmony_ci DBG (DBG_info, "RTS88XX library, version %d.%d-%d\n", SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 67141cc406Sopenharmony_ci RTS88XX_LIB_BUILD); 68141cc406Sopenharmony_ci} 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_ci/* 71141cc406Sopenharmony_ci * registers helpers to avoid direct access 72141cc406Sopenharmony_ci */ 73141cc406Sopenharmony_ciSANE_Bool 74141cc406Sopenharmony_cisanei_rts88xx_is_color (SANE_Byte * regs) 75141cc406Sopenharmony_ci{ 76141cc406Sopenharmony_ci if ((regs[0x2f] & 0x11) == 0x11) 77141cc406Sopenharmony_ci return SANE_TRUE; 78141cc406Sopenharmony_ci return SANE_FALSE; 79141cc406Sopenharmony_ci} 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_civoid 82141cc406Sopenharmony_cisanei_rts88xx_set_gray_scan (SANE_Byte * regs) 83141cc406Sopenharmony_ci{ 84141cc406Sopenharmony_ci regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20; 85141cc406Sopenharmony_ci} 86141cc406Sopenharmony_ci 87141cc406Sopenharmony_civoid 88141cc406Sopenharmony_cisanei_rts88xx_set_color_scan (SANE_Byte * regs) 89141cc406Sopenharmony_ci{ 90141cc406Sopenharmony_ci regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10; 91141cc406Sopenharmony_ci} 92141cc406Sopenharmony_ci 93141cc406Sopenharmony_civoid 94141cc406Sopenharmony_cisanei_rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, 95141cc406Sopenharmony_ci SANE_Byte blue) 96141cc406Sopenharmony_ci{ 97141cc406Sopenharmony_ci /* offset for odd pixels */ 98141cc406Sopenharmony_ci regs[0x02] = red; 99141cc406Sopenharmony_ci regs[0x03] = green; 100141cc406Sopenharmony_ci regs[0x04] = blue; 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_ci /* offset for even pixels */ 103141cc406Sopenharmony_ci regs[0x05] = red; 104141cc406Sopenharmony_ci regs[0x06] = green; 105141cc406Sopenharmony_ci regs[0x07] = blue; 106141cc406Sopenharmony_ci} 107141cc406Sopenharmony_ci 108141cc406Sopenharmony_civoid 109141cc406Sopenharmony_cisanei_rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, 110141cc406Sopenharmony_ci SANE_Byte blue) 111141cc406Sopenharmony_ci{ 112141cc406Sopenharmony_ci regs[0x08] = red; 113141cc406Sopenharmony_ci regs[0x09] = green; 114141cc406Sopenharmony_ci regs[0x0a] = blue; 115141cc406Sopenharmony_ci} 116141cc406Sopenharmony_ci 117141cc406Sopenharmony_civoid 118141cc406Sopenharmony_cisanei_rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency) 119141cc406Sopenharmony_ci{ 120141cc406Sopenharmony_ci regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f); 121141cc406Sopenharmony_ci} 122141cc406Sopenharmony_ci 123141cc406Sopenharmony_ci/* 124141cc406Sopenharmony_ci * read one register at given index 125141cc406Sopenharmony_ci */ 126141cc406Sopenharmony_ciSANE_Status 127141cc406Sopenharmony_cisanei_rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) 128141cc406Sopenharmony_ci{ 129141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 130141cc406Sopenharmony_ci unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 }; 131141cc406Sopenharmony_ci size_t size; 132141cc406Sopenharmony_ci 133141cc406Sopenharmony_ci cmd[1] = index; 134141cc406Sopenharmony_ci 135141cc406Sopenharmony_ci size = 4; 136141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, cmd, &size); 137141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 138141cc406Sopenharmony_ci { 139141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_reg: bulk write failed\n"); 140141cc406Sopenharmony_ci return status; 141141cc406Sopenharmony_ci } 142141cc406Sopenharmony_ci size = 1; 143141cc406Sopenharmony_ci status = sanei_usb_read_bulk (devnum, reg, &size); 144141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 145141cc406Sopenharmony_ci { 146141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_reg: bulk read failed\n"); 147141cc406Sopenharmony_ci return status; 148141cc406Sopenharmony_ci } 149141cc406Sopenharmony_ci DBG (DBG_io2, "sanei_rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg); 150141cc406Sopenharmony_ci return status; 151141cc406Sopenharmony_ci} 152141cc406Sopenharmony_ci 153141cc406Sopenharmony_ci/* 154141cc406Sopenharmony_ci * write one register at given index 155141cc406Sopenharmony_ci */ 156141cc406Sopenharmony_ciSANE_Status 157141cc406Sopenharmony_cisanei_rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) 158141cc406Sopenharmony_ci{ 159141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 160141cc406Sopenharmony_ci unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01, 0xff }; 161141cc406Sopenharmony_ci size_t size; 162141cc406Sopenharmony_ci 163141cc406Sopenharmony_ci cmd[1] = index; 164141cc406Sopenharmony_ci cmd[4] = *reg; 165141cc406Sopenharmony_ci 166141cc406Sopenharmony_ci size = 5; 167141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, cmd, &size); 168141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 169141cc406Sopenharmony_ci { 170141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_write_reg: bulk write failed\n"); 171141cc406Sopenharmony_ci return status; 172141cc406Sopenharmony_ci } 173141cc406Sopenharmony_ci DBG (DBG_io2, "sanei_rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg); 174141cc406Sopenharmony_ci return status; 175141cc406Sopenharmony_ci} 176141cc406Sopenharmony_ci 177141cc406Sopenharmony_ci/* 178141cc406Sopenharmony_ci * write length consecutive registers, starting at index 179141cc406Sopenharmony_ci * register 0xb3 is never wrote in bulk register write, so we split 180141cc406Sopenharmony_ci * write if it belongs to the register set sent 181141cc406Sopenharmony_ci */ 182141cc406Sopenharmony_ciSANE_Status 183141cc406Sopenharmony_cisanei_rts88xx_write_regs (SANE_Int devnum, SANE_Int start, 184141cc406Sopenharmony_ci SANE_Byte * source, SANE_Int length) 185141cc406Sopenharmony_ci{ 186141cc406Sopenharmony_ci size_t size = 0; 187141cc406Sopenharmony_ci size_t i; 188141cc406Sopenharmony_ci SANE_Byte buffer[260]; 189141cc406Sopenharmony_ci char message[256 * 5]; 190141cc406Sopenharmony_ci 191141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io) 192141cc406Sopenharmony_ci { 193141cc406Sopenharmony_ci for (i = 0; i < (size_t) length; i++) 194141cc406Sopenharmony_ci { 195141cc406Sopenharmony_ci sprintf (message + 5 * i, "0x%02x ", source[i]); 196141cc406Sopenharmony_ci } 197141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_write_regs : write_regs(0x%02x,%d)=%s\n", 198141cc406Sopenharmony_ci start, length, message); 199141cc406Sopenharmony_ci } 200141cc406Sopenharmony_ci 201141cc406Sopenharmony_ci /* when writing several registers at a time, we avoid writing the 0xb3 register 202141cc406Sopenharmony_ci * which is used to control the status of the scanner */ 203141cc406Sopenharmony_ci if ((start + length > 0xb3) && (length > 1)) 204141cc406Sopenharmony_ci { 205141cc406Sopenharmony_ci size = 0xb3 - start; 206141cc406Sopenharmony_ci buffer[0] = 0x88; 207141cc406Sopenharmony_ci buffer[1] = start; 208141cc406Sopenharmony_ci buffer[2] = 0x00; 209141cc406Sopenharmony_ci buffer[3] = size; 210141cc406Sopenharmony_ci for (i = 0; i < size; i++) 211141cc406Sopenharmony_ci buffer[i + 4] = source[i]; 212141cc406Sopenharmony_ci /* the USB block is size + 4 bytes of header long */ 213141cc406Sopenharmony_ci size += 4; 214141cc406Sopenharmony_ci if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) 215141cc406Sopenharmony_ci { 216141cc406Sopenharmony_ci DBG (DBG_error, 217141cc406Sopenharmony_ci "sanei_rts88xx_write_regs : write registers part 1 failed ...\n"); 218141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 219141cc406Sopenharmony_ci } 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_ci /* skip 0xb3 register */ 222141cc406Sopenharmony_ci size -= 3; 223141cc406Sopenharmony_ci start = 0xb4; 224141cc406Sopenharmony_ci source = source + size; 225141cc406Sopenharmony_ci } 226141cc406Sopenharmony_ci size = length - size; 227141cc406Sopenharmony_ci buffer[0] = 0x88; 228141cc406Sopenharmony_ci buffer[1] = start; 229141cc406Sopenharmony_ci buffer[2] = 0x00; 230141cc406Sopenharmony_ci buffer[3] = size; 231141cc406Sopenharmony_ci for (i = 0; i < size; i++) 232141cc406Sopenharmony_ci buffer[i + 4] = source[i]; 233141cc406Sopenharmony_ci /* the USB block is size + 4 bytes of header long */ 234141cc406Sopenharmony_ci size += 4; 235141cc406Sopenharmony_ci if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) 236141cc406Sopenharmony_ci { 237141cc406Sopenharmony_ci DBG (DBG_error, 238141cc406Sopenharmony_ci "sanei_rts88xx_write_regs : write registers part 2 failed ...\n"); 239141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 240141cc406Sopenharmony_ci } 241141cc406Sopenharmony_ci 242141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 243141cc406Sopenharmony_ci 244141cc406Sopenharmony_ci} 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_ci/* read several registers starting at the given index */ 247141cc406Sopenharmony_ciSANE_Status 248141cc406Sopenharmony_cisanei_rts88xx_read_regs (SANE_Int devnum, SANE_Int start, 249141cc406Sopenharmony_ci SANE_Byte * dest, SANE_Int length) 250141cc406Sopenharmony_ci{ 251141cc406Sopenharmony_ci SANE_Status status; 252141cc406Sopenharmony_ci static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF }; 253141cc406Sopenharmony_ci size_t size, i; 254141cc406Sopenharmony_ci char message[256 * 5]; 255141cc406Sopenharmony_ci 256141cc406Sopenharmony_ci if (start + length > 255) 257141cc406Sopenharmony_ci { 258141cc406Sopenharmony_ci DBG (DBG_error, 259141cc406Sopenharmony_ci "sanei_rts88xx_read_regs: start and length must be within [0..255]\n"); 260141cc406Sopenharmony_ci return SANE_STATUS_INVAL; 261141cc406Sopenharmony_ci } 262141cc406Sopenharmony_ci 263141cc406Sopenharmony_ci /* write header */ 264141cc406Sopenharmony_ci size = 4; 265141cc406Sopenharmony_ci command_block[1] = start; 266141cc406Sopenharmony_ci command_block[3] = length; 267141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, command_block, &size); 268141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 269141cc406Sopenharmony_ci { 270141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_regs: failed to write header\n"); 271141cc406Sopenharmony_ci return status; 272141cc406Sopenharmony_ci } 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci /* read data */ 275141cc406Sopenharmony_ci size = length; 276141cc406Sopenharmony_ci status = sanei_usb_read_bulk (devnum, dest, &size); 277141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 278141cc406Sopenharmony_ci { 279141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_regs: failed to read data\n"); 280141cc406Sopenharmony_ci return status; 281141cc406Sopenharmony_ci } 282141cc406Sopenharmony_ci if (size != (size_t) length) 283141cc406Sopenharmony_ci { 284141cc406Sopenharmony_ci DBG (DBG_warn, "sanei_rts88xx_read_regs: read got only %lu bytes\n", 285141cc406Sopenharmony_ci (u_long) size); 286141cc406Sopenharmony_ci } 287141cc406Sopenharmony_ci if (DBG_LEVEL >= DBG_io) 288141cc406Sopenharmony_ci { 289141cc406Sopenharmony_ci for (i = 0; i < size; i++) 290141cc406Sopenharmony_ci sprintf (message + 5 * i, "0x%02x ", dest[i]); 291141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_read_regs: read_regs(0x%02x,%d)=%s\n", 292141cc406Sopenharmony_ci start, length, message); 293141cc406Sopenharmony_ci } 294141cc406Sopenharmony_ci return status; 295141cc406Sopenharmony_ci} 296141cc406Sopenharmony_ci 297141cc406Sopenharmony_ci/* 298141cc406Sopenharmony_ci * get status by reading registers 0x10 and 0x11 299141cc406Sopenharmony_ci */ 300141cc406Sopenharmony_ciSANE_Status 301141cc406Sopenharmony_cisanei_rts88xx_get_status (SANE_Int devnum, SANE_Byte * regs) 302141cc406Sopenharmony_ci{ 303141cc406Sopenharmony_ci SANE_Status status; 304141cc406Sopenharmony_ci status = sanei_rts88xx_read_regs (devnum, 0x10, regs + 0x10, 2); 305141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_get_status: get_status()=0x%02x 0x%02x\n", 306141cc406Sopenharmony_ci regs[0x10], regs[0x11]); 307141cc406Sopenharmony_ci return status; 308141cc406Sopenharmony_ci} 309141cc406Sopenharmony_ci 310141cc406Sopenharmony_ci/* 311141cc406Sopenharmony_ci * set status by writing registers 0x10 and 0x11 312141cc406Sopenharmony_ci */ 313141cc406Sopenharmony_ciSANE_Status 314141cc406Sopenharmony_cisanei_rts88xx_set_status (SANE_Int devnum, SANE_Byte * regs, 315141cc406Sopenharmony_ci SANE_Byte reg10, SANE_Byte reg11) 316141cc406Sopenharmony_ci{ 317141cc406Sopenharmony_ci SANE_Status status; 318141cc406Sopenharmony_ci 319141cc406Sopenharmony_ci regs[0x10] = reg10; 320141cc406Sopenharmony_ci regs[0x11] = reg11; 321141cc406Sopenharmony_ci status = sanei_rts88xx_write_regs (devnum, 0x10, regs + 0x10, 2); 322141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_set_status: 0x%02x 0x%02x\n", regs[0x10], 323141cc406Sopenharmony_ci regs[0x11]); 324141cc406Sopenharmony_ci return status; 325141cc406Sopenharmony_ci} 326141cc406Sopenharmony_ci 327141cc406Sopenharmony_ci/* 328141cc406Sopenharmony_ci * get lamp status by reading registers 0x84 to 0x8f, only 0x8F is currently useful 329141cc406Sopenharmony_ci * 0x84 and following could "on" timers 330141cc406Sopenharmony_ci */ 331141cc406Sopenharmony_ciSANE_Status 332141cc406Sopenharmony_cisanei_rts88xx_get_lamp_status (SANE_Int devnum, SANE_Byte * regs) 333141cc406Sopenharmony_ci{ 334141cc406Sopenharmony_ci SANE_Status status; 335141cc406Sopenharmony_ci status = sanei_rts88xx_read_regs (devnum, 0x84, regs + 0x84, 11); 336141cc406Sopenharmony_ci return status; 337141cc406Sopenharmony_ci} 338141cc406Sopenharmony_ci 339141cc406Sopenharmony_ci/* resets lamp */ 340141cc406Sopenharmony_ciSANE_Status 341141cc406Sopenharmony_cisanei_rts88xx_reset_lamp (SANE_Int devnum, SANE_Byte * regs) 342141cc406Sopenharmony_ci{ 343141cc406Sopenharmony_ci SANE_Status status; 344141cc406Sopenharmony_ci SANE_Byte reg; 345141cc406Sopenharmony_ci 346141cc406Sopenharmony_ci /* read the 0xda register, then clear lower nibble and write it back */ 347141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (devnum, 0xda, ®); 348141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 349141cc406Sopenharmony_ci { 350141cc406Sopenharmony_ci DBG (DBG_error, 351141cc406Sopenharmony_ci "sanei_rts88xx_reset_lamp: failed to read 0xda register\n"); 352141cc406Sopenharmony_ci return status; 353141cc406Sopenharmony_ci } 354141cc406Sopenharmony_ci reg = 0xa0; 355141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (devnum, 0xda, ®); 356141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 357141cc406Sopenharmony_ci { 358141cc406Sopenharmony_ci DBG (DBG_error, 359141cc406Sopenharmony_ci "sanei_rts88xx_reset_lamp: failed to write 0xda register\n"); 360141cc406Sopenharmony_ci return status; 361141cc406Sopenharmony_ci } 362141cc406Sopenharmony_ci 363141cc406Sopenharmony_ci /* on cleared, get status */ 364141cc406Sopenharmony_ci status = sanei_rts88xx_get_status (devnum, regs); 365141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 366141cc406Sopenharmony_ci { 367141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to get status\n"); 368141cc406Sopenharmony_ci return status; 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_reset_lamp: status=0x%02x 0x%02x\n", regs[0x10], 371141cc406Sopenharmony_ci regs[0x11]); 372141cc406Sopenharmony_ci 373141cc406Sopenharmony_ci /* set low nibble to 7 and write it */ 374141cc406Sopenharmony_ci reg = reg | 0x07; 375141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (devnum, 0xda, ®); 376141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 377141cc406Sopenharmony_ci { 378141cc406Sopenharmony_ci DBG (DBG_error, 379141cc406Sopenharmony_ci "sanei_rts88xx_reset_lamp: failed to write 0xda register\n"); 380141cc406Sopenharmony_ci return status; 381141cc406Sopenharmony_ci } 382141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (devnum, 0xda, ®); 383141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 384141cc406Sopenharmony_ci { 385141cc406Sopenharmony_ci DBG (DBG_error, 386141cc406Sopenharmony_ci "sanei_rts88xx_reset_lamp: failed to read 0xda register\n"); 387141cc406Sopenharmony_ci return status; 388141cc406Sopenharmony_ci } 389141cc406Sopenharmony_ci if (reg != 0xa7) 390141cc406Sopenharmony_ci { 391141cc406Sopenharmony_ci DBG (DBG_warn, 392141cc406Sopenharmony_ci "sanei_rts88xx_reset_lamp: expected reg[0xda]=0xa7, got 0x%02x\n", 393141cc406Sopenharmony_ci reg); 394141cc406Sopenharmony_ci } 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci /* store read value in shadow register */ 397141cc406Sopenharmony_ci regs[0xda] = reg; 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci return status; 400141cc406Sopenharmony_ci} 401141cc406Sopenharmony_ci 402141cc406Sopenharmony_ci/* 403141cc406Sopenharmony_ci * get lcd status by reading registers 0x20, 0x21 and 0x22 404141cc406Sopenharmony_ci */ 405141cc406Sopenharmony_ciSANE_Status 406141cc406Sopenharmony_cisanei_rts88xx_get_lcd (SANE_Int devnum, SANE_Byte * regs) 407141cc406Sopenharmony_ci{ 408141cc406Sopenharmony_ci SANE_Status status; 409141cc406Sopenharmony_ci status = sanei_rts88xx_read_regs (devnum, 0x20, regs + 0x20, 3); 410141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_get_lcd: 0x%02x 0x%02x 0x%02x\n", regs[0x20], 411141cc406Sopenharmony_ci regs[0x21], regs[0x22]); 412141cc406Sopenharmony_ci return status; 413141cc406Sopenharmony_ci} 414141cc406Sopenharmony_ci 415141cc406Sopenharmony_ci/* 416141cc406Sopenharmony_ci * write to special control register CONTROL_REG=0xb3 417141cc406Sopenharmony_ci */ 418141cc406Sopenharmony_ciSANE_Status 419141cc406Sopenharmony_cisanei_rts88xx_write_control (SANE_Int devnum, SANE_Byte value) 420141cc406Sopenharmony_ci{ 421141cc406Sopenharmony_ci SANE_Status status; 422141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (devnum, CONTROL_REG, &value); 423141cc406Sopenharmony_ci return status; 424141cc406Sopenharmony_ci} 425141cc406Sopenharmony_ci 426141cc406Sopenharmony_ci/* 427141cc406Sopenharmony_ci * send the cancel control sequence 428141cc406Sopenharmony_ci */ 429141cc406Sopenharmony_ciSANE_Status 430141cc406Sopenharmony_cisanei_rts88xx_cancel (SANE_Int devnum) 431141cc406Sopenharmony_ci{ 432141cc406Sopenharmony_ci SANE_Status status; 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci status = sanei_rts88xx_write_control (devnum, 0x02); 435141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 436141cc406Sopenharmony_ci return status; 437141cc406Sopenharmony_ci status = sanei_rts88xx_write_control (devnum, 0x02); 438141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 439141cc406Sopenharmony_ci return status; 440141cc406Sopenharmony_ci status = sanei_rts88xx_write_control (devnum, 0x00); 441141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 442141cc406Sopenharmony_ci return status; 443141cc406Sopenharmony_ci status = sanei_rts88xx_write_control (devnum, 0x00); 444141cc406Sopenharmony_ci return status; 445141cc406Sopenharmony_ci} 446141cc406Sopenharmony_ci 447141cc406Sopenharmony_ci/* 448141cc406Sopenharmony_ci * write the given number of bytes pointed by value into memory 449141cc406Sopenharmony_ci * length is payload length 450141cc406Sopenharmony_ci * extra is number of bytes to add to the usb write length 451141cc406Sopenharmony_ci */ 452141cc406Sopenharmony_ciSANE_Status 453141cc406Sopenharmony_cisanei_rts88xx_write_mem (SANE_Int devnum, SANE_Int length, SANE_Int extra, 454141cc406Sopenharmony_ci SANE_Byte * value) 455141cc406Sopenharmony_ci{ 456141cc406Sopenharmony_ci SANE_Status status; 457141cc406Sopenharmony_ci SANE_Byte *buffer; 458141cc406Sopenharmony_ci size_t i, size; 459141cc406Sopenharmony_ci char message[(0xFFC0 + 10) * 3] = ""; 460141cc406Sopenharmony_ci 461141cc406Sopenharmony_ci buffer = (SANE_Byte *) malloc (length + 10); 462141cc406Sopenharmony_ci if (buffer == NULL) 463141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 464141cc406Sopenharmony_ci memset (buffer, 0, length + 10); 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci buffer[0] = 0x89; 467141cc406Sopenharmony_ci buffer[1] = 0x00; 468141cc406Sopenharmony_ci buffer[2] = HIBYTE (length); 469141cc406Sopenharmony_ci buffer[3] = LOBYTE (length); 470141cc406Sopenharmony_ci for (i = 0; i < (size_t) length; i++) 471141cc406Sopenharmony_ci { 472141cc406Sopenharmony_ci buffer[i + 4] = value[i]; 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io2) 475141cc406Sopenharmony_ci { 476141cc406Sopenharmony_ci sprintf (message + 3 * i, "%02x ", buffer[i + 4]); 477141cc406Sopenharmony_ci } 478141cc406Sopenharmony_ci } 479141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_write_mem: %02x %02x %02x %02x -> %s\n", 480141cc406Sopenharmony_ci buffer[0], buffer[1], buffer[2], buffer[3], message); 481141cc406Sopenharmony_ci 482141cc406Sopenharmony_ci size = length + 4 + extra; 483141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, buffer, &size); 484141cc406Sopenharmony_ci free (buffer); 485141cc406Sopenharmony_ci if ((status == SANE_STATUS_GOOD) && (size != (size_t) length + 4 + extra)) 486141cc406Sopenharmony_ci { 487141cc406Sopenharmony_ci DBG (DBG_error, 488141cc406Sopenharmony_ci "sanei_rts88xx_write_mem: only wrote %lu bytes out of %d\n", 489141cc406Sopenharmony_ci (u_long) size, length + 4); 490141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 491141cc406Sopenharmony_ci } 492141cc406Sopenharmony_ci return status; 493141cc406Sopenharmony_ci} 494141cc406Sopenharmony_ci 495141cc406Sopenharmony_ci/* 496141cc406Sopenharmony_ci * set memory with the given data 497141cc406Sopenharmony_ci */ 498141cc406Sopenharmony_ciSANE_Status 499141cc406Sopenharmony_cisanei_rts88xx_set_mem (SANE_Int devnum, SANE_Byte ctrl1, 500141cc406Sopenharmony_ci SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value) 501141cc406Sopenharmony_ci{ 502141cc406Sopenharmony_ci SANE_Status status; 503141cc406Sopenharmony_ci SANE_Byte regs[2]; 504141cc406Sopenharmony_ci regs[0] = ctrl1; 505141cc406Sopenharmony_ci regs[1] = ctrl2; 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci status = sanei_rts88xx_write_regs (devnum, 0x91, regs, 2); 508141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 509141cc406Sopenharmony_ci { 510141cc406Sopenharmony_ci DBG (DBG_error, 511141cc406Sopenharmony_ci "sanei_rts88xx_set_mem: failed to write 0x91/0x92 registers\n"); 512141cc406Sopenharmony_ci return status; 513141cc406Sopenharmony_ci } 514141cc406Sopenharmony_ci status = sanei_rts88xx_write_mem (devnum, length, 0, value); 515141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 516141cc406Sopenharmony_ci { 517141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_set_mem: failed to write memory\n"); 518141cc406Sopenharmony_ci } 519141cc406Sopenharmony_ci return status; 520141cc406Sopenharmony_ci} 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci/* 523141cc406Sopenharmony_ci * read length bytes of memory into area pointed by value 524141cc406Sopenharmony_ci */ 525141cc406Sopenharmony_ciSANE_Status 526141cc406Sopenharmony_cisanei_rts88xx_read_mem (SANE_Int devnum, SANE_Int length, SANE_Byte * value) 527141cc406Sopenharmony_ci{ 528141cc406Sopenharmony_ci SANE_Status status; 529141cc406Sopenharmony_ci size_t size, read, want; 530141cc406Sopenharmony_ci SANE_Byte header[4]; 531141cc406Sopenharmony_ci 532141cc406Sopenharmony_ci /* build and write length header */ 533141cc406Sopenharmony_ci header[0] = 0x81; 534141cc406Sopenharmony_ci header[1] = 0x00; 535141cc406Sopenharmony_ci header[2] = HIBYTE (length); 536141cc406Sopenharmony_ci header[3] = LOBYTE (length); 537141cc406Sopenharmony_ci size = 4; 538141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, header, &size); 539141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 540141cc406Sopenharmony_ci { 541141cc406Sopenharmony_ci DBG (DBG_error, 542141cc406Sopenharmony_ci "sanei_rts88xx_read_mem: failed to write length header\n"); 543141cc406Sopenharmony_ci return status; 544141cc406Sopenharmony_ci } 545141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_read_mem: %02x %02x %02x %02x -> ...\n", 546141cc406Sopenharmony_ci header[0], header[1], header[2], header[3]); 547141cc406Sopenharmony_ci read = 0; 548141cc406Sopenharmony_ci while (length > 0) 549141cc406Sopenharmony_ci { 550141cc406Sopenharmony_ci if (length > 2048) 551141cc406Sopenharmony_ci want = 2048; 552141cc406Sopenharmony_ci else 553141cc406Sopenharmony_ci want = length; 554141cc406Sopenharmony_ci size = want; 555141cc406Sopenharmony_ci status = sanei_usb_read_bulk (devnum, value + read, &size); 556141cc406Sopenharmony_ci if (size != want) 557141cc406Sopenharmony_ci { 558141cc406Sopenharmony_ci DBG (DBG_error, 559141cc406Sopenharmony_ci "sanei_rts88xx_read_mem: only read %lu bytes out of %lu\n", 560141cc406Sopenharmony_ci (u_long) size, (u_long) want); 561141cc406Sopenharmony_ci status = SANE_STATUS_IO_ERROR; 562141cc406Sopenharmony_ci } 563141cc406Sopenharmony_ci length -= size; 564141cc406Sopenharmony_ci read += size; 565141cc406Sopenharmony_ci } 566141cc406Sopenharmony_ci return status; 567141cc406Sopenharmony_ci} 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci/* 570141cc406Sopenharmony_ci * set memory with the given data 571141cc406Sopenharmony_ci */ 572141cc406Sopenharmony_ciSANE_Status 573141cc406Sopenharmony_cisanei_rts88xx_get_mem (SANE_Int devnum, SANE_Byte ctrl1, 574141cc406Sopenharmony_ci SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value) 575141cc406Sopenharmony_ci{ 576141cc406Sopenharmony_ci SANE_Status status; 577141cc406Sopenharmony_ci SANE_Byte regs[2]; 578141cc406Sopenharmony_ci regs[0] = ctrl1; 579141cc406Sopenharmony_ci regs[1] = ctrl2; 580141cc406Sopenharmony_ci 581141cc406Sopenharmony_ci status = sanei_rts88xx_write_regs (devnum, 0x91, regs, 2); 582141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 583141cc406Sopenharmony_ci { 584141cc406Sopenharmony_ci DBG (DBG_error, 585141cc406Sopenharmony_ci "sanei_rts88xx_get_mem: failed to write 0x91/0x92 registers\n"); 586141cc406Sopenharmony_ci return status; 587141cc406Sopenharmony_ci } 588141cc406Sopenharmony_ci status = sanei_rts88xx_read_mem (devnum, length, value); 589141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 590141cc406Sopenharmony_ci { 591141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_get_mem: failed to read memory\n"); 592141cc406Sopenharmony_ci } 593141cc406Sopenharmony_ci return status; 594141cc406Sopenharmony_ci} 595141cc406Sopenharmony_ci 596141cc406Sopenharmony_ci/* 597141cc406Sopenharmony_ci * write to the nvram controller 598141cc406Sopenharmony_ci */ 599141cc406Sopenharmony_ciSANE_Status 600141cc406Sopenharmony_cisanei_rts88xx_nvram_ctrl (SANE_Int devnum, SANE_Int length, SANE_Byte * value) 601141cc406Sopenharmony_ci{ 602141cc406Sopenharmony_ci SANE_Status status; 603141cc406Sopenharmony_ci SANE_Int i; 604141cc406Sopenharmony_ci char message[60 * 5]; 605141cc406Sopenharmony_ci#ifdef HAZARDOUS_EXPERIMENT 606141cc406Sopenharmony_ci SANE_Int size = 0; 607141cc406Sopenharmony_ci SANE_Byte buffer[60]; 608141cc406Sopenharmony_ci#endif 609141cc406Sopenharmony_ci 610141cc406Sopenharmony_ci if (DBG_LEVEL > DBG_io) 611141cc406Sopenharmony_ci { 612141cc406Sopenharmony_ci for (i = 0; i < length; i++) 613141cc406Sopenharmony_ci { 614141cc406Sopenharmony_ci sprintf (message + 5 * i, "0x%02x ", value[i]); 615141cc406Sopenharmony_ci } 616141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_nvram_ctrl : devnum=%d, nvram_ctrl(0x00,%d)=%s\n", 617141cc406Sopenharmony_ci devnum, length, message); 618141cc406Sopenharmony_ci } 619141cc406Sopenharmony_ci 620141cc406Sopenharmony_ci#ifdef HAZARDOUS_EXPERIMENT 621141cc406Sopenharmony_ci buffer[0] = 0x8a; 622141cc406Sopenharmony_ci buffer[1] = 0x00; 623141cc406Sopenharmony_ci buffer[2] = 0x00; 624141cc406Sopenharmony_ci buffer[3] = length; 625141cc406Sopenharmony_ci for (i = 0; i < size; i++) 626141cc406Sopenharmony_ci buffer[i + 4] = value[i]; 627141cc406Sopenharmony_ci /* the USB block is size + 4 bytes of header long */ 628141cc406Sopenharmony_ci size = length + 4; 629141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, buffer, &size); 630141cc406Sopenharmony_ci#else 631141cc406Sopenharmony_ci status = SANE_STATUS_GOOD; 632141cc406Sopenharmony_ci#endif 633141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 634141cc406Sopenharmony_ci { 635141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_nvram_ctrl : write failed ...\n"); 636141cc406Sopenharmony_ci } 637141cc406Sopenharmony_ci return status; 638141cc406Sopenharmony_ci} 639141cc406Sopenharmony_ci 640141cc406Sopenharmony_ci/* 641141cc406Sopenharmony_ci * setup nvram 642141cc406Sopenharmony_ci */ 643141cc406Sopenharmony_ciSANE_Status 644141cc406Sopenharmony_cisanei_rts88xx_setup_nvram (SANE_Int devnum, SANE_Int length, 645141cc406Sopenharmony_ci SANE_Byte * value) 646141cc406Sopenharmony_ci{ 647141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 648141cc406Sopenharmony_ci SANE_Byte local[2], reg; 649141cc406Sopenharmony_ci int i; 650141cc406Sopenharmony_ci 651141cc406Sopenharmony_ci status = sanei_rts88xx_nvram_ctrl (devnum, length, value); 652141cc406Sopenharmony_ci 653141cc406Sopenharmony_ci#ifndef HAZARDOUS_EXPERIMENT 654141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 655141cc406Sopenharmony_ci#endif 656141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 657141cc406Sopenharmony_ci { 658141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed step #1 ...\n"); 659141cc406Sopenharmony_ci return status; 660141cc406Sopenharmony_ci } 661141cc406Sopenharmony_ci local[0] = 0x18; 662141cc406Sopenharmony_ci local[1] = 0x08; 663141cc406Sopenharmony_ci for (i = 0; i < 8; i++) 664141cc406Sopenharmony_ci { 665141cc406Sopenharmony_ci status = sanei_rts88xx_nvram_ctrl (devnum, 2, local); 666141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 667141cc406Sopenharmony_ci { 668141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed loop #%d ...\n", 669141cc406Sopenharmony_ci i); 670141cc406Sopenharmony_ci return status; 671141cc406Sopenharmony_ci } 672141cc406Sopenharmony_ci status = sanei_rts88xx_read_reg (devnum, 0x10, ®); 673141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 674141cc406Sopenharmony_ci { 675141cc406Sopenharmony_ci DBG (DBG_error, 676141cc406Sopenharmony_ci "sanei_rts88xx_setup_nvram : register reading failed loop #%d ...\n", 677141cc406Sopenharmony_ci i); 678141cc406Sopenharmony_ci return status; 679141cc406Sopenharmony_ci } 680141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_setup_nvram: reg[0x10]=0x%02x\n", reg); 681141cc406Sopenharmony_ci } 682141cc406Sopenharmony_ci reg = 0; 683141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, ®); 684141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 685141cc406Sopenharmony_ci { 686141cc406Sopenharmony_ci DBG (DBG_error, 687141cc406Sopenharmony_ci "sanei_rts88xx_setup_nvram : controller register write failed\n"); 688141cc406Sopenharmony_ci return status; 689141cc406Sopenharmony_ci } 690141cc406Sopenharmony_ci reg = 1; 691141cc406Sopenharmony_ci status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, ®); 692141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 693141cc406Sopenharmony_ci { 694141cc406Sopenharmony_ci DBG (DBG_error, 695141cc406Sopenharmony_ci "sanei_rts88xx_setup_nvram : controller register write failed\n"); 696141cc406Sopenharmony_ci return status; 697141cc406Sopenharmony_ci } 698141cc406Sopenharmony_ci return status; 699141cc406Sopenharmony_ci} 700141cc406Sopenharmony_ci 701141cc406Sopenharmony_ci/* 702141cc406Sopenharmony_ci * Sets scan area, no checks are being done, so watch your steps 703141cc406Sopenharmony_ci */ 704141cc406Sopenharmony_civoid 705141cc406Sopenharmony_cisanei_rts88xx_set_scan_area (SANE_Byte * regs, SANE_Int ystart, 706141cc406Sopenharmony_ci SANE_Int yend, SANE_Int xstart, SANE_Int xend) 707141cc406Sopenharmony_ci{ 708141cc406Sopenharmony_ci /* vertical lines to move before scan */ 709141cc406Sopenharmony_ci regs[START_LINE] = LOBYTE (ystart); 710141cc406Sopenharmony_ci regs[START_LINE + 1] = HIBYTE (ystart); 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci /* total number of line to move */ 713141cc406Sopenharmony_ci regs[END_LINE] = LOBYTE (yend); 714141cc406Sopenharmony_ci regs[END_LINE + 1] = HIBYTE (yend); 715141cc406Sopenharmony_ci 716141cc406Sopenharmony_ci /* set horizontal start position */ 717141cc406Sopenharmony_ci regs[START_PIXEL] = LOBYTE (xstart); 718141cc406Sopenharmony_ci regs[START_PIXEL + 1] = HIBYTE (xstart); 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci /* set horizontal end position */ 721141cc406Sopenharmony_ci regs[END_PIXEL] = LOBYTE (xend); 722141cc406Sopenharmony_ci regs[END_PIXEL + 1] = HIBYTE (xend); 723141cc406Sopenharmony_ci} 724141cc406Sopenharmony_ci 725141cc406Sopenharmony_ci/** 726141cc406Sopenharmony_ci * read available data count from scanner 727141cc406Sopenharmony_ci * from tests it appears that advertised data 728141cc406Sopenharmony_ci * may not be really available, and that a pause must be made 729141cc406Sopenharmony_ci * before reading data so that it is really there. 730141cc406Sopenharmony_ci * Such as reading data twice. 731141cc406Sopenharmony_ci */ 732141cc406Sopenharmony_ciSANE_Status 733141cc406Sopenharmony_cisanei_rts88xx_data_count (SANE_Int devnum, SANE_Word * count) 734141cc406Sopenharmony_ci{ 735141cc406Sopenharmony_ci SANE_Status status; 736141cc406Sopenharmony_ci size_t size; 737141cc406Sopenharmony_ci static SANE_Byte header[4] = { 0x90, 0x00, 0x00, 3 }; 738141cc406Sopenharmony_ci SANE_Byte result[3]; 739141cc406Sopenharmony_ci 740141cc406Sopenharmony_ci /* set count in case of failure */ 741141cc406Sopenharmony_ci *count = 0; 742141cc406Sopenharmony_ci 743141cc406Sopenharmony_ci size = 4; 744141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, header, &size); 745141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 746141cc406Sopenharmony_ci { 747141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_data_count : failed to write header\n"); 748141cc406Sopenharmony_ci return status; 749141cc406Sopenharmony_ci } 750141cc406Sopenharmony_ci size = 3; 751141cc406Sopenharmony_ci status = sanei_usb_read_bulk (devnum, result, &size); 752141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 753141cc406Sopenharmony_ci { 754141cc406Sopenharmony_ci DBG (DBG_error, 755141cc406Sopenharmony_ci "sanei_rts88xx_data_count : failed to read data count\n"); 756141cc406Sopenharmony_ci return status; 757141cc406Sopenharmony_ci } 758141cc406Sopenharmony_ci *count = result[0] + (result[1] << 8) + (result[2] << 16); 759141cc406Sopenharmony_ci DBG (DBG_io2, "sanei_rts88xx_data_count: %d bytes available (0x%06x)\n", 760141cc406Sopenharmony_ci *count, *count); 761141cc406Sopenharmony_ci return status; 762141cc406Sopenharmony_ci} 763141cc406Sopenharmony_ci 764141cc406Sopenharmony_ci/** 765141cc406Sopenharmony_ci * Waits for data being available while optionally polling motor. There is a timeout 766141cc406Sopenharmony_ci * to prevent scanner waiting forever non coming data. 767141cc406Sopenharmony_ci */ 768141cc406Sopenharmony_ciSANE_Status 769141cc406Sopenharmony_cisanei_rts88xx_wait_data (SANE_Int devnum, SANE_Bool busy, SANE_Word * count) 770141cc406Sopenharmony_ci{ 771141cc406Sopenharmony_ci SANE_Status status; 772141cc406Sopenharmony_ci SANE_Byte control; 773141cc406Sopenharmony_ci 774141cc406Sopenharmony_ci /* poll the available byte count until not 0 */ 775141cc406Sopenharmony_ci while (SANE_TRUE) 776141cc406Sopenharmony_ci { 777141cc406Sopenharmony_ci status = sanei_rts88xx_data_count (devnum, count); 778141cc406Sopenharmony_ci if (*count != 0) 779141cc406Sopenharmony_ci { 780141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_wait_data: %d bytes available\n", 781141cc406Sopenharmony_ci *count); 782141cc406Sopenharmony_ci return status; 783141cc406Sopenharmony_ci } 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci /* check that the scanner is busy scanning */ 786141cc406Sopenharmony_ci if (busy) 787141cc406Sopenharmony_ci { 788141cc406Sopenharmony_ci sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); 789141cc406Sopenharmony_ci if ((control & 0x08) == 0 && (*count == 0)) 790141cc406Sopenharmony_ci { 791141cc406Sopenharmony_ci DBG (DBG_error, 792141cc406Sopenharmony_ci "sanei_rts88xx_wait_data: scanner stopped being busy before data are available\n"); 793141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 794141cc406Sopenharmony_ci } 795141cc406Sopenharmony_ci } 796141cc406Sopenharmony_ci } 797141cc406Sopenharmony_ci 798141cc406Sopenharmony_ci /* we hit timeout */ 799141cc406Sopenharmony_ci return SANE_STATUS_IO_ERROR; 800141cc406Sopenharmony_ci} 801141cc406Sopenharmony_ci 802141cc406Sopenharmony_ci/* 803141cc406Sopenharmony_ci * read scanned data from scanner up to the size given. The actual length read is returned. 804141cc406Sopenharmony_ci */ 805141cc406Sopenharmony_ciSANE_Status 806141cc406Sopenharmony_cisanei_rts88xx_read_data (SANE_Int devnum, SANE_Word * length, 807141cc406Sopenharmony_ci unsigned char *dest) 808141cc406Sopenharmony_ci{ 809141cc406Sopenharmony_ci SANE_Status status = SANE_STATUS_GOOD; 810141cc406Sopenharmony_ci SANE_Byte header[4]; 811141cc406Sopenharmony_ci size_t size, len, remain, read; 812141cc406Sopenharmony_ci 813141cc406Sopenharmony_ci /* do not read too much data */ 814141cc406Sopenharmony_ci if (*length > RTS88XX_MAX_XFER_SIZE) 815141cc406Sopenharmony_ci len = RTS88XX_MAX_XFER_SIZE; 816141cc406Sopenharmony_ci else 817141cc406Sopenharmony_ci len = *length; 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_ci /* write command header first */ 820141cc406Sopenharmony_ci header[0] = 0x91; 821141cc406Sopenharmony_ci header[1] = 0x00; 822141cc406Sopenharmony_ci header[2] = HIBYTE (len); 823141cc406Sopenharmony_ci header[3] = LOBYTE (len); 824141cc406Sopenharmony_ci size = 4; 825141cc406Sopenharmony_ci 826141cc406Sopenharmony_ci status = sanei_usb_write_bulk (devnum, header, &size); 827141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 828141cc406Sopenharmony_ci { 829141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_data: failed to write header\n"); 830141cc406Sopenharmony_ci } 831141cc406Sopenharmony_ci read = 0; 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci /* first read blocks aligned on 64 bytes boundary */ 834141cc406Sopenharmony_ci while (len - read > 64) 835141cc406Sopenharmony_ci { 836141cc406Sopenharmony_ci size = (len - read) & 0xFFC0; 837141cc406Sopenharmony_ci status = sanei_usb_read_bulk (devnum, dest + read, &size); 838141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 839141cc406Sopenharmony_ci { 840141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_data: failed to read data\n"); 841141cc406Sopenharmony_ci return status; 842141cc406Sopenharmony_ci } 843141cc406Sopenharmony_ci DBG (DBG_io2, "sanei_rts88xx_read_data: read %lu bytes\n", 844141cc406Sopenharmony_ci (u_long) size); 845141cc406Sopenharmony_ci read += size; 846141cc406Sopenharmony_ci } 847141cc406Sopenharmony_ci 848141cc406Sopenharmony_ci /* then read remainder */ 849141cc406Sopenharmony_ci remain = len - read; 850141cc406Sopenharmony_ci if (remain > 0) 851141cc406Sopenharmony_ci { 852141cc406Sopenharmony_ci status = sanei_usb_read_bulk (devnum, dest + read, &remain); 853141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 854141cc406Sopenharmony_ci { 855141cc406Sopenharmony_ci DBG (DBG_error, "sanei_rts88xx_read_data: failed to read data\n"); 856141cc406Sopenharmony_ci return status; 857141cc406Sopenharmony_ci } 858141cc406Sopenharmony_ci DBG (DBG_io2, "sanei_rts88xx_read_data: read %lu bytes\n", 859141cc406Sopenharmony_ci (u_long) remain); 860141cc406Sopenharmony_ci read += remain; 861141cc406Sopenharmony_ci } 862141cc406Sopenharmony_ci 863141cc406Sopenharmony_ci /* update actual read length */ 864141cc406Sopenharmony_ci DBG (DBG_io, "sanei_rts88xx_read_data: read %lu bytes, %d required\n", 865141cc406Sopenharmony_ci (u_long) read, *length); 866141cc406Sopenharmony_ci *length = read; 867141cc406Sopenharmony_ci return status; 868141cc406Sopenharmony_ci} 869