diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-10-06 14:00:40 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-10-06 14:00:40 +0200 |
commit | 6e9c41a892ed0e0da326e0278b3221ce3f5713b8 (patch) | |
tree | 2e301d871bbeeb44aa57ff9cc070fcf3be484487 /sanei/sanei_lm983x.c |
Initial import of sane-backends version 1.0.24-1.2
Diffstat (limited to 'sanei/sanei_lm983x.c')
-rw-r--r-- | sanei/sanei_lm983x.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/sanei/sanei_lm983x.c b/sanei/sanei_lm983x.c new file mode 100644 index 0000000..5b41985 --- /dev/null +++ b/sanei/sanei_lm983x.c @@ -0,0 +1,265 @@ +/* sane - Scanner Access Now Easy. + + based on sources acquired from Plustek Inc. + Copyright (C) 2002-2004 Gerhard Jaeger <gerhard@gjaeger.de> + + 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 <sys/types.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#define BACKEND_NAME sanei_lm983x /**< the name of this module for dbg */ + +#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 /**< header for LM983x transfers */ +#define _MAX_RETRY 20 /**< number of tries for reset */ +#define _LM9831_MAX_REG 0x7f /**< number of LM983x bytes */ +#define _MAX_TRANSFER_SIZE 60 /**< max. number of bytes to transfer */ + +/******************************* the functions *******************************/ + +void +sanei_lm983x_init( void ) +{ + DBG_INIT(); +} + +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 ); +} + +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; /* LM983x 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; +} + +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 %lu bytes\n", (u_long) 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; +} + +SANE_Bool sanei_lm983x_reset( SANE_Int fd ) +{ + SANE_Status res; + 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 + */ + if( SANE_STATUS_GOOD != sanei_lm983x_read_byte( fd, 0x07, &tmp )) + continue; + + if( tmp & 0x20 ) { + + res = sanei_lm983x_write_byte( fd, 0x07, 0 ); + + /* We will attempt to reset it but we really don't do + * anything if this fails + */ + if( res == SANE_STATUS_GOOD ) { + DBG( 15, "Resetting the LM983x already done\n" ); + return SANE_TRUE; + } + } else { + + res = sanei_lm983x_write_byte( fd, 0x07, 0x20 ); + if( res == SANE_STATUS_GOOD ) { + DBG( 15, "Resetting the LM983x done\n" ); + return SANE_TRUE; + } + } + } + return SANE_FALSE; +} + +/* END sanei_lm983x.c .......................................................*/ |