kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			342 wiersze
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			342 wiersze
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
| /*.............................................................................
 | |
|  * Project : SANE library for Plustek flatbed scanners.
 | |
|  *.............................................................................
 | |
|  */
 | |
| 
 | |
| /** @file plustek-usbio.c
 | |
|  *  @brief Some I/O stuff.
 | |
|  *
 | |
|  * Based on sources acquired from Plustek Inc.<br>
 | |
|  * Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
 | |
|  *
 | |
|  * History:
 | |
|  * History:
 | |
|  * - 0.40 - starting version of the USB support
 | |
|  * - 0.41 - moved some functions to a sane library (sanei_lm983x.c)
 | |
|  * - 0.42 - no changes
 | |
|  * - 0.43 - no changes
 | |
|  * - 0.44 - added dump registers and dumpPic functions
 | |
|  *        - beautyfied output of ASIC detection
 | |
|  * - 0.45 - fixed dumpRegs
 | |
|  *        - added dimension stuff to dumpPic
 | |
|  * - 0.46 - disabled reset prior to the detection of Merlin
 | |
|  * - 0.47 - no changes
 | |
|  * - 0.48 - cleanup
 | |
|  * - 0.49 - no changes
 | |
|  * - 0.50 - usbio_DetectLM983x() now returns error if register 
 | |
|  *          could not be red
 | |
|  *        - usbio_ResetLM983x() checks for reg7 value before writing
 | |
|  * - 0.51 - allow dumpRegs to be called without valid fd
 | |
|  * .
 | |
|  * <hr>
 | |
|  * 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.
 | |
|  * <hr>
 | |
|  */
 | |
|  
 | |
| #include "sane/sanei_usb.h"
 | |
| #include "sane/sanei_lm983x.h"
 | |
| 
 | |
| #define _UIO(func)                            \
 | |
|     {                                         \
 | |
|         SANE_Status status;                   \
 | |
|         status = func;                        \
 | |
|         if (status != SANE_STATUS_GOOD) {     \
 | |
|             DBG( _DBG_ERROR, "UIO error\n" ); \
 | |
|             return SANE_FALSE;                \
 | |
|         }                                     \
 | |
|     }
 | |
| 
 | |
| #define usbio_ReadReg(fd, reg, value) \
 | |
|   sanei_lm983x_read (fd, reg, value, 1, 0)
 | |
| 
 | |
| typedef struct {
 | |
| 
 | |
| 	u_char depth;
 | |
| 	u_long x;
 | |
| 	u_long y;
 | |
| } PicDef, *pPicDef;
 | |
| 
 | |
| static PicDef dPix;
 | |
| 
 | |
| /**
 | |
|  */
 | |
| static void dumpPic( char* name, SANE_Byte *buffer, u_long len )
 | |
