From 5d71d97a6b639d4ee367411a100ffd3eeddcc5a0 Mon Sep 17 00:00:00 2001 From: Gerhard Jaeger Date: Thu, 10 Jan 2002 19:36:06 +0000 Subject: [PATCH] Added LM983x library functions --- sanei/Makefile.in | 6 +- sanei/sanei_lm983x.c | 325 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+), 3 deletions(-) create mode 100644 sanei/sanei_lm983x.c diff --git a/sanei/Makefile.in b/sanei/Makefile.in index 5293b2358..d6aa9eafc 100644 --- a/sanei/Makefile.in +++ b/sanei/Makefile.in @@ -49,14 +49,14 @@ LIBSANEI_OBJS = sanei_ab306.o sanei_constrain_value.o sanei_init_debug.o \ sanei_net.o sanei_wire.o sanei_codec_ascii.o sanei_codec_bin.o \ sanei_save_values.o sanei_load_values.o \ sanei_scsi.o sanei_config.o sanei_config2.o sanei_pio.o sanei_pa4s2.o \ - sanei_auth.o sanei_usb.o sanei_thread.o sanei_pv8630.o + sanei_auth.o sanei_usb.o sanei_thread.o sanei_pv8630.o sanei_lm983x.o LIBSANEI_LTOBJS = sanei_ab306.lo sanei_constrain_value.lo sanei_init_debug.lo \ sanei_net.lo sanei_wire.lo sanei_codec_ascii.lo sanei_codec_bin.lo \ sanei_save_values.lo sanei_load_values.lo \ sanei_scsi.lo sanei_config.lo sanei_config2.lo sanei_pio.lo \ sanei_pa4s2.lo sanei_auth.lo sanei_usb.lo sanei_thread.lo \ - sanei_pv8630.lo + sanei_pv8630.lo sanei_lm983x.lo TARGETS = libsanei.a TESTPROGRAMS = test_wire @@ -65,7 +65,7 @@ DISTFILES = Makefile.in linux_sg3_err.h os2_srb.h sanei_DomainOS.c \ sanei_DomainOS.h sanei_ab306.c sanei_auth.c sanei_codec_ascii.c \ sanei_codec_bin.c sanei_config.c sanei_config2.c \ sanei_constrain_value.c sanei_init_debug.c sanei_load_values.c \ - sanei_net.c sanei_pa4s2.c sanei_pio.c sanei_pv8630.c \ + sanei_net.c sanei_pa4s2.c sanei_pio.c sanei_pv8630.c sanei_lm983x.c \ sanei_save_values.c sanei_scsi.c sanei_thread.c sanei_usb.c \ sanei_wire.c test_wire.c diff --git a/sanei/sanei_lm983x.c b/sanei/sanei_lm983x.c new file mode 100644 index 000000000..565f3acf0 --- /dev/null +++ b/sanei/sanei_lm983x.c @@ -0,0 +1,325 @@ +/* sane - Scanner Access Now Easy. + + based on sources acquired from Plustek Inc. + Copyright (C) 2002 Gerhard Jaeger + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. + + Interface files for the LM9831/2/3 chip, + a chip used in many USB scanners. + + */ + +#include "../include/sane/config.h" + +#include +#include +#include +#include + +#define BACKEND_NAME sanei_lm983x + +#include "../include/sane/sane.h" +#include "../include/sane/sanei_debug.h" +#include "../include/sane/sanei_usb.h" +#include "../include/sane/sanei_lm983x.h" + +/***************************** some definitions ******************************/ + +#define _MIN(a,b) ((a) < (b) ? (a) : (b)) +#define _MAX(a,b) ((a) > (b) ? (a) : (b)) + +#define _CMD_BYTE_CNT 4 +#define _MAX_RETRY 20 +#define _LM9831_MAX_REG 0x7f +#define _MAX_TRANSFER_SIZE 60 + +/******************************* the functions *******************************/ + +/** + * function to write one data byte to a specific LM983x register + * + * @param fd - device file descriptor + * @param reg - number of register + * @param value - byte value to be written + * + * @return SANE_STATUS_GOOD - on success + * SANE_STATUS_IO_ERROR - system write function failed + * SANE_STATUS_INVAL - register out of range + */ +SANE_Status +sanei_lm983x_write_byte( SANE_Int fd, SANE_Byte reg, SANE_Byte value ) +{ + return sanei_lm983x_write( fd, reg, &value, 1, SANE_FALSE ); +} + +/** + * function to write one or more data bytes to one ore more specific LM983x + * registers. + * + * @param fd - device file descriptor + * @param reg - number of start-register + * @param buffer - buffer to be written + * @param len - number of bytes to be written + * @param increment - SANE_TRUE enables the autoincrement of the register + * value during the write cylce, SANE_FALSE disables this + * + * @return SANE_STATUS_GOOD - on success + * SANE_STATUS_IO_ERROR - system read function failed + * SANE_STATUS_INVAL - register out of range or len field was 0 + */ +SANE_Status +sanei_lm983x_write( SANE_Int fd, SANE_Byte reg, + SANE_Byte *buffer, SANE_Word len, SANE_Bool increment ) +{ + size_t size; + SANE_Byte command_buffer[_MAX_TRANSFER_SIZE + _CMD_BYTE_CNT]; + SANE_Status result; + SANE_Word bytes, max_len; + + DBG( 15, "sanei_lm983x_write: fd=%d, reg=%d, len=%d, increment=%d\n", fd, + reg, len, increment); + + if( reg > _LM9831_MAX_REG ) { + DBG( 1, "sanei_lm983x_write: register out of range (%u>%u)\n", + reg, _LM9831_MAX_REG ); + return SANE_STATUS_INVAL; + } + + for( bytes = 0; len > 0; ) { + + max_len = _MIN( len, _MAX_TRANSFER_SIZE ); + + command_buffer[0] = 0; /* write */ + command_buffer[1] = reg; /* LM9831 register */ + + if( increment == SANE_TRUE ) { + command_buffer[0] += 0x02; /* increase reg? */ + command_buffer[1] += bytes; + } + + command_buffer[2] = (max_len >> 8) & 0xff; /* bytes to write MSB */ + command_buffer[3] = max_len & 0xff; /* bytes to write LSB */ + + memcpy( command_buffer + _CMD_BYTE_CNT, buffer + bytes, max_len ); + + size = (max_len + _CMD_BYTE_CNT); + result = sanei_usb_write_bulk( fd, command_buffer, &size ); + + if( SANE_STATUS_GOOD != result ) + return result; + + if( size != (size_t)(max_len + _CMD_BYTE_CNT)) { + DBG( 2, "sanei_lm983x_write: short write (%d/%d)\n", + result, max_len + _CMD_BYTE_CNT); + + if( size < _CMD_BYTE_CNT ) { + DBG( 1, "sanei_lm983x_write: couldn't even send command\n" ); + return SANE_STATUS_IO_ERROR; + } + DBG( 1, "sanei_lm983x_write: trying again\n" ); + } + len -= (size - _CMD_BYTE_CNT); + bytes += (size - _CMD_BYTE_CNT); + } + + DBG( 15, "sanei_lm983x_write: succeeded\n" ); + return SANE_STATUS_GOOD; +} + +/** + * function to read one or more data bytes from one ore more specific LM983x + * registers. + * + * @param fd - device file descriptor + * @param reg - number of start-register + * @param buffer - buffer to receive the data + * @param len - number of bytes to receive + * @param increment - SANE_TRUE enables the autoincrement of the register + * value during the read cylce, SANE_FALSE disables this + * + * @return SANE_STATUS_GOOD - on success + * SANE_STATUS_IO_ERROR - system read function failed + * SANE_STATUS_INVAL - register out of range + * SANE_STATUS_EOF - if nothing can't be read + */ +SANE_Status +sanei_lm983x_read( SANE_Int fd, SANE_Byte reg, + SANE_Byte *buffer, SANE_Word len, SANE_Bool increment ) +{ + size_t size; + SANE_Byte command_buffer[_CMD_BYTE_CNT]; + SANE_Status result; + SANE_Word bytes, max_len, read_bytes; + + DBG( 15, "sanei_lm983x_read: fd=%d, reg=%d, len=%d, increment=%d\n", + fd, reg, len, increment ); + if( reg > _LM9831_MAX_REG ) { + DBG( 1, "sanei_lm983x_read: register out of range (%u>%u)\n", + reg, _LM9831_MAX_REG ); + return SANE_STATUS_INVAL; + } + + for( bytes = 0; len > 0; ) { + + max_len = _MIN(len, 0xFFFF ); + command_buffer[0] = 1; /* read */ + command_buffer[1] = reg; /* LM9831 register */ + + if( increment ) { + command_buffer[0] += 0x02; + command_buffer[1] += bytes; + } + + command_buffer[2] = (max_len >> 8) & 0xff; /* bytes to read MSB */ + command_buffer[3] = max_len & 0xff; /* bytes to read LSB */ + + DBG( 15, "sanei_lm983x_read: writing command: " + "%02x %02x %02x %02x\n", command_buffer[0], command_buffer[1], + command_buffer[2], command_buffer[3]); + + size = _CMD_BYTE_CNT; + result = sanei_usb_write_bulk( fd, command_buffer, &size ); + + if( SANE_STATUS_GOOD != result ) + return result; + + if( size != _CMD_BYTE_CNT) { + DBG( 1, "sanei_lm983x_read: short write while writing command " + "(%d/_CMD_BYTE_CNT)\n", result); + return SANE_STATUS_IO_ERROR; + } + + read_bytes = 0; + + do { + + size = (max_len - read_bytes); + + result = sanei_usb_read_bulk( fd, (buffer + bytes + read_bytes), &size ); + + if( SANE_STATUS_GOOD != result ) + return result; + + read_bytes += size; + DBG( 15, "sanei_lm983x_read: read %d bytes\n", size ); + + if( read_bytes != max_len ) { + DBG( 2, "sanei_lm983x_read: short read (%d/%d)\n", + result, max_len ); + + /* wait a little bit before retrying */ + usleep( 10000 ); + DBG( 2, "sanei_lm983x_read: trying again\n" ); + } + + } while( read_bytes < max_len ); + + bytes += (max_len); + len -= (max_len); + } + + DBG( 15, "sanei_lm983x_read: succeeded\n" ); + return SANE_STATUS_GOOD; +} + +/** + * function to reset the LM983x chips + * + * @param fd - device file descriptor + * @return SANE_TRUE - reset successfuly done + * SANE_FALSE - reset failed + */ +SANE_Bool sanei_lm983x_reset( SANE_Int fd ) +{ + SANE_Byte cmd_buffer[_CMD_BYTE_CNT]; + SANE_Byte tmp; + SANE_Int i; + + DBG( 15, "sanei_lm983x_reset()\n" ); + + for( i = 0; i < _MAX_RETRY; i++ ) { + + /* Read the command register and check that the reset bit is not set + * If it is set, clear it and return false to indicate that + * the bit has only now been cleared + * + * Write the command bytes for a register read + * without increment + */ + cmd_buffer[0] = 0x01; + cmd_buffer[1] = 7; /* command/status register */ + cmd_buffer[2] = 0; + cmd_buffer[3] = 1; + + if( _CMD_BYTE_CNT == write( fd, cmd_buffer, _CMD_BYTE_CNT )) { + + /* Then read the register in question */ + u_long cbBytes = 1; + + if( read( fd, &tmp, cbBytes )) { + + if( tmp & 0x20 ) { + + SANE_Byte wrt_buffer[_CMD_BYTE_CNT + 1]; + + /* Write the command bytes for a register read + * without increment + */ + wrt_buffer[0] = 0x00; + wrt_buffer[1] = 7; + wrt_buffer[2] = 0; + wrt_buffer[3] = 1; + wrt_buffer[4] = 0; /* <--- The data for the register */ + + /* We will attempt to reset it but we really don't do + * anything if this fails + */ + if( write( fd, wrt_buffer, _CMD_BYTE_CNT + 1)) { + DBG( 15, "Resetting the LM983x done\n" ); + return SANE_TRUE; + } + } + } + } + } + return SANE_FALSE; +} + +/* END sanei_lm983x.c........................................................*/