Updated Plustek backend and added code for alternative CIS calibration.

All the supported CanoScan devices should work now correctly.
Moved the Plustek parallelport support into a separate backend: plustek_pp.
Added new backend for Plustek ASIC 9600x/9800x based parallelport scanner.
merge-requests/1/head
Gerhard Jaeger 2003-09-23 07:10:53 +00:00
rodzic 86cead990d
commit 1eef5c8c60
52 zmienionych plików z 28042 dodań i 867 usunięć

Wyświetl plik

@ -1,3 +1,30 @@
2003-09-23 Gerhard Jaeger <gerhard@gjaeger.de>
* configure.in: added new backend plustek_pp
* doc/descriptions/plustek_pp.desc : added
* doc/plustek/*: added/updated various doc-files
* doc/sane-plustek_pp.man doc/Makefile.in : added new man page
* backend/dll.conf : added plustek_pp
* backend/Makefile.in : added plustek_pp files, updated plustek files
* backend/plustek-devs.c backend/pustek-pp.c : removed
* backend/plustek-usbcalfile.c backend/plustek-usbcal.c
backend/plustek-usbdevs.c: new files for the plustek usb backend
* backend/plustek_pp.c backend/plustek_pp.conf
* backend/plustek-pp.h backend/plustek-pp_dac.c backend/plustek-pp_dbg.h
backend/plustek-pp_detect.c backend/plustek-pp_genericio.c
backend/plustek-pp_hwdefs.h backend/plustek-pp_image.c
backend/plustek-pp_io.c backend/plustek-pp_map.c backend/plustek-pp_misc.c
backend/plustek-pp_models.c backend/plustek-pp_motor.c
backend/plustek-pp_p12.c backend/plustek-pp_p12ccd.c
backend/plustek-pp_p48xx.c backend/plustek-pp_p9636.c
backend/plustek-pp_procfs.c backend/plustek-pp_procs.h
backend/plustek-pp_ptdrv.c backend/plustek-pp_scale.c
backend/plustek-pp_scan.h backend/plustek-pp_scandata.h
backend/plustek-pp_sysdep.h backend/plustek-pp_tpa.c
backend/plustek-pp_types.h backend/plustek-pp_wrapper.c :
new added, contains all the code necessary for controlling various Plustek
ASIC 9600x/9800x based parallelport scanner
2003-09-21 Henning Meier-Geinitz <henning@meier-geinitz.de>
* tools/sane-desc.c: PATH_MAX is too small for long comments on

Wyświetl plik

@ -119,9 +119,17 @@ DISTFILES = abaton.c abaton.conf abaton.h agfafocus.c agfafocus.conf \
mustek_usb.h mustek_usb_high.c mustek_usb_high.h mustek_usb_low.c \
mustek_usb_low.h mustek_usb_mid.c mustek_usb_mid.h nec.c nec.conf nec.h \
net.c net.conf net.h pie.c pie.conf pie-scsidef.h pint.c pint.h plustek.c \
plustek.conf plustek-devs.c plustek.h plustek-pp.c plustek-share.h \
plustek.conf plustek-usbdevs.c plustek.h plustek-share.h \
plustek-usb.c plustek-usb.h plustek-usbhw.c plustek-usbimg.c \
plustek-usbio.c plustek-usbmap.c plustek-usbscan.c plustek-usbshading.c \
plustek-usbcalfile.c plustek-usbcal.c \
plustek-pp_dac.c plustek-pp_dbg.h plustek-pp_detect.c plustek-pp_genericio.c \
plustek-pp_hwdefs.h plustek-pp_image.c plustek-pp_io.c plustek-pp_map.c \
plustek-pp_misc.c plustek-pp_models.c plustek-pp_motor.c plustek-pp_p12.c \
plustek-pp_p12ccd.c plustek-pp_p48xx.c plustek-pp_p9636.c plustek-pp_procfs.c \
plustek-pp_procs.h plustek-pp_ptdrv.c plustek-pp_scale.c plustek-pp_scan.h \
plustek-pp_scandata.h plustek-pp_sysdep.h plustek-pp_tpa.c plustek-pp_types.h \
plustek_pp.c plustek-pp_wrapper.c plustek_pp.conf plustek-pp.h \
pnm.c qcam.c qcam.conf qcam.h ricoh.c ricoh.conf ricoh.h \
ricoh-scsi.c s9036.c s9036.conf s9036.h saned.conf sane_strstatus.c \
sceptre.c sceptre.conf sceptre.h sharp.c sharp.conf sharp.h sm3600.c \
@ -349,6 +357,7 @@ libsane-pint.la: ../sanei/sanei_constrain_value.lo
libsane-plustek.la: ../sanei/sanei_constrain_value.lo
libsane-plustek.la: ../sanei/sanei_usb.lo
libsane-plustek.la: ../sanei/sanei_lm983x.lo
libsane-plustekpp.la: ../sanei/sanei_constrain_value.lo
libsane-pnm.la: ../sanei/sanei_constrain_value.lo
libsane-qcam.la: ../sanei/sanei_constrain_value.lo
libsane-ricoh.la: ../sanei/sanei_config2.lo

Wyświetl plik

@ -37,6 +37,7 @@ nec
pie
pint
plustek
#plustek_pp
#pnm
qcam
ricoh

Wyświetl plik

@ -0,0 +1,379 @@
/*.............................................................................
* Project : SANE library for Plustek flatbed scanners.
*.............................................................................
*/
/** @file plustek-pp.h
* @brief Definitions for the backend.
*
* Based on Kazuhiro Sasayama previous
* Work on plustek.[ch] file from the SANE package.<br>
*
* original code taken from sane-0.71<br>
* Copyright (C) 1997 Hypercore Software Design, Ltd.<br>
* Copyright (C) 2001-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.01 - initial version
* .
* <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>
*/
#ifndef __PLUSTEKPP_H__
#define __PLUSTEKPP_H__
/************************ some definitions ***********************************/
#define MM_PER_INCH 25.4
#define PLUSTEK_CONFIG_FILE "plustek_pp.conf"
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
/*
* the default image size
*/
#define _DEFAULT_TLX 0 /* 0..216 mm */
#define _DEFAULT_TLY 0 /* 0..297 mm */
#define _DEFAULT_BRX 126 /* 0..216 mm*/
#define _DEFAULT_BRY 76.21 /* 0..297 mm */
#define _DEFAULT_TP_TLX 3.5 /* 0..42.3 mm */
#define _DEFAULT_TP_TLY 10.5 /* 0..43.1 mm */
#define _DEFAULT_TP_BRX 38.5 /* 0..42.3 mm */
#define _DEFAULT_TP_BRY 33.5 /* 0..43.1 mm */
#define _DEFAULT_NEG_TLX 1.5 /* 0..38.9 mm */
#define _DEFAULT_NEG_TLY 1.5 /* 0..29.6 mm */
#define _DEFAULT_NEG_BRX 37.5 /* 0..38.9 mm */
#define _DEFAULT_NEG_BRY 25.5 /* 0..29.6 mm */
/*
* image sizes for normal, transparent and negative modes
*/
#define _NORMAL_X 216.0
#define _NORMAL_Y 297.0
#define _TP_X ((double)_TPAPageWidth/300.0 * MM_PER_INCH)
#define _TP_Y ((double)_TPAPageHeight/300.0 * MM_PER_INCH)
#define _NEG_X ((double)_NegativePageWidth/300.0 * MM_PER_INCH)
#define _NEG_Y ((double)_NegativePageHeight/300.0 * MM_PER_INCH)
#define _MAX_ID_LEN 20
/******************** from former plustek-share.h ***************************/
/*
* for other OS than Linux, we might have to define the _IO macros
*/
#ifndef _IOC
#define _IOC(dir,type,nr,size) \
(((dir) << 30) | \
((type) << 8) | \
((nr) << 0) | \
((size) << 16))
#endif
#ifndef _IO
#define _IO(type,nr) _IOC(0U,(type),(nr),0)
#endif
#ifndef _IOR
#define _IOR(type,nr,size) _IOC(2U,(type),(nr),sizeof(size))
#endif
#ifndef _IOW
#define _IOW(type,nr,size) _IOC(1U,(type),(nr),sizeof(size))
#endif
#ifndef _IOWR
#define _IOWR(type,nr,size) _IOC(3U,(type),(nr),sizeof(size))
#endif
/*.............................................................................
* the ioctl interface
*/
#define _PTDRV_OPEN_DEVICE _IOW('x', 1, unsigned short)/* open */
#define _PTDRV_GET_CAPABILITIES _IOR('x', 2, ScannerCaps) /* get caps */
#define _PTDRV_GET_LENSINFO _IOR('x', 3, LensInfo) /* get lenscaps */
#define _PTDRV_PUT_IMAGEINFO _IOW('x', 4, ImgDef) /* put image info*/
#define _PTDRV_GET_CROPINFO _IOR('x', 5, CropInfo) /* get crop */
#define _PTDRV_SET_ENV _IOWR('x',6, ScanInfo) /* set env. */
#define _PTDRV_START_SCAN _IOR('x', 7, StartScan) /* start scan */
#define _PTDRV_STOP_SCAN _IOWR('x', 8, int) /* stop scan */
#define _PTDRV_CLOSE_DEVICE _IO('x', 9) /* close */
#define _PTDRV_ACTION_BUTTON _IOR('x', 10, int) /* rd act. button*/
#define _PTDRV_ADJUST _IOR('x', 11, AdjDef) /* adjust driver */
#define _PTDRV_SETMAP _IOR('x', 12, MapDef) /* download gamma*/
/*
* this version MUST match the one inside the driver to make sure, that
* both sides use the same structures. This version changes each time
* the ioctl interface changes
*/
#define _PTDRV_COMPAT_IOCTL_VERSION 0x0102
#define _PTDRV_IOCTL_VERSION 0x0103
/* NOTE: needs to be kept in sync with table below */
#define MODELSTR static char *ModelStr[] = { \
"unknown", \
"Primax 4800", \
"Primax 4800 Direct", \
"Primax 4800 Direct 30Bit", \
"Primax 9600 Direct 30Bit", \
"4800P", \
"4830P", \
"600P/6000P", \
"4831P", \
"9630P", \
"9630PL", \
"9636P", \
"A3I", \
"12000P/96000P", \
"9636P+/Turbo", \
"9636T/12000T", \
"P8", \
"P12", \
"PT12", \
"Genius Colorpage Vivid III V2", \
"USB-Device" \
}
/* the models */
#define MODEL_OP_UNKNOWN 0 /* unknown */
#define MODEL_PMX_4800 1 /* Primax Colorado 4800 like OP 4800 */
#define MODEL_PMX_4800D 2 /* Primax Compact 4800 Direct, OP 600 R->G, G->R */
#define MODEL_PMX_4800D3 3 /* Primax Compact 4800 Direct 30 */
#define MODEL_PMX_9600D3 4 /* Primax Compact 9600 Direct 30 */
#define MODEL_OP_4800P 5 /* 32k, 96001 ASIC, 24 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_4830P 6 /* 32k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_600P 7 /* 32k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_4831P 8 /* 128k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_9630P 9 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_9630PL 10 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x14 */
#define MODEL_OP_9636P 11 /* 512k, 98001 ASIC, 36 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_A3I 12 /* 128k, 96003 ASIC, 30 bit, 400x800, 11.69x17 */
#define MODEL_OP_12000P 13 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_9636PP 14 /* 512k, 98001 ASIC, 36 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_9636T 15 /* like OP_9636PP + transparency */
#define MODEL_OP_P8 16 /* 512k, 98003 ASIC, 36 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_P12 17 /* 512k, 98003 ASIC, 36 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_PT12 18 /* like OP_P12 + transparency */
#define MODEL_GEN_CPV2 19 /* Genius Colorpage Vivid III V2, ASIC 98003 */
#define MODEL_UNKNOWN 20 /* not known/supported */
#define _NO_BASE 0xFFFF
/************************ some structures ************************************/
enum {
OPT_NUM_OPTS = 0,
OPT_MODE_GROUP,
OPT_MODE,
OPT_EXT_MODE,
OPT_RESOLUTION,
OPT_PREVIEW,
OPT_GEOMETRY_GROUP,
OPT_TL_X,
OPT_TL_Y,
OPT_BR_X,
OPT_BR_Y,
OPT_ENHANCEMENT_GROUP,
OPT_HALFTONE,
OPT_BRIGHTNESS,
OPT_CONTRAST,
OPT_CUSTOM_GAMMA,
OPT_GAMMA_VECTOR,
OPT_GAMMA_VECTOR_R,
OPT_GAMMA_VECTOR_G,
OPT_GAMMA_VECTOR_B,
NUM_OPTIONS
};
/** for compatiblity to version 0x0102 drivers
*/
typedef struct {
int lampOff;
int lampOffOnEnd;
int warmup;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
} CompatAdjDef, *pCompatAdjDef;
/** for adjusting the parport stuff
*/
typedef struct {
int lampOff;
int lampOffOnEnd;
int warmup;
int enableTpa;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
/* for adjusting the default gamma settings */
double rgamma;
double ggamma;
double bgamma;
double graygamma;
} PPAdjDef, *pPPAdjDef;
/** for adjusting the scanner settings
*/
typedef struct {
int direct_io;
int mov;
int lampOff;
int lampOffOnEnd;
int warmup;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
/* for adjusting the default gamma settings */
double rgamma;
double ggamma;
double bgamma;
double graygamma;
} AdjDef, *pAdjDef;
/**
*/
typedef struct Plustek_Device
{
SANE_Int initialized; /* device already initialized? */
struct Plustek_Device *next; /* pointer to next dev in list */
int fd; /* device handle */
char *name; /* (to avoid compiler warnings!)*/
SANE_Device sane; /* info struct */
SANE_Int max_x; /* max XY-extension of the scan-*/
SANE_Int max_y; /* area */
SANE_Range dpi_range; /* resolution range */
SANE_Range x_range; /* x-range of the scan-area */
SANE_Range y_range; /* y-range of the scan-area */
SANE_Int *res_list; /* to hold the available phys. */
SANE_Int res_list_size; /* resolution values */
ScannerCaps caps; /* caps reported by the driver */
AdjDef adj; /* for driver adjustment */
/*
* each device we support may need other access functions...
*/
int (*open) ( const char*, void* );
int (*close) ( struct Plustek_Device* );
void (*shutdown) ( struct Plustek_Device* );
int (*getCaps) ( struct Plustek_Device* );
int (*getLensInfo)( struct Plustek_Device*, pLensInfo );
int (*getCropInfo)( struct Plustek_Device*, pCropInfo );
int (*putImgInfo) ( struct Plustek_Device*, pImgDef );
int (*setScanEnv) ( struct Plustek_Device*, pScanInfo );
int (*setMap) ( struct Plustek_Device*, SANE_Word*,
SANE_Word, SANE_Word );
int (*startScan) ( struct Plustek_Device*, pStartScan );
int (*stopScan) ( struct Plustek_Device*, int* );
int (*readImage) ( struct Plustek_Device*, SANE_Byte*, unsigned long );
int (*prepare) ( struct Plustek_Device*, SANE_Byte* );
int (*readLine) ( struct Plustek_Device* );
} Plustek_Device, *pPlustek_Device;
#ifndef SANE_OPTION
/* for compatibility with older versions */
typedef union
{
SANE_Word w;
SANE_Word *wa; /* word array */
SANE_String s;
} Option_Value;
#endif
typedef struct Plustek_Scanner
{
struct Plustek_Scanner *next;
pid_t reader_pid; /* process id of reader */
SANE_Status exit_code; /* status of the reader process */
int pipe; /* pipe to reader process */
unsigned long bytes_read; /* number of bytes currently read*/
Plustek_Device *hw; /* pointer to current device */
Option_Value val[NUM_OPTIONS];
SANE_Byte *buf; /* the image buffer */
SANE_Bool scanning; /* TRUE during scan-process */
SANE_Parameters params; /* for keeping the parameter */
/************************** gamma tables *********************************/
SANE_Word gamma_table[4][4096];
SANE_Range gamma_range;
int gamma_length;
SANE_Option_Descriptor opt[NUM_OPTIONS];
} Plustek_Scanner, *pPlustek_Scanner;
/** for collecting configuration info...
*/
typedef struct {
char devName[PATH_MAX];
/* contains the stuff to adjust... */
AdjDef adj;
} CnfDef, *pCnfDef;
#endif /* guard __PLUSTEKPP_H__ */
/* END PLUSTEK-PP.H .........................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,79 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_dbg.h - definition of some debug macros
*.............................................................................
*
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
/* uncomment this to have an SW-simulatet 98001 device - don't expect to scan*/
/* #define _ASIC_98001_SIM */
/*
* the print macros
*/
#ifdef __KERNEL__
# define _PRINT printk
#endif
/*
* some debug definitions
*/
#ifdef DEBUG
# ifndef __KERNEL__
# include <assert.h>
# define _ASSERT(x) assert(x)
# endif
# ifndef DBG
# define DBG(level, msg, args...) if ((dbg_level) & (level)) { \
_PRINT(msg, ##args); \
}
# endif
#else
# define _ASSERT(x)
# ifndef DBG
# define DBG(level, msg, args...)
# endif
#endif
/* different debug level */
#define DBG_LOW 0x01
#define DBG_MEDIUM 0x02
#define DBG_HIGH 0x04
#define DBG_HELPERS 0x08
#define DBG_TIMEOUT 0x10
#define DBG_SCAN 0x20
#define DBG_IO 0x40
#define DBG_IOF 0x80
#define DBG_ALL 0xFF
/*
* standard debug level
*/
#ifdef DEBUG
static int dbg_level=(DBG_ALL & ~(DBG_IO | DBG_IOF));
#endif
#endif /* guard __DEBUG_H__ */
/* END PLUSTEK-PP_DBG.H .....................................................*/

Wyświetl plik

@ -0,0 +1,508 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_detect.c - automatic scanner detection
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - no changes
* 0.33 - added portmode check
* 0.34 - no changes
* 0.35 - no changes
* 0.36 - added some debug messages
* replace the old _OUTB/_INB macros
* 0.37 - cosmetic changes
* added speed-test for the parallel-port
* 0.38 - added P12 stuff - replaced detectP9636 by detectAsic9800x
* added detectResetPort() function
* 0.39 - fixed problem in ASIC9800x detection
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/************************** local definitions ********************************/
/*************************** local functions *********************************/
/*.............................................................................
* as the name says...
*/
static void detectResetPort( pScanData ps )
{
UChar control;
control = _INB_CTRL( ps );
_DO_UDELAY( 2 );
_OUTB_CTRL( ps, _CTRL_RESERVED ); /* reset, 0xc0 */
_DO_UDELAY( 2 );
_OUTB_CTRL( ps, control ); /* and restore... */
_DO_UDELAY( 2 );
}
/*.............................................................................
* Check will the status port changed between printer/scanner path changed?
* Write out data and read in to compare
*/
static int detectScannerConnection( pScanData ps )
{
UChar data, control, status;
int retval = _E_NO_CONN;
DBG( DBG_LOW, "Dataport = 0x%04x\n", ps->IO.pbSppDataPort );
DBG( DBG_LOW, "Ctrlport = 0x%04x\n", ps->IO.pbControlPort );
detectResetPort( ps );
/*
* as we´re called during InitPorts, we can be sure
* to operate in EPP-mode (hopefuly ;-)
*/
control = _INB_CTRL( ps );
/*
* go ahead and do some checks
*/
_OUTB_CTRL( ps, _CTRL_GENSIGNAL );
_DO_UDELAY( 5 );
_OUTB_DATA( ps, 0x55 );
_DO_UDELAY( 5 );
data = _INB_DATA( ps );
if (0x55 == data) {
DBG( DBG_HIGH, "Test 0x55\n" );
_OUTB_DATA( ps, 0xAA );
_DO_UDELAY( 5 );
data = _INB_DATA( ps );
if (0xAA == data) {
DBG( DBG_HIGH, "Test 0xAA\n" );
_OUTB_DATA( ps, 0x0 );
_DO_UDELAY( 5 );
data = _INB_STATUS( ps );
ps->OpenScanPath( ps );
_OUTB_DATA( ps, 0x0 );
_DO_UDELAY( 5 );
status = _INB_STATUS( ps );
ps->CloseScanPath( ps );
/*
* so we´re done ´til now...
*/
DBG( DBG_HIGH, "Compare data=0x%x and status=0x%x, port=0x%x\n",
data, status, ps->IO.portBase );
if( data != status ) {
_ASSERT( ps->ReadWriteTest );
/*
* here we try to detect the operation speed of our
* parallel port
* if we have tested all the stuff and had no success, retval
* will contain the error-code
*/
for( ps->IO.delay = 0; ps->IO.delay < 5; ps->IO.delay++ ) {
retval = ps->ReadWriteTest( ps );
/* break on OK or when the ASIC detection fails */
if((_OK == retval) || (_E_NO_ASIC == retval))
break;
}
}
}
}
/*
* work on the result
*/
if ( _OK == retval ) {
ps->sCaps.wIOBase = ps->IO.pbSppDataPort;
ps->PutToIdleMode( ps );
} else {
ps->sCaps.wIOBase = _NO_BASE;
}
/*
* restore control port value
*/
_OUTB_CTRL( ps, control );
_DO_UDELAY( 5 );
DBG( DBG_HIGH, "detectScannerConnection() returns %i.\n", retval );
return retval;
}
/*.............................................................................
* we need some memory...
*/
static int detectSetupBuffers( pScanData ps )
{
DBG( DBG_LOW, "*** setupBuffers ***\n" );
/*
* bad news ?
*/
if ( 0 == ps->TotalBufferRequire ) {
#ifdef __KERNEL__
_PRINT(
#else
DBG( DBG_HIGH,
#endif
"pt_drv: asic 0x%x probably not supported\n", ps->sCaps.AsicID);
return _E_ALLOC; /* Out of memory */
} else {
/*
* allocate and clear
*/
DBG(DBG_LOW,"Driverbuf(%lu bytes) needed !\n", ps->TotalBufferRequire);
ps->driverbuf = (pUChar)_VMALLOC(ps->TotalBufferRequire);
if ( NULL == ps->driverbuf ) {
#ifdef __KERNEL__
_PRINT(
#else
DBG( DBG_HIGH,
#endif
"pt_drv: Not enough kernel memory %ld\n",
ps->TotalBufferRequire);
return _E_ALLOC; /* Out of memory */
}
memset( ps->driverbuf, 0, ps->TotalBufferRequire );
}
ps->pPrescan16 = ps->driverbuf;
ps->pPrescan8 = ps->pPrescan16 + ps->BufferFor1stColor;
ps->pScanBuffer1 = ps->pPrescan8 + ps->BufferFor2ndColor;
/* CHECK: Should we adjust that !!!
*/
ps->pEndBufR = ps->pPrescan8;
ps->pEndBufG = ps->pScanBuffer1;
ps->pColorRunTable = ps->pScanBuffer1 + ps->BufferForDataRead1;
DBG( DBG_LOW, "pColorRunTab = 0x%0lx - 0x%0lx\n",
(ULong)ps->pColorRunTable,
(ULong)((pUChar)ps->driverbuf + ps->TotalBufferRequire));
if ( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
DBG( DBG_LOW, "Adjust for 98001 ASIC\n" );
ps->pScanBuffer2 = ps->pPrescan16;
ps->pScanBuffer1 = ps->pScanBuffer2 + _LINE_BUFSIZE1;
ps->pColorRunTable = ps->pScanBuffer1 + _LINE_BUFSIZE * 2UL;
ps->pProcessingBuf = ps->pColorRunTable + ps->BufferForColorRunTable;
DBG( DBG_LOW, "sb2 = 0x%lx, sb1 = 0x%lx, Color = 0x%lx\n",
(ULong)ps->pScanBuffer2, (ULong)ps->pScanBuffer1,
(ULong)ps->pColorRunTable );
DBG( DBG_LOW, "Pro = 0x%lx, size = %ld\n",
(ULong)ps->pProcessingBuf, ps->TotalBufferRequire );
ps->dwShadow = (_DEF_BRIGHTEST_SKIP + _DEF_DARKEST_SKIP) * 5400UL * 2UL * 3UL;
ps->Shade.pHilight = _VMALLOC( ps->dwShadow );
if ( NULL != ps->Shade.pHilight ) {
memset( ps->Shade.pHilight, 0, ps->dwShadow );
ps->dwHilight = _DEF_BRIGHTEST_SKIP * 5400UL * 3UL;
ps->dwShadow = _DEF_DARKEST_SKIP * 5400UL * 3UL;
ps->pwShadow = (pUShort)ps->Shade.pHilight + ps->dwHilight;
ps->Shade.dwDiv = 32UL - _DEF_BRIGHTEST_SKIP - _DEF_DARKEST_SKIP;
ps->dwHilightCh = ps->dwHilight / 3UL;
ps->dwShadowCh = ps->dwShadow / 3UL;
}
} else if ( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
DBG( DBG_LOW, "Adjust for 98003 ASIC\n" );
ps->Bufs.b1.pReadBuf = ps->driverbuf;
ps->Bufs.b2.pSumBuf = ps->Bufs.b1.pReadBuf + _SizeDataBuf;
ps->Bufs.TpaBuf.pb = &((pUChar)ps->Bufs.b2.pSumBuf)[_SizeShadingSumBuf];
/* CHECK: We might should play around with these values... */
ps->Shade.skipHilight = _DEF_BRIGHTEST_SKIP;
ps->Shade.skipShadow = _DEF_DARKEST_SKIP;
if( ps->Shade.skipHilight && ps->Shade.skipShadow ) {
ULong skipSize;
skipSize = (ULong)((ps->Shade.skipHilight + ps->Shade.skipShadow)
* _SizeDataBuf * 3);
ps->Shade.pHilight = _VMALLOC( skipSize );
if( NULL != ps->Shade.pHilight ) {
ps->Shade.dwDiv = (ULong)(32UL - ps->Shade.skipHilight -
ps->Shade.skipShadow);
}
} else
ps->Shade.pHilight = NULL;
}
return _OK;
}
/*.............................................................................
* model 48xx detection or any other model using the 96001/3 ASIC
*/
static int detectP48xx( pScanData ps )
{
int result;
DBG( DBG_LOW, "************ DETECTP48xx ************\n" );
/* increase the delay-time */
ps->IO.delay = 4;
ModelSet4800( ps );
result = P48xxInitAsic( ps );
if( _OK != result )
return result;
return detectScannerConnection( ps );
}
/*.............................................................................
* ASIC 98003 model detection
*/
static int detectAsic98003( pScanData ps )
{
int result;
DBG( DBG_LOW, "************* ASIC98003 *************\n" );
/* increase the delay-time */
ps->IO.delay = 4;
ModelSetP12( ps );
result = P12InitAsic( ps );
if( _OK != result )
return result;
IOSoftwareReset( ps );
return detectScannerConnection( ps );
}
/*.............................................................................
* ASIC 98001 model detection
*/
static int detectAsic98001( pScanData ps )
{
int result;
DBG( DBG_LOW, "************* ASIC98001 *************\n" );
/* increase the delay-time */
ps->IO.delay = 4;
ModelSet9636( ps );
result = P9636InitAsic( ps );
#ifndef _ASIC_98001_SIM
if( _OK != result )
return result;
return detectScannerConnection( ps );
#else
#ifdef __KERNEL__
_PRINT(
#else
DBG( DBG_HIGH,
#endif
"!!!! WARNING, have a look at function detectAsic98001() !!!!\n" );
ps->sCaps.AsicID = _ASIC_IS_98001;
ps->sCaps.wIOBase = ps->IO.pbSppDataPort;
return _OK;
#endif
}
/************************ exported functions *********************************/
/*.............................................................................
* here we try to find the scanner, depending on the mode
*/
int DetectScanner( pScanData ps, int mode )
{
Byte asic;
int result = _E_INTERNAL;
/*
* before doing anything else, check the port-mode
*/
if((ps->IO.portMode != _PORT_EPP) && (ps->IO.portMode != _PORT_SPP) &&
(ps->IO.portMode != _PORT_BIDI)) {
DBG( DBG_LOW, "!!! Portmode (%u)not supported !!!\n", ps->IO.portMode );
return _E_INTERNAL;
}
/*
* autodetection ?
*/
if( 0 == mode ) {
DBG( DBG_HIGH, "Starting Scanner-Autodetection\n" );
/*
* try to find a 48xx Scanner
* (or even a scanner based on the 96001/3) ASIC
*/
result = detectP48xx( ps );
if( _OK != result ) {
DBG( DBG_LOW, "************* ASIC9800x *************\n" );
/*
* get the ASIC ID by using the OpenScanPath stuff from Asic9600x based
* models - only difference: change the ReadHigh/ReadLow signals before
*/
ps->CtrlReadHighNibble = _CTRL_GENSIGNAL+_CTRL_AUTOLF+_CTRL_STROBE;
ps->CtrlReadLowNibble = _CTRL_GENSIGNAL+_CTRL_AUTOLF;
/* read Register 0x18 (AsicID Register) of Asic9800x based devices */
#ifdef _ASIC_98001_SIM
#ifdef __KERNEL__
_PRINT(
#else
DBG( DBG_HIGH,
#endif
"!!!! WARNING, SW-Emulation active !!!!\n" );
asic = _ASIC_IS_98001;
#else
detectResetPort( ps );
/* do some presettings to make IODataRegisterFromScanner() work */
ps->RegAsicID = 0x18;
ps->IO.useEPPCmdMode = _FALSE;
ps->sCaps.AsicID = _ASIC_IS_98001;
IOInitialize( ps );
asic = IODataRegisterFromScanner( ps, ps->RegAsicID );
DBG( DBG_HIGH, "ASIC = 0x%02X\n", asic );
#endif
/* depending on what we have found, perform some extra tests */
switch( asic ) {
case _ASIC_IS_98001:
result = detectAsic98001( ps );
break;
case _ASIC_IS_98003:
/* as the reading of the ASIC ID causes trouble,
* we reset the device
*/
ps->IO.useEPPCmdMode = _FALSE;
ps->sCaps.AsicID = _ASIC_IS_98003;
IOInitialize( ps );
IOSoftwareReset( ps );
result = detectAsic98003( ps );
break;
default:
DBG( DBG_HIGH, "Unknown ASIC-ID\n" );
result = _E_NO_DEV;
break;
}
}
} else {
/* this will be called each time before operating on a previously
* detected device, to make sure we're already operating on the same one
*/
if( _ASIC_IS_98001 == mode ) {
DBG( DBG_HIGH, "Starting Scanner-detection (ASIC 98001)\n" );
result = detectAsic98001( ps );
} else if( _ASIC_IS_98003 == mode ) {
DBG( DBG_HIGH, "Starting Scanner-detection (ASIC 98003)\n" );
result = detectAsic98003( ps );
} else {
DBG( DBG_HIGH, "Starting Scanner-detection (ASIC 96001/3)\n" );
result = detectP48xx( ps );
}
}
if( _OK == result ) {
_ASSERT( ps->SetupScannerVariables );
ps->SetupScannerVariables( ps );
detectSetupBuffers( ps );
} else {
/* CHECK - we should not need that anymore - paranoia code ??!!!!
*/
ps->sCaps.wIOBase = _NO_BASE;
}
DBG( DBG_LOW, "*** DETECTION DONE, result: %i ***\n", result );
return result;
}
/* END PLUSTEK-PP_DETECT.C ..................................................*/

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,980 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustekpp-io.c - as the name says, here we have all the I/O
* functions according to the parallel port hardware
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.37 - initial version
* added Kevins' suggestions
* 0.38 - added Asic 98003 stuff and ioP98ReadWriteTest()
* added IODataRegisterToDAC()
* replaced function IOSPPWrite by IOMoveDataToScanner
* modified ioP98OpenScanPath again and reuse V0.36 stuff again
* added IO functions
* 0.39 - added IO functions
* added f97003 stuff from A3I code
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/*************************** some prototypes *********************************/
static Bool fnEPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize );
static Bool fnSPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize );
static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize );
static pFnReadData ioReadFunc[3] = {
fnEPPRead,
fnSPPRead,
fnBiDirRead
};
/*************************** some definitions ********************************/
#define _MEMTEST_SIZE 1280
/*************************** local functions *********************************/
/*.............................................................................
* we provide some functions to read data from SPP port according to
* the speed we have detected (ReadWriteTest!!)
*/
static Byte ioDataFromSPPFast( pScanData ps )
{
Byte bData, tmp;
/* notify asic we will read the high nibble data from status port */
if( _FALSE == ps->f97003 ) {
_OUTB_CTRL( ps, ps->CtrlReadHighNibble );
_DO_UDELAY( 1 );
}
/* read high nibble */
bData = _INB_STATUS( ps );
bData &= 0xf0;
_OUTB_CTRL( ps, ps->CtrlReadLowNibble );
_DO_UDELAY( 1 );
/* read low nibble */
tmp = _INB_STATUS( ps );
/* combine with low nibble */
bData |= (tmp >> 4);
_OUTB_CTRL( ps, _CTRL_GENSIGNAL );
_DO_UDELAY( 1 );
return bData;
}
static Byte ioDataFromSPPMiddle( pScanData ps )
{
Byte bData, tmp;
/* notify asic we will read the high nibble data from status port */
if( _FALSE == ps->f97003 ) {
_OUTB_CTRL( ps, ps->CtrlReadHighNibble );
_DO_UDELAY( 1 );
}
/* read high nibble */
_INB_STATUS( ps );
bData = _INB_STATUS( ps );
bData &= 0xf0;
_OUTB_CTRL( ps, ps->CtrlReadLowNibble );
_DO_UDELAY( 1 );
/* read low nibble */
_INB_STATUS( ps );
tmp = _INB_STATUS( ps );
/* combine with low nibble */
bData |= (tmp >> 4);
_OUTB_CTRL( ps, _CTRL_GENSIGNAL );
_DO_UDELAY( 1 );
return bData;
}
static UChar ioDataFromSPPSlow( pScanData ps )
{
Byte bData, tmp;
/* notify asic we will read the high nibble data from status port */
if( _FALSE == ps->f97003 ) {
_OUTB_CTRL( ps, ps->CtrlReadHighNibble );
_DO_UDELAY( 2 );
}
/* read high nibble */
_INB_STATUS( ps );
_INB_STATUS( ps );
bData = _INB_STATUS( ps );
bData &= 0xf0;
_OUTB_CTRL( ps, ps->CtrlReadLowNibble );
_DO_UDELAY( 2 );
/* read low nibble */
_INB_STATUS( ps );
_INB_STATUS( ps );
tmp = _INB_STATUS( ps );
/* combine with low nibble */
bData |= (tmp >> 4);
_OUTB_CTRL( ps, _CTRL_GENSIGNAL );
_DO_UDELAY( 2 );
return bData;
}
static UChar ioDataFromSPPSlowest( pScanData ps )
{
Byte bData, tmp;
/* notify asic we will read the high nibble data from status port */
if( _FALSE == ps->f97003 ) {
_OUTB_CTRL( ps, ps->CtrlReadHighNibble );
_DO_UDELAY( 3 );
}
/* read high nibble */
_INB_STATUS( ps );
_INB_STATUS( ps );
_INB_STATUS( ps );
bData = _INB_STATUS( ps );
bData &= 0xf0;
_OUTB_CTRL( ps, ps->CtrlReadLowNibble );
_DO_UDELAY( 3 );
/* read low nibble */
_INB_STATUS( ps );
_INB_STATUS( ps );
_INB_STATUS( ps );
tmp = _INB_STATUS( ps );
/* combine with low nibble */
bData |= (tmp >> 4);
_OUTB_CTRL( ps, _CTRL_GENSIGNAL );
_DO_UDELAY( 3 );
return bData;
}
/*.............................................................................
* Using buffer I/O to read data from EPP Data Port
*/
static Bool fnEPPRead( pScanData ps, pUChar pBuffer, ULong ulSize )
{
register ULong i;
if( _IS_ASIC98(ps->sCaps.AsicID)) {
_OUTB_CTRL( ps, (_CTRL_GENSIGNAL + _CTRL_DIRECTION));
_DO_UDELAY( 1 );
for( i = 0; i < ulSize; i++ )
pBuffer[i] = _INB_EPPDATA( ps );
_OUTB_CTRL( ps, _CTRL_GENSIGNAL );
_DO_UDELAY( 1 );
} else {
for( i = 0; i < ulSize; i++ )
pBuffer[i] = _INB_EPPDATA( ps );
}
return _TRUE;
}
/*.............................................................................
* Read data from STATUS port. We have to read twice and combine two nibble
* data to one byte
*/
static Bool fnSPPRead( pScanData ps, pUChar pBuffer, ULong ulSize )
{
switch( ps->IO.delay ) {
case 0:
for (; ulSize; ulSize--, pBuffer++)
*pBuffer = ioDataFromSPPFast( ps );
break;
case 1:
for (; ulSize; ulSize--, pBuffer++)
*pBuffer = ioDataFromSPPMiddle( ps );
break;
case 2:
for (; ulSize; ulSize--, pBuffer++)
*pBuffer = ioDataFromSPPSlow( ps );
break;
default:
for (; ulSize; ulSize--, pBuffer++)
*pBuffer = ioDataFromSPPSlowest( ps );
break;
}
return _TRUE;
}
/*.............................................................................
*
*/
static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize )
{
if( _IS_ASIC98(ps->sCaps.AsicID))
_OUTB_CTRL( ps, (_CTRL_GENSIGNAL + _CTRL_DIRECTION));
switch( ps->IO.delay ) {
case 0:
for(; ulSize; ulSize--, pBuffer++ ) {
_OUTB_CTRL( ps, _CTRL_SIGNAL_BIDIREAD); /* 0xe6 */
*pBuffer = _INB_DATA( ps );
_OUTB_CTRL( ps, _CTRL_END_BIDIREAD ); /* 0xe4 */
}
break;
case 1:
_DO_UDELAY( 1 );
for(; ulSize; ulSize--, pBuffer++ ) {
_OUTB_CTRL( ps, _CTRL_SIGNAL_BIDIREAD); /* 0xe6 */
_DO_UDELAY( 1 );
*pBuffer = _INB_DATA( ps );
_OUTB_CTRL( ps, _CTRL_END_BIDIREAD ); /* 0xe4 */
_DO_UDELAY( 1 );
}
break;
default:
_DO_UDELAY( 2 );
for(; ulSize; ulSize--, pBuffer++ ) {
_OUTB_CTRL( ps, _CTRL_SIGNAL_BIDIREAD); /* 0xe6 */
_DO_UDELAY( 2 );
*pBuffer = _INB_DATA( ps );
_OUTB_CTRL( ps, _CTRL_END_BIDIREAD ); /* 0xe4 */
_DO_UDELAY( 2 );
}
break;
}
if( _IS_ASIC98(ps->sCaps.AsicID))
_OUTB_CTRL( ps, _CTRL_END_DATAREAD ); /* 0xc4 */
return _TRUE;
}
/*.............................................................................
* as the name says, we switch to SPP mode
*/
static void ioSwitchToSPPMode( pScanData ps )
{
/*
* save the control and data port value
*/
ps->IO.bOldControlValue = _INB_CTRL( ps );
ps->IO.bOldDataValue = _INB_DATA( ps );
_OUTB_CTRL( ps, _CTRL_NORMAL ); /* 0xc4 */
_DO_UDELAY( 2 );
}
/*.............................................................................
* restore the settings
*/
static void ioRestoreParallelMode( pScanData ps )
{
_OUTB_CTRL( ps, ps->IO.bOldControlValue & 0x3f );
_DO_UDELAY( 1 );
_OUTB_DATA( ps, ps->IO.bOldDataValue );
_DO_UDELAY( 1 );
}
/*.............................................................................
* try to connect to scanner
*/
static void ioP98001EstablishScannerConnection( pScanData, ULong );
inline void ioP98001EstablishScannerConnection( pScanData ps, ULong delTime )
{
_OUTB_DATA( ps, _ID_TO_PRINTER );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID1ST );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID2ND );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID3RD );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID4TH );
_DO_UDELAY( delTime );
}
/*.............................................................................
* switch the printer interface to scanner
*/
static Bool ioP96OpenScanPath( pScanData ps )
{
if( 0 == ps->IO.bOpenCount ) {
/* not established */
ioSwitchToSPPMode( ps );
/* Scanner command sequence to open scanner path */
ioP98001EstablishScannerConnection( ps, 5 );
}
#ifdef DEBUG
else
DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount );
#endif
ps->IO.bOpenCount++; /* increment the opened count */
/*
* CHECK to we really need that !!
*/
ps->IO.useEPPCmdMode = _FALSE;
return _TRUE;
}
static void ioP98003EstablishScannerConnection( pScanData ps, ULong delTime )
{
_OUTB_DATA( ps, _ID1ST );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID2ND );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID3RD );
_DO_UDELAY( delTime );
_OUTB_DATA( ps, _ID4TH );
_DO_UDELAY( delTime );
}
/*.............................................................................
* try to connect to scanner
*/
static Bool ioP98OpenScanPath( pScanData ps )
{
Byte tmp;
ULong dw;
ULong dwTime = 1;
if( 0 == ps->IO.bOpenCount ) {
/* not established */
ioSwitchToSPPMode( ps );
for( dw = 10; dw; dw-- ) {
/*
* this seems to be necessary...
*/
if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
ioP98001EstablishScannerConnection( ps, dw );
#if 0
ioP98001EstablishScannerConnection( ps, dw );
ioP98001EstablishScannerConnection( ps, dw );
#endif
} else {
ioP98003EstablishScannerConnection( ps, dw );
}
_INB_STATUS( ps );
tmp = _INB_STATUS( ps );
if( 0x50 == ( tmp & 0xf0 )) {
ps->IO.bOpenCount = 1;
if( ps->sCaps.AsicID == IODataFromRegister(ps, ps->RegAsicID)) {
return _TRUE;
}
ps->IO.bOpenCount = 0;
}
dwTime++;
}
DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" );
return _FALSE;
}
#ifdef DEBUG
else
DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount );
#endif
ps->IO.bOpenCount++; /* increment the opened count */
return _TRUE;
}
/*.............................................................................
* Switch back to printer mode
* Restore the printer control/data port value.
*/
static void ioCloseScanPath( pScanData ps )
{
if( ps->IO.bOpenCount && !(--ps->IO.bOpenCount)) {
#ifdef DEBUG
ps->IO.bOpenCount = 1;
#endif
IORegisterToScanner( ps, 0xff );
/*
* back to pass-through printer mode
*/
IORegisterToScanner( ps, ps->RegSwitchBus );
#ifdef DEBUG
ps->IO.bOpenCount = 0;
#endif
ps->IO.useEPPCmdMode = _FALSE;
ioRestoreParallelMode( ps );
}
}
/*.............................................................................
* check the memory to see that the data-transfers will work
* ASIC 9800x only
*/
static int ioP98ReadWriteTest( pScanData ps )
{
UChar tmp;
ULong ul;
pUChar buffer;
int retval;
DBG( DBG_LOW, "ioP98ReadWriteTest()\n" );
/* _MEMTEST_SIZE: Read, _MEMTEST_SIZE:Write */
buffer = _KALLOC( sizeof(UChar) * _MEMTEST_SIZE*2, GFP_KERNEL );
if( NULL == buffer )
return _E_ALLOC;
/* prepare content */
for( ul = 0; ul < _MEMTEST_SIZE; ul++ )
buffer[ul] = (UChar)ul;
ps->OpenScanPath(ps);
/* avoid switching to Lamp0, when previously scanned in transp./neg mode */
tmp = ps->bLastLampStatus + _SCAN_BYTEMODE;
IODataToRegister( ps, ps->RegScanControl, tmp );
IODataToRegister( ps, ps->RegModelControl, (_LED_ACTIVITY | _LED_CONTROL));
IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
IODataToRegister( ps, ps->RegMemoryLow, 0 );
IODataToRegister( ps, ps->RegMemoryHigh, 0 );
/* fill to buffer */
IOMoveDataToScanner( ps, buffer, 1280 );
IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
IODataToRegister( ps, ps->RegMemoryLow, 0 );
IODataToRegister( ps, ps->RegMemoryHigh, 0 );
IODataToRegister( ps, ps->RegWidthPixelsLow, 0 );
IODataToRegister( ps, ps->RegWidthPixelsHigh, 5 );
ps->AsicReg.RD_ModeControl = _ModeReadMappingMem;
if( _ASIC_IS_98001 == ps->sCaps.AsicID )
ps->CloseScanPath( ps );
IOReadScannerImageData( ps, buffer + _MEMTEST_SIZE, _MEMTEST_SIZE );
if( _ASIC_IS_98003 == ps->sCaps.AsicID )
ps->CloseScanPath( ps );
/*
* check the result !
*/
retval = _OK;
for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) {
if( buffer[ul] != buffer[ul+_MEMTEST_SIZE] ) {
DBG( DBG_HIGH, "Error in memory test at pos %lu (%u != %u)\n",
ul, buffer[ul], buffer[ul+_MEMTEST_SIZE] );
retval = _E_NO_DEV;
break;
}
}
_KFREE(buffer);
return retval;
}
/*.............................................................................
* Put data to DATA port and trigger hardware through CONTROL port to read it.
*/
static void ioSPPWrite( pScanData ps, pUChar pBuffer, ULong size )
{
DBG( DBG_IO , "IODELAY = %u\n", ps->IO.delay );
switch( ps->IO.delay ) {
case 0:
for (; size; size--, pBuffer++) {
_OUTB_DATA( ps, *pBuffer );
_OUTB_CTRL( ps, _CTRL_SIGNAL_DATAWRITE );
_OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
}
break;
case 1:
case 2:
for (; size; size--, pBuffer++) {
_OUTB_DATA( ps, *pBuffer );
_DO_UDELAY( 1 );
_OUTB_CTRL( ps, _CTRL_SIGNAL_DATAWRITE );
_DO_UDELAY( 1 );
_OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
_DO_UDELAY( 2 );
}
break;
default:
for (; size; size--, pBuffer++) {
_OUTB_DATA( ps, *pBuffer );
_DO_UDELAY( 1 );
_OUTB_CTRL( ps, _CTRL_SIGNAL_DATAWRITE );
_DO_UDELAY( 2 );
_OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
_DO_UDELAY( 3 );
}
break;
}
}
/*.............................................................................
*
*/
static void ioEnterReadMode( pScanData ps )
{
if( ps->IO.portMode != _PORT_SPP ) {
_DO_UDELAY( 1 );
IORegisterToScanner( ps, ps->RegEPPEnable );
if( _IS_ASIC98( ps->sCaps.AsicID ))
ps->IO.useEPPCmdMode = _TRUE;
}
if( _ASIC_IS_98003 == ps->sCaps.AsicID )
ps->IO.bOldControlValue = _INB_CTRL( ps );
/* ask ASIC to enter read mode */
IORegisterToScanner( ps, ps->RegReadDataMode );
}
/************************ exported functions *********************************/
/*.............................................................................
* here we do some init work
*/
int IOInitialize( pScanData ps )
{
DBG( DBG_HIGH, "IOInitialize()\n" );
if( NULL == ps )
return _E_NULLPTR;
if( _IS_ASIC98(ps->sCaps.AsicID)) {
ps->OpenScanPath = ioP98OpenScanPath;
ps->ReadWriteTest = ioP98ReadWriteTest;
} else if( _IS_ASIC96(ps->sCaps.AsicID)) {
ps->OpenScanPath = ioP96OpenScanPath;
} else {
DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
return _E_NOSUPP;
}
ps->CloseScanPath = ioCloseScanPath;
ps->Device.ReadData = ioReadFunc[ps->IO.portMode];
return _OK;
}
/*.............................................................................
* Write specific length buffer to scanner
* The scan path is already established
*/
void IOMoveDataToScanner( pScanData ps, pUChar pBuffer, ULong size )
{
#ifdef DEBUG
if( 0 == ps->IO.bOpenCount )
DBG( DBG_IO, "IOMoveDataToScanner - no connection!\n" );
#endif
IORegisterToScanner( ps, ps->RegInitDataFifo );
IORegisterToScanner( ps, ps->RegWriteDataMode );
ioSPPWrite( ps, pBuffer, size );
}
/*.............................................................................
* Calling SITUATION: Scanner path is established.
* download a scanstate-table
*/
void IODownloadScanStates( pScanData ps )
{
TimerDef timer;
#ifdef DEBUG
if( 0 == ps->IO.bOpenCount )
DBG( DBG_IO, "IODownloadScanStates - no connection!\n" );
#endif
IORegisterToScanner( ps, ps->RegScanStateControl );
ioSPPWrite( ps, ps->a_nbNewAdrPointer, _SCANSTATE_BYTES );
if( ps->Scan.fRefreshState ) {
IORegisterToScanner( ps, ps->RegRefreshScanState );
MiscStartTimer( &timer, (_SECOND/2));
do {
if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP))
break;
}
while( !MiscCheckTimer(&timer));
}
}
/*.............................................................................
* Calling SITUATION: Scanner path is established.
* Write a data to asic
*/
void IODataToScanner( pScanData ps, Byte bValue )
{
ULong deltime = 4;
#ifdef DEBUG
if( 0 == ps->IO.bOpenCount )
DBG( DBG_IO, "IODataToScanner - no connection!\n" );
#endif
if( ps->IO.delay < 2 )
deltime = 2;
/* output data */
_OUTB_DATA( ps, bValue );
_DO_UDELAY( deltime );
/* notify asic there is data */
_OUTB_CTRL( ps, _CTRL_SIGNAL_DATAWRITE );
_DO_UDELAY( deltime );
/* end write cycle */
_OUTB_CTRL( ps, _CTRL_END_DATAWRITE );
_DO_UDELAY( deltime-1 );
}
/*.............................................................................
* Calling SITUATION: Scanner path is established.
* Write a data to specific asic's register
*/
void IODataToRegister( pScanData ps, Byte bReg, Byte bData )
{
#ifdef DEBUG
if( 0 == ps->IO.bOpenCount )
DBG( DBG_IO, "IODataToRegister - no connection!\n" );
#endif
/* specify register */
IORegisterToScanner( ps, bReg );
/* then write the content */
IODataToScanner( ps, bData );
}
/*.............................................................................
* Calling SITUATION: Scanner path is established.
* Read the content of specific asic's register
*/
Byte IODataFromRegister( pScanData ps, Byte bReg )
{
IORegisterToScanner( ps, bReg );
if( 0 == ps->IO.delay )
return ioDataFromSPPFast( ps );
else if( 1 == ps->IO.delay )
return ioDataFromSPPMiddle( ps );
else if( 2 == ps->IO.delay )
return ioDataFromSPPSlow( ps );
else
return ioDataFromSPPSlowest( ps );
}
/*.............................................................................
* Calling SITUATION: Scanner path is established.
* Write a register to asic (used for a command without parameter)
*/
void IORegisterToScanner( pScanData ps, Byte bReg )
{
#ifdef DEBUG
if( 0 == ps->IO.bOpenCount )
DBG( DBG_IO, "IORegisterToScanner - no connection!\n" );
#endif
/*
* write data to port
*/
_OUTB_DATA( ps, bReg );
/*
* depending on the mode, generate the trigger signals
*/
if( ps->IO.useEPPCmdMode ) {
_DO_UDELAY( 5 );
_OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */
_DO_UDELAY( 5 );
_OUTB_CTRL( ps, _CTRL_EPPTRIG_REGWRITE);/* 0xcd */
_DO_UDELAY( 5 );
_OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */
_DO_UDELAY( 5 );
_OUTB_CTRL( ps, _CTRL_END_REGWRITE); /* 0xc4 */
} else {
if( ps->IO.delay < 2 ) {
_DO_UDELAY( 1 );
_OUTB_CTRL( ps, _CTRL_SIGNAL_REGWRITE);
_DO_UDELAY( 1 );
_OUTB_CTRL( ps, _CTRL_END_REGWRITE);
} else {
_DO_UDELAY( 2 );
_OUTB_CTRL( ps, _CTRL_SIGNAL_REGWRITE);
_DO_UDELAY( 2 );
_OUTB_CTRL( ps, _CTRL_END_REGWRITE);
_DO_UDELAY( 2 );
}
}
}
/*.............................................................................
* write data to the DAC - ASIC 98001/3 only
*/
void IODataRegisterToDAC( pScanData ps, Byte bReg, Byte bData )
{
ULong i;
IODataToRegister( ps, ps->RegADCAddress, bReg );
IODataToRegister( ps, ps->RegADCData, bData );
IODataToRegister( ps, ps->RegADCSerialOutStr, bData );
/* TEST: ORG was 1 ms for ASIC 98001 */
_DO_UDELAY( 12 );
for( i = 4; i; i-- ) {
_OUTB_CTRL( ps, _CTRL_SIGNAL_DATAWRITE );
_DO_UDELAY( 5 );
_OUTB_CTRL( ps, _CTRL_NORMAL );
_DO_UDELAY( 12 );
}
}
/*.............................................................................
* Calling SITUATION: Scanner path was not established.
* Read the content of specific asics' register
*/
Byte IODataRegisterFromScanner( pScanData ps, Byte bReg )
{
Byte bData;
ps->OpenScanPath( ps );
bData = IODataFromRegister( ps, bReg );
ps->CloseScanPath( ps );
return bData;
}
/*.............................................................................
* Calling SITUATION: Scanner path not established.
* Write a value of register to asic
*/
void IOCmdRegisterToScanner( pScanData ps, Byte bReg, Byte bData )
{
ps->OpenScanPath( ps );
IODataToRegister( ps, bReg, bData );
ps->CloseScanPath( ps );
}
/*.............................................................................
* Calling SITUATION: Scanner path not established.
* Write a register to asic (used for a command without parameter)
*/
void IORegisterDirectToScanner( pScanData ps, Byte bReg )
{
ps->OpenScanPath( ps ); /* establish the connection */
IORegisterToScanner( ps, bReg ); /* write register to asic */
ps->CloseScanPath( ps ); /* disconnect */
}
/*.............................................................................
* perform a SW reset of ASIC 98003 models
*/
void IOSoftwareReset( pScanData ps )
{
if( _ASIC_IS_98003 != ps->sCaps.AsicID )
return;
ps->OpenScanPath( ps );
IODataToRegister( ps, ps->RegTestMode, _SW_TESTMODE );
ioSwitchToSPPMode( ps );
_OUTB_DATA( ps, _RESET1ST );
_DODELAY( 5 );
_OUTB_DATA( ps, _RESET2ND );
_DODELAY( 5 );
_OUTB_DATA( ps, _RESET3RD );
_DODELAY( 5 );
_OUTB_DATA( ps, _RESET4TH );
_DODELAY( 5 );
ioRestoreParallelMode( ps );
/* reset test mode register */
IODataToRegister( ps, ps->RegTestMode, 0 );
IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
ps->CloseScanPath( ps );
}
/*.............................................................................
* Read specific length data from scanner and the method depends on the
* mode defined in registry.
*/
void IOReadScannerImageData( pScanData ps, pUChar pBuf, ULong size )
{
if( _ASIC_IS_98003 != ps->sCaps.AsicID )
ps->OpenScanPath( ps);
if( _IS_ASIC98( ps->sCaps.AsicID))
IODataToRegister(ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
/* enter read mode */
ioEnterReadMode( ps );
/* call corresponding read proc */
ps->Device.ReadData( ps, pBuf, size );
/* Clear EPP/ECP read mode by simplely close scanner path and re-open it */
ps->CloseScanPath( ps );
if( _ASIC_IS_98003 == ps->sCaps.AsicID )
ps->OpenScanPath( ps );
}
/*.............................................................................
* to program the ASIC 97003 on some scanner devices
*/
void IOFill97003Register( pScanData ps, Byte bDecode1, Byte bDecode2 )
{
IODataToRegister( ps, ps->RegWriteIOBusDecode2, bDecode2 );
IODataToRegister( ps, ps->RegWriteIOBusDecode1, bDecode1 );
}
/*.............................................................................
* the wrapper functions to support delayed and non-delayed I/O
*/
void IOOut( Byte data, UShort port )
{
DBG( DBG_IOF, "outb(0x%04x, 0x%02x)\n", port, data );
outb( data, port );
}
void IOOutDelayed( Byte data, UShort port )
{
DBG( DBG_IOF, "outb_p(0x%04x, 0x%02x)\n", port, data );
outb_p( data, port );
}
Byte IOIn( UShort port )
{
#ifdef DEBUG
Byte data = inb( port );
DBG( DBG_IOF, "inb(0x%04x) = 0x%02x\n", port, data );
return data;
#else
return inb( port );
#endif
}
Byte IOInDelayed( UShort port )
{
#ifdef DEBUG
Byte data = inb_p( port );
DBG( DBG_IOF, "inb_p(0x%04x) = 0x%02x\n", port, data );
return data;
#else
return inb_p( port );
#endif
}
/* END PLUSTEK-PP_IO.C ......................................................*/

Wyświetl plik

@ -0,0 +1,286 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_map.c - functions to create and manipulate
* lookup tables.
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - brightness and contrast is working (see mapAdjust)
* 0.32 - no changes
* 0.33 - disabled a few functions
* 0.34 - added new dither matrix for checking
* 0.35 - no changes
* 0.36 - activated Dithermap 1
* removed some unused functions
* added additional SCANDEF_Inverse check to MapSetupDither()
* fixed the double inversion bug, the map always compensates
* the scanner hw-settings
* 0.37 - code cleanup
* 0.38 - added P12 stuff
* 0.39 - no changes
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - made MapAdjust global
* changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/*************************** local vars **************************************/
/*WORK:
* create other thresholds for the dither maps
*/
static Byte mapDitherMatrix0[_DITHERSIZE] =
{
0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21
};
static Byte mapDitherMatrix1[_DITHERSIZE] =
{
2, 60, 16, 56, 3, 57, 13, 53,
34, 18, 48, 32, 35, 19, 45, 29,
10, 50, 6, 63, 11, 51, 7, 61,
42, 26, 38, 22, 43, 27, 39, 23,
4, 58, 14, 54, 1, 59, 15, 55,
36, 20, 46, 30, 33, 17, 47, 31,
12, 52, 8, 62, 9, 49, 5, 63,
44, 28, 40, 24, 41, 25, 37, 21
};
/*************************** local functions *********************************/
/** set the selected dither maps...
*/
static void mapSetDitherMap( pScanData ps )
{
ULong i;
pUChar pDitherSource;
pUChar pDither = ps->a_bDitherPattern;
if( 0 == ps->DataInf.wDither ) {
DBG( DBG_LOW, "Using Dithermatrix 0\n" );
pDitherSource = mapDitherMatrix0;
} else {
DBG( DBG_LOW, "Using Dithermatrix 1\n" );
pDitherSource = mapDitherMatrix1;
}
for( i = 0; i < _DITHERSIZE; i++ ) {
pDither[i] = pDitherSource[i];
}
}
/** nothing more to say
*/
static void mapInvertMap( pScanData ps )
{
pULong pdw;
ULong dw, size;
DBG( DBG_LOW, "mapInvertMap()\n" );
if( _IS_ASIC98(ps->sCaps.AsicID)) {
size = 4096;
} else {
size = 256;
}
for (pdw = (pULong)ps->a_bMapTable, dw = size * 3 / 4; dw; dw--, pdw++) {
*pdw = ~(*pdw);
}
}
/** as the name says...
*/
static void mapInvertDitherMap( pScanData ps )
{
if( ps->DataInf.dwScanFlag & SCANDEF_Inverse ) {
ULong dw;
pULong pDither = (pULong)ps->a_bDitherPattern;
DBG( DBG_LOW, "mapInvertDitherMap()\n" );
mapInvertMap( ps );
for (dw = 0; dw < 16; dw++) {
pDither[dw] = ~pDither[dw];
}
}
}
/** build linear map...
*/
static void mapBuildLinearMap( pScanData ps )
{
ULong i;
DBG( DBG_LOW, "mapBuildLinearMap()\n" );
if( _IS_ASIC98(ps->sCaps.AsicID)) {
for( i = 0; i < 4096; i++ ) {
ps->a_bMapTable[i] = (UChar)(i >> 4);
ps->a_bMapTable[4096+i] = (UChar)(i >> 4);
ps->a_bMapTable[8192+i] = (UChar)(i >> 4);
}
} else {
for( i = 0; i < 256; i++ ) {
ps->a_bMapTable[i] = (UChar)(i & 0xff);
ps->a_bMapTable[256+i] = (UChar)(i & 0xff);
ps->a_bMapTable[512+i] = (UChar)(i & 0xff);
}
}
}
/************************ exported functions *********************************/
/** create a mapping table
* in the original code this map will be created by the TWAIN application
* and the is being downloaded to the driver, as I don't have the code
* we have to try to build up such a table here
*/
void MapInitialize( pScanData ps )
{
mapBuildLinearMap( ps );
MapAdjust( ps, _MAP_MASTER );
}
/** setup dither maps
*/
void MapSetupDither( pScanData ps )
{
DBG( DBG_LOW, "MapSetupDither() - %u\n", ps->DataInf.wAppDataType );
if( COLOR_HALFTONE == ps->DataInf.wAppDataType ) {
mapSetDitherMap( ps );
if (ps->DataInf.dwScanFlag & SCANDEF_Inverse)
mapInvertDitherMap( ps );
}
}
/** adjust acording to brightness and contrast
*/
void MapAdjust( pScanData ps, int which )
{
ULong i, tabLen;
pULong pdw;
double b, c, dw, tmp;
DBG( DBG_LOW, "MapAdjust(%u)\n", which );
if( _IS_ASIC98(ps->sCaps.AsicID)) {
tabLen = 4096;
} else {
tabLen = 256;
}
/*
* adjust brightness (b) and contrast (c) using the function:
*
* s´(x,y) = (s(x,y) + b) * c
* b = [-127, 127]
* c = [0,2]
*/
/*
* scale brightness and contrast...
*/
b = ((double)ps->wBrightness * 192.0)/100.0;
c = ((double)ps->wContrast + 100.0)/100.0;
DBG( DBG_LOW, "brightness = %i -> %i\n", ps->wBrightness, (UChar)b);
DBG( DBG_LOW, "contrast*100 = %i -> %i\n", ps->wContrast, (int)(c*100));
for( i = 0; i < tabLen; i++ ) {
if((_MAP_MASTER == which) || (_MAP_RED == which)) {
tmp = ((double)(ps->a_bMapTable[i] + b)) * c;
if( tmp < 0 ) tmp = 0;
if( tmp > 255 ) tmp = 255;
ps->a_bMapTable[i] = (UChar)tmp;
}
if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
tmp = ((double)(ps->a_bMapTable[tabLen+i] + b)) * c;
if( tmp < 0 ) tmp = 0;
if( tmp > 255 ) tmp = 255;
ps->a_bMapTable[tabLen+i] = (UChar)tmp;
}
if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
tmp = ((double)(ps->a_bMapTable[tabLen*2+i] + b)) * c;
if( tmp < 0 ) tmp = 0;
if( tmp > 255 ) tmp = 255;
ps->a_bMapTable[tabLen*2+i] = (UChar)tmp;
}
}
if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) {
DBG( DBG_LOW, "inverting...\n" );
if((_MAP_MASTER == which) || (_MAP_RED == which)) {
DBG( DBG_LOW, "inverting RED map\n" );
pdw = (pULong)ps->a_bMapTable;
for( dw = tabLen / 4; dw; dw--, pdw++ )
*pdw = ~(*pdw);
}
if((_MAP_MASTER == which) || (_MAP_GREEN == which)) {
DBG( DBG_LOW, "inverting GREEN map\n" );
pdw = (pULong)&ps->a_bMapTable[tabLen];
for( dw = tabLen / 4; dw; dw--, pdw++ )
*pdw = ~(*pdw);
}
if((_MAP_MASTER == which) || (_MAP_BLUE == which)) {
DBG( DBG_LOW, "inverting BLUE map\n" );
pdw = (pULong)&ps->a_bMapTable[tabLen*2];
for( dw = tabLen / 4; dw; dw--, pdw++ )
*pdw = ~(*pdw);
}
}
}
/* END PLUSTEK-PP_MAP.C .....................................................*/

Wyświetl plik

@ -0,0 +1,938 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_misc.c - here we have some helpful functions
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - moved the parport functions inside this module
* now using the information, the parport-driver provides
* for selecting the port-mode this driver uses
* 0.33 - added code to use faster portmodes
* 0.34 - added sample code for changing from ECP to PS/2 bidi mode
* 0.35 - added Kevins´ changes (new function miscSetFastMode())
* moved function initPageSettings() to module models.c
* 0.36 - added random generator
* added additional debug messages
* changed prototype of MiscInitPorts()
* added miscPreemptionCallback()
* 0.37 - changed inb_p/outb_p to macro calls (kernel-mode)
* added MiscGetModelName()
* added miscShowPortModes()
* 0.38 - fixed a small bug in MiscGetModelName()
* 0.39 - added forceMode support
* 0.40 - no changes
* 0.41 - merged Kevins' patch to make EPP(ECP) work
* 0.42 - changed get_fast_time to _GET_TIME
* changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/*************************** some definitions ********************************/
#ifndef __KERNEL__
#define PPA_PROBE_SPP 0x0001
#define PPA_PROBE_PS2 0x0002
#define PPA_PROBE_ECR 0x0010
#define PPA_PROBE_EPP17 0x0100
#define PPA_PROBE_EPP19 0x0200
#else
/*
* the parport driver in Kernel 2.4 has changed. It does report the
* possible modes in a different, more general way. As long, as
* we do not use the parport-module change mode facility, I assume
* the following correlations
*/
#if defined LINUX_24 || defined LINUX_26
# define PARPORT_MODE_PCPS2 PARPORT_MODE_TRISTATE
# define PARPORT_MODE_PCEPP PARPORT_MODE_EPP
# define PARPORT_MODE_PCECPPS2 PARPORT_MODE_TRISTATE
# define PARPORT_MODE_PCECPEPP PARPORT_MODE_EPP
# define PARPORT_MODE_PCECR PARPORT_MODE_ECP
#endif
#endif
#define _A 16807 /* multiplier */
#define _M 2147483647L /* 2**31 - 1 */
#define _Q 127773L /* m div a */
#define _R 2836 /* m mod a */
/*************************** some local vars *********************************/
static int port_feature;
static long randomnum = 1;
static int portIsClaimed[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 0 };
#ifdef __KERNEL__
MODELSTR; /* is a static char array (see plustek-share.h) */
#endif
/*************************** local functions *********************************/
/** display the avaialable port-modes
*/
#ifdef DEBUG
static void miscShowPortModes( int modes )
{
DBG( DBG_LOW, "parport-modi:" );
#ifdef __KERNEL__
if( modes & PARPORT_MODE_PCSPP )
DBG( DBG_LOW, " SPP" );
if( modes & PARPORT_MODE_PCPS2 )
DBG( DBG_LOW, " PS/2" );
if( modes & PARPORT_MODE_PCEPP )
DBG( DBG_LOW, " EPP" );
if( modes & PARPORT_MODE_PCECR )
DBG( DBG_LOW, " ECP" );
if( modes & PARPORT_MODE_PCECPEPP )
DBG( DBG_LOW, " EPP(ECP)" );
if( modes & PARPORT_MODE_PCECPPS2 )
DBG( DBG_LOW, " PS/2(ECP)" );
#else
if( modes & PPA_PROBE_SPP )
DBG( DBG_LOW, " SPP" );
if( modes & PPA_PROBE_PS2 )
DBG( DBG_LOW, " PS/2" );
if( modes & PPA_PROBE_EPP17 )
DBG( DBG_LOW, " EPP17" );
if( modes & PPA_PROBE_EPP19 )
DBG( DBG_LOW, " EPP19" );
if( modes & PPA_PROBE_ECR )
DBG( DBG_LOW, " ECP" );
#endif
DBG( DBG_LOW, "\n" );
}
#endif
/** probe the parallel port
*/
static int initPortProbe( pScanData ps )
{
int retv = 0;
#ifndef __KERNEL__
UShort port;
UChar a, b, c;
UInt i, j;
#endif
/*
* clear the controls
*/
ps->IO.lastPortMode = 0xFFFF;
#ifdef __KERNEL__
if( NULL != ps->pardev )
retv = ps->pardev->port->modes;
#else
port = ps->IO.portBase;
DBG(DBG_SCAN, "Probing port 0x%04x\n", port);
/* ##### ###### ######
* # # # # # #
* # # # # #
* ##### ###### ######
* # # #
* # # # #
* ##### # #
*/
outb(0x0c, port + 0x402);
outb(0x0c, port + 0x002);
outb(0x55, port);
a = inb(port);
if (a != 0x55)
return retv;
DBG(DBG_SCAN, " SPP port present\n");
retv += PPA_PROBE_SPP;
/* ####### ##### ######
* # # # # #
* # # # #
* ##### # ######
* # # #
* # # # #
* ####### ##### #
*/
for (i = 1024; i > 0; i--) { /* clear at most 1k of data from FIFO */
a = inb(port + 0x402);
if ((a & 0x03) == 0x03)
goto no_ecp;
if (a & 0x01)
break;
inb(port + 0x400); /* Remove byte from FIFO */
}
if (i <= 0)
goto no_ecp;
b = a ^ 3;
outb(b, port + 0x402);
c = inb(port + 0x402);
if (a == c) {
outb(0xc0, port + 0x402); /* FIFO test */
j = 0;
while (!(inb(port + 0x402) & 0x01) && (j < 1024)) {
inb(port + 0x400);
j++;
}
if (j >= 1024)
goto no_ecp;
i = 0;
j = 0;
while (!(inb(port + 0x402) & 0x02) && (j < 1024)) {
outb(0x00, port + 0x400);
i++;
j++;
}
if (j >= 1024)
goto no_ecp;
j = 0;
while (!(inb(port + 0x402) & 0x01) && (j < 1024)) {
inb(port + 0x400);
j++;
}
if (j >= 1024)
goto no_ecp;
DBG(DBG_SCAN, " ECP with a %i byte FIFO present\n", i);
retv += PPA_PROBE_ECR;
}
/* ###### ##### #####
* # # # # # #
* # # # #
* ###### ##### #####
* # # #
* # # # #
* # ##### #######
*/
no_ecp:
if (retv & PPA_PROBE_ECR)
outb(0x20, port + 0x402);
outb(0x55, port);
outb(0x0c, port + 2);
a = inb(port);
outb(0x55, port);
outb(0x2c, port + 2);
b = inb(port);
if (a != b) {
DBG(DBG_SCAN, " PS/2 bidirectional port present\n");
retv += PPA_PROBE_PS2;
}
/* ####### ###### ######
* # # # # #
* # # # # #
* ##### ###### ######
* # # #
* # # #
* ####### # #
*/
if (port & 0x007) {
DBG(DBG_SCAN, " EPP not supported at this address\n");
return retv;
}
if (retv & PPA_PROBE_ECR) {
for (i = 0x00; i < 0x80; i += 0x20) {
outb(i, port + 0x402);
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
a = inb(port + 1);
if (!(a & 0x01)) {
DBG(DBG_SCAN, " Failed Intel bug check. (Phony EPP in ECP)\n");
return retv;
}
}
DBG(DBG_SCAN, " Passed Intel bug check.\n");
outb(0x80, port + 0x402);
}
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
a = inb(port + 1);
if (a & 0x01) {
outb(0x0c, port + 0x402);
outb(0x0c, port + 0x002);
return retv;
}
outb(0x04, port + 2);
inb(port + 4);
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
if (a & 0x01) {
DBG(DBG_SCAN, " EPP 1.9 with hardware direction protocol\n");
retv += PPA_PROBE_EPP19;
} else {
/* The EPP timeout bit was not set, this could either be:
* EPP 1.7
* EPP 1.9 with software direction
*/
outb(0x24, port + 2);
inb(port + 4);
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
if (a & 0x01) {
DBG(DBG_SCAN, " EPP 1.9 with software direction protocol\n");
retv += PPA_PROBE_EPP19;
} else {
DBG(DBG_SCAN, " EPP 1.7\n");
retv += PPA_PROBE_EPP17;
}
}
outb(0x0c, port + 0x402);
outb(0x0c, port + 0x002);
#endif
return retv;
}
#ifdef __KERNEL__
/** will be called by the parport module when we already have access, but
* another module wants access to the port...
*/
static int miscPreemptionCallback( pVoid data )
{
pScanData ps = (pScanData)data;
if( NULL != ps ) {
/* never release during scanning */
if( ps->DataInf.dwScanFlag & _SCANNER_SCANNING ) {
DBG( DBG_LOW, "no way!!!\n" );
return 1;
}
}
/* let the port go...*/
return 0;
}
/** depending on the reported possible port modes, we try to set a faster mode
* than SPP
*/
static int miscSetFastMode( pScanData ps )
{
UChar a, b;
/*
* when previously found the EPP mode, break right here
*/
if (( _PORT_EPP == ps->IO.portMode ) && (!(port_feature & PARPORT_MODE_PCECR)))
return _OK;
/* CHECK REMOVE: from here we should have SPP (Paranoia Code !) */
if (( _PORT_SPP != ps->IO.portMode ) && (!(port_feature & PARPORT_MODE_PCECR)))
return _OK;
DBG(DBG_LOW, "Trying faster mode...\n" );
/*
* ECP mode usually has sub-modes of EPP and/or PS2.
* First we try to set EPP
*/
if((port_feature & PARPORT_MODE_PCECR) &&
(port_feature & PARPORT_MODE_PCECPEPP)){
DBG(DBG_LOW, "Attempting to set EPP from ECP mode.\n" );
a = _INB_ECTL(ps); /* get current ECR */
ps->IO.lastPortMode = a; /* save it for restoring later */
a = (a & 0x1F) | 0x80; /* set to EPP */
_OUTB_ECTL(ps, a); /* write it back */
_DO_UDELAY(1);
/*
* It is probably unnecessary to
* do this check but it makes me feel better
*/
b = _INB_ECTL(ps); /* check to see if port set */
if( a == b ) {
DBG( DBG_LOW, "Port is set to (ECP) EPP mode.\n" );
ps->IO.portMode = _PORT_EPP;
return _OK;
} else {
DBG( DBG_LOW, "Port could not be set to (ECP) EPP mode. "
"Using SPP mode.\n" );
_OUTB_ECTL(ps,(Byte)ps->IO.lastPortMode); /* restore */
_DO_UDELAY(1);
ps->IO.portMode = _PORT_SPP;
/* go ahead and try with other settings...*/
}
}
/* If port cannot be set to EPP, try PS2 */
if((port_feature & PARPORT_MODE_PCECR) &&
(port_feature & PARPORT_MODE_PCECPPS2)) {
DBG(DBG_LOW, "Attempting to set PS2 from ECPPS2 mode.\n" );
a = _INB_ECTL(ps); /* get current ECR */
ps->IO.lastPortMode = a; /* save it for restoring later */
/* set to Fast Centronics/bi-directional/PS2 */
a = (a & 0x1F) | 0x20;
_OUTB_ECTL(ps,a); /* write it back */
_DO_UDELAY(1);
/*
* It is probably unnecessary to do this check
* but it makes me feel better
*/
b = _INB_ECTL(ps); /* check to see if port set */
if (a == b) {
DBG(DBG_LOW, "Port is set to (ECP) PS2 bidirectional mode.\n");
ps->IO.portMode = _PORT_BIDI;
return _OK;
} else {
DBG(DBG_LOW, "Port could not be set to (ECP) PS2 mode. "
"Using SPP mode.\n");
_OUTB_ECTL(ps,ps->IO.lastPortMode); /* restore */
_DO_UDELAY(1);
ps->IO.portMode = _PORT_SPP;
/* next mode, last attempt... */
}
}
/*
* Some BIOS/cards have only a Bi-directional/PS2 mode (no EPP).
* Make one last attemp to set to PS2 mode.
*/
if ( port_feature & PARPORT_MODE_PCPS2 ){
DBG(DBG_LOW, "Attempting to set PS2 mode.\n" );
a = _INB_CTRL(ps); /* get current setting of control register*/
ps->IO.lastPortMode = a; /* save it for restoring later */
a = a | 0x20; /* set bit 5 of control reg */
_OUTB_CTRL(ps,a); /* set to Fast Centronics/bi-directional/PS2 */
_DO_UDELAY(1);
a = 0;
_OUTB_DATA(ps,0x55);
_DO_UDELAY(1);
if ((inb(ps->IO.portBase)) != 0x55) /* read data */
a++;
_OUTB_DATA(ps,0xAA);
_DO_UDELAY(1);
if (_INB_DATA(ps) != 0xAA) /* read data */
a++;
if (2 == a) {
DBG(DBG_LOW, "Port is set to PS2 bidirectional mode.\n");
ps->IO.portMode = _PORT_BIDI;
return _OK;
}
else {
DBG(DBG_LOW, "Port could not be set to PS2 mode. "
"Using SPP mode.\n");
_OUTB_CTRL(ps,(Byte)ps->IO.lastPortMode); /* restore */
_DO_UDELAY(1);
ps->IO.portMode = _PORT_SPP;
}
}
/*
* reaching this point, we´re back in SPP mode and there´s no need
* to restore at shutdown...
*/
ps->IO.lastPortMode = 0xFFFF;
return _OK;
}
#endif
/** check the state of the par-port and switch to EPP-mode if possible
*/
static int miscSetPortMode( pScanData ps )
{
#ifndef __KERNEL__
if (iopl(3)) {
DBG( DBG_HIGH, "Could not unlock IO ports. Are you superuser?\n" );
return _E_LOCK;
}
#endif
/*
* try to detect the port settings, SPP seems to work in any case !
*/
port_feature = initPortProbe( ps );
#ifdef DEBUG
miscShowPortModes( port_feature );
#endif
switch( ps->IO.forceMode ) {
case 1:
DBG( DBG_LOW, "Use of SPP-mode enforced\n" );
ps->IO.portMode = _PORT_SPP;
return _OK;
break;
case 2:
DBG( DBG_LOW, "Use of EPP-mode enforced\n" );
ps->IO.portMode = _PORT_EPP;
return _OK;
break;
default:
break;
}
#ifdef __KERNEL__
if( !(port_feature & PARPORT_MODE_PCEPP)) {
if( !(port_feature & PARPORT_MODE_PCSPP )) {
_PRINT("\nThis Port supports not the SPP- or EPP-Mode\n" );
_PRINT("Please activate SPP-Mode, EPP-Mode or\nEPP + ECP-Mode!\n");
return _E_NOSUPP;
} else {
DBG(DBG_LOW, "Using SPP-mode\n" );
ps->IO.portMode = _PORT_SPP;
}
#else
if (!(port_feature & (PPA_PROBE_EPP17 | PPA_PROBE_EPP19))){
if( !(port_feature & PPA_PROBE_SPP )) {
DBG(DBG_HIGH,"\nThis Port supports not the SPP- or EPP-Mode\n");
DBG(DBG_HIGH,"Please activate SPP-Mode, EPP-Mode or\n"
"EPP + ECP-Mode!\n");
return _E_NOSUPP;
} else {
DBG(DBG_LOW, "Using SPP-mode\n" );
ps->IO.portMode = _PORT_SPP;
}
#endif
} else {
DBG(DBG_LOW, "Using EPP-mode\n" );
ps->IO.portMode = _PORT_EPP;
}
#ifdef __KERNEL__
/* else try to set to a faster mode than SPP */
return miscSetFastMode( ps );
#else
return _OK;
#endif
}
/** miscNextLongRand() -- generate 2**31-2 random numbers
**
** public domain by Ray Gardner
**
** based on "Random Number Generators: Good Ones Are Hard to Find",
** S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988),
** and "Two Fast Implementations of the 'Minimal Standard' Random
** Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88
**
** linear congruential generator f(z) = 16807 z mod (2 ** 31 - 1)
**
** uses L. Schrage's method to avoid overflow problems
*/
static Long miscNextLongRand( Long seed )
{
ULong lo, hi;
lo = _A * (Long)(seed & 0xFFFF);
hi = _A * (Long)((ULong)seed >> 16);
lo += (hi & 0x7FFF) << 16;
if (lo > _M) {
lo &= _M;
++lo;
}
lo += hi >> 15;
if (lo > _M) {
lo &= _M;
++lo;
}
return (Long)lo;
}
/** initialize the random number generator
*/
static void miscSeedLongRand( ULong seed )
{
randomnum = seed ? (seed & _M) : 1; /* nonzero seed */
}
/************************ exported functions *********************************/
/** allocate and initialize some memory for the scanner structure
*/
pScanData MiscAllocAndInitStruct( void )
{
pScanData ps;
ps = (pScanData)_KALLOC(sizeof(ScanData), GFP_KERNEL);
if( NULL != ps ) {
MiscReinitStruct( ps );
}
DBG( DBG_HIGH, "ScanData = 0x%08lx\n", (ULong)ps );
return ps;
}
/** re-initialize the memory for the scanner structure
*/
int MiscReinitStruct( pScanData ps )
{
if( NULL == ps )
return _E_NULLPTR;
memset( ps, 0, sizeof(ScanData));
/*
* first init all constant stuff in ScanData
*/
ps->sCaps.Version = ((_PTDRV_V1 << 8) | _PTDRV_V0);
ps->bCurrentSpeed = 1;
ps->sCaps.wLens = 1; /* set wNumberOfLens */
ps->pbMapRed = ps->a_bMapTable;
ps->pbMapGreen = &ps->a_bMapTable[256];
ps->pbMapBlue = &ps->a_bMapTable[512];
ps->sCaps.wIOBase = _NO_BASE;
/* use memory address to seed the generator */
miscSeedLongRand((Long)ps);
DBG( DBG_HIGH, "Init settings done\n" );
return _OK;
}
/** in USER-Mode: probe the specified port and try to get the port-mode
* in KERNEL-Mode: only use the modes, the driver returns
*/
int MiscInitPorts( pScanData ps, int port )
{
int status;
if( NULL == ps )
return _E_NULLPTR;
/*
* Get access to the ports
*/
ps->IO.portBase = (UShort)port;
status = miscSetPortMode(ps);
if( _OK != status ) {
ps->sCaps.wIOBase = _NO_BASE;
ps->IO.portBase = _NO_BASE;
return status;
}
/*
* the port settings
*/
ps->IO.pbSppDataPort = (UShort)port;
ps->IO.pbStatusPort = (UShort)port+1;
ps->IO.pbControlPort = (UShort)port+2;
ps->IO.pbEppDataPort = (UShort)port+_EPPDATA_PORT;
return _OK;
}
/** here we restore the port
*/
void MiscRestorePort( pScanData ps )
{
if( 0 == ps->IO.pbSppDataPort )
return;
DBG(DBG_LOW,"MiscRestorePort()\n");
/* don´t restore if not necessary */
if( 0xFFFF == ps->IO.lastPortMode ) {
DBG(DBG_LOW,"- no need to restore portmode !\n");
return;
}
/*Restore Port-Mode*/
#ifdef __KERNEL__
if (port_feature & PARPORT_MODE_PCECR ){
_OUTB_ECTL( ps, (Byte)ps->IO.lastPortMode );
_DO_UDELAY(1);
} else {
_OUTB_CTRL( ps, (Byte)ps->IO.lastPortMode );
_DO_UDELAY(1);
}
#else
if (port_feature & PPA_PROBE_ECR ){
outb( ps->IO.lastPortMode, ps->IO.pbSppDataPort + 0x402);
}
#endif
}
/** starts a timer
*/
inline void MiscStartTimer( pTimerDef timer , unsigned long us)
{
struct timeval start_time;
#ifdef __KERNEL__
_GET_TIME( &start_time );
#else
gettimeofday(&start_time, NULL);
#endif
*timer = start_time.tv_sec * 1e6 + start_time.tv_usec + us;
}
/** checks for timeout
*/
inline int MiscCheckTimer( pTimerDef timer )
{
struct timeval current_time;
#ifdef __KERNEL__
_GET_TIME( &current_time );
#else
gettimeofday(&current_time, NULL);
#endif
if (current_time.tv_sec * 1e6 + current_time.tv_usec > *timer) {
return _E_TIMEOUT;
} else {
#ifdef __KERNEL__
schedule();
#else
sched_yield();
#endif
return _OK;
}
}
/** checks the function pointers
*/
#ifdef DEBUG
Bool MiscAllPointersSet( pScanData ps )
{
ULong i;
pULong ptr;
for( ptr = (pULong)&ps->OpenScanPath, i = 1;
ptr <= (pULong)&ps->ReadOneImageLine; ptr++, i++ ) {
if( NULL == (pVoid)*ptr ) {
DBG( DBG_HIGH, "Function pointer not set (pos = %lu) !\n", i );
return _FALSE;
}
}
return _TRUE;
}
#endif
/** registers this driver to use port "portAddr" (KERNEL-Mode only)
*/
int MiscRegisterPort( pScanData ps, int portAddr )
{
#ifndef __KERNEL__
int i;
Bool found;
ULong pref[] = { 0x378, 0x278, 0x3bc, 0xFFFFFFFF };
DBG( DBG_LOW, "Requested port at 0x%02x\n", portAddr );
_VAR_NOT_USED( ps );
/*
* check the port address !!!!
*/
found = _FALSE;
for( i = 0; 0xFFFFFFFF != pref[i]; i++ ) {
if(((ULong)portAddr != 0xFFFFFFFF) && (pref[i] == (ULong)portAddr)) {
found = _TRUE;
break;
}
}
if( !found )
return _E_INVALID;
#else
struct parport *pp;
DBG( DBG_LOW, "Requested port at 0x%02x\n", portAddr );
pp = parport_enumerate();
ps->pardev = NULL;
if( NULL == pp ) {
return _E_PORTSEARCH;
}
/*
* go through the list
*/
for( ps->pp = NULL; NULL != pp; ) {
if( pp->base == portAddr ) {
DBG( DBG_LOW, "Requested port (0x%02x) found\n", portAddr );
DBG( DBG_LOW, "Port mode reported: (0x%04x)\n", pp->modes );
ps->pp = pp;
break;
}
pp = pp->next;
}
if( NULL == ps->pp ) {
return _E_NO_PORT;
}
/*
* register this device
*/
ps->pardev = parport_register_device( ps->pp, "Plustek Driver",
miscPreemptionCallback, NULL, NULL, 0, (pVoid)ps );
if( NULL == ps->pardev ) {
return _E_REGISTER;
}
DBG( DBG_LOW, "Port for device %lu registered\n", ps->devno );
#endif
portIsClaimed[ps->devno] = 0;
return _OK;
}
/** unregisters the port from driver (KERNEL-Mode only)
*/
void MiscUnregisterPort( pScanData ps )
{
#ifdef __KERNEL__
if( NULL != ps->pardev ) {
DBG( DBG_LOW, "Port unregistered\n" );
parport_unregister_device( ps->pardev );
}
#else
_VAR_NOT_USED( ps );
#endif
}
/*.............................................................................
* try to claim the port (KERNEL-Mode only)
*/
int MiscClaimPort( pScanData ps )
{
#ifdef __KERNEL__
if( 0 == portIsClaimed[ps->devno] ) {
DBG( DBG_HIGH, "Try to claim the parport\n" );
if( 0 != parport_claim( ps->pardev ))
return _E_BUSY;
}
#endif
portIsClaimed[ps->devno]++;
return _OK;
}
/*.............................................................................
* release previously claimed port (KERNEL-Mode only)
*/
void MiscReleasePort( pScanData ps )
{
if( portIsClaimed[ps->devno] > 0 ) {
portIsClaimed[ps->devno]--;
#ifdef __KERNEL__
if( 0 == portIsClaimed[ps->devno] ) {
DBG( DBG_HIGH, "Releasing parport\n" );
parport_release( ps->pardev );
}
#endif
}
}
/*.............................................................................
* get random number
*/
Long MiscLongRand( void )
{
randomnum = miscNextLongRand( randomnum );
return randomnum;
}
/*.............................................................................
* according to the id, the function returns a pointer to the model name
*/
const char *MiscGetModelName( UShort id )
{
DBG( DBG_HIGH, "MiscGetModelName - id = %i\n", id );
if( MODEL_OP_PT12 < id )
return ModelStr[0];
return ModelStr[id];
}
/* END PLUSTEK-PP_MISC.C ....................................................*/

Wyświetl plik

@ -0,0 +1,611 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_models.c - model specific stuff
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - no changes
* 0.33 - no changes
* 0.34 - no changes
* 0.35 - added some comments
* did some fine tuning on the 9630P and 12000P/9600P models
* moved function initPageSettings() to this module
* 0.36 - as the ps->MaxWideLineBlks and ps->MaxWideLineLen are only used
* for the OP 4800, it has been removed from pScanData
* changed settings of OP600 according to the Primax Direct 4800 tests
* removed dwPreferSize from struct ScannerCaps
* fixed the 5seconds bed-hit problem for ASIC 96001/3 based models
* changes, due to define renaming
* 0.37 - added ButtonCount init
* added A3I model
* added functions modelInitCaps(), modelInitMotor() and
* modelSetBufferSizes()
* 0.38 - added P12 stuff
* code cleanup
* 0.39 - no changes
* 0.40 - changed back to build 0.39-3 (disabled A3I stuff)
* 0.41 - added _OVR_PLUSTEK_4800P switch
* 0.42 - added SFLAG_CUSTOM_GAMMA to capabilities
* added _OVR_PRIMAX_4800D30 switch
* changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/*************************** local functions *********************************/
/*.............................................................................
* initialize the extension according to the page size...
*/
static void modelInitPageSettings( pScanData ps )
{
DBG(DBG_LOW, "modelInitPageSettings()\n" );
if( MODEL_OP_9630PL == ps->sCaps.Model )
ps->dwScannerSize = _SCANSIZE_LEGAL;
else if( MODEL_OP_A3I == ps->sCaps.Model )
ps->dwScannerSize = _SCANSIZE_A3;
else
ps->dwScannerSize = _SCANSIZE_A4;
/* default width for all but A3 - 8.5"* 300dpi (_MEASURE_BASE) */
ps->sCaps.wMaxExtentX = 2550;
/* this applies to all scanners but the A3 model */
ps->LensInf.rExtentX.wMin = 150;
ps->LensInf.rExtentX.wDef = 2550;
ps->LensInf.rExtentX.wMax = 2550;
ps->LensInf.rExtentX.wPhyMax = 2500;
ps->LensInf.rExtentY.wMin = 150;
ps->LensInf.wBeginX = 0;
ps->LensInf.wBeginY = 0;
switch( ps->dwScannerSize ) {
case _SCANSIZE_A4:
/* 11.69 inches */
DBG( DBG_LOW, "A4 set\n" );
ps->sCaps.wMaxExtentY =
ps->LensInf.rExtentY.wDef =
ps->LensInf.rExtentY.wMax =
ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 11.6934;
break;
case _SCANSIZE_A3:
/* 17 inches */
DBG( DBG_LOW, "A3 set\n" );
ps->sCaps.wMaxExtentY =
ps->LensInf.rExtentY.wMax =
ps->LensInf.rExtentY.wDef =
ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 17;
/* _MEASURE_BASE * 11.69 */
ps->sCaps.wMaxExtentX =
ps->LensInf.rExtentX.wDef =
ps->LensInf.rExtentX.wMax = 3507;
ps->LensInf.rExtentX.wPhyMax = 3500;
break;
case _SCANSIZE_LETTER:
/* 11 inches */
DBG( DBG_LOW, "Letter set\n" );
ps->sCaps.wMaxExtentY =
ps->LensInf.rExtentY.wDef =
ps->LensInf.rExtentY.wMax =
ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 11;
break;
case _SCANSIZE_LEGAL:
/* 14 inches */
DBG( DBG_LOW, "Legal set\n" );
ps->sCaps.wMaxExtentY =
ps->LensInf.rExtentY.wDef =
ps->LensInf.rExtentY.wMax =
ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 14;
}
/*
* add this value to avoid the problems in binary mode
*/
ps->LensInf.rExtentY.wMax += 64;
/* set the DPI stuff */
ps->LensInf.rDpiX.wMin = 16;
ps->LensInf.rDpiX.wDef = 50;
ps->LensInf.rDpiX.wMax = (ps->PhysicalDpi * 16);
ps->LensInf.rDpiX.wPhyMax = ps->PhysicalDpi;
ps->LensInf.rDpiY.wMin = 16;
ps->LensInf.rDpiY.wDef = 50;
ps->LensInf.rDpiY.wMax = (ps->PhysicalDpi * 16);
ps->LensInf.rDpiY.wPhyMax = (ps->PhysicalDpi * 2);
}
/*.............................................................................
* set the scanner capabilities
*/
static void modelInitCaps( pScanData ps )
{
if( _ASIC_IS_96001 == ps->sCaps.AsicID )
ps->sCaps.dwBits = _BITS_8;
else
ps->sCaps.dwBits = _BITS_10;
ps->sCaps.rDataType.wMin = 0;
ps->sCaps.rDataType.wDef = COLOR_TRUE24;
ps->sCaps.rDataType.wMax = COLOR_TRUE24;
ps->sCaps.rDataType.wPhyMax = COLOR_TRUE24;
ps->sCaps.wIOBase = _NO_BASE;
ps->sCaps.wLens = 1;
ps->sCaps.dwFlag = (SFLAG_SCANNERDEV +
SFLAG_FLATBED + SFLAG_CUSTOM_GAMMA);
}
/*.............................................................................
* set the motor stuff
*/
static void modelInitMotor( pScanData ps )
{
if( _ASIC_IS_96001 == ps->sCaps.AsicID ) {
ps->FullStep = _MotorFullStep96001;
ps->MotorOn = _MotorOn96001;
ps->IgnorePF = _MotorIgnorePF96001;
ps->StepMask = ~ps->FullStep;
} else {
ps->FullStep = _Motor1FullStep;
ps->MotorOn = _MotorOn;
ps->IgnorePF = _MotorIgnorePF;
ps->StepMask = _MotorStepMask;
}
ps->BackwardSteps = 4000;
}
/*.............................................................................
* according to the models' capabilities, set the buffer stuff
*/
static void modelSetBufferSizes( pScanData ps )
{
/* should depend on the scan-area !!!! */
if( 400 == ps->PhysicalDpi ) {
/* assuming a A3I */
ps->BufferSizeBase = 3517;
ps->BufferForColorRunTable = (5500 * 4); /* might be 17" * 800dpi !!! */
} else if( 600 == ps->PhysicalDpi ) {
ps->BufferSizeBase = 2560;
ps->BufferForColorRunTable = (5500 * 4);
} else {
ps->BufferSizeBase = 1280;
ps->BufferForColorRunTable = 9000;
}
ps->BufferSizePerModel = ps->BufferSizeBase * 2;
ps->BufferForDataRead1 = ps->BufferSizePerModel * 3;
/* patch that for the 600 DPI models OP9630 etc.*/
if(( 300 != ps->PhysicalDpi) && (_ASIC_IS_96003 == ps->sCaps.AsicID))
ps->BufferForDataRead1 += 300;
ps->BufferFor1stColor = (ps->BufferSizePerModel * 17);
ps->BufferFor2ndColor = (ps->BufferSizePerModel * 9);
ps->TotalBufferRequire = (ps->BufferFor1stColor +
ps->BufferFor2ndColor +
ps->BufferForDataRead1 +
ps->BufferForColorRunTable );
}
/************************ exported functions *********************************/
/*.............................................................................
* set the model to 4800
*/
void ModelSet4800( pScanData ps )
{
DBG( DBG_LOW, "ModelSet4800()\n" );
/* has 96001 ASIC */
ps->sCaps.AsicID = _ASIC_IS_96001;
ps->sCaps.Model = MODEL_OP_4800P;
ps->Device.buttons = 0;
ps->Device.ModelCtrl = (_ModelDpi300 | _ModelMemSize32k96001 | _ModelWhiteIs0);
ps->Device.DataOriginX = 72;
ps->PhysicalDpi = 300;
ps->TimePerLine = 0x30;
ps->Offset70 = 70;
modelSetBufferSizes( ps );
ps->a_wGrayInitTime[0] = 220; /* _EppTimeForOthers */
ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */
ps->a_wGrayInitTime[2] = 360; /* _BidirTimeForOthers */
ps->a_wColorInitTime[0] = 500; /* _EppTimeForColor */
ps->a_wColorInitTime[1] = 1680; /* _SppTimeForColor */
ps->a_wColorInitTime[2] = 1100; /* _BidirTimeForColor */
ps->AsicRedColor = _ASIC_REDCOLOR;
ps->AsicGreenColor = _ASIC_GREENCOLOR;
ps->RedDataReady = _RED_DATA_READY;
ps->GreenDataReady = _GREEN_DATA_READY;
/*
* used for shading stuff (see dac.c)
*/
ps->FBKScanLineBlks = 5;
ps->FBKScanLineLenBase = 1024;
ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 3);
ps->ShadingBufferSize = ps->FBKScanLineLen;
ps->ShadingBankSize = (ps->FBKScanLineLenBase * 4);
ps->ShadingBankRed = (_MemBankSize4k96001 | 0x3a);
ps->ShadingBankGreen = (_MemBankSize4k96001 | 0x3e);
ps->ShadingBankBlue = (_MemBankSize4k96001 | 0x3c);
ps->ShadingScanLineBlks = 6;
ps->ShadingScanLineLen = (ps->BufferSizeBase * 3);
ps->OneScanLineLen = (ps->BufferSizePerModel * 3);
modelInitMotor( ps );
modelInitCaps ( ps );
modelInitPageSettings( ps );
DBG( DBG_LOW, "ModelSet4800() done.\n" );
}
/*.............................................................................
* set the model to 4830
*/
void ModelSet4830( pScanData ps )
{
DBG( DBG_LOW, "ModelSet4830()\n" );
/* has 96003 ASIC */
ps->sCaps.Model = MODEL_OP_4830P;
if( _OVR_PRIMAX_4800D30 == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> Primax 4800D 30\n" );
ps->sCaps.Model = MODEL_PMX_4800D3;
}
ps->sCaps.AsicID = _ASIC_IS_96003;
ps->Device.buttons = 1;
ps->Device.ModelCtrl = (_ModelDpi300 | _ModelMemSize32k3 | _ModelWhiteIs0);
ps->Device.DataOriginX = 72;
ps->PhysicalDpi = 300;
ps->TimePerLine = 0x30;
ps->Offset70 = 70;
modelSetBufferSizes( ps );
ps->a_wGrayInitTime[0] = 220; /* _EppTimeForOthers */
ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */
ps->a_wGrayInitTime[2] = 360; /* _BidirTimeForOthers */
ps->a_wColorInitTime[0] = 500; /* _EppTimeForColor */
ps->a_wColorInitTime[1] = 1680; /* _SppTimeForColor */
ps->a_wColorInitTime[2] = 1100; /* _BidirTimeForColor */
ps->AsicRedColor = _ASIC_REDCOLOR;
ps->AsicGreenColor = _ASIC_GREENCOLOR;
ps->RedDataReady = _RED_DATA_READY;
ps->GreenDataReady = _GREEN_DATA_READY;
/*
* used for shading stuff (see dac.c)
*/
ps->FBKScanLineBlks = 5;
ps->FBKScanLineLenBase = 1024;
ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 3);
ps->ShadingBufferSize = ps->FBKScanLineLen;
ps->ShadingBankSize = (ps->FBKScanLineLenBase * 4);
ps->ShadingBankRed = (_MemBankSize4k | 0x3a);
ps->ShadingBankGreen = (_MemBankSize4k | 0x3e);
ps->ShadingBankBlue = (_MemBankSize4k | 0x3c);
ps->ShadingScanLineBlks = 6;
ps->ShadingScanLineLen = (ps->BufferSizeBase * 3);
ps->OneScanLineLen = (ps->BufferSizePerModel * 3);
modelInitMotor( ps );
modelInitCaps ( ps );
modelInitPageSettings( ps );
DBG( DBG_LOW, "ModelSet4830() done.\n" );
}
/*.............................................................................
* set the model to 600, tested on a Primax Direct 4800 and OP600
*/
void ModelSet600( pScanData ps )
{
DBG( DBG_LOW, "ModelSet600()\n" );
/*
* set to 4830 first, then do the differences
*/
ModelSet4830( ps );
ps->Device.buttons = 0;
if( _OVR_PLUSTEK_4800P == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> OpticPro4800\n" );
ps->sCaps.Model = MODEL_OP_4800P;
} else if( _OVR_PRIMAX_4800D == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> Primax 4800D\n" );
ps->sCaps.Model = MODEL_PMX_4800D;
} else {
ps->sCaps.Model = MODEL_OP_600P;
/* for Plustek OpticPro 600P it's necessary to swap Red and Green
* changed by mh moloch@nikocity.de
*/
ps->AsicRedColor = _ASIC_GREENCOLOR;
ps->AsicGreenColor = _ASIC_REDCOLOR;
}
DBG( DBG_LOW, "ModelSet600() done.\n" );
}
/*.............................................................................
* set the model to 12000P, 96000P (tested on a OP96000P)
*/
void ModelSet12000( pScanData ps )
{
DBG( DBG_LOW, "ModelSet12000()\n" );
/*
* set to 9630 first, then do the differences
*/
ModelSet9630( ps );
ps->Device.buttons = 0;
ps->sCaps.Model = MODEL_OP_12000P;
/*
* swapped Red and Green for 12000P/96000P
*/
ps->AsicRedColor = _ASIC_GREENCOLOR;
ps->AsicGreenColor = _ASIC_REDCOLOR;
ps->RedDataReady = _GREEN_DATA_READY;
ps->GreenDataReady = _RED_DATA_READY;
DBG( DBG_LOW, "ModelSet12000() done.\n" );
}
/*.............................................................................
* set the model to A3I
*/
void ModelSetA3I( pScanData ps )
{
DBG( DBG_LOW, "ModelSetA3I()\n" );
/*
* has 96003 ASIC
*/
ps->Device.buttons = 1;
ps->sCaps.Model = MODEL_OP_A3I;
ps->sCaps.AsicID = _ASIC_IS_96003;
ps->Device.ModelCtrl = (_ModelDpi400 | _ModelMemSize128k4 | _ModelWhiteIs0);
ps->Device.DataOriginX = 164;
ps->PhysicalDpi = 400;
ps->TimePerLine = 0x50;
ps->Offset70 = 145;
modelSetBufferSizes( ps );
ps->a_wGrayInitTime[0] = 133; /* _EppTimeForOthers */
ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */
ps->a_wGrayInitTime[2] = 300; /* _BidirTimeForOthers */
ps->a_wColorInitTime[0] = 400; /* _EppTimeForColor */
ps->a_wColorInitTime[1] = 1800; /* _SppTimeForColor */
ps->a_wColorInitTime[2] = 800; /* _BidirTimeForColor */
ps->AsicRedColor = _ASIC_GREENCOLOR;
ps->AsicGreenColor = _ASIC_REDCOLOR;
ps->RedDataReady = _GREEN_DATA_READY;
ps->GreenDataReady = _RED_DATA_READY;
ps->FBKScanLineBlks = 10;
ps->FBKScanLineLenBase = 2048;
ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 3);
ps->ShadingBufferSize = (1024 * 7);
ps->ShadingBankSize = 8192;
ps->ShadingBankRed = (_MemBankSize8k | 0x34);
ps->ShadingBankGreen = (_MemBankSize8k | 0x3c);
ps->ShadingBankBlue = (_MemBankSize8k | 0x38);
ps->ShadingScanLineBlks = 10;
ps->ShadingScanLineLen = (ps->BufferSizeBase * 3);
ps->OneScanLineLen = (ps->ShadingScanLineLen * 2);
modelInitMotor( ps );
ps->BackwardSteps = 9000;
modelInitCaps( ps );
modelInitPageSettings( ps );
/*
* need to double the vals
*/
ps->LensInf.rExtentX.wMax *= 2;
ps->LensInf.rExtentX.wPhyMax *= 2;
ps->LensInf.rExtentY.wMax *= 2;
ps->LensInf.rExtentY.wPhyMax *= 2;
DBG( DBG_LOW, "ModelSetA3I() done.\n" );
}
/*.............................................................................
* set the model to 9630
*/
void ModelSet9630( pScanData ps )
{
DBG( DBG_LOW, "ModelSet9360()\n" );
/*
* has 96003 ASIC
*/
if( _OVR_PLUSTEK_9630PL == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> 9630PL\n" );
ps->sCaps.Model = MODEL_OP_9630PL;
} else {
ps->sCaps.Model = MODEL_OP_9630P;
}
ps->Device.buttons = 1;
ps->sCaps.AsicID = _ASIC_IS_96003;
ps->Device.ModelCtrl = (_ModelDpi600 | _ModelMemSize128k4 | _ModelWhiteIs0);
ps->Device.DataOriginX = 64;
ps->PhysicalDpi = 600;
ps->TimePerLine = 0x5a;
ps->Offset70 = 95;
modelSetBufferSizes( ps );
ps->a_wGrayInitTime[0] = 133; /* _EppTimeForOthers */
ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */
ps->a_wGrayInitTime[2] = 300; /* _BidirTimeForOthers */
ps->a_wColorInitTime[0] = 400; /* _EppTimeForColor */
ps->a_wColorInitTime[1] = 1800; /* _SppTimeForColor */
ps->a_wColorInitTime[2] = 800; /* _BidirTimeForColor */
ps->AsicRedColor = _ASIC_REDCOLOR;
ps->AsicGreenColor = _ASIC_GREENCOLOR;
ps->RedDataReady = _RED_DATA_READY;
ps->GreenDataReady = _GREEN_DATA_READY;
ps->ShadingBufferSize = (1024 * 7);
ps->ShadingBankSize = 8192;
ps->ShadingBankRed = (_MemBankSize8k | 0x34);
ps->ShadingBankGreen = (_MemBankSize8k | 0x3c);
ps->ShadingBankBlue = (_MemBankSize8k | 0x38);
ps->ShadingScanLineBlks = 10;
ps->ShadingScanLineLen = (2560 * 3);
ps->FBKScanLineBlks = 10;
ps->FBKScanLineLenBase = 2048;
ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 6);
ps->OneScanLineLen = (5120 * 3);
modelInitMotor( ps );
ps->BackwardSteps = 9000;
modelInitCaps( ps );
modelInitPageSettings( ps );
/*
* need to double the vals
*/
ps->LensInf.rExtentX.wMax *= 2;
ps->LensInf.rExtentX.wPhyMax *= 2;
ps->LensInf.rExtentY.wMax *= 2;
ps->LensInf.rExtentY.wPhyMax *= 2;
DBG( DBG_LOW, "ModelSet9630() done.\n" );
}
/*.............................................................................
* set the model to 9636 (ASIC 98001 models)
* works for 9636P Turbo and 9636T /12000T
*/
void ModelSet9636( pScanData ps )
{
DBG( DBG_LOW, "ModelSet9636()\n" );
/*
*set to 9630 first, then do the differences
*/
ModelSet9630( ps );
ps->Device.buttons = 0;
/*
* has 98001 ASIC
*/
if( _OVR_PLUSTEK_9636 == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> 9636P+/Turbo\n" );
ps->sCaps.Model = MODEL_OP_9636PP;
} else if( _OVR_PLUSTEK_9636P == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> 9636P\n" );
ps->sCaps.Model = MODEL_OP_9636P;
} else {
ps->sCaps.Model = MODEL_OP_9636T;
ps->sCaps.dwFlag |= SFLAG_TPA;
}
ps->Device.DataOriginX = 72;
ps->sCaps.AsicID = _ASIC_IS_98001;
ps->sCaps.dwBits = _BITS_12;
ps->sCaps.rDataType.wMax = COLOR_TRUE48;
ps->sCaps.rDataType.wPhyMax = COLOR_TRUE48;
ps->TotalBufferRequire = _LINE_BUFSIZE * 2 + _LINE_BUFSIZE1 +
ps->BufferForColorRunTable + _PROCESS_BUFSIZE;
/* do it again, as ModelSet9630() changes the result of this function !*/
modelInitPageSettings( ps );
DBG( DBG_LOW, "ModelSet9636() done.\n" );
}
/*.............................................................................
* set the model to P12 (ASIC 98003 models)
*/
void ModelSetP12( pScanData ps )
{
DBG( DBG_LOW, "ModelSetP12()\n" );
/*
* set to 9630 first, then do the differences
*/
ModelSet9630( ps );
ps->Device.DataOriginX = 72;
ps->sCaps.Model = MODEL_OP_PT12;
ps->sCaps.AsicID = _ASIC_IS_98003;
ps->sCaps.dwBits = _BITS_12;
ps->sCaps.rDataType.wMax = COLOR_TRUE48;
ps->sCaps.rDataType.wPhyMax = COLOR_TRUE48;
ps->TotalBufferRequire = _SizeTotalBufTpa;
/* do it again, as ModelSet9630() changes the result of this function !*/
modelInitPageSettings( ps );
DBG( DBG_LOW, "ModelSetP12() done.\n" );
}
/* END PLUSTEK-PP_MODEL.C ...................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,757 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_p12.c - p12 and pt12 specific stuff
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 2000 Plustek Inc.
* Copyright (C) 2001-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.38 - initial version
* 0.39 - added Genius Colorpage Vivid III V2 stuff
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - removed setting of ps->sCaps.dwFlag in p12InitiateComponentModel()
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/*************************** some local vars *********************************/
static RegDef p12CcdStop[] = {
{0x41, 0xff}, {0x42, 0xff}, {0x60, 0xff}, {0x61, 0xff},
{0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff},
{0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x15, 0x00}
};
/*************************** local functions *********************************/
/*.............................................................................
* init the stuff according to the buttons
*/
static void p12ButtonSetup( pScanData ps, Byte nrOfButtons )
{
ps->Device.buttons = nrOfButtons;
ps->Device.Model1Mono &= ~_BUTTON_MODE;
ps->Device.Model1Color &= ~_BUTTON_MODE;
ps->AsicReg.RD_MotorDriverType |= _BUTTON_DISABLE;
ps->Scan.motorPower |= _BUTTON_DISABLE;
ps->sCaps.dwFlag |= (SFLAG_MULTIFUNC | SFLAG_BUTTONOPT);
}
/*.............................................................................
* According to what we have detected, set the other stuff
*/
static void p12InitiateComponentModel( pScanData ps )
{
/* preset some stuff and do te differences later */
ps->Device.buttons = 0;
ps->Device.Model1Mono = _BUTTON_MODE + _CCD_SHIFT_GATE + _SCAN_GRAYTYPE;
ps->Device.Model1Color = _BUTTON_MODE + _CCD_SHIFT_GATE;
ps->Device.dwModelOriginY = 64;
ps->Device.fTpa = _FALSE;
ps->Device.ModelCtrl = (_LED_ACTIVITY | _LED_CONTROL);
/* ps->sCaps.dwFlag should have been set correctly in models.c */
switch( ps->Device.bPCBID ) {
case _PLUSTEK_SCANNER:
DBG( DBG_LOW, "We have a Plustek Scanner\n" );
ps->sCaps.Model = MODEL_OP_P12;
break;
case _SCANNER_WITH_TPA:
DBG( DBG_LOW, "Scanner has TPA\n" );
ps->Device.fTpa = _TRUE;
ps->sCaps.dwFlag |= SFLAG_TPA;
break;
case _SCANNER4Button:
DBG( DBG_LOW, "Scanner has 4 Buttons\n" );
p12ButtonSetup( ps, 4 );
break;
case _SCANNER4ButtonTPA:
DBG( DBG_LOW, "Scanner has 4 Buttons & TPA\n" );
ps->Device.fTpa = _TRUE;
ps->sCaps.dwFlag |= SFLAG_TPA;
p12ButtonSetup( ps, 4 );
break;
case _SCANNER5Button:
DBG( DBG_LOW, "Scanner has 5 Buttons\n" );
ps->Device.dwModelOriginY = 64 + 20;
p12ButtonSetup( ps, 5 );
break;
case _SCANNER5ButtonTPA:
DBG( DBG_LOW, "Scanner has 5 Buttons & TPA\n" );
ps->Device.dwModelOriginY = 64 + 20;
ps->Device.fTpa = _TRUE;
ps->sCaps.dwFlag |= SFLAG_TPA;
p12ButtonSetup( ps, 5 );
break;
case _SCANNER1Button:
DBG( DBG_LOW, "Scanner has 1 Button\n" );
p12ButtonSetup( ps, 1 );
break;
case _SCANNER1ButtonTPA:
DBG( DBG_LOW, "Scanner has 1 Button & TPA\n" );
ps-> Device.fTpa = _TRUE;
ps->sCaps.dwFlag |= SFLAG_TPA;
p12ButtonSetup( ps, 1 );
break;
case _AGFA_SCANNER:
DBG( DBG_LOW, "Agfa Scanner\n" );
ps->Device.dwModelOriginY = 24; /* 1200 dpi */
break;
case _SCANNER2Button:
DBG( DBG_LOW, "Scanner has 2 Buttons\n" );
DBG( DBG_LOW, "Seems we have a Genius Colorpage Vivid III V2\n" );
ps->Device.dwModelOriginY = 64 - 33;
p12ButtonSetup( ps, 2 );
ps->sCaps.Model = MODEL_GEN_CPV2;
break;
default:
DBG( DBG_LOW, "Default Model: P12\n" );
ps->sCaps.Model = MODEL_OP_P12;
break;
}
if( _MOTOR0_2003 == ps->Device.bMotorID ) {
ps->Device.f2003 = _TRUE;
ps->Device.XStepMono = 10;
ps->Device.XStepColor = 6;
ps->Device.XStepBack = 5;
ps->AsicReg.RD_MotorDriverType |= _MOTORR_STRONG;
} else {
ps->Device.f2003 = _FALSE;
ps->Device.XStepMono = 8;
ps->Device.XStepColor = 4;
ps->Device.XStepBack = 5;
ps->AsicReg.RD_MotorDriverType |= _MOTORR_WEAK;
}
}
/*.............................................................................
* prepare all the necessary variables -
*/
static void p12SetupScannerVariables( pScanData ps )
{
DBG( DBG_LOW, "p12SetupScannerVariables()\n" );
/*
* these values were originally altered by registry entries (NT-driver)
* and used to adjust the picture position...
*/
ps->Device.lUpNormal = 0;
ps->Device.lUpNegative = 20;
ps->Device.lUpPositive = -30;
ps->Device.lLeftNormal = 51;
ps->OpenScanPath( ps );
ps->ReInitAsic( ps, _FALSE );
ps->CloseScanPath( ps );
}
/*.............................................................................
*
*/
static void p12SetupScanningCondition( pScanData ps )
{
TimerDef timer;
ULong channel;
Byte bState;
pUChar pState = ps->Bufs.b1.pReadBuf;
DBG( DBG_LOW, "p12SetupScanningCondition()\n" );
P12SetGeneralRegister( ps );
IORegisterToScanner( ps, ps->RegResetMTSC );
/* ------- Setup MinRead/MaxRead Fifo size ------- */
if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) {
ps->Scan.dwMaxReadFifo =
ps->Scan.dwMinReadFifo = ps->DataInf.dwAsicBytesPerPlane * 2;
} else {
ps->Scan.dwMaxReadFifo =
ps->Scan.dwMinReadFifo = ps->DataInf.dwAppPixelsPerLine << 1;
}
if( ps->Scan.dwMinReadFifo < 1024)
ps->Scan.dwMinReadFifo = ps->Scan.dwMaxReadFifo = 1024;
ps->Scan.dwMaxReadFifo += (ps->DataInf.dwAsicBytesPerPlane / 2);
DBG( DBG_LOW, "MinReadFifo=%lu, MaxReadFifo=%lu\n",
ps->Scan.dwMinReadFifo, ps->Scan.dwMaxReadFifo );
/* ------- Set the max. read fifo to asic ------- */
if( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
ps->Scan.bFifoSelect = ps->RegBFifoOffset;
if( !ps->Scan.p48BitBuf.pb ) {
Long lRed, lGreen;
lRed = (_SIZE_REDFIFO - _SIZE_BLUEFIFO) /
ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep;
lGreen = (_SIZE_GREENFIFO - _SIZE_BLUEFIFO) /
ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep;
if((lRed < 0) || (lGreen < 0)) {
if( lRed < lGreen ) {
channel = _RED_FULLSIZE << 16;
ps->AsicReg.RD_BufFullSize = _SIZE_REDFIFO;
lGreen = lRed;
} else {
channel = _GREEN_FULLSIZE << 16;
ps->AsicReg.RD_BufFullSize = _SIZE_GREENFIFO;
}
lGreen = (ULong)(-lGreen * ps->DataInf.dwAsicBytesPerPlane);
if( ps->DataInf.wPhyDataType > COLOR_TRUE24 )
lGreen >>= 1;
ps->Scan.dwMinReadFifo += (ULong)lGreen;
ps->Scan.dwMaxReadFifo += (ULong)lGreen;
} else {
channel = _BLUE_FULLSIZE << 16;
ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO;
}
} else {
channel = _BLUE_FULLSIZE << 16;
ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO;
}
} else {
ps->Scan.bFifoSelect = ps->RegGFifoOffset;
channel = _GREEN_FULLSIZE << 16;
ps->AsicReg.RD_BufFullSize = _SIZE_GRAYFIFO;
}
ps->AsicReg.RD_BufFullSize -= (ps->DataInf.dwAsicBytesPerPlane << 1);
if( ps->DataInf.wPhyDataType > COLOR_TRUE24 )
ps->AsicReg.RD_BufFullSize >>= 1;
ps->AsicReg.RD_BufFullSize |= channel;
ps->Scan.bRefresh = (Byte)(ps->Scan.dwInterval << 1);
ps->AsicReg.RD_LineControl = (_LOBYTE (ps->Shade.wExposure));
ps->AsicReg.RD_ExtLineControl = (_HIBYTE (ps->Shade.wExposure));
ps->AsicReg.RD_XStepTime = (_LOBYTE (ps->Shade.wXStep));
ps->AsicReg.RD_ExtXStepTime = (_HIBYTE (ps->Shade.wXStep));
ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
ps->AsicReg.RD_ModeControl = (_ModeScan | _ModeFifoGSel);
DBG( DBG_LOW, "bRefresh = %i\n", ps->Scan.bRefresh );
if( ps->DataInf.wPhyDataType == COLOR_BW ) {
ps->AsicReg.RD_ScanControl = _SCAN_BITMODE;
if( !(ps->DataInf.dwScanFlag & SCANDEF_Inverse))
ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT;
} else if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 )
ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
else {
ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE;
if(!(ps->DataInf.dwScanFlag & SCANDEF_RightAlign))
ps->AsicReg.RD_ScanControl |= _BITALIGN_LEFT;
if( ps->DataInf.dwScanFlag & SCANDEF_Inverse)
ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT;
}
ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE;
IOSelectLampSource( ps );
DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl );
ps->AsicReg.RD_MotorTotalSteps = (ULong)ps->DataInf.crImage.cy * 4 +
((ps->Device.f0_8_16) ? 32 : 16) +
((ps->Scan.bDiscardAll) ? 32 : 0);
ps->AsicReg.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL |
_MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP);
ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x;
if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA )) {
ps->AsicReg.RD_Origin = (UShort)(ps->Device.lLeftNormal * 2 +
ps->Device.DataOriginX +
ps->DataInf.crImage.x );
} else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) {
ps->AsicReg.RD_Origin =
(UShort)(ps->Scan.posBegin + ps->DataInf.crImage.x);
} else {
ps->AsicReg.RD_Origin =
(UShort)(ps->Scan.negBegin + ps->DataInf.crImage.x);
}
if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
ps->AsicReg.RD_Origin >>= 1;
if( ps->DataInf.wPhyDataType == COLOR_BW )
ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicBytesPerPlane;
else
ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAppPixelsPerLine;
DBG( DBG_LOW, "RD_Origin = %u, RD_Pixels = %u\n",
ps->AsicReg.RD_Origin, ps->AsicReg.RD_Pixels );
/* ------- Prepare scan states ------- */
memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
memset( ps->Bufs.b1.pReadBuf, 0, _NUMBER_OF_SCANSTEPS );
if( ps->DataInf.wPhyDataType <= COLOR_256GRAY )
bState = (_SS_MONO | _SS_STEP);
else
bState = (_SS_COLOR | _SS_STEP);
for( channel = _NUMBER_OF_SCANSTEPS;
channel; channel -= ps->Scan.dwInterval ) {
*pState = bState;
if( ps->Scan.dwInterlace )
pState[ ps->Scan.dwInterlace] = _SS_STEP;
pState += ps->Scan.dwInterval;
}
for( channel = 0, pState = ps->Bufs.b1.pReadBuf;
channel < _SCANSTATE_BYTES; channel++) {
ps->a_nbNewAdrPointer[channel] = pState [0] | (pState [1] << 4);
pState += 2;
}
/* ------- Wait for scan state stop ------- */
MiscStartTimer( &timer, _SECOND * 2 );
while(!(IOGetScanState( ps, _FALSE ) & _SCANSTATE_STOP) &&
!MiscCheckTimer(&timer));
/* CHECK: Replace by IOPutAll.... */
IODownloadScanStates( ps );
IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl);
IODataToRegister( ps, ps->RegExtendedLineControl,
ps->AsicReg.RD_ExtLineControl);
IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime);
IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime);
IODataToRegister( ps, ps->RegMotorDriverType,
ps->AsicReg.RD_MotorDriverType);
IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl);
IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control);
IODataToRegister( ps, ps->RegModelControl,ps->AsicReg.RD_ModelControl);
IODataToRegister( ps, ps->RegDpiLow, (_LOBYTE(ps->AsicReg.RD_Dpi)));
IODataToRegister( ps, ps->RegDpiHigh, (_HIBYTE(ps->AsicReg.RD_Dpi)));
IODataToRegister( ps, ps->RegScanPosLow, (_LOBYTE(ps->AsicReg.RD_Origin)));
IODataToRegister( ps, ps->RegScanPosHigh,(_HIBYTE(ps->AsicReg.RD_Origin)));
IODataToRegister( ps, ps->RegWidthPixelsLow,
(_LOBYTE(ps->AsicReg.RD_Pixels)));
IODataToRegister( ps, ps->RegWidthPixelsHigh,
(_HIBYTE(ps->AsicReg.RD_Pixels)));
IODataToRegister( ps, ps->RegThresholdLow,
(_LOBYTE(ps->AsicReg.RD_ThresholdControl)));
IODataToRegister( ps, ps->RegThresholdHigh,
(_HIBYTE(ps->AsicReg.RD_ThresholdControl)));
IODataToRegister( ps, ps->RegMotorTotalStep0,
(_LOBYTE(ps->AsicReg.RD_MotorTotalSteps)));
IODataToRegister( ps, ps->RegMotorTotalStep1,
(_HIBYTE(ps->AsicReg.RD_MotorTotalSteps)));
IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
IORegisterToScanner( ps, ps->RegInitDataFifo);
}
/*.............................................................................
* program the CCD relevant stuff
*/
static void p12ProgramCCD( pScanData ps)
{
UShort w;
pRegDef rp;
DBG( DBG_IO, "p12ProgramCCD: 0x%08lx[%lu]\n",
(ULong)ps->Device.pCCDRegisters,
((ULong)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate));
DBG( DBG_IO, " %u regs * %u (intermediate)\n",
ps->Device.wNumCCDRegs, ps->Shade.bIntermediate );
rp = ps->Device.pCCDRegisters +
(ULong)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate;
for( w = ps->Device.wNumCCDRegs; w--; rp++ ) {
DBG( DBG_IO, "[0x%02x] = 0x%02x\n", rp->bReg, rp->bParam );
IODataToRegister( ps, rp->bReg, rp->bParam );
}
}
/*.............................................................................
* this initializes the ASIC and prepares the different functions for shading
* and scanning
*/
static void p12Init98003( pScanData ps, Bool shading )
{
DBG( DBG_LOW, "p12InitP98003(%d)\n", shading );
/* get DAC and motor stuff */
ps->Device.bDACType = IODataFromRegister( ps, ps->RegResetConfig );
ps->Device.bMotorID = (Byte)(ps->Device.bDACType & _MOTOR0_MASK);
ps->AsicReg.RD_MotorDriverType =
(Byte)((ps->Device.bDACType & _MOTOR0_MASK) >> 3);
ps->AsicReg.RD_MotorDriverType |=
(Byte)((ps->Device.bDACType & _MOTOR1_MASK) >> 1);
ps->Scan.motorPower = ps->AsicReg.RD_MotorDriverType | _MOTORR_STRONG;
ps->Device.bDACType &= _ADC_MASK;
/*get CCD and PCB ID */
ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration );
ps->Device.bCCDID = ps->Device.bPCBID & 0x07;
ps->Device.bPCBID &= 0xf0;
if( _AGFA_SCANNER == ps->Device.bPCBID )
ps->Device.bDACType = _DA_WOLFSON8141;
DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x, DAC-TYPE=0x%02x\n",
ps->Device.bPCBID, ps->Device.bCCDID, ps->Device.bDACType );
p12InitiateComponentModel( ps );
/* encode the CCD-id into the flag parameter */
ps->sCaps.dwFlag |= ((ULong)(ps->Device.bCCDID | ps->Device.bPCBID) << 16);
P12InitCCDandDAC( ps, shading );
if( ps->Shade.bIntermediate & _ScanMode_Mono )
ps->AsicReg.RD_Model1Control = ps->Device.Model1Mono;
else
ps->AsicReg.RD_Model1Control = ps->Device.Model1Color;
IODataToRegister( ps, ps->RegPllPredivider, 1 );
IODataToRegister( ps, ps->RegPllMaindivider, 0x20 );
IODataToRegister( ps, ps->RegPllPostdivider, 2 );
IODataToRegister( ps, ps->RegClockSelector, 3 ); /* 2 */
IODataToRegister( ps, ps->RegMotorDriverType,
ps->AsicReg.RD_MotorDriverType );
/* this might be changed, def value is 11 */
IODataToRegister( ps, ps->RegWaitStateInsert, 11 );
IODataToRegister( ps, ps->RegModel1Control, ps->AsicReg.RD_Model1Control );
p12ProgramCCD( ps );
}
/*.............................................................................
* initialize the register values for the 98003 asic and preset other stuff
*/
static void p12InitializeAsicRegister( pScanData ps )
{
memset( &ps->AsicReg, 0, sizeof(RegData));
}
/*.............................................................................
* as the function name says
*/
static void p12PutToIdleMode( pScanData ps )
{
ULong i;
ps->OpenScanPath( ps );
DBG( DBG_IO, "CCD-Stop\n" );
for( i = 0; i < 13; i++ ) {
DBG( DBG_IO, "[0x%02x] = 0x%02x\n",
p12CcdStop[i].bReg, p12CcdStop[i].bParam );
IODataToRegister( ps, p12CcdStop[i].bReg, p12CcdStop[i].bParam );
}
ps->CloseScanPath( ps );
}
/*.............................................................................
* here we simply call the WaitForShading function which performs this topic
*/
static int p12Calibration( pScanData ps )
{
Bool result;
DBG( DBG_LOW, "p12Calibration()\n" );
/*
* wait for shading to be done
*/
ps->OpenScanPath( ps );
_ASSERT(ps->WaitForShading);
result = ps->WaitForShading( ps );
ps->CloseScanPath( ps );
if( !result )
return _E_TIMEOUT;
return _OK;
}
/************************ exported functions *********************************/
/*.............................................................................
* initialize the register values and function calls for the 98003 asic
*/
int P12InitAsic( pScanData ps )
{
int result;
DBG( DBG_LOW, "P12InitAsic()\n" );
/*
* preset the asic shadow registers
*/
p12InitializeAsicRegister( ps );
ps->IO.bOpenCount = 0;
/*
* setup the register values
*/
ps->RegSwitchBus = 0;
ps->RegEPPEnable = 1;
ps->RegECPEnable = 2;
ps->RegReadDataMode = 3;
ps->RegWriteDataMode = 4;
ps->RegInitDataFifo = 5;
ps->RegForceStep = 6;
ps->RegInitScanState = 7;
ps->RegRefreshScanState = 8;
ps->RegWaitStateInsert = 0x0a;
ps->RegRFifoOffset = 0x0a;
ps->RegGFifoOffset = 0x0b;
ps->RegBFifoOffset = 0x0c;
ps->RegBitDepth = 0x13;
ps->RegStepControl = 0x14;
ps->RegMotor0Control = 0x15;
ps->RegXStepTime = 0x16;
ps->RegGetScanState = 0x17;
ps->RegAsicID = 0x18;
ps->RegMemoryLow = 0x19;
ps->RegMemoryHigh = 0x1a;
ps->RegModeControl = 0x1b;
ps->RegLineControl = 0x1c;
ps->RegScanControl = 0x1d;
ps->RegConfiguration = 0x1e;
ps->RegModelControl = 0x1f;
ps->RegModel1Control = 0x20;
ps->RegDpiLow = 0x21;
ps->RegDpiHigh = 0x22;
ps->RegScanPosLow = 0x23;
ps->RegScanPosHigh = 0x24;
ps->RegWidthPixelsLow = 0x25;
ps->RegWidthPixelsHigh = 0x26;
ps->RegThresholdLow = 0x27;
ps->RegThresholdHigh = 0x28;
ps->RegThresholdGapControl = 0x29;
ps->RegADCAddress = 0x2a;
ps->RegADCData = 0x2b;
ps->RegADCPixelOffset = 0x2c;
ps->RegADCSerialOutStr = 0x2d;
ps->RegResetConfig = 0x2e;
ps->RegLensPosition = 0x2f;
ps->RegStatus = 0x30;
ps->RegScanStateControl = 0x31;
ps->RegRedChDarkOffsetLow = 0x33;
ps->RegRedChDarkOffsetHigh = 0x34;
ps->RegGreenChDarkOffsetLow = 0x35;
ps->RegGreenChDarkOffsetHigh= 0x36;
ps->RegBlueChDarkOffsetLow = 0x37;
ps->RegBlueChDarkOffsetHigh = 0x38;
ps->RegResetPulse0 = 0x39;
ps->RegResetPulse1 = 0x3a;
ps->RegCCDClampTiming0 = 0x3b;
ps->RegCCDClampTiming1 = 0x3c;
ps->RegVSMPTiming0 = 0x41;
ps->RegVSMPTiming1 = 0x42;
ps->RegCCDQ1Timing0 = 0x43;
ps->RegCCDQ1Timing1 = 0x44;
ps->RegCCDQ1Timing2 = 0x45;
ps->RegCCDQ1Timing3 = 0x46;
ps->RegCCDQ2Timing0 = 0x47;
ps->RegCCDQ2Timing1 = 0x48;
ps->RegCCDQ2Timing2 = 0x49;
ps->RegCCDQ2Timing3 = 0x4a;
ps->RegADCclockTiming0 = 0x4b;
ps->RegADCclockTiming1 = 0x4c;
ps->RegADCclockTiming2 = 0x4d;
ps->RegADCclockTiming3 = 0x4e;
ps->RegADCDVTiming0 = 0x50;
ps->RegADCDVTiming1 = 0x51;
ps->RegADCDVTiming2 = 0x52;
ps->RegADCDVTiming3 = 0x53;
ps->RegFifoFullLength0 = 0x54;
ps->RegFifoFullLength1 = 0x55;
ps->RegFifoFullLength2 = 0x56;
ps->RegMotorTotalStep0 = 0x57;
ps->RegMotorTotalStep1 = 0x58;
ps->RegMotorFreeRunCount0 = 0x59;
ps->RegMotorFreeRunCount1 = 0x5a;
ps->RegScanControl1 = 0x5b;
ps->RegMotorFreeRunTrigger = 0x5c;
ps->RegResetMTSC = 0x5d;
ps->RegMotor1Control = 0x62;
ps->RegMotor2Control = 0x63;
ps->RegMotorDriverType = 0x64;
ps->RegStatus2 = 0x66;
ps->RegExtendedLineControl = 0x6d;
ps->RegExtendedXStep = 0x6e;
ps->RegPllPredivider = 0x71;
ps->RegPllMaindivider = 0x72;
ps->RegPllPostdivider = 0x73;
ps->RegClockSelector = 0x74;
ps->RegTestMode = 0xf0;
/*
* setup function calls
*/
ps->SetupScannerVariables = p12SetupScannerVariables;
ps->SetupScanningCondition = p12SetupScanningCondition;
ps->Calibration = p12Calibration;
ps->PutToIdleMode = p12PutToIdleMode;
ps->ReInitAsic = p12Init98003;
ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE;
ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF;
ps->IO.useEPPCmdMode = _FALSE;
/*
* initialize the other modules and set some
* function pointer
*/
result = DacInitialize( ps );
if( _OK != result )
return result;
result = ImageInitialize( ps );
if( _OK != result )
return result;
result = IOFuncInitialize( ps );
if( _OK != result )
return result;
result = IOInitialize( ps );
if( _OK != result )
return result;
result = MotorInitialize( ps );
if( _OK != result )
return result;
if( _FALSE == ps->OpenScanPath( ps )) {
DBG( DBG_LOW, "P12InitAsic() failed.\n" );
return _E_NO_DEV;
}
/*get CCD and PCB ID */
ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration );
ps->Device.bCCDID = ps->Device.bPCBID & 0x07;
ps->Device.bPCBID &= 0xf0;
DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x\n", ps->Device.bPCBID, ps->Device.bCCDID );
/* get a more closer model description...*/
p12InitiateComponentModel( ps );
ps->CloseScanPath( ps );
/* here we check for the OpticWorks 2000, which is not supported */
if( _OPTICWORKS2000 == ps->Device.bPCBID ) {
DBG( DBG_LOW, "OpticWorks 2000 not supported!\n" );
return _E_NOSUPP;
}
DBG( DBG_LOW, "P12InitAsic() done.\n" );
return _OK;
}
/*.............................................................................
* set all necessary register contents
*/
void P12SetGeneralRegister( pScanData ps )
{
DBG( DBG_LOW, "P12SetGeneralRegister()\n" );
ps->Scan.fMotorBackward = _FALSE;
ps->Scan.fRefreshState = _FALSE;
if( COLOR_BW == ps->DataInf.wPhyDataType )
ps->AsicReg.RD_ScanControl = _SCAN_BITMODE;
else {
if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 )
ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
else
ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE;
}
IOSelectLampSource( ps );
if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi300;
else
ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi600;
ps->AsicReg.RD_Motor0Control = _MotorOn | _MotorHQuarterStep | _MotorPowerEnable;
ps->AsicReg.RD_ScanControl1 = _SCANSTOPONBUFFULL | _MFRC_BY_XSTEP;
ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
}
/* END PLUSTEK-PP_P12.C .....................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,853 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_p48xx.c - here we have all functionality according to
* the ASIC96001/3 basedmodels
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - fixed a bug for the return value in p48xxDoTest
* added additional debug messages
* added function p48xxCheck4800Memory
* 0.32 - added debug messages
* fixed a bug in p48xxDoTest
* disabled RD_WatchDogControl, lamp will be controlled by driver
* 0.33 - added function p48xxSetAsicRegisters()
* fixed a bug in p48xxDoTest (reset the ASIC registers)
* removed p48xxPositionLamp
* 0.34 - added some comments
* 0.35 - added some comments
* 0.36 - added function p48xxInitAllModules() to allow reinit of the modules
* switching from Full- to Halfstep at ps->PhysicalDpi now in
* p48xxSetGeneralRegister
* fixed the color-inverse problem for model OP4800
* 0.37 - move p48xxOpenScanPath, p48xxCloseScanPath
* and p48xxRegisterToScanner to io.c
* removed // comments
* added override for A3I scanner
* 0.38 - added function p48xxPutToIdleMode()
* added function p48xxCalibration
* 0.39 - added A3I stuff
* 0.40 - disabled A3I stuff
* 0.41 - no changes
* 0.42 - changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/*************************** some definitions ********************************/
#define _TEST_SZ 2048 /* always use 2048 for mem size (= one bank) */
#define _START_VAL 0x12345678 /* pick a non-zero starting value for our long */
#define _BankAndSizeForTest _MemBankSize2k /* always use 2k for mem test */
/*************************** local functions *********************************/
/*.............................................................................
* 1) Set asic to PROGRAM mode
* 2) Select the memory bank and size
* 3) Initiate data fifo
*/
static void p48xxSetMemoryBankForProgram( pScanData ps , Byte bBankAndSize )
{
/* enter program mode */
IODataToRegister( ps, ps->RegModeControl, _ModeProgram );
/* bank and size */
IODataToRegister( ps, ps->RegMemAccessControl, bBankAndSize );
/* initiate data fifo */
IORegisterToScanner( ps, ps->RegInitDataFifo );
}
/*.............................................................................
* use the internal memory of a scanner to find the model
*/
static int p48xxDoTest( pScanData ps )
{
UChar tmpByte;
int retval;
ULong adder, ul, cntr;
pULong buffer;
DBG( DBG_LOW, "p48xxDoTest()\n" );
buffer = _KALLOC( sizeof(UChar) * _TEST_SZ, GFP_KERNEL );
if( NULL == buffer )
return _E_ALLOC;
retval = _E_NO_DEV;
/*
* do a memory test to determine how much memory this unit has, in the
* process we can figure out if it's a 4830 or a 9630. NOTE: the ram
* seems to be mirrored such that if you have a unit with only 32k it's
* mirrored 4 times to fill the 128k (2k * (_MemBankMask + 1)) space,
* so we will run a 32 bit incrementing pattern over the entire 128k and
* look for the 1st page (2k) to fail
*/
adder = 0;
for (cntr = _BankAndSizeForTest;
cntr < _BankAndSizeForTest + _MemBanks; cntr++) {
ps->OpenScanPath( ps );
p48xxSetMemoryBankForProgram( ps, cntr );
/* prepare content, incrementing 32 val */
for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++)
buffer[ul] = ul + adder + _START_VAL;
/* fill to buffer */
IOMoveDataToScanner( ps, (pUChar)buffer, _TEST_SZ );
/*
* now check bank 0 to see if it got overwritten
* bank 0, size 2k
*/
p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest );
ps->CloseScanPath( ps );
/* read data back */
IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ );
/* check */
for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++) {
if (buffer[ul] != ul + _START_VAL) {
break;
}
}
/* if fail */
if (ul != _TEST_SZ / sizeof (ULong)) {
DBG( DBG_LOW, "Bank 0 overwritten\n" );
break;
}
/* now check current bank */
ps->OpenScanPath( ps );
p48xxSetMemoryBankForProgram( ps, cntr );
ps->CloseScanPath( ps );
/* read data back */
IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ);
/* check if fail */
for( ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++ ) {
if( buffer[ul] != ul + adder + _START_VAL )
break;
}
/* check if fail */
if (ul != _TEST_SZ / sizeof(ULong)) {
DBG( DBG_LOW, "Bank not present, error at pos %lu (%u)\n", ul,
_TEST_SZ / sizeof(ULong));
break;
}
adder += _TEST_SZ / sizeof(ULong);
}
_KFREE( buffer );
DBG( DBG_LOW, "found %ld bytes of memory\n",
_TEST_SZ * (cntr - _BankAndSizeForTest));
if( cntr == _BankAndSizeForTest ) {
DBG( DBG_LOW, "No memory ! No scanner...\n" );
return retval;
}
#ifdef DEBUG
tmpByte = IODataRegisterFromScanner( ps, 0x18 );
DBG( DBG_LOW, "tmpByte[0x18] = 0x%02x\n",tmpByte );
#endif
tmpByte = IODataRegisterFromScanner( ps, 0x0e );
DBG( DBG_LOW, "tmpByte = 0x%02x, cntr = %lu, AsicId = 0x%02x\n",
tmpByte, cntr, ps->sCaps.AsicID );
/* 128k */
if ((_TEST_SZ * (cntr - _BankAndSizeForTest) == 1 << 17) &&
(ps->sCaps.AsicID == _ASIC_IS_96003)) {
/*
* if 128k then must be a 9630 or above
* hack, test for 12000P, The 9630 returns an 0x08
*/
if ( tmpByte == 0x02 ) {
/*
* as we currently can't automagically detect an A3I we have to
* use the override switch
*/
if( _OVR_PLUSTEK_A3I == ps->ModelOverride ) {
DBG( DBG_LOW, "Model Override --> A3I\n" );
ModelSetA3I( ps );
} else {
ModelSet12000( ps );
DBG( DBG_LOW, "It seems we have a 12000P/96000P\n" );
}
} else {
ModelSet9630( ps );
DBG( DBG_LOW, "It seems we have a 9630\n" );
}
retval = _OK;
} else {
DBG( DBG_LOW, "Scanner is not a 9630 or above\n");
if ( tmpByte != 0x0f ) {
DBG( DBG_LOW, "Looks like a 600!\n" );
if (( 0x08 == tmpByte ) &&
((_TEST_SZ * (cntr - _BankAndSizeForTest)) == 32768 )) {
DBG( DBG_LOW, "But it is a 4830P!!! "
"(by mkochano@ee.pw.edu.pl)\n" );
ModelSet4830( ps );
} else {
ModelSet600( ps );
}
}
#ifdef DEBUG
else
DBG( DBG_LOW, "It seems we have a 4830\n" );
#endif
retval = _OK;
}
return retval;
}
/*.............................................................................
* setup ASIC registers and clear all scan states (no stepping)
*/
static void p48xxSetAsicRegisters( pScanData ps )
{
memset( &ps->AsicReg, 0, sizeof(ps->AsicReg));
memset( &ps->Asic96Reg, 0, sizeof(ps->Asic96Reg));
memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
ps->AsicReg.RD_LineControl = ps->TimePerLine;
ps->AsicReg.RD_ScanControl = _SCAN_LAMP_ON;
ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0;
ps->AsicReg.RD_Origin = 0;
ps->AsicReg.RD_Pixels = 5110; /*ps->RdPix;*/
ps->Asic96Reg.RD_MotorControl = 0;
ps->Asic96Reg.RD_WatchDogControl = 0; /* org. val = 0x8f; */
IOPutOnAllRegisters( ps );
}
/*.............................................................................
* use the internal memory of a scanner to find the model
*/
static int p48xxCheck4800Memory( pScanData ps )
{
int retval;
ULong ul;
pUChar buffer;
DBG( DBG_LOW, "p48xxCheck4800Memory()\n" );
buffer = _KALLOC( 2560, GFP_KERNEL ); /* 1280: Read,1280:Write */
if( NULL == buffer )
return _E_ALLOC;
retval = _OK;
/* bank 0, size 2k */
ps->OpenScanPath( ps );
p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest );
for (ul = 0; ul < 1280; ul++)
buffer[ul] = (UChar)ul; /* prepare content */
IOMoveDataToScanner( ps, buffer, 1280 ); /* fill to buffer */
p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest );
ps->CloseScanPath( ps );
/* read data back */
IOReadScannerImageData( ps, buffer + 1280, 1280 );
for( ul = 0; ul < 1280; ul++ ) {
if( buffer[ul] != buffer[ul+1280] ) {
DBG( DBG_HIGH, "Error in memory test at pos %lu (%u != %u)\n",
ul, buffer[ul], buffer[ul+1280] );
retval = _E_NO_DEV;
break;
}
}
_KFREE(buffer);
return retval;
}
/*.............................................................................
* call all other modules, to initialize themselves
*/
static int p48xxInitAllModules( pScanData ps )
{
int result;
result = DacInitialize( ps );
if( _OK != result )
return result;
result = ImageInitialize( ps );
if( _OK != result )
return result;
result = IOFuncInitialize( ps );
if( _OK != result )
return result;
result = IOInitialize( ps );
if( _OK != result )
return result;
result = MotorInitialize( ps );
if( _OK != result )
return result;
/*
* in debug version, check all function pointers
*/
#ifdef DEBUG
if( _FALSE == MiscAllPointersSet( ps ))
return _E_INTERNAL;
#endif
return _OK;
}
/*.............................................................................
*
*/
static int p48xxReadWriteTest( pScanData ps )
{
int retval;
DBG( DBG_LOW, "p48xxReadWriteTest()\n" );
/*
* determine the model by the ASIC type (except for 4830/9630)
* might want to make a SetModelCommon() someday for this...
*/
ps->RedDataReady = 0x01; /* normal for Red and Green */
ps->GreenDataReady = 0x02;
ps->AsicRedColor = 0x01;
ps->AsicGreenColor = 0x03;
/*
* if not already set, try to find ASIC type (96001 or 96003)
*/
if ( _NO_BASE == ps->sCaps.wIOBase ) {
/* get copy of asic id */
ps->sCaps.AsicID = IODataRegisterFromScanner( ps, ps->RegAsicID );
if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) {
/* actually either a 4830, 9630, 12000, find out later */
DBG( DBG_LOW, "Found a 96003 ASIC at Reg 0x%x\n", ps->RegAsicID );
ModelSet4830( ps );
} else {
if ( _ASIC_IS_96001 == ps->sCaps.AsicID ) {
DBG( DBG_LOW, "Found a 96001 ASIC at Reg 0x%x\n",
ps->RegAsicID );
ModelSet4800( ps );
} else {
DBG( DBG_LOW, "Can't find your model, asic = 0x%x\n",
ps->sCaps.AsicID );
return _E_NO_ASIC;
}
}
}
/*
* set the registers according to the assumptions above
*/
p48xxSetAsicRegisters( ps );
if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) {
retval = p48xxDoTest( ps );
/*
* as we may now have detected another model, we have to set
* the registers to their new values...
* and maybe the modules have to be reset as well
*/
if( _OK == retval ) {
p48xxSetAsicRegisters( ps );
retval = p48xxInitAllModules( ps );
}
return retval;
}
/*
* this part will be reached only for the 4800 - ASIC 96001
* we check only the memory as the original driver does
*/
return p48xxCheck4800Memory( ps );
}
/*.............................................................................
* 1) Setup the registers of asic.
* 2) Determine which type of CCD we are using
* 3) According to the CCD, prepare the CCD dependent veriables
* SONY CCD:
* The color exposure sequence: Red, Green (after 11 red lines),
* Blue (after 8 green lines)
* TOSHIBA CCD:
* The color exposure sequence: Red, Blue (after 11 red lines),
* Green (after 8 blue lines)
*/
static void p48xxSetupScannerVariables( pScanData ps )
{
UChar tmp;
TimerDef timer;
DBG( DBG_LOW, "p48xxSetupScannerVariables()\n" );
ps->OpenScanPath( ps );
IODataToRegister( ps, ps->RegModelControl2, _Model2ChannelMult );
if( 2 == IODataFromRegister( ps, ps->RegWriteIOBusDecode1 )) {
DBG( DBG_LOW, "Scanner has 97003 ASIC too.\n" );
ps->f97003 = _TRUE;
ps->b97003DarkR = 8;
ps->b97003DarkG = 8;
ps->b97003DarkB = 8;
ps->Asic96Reg.u26.RD_ModelControl2 = _Model2ChannelMult;
} else {
DBG( DBG_LOW, "No ASIC 97003 found.\n" );
ps->f97003 = _FALSE;
ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort;
}
IODataToRegister( ps, ps->RegModelControl2,
ps->Asic96Reg.u26.RD_ModelControl2 );
tmp = IODataFromRegister( ps, ps->RegStatus );
DBG( DBG_LOW, "Status-Register = 0x%02X\n", tmp );
#ifdef DEBUG
if( tmp & _FLAG_P96_MOTORTYPE ) {
DBG( DBG_LOW, "Scanner has Full/Half Stepping drive\n" );
} else {
DBG( DBG_LOW, "Scanner has Micro Stepping drive\n" );
}
#endif
if( tmp & _FLAG_P96_CCDTYPE) {
ps->fSonyCCD = _FALSE;
DBG( DBG_LOW, "CCD is NEC/TOSHIBA Type\n" );
} else {
ps->fSonyCCD = _TRUE;
DBG( DBG_LOW, "CCD is SONY Type\n" );
}
ps->CloseScanPath( ps );
ps->b1stColorByte = ps->AsicRedColor;
ps->b1stColor = ps->RedDataReady;
if (ps->fSonyCCD) {
ps->b2ndColorByte = ps->AsicGreenColor;
ps->b2ndColor = ps->GreenDataReady;
ps->b3rdColorByte = _ASIC_BLUECOLOR;
ps->b3rdColor = _BLUE_DATA_READY;
} else { /* NEC/Toshiba CCD */
ps->b2ndColorByte = _ASIC_BLUECOLOR;
ps->b2ndColor = _BLUE_DATA_READY;
ps->b3rdColorByte = ps->AsicGreenColor;
ps->b3rdColor = ps->GreenDataReady;
}
ps->b1stMask = (Byte)~ps->b1stColor;
ps->b2ndMask = (Byte)~ps->b2ndColor;
ps->b3rdMask = (Byte)~ps->b3rdColor;
ps->b1stLinesOffset = 17;
ps->b2ndLinesOffset = 9;
/*
* calculate I/O Timer
* if we cannot read 200 lines within 1 second, the I/O time has to add 2
* CalculateIOTime ()
*/
if( _PORT_SPP != ps->IO.portMode ) {
UShort wLines = 200;
pUChar pBuf;
pBuf = _KALLOC((_BUF_SIZE_BASE_CONST * 2), GFP_KERNEL );
if ( NULL != pBuf ) {
MiscStartTimer( &timer, _SECOND );
do {
IOReadScannerImageData( ps, pBuf, (_BUF_SIZE_BASE_CONST * 2));
wLines--;
} while (!MiscCheckTimer( &timer) && wLines);
if( !wLines )
ps->bExtraAdd = 0;
else
ps->bExtraAdd = 2;
_KFREE( pBuf );
} else {
ps->bExtraAdd = 2; /* poor resource */
}
} else {
ps->bExtraAdd = 0;
}
}
/*.............................................................................
*
*/
static void p48xxSetGeneralRegister( pScanData ps )
{
if( MODEL_OP_A3I == ps->sCaps.Model ) {
ps->AsicReg.RD_ModelControl = _ModelDpi400 | _ModelWhiteIs0 |
_ModelMemSize128k4;
}
ps->AsicReg.RD_ModeControl = _ModeScan;
/* WORK: ps->PhysicalDpi should be correct, but the we have to work
* on motor.c again to use other running-tables
* if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) {
*/
if ( ps->DataInf.xyAppDpi.y <= 300 ) {
/* HEINER:A3I
if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) {
*/
ps->Asic96Reg.RD_MotorControl = (ps->FullStep | ps->IgnorePF |
ps->MotorOn | _MotorDirForward);
} else {
ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF | ps->MotorOn |
_MotorDirForward);
}
if ( ps->DataInf.wPhyDataType == COLOR_BW ) {
ps->AsicReg.RD_ScanControl = ps->bLampOn;
if (!(ps->DataInf.dwScanFlag & SCANDEF_Inverse))
ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT;
} else {
ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE;
if (ps->DataInf.dwScanFlag & SCANDEF_Inverse)
ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT;
}
if (ps->DataInf.xyPhyDpi.x <= 200)
ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE;
DBG( DBG_LOW, "RD_ModeControl = 0x%02x\n", ps->AsicReg.RD_ModeControl );
DBG( DBG_LOW, "RD_MotorControl = 0x%02x\n", ps->Asic96Reg.RD_MotorControl );
DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl );
}
/*.............................................................................
*
*/
static void p48xxSetupScanningCondition( pScanData ps )
{
DBG( DBG_LOW, "p48xxSetupScanningCondition()\n" );
IORegisterDirectToScanner( ps, ps->RegInitDataFifo );
/* Cal64kTime (); */
if( MODEL_OP_A3I == ps->sCaps.Model )
ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane *
5UL);
else
ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane *
10UL / 3UL);
DBG( DBG_LOW, "wLinesPer64kTime = %u\n", ps->wLinesPer64kTime );
ps->InitialSetCurrentSpeed( ps );
DBG( DBG_LOW, "Current Speed = %u\n", ps->bCurrentSpeed );
ps->bMinReadFifo = (Byte)((ps->DataInf.dwAsicBytesPerPlane + 511) / 512);
DBG( DBG_LOW, "MinReadFifo = %u\n", ps->bMinReadFifo );
p48xxSetGeneralRegister( ps );
/*
* if speed is not the fastest and DPI is less than 400, do half steps
*/
if( ps->DataInf.wPhyDataType >= COLOR_256GRAY &&
!(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= 300)) {
/* HEINER:A3I
if( !(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi)) {
*/
ps->fHalfStepTableFlag = _TRUE;
ps->Asic96Reg.RD_MotorControl &= ps->StepMask;
}
ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x;
DBG( DBG_LOW, "RD_Dpi = %u\n", ps->AsicReg.RD_Dpi );
/* SetStartStopRegister (ps) */
ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + ps->Device.DataOriginX +
ps->DataInf.crImage.x);
if (ps->DataInf.wPhyDataType < COLOR_256GRAY) {
ps->AsicReg.RD_Pixels =
(UShort)(ps->DataInf.dwAsicPixelsPerPlane + 7) & 0xfff8;
} else {
ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicPixelsPerPlane;
}
DBG( DBG_LOW, "RD_Pixels = %u\n", ps->AsicReg.RD_Pixels );
/* SetupMotorStart () */
IORegisterDirectToScanner( ps, ps->RegInitDataFifo);
ps->SetupMotorRunTable( ps );
IOSetToMotorRegister( ps );
ps->pCurrentColorRunTable = ps->pColorRunTable;
ps->bCurrentLineCount = 0;
IOPutOnAllRegisters( ps );
ps->OpenScanPath( ps );
/*
* when using the full-step speed on 600 dpi models, then set
* the motor into half-step mode, to avoid that the scanner hits
* the back of its cover
*/
if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) {
ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep;
}
IODataToRegister( ps, ps->RegMotorControl,
(Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn));
IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl);
IORegisterToScanner( ps, ps->RegInitDataFifo );
ps->CloseScanPath( ps );
}
/*.............................................................................
* switch the motor off and put the scanner into idle mode
*/
static void p48xxPutToIdleMode( pScanData ps )
{
DBG( DBG_LOW, "Putting Scanner (ASIC 96001/3) into Idle-Mode\n" );
/*
* turn off motor
*/
ps->Asic96Reg.RD_MotorControl = 0;
IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
}
/*.............................................................................
* for P96001/3 ASIC
* do all the preliminary stuff here (calibrate the scanner and move the
* sensor to it´s start position, also setup the driver for the
* current run)
*/
static int p48xxCalibration( pScanData ps )
{
DBG( DBG_LOW, "p48xxCalibration()\n" );
ps->Scan.bFifoSelect = ps->RegGFifoOffset;
while (_TRUE) {
_ASSERT(ps->WaitForShading);
if (ps->WaitForShading( ps )) {
if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
/* HEINER:A3I disable !! */
MotorP96AheadToDarkArea( ps );
if( ps->Scan.fRefreshState ) {
ps->Scan.fRefreshState = _FALSE;
if (!ps->fReshaded) {
ps->fReshaded = _TRUE;
if (ps->fColorMoreRedFlag || ps->fColorMoreBlueFlag) {
continue;
}
}
}
}
break;
} else {
ps->fScanningStatus = _FALSE;
ps->DataInf.dwAppLinesPerArea = 0;
return _E_TIMEOUT;
}
}
if((ps->sCaps.AsicID != _ASIC_IS_96001) &&
(ps->DataInf.wPhyDataType != COLOR_BW)) {
DacP96WriteBackToGammaShadingRAM(ps);
}
if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
ps->bExtraMotorCtrl = 0;
ps->Scan.fMotorBackward = _TRUE;
MotorP96ConstantMoveProc( ps, 4000 );
}
/*
* move sensor and setup scanner for grabbing the picture
*/
_ASSERT(ps->WaitForPositionY);
ps->WaitForPositionY(ps);
return _OK;
}
/************************ exported functions *********************************/
/*.............................................................................
* initialize the register values and function calls for the 96001/3 asic
*/
int P48xxInitAsic( pScanData ps )
{
DBG( DBG_LOW, "P48xxInitAsic()\n" );
ps->IO.bOpenCount = 0;
ps->RegSwitchBus = 0;
ps->RegReadDataMode = 1;
ps->RegWriteDataMode = 2;
ps->RegEPPEnable = 3;
ps->RegInitDataFifo = 4;
ps->RegForceStep = 5;
ps->RegInitScanState = 6;
ps->RegRefreshScanState = 7;
ps->RegStatus = 0x10;
ps->RegFifoOffset = 0x11;
ps->RegGetScanState = 0x12;
ps->RegAsicID = 0x13; /* Determine the asic */
ps->RegReadIOBufBus = 0x17;
ps->RegModeControl = 0x18;
ps->RegLineControl = 0x19;
ps->RegScanControl = 0x1a;
ps->RegMotorControl = 0x1b;
ps->RegModelControl = 0x1c;
ps->RegMemAccessControl = 0x1d;
ps->RegDpiLow = 0x1e;
ps->RegDpiHigh = 0x1f;
ps->RegScanPosLow = 0x20;
ps->RegScanPosHigh = 0x21;
ps->RegWidthPixelsLow = 0x22;
ps->RegWidthPixelsHigh = 0x23;
ps->RegThresholdControl = 0x24;
ps->RegWatchDogControl = 0x25;
ps->RegModelControl2 = 0x26;
ps->RegThresholdGapControl = 0x27;
ps->RegRedChShadingOffset = 0x28;
ps->RegGreenChShadingOffset = 0x29;
ps->RegRedDCAdjust = 0x27; /* not sure why these are dup's */
ps->RegGreenDCAdjust = 0x28;
ps->RegBlueDCAdjust = 0x29;
ps->RegBlueChShadingOffset = 0x2a;
ps->RegRedChDarkOffset = 0x2b;
ps->RegGreenChDarkOffset = 0x2c;
ps->RegBlueChDarkOffset = 0x2d;
ps->RegWriteIOBusDecode1 = 0x2e;
ps->RegWriteIOBusDecode2 = 0x2f;
ps->RegScanStateControl = 0x30;
ps->RegRedChEvenOffset = 0x31;
ps->RegGreenChEvenOffset = 0x32;
ps->RegBlueChEvenOffset = 0x33;
ps->RegRedChOddOffset = 0x34;
ps->RegGreenChOddOffset = 0x35;
ps->RegBlueChOddOffset = 0x36;
ps->RegRedGainOutDirect = 0x37;
ps->RegGreenGainOutDirect = 0x38;
ps->RegBlueGainOutDirect = 0x39;
ps->RegLedControl = 0x3a;
ps->RegShadingCorrectCtrl = 0x3b;
ps->RegScanStateBegin = 0x40; /* (0, 1) */
ps->RegScanStateEnd = 0x5f; /* (62, 63) */
/*
* setup function calls
*/
ps->ReadWriteTest = p48xxReadWriteTest;
ps->SetupScannerVariables = p48xxSetupScannerVariables;
ps->SetupScanningCondition = p48xxSetupScanningCondition;
ps->PutToIdleMode = p48xxPutToIdleMode;
ps->Calibration = p48xxCalibration;
/*
* setup misc
*/
ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF;
ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE;
ps->MotorFreeRun = 0x80;
ps->bLampOn = _SCAN_LAMP_ON;
ps->f97003 = _FALSE;
/*
* initialize the other modules
*/
return p48xxInitAllModules( ps );
}
/* END PLUSTEK-PP_P48xx.C ...................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,456 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_procfs.c - this is the interface to the proc filesystem
*.............................................................................
*
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.37 - initial version
* 0.38 - changes according to generic structure changes
* 0.39 - added info about forceMode and slowIO
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __KERNEL__
#include <linux/proc_fs.h>
#include "plustek-pp_scan.h"
/* toggled by your kernel configuration */
#ifdef CONFIG_PROC_FS
/****************************** static vars **********************************/
/*
* for the proc filesystem
*/
extern struct proc_dir_entry proc_root;
static struct proc_dir_entry *base = NULL;
static struct proc_dir_entry *binfo = NULL;
static ULong devcount;
/* parallel port modes... */
static char *procfsPortModes[] = {
"EPP",
"SPP",
"BiDi (PS/2)",
"ECP"
"unknown",
NULL
};
/* CCD-Types (as for ASIC 98001 based series) */
static TabDef procfsCCDTypes98001[] = {
{ _CCD_3797, "3797" },
{ _CCD_3717, "3717" },
{ _CCD_535, "535" },
{ _CCD_2556, "2556" },
{ _CCD_518, "518" },
{ _CCD_539, "539" },
{ -1 , "unknown" }
};
/* CCD-Types (as for ASIC 98003 based series) */
static TabDef procfsCCDTypes98003[] = {
{ _CCD_3797, "3797" },
{ _CCD_3799, "3799" },
{ _CCD_535, "535" },
{ _CCD_2556, "2556" },
{ _CCD_518, "518" },
{ _CCD_539, "539" },
{ _CCD_3777, "3777" },
{ _CCD_548 , "548" },
{ -1 , "unknown" }
};
/****************************** local functions ******************************/
#ifndef LINUX_24
/*.............................................................................
* This is called as the fill_inode function when an inode
* is going into (fill = 1) or out of service (fill = 0).
*
* Note: only the top-level directory needs to do this; if
* a lower level is referenced, the parent will be as well.
*
* Here simply a dummy function
*/
static void procfsFillFunc( struct inode *inode, int fill )
{
}
#endif
/*.............................................................................
* returns a pointer to the port-mode string
*/
static const char* procfsGetMode( int mode )
{
if((mode < _PORT_EPP) || (mode > _PORT_ECP))
return procfsPortModes[_PORT_ECP+1];
return procfsPortModes[mode];
}
/*.............................................................................
* determines CCD-Type string
*/
static const char* procfsGetCCDType( pScanData ps )
{
int i;
int ccd_id = ps->Device.bCCDID;
pTabDef tab = procfsCCDTypes98001;
if( _IS_ASIC98(ps->sCaps.AsicID)) {
if(_ASIC_IS_98003 == ps->sCaps.AsicID)
tab = procfsCCDTypes98003;
/* seek down the description table */
for( i = 0; -1 != tab[i].id; i++ ) {
if( tab[i].id == ccd_id )
return tab[i].desc;
}
} else {
/* for older scanners only this info is available */
if( ps->fSonyCCD )
return "SONY Type";
else
return "NEC/TOSHIBA Type";
}
/* return the last entry if nothing applies! */
return tab[(sizeof(procfsCCDTypes98001)/sizeof(TabDef)-1)].desc;
}
/*.............................................................................
* will be called when reading the proc filesystem:
* cat /proc/pt_drv/info
*/
static int procfsBInfoReadProc( char *buf, char **start, off_t offset,
int count, int *eof, void *data )
{
int len = 0;
len += sprintf( buf, "Plustek Flatbed Scanner Driver version %d.%d-%d\n",
_PTDRV_V1, _PTDRV_V0, _PTDRV_BUILD );
len += sprintf( buf + len, "Devices : %lu\n", *((pULong)data) );
len += sprintf( buf + len, "IOCTL-Version: 0x%08x\n", _PTDRV_IOCTL_VERSION );
return len;
}
/*.............................................................................
* will be called when reading the proc filesystem:
* cat /proc/pt_drv/deviceX/info
*/
static int procfsInfoReadProc( char *buf, char **start, off_t offset,
int count, int *eof, void *data )
{
int len = 0;
pScanData ps = (pScanData)data;
/* Tell us something about the device... */
if( NULL != ps ) {
len += sprintf( buf+len, "Model : %s\n",
MiscGetModelName(ps->sCaps.Model));
len += sprintf( buf+len, "Portaddress : 0x%X\n", ps->IO.portBase );
len += sprintf( buf+len, "Portmode : %s (%s I/O, %s)\n",
procfsGetMode(ps->IO.portMode),
(ps->IO.slowIO == _TRUE?"delayed":"fast"),
(ps->IO.forceMode == 0?"autodetect":"forced"));
len += sprintf( buf+len, "Buttons : %u\n", ps->Device.buttons);
len += sprintf( buf+len, "Warmuptime : %us\n", ps->warmup );
len += sprintf( buf+len, "Lamp timeout: %us\n", ps->lampoff );
len += sprintf( buf+len, "mov-switch : %u\n", ps->ModelOverride );
len += sprintf( buf+len, "I/O-delay : %u\n", ps->IO.delay );
len += sprintf( buf+len, "CCD-Type : %s\n", procfsGetCCDType(ps));
len += sprintf( buf+len, "TPA : %s\n",
(ps->sCaps.dwFlag & SFLAG_TPA) ? "yes":"no" );
}
return len;
}
/*.............................................................................
* will be called when reading the proc filesystem:
* cat /proc/pt_drv/devicex/buttony
*/
static int procfsButtonsReadProc( char *buf, char **start, off_t offset,
int count, int *eof, void *data )
{
Byte b;
int bc = 0;
int len = 0;
pScanData ps = (pScanData)data;
if( NULL != ps ) {
bc = ps->Device.buttons;
}
/* Check the buttons... */
if( 0 != bc ) {
if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) {
MiscClaimPort( ps );
b = IODataRegisterFromScanner( ps, ps->RegStatus );
if(_FLAG_P96_KEY == (b & _FLAG_P96_KEY))
b = 0;
else
b = 1;
MiscReleasePort( ps );
len += sprintf( buf + len, "%u\n", b );
} else
bc = 0;
}
if( 0 == bc )
len += sprintf( buf + len, "none\n" );
return len;
}
/*.............................................................................
* create a procfs entry
*/
static struct proc_dir_entry *new_entry( const char *name, mode_t mode,
struct proc_dir_entry *parent )
{
#ifndef LINUX_24
int len;
#endif
struct proc_dir_entry *ent;
if (mode == S_IFDIR)
mode |= S_IRUGO | S_IXUGO;
else if (mode == 0)
mode = S_IFREG | S_IRUGO;
#ifndef LINUX_24
len = strlen(name) + 1;
/* allocate memory for the entry and the name */
ent = kmalloc(sizeof(struct proc_dir_entry) + len, GFP_KERNEL);
if( NULL == ent )
return NULL;
memset(ent, 0, sizeof(struct proc_dir_entry));
/* position pointer of name to end of the structure*/
ent->name = ((char *) ent) + sizeof(*ent);
strcpy((char *)ent->name, name );
ent->namelen = strlen(name);
ent->mode = mode;
if (S_ISDIR(mode)) {
ent->nlink = 2;
ent->fill_inode = &procfsFillFunc;
} else {
ent->nlink = 1;
}
proc_register( parent, ent );
#else
if (mode == S_IFDIR)
ent = proc_mkdir( name, parent );
else
ent = create_proc_entry( name, mode, parent );
#endif
return ent;
}
/*.............................................................................
* shutdown one proc fs entry
*/
static inline void destroy_proc_entry( struct proc_dir_entry *root,
struct proc_dir_entry **d )
{
#ifndef LINUX_24
proc_unregister( root, (*d)->low_ino );
kfree(*d);
#else
DBG(DBG_HIGH, "pt_drv: proc del '%s' root='%s'\n", (*d)->name, root->name);
remove_proc_entry((*d)->name, root );
#endif
*d = NULL;
}
/*.............................................................................
* shutdown the proc-tree for one device
*/
static void destroy_proc_tree( pScanData ps )
{
int i;
DBG( DBG_HIGH, "pt_drv: destroy_proc_tree !\n" );
if( ps ) {
if( ps->procDir.entry ) {
if( ps->procDir.info )
destroy_proc_entry( ps->procDir.entry, &ps->procDir.info );
for( i = 0; i < ps->Device.buttons; i++ ) {
if( ps->procDir.buttons[i] )
destroy_proc_entry(ps->procDir.entry, &ps->procDir.buttons[i]);
}
destroy_proc_entry( base, &ps->procDir.entry );
}
}
}
/*************************** exported functions ******************************/
/*.............................................................................
* initialize our proc-fs stuff
*/
int ProcFsInitialize( void )
{
DBG( DBG_HIGH, "ProcFsInitialize()\n" );
base = new_entry( _DRV_NAME, S_IFDIR, &proc_root );
if( NULL != base ) {
devcount = 0;
binfo = new_entry( "info", 0, base );
if( NULL != binfo ) {
binfo->read_proc = procfsBInfoReadProc;
binfo->data = &devcount;
}
}
return _OK;
}
/*.............................................................................
* cleanup the base entry
*/
void ProcFsShutdown( void )
{
DBG( DBG_HIGH, "ProcFsShutdown()\n" );
if( NULL != base ) {
if( NULL != binfo )
destroy_proc_entry( base, &binfo );
destroy_proc_entry( &proc_root, &base );
}
devcount = 0;
}
/*.............................................................................
* will be called for each device, that has been found
*/
void ProcFsRegisterDevice( pScanData ps )
{
int i;
char str[20];
if( NULL == base ) {
printk( KERN_ERR "pt_drv : proc not initialised yet!\n");
return;
}
memset( &ps->procDir, 0, sizeof(ProcDirDef));
sprintf( str, "device%lu", ps->devno );
ps->procDir.entry = new_entry( str, S_IFDIR, base );
if( NULL == ps->procDir.entry )
goto error_exit;
ps->procDir.info = new_entry( "info", 0, ps->procDir.entry );
if( NULL == ps->procDir.info )
goto error_exit;
ps->procDir.info->read_proc = procfsInfoReadProc;
ps->procDir.info->data = ps;
for( i = 0; i < ps->Device.buttons; i++ ) {
sprintf( str, "button%u", i );
ps->procDir.buttons[i] = new_entry( str, 0, ps->procDir.entry );
if( NULL == ps->procDir.buttons[i] )
goto error_exit;
ps->procDir.buttons[i]->read_proc = procfsButtonsReadProc;
ps->procDir.buttons[i]->data = ps;
}
devcount++;
return;
error_exit:
printk(KERN_ERR "pt_drv: failure registering /proc/ entry %s.\n", str );
destroy_proc_tree( ps );
}
/*.............................................................................
* cleanup the proc-fs for a certain device
*/
void ProcFsUnregisterDevice( pScanData ps )
{
destroy_proc_tree( ps );
}
#else /* CONFIG_PROC_FS */
int ProcFsInitialize( void )
{
return _OK;
}
void ProcFsShutdown( void )
{
}
void ProcFsRegisterDevice( pScanData ps )
{
}
void ProcFsUnregisterDevice( pScanData ps )
{
}
#endif
#endif /* guard __KERNEL__ */
/* END PLUSTEK-PP_PROCFS.C ..................................................*/

Wyświetl plik

@ -0,0 +1,228 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_procs.h
* here are the prototypes of all exported functions
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson <rick@efn.org>
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - no changes
* 0.33 - no changes
* 0.34 - added this history
* 0.35 - added Kevins´ changes to MiscRestorePort
* changed prototype of MiscReinitStruct
* added prototype for function PtDrvLegalRequested()
* 0.36 - added prototype for function MiscLongRand()
* removed PtDrvLegalRequested()
* changed prototype of function MiscInitPorts()
* 0.37 - added io.c and procfs.c
* added MiscGetModelName()
* added ModelSetA3I()
* 0.38 - added P12 stuff
* removed prototype of IOScannerIdleMode()
* removed prototype of IOSPPWrite()
* 0.39 - moved prototypes for the user space stuff to plustek-share.h
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - added MapAdjust
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __PROCS_H__
#define __PROCS_H__
/*
* implementation in plustekpp-misc.c
*/
pScanData MiscAllocAndInitStruct( void );
int MiscReinitStruct ( pScanData ps );
int MiscInitPorts ( pScanData ps, int port );
void MiscRestorePort ( pScanData ps );
inline void MiscStartTimer ( pTimerDef timer, unsigned long us );
inline int MiscCheckTimer ( pTimerDef timer );
int MiscRegisterPort ( pScanData ps, int portAddr );
void MiscUnregisterPort ( pScanData ps );
int MiscClaimPort ( pScanData ps );
void MiscReleasePort ( pScanData ps );
Long MiscLongRand ( void );
const char *MiscGetModelName( UShort id );
#ifdef DEBUG
Bool MiscAllPointersSet( pScanData ps );
#endif
/*
* implementation in plustekpp-detect.c
*/
int DetectScanner( pScanData ps, int mode );
/*
* implementation in plustekpp-p48xx.c
*/
int P48xxInitAsic( pScanData ps );
/*
* implementation in plustekpp-p9636.c
*/
int P9636InitAsic( pScanData ps );
/*
* implementation in plustekpp-p12.c
*/
int P12InitAsic ( pScanData ps );
void P12SetGeneralRegister( pScanData ps );
/*
* implementation in plustekpp-p12ccd.c
*/
void P12InitCCDandDAC( pScanData ps, Bool shading );
/*
* implementation in plustekpp-models.c
*/
void ModelSet4800 ( pScanData ps );
void ModelSet4830 ( pScanData ps );
void ModelSet600 ( pScanData ps );
void ModelSet12000( pScanData ps );
void ModelSetA3I ( pScanData ps );
void ModelSet9630 ( pScanData ps );
void ModelSet9636 ( pScanData ps );
void ModelSetP12 ( pScanData ps );
/*
* implementation in plustekpp-dac.c
*/
int DacInitialize( pScanData ps );
void DacP98AdjustDark ( pScanData ps );
void DacP98FillGainOutDirectPort ( pScanData ps );
void DacP98FillShadingDarkToShadingRegister( pScanData ps );
void DacP96WriteBackToGammaShadingRAM( pScanData ps );
void DacP98003FillToDAC ( pScanData ps, pRGBByteDef regs, pColorByte data );
void DacP98003AdjustGain( pScanData ps, ULong color, Byte hilight );
Byte DacP98003SumGains ( pUChar pb, ULong pixelsLine );
/*
* implementation in plustekpp-motor.c
*/
int MotorInitialize ( pScanData ps );
void MotorSetConstantMove( pScanData ps, Byte bMovePerStep );
void MotorToHomePosition ( pScanData ps );
void MotorP98GoFullStep ( pScanData ps, ULong dwStep );
void MotorP96SetSpeedToStopProc( pScanData ps );
void MotorP96ConstantMoveProc ( pScanData ps, ULong dwLines );
Bool MotorP96AheadToDarkArea ( pScanData ps );
void MotorP96AdjustCurrentSpeed( pScanData ps, Byte bSpeed );
void MotorP98003BackToHomeSensor ( pScanData ps );
void MotorP98003ModuleForwardBackward( pScanData ps );
void MotorP98003ForceToLeaveHomePos ( pScanData ps );
void MotorP98003PositionYProc ( pScanData ps, ULong steps);
/*
* implementation in plustekpp-map.c
*/
void MapInitialize ( pScanData ps );
void MapSetupDither( pScanData ps );
void MapAdjust ( pScanData ps, int which );
/*
* implementation in plustekpp-image.c
*/
int ImageInitialize( pScanData ps );
/*
* implementation in plustekpp-genericio.c
*/
int IOFuncInitialize ( pScanData ps );
Byte IOSetToMotorRegister ( pScanData ps );
Byte IOGetScanState ( pScanData ps, Bool fOpenned );
Byte IOGetExtendedStatus ( pScanData ps );
void IOGetCurrentStateCount( pScanData, pScanState pScanStep);
int IOIsReadyForScan ( pScanData ps );
void IOSetXStepLineScanTime( pScanData ps, Byte b );
void IOSetToMotorStepCount ( pScanData ps );
void IOSelectLampSource ( pScanData ps );
Bool IOReadOneShadingLine ( pScanData ps, pUChar pBuf, ULong len );
ULong IOReadFifoLength ( pScanData ps );
void IOPutOnAllRegisters ( pScanData ps );
void IOReadColorData ( pScanData ps, pUChar pBuf, ULong len );
/*
* implementation in plustekpp-io.c
*/
int IOInitialize ( pScanData ps );
void IOMoveDataToScanner ( pScanData ps, pUChar pBuffer, ULong size );
void IODownloadScanStates( pScanData ps );
void IODataToScanner ( pScanData, Byte bValue );
void IODataToRegister ( pScanData ps, Byte bReg, Byte bData );
Byte IODataFromRegister ( pScanData ps, Byte bReg );
void IORegisterToScanner ( pScanData ps, Byte bReg );
void IODataRegisterToDAC ( pScanData ps, Byte bReg, Byte bData );
Byte IODataRegisterFromScanner( pScanData ps, Byte bReg );
void IOCmdRegisterToScanner ( pScanData ps, Byte bReg, Byte bData );
void IORegisterDirectToScanner( pScanData, Byte bReg );
void IOSoftwareReset ( pScanData ps );
void IOReadScannerImageData ( pScanData ps, pUChar pBuf, ULong size );
void IOFill97003Register ( pScanData ps, Byte bDecode1, Byte bDecode2 );
void IOOut ( Byte data, UShort port );
void IOOutDelayed( Byte data, UShort port );
Byte IOIn ( UShort port );
Byte IOInDelayed ( UShort port );
/*
* implementation in plustekpp-tpa.c
*/
void TPAP98001AverageShadingData( pScanData ps );
void TPAP98003FindCenterPointer ( pScanData ps );
void TPAP98003Reshading ( pScanData ps );
/*
* implementation in plustekpp-scale.c
*/
void ScaleX( pScanData ps, pUChar inBuf, pUChar outBuf );
/*
* implementation in plustekpp-procfs.c (Kernel-mode only)
*/
#ifdef __KERNEL__
int ProcFsInitialize ( void );
void ProcFsShutdown ( void );
void ProcFsRegisterDevice ( pScanData ps );
void ProcFsUnregisterDevice( pScanData ps );
#endif
#endif /* guard __PROCS_H__ */
/* END PLUSTEK-PP_PROCS.H ...................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,134 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_scale.c
*.............................................................................
*
* Scaling functionality
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.32 - initial version
* 0.33 - no changes
* 0.34 - no changes
* 0.35 - no changes
* 0.36 - no changes
* 0.37 - no changes
* 0.38 - no changes
* 0.39 - no changes
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "plustek-pp_scan.h"
/************************ exported functions *********************************/
/*.............................................................................
* scaling picture data in x-direction, using a DDA algo
* (digital differential analyzer).
*/
void ScaleX( pScanData ps, pUChar inBuf, pUChar outBuf )
{
UChar tmp;
int step;
int izoom;
int ddax;
register ULong i, j, x;
#ifdef DEBUG
_VAR_NOT_USED( dbg_level );
#endif
/* scale... */
izoom = (int)(1.0/ps->DataInf.XYRatio * 1000);
switch( ps->DataInf.wAppDataType ) {
case COLOR_BW : step = 0; break;
case COLOR_HALFTONE: step = 0; break;
case COLOR_256GRAY : step = 1; break;
case COLOR_TRUE24 : step = 3; break; /*NOTE: COLOR_TRUE32 is the same !*/
case COLOR_TRUE48 : step = 6; break;
default : step = 99; break;
}
/*
* when not supported, only copy the data
*/
if( 99 == step ) {
memcpy( outBuf, inBuf, ps->DataInf.dwAppBytesPerLine );
return;
}
/*
* now scale...
*/
if( 0 == step ) {
/*
* binary scaling
*/
ddax = 0;
x = 0;
memset( outBuf, 0, ps->DataInf.dwAppBytesPerLine );
for( i = 0; i < ps->DataInf.dwPhysBytesPerLine*8; i++ ) {
ddax -= 1000;
while( ddax < 0 ) {
tmp = inBuf[(i>>3)];
if((x>>3) < ps->DataInf.dwAppBytesPerLine ) {
if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7))))
outBuf[x>>3] |= (1 << ((~(x & 0x7))&0x7));
}
x++;
ddax += izoom;
}
}
} else {
/*
* color and gray scaling
*/
ddax = 0;
x = 0;
for( i = 0; i < ps->DataInf.dwPhysBytesPerLine*step; i+=step ) {
ddax -= 1000;
while( ddax < 0 ) {
for( j = 0; j < (ULong)step; j++ ) {
if((x+j) < ps->DataInf.dwAppBytesPerLine ) {
outBuf[x+j] = inBuf[i+j];
}
}
x += step;
ddax += izoom;
}
}
}
}
/* END PLUSTEK-PP_SCALE.C ...................................................*/

Wyświetl plik

@ -0,0 +1,185 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_scan.h - the global header for the plustek driver
*.............................................................................
*
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - changed _DODELAY macro to work properly for delays > 5 ms
* 0.33 - no changes
* 0.34 - no changes
* 0.35 - removed _PTDRV_PUT_SCANNER_MODEL from ioctl interface
* 0.36 - now including plustek-share.h from the backend path
* changed _INB/_OUTB to _INB_STATUS, _INB_CTRL, _INB_DATA ...
* 0.37 - added _OUTB_ECTL/_INB_ECTL, _MAX_PTDEVS, _DRV_NAME and _MAX_BTNS
* added _OUTB_STATUS
* 0.38 - added _IS_ASIC96() and _IS_ASIC98() macros
* 0.39 - no changes
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - changed include names
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __PLUSTEK_SCAN_H__
#define __PLUSTEK_SCAN_H__
#ifndef __KERNEL__
# include <stdlib.h>
# include <stdarg.h>
# include <string.h>
# include <stdio.h>
# include <unistd.h>
# include <sched.h>
# include <sys/time.h>
# include <sys/signal.h>
# include <sys/ioctl.h>
# include <sys/io.h>
#else
# include <linux/version.h>
# include "plustek-pp_sysdep.h"
# include <linux/delay.h>
# include <linux/parport.h>
#ifdef LINUX_24
# include <linux/parport_pc.h>
#endif /* LINUX_24 */
#endif /* __KERNEL__ */
/*.............................................................................
* driver properties
*/
#define _DRV_NAME "pt_drv" /* driver's name */
#define _MAX_PTDEVS 4 /* support for 4 devices */
#define _MAX_BTNS 6 /* support for 6 buttons */
#define _PTDRV_MAJOR 40 /* our major number */
/*.............................................................................
* for port operations
*/
# define _OPF ps->IO.fnOut
# define _IPF ps->IO.fnIn
#if 1
#define _OUTB_CTRL(pSD,port_value) _OPF(port_value,pSD->IO.pbControlPort)
#define _OUTB_DATA(pSD,port_value) _OPF(port_value,pSD->IO.pbSppDataPort)
#define _OUTB_ECTL(pSD,port_value) _OPF(port_value,(pSD->IO.portBase+0x402))
#define _OUTB_STATUS(pSD,port_value) _OPF(port_value,pSD->IO.pbStatusPort)
#define _INB_CTRL(pSD) _IPF(pSD->IO.pbControlPort)
#define _INB_DATA(pSD) _IPF(pSD->IO.pbSppDataPort)
#define _INB_EPPDATA(pSD) _IPF(pSD->IO.pbEppDataPort)
#define _INB_STATUS(pSD) _IPF(pSD->IO.pbStatusPort)
#define _INB_ECTL(pSD) _IPF((pSD->IO.portBase+0x402))
#else
#define _OUTB_CTRL(pSD,port_value) parport_pc_write_control(pSD->pp, port_value)
#define _OUTB_DATA(pSD,port_value) parport_pc_write_data(pSD->pp, port_value)
#define _OUTB_STATUS(pSD,port_value) parport_pc_write_status(pSD->pp, port_value)
#define _INB_CTRL(pSD) parport_pc_read_control(pSD->pp)
#define _INB_DATA(pSD) parport_pc_read_data(pSD->pp)
#define _INB_STATUS(pSD) parport_pc_read_status(pSD->pp)
#ifdef LINUX_24
# define _OUTB_ECTL(pSD,port_value) outb_p(port_value,(pSD->IO.portBase+0x402))
# define _INB_EPPDATA(pSD) inb_p(pSD->IO.pbEppDataPort)
# define _INB_ECTL(pSD) inb_p((pSD->IO.portBase+0x402))
#else
# define _OUTB_ECTL(pSD,port_value) parport_pc_write_econtrol(pSD->pp, port_value)
# define _INB_EPPDATA(pSD) parport_pc_read_epp(pSD->pp)
# define _INB_ECTL(pSD) parport_pc_read_econtrol(pSD->pp)
#endif
#endif
/*.............................................................................
* for memory allocation
*/
#ifndef __KERNEL__
# define _KALLOC(x,y) malloc(x)
# define _KFREE(x) free(x)
# define _VMALLOC(x) malloc(x)
# define _VFREE(x) free(x)
#else
# define _KALLOC(x,y) kmalloc(x,y)
# define _KFREE(x) kfree(x)
# define _VMALLOC(x) vmalloc(x)
# define _VFREE(x) vfree(x)
#endif
/*
* WARNING - never use the _SECOND define with the _DODELAY macro !!
* they are for use the the MiscStartTimer function and the _DO_UDELAY macro
*/
#ifndef __KERNEL__
typedef long long TimerDef, *pTimerDef;
#else
typedef long long TimerDef, *pTimerDef;
#endif
#define _MSECOND 1000 /* based on 1 us */
#define _SECOND (1000*_MSECOND)
/*.............................................................................
* timer topics
*/
#ifndef __KERNEL__
#define _DO_UDELAY(usecs) { int i; for( i = usecs; i--; ) outb(0x80,0); }
#define _DODELAY(msecs) { int i; for( i = msecs; i--; ) _DO_UDELAY(1); }
#else
#define _DO_UDELAY(usecs) udelay(usecs)
#define _DODELAY(msecs) mdelay(msecs)
#endif
/*.............................................................................
* include the shared stuff right here, this concerns the ioctl interface
* and the communication stuff
*/
#include "plustek-share.h"
/*.............................................................................
* WARNING: don't move the following headers above the previous defines !!!!!!!
*
* the include files for user-mode and kernel-mode program
*/
#include "plustek-pp_types.h"
#include "plustek-pp_hwdefs.h"
#include "plustek-pp_scandata.h"
#include "plustek-pp_procs.h"
#include "plustek-pp_dbg.h"
/*.............................................................................
* some macros for convenience
*/
#define _IS_ASIC96(aid) ((_ASIC_IS_96001 == aid) || (_ASIC_IS_96003 == aid))
#define _IS_ASIC98(aid) ((_ASIC_IS_98001 == aid) || (_ASIC_IS_98003 == aid))
#endif /* guard __PLUSTEK_SCAN_H__ */
/* END PLUSTEK-PP_SCAN.H ....................................................*/

Wyświetl plik

@ -0,0 +1,645 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_scandata.h - here we define the ScanData structure...
* and a lot of register settings
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson <rick@efn.org>
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - added fWarmupNeeded to struct ScanData
* - removed function FillDataToColorTable from struct ScanData
* - removed dwLampDelay from struct ScanData
* 0.33 - cosmetic changes
* - removed PositionLamp from structure
* - added dwLastPortMode to struct ScanData
* 0.34 - removed WaitBack() function from pScanData structure
* removed wStayMaxStep from pScanData structure
* 0.35 - removed SetInitialGainRAM from pScanData structure
* changed ModelStr list
* 0.36 - added some defines for the ASIC 96001 (model 4800)
* added wDither to DataInfo structure
* removed dwPreferSize from struct ScannerCaps
* cleanup
* moved all stuff that is used by the backend and the driver
* to plustek-share.h which is in the backend directory
* added ModelOverride parameter to struct
* added strcut pardevice to struct
* 0.37 - added bIODelay for SPP/BIDI port operations
* added ReadData to struct
* added ProcDirDef
* added ButtonCount
* removed RegisterToScanner from struct
* removed MaxDpiByInterpolation from struct
* 0.38 - added function PutToIdleMode() to struct
* added function Calibration() to struct
* changed interface of the ReInitAsic() function
* major changes: moved a lot of stuff to hwdefs.h
* added IO, Device, Shade, Scan and Bufs to struct
* 0.39 - added forceMode to struct
* added f97003, b97003DarkR, b97003DarkB, b97003DarkG to struct
* 0.40 - no changes
* 0.41 - no changes
* 0.42 - no changes
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __SCANDATA_H__
#define __SCANDATA_H__
/*
*Directory information for the /proc interface
*/
typedef struct {
struct proc_dir_entry *entry; /* Directory /proc/pt_drv/X */
struct proc_dir_entry *info; /* .../info */
struct proc_dir_entry *buttons[_MAX_BTNS]; /* .../buttons */
} ProcDirDef, *pProcDirDef;
/*
* here we have some structs internally used
*/
/* CHECK: replace current stuff by this - looks much better !!! */
#if 0
typedef struct _IMAGESIZE
{
DWORD dwPixels;
DWORD dwBytes;
DWORD dwLines;
DWORD dwBytesCh;
} IMAGESIZE, *PIMAGESIZE;
typedef struct _IMAGEDEF
{
IMAGESIZE Image;
DWORD dwVxDFlag;
DWORD dwScanFlag;
CROPRECT Area;
XY Dpi;
WORD wDataType;
WORD wBrightness;
WORD wPhyDpiY;
WORD wResult;
WORD Reserved;
} IMAGEDEF, *PIMAGEDEF;
#endif
typedef struct {
ULong dwVxdFlag;
ULong dwScanFlag;
/*
* CHECK: why there are dups ?
*/
ULong dwAppLinesPerArea;
ULong dwAppPixelsPerLine;
ULong dwAppPhyBytesPerLine;
ULong dwAppBytesPerLine;
ULong dwAsicPixelsPerPlane;
ULong dwAsicBytesPerPlane;
ULong dwAsicBytesPerLine;
CropRect crImage;
XY xyAppDpi;
XY xyPhyDpi;
pUChar pCurrentBuffer;
UShort wPhyDataType;
UShort wAppDataType;
UShort wYSum;
short siBrightness;
/*
* CHANGE added these vars for scaling
*/
double XYRatio;
ULong dwPhysBytesPerLine;
/*
* CHANGE added this for selecting dither method
*/
UShort wDither;
} DataInfo, *pDataInfo;
/*
* here it is, the great structure
*/
typedef struct scandata
{
#ifdef __KERNEL__
UInt flags; /* as follows: */
#define _PTDRV_INITALIZED 0x00000001
#define _PTDRV_OPEN 0x00000002
struct pardevice *pardev; /* for accessing parport... */
struct parport *pp;
ProcDirDef procDir;
#endif
/*
* device control
*/
ULong devno;
int lampoff;
int warmup;
int lOffonEnd;
/*
* CHECK for controlling the ECP-mode (not used now)
*/
#if 0
Byte bOldECR;
Bool fECPReadWriteTest;
Bool fSkipEcpFlag;
Bool fECPFlag;
Bool fECPtoEPP;
Bool fECRFIFO;
#endif
/*
* the following stuff gets changed on a per model basis
*/
UShort ModelOverride; /* for non-auto detection stuff */
UShort Offset70; /* CHECK: --> to Device */
UShort BufferSizeBase; /* --> to Device */
UShort BufferSizePerModel; /* --> to Device */
UShort TimePerLine; /* --> to Device */
/*
* scanner properties
*/
RegData AsicReg; /* here we have the 98001/3 register set */
Reg96 Asic96Reg; /* here we hold the 96001/3 specific regs */
LensInfo LensInf;
ScannerCaps sCaps;
ULong dwScannerSize;
Byte bCurrentSpeed;
pUChar pbMapRed;
pUChar pbMapGreen;
pUChar pbMapBlue;
ULong TotalBufferRequire;
ULong BufferForColorRunTable;
UShort PhysicalDpi;
UShort RdPix; /* for ASIC 96003 devices */
Byte a_bMapTable[4096 * 3]; /* pre 98001 was 256 * 3 */
Byte a_nbNewAdrPointer[_SCANSTATE_BYTES];
/*
* for P9600x ASIC based scanners
*/
Bool fColorMoreRedFlag;
Bool fColorMoreBlueFlag;
Bool fSonyCCD;
Bool f97003;
Byte AsicRedColor;
Byte AsicGreenColor;
Byte RedDataReady;
Byte GreenDataReady;
Byte b1stColorByte;
Byte b1stColor;
Byte b1stMask;
Byte b2ndColorByte;
Byte b2ndColor;
Byte b2ndMask;
Byte b3rdColorByte;
Byte b3rdColor;
Byte b3rdMask;
Byte b1stLinesOffset;
Byte b2ndLinesOffset;
Byte bLampOn;
Byte bExtraAdd;
Byte bFifoCount;
Byte bMinReadFifo;
Byte FullStep;
Byte StepMask;
Byte MotorOn;
Byte MotorFreeRun;
Byte IgnorePF;
Byte bMotorStepTableNo;
/* for ASIC 97003... */
Byte b97003DarkR;
Byte b97003DarkG;
Byte b97003DarkB;
/* CHECK: to Scan!!!! */
pUChar pGetBufR; /* NOTE: these aren't actually Red/Green buffer */
pUChar pGetBufG; /* pointers but instead are used */
pUChar pPutBufR; /* generically to point to the first 2 */
pUChar pPutBufG; /* color buffers as temp storage */
pUChar pCurrentColorRunTable;
UShort a_wGrayInitTime[3];
UShort a_wColorInitTime[3];
UShort BackwardSteps;
UShort wLinesPer64kTime;
UShort ShadingBufferSize;
UShort ShadingBankSize;
UShort ShadingBankRed;
UShort ShadingBankGreen;
UShort ShadingBankBlue;
UShort ShadingScanLineBlks;
UShort ShadingScanLineLen;
UShort wOverBlue;
UShort FBKScanLineBlks;
UShort FBKScanLineLenBase;
UShort FBKScanLineLen;
UShort OneScanLineLen;
/*
* the DAC part - to Shade !!!
*/
UShort wsDACCompareHighRed, wsDACCompareLowRed;
UShort wsDACCompareHighGreen, wsDACCompareLowGreen;
UShort wsDACCompareHighBlue, wsDACCompareLowBlue;
UShort wsDACOffsetRed, wsDACOffsetGreen, wsDACOffsetBlue;
Byte bsPreRedDAC, bsPreGreenDAC, bsPreBlueDAC;
Byte bRedDAC, bGreenDAC, bBlueDAC;
Byte bRedGainIndex, bGreenGainIndex, bBlueGainIndex;
/*
* for image description
*/
DataInfo DataInf;
Bool fReshaded;
ULong dwDitherIndex;
Bool fDoFilter, fFilterFirstLine;
ULong dwDivFilter;
ULong dwMul;
Byte bOffsetFilter;
ULong dwLinesFilter;
pUChar pFilterBuf, pEndBuf;
pUChar pGet1, pGet2, pGet3;
Byte bSetScanModeFlag; /* see Section 5 - Scanmodes --> ps->Shade.bIntermediate*/
/*
* some admin vals (they used to be global vars in the original driver)
*/
Bool fScanningStatus;
Byte bLastLampStatus;
Bool fWarmupNeeded;
ULong dwOffset70;
ULong dwMaxReadFifoData;
/*
*
*/
pUChar pColorRunTable;
pUChar pPrescan16;
pUChar pPrescan8;
UShort BufferForDataRead1;
ULong BufferFor1stColor;
ULong BufferFor2ndColor;
pUChar driverbuf;
pUChar pEndBufR;
pUChar pEndBufG;
pUChar pProcessingBuf;
/*
* formerly used as global vars in ioproc.c, now in genericio.c
*/
pUChar pScanBuffer1;
pUChar pScanBuffer2;
pModeTypeVar lpEppColorHomePos;
pModeTypeVar lpEppColorExposure;
pModeTypeVar lpBppColorHomePos;
pModeTypeVar lpSppColorHomePos;
UShort wMinCmpDpi;
pModeTypeVar a_ColorSettings;
pDiffModeVar a_tabDiffParam;
Byte bSpeed48;
Byte bSpeed32;
Byte bSpeed24;
Byte bSpeed16;
Byte bSpeed12;
Byte bSpeed8;
Byte bSpeed6;
Byte bSpeed4;
Byte bSpeed3;
Byte bSpeed2;
Byte bSpeed1;
Byte bHpMotor;
Byte bStepSpeed;
ULong dwFullStateSpeed;
/*
* reference to globals from motor.c
*/
Bool fHalfStepTableFlag;
Bool fFullLength;
Byte bMoveDataOutFlag;
Byte bExtraMotorCtrl;
Byte bFastMoveFlag;
Byte bOldStateCount;
Byte bMotorSpeedData;
Byte bCurrentLineCount;
Byte bNewGap;
Byte bNewCurrentLineCountGap;
UShort wMaxMoveStep;
ULong dwScanStateCount;
ULong dwColorRunIndex;
pByte a_bColorByteTable;
pUChar pScanState;
pUShort a_wMoveStepTable;
/*
* for shading - dac.c
* CHECK: move to ps->Shade
*/
Byte bShadingTimeFlag;
ULong dwShadow, dwShadowCh;
ULong dwHilight, dwHilightCh;
ULong dwShadingLen, dwShadingPixels;
pUShort pwShadow;
/*
* from transform.c
*/
Byte bRedHigh, bGreenHigh, bBlueHigh;
UShort wPosAdjustX;
UShort wNegAdjustX;
UShort wReduceRedFactor;
UShort wReduceGreenFactor;
UShort wReduceBlueFactor;
ULong dwOffsetNegative;
/*
* reference to globals from map.c
*/
#define _DITHERSIZE 64
Byte a_bDitherPattern[_DITHERSIZE];
Short wBrightness;
Short wContrast;
UShort wInitialStep;
ULong dwSizeMustProcess;
/*
* here we have pointers to the functions to call
*/
Bool (*OpenScanPath) (pScanData);
void (*CloseScanPath) (pScanData);
int (*ReadWriteTest) (pScanData);
void (*PutToIdleMode) (pScanData);
int (*Calibration) (pScanData);
void (*SetupScannerVariables) (pScanData);
int (*SetupScanSettings) (pScanData, pScanInfo pInf );
void (*GetImageInfo) (pScanData, pImgDef pInf );
Bool (*WaitForShading) (pScanData);
void (*WaitForPositionY) (pScanData);
void (*InitialSetCurrentSpeed) (pScanData);
Bool (*GotoShadingPosition) (pScanData);
void (*SetupScanningCondition) (pScanData);
void (*SetMotorSpeed) (pScanData,Byte bSpeed,Bool fSetRunState);
void (*FillRunNewAdrPointer) (pScanData);
void (*SetupMotorRunTable) (pScanData);
void (*PauseColorMotorRunStates) (pScanData);
void (*UpdateDataCurrentReadLine)(pScanData);
Bool (*ReadOneImageLine) (pScanData);
/* used only by ASIC9800x Part of the driver ! */
void (*ReInitAsic) (pScanData, Bool shading);
/* value used to read nibble's */
Byte CtrlReadHighNibble;
Byte CtrlReadLowNibble;
/*
* asic register offset values
*/
Byte RegSwitchBus;
Byte RegEPPEnable;
Byte RegECPEnable;
Byte RegReadDataMode;
Byte RegWriteDataMode;
Byte RegInitDataFifo;
Byte RegForceStep;
Byte RegInitScanState;
Byte RegRefreshScanState;
Byte RegThresholdGapControl;
Byte RegADCAddress;
Byte RegADCData;
Byte RegADCPixelOffset;
Byte RegADCSerialOutStr;
Byte RegResetConfig;
Byte RegLensPosition;
Byte RegStatus;
Byte RegWaitStateInsert;
Byte RegFifoOffset;
Byte RegRFifoOffset;
Byte RegGFifoOffset;
Byte RegBFifoOffset;
Byte RegBitDepth;
Byte RegStepControl;
Byte RegMotor0Control;
Byte RegXStepTime;
Byte RegGetScanState;
Byte RegAsicID;
Byte RegReadIOBufBus;
Byte RegMemoryLow;
Byte RegMemoryHigh;
Byte RegModeControl;
Byte RegLineControl;
Byte RegScanControl;
Byte RegMotorControl;
#define _MotorDirForward 0x01 /* go forward */
#define _MotorOn 0x02 /* turn on motor */
#define _MotorIgnorePF 0x04 /* motor rolling don't care */
/* paper define flag */
#define _MotorFreeRun 0x80 /*ScanState count don't stop */
/* Following bits (bit 3 & 4 are depended on StatusPort */
/* bit-7:MotorType when it is 1: */
#define _Motor1FullStep 0x08 /* bit 4 is ignored */
/* When it is 0: */
#define _Motor0FullStepWeak 0 /* Full step (driving weak) */
#define _Motor0HalfStep 0x10 /* 1/2 step */
#define _Motor0QuarterStep 0x08 /* 1/4 step */
#define _Motor0FullStepStrong 0x18 /* Full step (driving strong)*/
#define _MotorStepMask 0xe7
/* for 96001 */
#define _MotorFullStep96001 0x02
#define _MotorOn96001 0x04
#define _MotorIgnorePF96001 0x08
Byte RegConfiguration;
Byte RegModelControl;
Byte RegModel1Control;
Byte RegMemAccessControl;
#define _MemBanks 64 /* the number of banks, 5 ls bits */
#define _MemBankMask (_MemBanks - 1)
#define _MemBankSize1k 0
#define _MemBankSize2k 0x40
#define _MemBankSize4k 0x80
#define _MemBankSize8k 0xc0
/* 96001 specific */
#define _MemBankSize2k96001 0x00
#define _MemBankSize4k96001 0x40
#define _MemBankSize8k96001 0x80
Byte RegDpiLow;
Byte RegDpiHigh;
Byte RegScanPosLow;
Byte RegScanPosHigh;
Byte RegWidthPixelsLow;
Byte RegWidthPixelsHigh;
Byte RegThresholdLow;
Byte RegThresholdHigh;
Byte RegThresholdControl;
Byte RegWatchDogControl;
#define _WDOnIntervalMask 0x0f /* WD * 8192 scan lines to turn
off Lamp */
#define _WDMotorLongInterval 0x40 /* short = 8192 lines time
long = 32768 lines time */
#define _WDEnable 0x80
Byte RegModelControl2;
#define _Model2ChannelSlct 0
#define _Model2ChannelMult 0x01 /* bit on/off accords to JONES */
#define _Model2CCSInvert 0x02
#define _Model2DirectOutPort 0x04
#define _Model2PipeLineDelayN 0x08
#define _Model2ShiftGapTiming10 0x10
#define _Model2BtnKeyPassThrough 0x20
Byte RegRedDCAdjust;
Byte RegGreenDCAdjust;
Byte RegBlueDCAdjust;
Byte RegRedChShadingOffset;
Byte RegGreenChShadingOffset;
Byte RegBlueChShadingOffset;
Byte RegRedChDarkOffset;
Byte RegGreenChDarkOffset;
Byte RegBlueChDarkOffset;
Byte RegWriteIOBusDecode1;
Byte RegWriteIOBusDecode2;
Byte RegScanStateControl;
#define _ScanStateEvenMask 0x0f
#define _ScanStateOddMask 0xf0
Byte RegRedChEvenOffset;
Byte RegGreenChEvenOffset;
Byte RegBlueChEvenOffset;
Byte RegRedChOddOffset;
Byte RegGreenChOddOffset;
Byte RegBlueChOddOffset;
Byte RegRedGainOutDirect;
Byte RegGreenGainOutDirect;
Byte RegBlueGainOutDirect;
Byte RegLedControl;
#define _LedCmdActEnable 0x04
#define _LedMotorActEnable 0x08
#define _LedClrChActEnable 0x10 /* Color Channel Action */
#define _LedLightOnActEnable 0x20
#define _LedHostTurnOnEnable 0x40
#define _LedActControl 0x80
Byte RegShadingCorrectCtrl;
#define _ShadingRCorrectX1 0
#define _ShadingRCorrectX2 0x01
#define _ShadingRCorrectX3 0x02
#define _ShadingRCorrectX4 0x03
#define _ShadingGCorrectX1 0
#define _ShadingGCorrectX2 0x04
#define _ShadingGCorrectX3 0x08
#define _ShadingGCorrectX4 0x0c
#define _ShadingBCorrectX1 0
#define _ShadingBCorrectX2 0x10
#define _ShadingBCorrectX3 0x20
#define _ShadingBCorrectX4 0x30
Byte RegScanStateBegin;
Byte RegRedChDarkOffsetLow;
Byte RegRedChDarkOffsetHigh;
Byte RegGreenChDarkOffsetLow;
Byte RegGreenChDarkOffsetHigh;
Byte RegBlueChDarkOffsetLow;
Byte RegBlueChDarkOffsetHigh;
Byte RegResetPulse0;
Byte RegResetPulse1;
Byte RegCCDClampTiming0;
Byte RegCCDClampTiming1;
Byte RegVSMPTiming0;
Byte RegVSMPTiming1;
Byte RegCCDQ1Timing0;
Byte RegCCDQ1Timing1;
Byte RegCCDQ1Timing2;
Byte RegCCDQ1Timing3;
Byte RegCCDQ2Timing0;
Byte RegCCDQ2Timing1;
Byte RegCCDQ2Timing2;
Byte RegCCDQ2Timing3;
Byte RegADCclockTiming0;
Byte RegADCclockTiming1;
Byte RegADCclockTiming2;
Byte RegADCclockTiming3;
Byte RegADCDVTiming0;
Byte RegADCDVTiming1;
Byte RegADCDVTiming2;
Byte RegADCDVTiming3;
Byte RegScanStateEnd;
/* ASIC 98003 specific*/
Byte RegFifoFullLength0;
Byte RegFifoFullLength1;
Byte RegFifoFullLength2;
Byte RegMotorTotalStep0;
Byte RegMotorTotalStep1;
Byte RegMotorFreeRunCount0;
Byte RegMotorFreeRunCount1;
Byte RegScanControl1;
Byte RegMotorFreeRunTrigger;
Byte RegResetMTSC;
Byte RegMotor1Control;
Byte RegMotor2Control;
Byte RegMotorDriverType;
Byte RegStatus2;
Byte RegExtendedLineControl;
Byte RegExtendedXStep;
Byte RegPllPredivider;
Byte RegPllMaindivider;
Byte RegPllPostdivider;
Byte RegClockSelector;
Byte RegTestMode;
/* CHECK: subject to change */
IODef IO;
DeviceDef Device;
ShadingDef Shade;
ScanDef Scan;
BufferDef Bufs;
} ScanData;
#endif /* guard __SCANDATA_H__ */
/* END PLUTSEK-PP_SCANDATA.H ................................................*/

Wyświetl plik

@ -0,0 +1,279 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_sysdep.h
* a trial to centralize changes between the different
* kernel-versions some stuff is maybe not relevant, but anyway...
*.............................................................................
*
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.30 - initial version
* 0.38 - added this header
* 0.39 - added kernel 2.4 stuff
* 0.40 - added slab.h/malloc.h stuff for kernel >= 2.4.17
* 0.41 - no changes
* 0.42 - added _GET_TIME
* - added LINUX_26 for new kernel
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _SYSDEP_H_
#define _SYSDEP_H_
#ifndef LINUX_VERSION_CODE
# include <linux/version.h>
#endif
#ifndef VERSION_CODE
# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) )
#endif
/* only allow > 2.0.x */
#if LINUX_VERSION_CODE < VERSION_CODE(2,0,0)
# error "This kernel is too old: not supported by this file"
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
# define LINUX_20
#elif LINUX_VERSION_CODE < VERSION_CODE(2,4,0)
# define LINUX_21
#elif LINUX_VERSION_CODE < VERSION_CODE(2,6,0)
# define LINUX_24
#else
# define LINUX_24
# define LINUX_26
#endif
#include <linux/types.h> /* used later in this header */
/* Modularization issues */
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,18)
# define __USE_OLD_SYMTAB__
# define EXPORT_NO_SYMBOLS register_symtab(NULL);
# define REGISTER_SYMTAB(tab) register_symtab(tab)
#else
# define REGISTER_SYMTAB(tab) /* nothing */
#endif
#ifdef __USE_OLD_SYMTAB__
# define __MODULE_STRING(s) /* nothing */
# define MODULE_PARM(v,t) /* nothing */
# define MODULE_PARM_DESC(v,t) /* nothing */
# define MODULE_AUTHOR(n) /* nothing */
# define MODULE_DESCRIPTION(d) /* nothing */
# define MODULE_SUPPORTED_DEVICE(n) /* nothing */
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,31)
# define CLOSETYPE void
# define CLOSERETURN(arg)
#else
# define CLOSETYPE int
# define CLOSERETURN(arg) return arg
#endif
/*
* "select" changed in 2.1.23. The implementation is twin, but this
* header is new
*/
#if LINUX_VERSION_CODE > VERSION_CODE(2,1,22)
# include <linux/poll.h>
#else
# define __USE_OLD_SELECT__
#endif
/* Other change in the fops are solved using pseudo-types */
#if defined(LINUX_21) || defined(LINUX_24) || defined(LINUX_26)
# define lseek_t long long
# define lseek_off_t long long
#else
# define lseek_t int
# define lseek_off_t off_t
#endif
/* changed the prototype of read/write */
#if defined(LINUX_21) || defined (LINUX_24) || defined(LINUX_26) || defined(__alpha__)
# define count_t unsigned long
# define read_write_t long
#else
# define count_t int
# define read_write_t int
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,31)
# define release_t void
# define release_return(x) return
#else
# define release_t int
# define release_return(x) return (x)
#endif
/*
* access to user space: use the 2.1 functions,
* and implement them as macros for 2.0
*/
#ifdef LINUX_20
# include <asm/segment.h>
# define access_ok(t,a,sz) (verify_area((t),(a),(sz)) ? 0 : 1)
# define verify_area_20 verify_area
# define copy_to_user(t,f,n) (memcpy_tofs(t,f,n), 0)
# define __copy_to_user(t,f,n) copy_to_user((t),(f),(n))
# define copy_to_user_ret(t,f,n,r) copy_to_user((t),(f),(n))
# define copy_from_user(t,f,n) (memcpy_fromfs((t),(f),(n)), 0)
# define __copy_from_user(t,f,n) copy_from_user((t),(f),(n))
# define copy_from_user_ret(t,f,n,r) copy_from_user((t),(f),(n))
# define PUT_USER(val,add) (put_user((val),(add)), 0)
# define __PUT_USER(val,add) PUT_USER((val),(add))
# define PUT_USER_RET(val,add,ret) PUT_USER((val),(add))
# define GET_USER(dest,add) ((dest)=get_user((add)), 0)
# define __GET_USER(dest,add) GET_USER((dest),(add))
# define GET_USER_RET(dest,add,ret) GET_USER((dest),(add))
#else
# include <asm/uaccess.h>
# include <asm/io.h>
# define verify_area_20(t,a,sz) (0) /* == success */
# define PUT_USER put_user
# define __PUT_USER __put_user
# define PUT_USER_RET put_user_ret
# define GET_USER get_user
# define __GET_USER __get_user
# define GET_USER_RET get_user_ret
/* starting with 2.4.0-test8, they removed the put_user_ret and get_user_ret
* macros, so we recode'em
*/
#if defined(LINUX_24) || defined(LINUX_26)
#ifndef put_user_ret
# define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
#endif
#ifndef get_user_ret
# define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
#endif
#endif
#endif
/* ioremap */
#ifdef LINUX_20
# define ioremap vremap
# define iounmap vfree
#endif
/* The use_count of exec_domain and binfmt changed in 2.1.23 */
#ifdef LINUX_20
# define INCRCOUNT(p) ((p)->module ? __MOD_INC_USE_COUNT((p)->module) : 0)
# define CURRCOUNT(p) ((p)->module && (p)->module->usecount)
# define DECRCOUNT(p) ((p)->module ? __MOD_DEC_USE_COUNT((p)->module) : 0)
#else
# define INCRCOUNT(p) ((p)->use_count++)
# define CURRCOUNT(p) ((p)->use_count)
# define DECRCOUNT(p) ((p)->use_count--)
#endif
/* register_dynamic no more existent -- just have 0 as inum */
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,29)
# define proc_register_dynamic proc_register
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,37)
# define test_and_set_bit(nr,addr) test_bit((nr),(addr))
# define test_and_clear_bit(nr,addr) clear_bit((nr),(addr))
# define test_and_change_bit(nr,addr) change_bit((nr),(addr))
#endif
/* 2.1.30 removed these functions. Let's define them, just in case */
#if LINUX_VERSION_CODE > VERSION_CODE(2,1,29)
# define queue_task_irq queue_task
# define queue_task_irq_off queue_task
#endif
/* 2.1.10 and 2.1.43 introduced new functions. They are worth using */
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,10)
# include <asm/byteorder.h>
# ifdef __LITTLE_ENDIAN
# define cpu_to_le16(x) (x)
# define cpu_to_le32(x) (x)
# define cpu_to_be16(x) htons((x))
# define cpu_to_be32(x) htonl((x))
# else
# define cpu_to_be16(x) (x)
# define cpu_to_be32(x) (x)
extern inline __u16 cpu_to_le16(__u16 x) { return (x<<8) | (x>>8);}
extern inline __u32 cpu_to_le32(__u32 x) { return((x>>24) |
((x>>8)&0xff00) | ((x<<8)&0xff0000) | (x<<24));}
# endif
# define le16_to_cpu(x) cpu_to_le16(x)
# define le32_to_cpu(x) cpu_to_le32(x)
# define be16_to_cpu(x) cpu_to_be16(x)
# define be32_to_cpu(x) cpu_to_be32(x)
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,43)
# define cpu_to_le16p(addr) (cpu_to_le16(*(addr)))
# define cpu_to_le32p(addr) (cpu_to_le32(*(addr)))
# define cpu_to_be16p(addr) (cpu_to_be16(*(addr)))
# define cpu_to_be32p(addr) (cpu_to_be32(*(addr)))
extern inline void cpu_to_le16s(__u16 *a) {*a = cpu_to_le16(*a);}
extern inline void cpu_to_le32s(__u16 *a) {*a = cpu_to_le32(*a);}
extern inline void cpu_to_be16s(__u16 *a) {*a = cpu_to_be16(*a);}
extern inline void cpu_to_be32s(__u16 *a) {*a = cpu_to_be32(*a);}
# define le16_to_cpup(x) cpu_to_le16p(x)
# define le32_to_cpup(x) cpu_to_le32p(x)
# define be16_to_cpup(x) cpu_to_be16p(x)
# define be32_to_cpup(x) cpu_to_be32p(x)
# define le16_to_cpus(x) cpu_to_le16s(x)
# define le32_to_cpus(x) cpu_to_le32s(x)
# define be16_to_cpus(x) cpu_to_be16s(x)
# define be32_to_cpus(x) cpu_to_be32s(x)
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,15)
# define __USE_OLD_REBUILD_HEADER__
#endif
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,30)
# define in_interrupt() (intr_count!=0)
#endif
/*
* from 2.4.17 on, they decided to use slab.h instead of malloc.h... so what...
* somewhere from 2.4.18-pre9 they skipped get_fast_time...
*/
#if LINUX_VERSION_CODE < VERSION_CODE(2,4,17)
# include "linux/malloc.h"
# define _GET_TIME get_fast_time
#else
# include "linux/slab.h"
# define _GET_TIME do_gettimeofday
#endif
#endif /* _SYSDEP_H_ */
/* END PLUSTEK-PP_SYSDEP.H ..................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,161 @@
/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_types.h - some typedefs and error codes
*.............................................................................
*
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - added _VAR_NOT_USED()
* 0.33 - no changes
* 0.34 - no changes
* 0.35 - no changes
* 0.36 - added _E_ABORT and _E_VERSION
* 0.37 - moved _MAX_DEVICES to plustek_scan.h
* added pChar and TabDef
* 0.38 - comment change for _E_NOSUPP
* added RGBByteDef, RGBWordDef and RGBULongDef
* replaced AllPointer by DataPointer
* replaced AllType by DataType
* added _LOBYTE and _HIBYTE stuff
* added _E_NO_ASIC and _E_NORESOURCE
* 0.39 - no changes
* 0.40 - moved _VAR_NOT_USED and TabDef to plustek-share.h
* 0.41 - no changes
* 0.42 - moved errorcodes to plustek-share.h
*
*.............................................................................
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __DRV_TYPES_H__
#define __DRV_TYPES_H__
/* define some useful types */
typedef int Bool;
typedef char Char;
typedef char *pChar;
typedef unsigned char UChar;
typedef UChar *pUChar;
typedef unsigned char Byte;
typedef Byte *pByte;
typedef short Short;
typedef unsigned short UShort;
typedef UShort *pUShort;
typedef unsigned int UInt;
typedef UInt *pUInt;
typedef long Long;
typedef long *pLong;
typedef unsigned long ULong;
typedef ULong *pULong;
typedef void *pVoid;
/*
* the boolean values
*/
#ifndef _TRUE
# define _TRUE 1
#endif
#ifndef _FALSE
# define _FALSE 0
#endif
#define _LOWORD(x) ((UShort)(x & 0xffff))
#define _HIWORD(x) ((UShort)(x >> 16))
#define _LOBYTE(x) ((Byte)((x) & 0xFF))
#define _HIBYTE(x) ((Byte)((x) >> 8))
/*
* some useful things...
*/
typedef struct
{
Byte b1st;
Byte b2nd;
} WordVal, *pWordVal;
typedef struct
{
WordVal w1st;
WordVal w2nd;
} DWordVal, *pDWordVal;
/* useful for RGB-values */
typedef struct {
Byte Red;
Byte Green;
Byte Blue;
} RGBByteDef, *pRGBByteDef;
typedef struct {
UShort Red;
UShort Green;
UShort Blue;
} RGBUShortDef, *pRGBUShortDef;
typedef struct {
union {
pUChar bp;
pUShort usp;
pULong ulp;
} red;
union {
pUChar bp;
pUShort usp;
pULong ulp;
} green;
union {
pUChar bp;
pUShort usp;
pULong ulp;
} blue;
} RBGPtrDef;
typedef struct {
ULong Red;
ULong Green;
ULong Blue;
} RGBULongDef, *pRGBULongDef;
typedef union {
pUChar pb;
pUShort pw;
pULong pdw;
pRGBByteDef pbrgb;
pRGBUShortDef pusrgb;
pRGBULongDef pulrgb;
} DataPointer, *pDataPointer;
typedef union {
WordVal wOverlap;
DWordVal dwOverlap;
ULong dwValue;
UShort wValue;
Byte bValue;
} DataType, *pDataType;
#endif /* guard __DRV_TYPES_H__ */
/* END PLUSTEK-PP_TYPES.H ...................................................*/

Wyświetl plik

@ -3,8 +3,8 @@
*.............................................................................
*/
/** @file plustek-pp.c
* @brief The interface to the parport driver.
/** @file plustek-pp_wrapper.c
* @brief The interface to the parport driver-code and the kernel module.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2003 Gerhard Jaeger <gerhard@gjaeger.de>
@ -17,6 +17,7 @@
* - 0.43 - no changes
* - 0.44 - added initialized setting
* - 0.45 - no changes
* - 0.46 - cleanup
* .
* <hr>
* This file is part of the SANE package.
@ -61,8 +62,28 @@
/******************* wrapper functions for parport device ********************/
/*.............................................................................
*
/*
* stuff needed for user space stuff
*/
int PtDrvInit ( int portAddr, unsigned short model_override );
int PtDrvShutdown ( void );
int PtDrvOpen ( void );
int PtDrvClose ( void );
int PtDrvIoctl ( unsigned int cmd, void *arg );
int PtDrvRead ( unsigned char *buffer, int count );
#ifdef _USER_MODE
#define _IOCTL(hd,cmd,arg) PtDrvIoctl(cmd,arg)
#else
#define _IOCTL(hd,cmd,arg) ioctl(hd,cmd,arg)
#endif
/**
*/
static int ppDev_open( const char *dev_name, void *misc )
{
@ -73,14 +94,30 @@ static int ppDev_open( const char *dev_name, void *misc )
unsigned short version = _PTDRV_IOCTL_VERSION;
Plustek_Device *dev = (Plustek_Device *)misc;
_INIT(0x378,190,15);
if ((handle = _OPEN(dev_name)) < 0) {
if( dev->adj.direct_io ) {
/* convert device name to port-address... */
long portaddr = strtol( dev_name, 0, 0 );
PtDrvInit((int)portaddr, dev->adj.mov );
}
if( dev->adj.direct_io )
handle = PtDrvOpen();
else
handle = open( dev_name, O_RDONLY );
if ( handle < 0 ) {
DBG(_DBG_ERROR, "open: can't open %s as a device\n", dev_name);
return handle;
}
result = _IOCTL( handle, _PTDRV_OPEN_DEVICE, &version );
if( dev->adj.direct_io )
result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version );
else
result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version );
if( result < 0 ) {
if( -9019 == result ) {
@ -91,9 +128,18 @@ static int ppDev_open( const char *dev_name, void *misc )
version = _PTDRV_COMPAT_IOCTL_VERSION;
result = _IOCTL( handle, _PTDRV_OPEN_DEVICE, &version );
if( dev->adj.direct_io )
result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version );
else
result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version );
if( result < 0 ) {
_CLOSE( handle );
if( dev->adj.direct_io )
PtDrvClose();
else
close( dev->fd );
DBG( _DBG_ERROR,
"ioctl PT_DRV_OPEN_DEVICE failed(%d)\n", result );
@ -113,7 +159,10 @@ static int ppDev_open( const char *dev_name, void *misc )
memcpy( &compatAdj.neg, &dev->adj.neg, sizeof(OffsDef));
memcpy( &compatAdj.tpa, &dev->adj.tpa, sizeof(OffsDef));
_IOCTL( handle, _PTDRV_ADJUST, &compatAdj );
if( dev->adj.direct_io )
PtDrvIoctl( _PTDRV_ADJUST, &compatAdj );
else
ioctl( handle, _PTDRV_ADJUST, &compatAdj );
return handle;
}
}
@ -135,71 +184,85 @@ static int ppDev_open( const char *dev_name, void *misc )
adj.bgamma = dev->adj.bgamma;
adj.graygamma = dev->adj.graygamma;
_IOCTL( handle, _PTDRV_ADJUST, &adj );
dev->initialized = SANE_TRUE;
if( dev->adj.direct_io )
PtDrvIoctl( _PTDRV_ADJUST, &adj );
else
ioctl( handle, _PTDRV_ADJUST, &adj );
dev->initialized = SANE_TRUE;
return handle;
}
/*.............................................................................
*
/**
*/
static int ppDev_close( Plustek_Device *dev )
{
return _CLOSE( dev->fd );
if( dev->adj.direct_io )
return PtDrvClose();
else
return close( dev->fd );
}
/*.............................................................................
*
/**
*/
static int ppDev_getCaps( Plustek_Device *dev )
{
return _IOCTL( dev->fd, _PTDRV_GET_CAPABILITIES, &dev->caps );
}
/*.............................................................................
*
/**
*/
static int ppDev_getLensInfo( Plustek_Device *dev, pLensInfo lens )
{
#ifdef _USER_MODE
_VAR_NOT_USED( dev );
#endif
return _IOCTL( dev->fd, _PTDRV_GET_LENSINFO, lens );
}
/*.............................................................................
*
/**
*/
static int ppDev_getCropInfo( Plustek_Device *dev, pCropInfo crop )
{
#ifdef _USER_MODE
_VAR_NOT_USED( dev );
#endif
return _IOCTL( dev->fd, _PTDRV_GET_CROPINFO, crop );
}
/*.............................................................................
*
/**
*/
static int ppDev_putImgInfo( Plustek_Device *dev, pImgDef img )
{
#ifdef _USER_MODE
_VAR_NOT_USED( dev );
#endif
return _IOCTL( dev->fd, _PTDRV_PUT_IMAGEINFO, img );
}
/*.............................................................................
/**
*
*/
static int ppDev_setScanEnv( Plustek_Device *dev, pScanInfo sinfo )
{
#ifdef _USER_MODE
_VAR_NOT_USED( dev );
#endif
return _IOCTL( dev->fd, _PTDRV_SET_ENV, sinfo );
}
/*.............................................................................
*
/**
*/
static int ppDev_startScan( Plustek_Device *dev, pStartScan start )
{
#ifdef _USER_MODE
_VAR_NOT_USED( dev );
#endif
return _IOCTL( dev->fd, _PTDRV_START_SCAN, start );
}
/**
* function to send a gamma table to the kernel module. As the default table
* entry is 16-bit, but the maps are 8-bit, we have to copy the values...
/** function to send a gamma table to the kernel module. As the default table
* entry is 16-bit, but the maps are 8-bit, we have to copy the values...
*/
static int ppDev_setMap( Plustek_Device *dev, SANE_Word *map,
SANE_Word length, SANE_Word channel )
@ -229,7 +292,11 @@ static int ppDev_setMap( Plustek_Device *dev, SANE_Word *map,
m.map = buf;
_IOCTL( dev->fd, _PTDRV_SETMAP, &m );
if( dev->adj.direct_io )
PtDrvIoctl( _PTDRV_SETMAP, &m );
else
ioctl( dev->fd, _PTDRV_SETMAP, &m );
/* we ignore the return values */
free( buf );
@ -237,8 +304,7 @@ static int ppDev_setMap( Plustek_Device *dev, SANE_Word *map,
return 0;
}
/*.............................................................................
*
/**
*/
static int ppDev_stopScan( Plustek_Device *dev, int *mode )
{
@ -247,24 +313,32 @@ static int ppDev_stopScan( Plustek_Device *dev, int *mode )
/* save this one... */
tmp = *mode;
retval = _IOCTL( dev->fd, _PTDRV_STOP_SCAN, mode );
/* ... and use it here */
if( 0 == tmp )
_IOCTL( dev->fd, _PTDRV_CLOSE_DEVICE, 0);
if( dev->adj.direct_io )
retval = PtDrvIoctl( _PTDRV_STOP_SCAN, mode );
else
retval = ioctl( dev->fd, _PTDRV_STOP_SCAN, mode );
/* ... and use it here */
if( 0 == tmp ) {
if( dev->adj.direct_io )
PtDrvIoctl( _PTDRV_CLOSE_DEVICE, 0 );
else
ioctl( dev->fd, _PTDRV_CLOSE_DEVICE, 0);
}else
sleep( 1 );
return retval;
}
/*.............................................................................
*
/**
*/
static int ppDev_readImage( Plustek_Device *dev,
SANE_Byte *buf, unsigned long data_length )
{
return _READ( dev->fd, buf, data_length );
if( dev->adj.direct_io )
return PtDrvRead( buf, data_length );
else
return read( dev->fd, buf, data_length );
}
/* END PLUSTEK_PP.C .........................................................*/
/* END PLUSTEK-PP_WRAPPER.C .................................................*/

Wyświetl plik

@ -4,7 +4,7 @@
*/
/** @file plustek-share.h
* @brief Common definitions for the backend and the kernel driver
* @brief Common definitions for the usb backend and parport backend
*
* Copyright (C) 2001-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*
@ -27,6 +27,8 @@
* - 0.43 - added tpa entry for AdjDef
* - 0.44 - extended AdjDef
* - 0.45 - added skipFine and skipFineWhite to AdjDef
* - 0.46 - added altCalibrate and cacheCalData to AdjDef
* - moved some stuff to the specific backend headers
* .
* <hr>
* This file is part of the SANE package.
@ -71,57 +73,6 @@
#ifndef __PLUSTEK_SHARE_H__
#define __PLUSTEK_SHARE_H__
/*
* for other OS than Linux, we might have to define the _IO macros
*/
#ifndef _IOC
#define _IOC(dir,type,nr,size) \
(((dir) << 30) | \
((type) << 8) | \
((nr) << 0) | \
((size) << 16))
#endif
#ifndef _IO
#define _IO(type,nr) _IOC(0U,(type),(nr),0)
#endif
#ifndef _IOR
#define _IOR(type,nr,size) _IOC(2U,(type),(nr),sizeof(size))
#endif
#ifndef _IOW
#define _IOW(type,nr,size) _IOC(1U,(type),(nr),sizeof(size))
#endif
#ifndef _IOWR
#define _IOWR(type,nr,size) _IOC(3U,(type),(nr),sizeof(size))
#endif
/*.............................................................................
* the ioctl interface
*/
#define _PTDRV_OPEN_DEVICE _IOW('x', 1, unsigned short)/* open */
#define _PTDRV_GET_CAPABILITIES _IOR('x', 2, ScannerCaps) /* get caps */
#define _PTDRV_GET_LENSINFO _IOR('x', 3, LensInfo) /* get lenscaps */
#define _PTDRV_PUT_IMAGEINFO _IOW('x', 4, ImgDef) /* put image info*/
#define _PTDRV_GET_CROPINFO _IOR('x', 5, CropInfo) /* get crop */
#define _PTDRV_SET_ENV _IOWR('x',6, ScanInfo) /* set env. */
#define _PTDRV_START_SCAN _IOR('x', 7, StartScan) /* start scan */
#define _PTDRV_STOP_SCAN _IOWR('x', 8, int) /* stop scan */
#define _PTDRV_CLOSE_DEVICE _IO('x', 9) /* close */
#define _PTDRV_ACTION_BUTTON _IOR('x', 10, int) /* rd act. button*/
#define _PTDRV_ADJUST _IOR('x', 11, AdjDef) /* adjust driver */
#define _PTDRV_SETMAP _IOR('x', 12, MapDef) /* download gamma*/
/*
* this version MUST match the one inside the driver to make sure, that
* both sides use the same structures. This version changes each time
* the ioctl interface changes
*/
#define _PTDRV_COMPAT_IOCTL_VERSION 0x0102
#define _PTDRV_IOCTL_VERSION 0x0103
/*.............................................................................
* the structures for driver communication
*/
@ -217,132 +168,21 @@ typedef struct {
int y;
} OffsDef, *pOffsDef;
/*
* for compatiblity to version 0x0102 drivers
*/
typedef struct {
int lampOff;
int lampOffOnEnd;
int warmup;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
} CompatAdjDef, *pCompatAdjDef;
/*
* for adjusting the parport-drivers
*/
typedef struct {
int lampOff;
int lampOffOnEnd;
int warmup;
int enableTpa;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
/* for adjusting the default gamma settings */
double rgamma;
double ggamma;
double bgamma;
double graygamma;
} PPAdjDef, *pPPAdjDef;
/*
* for adjusting the usb stuff
*/
typedef struct {
int lampOff;
int lampOffOnEnd;
int warmup;
int enableTpa;
int skipCalibration;
int skipFine;
int skipFineWhite;
int invertNegatives;
int rgain;
int ggain;
int bgain;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
int posShadingY;
int tpaShadingY;
int negShadingY;
/* for adjusting the default gamma settings */
double rgamma;
double ggamma;
double bgamma;
double graygamma;
} AdjDef, *pAdjDef;
/*
* useful for description tables
/** useful for description tables
*/
typedef struct {
int id;
char *desc;
} TabDef, *pTabDef;
/* NOTE: needs to be kept in sync with table below */
#define MODELSTR static char *ModelStr[] = { \
"unknown", \
"Primax 4800", \
"Primax 4800 Direct", \
"Primax 4800 Direct 30Bit", \
"Primax 9600 Direct 30Bit", \
"4800P", \
"4830P", \
"600P/6000P", \
"4831P", \
"9630P", \
"9630PL", \
"9636P", \
"A3I", \
"12000P/96000P", \
"9636P+/Turbo", \
"9636T/12000T", \
"P8", \
"P12", \
"PT12", \
"Genius Colorpage Vivid III V2", \
"USB-Device" \
}
/* the models */
#define MODEL_OP_UNKNOWN 0 /* unknown */
#define MODEL_PMX_4800 1 /* Primax Colorado 4800 like OP 4800 */
#define MODEL_PMX_4800D 2 /* Primax Compact 4800 Direct, OP 600 R->G, G->R */
#define MODEL_PMX_4800D3 3 /* Primax Compact 4800 Direct 30 */
#define MODEL_PMX_9600D3 4 /* Primax Compact 9600 Direct 30 */
#define MODEL_OP_4800P 5 /* 32k, 96001 ASIC, 24 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_4830P 6 /* 32k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_600P 7 /* 32k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_4831P 8 /* 128k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_9630P 9 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_9630PL 10 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x14 */
#define MODEL_OP_9636P 11 /* 512k, 98001 ASIC, 36 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_A3I 12 /* 128k, 96003 ASIC, 30 bit, 400x800, 11.69x17 */
#define MODEL_OP_12000P 13 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_9636PP 14 /* 512k, 98001 ASIC, 36 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_9636T 15 /* like OP_9636PP + transparency */
#define MODEL_OP_P8 16 /* 512k, 98003 ASIC, 36 bit, 300x600, 8.5x11.69 */
#define MODEL_OP_P12 17 /* 512k, 98003 ASIC, 36 bit, 600x1200, 8.5x11.69 */
#define MODEL_OP_PT12 18 /* like OP_P12 + transparency */
#define MODEL_GEN_CPV2 19 /* Genius Colorpage Vivid III V2, ASIC 98003 */
#define MODEL_OP_USB 20 /* some USB scanner device */
/** for defining the scanmodes
*/
typedef const struct mode_param
{
int color;
int depth;
int scanmode;
} ModeParam, *pModeParam;
/******************************************************************************
* Section 1
@ -366,16 +206,10 @@ typedef struct {
#define SFLAG_CUSTOM_GAMMA 0x00000200 /* driver supports custom gamma */
/*
* (1.2.1) Provide the scanner ID. This field is valid when the wIOBase
* field of ScannerCaps is not _NO_BASE
*/
#define SFLAG_CCDTypeMask 0x000f0000 /* CCD type, system reserved*/
#define SFLAG_IDMask 0x00f00000 /* Scanner ID */
/* (1.3): SCANNERINFO.wIOBase */
#define _NO_BASE 0xFFFF
#if 0
/******************************************************************************
* Section 2
* (2.1): MAPINFO.wRGB
@ -383,6 +217,8 @@ typedef struct {
#define RGB_Master 1
#define RGB_RGB 3
#endif
/******************************************************************************
* Section 3
* (3.1): SCANINFO.dwFlag
@ -416,7 +252,7 @@ typedef struct {
#define _SCANNER_SCANNING 0x8000000
#define _SCANNER_PAPEROUT 0x4000000
#if 0
/* (3.2): SCANINFO.wMapType */
#define CHANNEL_Master 0 /* used only MAPINFO.wRGB == RGB_Master */
/* or scan gray */
@ -424,6 +260,7 @@ typedef struct {
#define CHANNEL_RGB 1
#define CHANNEL_Default 2
/* these are used only to pointer out which color are used as gray map
* It also pointers out which channel will be used to scan gray data
* (CHANNEL_Default = Device default)
@ -439,6 +276,9 @@ typedef struct {
#define DITHER_VerticalLine 3
#define DITHER_UserDefine 4
#endif
/* (3.4): SCANINFO.wBits */
#define OUTPUT_8Bits 0
#define OUTPUT_10Bits 1
@ -497,7 +337,6 @@ typedef struct {
#define _ASIC_IS_96003 0x10 /* value for 96003 */
#define _ASIC_IS_98001 0x81 /* value for 98001 */
#define _ASIC_IS_98003 0x83 /* value for 98003 */
#define _ASIC_IS_USB 0x42 /* for the USB stuff*/
/*
* transparency/negative mode set ranges
@ -515,8 +354,8 @@ typedef struct {
#define _Transparency96OriginOffsetX 0x03DB /* org. was 0x0430 */
#define _Negative96OriginOffsetX 0x03F3 /* org. was 0x0428 */
#define _NegativePageWidth 460U /* 38.9 mm */
#define _NegativePageHeight 350U /* 29.6 mm */
#define _NegativePageWidth 460UL /* 38.9 mm */
#define _NegativePageHeight 350UL /* 29.6 mm */
#define _DEF_DPI 50
@ -567,37 +406,6 @@ typedef struct {
#define _E_BUFFER_TOO_SMALL (_FIRST_ERR-43)
#define _E_DATAREAD (_FIRST_ERR-44)
/*
* stuff needed for user space stuff
*/
#ifdef _USER_MODE
int PtDrvInit ( int portAddr, int lamp_off, int warm_up );
int PtDrvShutdown ( void );
int PtDrvOpen ( void );
int PtDrvClose ( void );
int PtDrvIoctl ( unsigned int cmd, void *arg );
int PtDrvRead ( unsigned char *buffer, int count );
#define _INIT(portAddr,lamp_off,warmup) PtDrvInit(portAddr,lamp_off,warmup)
#define _DOWN() PtDrvShutdown()
#define _OPEN(dev) PtDrvOpen()
#define _CLOSE(hd) PtDrvClose()
#define _IOCTL(hd,cmd,arg) PtDrvIoctl(cmd,arg)
#define _READ(hd,buf,len) PtDrvRead(buf,len)
#else
#define _INIT(portAddr,lamp_off,warmup)
#define _DOWN()
#define _OPEN(dev) open(dev,O_RDONLY)
#define _CLOSE(hd) close(hd)
#define _IOCTL(hd,cmd,arg) ioctl(hd,cmd,arg)
#define _READ(hd,buf,len) read(hd,buf,len)
#endif
#endif /* guard __PLUSTEK_SHARE_H__ */
/* END PLUSTEK-SHARE.H.......................................................*/

Wyświetl plik

@ -32,6 +32,7 @@
* - removed the scaler stuff for CIS devices
* - removed homeing stuff from readline function
* - fixed flag setting in usbDev_startScan()
* - 0.46 - added additional branch to support alternate calibration
* .
* <hr>
* This file is part of the SANE package.
@ -74,8 +75,11 @@
* <hr>
*/
/**
* to allow different vendors...
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
/** to allow different vendors...
*/
static TabDef usbVendors[] = {
@ -99,19 +103,51 @@ static SANE_Char USB_devname[1024];
/********************** the USB scanner interface ****************************/
/** remove the slash out of the model-name to obtain a valid filename
*/
static SANE_Bool usb_normFileName( char *fname, char* buffer, u_long max_len )
{
char *src, *dst;
if( NULL == fname )
return SANE_FALSE;
if( strlen( fname ) >= max_len )
return SANE_FALSE;
src = fname;
dst = buffer;
while( *src != '\0' ) {
if((*src == '/') || isspace(*src))
*dst = '_';
else
*dst = *src;
*dst++;
*src++;
}
*dst = '\0';
return SANE_TRUE;
}
/**
* assign the values to the structures used by the currently found scanner
*/
static void usb_initDev( pPlustek_Device dev, int idx, int handle, int vendor )
{
char *ptr;
char tmp_str1[PATH_MAX];
char tmp_str2[PATH_MAX];
int i;
ScanParam sParam;
u_short tmp = 0;
DBG( _DBG_INFO, "usb_initDev(%d,0x%04x,%u)\n",
DBG( _DBG_INFO, "usb_initDev(%d,0x%04x,%i)\n",
idx, vendor, dev->initialized );
/* save capability flags... */
if( dev->initialized ) {
if( dev->initialized >= 0 ) {
tmp = DEVCAPSFLAG_TPA;
}
@ -120,7 +156,7 @@ static void usb_initDev( pPlustek_Device dev, int idx, int handle, int vendor )
memcpy( &dev->usbDev.HwSetting, Settings[idx].pHwDef, sizeof(HWDef));
/* restore capability flags... */
if( dev->initialized ) {
if( dev->initialized >= 0 ) {
dev->usbDev.Caps.wFlags |= tmp;
}
@ -182,7 +218,7 @@ static void usb_initDev( pPlustek_Device dev, int idx, int handle, int vendor )
/* check for TPA on EPSON device
*/
if( !dev->initialized && vendor == 0x04B8 ) {
if((dev->initialized < 0) && vendor == 0x04B8 ) {
u_char t;
@ -221,9 +257,11 @@ static void usb_initDev( pPlustek_Device dev, int idx, int handle, int vendor )
}
dev->usbDev.currentLamp = usb_GetLampStatus( dev );
usb_ResetRegisters( dev );
if( dev->initialized >= 0 )
return;
usbio_ResetLM983x ( dev );
usb_IsScannerReady( dev );
@ -240,6 +278,23 @@ static void usb_initDev( pPlustek_Device dev, int idx, int handle, int vendor )
sParam.dMCLK = 4;
sParam.Size.dwPixels = 0;
/* create calibration-filename */
ptr = getenv ("HOME");
if( !usb_normFileName( dev->usbDev.ModelStr, tmp_str1, PATH_MAX )) {
strcpy( tmp_str1, "plustek-default" );
}
if( NULL == ptr ) {
sprintf( tmp_str2, "/tmp/%s-%s.cal",
dev->sane.vendor, tmp_str1 );
} else {
sprintf( tmp_str2, "%s/.sane/%s-%s.cal",
ptr, dev->sane.vendor, tmp_str1 );
}
dev->calFile = strdup( tmp_str2 );
DBG( _DBG_INFO, "Calibration file-name set to:\n" );
DBG( _DBG_INFO, ">%s<\n", dev->calFile );
/* initialize the ASIC registers */
usb_SetScanParameters( dev, &sParam );
@ -247,7 +302,7 @@ static void usb_initDev( pPlustek_Device dev, int idx, int handle, int vendor )
usb_ModuleToHome( dev, SANE_FALSE );
/* set the global flag, that we are initialized so far */
dev->initialized = SANE_TRUE;
dev->initialized = idx;
}
/**
@ -354,7 +409,7 @@ static void usbDev_shutdown( Plustek_Device *dev )
dev->fd = -1;
sanei_usb_close( handle );
}
usb_StopLampTimer( dev );
}
@ -631,14 +686,9 @@ static int usbDev_getCaps( Plustek_Device *dev )
dev->caps.dwFlag |= SFLAG_TPA;
}
dev->caps.wIOBase = 0;
dev->caps.wLens = 1;
dev->caps.wMaxExtentX = scaps->Normal.Size.x;
dev->caps.wMaxExtentY = scaps->Normal.Size.y;
dev->caps.AsicID = _ASIC_IS_USB;
dev->caps.Model = MODEL_OP_USB;
dev->caps.Version = 0;
return 0;
}
@ -941,7 +991,7 @@ static int usbDev_startScan( Plustek_Device *dev, pStartScan start )
return 0;
}
return _E_ALLOC;
return _E_ALLOC;
}
/**
@ -963,12 +1013,27 @@ static int usbDev_Prepare( struct Plustek_Device *dev, SANE_Byte *buf )
*/
usb_ModuleStatus( dev );
result = usb_DoCalibration( dev );
/* the CanoScan CIS devices need special handling... */
if((dev->usbDev.vendor == 0x04A9) &&
(dev->usbDev.product==0x2206 || dev->usbDev.product==0x2207 ||
dev->usbDev.product==0x220D || dev->usbDev.product==0x220E)) {
result = cano_DoCalibration( dev );
} else {
if( dev->adj.altCalibrate )
result = cano_DoCalibration( dev );
else
result = usb_DoCalibration( dev );
}
if( SANE_TRUE != result ) {
DBG( _DBG_INFO, "calibration failed!!!\n" );
return result;
}
if( dev->adj.cacheCalData )
usb_SaveCalData( dev );
DBG( _DBG_INFO, "calibration done.\n" );
if( !( scanning->dwFlag & SCANFLAG_Scanning )) {
@ -1309,7 +1374,6 @@ static int usbDev_readLine( struct Plustek_Device *dev )
}
}
}
return 0;
}

Wyświetl plik

@ -24,6 +24,9 @@
* - added _WAF_SKIP_WHITEFINE for skipping fine white calibration
* - added MCLK setting for 16 bit modes
* - added _WAF_FIX_GAIN and _WAF_FIX_OFS
* - 0.46 - added UMAX1200 for 5400 model
* - removed _WAF_FIX_GAIN and _WAF_FIX_OFS
* - added skipCoarseCalib to ScanDef
* .
* <hr>
* This file is part of the SANE package.
@ -77,7 +80,8 @@
#define kNECSLIM 5
#define kCIS650 6
#define kCIS670 7
#define kCIS1240 8
#define kCIS1220 8
#define kCIS1240 9
/*********************************** plustek_types.h!!! ************************/
@ -213,9 +217,7 @@ enum _WORKAROUNDS
_WAF_BYPASS_CALIBRATION = 0x00000008, /* no calibration,use linear gamma */
_WAF_INV_NEGATIVE_MAP = 0x00000010, /* the backend does the neg. stuff */
_WAF_SKIP_FINE = 0x00000020, /* skip the fine calbration */
_WAF_SKIP_WHITEFINE = 0x00000040, /* skip the fine white calbration */
_WAF_FIX_GAIN = 0x00000080, /* use fixed gain for coarse cal. */
_WAF_FIX_OFS = 0x00000100 /* use fixed offset for coarse cal.*/
_WAF_SKIP_WHITEFINE = 0x00000040 /* skip the fine white calbration */
};
/** for lamps connected to the misc I/O pins*/
@ -537,6 +539,7 @@ struct Plustek_Device;
typedef struct ScanDef
{
SANE_Bool fCalibrated; /**< calibrated or not */
SANE_Bool skipCoarseCalib;/**< skip coarse calibration or not */
u_long dwFlag; /**< scan attributes */
ScanParam sParam; /**< all we need to scan */

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,416 @@
/*.............................................................................
* Project : SANE library for Plustek flatbed scanners.
*.............................................................................
*/
/** @file plustek-usbcalfile.c
* @brief Functions for saving/restoring calibration settings
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2003 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.46 - first version
* .
* <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>
*/
typedef struct {
u_long red_light_on;
u_long red_light_off;
u_long green_light_on;
u_long green_light_off;
u_long blue_light_on;
u_long blue_light_off;
u_long green_pwm_duty;
} LightCtrl, *pLightCtrl;
typedef struct {
u_short version;
u_short red_gain;
u_short green_gain;
u_short blue_gain;
u_short red_offs;
u_short green_offs;
u_short blue_offs;
LightCtrl light;
} CalData, *pCalData;
#define _PT_CF_VERSION 0x0001
/** function to read a text file and returns the string which starts which
* 'id' string.
* no duplicate entries where detected, always the first occurance will be
* red.
* @param fp - file pointer of file to read
* @param id - what to search for
* @param res - where to store the result upon success
* @return SANE_TRUE on success, SANE_FALSE on any error
*/
static SANE_Bool usb_ReadSpecLine( FILE *fp, char *id, char* res )
{
char tmp[1024];
char *ptr;
/* rewind file pointer */
if( 0 != fseek( fp, 0L, SEEK_SET)) {
DBG( _DBG_ERROR, "fseek: %s\n", strerror(errno));
return SANE_FALSE;
}
/* roam through the file and examine each line... */
while( !feof( fp )) {
if( NULL != fgets( tmp, 1024, fp )) {
if( 0 == strncmp( tmp, id, strlen(id))) {
ptr = &tmp[strlen(id)];
if( '\0' == *ptr )
break;
strcpy( res, ptr );
res[strlen(res)-1] = '\0';
return SANE_TRUE;
}
}
}
return SANE_FALSE;
}
/**
*/
static char *usb_ReadOtherLines( FILE *fp, char *except )
{
char tmp[1024];
char *ptr, *ptr_base;
int len;
if( 0 != fseek( fp, 0L, SEEK_END))
return NULL;
len = ftell(fp);
/* rewind file pointer */
if( 0 != fseek( fp, 0L, SEEK_SET))
return NULL;
if( len == 0 )
return NULL;
ptr = (char*)malloc(len);
if( NULL == ptr )
return NULL;
ptr_base = ptr;
*ptr = '\0';
/* roam through the file and examine each line... */
while( !feof( fp )) {
if( NULL != fgets( tmp, 1024, fp )) {
if( 0 == strncmp( tmp, "version=", 8 ))
continue;
if( 0 != strncmp( tmp, except, strlen(except))) {
if( strlen( tmp ) > 0 ) {
strcpy( ptr, tmp );
ptr += strlen(tmp);
*ptr = '\0';
}
}
}
}
return ptr_base;
}
/**
*/
static void usb_RestoreCalData( pCalData cal )
{
a_bRegs[0x3b] = (u_char)cal->red_gain;
a_bRegs[0x3c] = (u_char)cal->green_gain;
a_bRegs[0x3d] = (u_char)cal->blue_gain;
a_bRegs[0x38] = (u_char)cal->red_offs;
a_bRegs[0x39] = (u_char)cal->green_offs;
a_bRegs[0x3a] = (u_char)cal->blue_offs;
a_bRegs[0x2a] = _HIBYTE((u_short)cal->light.green_pwm_duty);
a_bRegs[0x2b] = _LOBYTE((u_short)cal->light.green_pwm_duty);
a_bRegs[0x2c] = _HIBYTE((u_short)cal->light.red_light_on);
a_bRegs[0x2d] = _LOBYTE((u_short)cal->light.red_light_on);
a_bRegs[0x2e] = _HIBYTE((u_short)cal->light.red_light_off);
a_bRegs[0x2f] = _LOBYTE((u_short)cal->light.red_light_off);
a_bRegs[0x30] = _HIBYTE((u_short)cal->light.green_light_on);
a_bRegs[0x31] = _LOBYTE((u_short)cal->light.green_light_on);
a_bRegs[0x32] = _HIBYTE((u_short)cal->light.green_light_off);
a_bRegs[0x33] = _LOBYTE((u_short)cal->light.green_light_off);
a_bRegs[0x34] = _HIBYTE((u_short)cal->light.blue_light_on);
a_bRegs[0x35] = _LOBYTE((u_short)cal->light.blue_light_on);
a_bRegs[0x36] = _HIBYTE((u_short)cal->light.blue_light_off);
a_bRegs[0x37] = _LOBYTE((u_short)cal->light.blue_light_off);
}
/**
*/
static void usb_CreatePrefix( pPlustek_Device dev, char *pfx )
{
char bd[5];
pScanDef scanning = &dev->scanning;
pScanParam param = &scanning->sParam;
switch( scanning->sParam.bSource ) {
case SOURCE_Transparency: strcpy( pfx, "tpa-" ); break;
case SOURCE_Negative: strcpy( pfx, "neg-" ); break;
case SOURCE_ADF: strcpy( pfx, "adf-" ); break;
default: pfx[0] = '\0'; break;
}
sprintf( bd, "%u=", param->bBitDepth );
if( param->bDataType == SCANDATATYPE_Color )
strcat( pfx, "color" );
else
strcat( pfx, "gray" );
strcat( pfx, bd );
}
/** function to read and set the calibration data from external file
*/
static SANE_Bool usb_ReadAndSetCalData( pPlustek_Device dev )
{
char pfx[20];
char tmp[1024];
u_short version;
int res;
FILE *fp;
CalData cal;
SANE_Bool ret;
DBG( _DBG_INFO, "usb_ReadAndSetCalData()\n" );
if( NULL == dev->calFile ) {
DBG( _DBG_ERROR, "- No calibration filename set!\n" );
return SANE_FALSE;
}
DBG( _DBG_INFO, "- Reading calibration data from file\n");
DBG( _DBG_INFO, " %s\n", dev->calFile );
fp = fopen( dev->calFile, "r" );
if( NULL == fp ) {
DBG( _DBG_ERROR, "File %s not found\n", dev->calFile );
return SANE_FALSE;
}
/* check version */
if( !usb_ReadSpecLine( fp, "version=", tmp )) {
DBG( _DBG_ERROR, "Could not find version info!\n" );
fclose( fp );
return SANE_FALSE;
}
DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp );
if( 1 != sscanf( tmp, "0x%04hx", &version )) {
DBG( _DBG_ERROR, "Could not decode version info!\n" );
fclose( fp );
return SANE_FALSE;
}
if( version != _PT_CF_VERSION ) {
DBG( _DBG_ERROR, "Versions do not match!\n" );
fclose( fp );
return SANE_FALSE;
}
usb_CreatePrefix( dev, pfx );
ret = SANE_FALSE;
if( usb_ReadSpecLine( fp, pfx, tmp )) {
DBG( _DBG_INFO, "- Calibration data: %s\n", tmp );
res = sscanf( tmp, "%hu,%hu,%hu,%hu,%hu,%hu,"
"%lu,%lu,%lu,%lu,%lu,%lu,%lu\n",
&cal.red_gain, &cal.red_offs,
&cal.green_gain, &cal.green_offs,
&cal.blue_gain, &cal.blue_offs,
&cal.light.red_light_on, &cal.light.red_light_off,
&cal.light.green_light_on, &cal.light.green_light_off,
&cal.light.blue_light_on, &cal.light.blue_light_off,
&cal.light.green_pwm_duty );
if( 13 == res ) {
usb_RestoreCalData( &cal );
ret = SANE_TRUE;
}
}
fclose( fp );
DBG( _DBG_INFO, "usb_ReadAndSetCalData() done -> %u\n", ret );
return ret;
}
/**
*/
static void usb_PrepCalData( pCalData cal )
{
memset( cal, 0, sizeof(CalData));
cal->version = _PT_CF_VERSION;
cal->red_gain = (u_short)a_bRegs[0x3b];
cal->green_gain = (u_short)a_bRegs[0x3c];
cal->blue_gain = (u_short)a_bRegs[0x3d];
cal->red_offs = (u_short)a_bRegs[0x38];
cal->green_offs = (u_short)a_bRegs[0x39];
cal->blue_offs = (u_short)a_bRegs[0x3a];
cal->light.green_pwm_duty = a_bRegs[0x2a] * 256 + a_bRegs[0x2b];
cal->light.red_light_on = a_bRegs[0x2c] * 256 + a_bRegs[0x2d];
cal->light.red_light_off = a_bRegs[0x2e] * 256 + a_bRegs[0x2f];
cal->light.green_light_on = a_bRegs[0x30] * 256 + a_bRegs[0x31];
cal->light.green_light_off = a_bRegs[0x32] * 256 + a_bRegs[0x33];
cal->light.blue_light_on = a_bRegs[0x34] * 256 + a_bRegs[0x35];
cal->light.blue_light_off = a_bRegs[0x36] * 256 + a_bRegs[0x37];
}
/** function to save/update the calibration data
*/
static void usb_SaveCalData( pPlustek_Device dev )
{
char pfx[20];
char tmp[1024];
char set_tmp[1024];
char *other_tmp;
u_short version;
FILE *fp;
CalData cal;
pScanDef scanning = &dev->scanning;
DBG( _DBG_INFO, "usb_SaveCalData()\n" );
/* no new data, so skip this step too */
if( SANE_TRUE == scanning->skipCoarseCalib ) {
DBG( _DBG_INFO, "- No calibration data to save!\n" );
return;
}
if( NULL == dev->calFile ) {
DBG( _DBG_ERROR, "- No calibration filename set!\n" );
return;
}
DBG( _DBG_INFO, "- Saving calibration data to file\n" );
DBG( _DBG_INFO, " %s\n", dev->calFile );
usb_PrepCalData ( &cal );
usb_CreatePrefix( dev, pfx );
sprintf( set_tmp, "%s%u,%u,%u,%u,%u,%u,"
"%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", pfx,
cal.red_gain, cal.red_offs,
cal.green_gain, cal.green_offs,
cal.blue_gain, cal.blue_offs,
cal.light.red_light_on, cal.light.red_light_off,
cal.light.green_light_on, cal.light.green_light_off,
cal.light.blue_light_on, cal.light.blue_light_off,
cal.light.green_pwm_duty );
/* read complete old file if compatible... */
other_tmp = NULL;
fp = fopen( dev->calFile, "r+" );
if( NULL != fp ) {
if( usb_ReadSpecLine( fp, "version=", tmp )) {
DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp );
if( 1 == sscanf( tmp, "0x%04hx", &version )) {
if( version == cal.version ) {
DBG( _DBG_INFO, "- Versions do match\n" );
/* read the rest... */
other_tmp = usb_ReadOtherLines( fp, pfx );
} else {
DBG( _DBG_INFO2, "- Versions do not match (0x%04x)\n", version );
}
} else {
DBG( _DBG_INFO2, "- cannot decode version\n" );
}
} else {
DBG( _DBG_INFO2, "- Version not found\n" );
}
fclose( fp );
}
fp = fopen( dev->calFile, "w+" );
if( NULL == fp ) {
DBG( _DBG_ERROR, "- Cannot create file %s\n", dev->calFile );
DBG( _DBG_ERROR, "- -> %s\n", strerror(errno));
if( other_tmp )
free( other_tmp );
return;
}
/* rewrite the file again... */
fprintf( fp, "version=0x%04X\n", cal.version );
if( strlen( set_tmp ))
fprintf( fp, "%s", set_tmp );
if( other_tmp ) {
fprintf( fp, "%s", other_tmp );
free( other_tmp );
}
fclose( fp );
DBG( _DBG_INFO, "usb_SaveCalData() done.\n" );
}
/* END PLUSTEK-USBCALFILE.C .................................................*/

Wyświetl plik

@ -3,7 +3,7 @@
*.............................................................................
*/
/** @file plustek-devs.c
/** @file plustek-usbdevs.c
* @brief Here we have our USB device definitions.
*
* Based on sources acquired from Plustek Inc.<br>
@ -38,6 +38,9 @@
* - removed EPSON 660 stuff
* - added Canon 1220U entry
* - added entry for Compaq S4-100
* -0.46 - fine-tuning for the CanoScan devices
* - fixed HP2200 shading position
* - renamed to plustek-usbdevs.c
* .
* <hr>
* This file is part of the SANE package.
@ -491,11 +494,10 @@ static DCapsDef Cap0x03F0_0x0505 =
static DCapsDef Cap0x03F0_0x0605 =
{
/* DataOrigin (x, y), ShadingOriginY */
{{ 0, 209}, 0, -1, {2550, 3508}, { 50, 50}, COLOR_BW },
{{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }, 0 }, /* No film scanner module */
{{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }, 0 }, /* No film scanner module */
{{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }, 0 }, /* No ADF */
{{ 0, 209}, 40, -1, {2550, 3508}, { 50, 50}, COLOR_BW },
{{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }, 0 }, /* No film scanner module */
{{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }, 0 }, /* No film scanner module */
{{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }, 0 }, /* No ADF */
{600, 600}, /* Motor can handle 1200 DPI */
0, /* OK */
SENSORORDER_rgb, /* OK */
@ -543,7 +545,7 @@ static DCapsDef Cap0x0400_0x1001_0 =
static DCapsDef Cap0x04B8_0x010F_0 =
{
/* Normal */
{{ 25, 80}, 10, -1, {2550, 3508}, { 100, 100 }, COLOR_BW },
{{ 25, 85}, 10, -1, {2550, 3508}, { 100, 100 }, COLOR_BW },
/* Positive */
{{ 1100, 972}, 720, -1, { 473, 414}, { 150, 150 }, COLOR_GRAY16 },
/* Negative */
@ -618,7 +620,7 @@ static DCapsDef Cap0x04A9_0x2206_0 =
1, /* number of buttons */
kCIS650, /* use default settings during calibration */
0, /* not used here... */
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE | _WAF_FIX_OFS, _NO_MIO
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE, _NO_MIO
};
/* Canon N1220U
@ -634,9 +636,9 @@ static DCapsDef Cap0x04A9_0x2207_0 =
SENSORORDER_rgb,
16, /* sensor distance */
1, /* number of buttons */
kCIS650, /* use default settings during calibration */
kCIS1220, /* use default settings during calibration */
0, /* not used here... */
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE | _WAF_FIX_OFS, _NO_MIO
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE, _NO_MIO
};
/* Canon N670U/N676U/LiDE20
@ -654,7 +656,7 @@ static DCapsDef Cap0x04A9_0x220D_0 =
3, /* number of buttons */
kCIS670,
0, /* not used here... */
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE | _WAF_FIX_OFS, _NO_MIO
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE, _NO_MIO
};
/* Canon N1240U
@ -672,7 +674,7 @@ static DCapsDef Cap0x04A9_0x220E_0 =
3, /* number of buttons */
kCIS1240, /* use default settings during calibration */
0, /* not used here... */
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE | _WAF_FIX_OFS, _NO_MIO
_WAF_MISC_IO_LAMPS | _WAF_BLACKFINE, _NO_MIO
};
/******************* additional Hardware descriptions ************************/
@ -1854,8 +1856,8 @@ static HWDef Hw0x04A9_0x2206_0 =
0x00, /* bReg 0x27 color mode */
2, /* bReg 0x29 illumination mode (runtime) */
/* illumination mode settings */
{ 3, 0, 0, 23, 1500, 0, 0 },
{ 2, 23, 4000, 23, 2600, 23, 1600 },
{ 3, 0, 0, 23, 1300, 0, 0 },
{ 2, 23, 4000, 23, 2600, 23, 850 },
1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */
0, /* bOpticBlackStart (reg 0x1c) */
@ -1863,12 +1865,12 @@ static HWDef Hw0x04A9_0x2206_0 =
89, /* ? wActivePixelsStart (reg 0x1e + 0x1f) */
6074, /* wLineEnd (reg 0x20 + 0x21) */
23, /* red lamp on (reg 0x2c + 0x2d) */
2416, /* red lamp off (reg 0x2e + 0x2f) */
23, /* green lamp on (reg 0x30 + 0x31) */
1801, /* green lamp off (reg 0x32 + 0x33) */
23, /* blue lamp on (reg 0x34 + 0x35) */
1472, /* blue lamp off (reg 0x36 + 0x37) */
23, /* red lamp on (reg 0x2c + 0x2d) */
4000, /* red lamp off (reg 0x2e + 0x2f) */
23, /* green lamp on (reg 0x30 + 0x31) */
2600, /* green lamp off (reg 0x32 + 0x33) */
23, /* blue lamp on (reg 0x34 + 0x35) */
850, /* blue lamp off (reg 0x36 + 0x37) */
3, /* stepper motor control (reg 0x45) */
0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */
@ -1920,8 +1922,8 @@ static HWDef Hw0x04A9_0x2207_0 =
0x00, /* bReg 0x27 color mode */
2, /* bReg 0x29 illumination mode */
{ 3, 0, 0, 23, 3937, 0, 0 },
{ 2, 23, 14000, 23, 7500, 23, 5900 },
{ 3, 0, 0, 23, 4950, 0, 0 },
{ 2, 23, 16383, 23, 15000, 23, 6600 },
1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */
0, /* bOpticBlackStart (reg 0x1c) */
@ -1930,11 +1932,11 @@ static HWDef Hw0x04A9_0x2207_0 =
10586, /* wLineEnd (reg 0x20 + 0x21) */
23, /* red lamp on (reg 0x2c + 0x2d) */
8870, /* red lamp off (reg 0x2e + 0x2f) */
16383, /* red lamp off (reg 0x2e + 0x2f) */
23, /* green lamp on (reg 0x30 + 0x31) */
5055, /* green lamp off (reg 0x32 + 0x33) */
15000, /* green lamp off (reg 0x32 + 0x33) */
23, /* blue lamp on (reg 0x34 + 0x35) */
2828, /* blue lamp off (reg 0x36 + 0x37) */
6600, /* blue lamp off (reg 0x36 + 0x37) */
3, /* stepper motor control (reg 0x45) */
0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */
@ -1996,14 +1998,12 @@ static HWDef Hw0x04A9_0x220D_0 =
75, /* wActivePixelsStart (reg 0x1e + 0x1f) */
6074, /* wLineEnd (reg 0x20 + 0x21) */
/* ??0x17ba = 6074 bis 100dpi, 0x14ba = 5306 */
23, /* red lamp on (reg 0x2c + 0x2d) */
4562, /* red lamp off (reg 0x2e + 0x2f) */
3800, /* red lamp off (reg 0x2e + 0x2f) */
23, /* green lamp on (reg 0x30 + 0x31) */
4315, /* green lamp off (reg 0x32 + 0x33) */
3300, /* green lamp off (reg 0x32 + 0x33) */
23, /* blue lamp on (reg 0x34 + 0x35) */
3076, /* blue lamp off (reg 0x36 + 0x37) */
2700, /* blue lamp off (reg 0x36 + 0x37) */
3, /* stepper motor control (reg 0x45) */
0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */
@ -2055,28 +2055,22 @@ static HWDef Hw0x04A9_0x220E_0 =
0x00, /* bReg 0x27 color mode */
2, /* bReg 0x29 illumination mode */
#if 1
{ 3, 0, 0, 23, 3937, 0, 0 },
{ 2, 23, 13000, 23, 6500, 23, 4900 },
#else
{ 3, 0, 0, 23, 16383, 0, 0 },
{ 2, 23, 16383, 23, 16383, 23, 16383 },
#endif
{ 3, 0, 0, 23, 4000, 0, 0 },
{ 2, 23, 16383, 23, 6500, 23, 4900 },
1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */
0, /* bOpticBlackStart (reg 0x1c) */
0, /* bOpticBlackEnd (reg 0x1d) */
52, /* wActivePixelsStart (reg 0x1e + 0x1f) */
10586, /* wLineEnd (reg 0x20 + 0x21) */
/* 0x2f7a = 12154 bis 100dpi, 0x295a = 10586 */
10586, /* wLineEnd (reg 0x20 + 0x21) */
23, /* red lamp on (reg 0x2c + 0x2d) */
10581, /* red lamp off (reg 0x2e + 0x2f) */
16383, /* red lamp off (reg 0x2e + 0x2f) */
23, /* green lamp on (reg 0x30 + 0x31) */
5096, /* green lamp off (reg 0x32 + 0x33) */
6500, /* green lamp off (reg 0x32 + 0x33) */
23, /* blue lamp on (reg 0x34 + 0x35) */
3735, /* blue lamp off (reg 0x36 + 0x37) */
4900, /* blue lamp off (reg 0x36 + 0x37) */
3, /* stepper motor control (reg 0x45) */
0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */
@ -2146,7 +2140,7 @@ static SetDef Settings[] =
{"0x0458-0x2016", &Cap0x07B3_0x0005_4, &Hw0x07B3_0x0007_0, "ColorPage-HR6X" },
/* Hewlett Packard... */
{"0x03F0-0x0505", &Cap0x03F0_0x0505, &Hw0x03F0_0x0505, "Scanjet 2100c" },
{"0x03F0-0x0505", &Cap0x03F0_0x0505, &Hw0x03F0_0x0505, "Scanjet 2100c" },
{"0x03F0-0x0605", &Cap0x03F0_0x0605, &Hw0x03F0_0x0605, "Scanjet 2200c" },
/* EPSON... */
@ -2154,18 +2148,18 @@ static SetDef Settings[] =
{"0x04B8-0x011D", &Cap0x04B8_0x010F_0, &Hw0x04B8_0x011D_0, "Perfection 1260/Photo" },
/* UMAX... */
{"0x1606-0x0060", &Cap0x1606_0x0060_0, &Hw0x1606_0x0060_0, "3400/3450" },
{"0x1606-0x0160", &Cap0x1606_0x0160_0, &Hw0x1606_0x0160_0, "5400" },
{"0x1606-0x0060", &Cap0x1606_0x0060_0, &Hw0x1606_0x0060_0, "3400/3450" },
{"0x1606-0x0160", &Cap0x1606_0x0160_0, &Hw0x1606_0x0160_0, "5400" },
/* COMPAQ... */
{"0x049F-0x001A", &Cap0x1606_0x0060_0, &Hw0x1606_0x0060_0, "S4-100" },
{"0x049F-0x001A", &Cap0x1606_0x0060_0, &Hw0x1606_0x0060_0, "S4-100" },
/* CANON... */
{"0x04A9-0x2206", &Cap0x04A9_0x2206_0, &Hw0x04A9_0x2206_0, "N650U/N656U" },
{"0x04A9-0x2207", &Cap0x04A9_0x2207_0, &Hw0x04A9_0x2207_0, "N1220U" },
{"0x04A9-0x220D", &Cap0x04A9_0x220D_0, &Hw0x04A9_0x220D_0, "N670U/N676U/LiDE20" },
{"0x04A9-0x220E", &Cap0x04A9_0x220E_0, &Hw0x04A9_0x220E_0, "N1240U/LiDE30" },
/* Please add other devices here...
* The first entry is a string, composed out of the vendor and product id,
* it's used by the driver to select the device settings. For other devices
@ -2351,4 +2345,4 @@ static ClkMotorDef Motors[] = {
},
};
/* END PLUSTEK-DEVS.C .......................................................*/
/* END PLUSTEK-USBDEVS.C ....................................................*/

Wyświetl plik

@ -27,6 +27,8 @@
* - 0.45 - added function usb_AdjustLamps() to tweak CIS lamp settings
* - fixed NULL pointer problem in lamp-off ISR
* - added usb_AdjustCISLampSettings()
* - skipping warmup for CIS devices
* - 0.46 - no changes
* .
* <hr>
* This file is part of the SANE package.
@ -1070,6 +1072,8 @@ static SANE_Bool usb_LampOn( pPlustek_Device dev,
* 0x0f - 0x18 - Sensor Configuration - directly from the HwDef<br>
* 0x1a - 0x1b - Stepper Phase Correction<br>
* 0x20 - 0x21 - Line End<br>
* 0x21 - 0x22 - Data Pixel start<br>
* 0x23 - 0x24 - Data Pixel end<br>
* 0x45 - Stepper Motor Mode<br>
* 0x4c - 0x4d - Full Steps to Scan after PAPER SENSE 2 trips<br>
* 0x50 - Steps to reverse when buffer is full<br>
@ -1082,19 +1086,37 @@ static SANE_Bool usb_LampOn( pPlustek_Device dev,
*/
static void usb_ResetRegisters( pPlustek_Device dev )
{
int linend;
pHWDef hw = &dev->usbDev.HwSetting;
DBG( _DBG_INFO, "RESETTING REGISTERS(%u)\n", dev->initialized );
DBG( _DBG_INFO, "RESETTING REGISTERS(%i)\n", dev->initialized );
memset( a_bRegs, 0, sizeof(a_bRegs));
memcpy( a_bRegs+0x0b, &hw->bSensorConfiguration, 4 );
memcpy( a_bRegs+0x0f, &hw->bReg_0x0f_Color, 10 );
a_bRegs[0x1a] = _HIBYTE( hw->StepperPhaseCorrection );
a_bRegs[0x1b] = _LOBYTE( hw->StepperPhaseCorrection );
#if 0
a_bRegs[0x1e] = _HIBYTE( hw->wActivePixelsStart );
a_bRegs[0x1f] = _LOBYTE( hw->wActivePixelsStart );
#endif
a_bRegs[0x20] = _HIBYTE( hw->wLineEnd );
a_bRegs[0x21] = _LOBYTE( hw->wLineEnd );
a_bRegs[0x22] = _HIBYTE( hw->bOpticBlackStart );
a_bRegs[0x22] = _LOBYTE( hw->bOpticBlackStart );
linend = hw->bOpticBlackStart + hw->wLineEnd;
if( linend < (hw->wLineEnd-20))
linend = hw->wLineEnd-20;
a_bRegs[0x24] = _HIBYTE( linend );
a_bRegs[0x25] = _LOBYTE( linend );
a_bRegs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleHigh );
a_bRegs[0x2b] = _LOBYTE( hw->wGreenPWMDutyCycleHigh );
a_bRegs[0x45] = hw->bReg_0x45;
a_bRegs[0x4c] = _HIBYTE( hw->wStepsAfterPaperSensor2 );
a_bRegs[0x4d] = _LOBYTE( hw->wStepsAfterPaperSensor2 );
@ -1104,21 +1126,25 @@ static void usb_ResetRegisters( pPlustek_Device dev )
/* if already initialized, we ignore the MISC I/O settings as
* they are used to determine the current lamp settings...
*/
if( dev->initialized ) {
if( dev->initialized >= 0 ) {
DBG( _DBG_INFO2, "USING MISC I/O settings\n" );
memcpy( a_bRegs+0x54, &hw->bReg_0x54, 0x58 - 0x54 + 1 );
a_bRegs[0x5c] = hw->bReg_0x5c;
a_bRegs[0x5d] = hw->bReg_0x5d;
a_bRegs[0x5e] = hw->bReg_0x5e;
sanei_lm983x_read( dev->fd, 0x59, &a_bRegs[0x59], 3, SANE_TRUE );
} else {
DBG( _DBG_INFO2, "SETTING THE MISC I/Os\n" );
memcpy( a_bRegs+0x54, &hw->bReg_0x54, 0x5e - 0x54 + 1 );
sanei_lm983x_write( dev->fd, 0x59, &a_bRegs[0x59], 3, SANE_TRUE );
}
DBG( _DBG_INFO, "MISC I/O after RESET: 0x%02x, 0x%02x, 0x%02x\n",
a_bRegs[0x59], a_bRegs[0x5a], a_bRegs[0x5b] );
}
/** usb_ModuleStatus
*
*/
static SANE_Bool usb_ModuleStatus( pPlustek_Device dev )
{

Wyświetl plik

@ -22,6 +22,7 @@
* - fixed a bug in usb_GrayScalePseudo16 function
* - fixed a bug in usb_GrayDuplicatePseudo16 function
* - removed the scaler stuff for CIS devices
* - 0.46 - no changes
* .
* <hr>
* This file is part of the SANE package.

Wyświetl plik

@ -19,6 +19,7 @@
* - beautyfied output of ASIC detection
* - 0.45 - fixed dumpRegs
* - added dimension stuff to dumpPic
* - 0.46 - disabled reset prior to the detection of Merlin
* .
* <hr>
* This file is part of the SANE package.
@ -262,8 +263,7 @@ static SANE_Bool usbio_WriteReg( SANE_Int handle,
return SANE_FALSE;
}
/*.............................................................................
*
/**
*/
static SANE_Status usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version )
{
@ -273,10 +273,12 @@ static SANE_Status usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version )
DBG( _DBG_INFO, "usbio_DetectLM983x\n");
#if 0
_UIO( sanei_lm983x_write_byte(fd, 0x07, 0x00));
_UIO( sanei_lm983x_write_byte(fd, 0x08, 0x02));
_UIO( usbio_ReadReg(fd, 0x07, &value));
_UIO( usbio_ReadReg(fd, 0x08, &value));
#endif
_UIO( usbio_ReadReg(fd, 0x69, &value));
value &= 7;
@ -303,8 +305,7 @@ static SANE_Status usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version )
return res;
}
/*.............................................................................
*
/**
*/
static SANE_Status usbio_ResetLM983x( pPlustek_Device dev )
{

Wyświetl plik

@ -16,6 +16,7 @@
* - 0.43 - no changes
* - 0.44 - map inversion for negatatives now only upon user request
* - 0.45 - no changes
* - 0.46 - no changes
* .
* <hr>
* This file is part of the SANE package.

Wyświetl plik

@ -21,6 +21,7 @@
* - fixed cancel hang problem
* - fixed CIS PhyBytes adjustment
* - removed CanoScan specific setting stuff
* - 0.46 - fixed problem in usb_SetScanParameters()
* .
* <hr>
* This file is part of the SANE package.

Wyświetl plik

@ -20,6 +20,8 @@
* - 0.45 - added coarse calibration for CIS devices
* - added _WAF_SKIP_FINE to skip the results of fine calibration
* - CanoScan fixes and fine-tuning
* - 0.46 - CanoScan will now be calibrated by code in plustek-usbcal.c
* - added functions to save and restore calibration data from a file
* .
* <hr>
* This file is part of the SANE package.
@ -332,63 +334,33 @@ static void usb_GetSoftwareOffsetGain( pPlustek_Device dev )
break;
case kCIS650:
DBG( _DBG_INFO2, "kCIS650 adjustments\n" );
if(pParam->bDataType == SCANDATATYPE_Color) {
pParam->swGain[0] = 1160;
pParam->swGain[1] = 1160;
pParam->swGain[2] = 1160;
} else {
pParam->swOffset[0] =
pParam->swOffset[1] =
pParam->swOffset[2] = -1500;
pParam->swGain[0] =
pParam->swGain[1] =
pParam->swGain[2] = 1000;
}
break;
case kCIS670:
DBG( _DBG_INFO2, "kCIS670 adjustments\n" );
case kCIS1220:
DBG( _DBG_INFO2, "kCIS adjustments\n" );
if(pParam->bDataType == SCANDATATYPE_Color) {
pParam->swOffset[0] = -2650;
pParam->swOffset[1] = -2800;
pParam->swOffset[2] = -2850;
pParam->swGain[0] = 1150;
pParam->swGain[1] = 1150;
pParam->swGain[2] = 1150;
} else {
pParam->swOffset[0] =
pParam->swOffset[1] =
pParam->swOffset[2] = -2800;
pParam->swGain[0] =
pParam->swGain[1] =
pParam->swGain[2] = 980;
pParam->swGain[2] = 952;
pParam->swOffset[0] =
pParam->swOffset[1] =
pParam->swOffset[2] = 1000;
}
break;
case kCIS1240:
DBG( _DBG_INFO2, "kCIS1240 adjustments\n" );
if(pParam->bDataType == SCANDATATYPE_Color) {
pParam->swOffset[0] = -1650;
pParam->swOffset[1] = -1500;
pParam->swOffset[2] = -1500;
pParam->swGain[0] = 1010;
pParam->swGain[1] = 1050;
pParam->swGain[2] = 1030;
} else {
pParam->swOffset[0] = -1000;
pParam->swOffset[1] = -1000;
pParam->swOffset[2] = -1000;
pParam->swGain[0] = 950;
pParam->swGain[1] = 950;
pParam->swGain[2] = 900;
pParam->swGain[0] = 1100;
pParam->swGain[1] = 1100;
pParam->swGain[2] = 1100;
}
pParam->swOffset[0] =
pParam->swOffset[1] =
pParam->swOffset[2] = 0; /*1000;*/
}
break;
case kNEC3799:
@ -702,14 +674,6 @@ static SANE_Bool usb_AdjustGain( pPlustek_Device dev, int fNegative )
bMaxITA = 0xff;
DBG( _DBG_INFO2, "usb_AdjustGain()\n" );
if( scaps->workaroundFlag & _WAF_FIX_GAIN ) {
a_bRegs[0x3b] =
a_bRegs[0x3c] =
a_bRegs[0x3d] = _CIS_GAIN;
/* don't blame on me - I know it's shitty... */
goto show_sets;
}
/*
* define the strip to scan for coarse calibration
@ -1074,7 +1038,6 @@ TOGAIN:
}
}
show_sets:
DBG( _DBG_INFO2, "REG[0x3b] = %u\n", a_bRegs[0x3b] );
DBG( _DBG_INFO2, "REG[0x3c] = %u\n", a_bRegs[0x3c] );
DBG( _DBG_INFO2, "REG[0x3d] = %u\n", a_bRegs[0x3d] );
@ -1164,19 +1127,12 @@ static SANE_Bool usb_AdjustOffset( pPlustek_Device dev )
u_long dw, dwPixels;
u_long dwDiff[3], dwSum[3];
pDCapsDef scaps = &dev->usbDev.Caps;
pHWDef hw = &dev->usbDev.HwSetting;
pHWDef hw = &dev->usbDev.HwSetting;
if( usb_IsEscPressed())
return SANE_FALSE;
DBG( _DBG_INFO2, "usb_AdjustOffset()\n" );
if( scaps->workaroundFlag & _WAF_FIX_OFS ) {
a_bRegs[0x38] =
a_bRegs[0x39] =
a_bRegs[0x3a] = _CIS_OFFS;
return SANE_TRUE;
}
m_ScanParam.Size.dwLines = 1; /* for gain */
m_ScanParam.Size.dwPixels = 2550;
@ -2017,7 +1973,6 @@ static void usb_ResizeWhiteShading( double dAmp, u_short *pwShading, int iGain )
pwShading[dw] = (u_short)_LOBYTE(w) * 256 + _HIBYTE(w);
}
}
/**
*/
static void usb_PrepareCalibration( pPlustek_Device dev )
@ -2053,10 +2008,15 @@ static void usb_PrepareCalibration( pPlustek_Device dev )
memset( a_wWhiteShading, 0, _SHADING_BUF );
memset( a_wDarkShading, 0, _SHADING_BUF );
scanning->skipCoarseCalib = SANE_FALSE;
if( dev->adj.cacheCalData )
if( usb_ReadAndSetCalData( dev ))
scanning->skipCoarseCalib = SANE_TRUE;
}
/** usb_DoCalibration
*
*/
static int usb_DoCalibration( pPlustek_Device dev )
{
@ -2071,14 +2031,12 @@ static int usb_DoCalibration( pPlustek_Device dev )
/* Go to shading position
*/
if( !(scaps->workaroundFlag & (_WAF_FIX_GAIN & _WAF_FIX_OFS))) {
DBG( _DBG_INFO, "goto shading position\n" );
DBG( _DBG_INFO, "goto shading position\n" );
/* HEINER: Currently not clear why Plustek didn't use the ShadingOriginY
* for all modes
* It should be okay to remove this and reference to the ShadingOriginY
*/
/* HEINER: Currently not clear why Plustek didn't use the ShadingOriginY
* for all modes
* It should be okay to remove this and reference to the ShadingOriginY
*/
#if 0
if( scanning->sParam.bSource == SOURCE_Negative ) {
@ -2092,22 +2050,21 @@ static int usb_DoCalibration( pPlustek_Device dev )
} else {
#endif
DBG( _DBG_INFO, "ShadingOriginY=%lu\n",
(u_long)dev->usbDev.pSource->ShadingOriginY );
DBG( _DBG_INFO, "ShadingOriginY=%lu\n",
(u_long)dev->usbDev.pSource->ShadingOriginY );
if((hw->motorModel == MODEL_HuaLien) && (scaps->OpticDpi.x==600)) {
if (!usb_ModuleMove(dev, MOVE_ToShading,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
return _E_LAMP_NOT_IN_POS;
}
} else {
if( !usb_ModuleMove(dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
return _E_LAMP_NOT_IN_POS;
}
if((hw->motorModel == MODEL_HuaLien) && (scaps->OpticDpi.x==600)) {
if (!usb_ModuleMove(dev, MOVE_ToShading,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
return _E_LAMP_NOT_IN_POS;
}
/* }*/
}
} else {
if( !usb_ModuleMove(dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
return _E_LAMP_NOT_IN_POS;
}
}
/* }*/
DBG( _DBG_INFO, "shading position reached\n" );
@ -2474,7 +2431,8 @@ static int usb_DoCalibration( pPlustek_Device dev )
}
scanning->fCalibrated = SANE_TRUE;
DBG( _DBG_INFO, "Calibration done\n-----------------------\n" );
DBG( _DBG_INFO, "Calibration done\n" );
DBG( _DBG_INFO, "-----------------------\n" );
DBG( _DBG_INFO, "Static Gain:\n" );
DBG( _DBG_INFO, "REG[0x3b] = %u\n", a_bRegs[0x3b] );
DBG( _DBG_INFO, "REG[0x3c] = %u\n", a_bRegs[0x3c] );

Wyświetl plik

@ -58,6 +58,10 @@
* - added WIFSIGNALED to check result of child termination
* - changed readImage interface for USB devices
* - homeing of USB scanner is now working correctly
* - 0.46 - added plustek-usbcal.c for extra CIS device calibration
* based in Montys' great work
* - added altCalibration option
* - removed parallelport support
*.
* <hr>
* This file is part of the SANE package.
@ -131,7 +135,7 @@
#include "sane/sanei.h"
#include "sane/saneopts.h"
#define BACKEND_VERSION "0.45-7"
#define BACKEND_VERSION "0.46-TEST2"
#define BACKEND_NAME plustek
#include "sane/sanei_backend.h"
#include "sane/sanei_config.h"
@ -161,7 +165,8 @@
/*****************************************************************************/
#define _DEFAULT_DEVICE "/dev/pt_drv"
#define _SECTION "[merlin-device]"
#define _DEFAULT_DEVICE "/dev/usb/scanner0"
/* declare it here, as it's used in plustek-usbscan.c too :-( */
static SANE_Bool cancelRead;
@ -169,18 +174,17 @@ static SANE_Bool cancelRead;
/* the USB-stuff... I know this is in general no good idea, but it works */
#ifdef _PLUSTEK_USB
# include "plustek-usbio.c"
# include "plustek-devs.c"
# include "plustek-usbdevs.c"
# include "plustek-usbhw.c"
# include "plustek-usbmap.c"
# include "plustek-usbscan.c"
# include "plustek-usbimg.c"
# include "plustek-usbcalfile.c"
# include "plustek-usbshading.c"
# include "plustek-usbcal.c"
# include "plustek-usb.c"
#endif
/* the parport wrapper... */
#include "plustek-pp.c"
/************************** global vars **************************************/
static int num_devices;
@ -190,25 +194,6 @@ static const SANE_Device **devlist = 0;
static unsigned long tsecs = 0;
static ModeParam mode_params[] =
{
{0, 1, COLOR_BW},
{0, 1, COLOR_HALFTONE},
{0, 8, COLOR_256GRAY},
{1, 8, COLOR_TRUE24},
{1, 16, COLOR_TRUE32},
{1, 16, COLOR_TRUE36}
};
static ModeParam mode_9800x_params[] =
{
{0, 1, COLOR_BW},
{0, 1, COLOR_HALFTONE},
{0, 8, COLOR_256GRAY},
{1, 8, COLOR_TRUE24},
{1, 16, COLOR_TRUE48}
};
static ModeParam mode_usb_params[] =
{
{0, 1, COLOR_BW},
{0, 8, COLOR_256GRAY},
@ -227,16 +212,6 @@ static const SANE_String_Const mode_list[] =
NULL
};
static const SANE_String_Const mode_9800x_list[] =
{
SANE_I18N("Binary"),
SANE_I18N("Halftone"),
SANE_I18N("Gray"),
SANE_I18N("Color"),
SANE_I18N("Color36"),
NULL
};
static const SANE_String_Const mode_usb_list[] =
{
SANE_I18N("Binary"),
@ -275,16 +250,13 @@ static const SANE_Range percentage_range =
*/
static LensInfo lens = {{0,0,0,0,},{0,0,0,0,},{0,0,0,0,},{0,0,0,0,},0,0};
/*
* see plustek-share.h
*/
MODELSTR;
/* authorization stuff */
static SANE_Auth_Callback auth = NULL;
/****************************** the backend... *******************************/
#define _YN(x) (x?"yes":"no")
/**
* function to display the configuration options for the current device
* @param cnf - pointer to the configuration structure whose content should be
@ -292,34 +264,35 @@ static SANE_Auth_Callback auth = NULL;
*/
static void show_cnf( pCnfDef cnf )
{
DBG( _DBG_SANE_INIT, "Device configuration:\n" );
DBG( _DBG_SANE_INIT, "device name : >%s<\n", cnf->devName );
DBG( _DBG_SANE_INIT, "porttype : %d\n", cnf->porttype );
DBG( _DBG_SANE_INIT, "USB-ID : >%s<\n", cnf->usbId );
DBG( _DBG_SANE_INIT, "warmup : %ds\n", cnf->adj.warmup );
DBG( _DBG_SANE_INIT, "lampOff : %d\n", cnf->adj.lampOff );
DBG( _DBG_SANE_INIT, "lampOffOnEnd : %d\n", cnf->adj.lampOffOnEnd );
DBG( _DBG_SANE_INIT, "skipCalibr. : %d\n", cnf->adj.skipCalibration );
DBG( _DBG_SANE_INIT, "skipFine : %d\n", cnf->adj.skipFine );
DBG( _DBG_SANE_INIT, "skipFineWhite: %d\n", cnf->adj.skipFineWhite );
DBG( _DBG_SANE_INIT, "invertNegs. : %d\n", cnf->adj.invertNegatives );
DBG( _DBG_SANE_INIT, "pos_x : %d\n", cnf->adj.pos.x );
DBG( _DBG_SANE_INIT, "pos_y : %d\n", cnf->adj.pos.y );
DBG( _DBG_SANE_INIT, "pos_shading_y: %d\n", cnf->adj.posShadingY );
DBG( _DBG_SANE_INIT, "neg_x : %d\n", cnf->adj.neg.x );
DBG( _DBG_SANE_INIT, "neg_y : %d\n", cnf->adj.neg.y );
DBG( _DBG_SANE_INIT, "neg_shading_y: %d\n", cnf->adj.negShadingY );
DBG( _DBG_SANE_INIT, "tpa_x : %d\n", cnf->adj.tpa.x );
DBG( _DBG_SANE_INIT, "tpa_y : %d\n", cnf->adj.tpa.y );
DBG( _DBG_SANE_INIT, "tpa_shading_y: %d\n", cnf->adj.tpaShadingY );
DBG( _DBG_SANE_INIT, "red gain : %d\n", cnf->adj.rgain );
DBG( _DBG_SANE_INIT, "green gain : %d\n", cnf->adj.ggain );
DBG( _DBG_SANE_INIT, "blue gain : %d\n", cnf->adj.bgain );
DBG( _DBG_SANE_INIT, "red Gamma : %.2f\n", cnf->adj.rgamma );
DBG( _DBG_SANE_INIT, "green Gamma : %.2f\n", cnf->adj.ggamma );
DBG( _DBG_SANE_INIT, "blue Gamma : %.2f\n", cnf->adj.bgamma );
DBG( _DBG_SANE_INIT, "gray Gamma : %.2f\n", cnf->adj.graygamma );
DBG( _DBG_SANE_INIT, "---------------------\n" );
DBG( _DBG_SANE_INIT,"Device configuration:\n" );
DBG( _DBG_SANE_INIT,"device name : >%s<\n",cnf->devName );
DBG( _DBG_SANE_INIT,"USB-ID : >%s<\n",cnf->usbId );
DBG( _DBG_SANE_INIT,"warmup : %ds\n", cnf->adj.warmup );
DBG( _DBG_SANE_INIT,"lampOff : %d\n", cnf->adj.lampOff );
DBG( _DBG_SANE_INIT,"lampOffOnEnd : %s\n", _YN(cnf->adj.lampOffOnEnd ));
DBG( _DBG_SANE_INIT,"cacheCalData : %s\n", _YN(cnf->adj.cacheCalData ));
DBG( _DBG_SANE_INIT,"altCalibrate : %s\n", _YN(cnf->adj.altCalibrate ));
DBG( _DBG_SANE_INIT,"skipCalibr. : %s\n", _YN(cnf->adj.skipCalibration));
DBG( _DBG_SANE_INIT,"skipFine : %s\n", _YN(cnf->adj.skipFine ));
DBG( _DBG_SANE_INIT,"skipFineWhite: %s\n", _YN(cnf->adj.skipFineWhite ));
DBG( _DBG_SANE_INIT,"invertNegs. : %s\n", _YN(cnf->adj.invertNegatives));
DBG( _DBG_SANE_INIT,"pos_x : %d\n", cnf->adj.pos.x );
DBG( _DBG_SANE_INIT,"pos_y : %d\n", cnf->adj.pos.y );
DBG( _DBG_SANE_INIT,"pos_shading_y: %d\n", cnf->adj.posShadingY );
DBG( _DBG_SANE_INIT,"neg_x : %d\n", cnf->adj.neg.x );
DBG( _DBG_SANE_INIT,"neg_y : %d\n", cnf->adj.neg.y );
DBG( _DBG_SANE_INIT,"neg_shading_y: %d\n", cnf->adj.negShadingY );
DBG( _DBG_SANE_INIT,"tpa_x : %d\n", cnf->adj.tpa.x );
DBG( _DBG_SANE_INIT,"tpa_y : %d\n", cnf->adj.tpa.y );
DBG( _DBG_SANE_INIT,"tpa_shading_y: %d\n", cnf->adj.tpaShadingY );
DBG( _DBG_SANE_INIT,"red gain : %d\n", cnf->adj.rgain );
DBG( _DBG_SANE_INIT,"green gain : %d\n", cnf->adj.ggain );
DBG( _DBG_SANE_INIT,"blue gain : %d\n", cnf->adj.bgain );
DBG( _DBG_SANE_INIT,"red Gamma : %.2f\n",cnf->adj.rgamma );
DBG( _DBG_SANE_INIT,"green Gamma : %.2f\n",cnf->adj.ggamma );
DBG( _DBG_SANE_INIT,"blue Gamma : %.2f\n",cnf->adj.bgamma );
DBG( _DBG_SANE_INIT,"gray Gamma : %.2f\n",cnf->adj.graygamma );
DBG( _DBG_SANE_INIT,"---------------------\n" );
}
/** open the device specific driver and reset the internal timing stuff
@ -372,29 +345,13 @@ static SANE_Status drvclose( Plustek_Device *dev )
*/
static pModeParam getModeList( Plustek_Scanner *scanner )
{
pModeParam mp;
if( _ASIC_IS_USB == scanner->hw->caps.AsicID ) {
mp = mode_usb_params;
} else {
if((_ASIC_IS_98003 == scanner->hw->caps.AsicID) ||
(_ASIC_IS_98001 == scanner->hw->caps.AsicID)) {
mp = mode_9800x_params;
} else {
mp = mode_params;
}
}
pModeParam mp= mode_params;
/*
* the transparency/negative mode supports only GRAY/COLOR/COLOR32/COLOR48
*/
if( 0 != scanner->val[OPT_EXT_MODE].w ) {
if( _ASIC_IS_USB == scanner->hw->caps.AsicID )
mp = &mp[_TPAModeSupportMin];
else
mp = &mp[_TPAModeSupportMin];
mp = &mp[_TPAModeSupportMin];
}
return mp;
@ -505,10 +462,8 @@ static int reader_process( Plustek_Scanner *scanner, int pipe_fd )
act.sa_handler = reader_process_sigterm_handler;
sigaction( SIGTERM, &act, 0 );
if( _ASIC_IS_USB == scanner->hw->caps.AsicID ) {
act.sa_handler = usb_reader_process_sigterm_handler;
sigaction( SIGUSR1, &act, 0 );
}
act.sa_handler = usb_reader_process_sigterm_handler;
sigaction( SIGUSR1, &act, 0 );
data_length = scanner->params.lines * scanner->params.bytes_per_line;
@ -580,7 +535,6 @@ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
{
struct SIGACTION act;
pid_t res;
int int_cnt;
DBG( _DBG_PROC,"do_cancel\n" );
@ -590,14 +544,6 @@ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
DBG( _DBG_PROC, ">>>>>>>> killing reader_process <<<<<<<<\n" );
/* tell the driver to stop scanning */
if( _ASIC_IS_USB != scanner->hw->caps.AsicID ) {
if( -1 != scanner->hw->fd ) {
int_cnt = 1;
scanner->hw->stopScan( scanner->hw, &int_cnt );
}
}
cancelRead = SANE_TRUE;
sigemptyset(&(act.sa_mask));
@ -607,10 +553,7 @@ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe )
sigaction( SIGALRM, &act, 0 );
/* kill our child process and wait until done */
if( _ASIC_IS_USB == scanner->hw->caps.AsicID )
kill( scanner->reader_pid, SIGUSR1 );
else
kill( scanner->reader_pid, SIGTERM );
kill( scanner->reader_pid, SIGUSR1 );
/* give'em 10 seconds 'til done...*/
alarm(10);
@ -652,18 +595,7 @@ static SANE_Status limitResolution( Plustek_Device *dev )
if( dev->dpi_range.min < _DEF_DPI )
dev->dpi_range.min = _DEF_DPI;
/*
* CHANGE: limit resolution to max. physical available one
* Note: the resolution for the Asic 96001/3 models is limited to
* the X-Resolution
*/
if((_ASIC_IS_96003 == dev->caps.AsicID) ||
(_ASIC_IS_96001 == dev->caps.AsicID)) {
dev->dpi_range.max = lens.rDpiX.wPhyMax;
} else {
dev->dpi_range.max = lens.rDpiY.wPhyMax;
}
dev->dpi_range.max = lens.rDpiY.wPhyMax;
dev->dpi_range.quant = 0;
dev->x_range.min = 0;
dev->x_range.max = SANE_FIX(dev->max_x);
@ -695,12 +627,6 @@ static SANE_Status initGammaSettings( Plustek_Scanner *s )
s->gamma_range.max = 255;
s->gamma_range.quant = 0;
if((_ASIC_IS_96003 == s->hw->caps.AsicID) ||
(_ASIC_IS_96001 == s->hw->caps.AsicID)) {
s->gamma_length = 256;
}
DBG( _DBG_INFO, "Presetting Gamma tables (len=%u)\n", s->gamma_length );
DBG( _DBG_INFO, "----------------------------------\n" );
@ -785,20 +711,8 @@ static SANE_Status init_options( Plustek_Scanner *s )
s->opt[OPT_MODE].type = SANE_TYPE_STRING;
s->opt[OPT_MODE].size = 32;
s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
if( _ASIC_IS_USB == s->hw->caps.AsicID ) {
s->opt[OPT_MODE].constraint.string_list = mode_usb_list;
s->val[OPT_MODE].w = 3; /* Color */
} else {
if((_ASIC_IS_98001 == s->hw->caps.AsicID) ||
(_ASIC_IS_98003 == s->hw->caps.AsicID)) {
s->opt[OPT_MODE].constraint.string_list = mode_9800x_list;
} else {
s->opt[OPT_MODE].constraint.string_list = mode_list;
}
s->val[OPT_MODE].w = 3; /* Color */
}
s->opt[OPT_MODE].constraint.string_list = mode_usb_list;
s->val[OPT_MODE].w = 3; /* Color */
/* scan source */
s->opt[OPT_EXT_MODE].name = SANE_NAME_SCAN_SOURCE;
@ -993,17 +907,18 @@ static void decodeUsbIDs( char *src, char **dest )
{
const char *name;
char *tmp = *dest;
int len = strlen(_SECTION);
if( isspace(src[5])) {
strncpy( tmp, &src[6], (strlen(src)-6));
tmp[(strlen(src)-6)] = '\0';
if( isspace(src[len])) {
strncpy( tmp, &src[len+1], (strlen(src)-(len+1)));
tmp[(strlen(src)-(len+1))] = '\0';
}
name = tmp;
name = sanei_config_skip_whitespace( name );
if( '\0' == name[0] ) {
DBG( _DBG_SANE_INIT, "next device is a USB device (autodetection)\n" );
DBG( _DBG_SANE_INIT, "next device uses autodetection\n" );
} else {
u_short pi = 0, vi = 0;
@ -1178,69 +1093,47 @@ static SANE_Status attach( const char *dev_name, pCnfDef cnf,
dev->name = strdup(dev_name); /* hold it double to avoid */
dev->sane.name = dev->name; /* compiler warnings */
dev->sane.vendor = "Plustek";
dev->initialized = SANE_FALSE;
dev->initialized = -1; /* will be used as index too */
dev->calFile = NULL;
memcpy( &dev->adj, &cnf->adj, sizeof(AdjDef));
show_cnf( cnf );
if( PARPORT == cnf->porttype ) {
dev->sane.type = "parallel port flatbed scanner";
dev->open = ppDev_open;
dev->close = ppDev_close;
dev->getCaps = ppDev_getCaps;
dev->getLensInfo = ppDev_getLensInfo;
dev->getCropInfo = ppDev_getCropInfo;
dev->putImgInfo = ppDev_putImgInfo;
dev->setScanEnv = ppDev_setScanEnv;
dev->startScan = ppDev_startScan;
dev->stopScan = ppDev_stopScan;
dev->setMap = ppDev_setMap;
dev->readImage = ppDev_readImage;
dev->shutdown = NULL;
dev->readLine = NULL;
dev->prepare = NULL;
} else {
dev->sane.type = "USB flatbed scanner";
dev->sane.type = "USB flatbed scanner";
#ifdef _PLUSTEK_USB
dev->open = usbDev_open;
dev->close = usbDev_close;
dev->getCaps = usbDev_getCaps;
dev->getLensInfo = usbDev_getLensInfo;
dev->getCropInfo = usbDev_getCropInfo;
dev->putImgInfo = NULL;
dev->setScanEnv = usbDev_setScanEnv;
dev->startScan = usbDev_startScan;
dev->stopScan = usbDev_stopScan;
dev->setMap = usbDev_setMap;
dev->readImage = NULL;
dev->readLine = usbDev_readLine;
dev->prepare = usbDev_Prepare;
dev->shutdown = usbDev_shutdown;
dev->open = usbDev_open;
dev->close = usbDev_close;
dev->getCaps = usbDev_getCaps;
dev->getLensInfo = usbDev_getLensInfo;
dev->getCropInfo = usbDev_getCropInfo;
dev->putImgInfo = NULL;
dev->setScanEnv = usbDev_setScanEnv;
dev->startScan = usbDev_startScan;
dev->stopScan = usbDev_stopScan;
dev->setMap = usbDev_setMap;
dev->readImage = NULL;
dev->readLine = usbDev_readLine;
dev->prepare = usbDev_Prepare;
dev->shutdown = usbDev_shutdown;
strncpy( dev->usbId, cnf->usbId, _MAX_ID_LEN );
strncpy( dev->usbId, cnf->usbId, _MAX_ID_LEN );
if( cnf->adj.warmup >= 0 )
dev->usbDev.dwWarmup = cnf->adj.warmup;
if( cnf->adj.warmup >= 0 )
dev->usbDev.dwWarmup = cnf->adj.warmup;
if( cnf->adj.lampOff >= 0 )
dev->usbDev.dwLampOnPeriod = cnf->adj.lampOff;
if( cnf->adj.lampOff >= 0 )
dev->usbDev.dwLampOnPeriod = cnf->adj.lampOff;
if( cnf->adj.lampOffOnEnd >= 0 )
dev->usbDev.bLampOffOnEnd = cnf->adj.lampOffOnEnd;
if( cnf->adj.lampOffOnEnd >= 0 )
dev->usbDev.bLampOffOnEnd = cnf->adj.lampOffOnEnd;
#else
free( dev->name );
free( dev );
DBG( _DBG_ERROR, "Portmode %u not supported\n", cnf->porttype );
return SANE_STATUS_INVAL;
free( dev->name );
free( dev );
DBG( _DBG_ERROR, "Backend non-functional on this platform :-(\n" );
return SANE_STATUS_INVAL;
#endif
}
/*
* go ahead and open the scanner device
@ -1277,28 +1170,16 @@ static SANE_Status attach( const char *dev_name, pCnfDef cnf,
/* save the info we got from the driver */
DBG( _DBG_INFO, "Scanner information:\n" );
if( dev->caps.Model == MODEL_OP_USB ) {
#ifdef _PLUSTEK_USB
if( NULL != dev->usbDev.ModelStr )
dev->sane.model = dev->usbDev.ModelStr;
else
#endif
dev->sane.model = ModelStr[MODEL_OP_USB];
} else if( dev->caps.Model < MODEL_OP_USB ) {
dev->sane.model = ModelStr[dev->caps.Model];
} else {
dev->sane.model = ModelStr[0];
}
if( NULL != dev->usbDev.ModelStr )
dev->sane.model = dev->usbDev.ModelStr;
else
#endif
dev->sane.model = "USB-Device";
DBG( _DBG_INFO, "Vendor : %s\n", dev->sane.vendor );
DBG( _DBG_INFO, "Model : %s\n", dev->sane.model );
DBG( _DBG_INFO, "Asic : 0x%02x\n", dev->caps.AsicID );
DBG( _DBG_INFO, "Flags : 0x%08lx\n", dev->caps.dwFlag );
DBG( _DBG_INFO, "Version: 0x%08x\n", dev->caps.Version );
dev->max_x = dev->caps.wMaxExtentX*MM_PER_INCH/_MEASURE_BASE;
dev->max_y = dev->caps.wMaxExtentY*MM_PER_INCH/_MEASURE_BASE;
@ -1433,7 +1314,11 @@ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize )
decodeVal( str, "blue_gain", _INT, &config.adj.bgain, &ival);
ival = 0;
decodeVal( str, "enableTPA", _INT, &config.adj.enableTpa, &ival);
decodeVal( str, "enableTPA", _INT, &config.adj.enableTpa, &ival);
decodeVal( str, "cacheCalData",
_INT, &config.adj.cacheCalData,&ival);
decodeVal( str, "altCalibrate",
_INT, &config.adj.altCalibrate,&ival);
decodeVal( str, "skipCalibration",
_INT, &config.adj.skipCalibration,&ival);
decodeVal( str, "skipFine",
@ -1460,7 +1345,7 @@ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize )
continue;
/* check for sections: */
} else if( 0 == strncmp( str, "[usb]", 5)) {
} else if( 0 == strncmp( str, _SECTION, strlen(_SECTION))) {
char *tmp;
@ -1474,21 +1359,9 @@ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize )
tmp = config.usbId;
decodeUsbIDs( str, &tmp );
config.porttype = USB;
DBG( _DBG_SANE_INIT, "next device is an USB device\n" );
continue;
} else if(( 0 == strncmp( str, "[parport]", 10))&&( '\0' == str[10])) {
/* new section, try and attach previous device */
if( config.devName[0] != '\0' )
attach( config.devName, &config, 0 );
/* re-initialize the configuration structure */
init_config_struct( &config, SANE_FALSE );
DBG( _DBG_SANE_INIT, "next device is a PARPORT device\n" );
continue;
} else if( SANE_TRUE == decodeDevName( str, config.devName )) {
continue;
}
@ -1527,6 +1400,9 @@ void sane_exit( void )
*/
if( dev->sane.name )
free( dev->name );
if( dev->calFile )
free( dev->calFile );
if( dev->res_list )
free( dev->res_list );
@ -1538,9 +1414,6 @@ void sane_exit( void )
if( devlist )
free( devlist );
/* call driver specific shutdown function... */
_DOWN();
devlist = NULL;
auth = NULL;
first_dev = NULL;
@ -1596,16 +1469,9 @@ SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle )
memset( &config, 0, sizeof(CnfDef));
/* check if a valid parport-device is meant... */
status = attach( devicename, &config, &dev );
if( SANE_STATUS_GOOD != status ) {
/* check if a valid usb-device is meant... */
config.porttype = USB;
status = attach( devicename, &config, &dev );
if( SANE_STATUS_GOOD != status )
return status;
}
if( SANE_STATUS_GOOD != status )
return status;
}
} else {
/* empty devicename -> use first device */
@ -1851,17 +1717,9 @@ SANE_Status sane_control_option( SANE_Handle handle, SANE_Int option,
case OPT_MODE: {
int idx = (optval - mode_list);
int idx = (optval - mode_usb_list);
if((_ASIC_IS_98001 == s->hw->caps.AsicID) ||
(_ASIC_IS_98003 == s->hw->caps.AsicID)) {
idx = optval - mode_9800x_list;
} else if( _ASIC_IS_USB == s->hw->caps.AsicID ) {
idx = optval - mode_usb_list;
}
mp = getModeList( s );
mp = getModeList( s );
if( mp[idx].scanmode != COLOR_HALFTONE ){
s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
@ -1922,15 +1780,8 @@ SANE_Status sane_control_option( SANE_Handle handle, SANE_Int option,
s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY);
s->val[OPT_MODE].w = 3; /* COLOR_TRUE24 */
if((_ASIC_IS_98001 == s->hw->caps.AsicID) ||
(_ASIC_IS_98003 == s->hw->caps.AsicID)) {
s->opt[OPT_MODE].constraint.string_list = mode_9800x_list;
} else if( _ASIC_IS_USB == s->hw->caps.AsicID ) {
s->opt[OPT_MODE].constraint.string_list = mode_usb_list;
s->val[OPT_MODE].w = 3; /* COLOR_TRUE24 */
} else {
s->opt[OPT_MODE].constraint.string_list = mode_list;
}
s->opt[OPT_MODE].constraint.string_list = mode_usb_list;
s->val[OPT_MODE].w = 3; /* COLOR_TRUE24 */
} else {
@ -1955,12 +1806,8 @@ SANE_Status sane_control_option( SANE_Handle handle, SANE_Int option,
if( s->hw->caps.dwFlag & SFLAG_TPA ) {
if( _ASIC_IS_USB == s->hw->caps.AsicID )
s->opt[OPT_MODE].constraint.string_list =
s->opt[OPT_MODE].constraint.string_list =
&mode_usb_list[_TPAModeSupportMin];
else
s->opt[OPT_MODE].constraint.string_list =
&mode_9800x_list[_TPAModeSupportMin];
} else {
s->opt[OPT_MODE].constraint.string_list =
&mode_list[_TPAModeSupportMin];
@ -2230,11 +2077,9 @@ SANE_Status sane_start( SANE_Handle handle )
/* build a SCANINFO block and get ready to scan it */
sinfo.ImgDef.dwFlag |= (SCANDEF_BuildBwMap | SCANDEF_QualityScan);
/* remove that for preview scans (USB only) */
if( _ASIC_IS_USB == s->hw->caps.AsicID ) {
if( s->val[OPT_PREVIEW].w )
sinfo.ImgDef.dwFlag &= (~SCANDEF_QualityScan);
}
/* remove that for preview scans */
if( s->val[OPT_PREVIEW].w )
sinfo.ImgDef.dwFlag &= (~SCANDEF_QualityScan);
/* set adjustments for brightness and contrast */
sinfo.siBrightness = s->val[OPT_BRIGHTNESS].w;

Wyświetl plik

@ -1,27 +1,12 @@
# Plustek-SANE Backend configuration file
# For use with Plustek parallel-port scanners and
# LM9831/2/3 based USB scanners
# For use with LM9831/2/3 based USB scanners
#
# For parport devices use the parport section
#
[parport]
device /dev/pt_drv
#
# leave the default values as specified in /etc/modules.conf
#
option warmup -1
option lOffOnEnd -1
option lampOff -1
#
# The USB section:
# each device needs at least two lines:
# - [usb] vendor-ID and product-ID
# - [merlin-device] vendor-ID and product-ID
# - device devicename
# i.e. for Plustek (0x07B3) UT12/16/24 (0x0017)
# [usb] 0x07B3 0x0017
# [merlin-device] 0x07B3 0x0017
# device /dev/usbscanner
# or
# device libusb:bbb:ddd
@ -32,15 +17,15 @@ option lampOff -1
# warmup, lOffOnEnd, lampOff
#
# For autodetection use
# [usb]
# [merlin-device]
# device /dev/usbscanner
#
# or simply
# [usb]
# [merlin-device]
#
# or if you want a specific device but you have no idea about
# the device node or you use libusb, simply set vendor- and product-ID
# [usb] 0x07B3 0x0017
# [merlin-device] 0x07B3 0x0017
# device auto
#
# NOTE: autodetection is safe, as it uses the info it got
@ -49,7 +34,7 @@ option lampOff -1
# at your USB-port, that you have specified...
#
[usb]
[merlin-device]
#
# options for the previous USB entry
@ -95,6 +80,16 @@ option negShadingY -1
#
option invertNegatives 0
#
# to save/restore coarse calibration data
#
option cacheCalData 0
#
# use alternate calibration routines
#
option altCalibration 0
# for skipping whole calibration step
option skipCalibration 0
@ -134,5 +129,5 @@ device auto
#
# to define a new device, start with a new section:
# [usb] or [parport]
# [merlin-device]
#

Wyświetl plik

@ -40,6 +40,8 @@
* - 0.43 - no changes
* - 0.44 - added flag initialized
* - 0.45 - added readLine function
* - 0.46 - flag initialized is now used as device index
* - added calFile to Plustek_Device
* .
* <hr>
* This file is part of the SANE package.
@ -159,12 +161,50 @@ typedef enum {
NUM_PORTTYPES
} PORTTYPE;
/** for adjusting the scanner settings
*/
typedef struct {
int lampOff;
int lampOffOnEnd;
int warmup;
int enableTpa;
int skipCalibration;
int skipFine;
int skipFineWhite;
int invertNegatives;
int cacheCalData;
int altCalibrate; /* force use of the alternate canoscan
autocal; perhaps other Canon
scanners require the alternate
autocalibration as well */
int rgain;
int ggain;
int bgain;
OffsDef pos; /* for adjusting normal scan area */
OffsDef tpa; /* for adjusting transparency scan area */
OffsDef neg; /* for adjusting negative scan area */
int posShadingY;
int tpaShadingY;
int negShadingY;
/* for adjusting the default gamma settings */
double rgamma;
double ggamma;
double bgamma;
double graygamma;
} AdjDef, *pAdjDef;
typedef struct Plustek_Device
{
SANE_Bool initialized; /* device already initialized? */
SANE_Int initialized; /* device already initialized? */
struct Plustek_Device *next; /* pointer to next dev in list */
int fd; /* device handle */
char *name; /* (to avoid compiler warnings!)*/
char *calFile; /* for saving calibration data */
SANE_Device sane; /* info struct */
SANE_Int max_x; /* max XY-extension of the scan-*/
SANE_Int max_y; /* area */
@ -185,7 +225,6 @@ typedef struct Plustek_Device
DeviceDef usbDev;
struct itimerval saveSettings; /* for lamp timer */
#endif
/*
* each device we support may need other access functions...
*/
@ -208,6 +247,16 @@ typedef struct Plustek_Device
} Plustek_Device, *pPlustek_Device;
#ifndef SANE_OPTION
/* for compatibility with older versions */
typedef union
{
SANE_Word w;
SANE_Word *wa; /* word array */
SANE_String s;
} Option_Value;
#endif
typedef struct Plustek_Scanner
{
struct Plustek_Scanner *next;
@ -232,20 +281,11 @@ typedef struct Plustek_Scanner
} Plustek_Scanner, *pPlustek_Scanner;
typedef const struct mode_param {
int color;
int depth;
int scanmode;
} ModeParam, *pModeParam;
/*
* for collecting configuration info...
/** for collecting configuration info...
*/
typedef struct {
char devName[PATH_MAX];
PORTTYPE porttype;
char usbId[_MAX_ID_LEN];
/* contains the stuff to adjust... */

2188
backend/plustek_pp.c 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,33 @@
# Plustek-PP SANE Backend configuration file
# For use with Plustek parallel-port scanners
#
#
# user either [direct] or [kernel] to access the scanner
# when using [kernel], device specifies the device-node, which is created
# by the kernel-modules loader
# when using [direct], device is used to set the parallel-port base address
#
[direct]
device 0x378
#
# leave the default values as specified in /etc/modules.conf
#
option warmup -1
option lOffOnEnd -1
option lampOff -1
# model override switch, mostly for cosmetic changes, if the autodetection
# does not work or could not work correctly
#option mov 7
#
# example for accessing the scanner via the kernel module
#
[kernel]
device /dev/pt_drv
option warmup -1
option lOffOnEnd -1
option lampOff -1

Wyświetl plik

@ -269,7 +269,7 @@ else
BACKENDS="abaton agfafocus apple artec as6e avision bh canon \
canon630u coolscan coolscan2 dc25 dmc \
epson fujitsu gt68xx hp leo matsushita microtek \
microtek2 mustek mustek_pp mustek_usb nec pie plustek \
microtek2 mustek mustek_pp mustek_usb nec pie plustek plustek_pp \
ricoh s9036 sceptre sharp \
sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \
artec_eplus48u ma1509 ibm hp5400"

Wyświetl plik

@ -51,7 +51,7 @@ SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 \
sane-mustek_usb.5 sane-sceptre.5 sane-canon_pp.5 sane-canon630u.5 \
sane-teco1.5 sane-teco2.5 sane-teco3.5 sane-test.5 sane-sp15c.5 \
sane-coolscan2.5 sane-hpsj5s.5 sane-gt68xx.5 sane-artec_eplus48u.5 \
sane-ma1509.5 sane-ibm.5 sane-hp5400.5
sane-ma1509.5 sane-ibm.5 sane-hp5400.5 sane-plustek_pp.5
SECT7 = sane.7
MANPAGES = $(SECT1) $(SECT5) $(SECT7)
READMES = README AUTHORS COPYING ChangeLog LICENSE NEWS PROBLEMS \
@ -102,7 +102,7 @@ DISTFILES = Makefile.in backend-writing.txt descriptions.txt \
sane.tex saned.man scanimage.man sane-sceptre.man sane-canon_pp.man \
sane-teco1.man sane-teco2.man sane-teco3.man sane-test.man sane-sp15c.man \
sane-hpsj5s.man gamma4scanimage.man sane-gt68xx.man sane-artec_eplus48u.man \
sane-ma1509.man sane-ibm.man sane-hp5400.man
sane-ma1509.man sane-ibm.man sane-hp5400.man sane-plustek_pp.man
.PHONY: all clean depend dist distclean html html-man install \
install-mostang sane-html uninstall

Wyświetl plik

@ -1,9 +1,9 @@
;
; SANE Backend description file for Plustek backend
; SANE Backend description file for Plustek backend (USB only)
;
:backend "plustek"
:version "0.45"
:version "0.46"
:manpage "sane-plustek"
; backend's web page
:url "http://www.gjaeger.de/scanner/plustek.html"
@ -17,79 +17,6 @@
:url "http://www.plustek.com/"
;name models for above-specified mfg.
:model "OpticPro 4800P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 4830P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 600P/6000P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 4831P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 9630P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 9630PL"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=1"
:model "OpticPro 9600P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 1236P"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "reported as OpticPro 12000P/96000P"
:model "OpticPro 12000P/96000P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 9636P"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=4"
:model "OpticPro 9636P+/Turbo"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=3"
:model "OpticPro 9636T"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 12000T"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro AI3"
:interface "Parport (SPP, EPP)"
:status :basic
:comment "use driver-switch mov=5, poor picture quality"
:model "OpticPro P8"
:interface "Parport"
:status :untested
:model "OpticPro P12"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro PT12"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro U12"
:interface "USB"
:status :complete
@ -119,51 +46,11 @@
:status :unsupported
:comment "rebadged Artec AM12S (supported by Artec Backend)"
;* Primax ***********************************************************************************
:mfg "Primax" ; name of manufacturer
:url "http://www.primax.nl/"
;name models for above-specified mfg.
:model "Colorado 4800"
:interface "Parport (SPP, EPP)"
:status :untested
:comment "same as OpticPro 4800P"
:model "Compact 4800 Direct"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=2"
:model "Compact 4800 Direct-30"
:interface "Parport (SPP, EPP)"
:status :untested
:comment "same as OpticPro 4830P"
:model "Compact 9600 Direct-30"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "same as OpticPro 9630P"
;* Genius/KYE *******************************************************************************************
:mfg "Genius"
:url "http://www.geniusnet.com.tw/"
:model "Colorpage Vivid III V2"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "Reported as PT12"
:model "Colorpage Vivid Pro II Film"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "Reported as OP9636T/12000T"
:model "Colorpage HR6X EPP"
:interface "Parport (SPP, EPP)"
:status :untested
:model "Colorpage HR6 V2"
:interface "USB"
:status :complete
@ -184,24 +71,6 @@
:interface "USB"
:status :untested
;********************************************************************************************
:mfg "Aries"
:model "Scan-It Pro 4800"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=2"
;********************************************************************************************
:mfg "BrightScan"
:model "BrighScan OpticPro"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "Reported as P12"
;* MUSTEK ***********************************************************************************
:mfg "Mustek"
@ -286,30 +155,25 @@
:model "CanoScan N650U/N656U"
:interface "USB"
:status :basic
:status :complete
:model "CanoScan N1220U"
:interface "USB"
:status :basic
:comment "Poor color picture quality"
:status :complete
:model "CanoScan N670U/N676U"
:interface "USB"
:status :basic
:comment "Poor color picture quality"
:status :complete
:model "CanoScan N1240U"
:interface "USB"
:status :basic
:comment "Poor color picture quality"
:status :complete
:model "CanoScan LiDE20"
:interface "USB"
:status :basic
:comment "Poor color picture quality"
:status :complete
:model "CanoScan LiDE30"
:interface "USB"
:status :basic
:comment "Poor color picture quality"
:status :complete

Wyświetl plik

@ -0,0 +1,155 @@
;
; SANE Backend description file for Plustek_pp backend
;
:backend "plustek_pp"
:version "0.01"
:manpage "sane-plustek_pp"
; backend's web page
:url "http://www.gjaeger.de/scanner/plustek.html"
:devicetype :scanner
;* Plustek **********************************************************************************
:mfg "Plustek"
:url "http://www.plustek.de/"
:url "http://www.plustek.com/"
;name models for above-specified mfg.
:model "OpticPro 4800P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 4830P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 600P/6000P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 4831P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 9630P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 9630PL"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=1"
:model "OpticPro 9600P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 1236P"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "reported as OpticPro 12000P/96000P"
:model "OpticPro 12000P/96000P"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 9636P"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=4"
:model "OpticPro 9636P+/Turbo"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=3"
:model "OpticPro 9636T"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro 12000T"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro AI3"
:interface "Parport (SPP, EPP)"
:status :basic
:comment "use driver-switch mov=5, poor picture quality"
:model "OpticPro P8"
:interface "Parport"
:status :untested
:model "OpticPro P12"
:interface "Parport (SPP, EPP)"
:status :complete
:model "OpticPro PT12"
:interface "Parport (SPP, EPP)"
:status :complete
;* Primax ***********************************************************************************
:mfg "Primax" ; name of manufacturer
:url "http://www.primax.nl/"
;name models for above-specified mfg.
:model "Colorado 4800"
:interface "Parport (SPP, EPP)"
:status :untested
:comment "same as OpticPro 4800P"
:model "Compact 4800 Direct"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=2"
:model "Compact 4800 Direct-30"
:interface "Parport (SPP, EPP)"
:status :untested
:comment "same as OpticPro 4830P, use driver-switch mov=7"
:model "Compact 9600 Direct-30"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "same as OpticPro 9630P"
;* Genius/KYE *******************************************************************************************
:mfg "Genius"
:url "http://www.geniusnet.com.tw/"
:model "Colorpage Vivid III V2"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "Reported as PT12"
:model "Colorpage Vivid Pro II Film"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "Reported as OP9636T/12000T"
:model "Colorpage HR6X EPP"
:interface "Parport (SPP, EPP)"
:status :untested
;********************************************************************************************
:mfg "Aries"
:model "Scan-It Pro 4800"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "use driver-switch mov=2"
;********************************************************************************************
:mfg "BrightScan"
:model "BrighScan OpticPro"
:interface "Parport (SPP, EPP)"
:status :complete
:comment "Reported as P12"

Wyświetl plik

@ -1,4 +1,4 @@
.TH sane-plustek 5 "30 May 2003" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.TH sane-plustek 5 "17 September 2003" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.IX sane-plustek
.SH NAME
sane-plustek \- SANE backend for Plustek parallel port and
@ -76,7 +76,7 @@ Colorado 4800 OpticPro 4800 not tested
.br
Compact 4800 Direct OpticPro 600 mov=2
.br
Compact 4800 Direct 30bit OpticPro 4830 not tested
Compact 4800 Direct 30bit OpticPro 4830 mov=7
.br
Compact 9600 Direct 30bit OpticPro 9630 works
.PP
@ -268,7 +268,15 @@ backend.
.br
Only the National Semiconductor LM9831/2 based devices of Plustek
are supported by this driver. Older versions of the U12, the UT12,
the U1212 and U1248 (GrandTech chipset are not supported)
the U1212 and U1248 (GrandTech chipset) are not supported.
.PP
Model Chipset backend
.br
---------------------------
.br
U1248 GrandTech gt68xx
.br
UT16B GrandTech gt68xx
.PP
.SH "DEVICE NAMES"
@ -433,6 +441,11 @@ mov=m
.br
has been detected) swaps red/green color
.br
.I m
=7 - Primax 4800Direct 30bit override (works if OP4830
.br
has been detected)
.br
.RE
.PP
Sample entry for file

Wyświetl plik

@ -0,0 +1,753 @@
.TH sane-plustek 5 "17 September 2003" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.IX sane-plustek
.SH NAME
sane-plustek \- SANE backend for Plustek parallel port and
LM983[1/2/3] based USB flatbed scanners
.SH DESCRIPTION
The
.B sane-plustek
library implements a SANE (Scanner Access Now Easy) backend that
provides access to Plustek parallel port and USB flatbed scanners.
The USB support is part of the SANE package but for usage with
parallel port scanners you will need a kernel module, called
pt_drv which currently can be downloaded from
.br
.B http://www.gjaeger.de/scanner/plustek.html
.PP
.B !!!Please note that you need the kernel module only for
.B parallel port scanners!!!
.SH "PARALLEL PORT SUPPORT"
At present, the following scanners should work with this backend
and the corresponding kernel module:
.PP
.B "PLUSTEK SCANNERS"
.PP
Parallelport Model: ASIC: Properties:
.br
---------------------- ----- ------------------------
.br
OpticPro PT12 98003 600x1200 dpi 36bit 512Kb
.br
OpticPro P12 98003 600x1200 dpi 36bit 512Kb
.br
OpticPro 9636T/12000T 98001 600x1200 dpi 36bit 512Kb
.br
OpticPro 12000P Turbo 98001 600x1200 dpi 36bit 512Kb
.br
OpticPro 9636P+/Turbo 98001 600x1200 dpi 36bit 512Kb
.br
OpticPro 9636P 96003 600x1200 dpi 36bit 128Kb
.br
OpticPro 12000P/96000P 96003 600x1200 dpi 36bit 128Kb
.br
OpticPro 1236P 96003 600x1200 dpi 30bit 128Kb
.br
OpticPro 9600P 96003 600x1200 dpi 30bit 128Kb
.br
OpticPro 9630P/FBIV 96003 600x1200 dpi 30bit 128Kb
.br
OpticPro 9630PL (14") 96003 600x1200 dpi 30bit 128Kb
.br
OpticPro A3I 96003 400x800 dpi 36bit 128Kb
.br
OpticPro 600P/6000P 96003 300x600 dpi 30bit 32Kb
.br
OpticPro 4831P 96003 300x600 dpi 30bit 32Kb
.br
OpticPro 4830P/FBIII 96003 300x600 dpi 30bit 32Kb
.br
OpticPro 4800P/FBII 96001 300x600 dpi 24bit 32Kb
.br
.PP
.B "PRIMAX SCANNERS"
There are some scanners sold by Primax, but they are in fact
Plustek devices. These scanners are also supported.
The following table will show the relationship:
.PP
Model: Plustek Model: Remarks:
.br
--------------------------- -------------- ------------
.br
Colorado 4800 OpticPro 4800 not tested
.br
Compact 4800 Direct OpticPro 600 mov=2
.br
Compact 4800 Direct 30bit OpticPro 4830 mov=7
.br
Compact 9600 Direct 30bit OpticPro 9630 works
.PP
.B "GENIUS SCANNERS"
The following devices are sold as Genius Scanners, but are in fact
Plustek devices.
The table will show the relationship:
.PP
Model: Remarks:
.br
--------------------------- ----------------------------
.br
Colorpage Vivid III V2 Like P12 but has two buttons
.br
and Wolfson DAC
.PP
.B "ARIES SCANNERS"
There's one scanner sold as Aries Scanner, but is in fact a
Plustek device.
The following table will show the relationship:
.PP
Model: Plustek Model: Remarks:
.br
--------------------------- -------------- ------------
.br
Scan-It 4800 OpticPro 600 mov=2
.PP
.B "BrightScan SCANNERS"
There's one scanner sold as BrightScan OpticPro Scanner, this is also
rebadged Plustek device.
The following table will show the relationship:
.PP
Model: Remarks:
.br
--------------------------- ----------------------------
.br
BrightScan OpticPro OpticPro P12
.SH "USB SUPPORT"
The Backend is able to support USB scanner based on the National
Semiconductor chipset LM9831, LM9832 and LM9833. The following tables
show various devices which are currently reported to work. If your
Plustek scanner has another Product ID, then the device is
.B NOT
supported, as it contains unsupported ASICs inside.
.br
Vendor Plustek - ID: 0x07B3
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
OpticPro U12 LM9831 600x1200dpi 42bit 512Kb 0x0010
.br
OpticPro UT12 LM9831 600x1200dpi 42bit 512Kb 0x0013
.br
OpticPro UT12 LM9832 600x1200dpi 42bit 512Kb 0x0017
.br
OpticPro UT16 LM9832 600x1200dpi 42bit 512Kb 0x0017
.br
OpticPro U24 LM9831 1200x2400dpi 42bit 2Mb 0x0011
.br
OpticPro U24 LM9832 1200x2400dpi 42bit 2Mb 0x0015
.br
OpticPro UT24 LM9832 1200x2400dpi 42bit 2Mb 0x0017
.PP
Vendor KYE/Genius - ID: 0x0458
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
Colorpage HR6 V2 LM9832 600x1200dpi 42bit 512Kb 0x2007
.br
Colorpage HR6 V2 LM9832 600x1200dpi 42bit 512Kb 0x2008
.br
Colorpage HR6A LM9832 600x1200dpi 42bit 512Kb 0x2009
.br
Colorpage HR7 LM9832 600x1200dpi 42bit 512Kb 0x2013
.br
Colorpage HR7LE LM9832 600x1200dpi 42bit 512Kb 0x2015
.br
Colorpage HR6X LM9832 600x1200dpi 42bit 512Kb 0x2016
.PP
Vendor Hewlett-Packard - ID: 0x03F0
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
ScanJet 2100C LM9831 600x1200dpi 42bit 512Kb 0x0505
.br
ScanJet 2200C LM9832 600x1200dpi 42bit 512Kb 0x0605
.PP
Vendor Mustek - ID: 0x0400
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
BearPaw 1200 LM9831 600x1200dpi 42bit 512Kb 0x1000
.br
BearPaw 2400 LM9832 1200x2400dpi 42bit 2Mb 0x1001
.PP
Vendor UMAX - ID: 0x1606
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
UMAX 3400/3450 LM9832 600x1200dpi 42bit 512Kb 0x0060
.br
UMAX 5400 LM9832 1200x2400dpi 42bit 512Kb 0x0160
.PP
Vendor COMPAQ - ID: 0x049F
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
S4-100 LM9832 600x1200dpi 42bit 512Kb 0x001A
.PP
Vendor Epson - ID: 0x04B8
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
Perfection 1250 LM9832 1200x2400dpi 42bit 512Kb 0x010F
.br
Perfection 1260 LM9832 1200x2400dpi 42bit 512Kb 0x011D
.PP
Vendor CANON - ID: 0x04A9
.br
----------------------------------------------------------
.br
USB Model: ASIC: Properties: Prod-ID
.br
----------------------------------------------------------
.br
CanoScan N650/656U LM9832 600x1200dpi 42bit 512Kb 0x2206
.br
CanoScan N1220U LM9832 1200x2400dpi 42bit 512Kb 0x2207
.br
CanoScan N670/676U LM9833 600x1200dpi 48bit 512Kb 0x220D
.br
CanoScan N1240U LM9833 1200x2400dpi 48bit 512Kb 0x220E
.br
CanoScan LIDE20 LM9833 600x1200dpi 48bit 512Kb 0x220D
.br
CanoScan LIDE30 LM9833 1200x2400dpi 48bit 512Kb 0x220E
.PP
.SH "OTHER PLUSTEK SCANNERS"
The SCSI scanner OpticPro 19200S is a rebadged Artec AM12S scanner
and is supported by the
.B Artec
backend.
.br
Only the National Semiconductor LM9831/2 based devices of Plustek
are supported by this driver. Older versions of the U12, the UT12,
the U1212 and U1248 (GrandTech chipset) are not supported.
.PP
Model Chipset backend
.br
---------------------------
.br
U1248 GrandTech gt68xx
.br
UT16B GrandTech gt68xx
.PP
.SH "DEVICE NAMES"
This backend expects a default device called:
.PP
.RS
.I /dev/pt_drv
.RE
.PP
This default device will be used, if no configuration
file can be found.
.PP
The device-driver is currently not part of the SANE distribution.
It has to be downloaded from:
.br
.B http://www.gjaeger.de/scanner/plustek.html
.br
See the INSTALL file there for a proper setup. Currently only Linux
is supported by this driver (Kernel 2.2.x and higher).
.PP
As the backend and the driver support up to four devices
per system, it is possible to specify them in the configuration
file
.PP
.RS
.I @CONFIGDIR@/plustek.conf
.RE
.PP
See the plustek.conf file for examples.
.PP
.SH "CONFIGURATION"
.PP
The configuration of this backend can be divided into two sections:
.br
.PP
.B "CONFIGURATION - parallel port scanner"
.PP
.br
.B "CONFIGURATION - USB scanner"
.PP
.br
Please make sure, that the configuration matches the real world,
namely your configuration. And note again, .I pt_drv is only needed
.PP
.SH "CONFIGURATION - PARALLEL PORT SCANNER"
.PP
Beside the kernel-module options, which are described below, you
need to enable the parallel port device in the configuration file
.PP
.RS
.I @CONFIGDIR@/plustek.conf
.RE
.PP
For a proper setup, you will need at least two entries:
.TP
.I [parport]
.TP
.I device /dev/pt_drv
.PP
.I parport
tells the backend, that the following devicename (here
.I /dev/pt_drv
) has to be interpreted as parallel port scanner device.
.PP
To have this device, you will need to setup the kernel module.
As the driver is a loadable kernel module, it is configured
by invoking insmod with the appropriate parameters or
appending the options to the file
.B /etc/conf.modules
.PP
.B
The Options:
.br
lampoff=lll
.RS
The value
.I lll
tells the driver, after how many seconds to
switch-off the lamp(s). The default value is 180.
0 will disable this feature.
.br
.B HINT:
Do not use a value that is too small, because often
switching on/off the lamps will reduce their lifetime.
.RE
.PP
port=ppp
.RS
.I ppp
specifies the port base address, where the scanner
is connected to. The default value is 0x378 which
normaly is standard.
.RE
.PP
warmup=www
.RS
.I www
specifies the time in seconds, how long a lamp has to be on,
until the driver will start to scan. The default value is 30.
.RE
.PP
lOffonEnd=e
.RS
.I e
specifies the behaviour when unloading the driver, 1 --> switch
lamps off, 0 --> do not change lamp status
.RE
.PP
slowIO=s
.RS
.I s
specifies which I/O functions the driver should use, 1 --> use
delayed functions, 0 --> use the non-delayed ones
.RE
.PP
forceMode=fm
.RS
.I fm
specifies port mode which should be used, 0 --> autodetection,
1 --> use SPP mode and 2 --> use EPP mode
.RE
.PP
mov=m
.RS
.I m
=0 - default: no override
.br
.I m
=1 - OpticPro 9630PL override (works if OP9630
.br
has been detected) forces legal size (14")
.br
.I m
=2 - Primax 4800Direct override (works if OP600
.br
has been detected) swaps red/green color
.br
.I m
=3 - OpticPro 9636 override (works if OP9636 has
.br
been detected) disables backends
.br
transparency/negativ capabilities
.br
.I m
=4 - OpticPro 9636P override (works if OP9636 has
.br
been detected) disables backends
.br
transparency/negativ capabilities
.br
.I m
=5 - OpticPro A3I override (works if OP12000 has
.br
been detected) enables A3 scanning
.br
.I m
=6 - OpticPro 4800P override (works if OP600
.br
has been detected) swaps red/green color
.br
.I m
=7 - Primax 4800Direct 30bit override (works if OP4830
.br
has been detected)
.br
.RE
.PP
Sample entry for file
.B "/etc/modules.conf"
:
.br
.I alias char-major-40 pt_drv
.br
.I pre-install pt_drv modprobe -k parport
.br
.I options pt_drv lampoff=180 warmup=15 port=0x378 lOffonEnd=0 mov=0 slowIO=0 forceMode=0
.PP
For multidevice support, simply add values separated by commas to
the different options
.br
.I options pt_drv port=0x378,0x278 mov=0,4 slowIO=0,1 forceMode=0,1
.PP
Remember to call depmod after changing /etc/conf.modules.
.PP
.B "PARALLEL PORT MODES"
.PP
The current driver works best, when the parallel port
has been set to EPP-mode. When detecting any other
mode such as ECP or PS/2 the driver tries to set to a
faster, supported mode. If this fails, it will use the
SPP mode, as this mode should work with all Linux supported
parallel ports.
.PP
Former Plustek scanner models (4830, 9630) supplied a
ISA parallel port adapter card. This card is
.BR not
supported by the driver.
.PP
The ASIC 96001/3 based models have sometimes trouble with
high resolution modes. If you encounter sporadic corrupted
images (parts duplicated or shifted horizontally) kill all
other applications before scanning and (if sufficient
memory available) disable swapping.
.PP
.SH "CONFIGURATION - USB SCANNER"
.PP
To use the USB device with this backend, you need at least
two entries in the configuration file
.br
.I @CONFIGDIR@/plustek.conf
.TP
.I [usb] vendor-id product-id
.TP
.I device /dev/usbscanner
.PP
.I usb
tells the backend, that the following devicename (here
.I /dev/usbscanner
) has to be interpreted as USB scanner device. If vendor- and
product-id has not been specified, the backend tries to
detect this by its own. If device ist set to
.I auto
then the next matching device is used.
.PP
.B
The Options:
.PP
option warmup t
.RS
.I t
specifies the warmup period in seconds
.RE
.PP
option lampOff t
.RS
.I t
is the time in seconds for switching off the lamps in
standby mode
.RE
.PP
option lOffonEnd b
.RS
.I b
specifies the behaviour when closing the backend, 1 --> switch
lamps off, 0 --> do not change lamp status
.RE
.PP
option invertNegatives b
.RS
.I b
0 --> do not invert the picture during negativ scans,
1 --> invert picture
.RE
.PP
option skipCalibration b
.RS
.I b
0 --> perform calibration,
1 --> skip calibration (only non Plustek devices)
.RE
.PP
option enableTPA b
.RS
.I b
0 --> default behaviour, specified by the internal tables,
1 --> override internal tables and allow TPA mode (EPSON only)
.RE
.PP
option posOffX x
.br
option posOffY y
.br
option tpaOffX x
.br
option tpaOffY y
.br
option negOffX x
.br
option negOffY y
.RS
.I x y
By using this settings, the user can adjust the given image
positions.
.B Please note, that there's no internal range checking for
.B this feature.
.RE
.PP
option posShadingY p
.br
option tpaShadingY p
.br
option negShadingY p
.RS
.I p
overrides the internal shading position. The values are in steps.
.B Please note, that there's no internal range checking for
.B this feature.
.RE
.PP
option redGamma r
.br
option greenGamma g
.br
option blueGamma b
.br
option grayGamma gr
.RS
.I r g b gr
.RE
By using these values, the internal linear gamma table (r,g,b,gr = 1.0)
can be adjusted.
.PP
option red_gain r
.br
option green_gain g
.br
option blue_gain b
.RS
.I r g b
These values can be used to adjust the internally detected gain values of
the AFE for each channel. The range is between 0 and 63.
.RE
.PP
See the plustek.conf file for examples.
.PP
.B Note:
.br
You have to make sure, that the USB subsystem is loaded
correctly and the module
.I scanner
has been loaded too. To make this module recognize your
scanner, you might have to add the following line to
your
.B "/etc/modules.conf"
:
.br
.I options scanner vendor=0x7b3 product=0x17
.PP
.br
If you're not sure about the vendor and product id of your
device, simply load the USB subsystem and plug in your
scanner. Then do a
.I cat /proc/bus/usb/devices
and look for the scanner.
.PP
.SH FILES
.TP
.I @CONFIGDIR@/plustek.conf
The backend configuration file
.TP
.I @LIBDIR@/libsane-plustek.a
The static library implementing this backend.
.TP
.I @LIBDIR@/libsane-plustek.so
The shared library implementing this backend (present on systems that
support dynamic loading).
.TP
.I /lib/modules/<Kernel-Version>/misc/pt_drv.o
The Linux Kernelmodule.
.PP
.SH "CONTACT AND BUG-REPORTS"
.PP
Please send any information and bug-reports to:
.br
.B Plustek Driver Mailing List <plustek@linuxhacker.org>
.br
or directly to:
.br
.B Gerhard Jaeger <gerhard@gjaeger.de>
.PP
Additional info and hints can be obtained from our
.br
Mailing-List archive at:
.br
.B http://www.linuxhacker.org/cgi-bin/ezmlm-cgi/3
.PP
or directly from the projects' homepage at:
.br
.B http://www.gjaeger.de/scanner/plustek.html
.PP
To obtain debug messages from the backend, please set the
environment-variable
.I SANE_DEBUG_PLUSTEK
before calling your favorite scan-frontend (i.e. xscanimage).
.br
.B i.e.: export SANE_DEBUG_PLUSTEK=20 ; xscanimage
.PP
The value controls the verbosity of the backend. Please note, that
values greater than 19 force the backend to output raw data files,
which could be rather large. The ending of these files is ".raw".
For problem reports it should be enough the set the verbosity to
13.
.PP
.SH "KNOWN BUGS & RESTRICTIONS"
.PP
.br
* The Halftoning works, but the quality is poor
.br
* Printers (especially HP models) will start to
.br
print during scanning. This in fact is a problem
.br
to other printers too, using bidirectional protocol
.br
(see www.plustek.com (TAIWAN) page for further details)
.br
* The driver does not support these manic scalings up
.br
to 16 times the physical resolution. The only scaling
.br
is done on resolutions between the physical resolution
.br
of the CDD-sensor and the stepper motor i.e. you have a
.br
600x1200 dpi scanner and you are scanning using 800dpi,
.br
so scaling is necesary, because the sensor only delivers
.br
600dpi but the motor is capable to perform 800dpi steps.
.br
* On some devices, the pictures seems to be bluished
.PP
ASIC 98001 based models:
.br
* The 300dpi transparency and negative mode does not work
.br
correctly.
.br
* There is currently no way to distinguish a model with
.br
and without transpareny unit.
.br
* The scanned images seem to be too dark (P9636T)
.PP
ASIC 96003/1 based models:
.br
* 30bit mode is currently not supported.
.br
* On low-end systems and under heavy system load, the
.br
driver will loosing data, this might causes the sensor
.br
to hit the scan-bed and/or the picture is corrupted.
.br
* The scanspeed on 600x1200 dpi models is slow.
.br
* The scanquality of the A3I is poor
.br
.PP
USB models:
.br
* Plusteks' model policy is somewhat inconsistent. This
.br
means, they sell technical different devices under the
.br
same product name. Therefore it is possible that some
.br
devices like the UT12 or U12 won't work - please check
.br
the model list above and compare the product-id to
.br
the one your device has.
.br
* Negative scanning quality is poor.