| {
 | |
| 	FILE *fp;
 | |
| 
 | |
| 	if( DBG_LEVEL < _DBG_DPIC )
 | |
| 		return;
 | |
| 
 | |
| 	if( NULL == buffer ) {
 | |
| 
 | |
| 		DBG( _DBG_DPIC, "Creating file '%s'\n", name );
 | |
| 
 | |
| 		fp = fopen( name, "w+b" );
 | |
| 
 | |
| 		if( NULL != fp ) {
 | |
| 
 | |
| 			if( 0 != dPix.x ) {
 | |
| 
 | |
| 				DBG( _DBG_DPIC, "> X=%lu, Y=%lu, depth=%u\n",
 | |
| 				                 dPix.x, dPix.y, dPix.depth );
 | |
| 				if( dPix.depth > 8 )
 | |
| 					fprintf( fp, "P6\n%lu %lu\n65535\n", dPix.x, dPix.y );
 | |
|     			else
 | |
| 					fprintf( fp, "P6\n%lu %lu\n255\n", dPix.x, dPix.y );
 | |
| 			}
 | |
|     	}
 | |
| 	} else {
 | |
| 		fp = fopen( name, "a+b" );
 | |
| 	}
 | |
| 
 | |
| 	if( NULL == fp ) {
 | |
| 		DBG( _DBG_DPIC, "Can not open file '%s'\n", name );
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	fwrite( buffer, 1, len, fp );
 | |
| 	fclose( fp );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  */
 | |
| static void dumpPicInit( ScanParam *sd, char* name )
 | |
| {
 | |
| 	dPix.x = sd->Size.dwPhyBytes;
 | |
| 
 | |
| 	if( sd->bDataType == SCANDATATYPE_Color )
 | |
| 		dPix.x /= 3;
 | |
| 
 | |
| 	if( sd->bBitDepth > 8 )
 | |
| 		dPix.x /= 2;
 | |
| 
 | |
| 	dPix.y	   = sd->Size.dwLines;
 | |
| 	dPix.depth = sd->bBitDepth;
 | |
| 
 | |
| 	dumpPic( name, NULL, 0 );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * dump the LM983x registers
 | |
|  */
 | |
| static void dumpregs( int fd, SANE_Byte *cmp )
 | |
| {
 | |
| 	char      buf[256], b2[10];
 | |
| 	SANE_Byte regs[0x80];
 | |
| 	int       i;
 | |
| 
 | |
| 	if( DBG_LEVEL < _DBG_DREGS )
 | |
| 		return;
 | |
| 
 | |
| 	buf[0] = '\0';
 | |
| 
 | |
| 	if( fd >= 0 ) {
 | |
| 		usbio_ReadReg(fd, 0x01, ®s[0x01]);
 | |
| 		usbio_ReadReg(fd, 0x02, ®s[0x02]);
 | |
| 		usbio_ReadReg(fd, 0x03, ®s[0x03]);
 | |
| 		usbio_ReadReg(fd, 0x04, ®s[0x04]);
 | |
| 		usbio_ReadReg(fd, 0x07, ®s[0x07]);
 | |
| 
 | |
| 		sanei_lm983x_read( fd, 0x08, ®s[0x8], 0x80-0x8, SANE_TRUE );
 | |
| 
 | |
| 		for( i = 0x0; i < 0x80; i++ ) {
 | |
| 
 | |
| 			if((i%16) ==0 ) {
 | |
| 
 | |
| 				if( buf[0] )
 | |
| 					DBG( _DBG_DREGS, "%s\n", buf );
 | |
| 				sprintf( buf, "0x%02x:", i );
 | |
| 			}
 | |
| 
 | |
| 			if((i%8)==0)
 | |
| 				strcat( buf, " ");
 | |
| 
 | |
| 			/* the dataport read returns with "0 Bytes read", of course. */
 | |
| 			if((i == 0) || (i == 5) || (i == 6))
 | |
| 				strcat( buf, "XX ");
 | |
| 			else {
 | |
| 
 | |
| 				sprintf( b2, "%02x ", regs[i]);
 | |
| 				strcat( buf, b2 );
 | |
| 			}
 | |
| 		}
 | |
| 		DBG( _DBG_DREGS, "%s\n", buf );
 | |
| 	}
 | |
| 
 | |
| 	if( cmp ) {
 | |
| 
 | |
| 		buf[0] = '\0';
 | |
| 
 | |
| 		DBG( _DBG_DREGS, "Internal setting:\n" );
 | |
| 		for( i = 0x0; i < 0x80; i++ ) {
 | |
| 
 | |
| 			if((i%16) ==0 ) {
 | |
| 
 | |
| 				if( buf[0] )
 | |
| 					DBG( _DBG_DREGS, "%s\n", buf );
 | |
| 				sprintf( buf, "0x%02x:", i );
 | |
| 			}
 | |
| 
 | |
| 			if((i%8)==0)
 | |
| 				strcat( buf, " ");
 | |
| 
 | |
| 			if((i == 0) || (i == 5) || (i == 6))
 | |
| 				strcat( buf, "XX ");
 | |
| 			else {
 | |
| 				sprintf( b2, "%02x ", cmp[i]);
 | |
| 				strcat( buf, b2 );
 | |
| 			}
 | |
| 		}
 | |
| 		DBG( _DBG_DREGS, "%s\n", buf );
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * function to read the contents of a LM983x register and regarding some
 | |
|  * extra stuff, like flushing register 2 when writing register 0x58, etc
 | |
|  *
 | |
|  * @param handle -
 | |
|  * @param reg    -
 | |
|  * @param value  -
 | |
|  * @return
 | |
|  */
 | |
| static SANE_Bool usbio_WriteReg( SANE_Int handle,
 | |
|                                  SANE_Byte reg, SANE_Byte value )
 | |
| {
 | |
| 	int       i;
 | |
| 	SANE_Byte data;
 | |
| 
 | |
| 	/* retry loop... */
 | |
| 	for( i = 0; i < 100; i++ ) {
 | |
| 
 | |
| 		sanei_lm983x_write_byte( handle, reg, value );
 | |
| 	
 | |
| 		/* Flush register 0x02 when register 0x58 is written */
 | |
| 		if( 0x58 == reg ) {
 | |
| 			_UIO( usbio_ReadReg( handle, 2, &data ));
 | |
| 			_UIO( usbio_ReadReg( handle, 2, &data ));
 | |
| 		}
 | |
| 
 | |
| 		if( reg != 7 )
 | |
| 			return SANE_TRUE;
 | |
| 
 | |
| 		/* verify register 7 */
 | |
| 		_UIO( usbio_ReadReg( handle, 7, &data ));
 | |
| 		if( data == value ) {
 | |
| 			return SANE_TRUE;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return SANE_FALSE;
 | |
| }
 | |
| 
 | |
| /** try and read register 0x69 from a LM983x to find out which version we have.
 | |
|  */
 | |
| static SANE_Status usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version )
 | |
| {
 | |
| 	char        buf[256];
 | |
| 	SANE_Byte   value;
 | |
| 	SANE_Status res;
 | |
| 
 | |
| 	DBG( _DBG_INFO, "usbio_DetectLM983x\n");
 | |
| 
 | |
| 	res = usbio_ReadReg(fd, 0x69, &value);
 | |
| 	if( res != SANE_STATUS_GOOD ) {
 | |
| 		DBG( _DBG_ERROR, " * could not read version register!\n");
 | |
| 		return res;
 | |
| 	}
 | |
| 
 | |
| 	value &= 7;
 | |
| 	if (version)
 | |
| 		*version = value;
 | |
| 
 | |
| 	res = SANE_STATUS_GOOD;
 | |
| 
 | |
| 	sprintf( buf, "usbio_DetectLM983x: found " );
 | |
| 
 | |
| 	switch((SANE_Int)value ) {
 | |
| 		
 | |
| 		case 4:	 strcat( buf, "LM9832/3" ); break;
 | |
| 		case 3:	 strcat( buf, "LM9831" );   break;
 | |
| 		case 2:	 strcat( buf, "LM9830 --> unsupported!!!" );
 | |
| 				 res =  SANE_STATUS_INVAL;
 | |
| 				 break;
 | |
| 		default: DBG( _DBG_INFO, "Unknown chip v%d", value );
 | |
| 				 res = SANE_STATUS_INVAL;
 | |
| 				 break;
 | |
| 	}
 | |
| 
 | |
| 	DBG( _DBG_INFO, "%s\n", buf );
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| /** well, this is more or less a reset function, for LM9831 based devices
 | |
|  * we issue a real reset command, while for LM9832/3 based devices, checking
 | |
|  * and resetting register 7 will be enough...
 | |
|  */
 | |
| static SANE_Status usbio_ResetLM983x( Plustek_Device *dev )
 | |
| {
 | |
| 	SANE_Byte value;
 | |
| 	HWDef    *hw = &dev->usbDev.HwSetting;
 | |
| 
 | |
| 	if( _LM9831 == hw->chip ) {
 | |
| 
 | |
| 		DBG( _DBG_INFO," * resetting LM9831 device!\n");
 | |
| 		_UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0));
 | |
| 		_UIO( sanei_lm983x_write_byte( dev->fd, 0x07,0x20));
 | |
| 		_UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0));
 | |
| 		_UIO( usbio_ReadReg( dev->fd, 0x07, &value));
 | |
| 		if (value != 0) {
 | |
|  			DBG( _DBG_ERROR, "usbio_ResetLM983x: reset was not "
 | |
| 			                 "successful, status=%d\n", value );
 | |
| 			return SANE_STATUS_INVAL;
 | |
| 		}
 | |
| 
 | |
| 	} else {
 | |
| 		_UIO( usbio_ReadReg( dev->fd, 0x07, &value));
 | |
| 		if (value != 0 ) {
 | |
| 			DBG( _DBG_INFO," * setting device to idle state!\n");
 | |
| 			_UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0));
 | |
| 		}
 | |
| 	}
 | |
| 	return SANE_STATUS_GOOD;
 | |
| }
 | |
| 
 | |
| /* END PLUSTEK-USBIO.C ......................................................*/
 |