Added support for CIS-based sheetfed scanners, namely

TravelScan662.
Added support for saving calibration data for CIS
devices - should speedup CanoScan devices.
merge-requests/1/head
Gerhard Jaeger 2006-05-28 11:25:53 +00:00
rodzic 55c30456b9
commit c41669198f
15 zmienionych plików z 2246 dodań i 1069 usunięć

Wyświetl plik

@ -1,3 +1,19 @@
2006-5-28 Gerhard Jaeger <gerhard@gjaeger.de>
* doc/sane-plustek_pp.man: Fixed typo.
* doc/sane-plustek.man: Update.
* doc/descriptions/plustek.desc: Update.
* backend/plustek.c backend/plustek.h backend/plustek-usb.c
backend/plustek-usbcal.c backend/plustek-usbcalfile.c
backend/plustek-usbdevs.c backend/plustek-usb.h
backend/plustek-usbhw.c backend/plustek-usbimg.c
backend/plustek-usbio.c backend/plustek-usbmap.c
backend/plustek-usbscan.c backend/plustek-usbshading.c:
Added support for CIS-based sheetfed scanners, namely
TravelScan662.
Added support for saving calibration data for CIS
devices - should speedup CanoScan devices.
2006-05-28 Wittawat Yamwong <wittawat@web.de>
* backend/pixma.h: Added #define ENODATA and EPROTO to let the
@ -74,7 +90,7 @@
do_cmd() - simplify timeout handling
* backend/fujitsu-scsi.h: increase default timeoutes
2006-05-15 Stéphane Voltz <stefdev@modulonet.fr>
2006-05-15 St<EFBFBD>hane Voltz <stefdev@modulonet.fr>
* backend/genesys_devices.c backend/genesys_gl646.c: tuned HP 2300
geometry description and added a safeguard against failed origin
@ -118,7 +134,7 @@
* backend/genesys_devices.c: Increase length of acceleration
slopes for Canon LiDE 35/40/50/60
2006-04-21 Stéphane Voltz <stefdev@modulonet.fr>
2006-04-21 St<EFBFBD>hane Voltz <stefdev@modulonet.fr>
* backend/genesys.c: add workraound with issue related
to asic reset and data scan amount
@ -254,7 +270,7 @@
* doc/descriptions/unsupported.desc: Added Microtek ScanMaker 4850
II and Plustek OpticPro ST 64+.
2006-03-12 Stéphane Voltz <stefdev@modulonet.fr>
2006-03-12 St<EFBFBD>hane Voltz <stefdev@modulonet.fr>
* backend/genesys_gl646.c: removed now unneeded #ifdef in
gl646_send_gamma_table.

Wyświetl plik

@ -7,7 +7,7 @@
* @brief The interface functions to the USB driver stuff.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -43,6 +43,8 @@
* - 0.50 - minor fix for startup reset
* removed unnecessary calls to usbio_ResetLM983x()
* 1200DPI CIS devices don't use GrayFromColor any longer
* - 0.51 - added Syscan to the vendor list
* - added SCANFLAG_Calibration handling
* .
* <hr>
* This file is part of the SANE package.
@ -90,22 +92,23 @@
typedef struct {
int id;
char *desc;
char *desc_alt;
} TabDef, *pTabDef;
/** to allow different vendors...
*/
static TabDef usbVendors[] = {
{ 0x07B3, "Plustek" },
{ 0x0400, "Mustek" }, /* this in fact is not correct */
/* but is used for the BearPaws */
{ 0x0458, "KYE/Genius" },
{ 0x03F0, "Hewlett-Packard" },
{ 0x04B8, "Epson" },
{ 0x04A9, "Canon" },
{ 0x1606, "UMAX" },
{ 0x049F, "Compaq" },
{ 0xFFFF, NULL }
{ 0x07B3, "Plustek", NULL },
{ 0x0400, "NSC", "Mustek" },
{ 0x0458, "KYE/Genius", NULL },
{ 0x03F0, "Hewlett-Packard", NULL },
{ 0x04B8, "Epson", NULL },
{ 0x04A9, "Canon", NULL },
{ 0x1606, "UMAX", NULL },
{ 0x049F, "Compaq", NULL },
{ 0x0A82, "Syscan", NULL },
{ 0xFFFF, NULL, NULL }
};
/** we use at least 8 megs for scanning... */
@ -170,7 +173,8 @@ static void usb_CheckAndCopyAdjs( Plustek_Device *dev )
/**
* assign the values to the structures used by the currently found scanner
*/
static void usb_initDev( Plustek_Device *dev, int idx, int handle, int vendor )
static void
usb_initDev( Plustek_Device *dev, int idx, int handle, int vendor )
{
char *ptr;
char tmp_str1[PATH_MAX];
@ -252,6 +256,9 @@ static void usb_initDev( Plustek_Device *dev, int idx, int handle, int vendor )
if( usbVendors[i].id == vendor ) {
dev->sane.vendor = usbVendors[i].desc;
if (dev->usbDev.Caps.workaroundFlag & _WAF_USE_ALT_DESC )
if (usbVendors[i].desc_alt )
dev->sane.vendor = usbVendors[i].desc_alt;
DBG( _DBG_INFO, "Vendor adjusted to: >%s<\n", dev->sane.vendor );
break;
}
@ -285,15 +292,16 @@ static void usb_initDev( Plustek_Device *dev, int idx, int handle, int vendor )
}
if( NULL == ptr ) {
sprintf( tmp_str2, "/tmp/%s-%s.cal",
sprintf( tmp_str2, "/tmp/%s-%s",
dev->sane.vendor, tmp_str1 );
} else {
sprintf( tmp_str2, "%s/.sane/%s-%s.cal",
sprintf( tmp_str2, "%s/.sane/%s-%s",
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 );
DBG( _DBG_INFO, "Calibration file-names set to:\n" );
DBG( _DBG_INFO, ">%s-coarse.cal<\n", dev->calFile );
DBG( _DBG_INFO, ">%s-fine.cal<\n", dev->calFile );
/* initialize the ASIC registers */
usb_SetScanParameters( dev, &sParam );
@ -860,57 +868,67 @@ static int usbDev_setMap( Plustek_Device *dev, SANE_Word *map,
/**
*/
static int usbDev_setScanEnv( Plustek_Device *dev, ScanInfo *si )
static int
usbDev_setScanEnv( Plustek_Device *dev, ScanInfo *si )
{
ScanDef *scan = &dev->scanning;
DCapsDef *caps = &dev->usbDev.Caps;
DBG( _DBG_INFO, "usbDev_setScanEnv()\n" );
/* clear all the stuff */
memset( &dev->scanning, 0, sizeof(ScanDef));
memset( scan, 0, sizeof(ScanDef));
if((si->ImgDef.dwFlag & SCANDEF_Adf) &&
(si->ImgDef.dwFlag & SCANDEF_ContinuousScan)) {
dev->scanning.sParam.dMCLK = dMCLK_ADF;
scan->sParam.dMCLK = dMCLK_ADF;
}
/* Save necessary informations */
dev->scanning.fGrayFromColor = 0;
scan->fGrayFromColor = 0;
if( si->ImgDef.wDataType == COLOR_256GRAY ) {
/* for some devices and settings, we tweak the physical settings
* how to get the image - but not in calibration mode
*/
if((si->ImgDef.dwFlag & SCANFLAG_Calibration) == 0) {
if( !(si->ImgDef.dwFlag & SCANDEF_Adf) && !usb_IsCISDevice(dev) &&
(dev->usbDev.Caps.OpticDpi.x == 1200 && si->ImgDef.xyDpi.x <= 300)) {
dev->scanning.fGrayFromColor = 2;
si->ImgDef.wDataType = COLOR_TRUE24;
DBG( _DBG_INFO, "* Gray from color set!\n" );
}
if( si->ImgDef.wDataType == COLOR_256GRAY ) {
if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) {
DBG( _DBG_INFO, "* Gray(8-bit) from color set!\n" );
dev->scanning.fGrayFromColor = 2;
si->ImgDef.wDataType = COLOR_TRUE24;
}
if( !(si->ImgDef.dwFlag & SCANDEF_Adf) && !usb_IsCISDevice(dev) &&
(caps->OpticDpi.x == 1200 && si->ImgDef.xyDpi.x <= 300)) {
scan->fGrayFromColor = 2;
si->ImgDef.wDataType = COLOR_TRUE24;
DBG( _DBG_INFO, "* Gray from color set!\n" );
}
} else if ( si->ImgDef.wDataType == COLOR_GRAY16 ) {
if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) {
DBG( _DBG_INFO, "* Gray(16-bit) from color set!\n" );
dev->scanning.fGrayFromColor = 2;
si->ImgDef.wDataType = COLOR_TRUE48;
}
} else if ( si->ImgDef.wDataType == COLOR_BW ) {
if( caps->workaroundFlag & _WAF_BIN_FROM_COLOR ) {
DBG( _DBG_INFO, "* Binary from color set!\n" );
dev->scanning.fGrayFromColor = 10;
si->ImgDef.wDataType = COLOR_TRUE24;
if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) {
DBG( _DBG_INFO, "* Gray(8-bit) from color set!\n" );
scan->fGrayFromColor = 2;
si->ImgDef.wDataType = COLOR_TRUE24;
}
} else if ( si->ImgDef.wDataType == COLOR_GRAY16 ) {
if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) {
DBG( _DBG_INFO, "* Gray(16-bit) from color set!\n" );
scan->fGrayFromColor = 2;
si->ImgDef.wDataType = COLOR_TRUE48;
}
} else if ( si->ImgDef.wDataType == COLOR_BW ) {
if( caps->workaroundFlag & _WAF_BIN_FROM_COLOR ) {
DBG( _DBG_INFO, "* Binary from color set!\n" );
scan->fGrayFromColor = 10;
si->ImgDef.wDataType = COLOR_TRUE24;
}
}
}
usb_SaveImageInfo( dev, &si->ImgDef );
usb_GetImageInfo ( dev, &si->ImgDef, &dev->scanning.sParam.Size );
/* Flags */
dev->scanning.dwFlag = si->ImgDef.dwFlag &
(SCANFLAG_bgr | SCANFLAG_BottomUp |
usb_SaveImageInfo( dev, &si->ImgDef );
usb_GetImageInfo ( dev, &si->ImgDef, &scan->sParam.Size );
/* mask the flags */
scan->dwFlag = si->ImgDef.dwFlag &
(SCANFLAG_bgr | SCANFLAG_BottomUp | SCANFLAG_Calibration |
SCANFLAG_DWORDBoundary | SCANFLAG_RightAlign |
SCANFLAG_StillModule | SCANDEF_Adf | SCANDEF_ContinuousScan);
@ -918,27 +936,27 @@ static int usbDev_setScanEnv( Plustek_Device *dev, ScanInfo *si )
DBG( _DBG_INFO, "* Preview Mode set!\n" );
} else {
DBG( _DBG_INFO, "* Preview Mode NOT set!\n" );
dev->scanning.dwFlag |= SCANDEF_QualityScan;
scan->dwFlag |= SCANDEF_QualityScan;
}
dev->scanning.sParam.brightness = si->siBrightness;
dev->scanning.sParam.contrast = si->siContrast;
scan->sParam.brightness = si->siBrightness;
scan->sParam.contrast = si->siContrast;
if( dev->scanning.sParam.bBitDepth <= 8 )
dev->scanning.dwFlag &= ~SCANFLAG_RightAlign;
if( scan->sParam.bBitDepth <= 8 )
scan->dwFlag &= ~SCANFLAG_RightAlign;
if( dev->scanning.dwFlag & SCANFLAG_DWORDBoundary ) {
if( dev->scanning.fGrayFromColor && dev->scanning.fGrayFromColor < 10)
dev->scanning.dwBytesLine = (dev->scanning.sParam.Size.dwBytes / 3 + 3) & 0xfffffffcUL;
if( scan->dwFlag & SCANFLAG_DWORDBoundary ) {
if( scan->fGrayFromColor && scan->fGrayFromColor < 10)
scan->dwBytesLine = (scan->sParam.Size.dwBytes / 3 + 3) & 0xfffffffcUL;
else
dev->scanning.dwBytesLine = (dev->scanning.sParam.Size.dwBytes + 3UL) & 0xfffffffcUL;
scan->dwBytesLine = (scan->sParam.Size.dwBytes + 3UL) & 0xfffffffcUL;
} else {
if( dev->scanning.fGrayFromColor && dev->scanning.fGrayFromColor < 10)
dev->scanning.dwBytesLine = dev->scanning.sParam.Size.dwBytes / 3;
if( scan->fGrayFromColor && scan->fGrayFromColor < 10)
scan->dwBytesLine = scan->sParam.Size.dwBytes / 3;
else
dev->scanning.dwBytesLine = dev->scanning.sParam.Size.dwBytes;
scan->dwBytesLine = scan->sParam.Size.dwBytes;
}
/* on CIS based devices we have to reconfigure the illumination
@ -946,72 +964,73 @@ static int usbDev_setScanEnv( Plustek_Device *dev, ScanInfo *si )
*/
usb_AdjustCISLampSettings( dev, SANE_TRUE );
if( dev->scanning.dwFlag & SCANFLAG_BottomUp)
dev->scanning.lBufAdjust = -(long)dev->scanning.dwBytesLine;
if( scan->dwFlag & SCANFLAG_BottomUp)
scan->lBufAdjust = -(long)scan->dwBytesLine;
else
dev->scanning.lBufAdjust = dev->scanning.dwBytesLine;
scan->lBufAdjust = scan->dwBytesLine;
/* LM9831 has a BUG in 16-bit mode,
* so we generate pseudo 16-bit data from 8-bit
*/
if( dev->scanning.sParam.bBitDepth > 8 ) {
if( scan->sParam.bBitDepth > 8 ) {
if( _LM9831 == dev->usbDev.HwSetting.chip ) {
dev->scanning.sParam.bBitDepth = 8;
dev->scanning.dwFlag |= SCANFLAG_Pseudo48;
dev->scanning.sParam.Size.dwBytes >>= 1;
scan->sParam.bBitDepth = 8;
scan->dwFlag |= SCANFLAG_Pseudo48;
scan->sParam.Size.dwBytes >>= 1;
}
}
/* Source selection */
if( dev->scanning.sParam.bSource == SOURCE_Reflection ) {
if( scan->sParam.bSource == SOURCE_Reflection ) {
dev->usbDev.pSource = &dev->usbDev.Caps.Normal;
dev->scanning.sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
dev->usbDev.pSource = &caps->Normal;
scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
(u_long)dev->usbDev.Normal.lLeft;
dev->scanning.sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
(u_long)dev->usbDev.Normal.lUp;
} else if( dev->scanning.sParam.bSource == SOURCE_Transparency ) {
} else if( scan->sParam.bSource == SOURCE_Transparency ) {
dev->usbDev.pSource = &dev->usbDev.Caps.Positive;
dev->scanning.sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
dev->usbDev.pSource = &caps->Positive;
scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
(u_long)dev->usbDev.Positive.lLeft;
dev->scanning.sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
(u_long)dev->usbDev.Positive.lUp;
} else if( dev->scanning.sParam.bSource == SOURCE_Negative ) {
} else if( scan->sParam.bSource == SOURCE_Negative ) {
dev->usbDev.pSource = &dev->usbDev.Caps.Negative;
dev->scanning.sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
dev->usbDev.pSource = &caps->Negative;
scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
(u_long)dev->usbDev.Negative.lLeft;
dev->scanning.sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
(u_long)dev->usbDev.Negative.lUp;
} else {
dev->usbDev.pSource = &dev->usbDev.Caps.Adf;
dev->scanning.sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x +
(u_long)dev->usbDev.Normal.lLeft;
dev->scanning.sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y +
(u_long)dev->usbDev.Normal.lUp;
}
if( dev->scanning.sParam.bSource == SOURCE_ADF ) {
if( scan->sParam.bSource == SOURCE_ADF ) {
if( dev->scanning.dwFlag & SCANDEF_ContinuousScan )
if( scan->dwFlag & SCANDEF_ContinuousScan )
dev->usbDev.fLastScanIsAdf = SANE_TRUE;
else
dev->usbDev.fLastScanIsAdf = SANE_FALSE;
}
return 0;
return 0;
}
/**
*/
static int usbDev_stopScan( Plustek_Device *dev )
static int
usbDev_stopScan( Plustek_Device *dev )
{
DBG( _DBG_INFO, "usbDev_stopScan()\n" );
@ -1031,7 +1050,8 @@ static int usbDev_stopScan( Plustek_Device *dev )
/**
*/
static int usbDev_startScan( Plustek_Device *dev )
static int
usbDev_startScan( Plustek_Device *dev )
{
ScanDef *scan = &dev->scanning;
DBG( _DBG_INFO, "usbDev_startScan()\n" );
@ -1066,6 +1086,10 @@ static int usbDev_startScan( Plustek_Device *dev )
m_fStart = m_fFirst = SANE_TRUE;
m_fAutoPark = (scan->dwFlag&SCANFLAG_StillModule)?SANE_FALSE:SANE_TRUE;
if( usb_IsSheetFedDevice(dev))
if(usb_InCalibrationMode(dev))
m_fAutoPark = SANE_FALSE;
usb_StopLampTimer( dev );
return 0;
}
@ -1075,7 +1099,8 @@ static int usbDev_startScan( Plustek_Device *dev )
* first we perform the calibration step, and then we read the image
* line for line
*/
static int usbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf )
static int
usbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf )
{
int result;
SANE_Bool use_alt_cal = SANE_FALSE;
@ -1088,13 +1113,11 @@ static int usbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf )
/* check the current position of the sensor and move it back
* to it's home position if necessary...
*/
usb_ModuleStatus( dev );
if( !usb_IsSheetFedDevice(dev))
usb_SensorStatus( 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 ||
dev->usbDev.product==0x2220)) {
/* CIS devices need special handling... */
if( usb_IsCISDevice(dev)) {
use_alt_cal = SANE_TRUE;
} else {
@ -1116,15 +1139,17 @@ static int usbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf )
if( SANE_TRUE != result ) {
DBG( _DBG_ERROR, "calibration failed!!!\n" );
return result;
return _E_ABORT;
}
if( dev->adj.cacheCalData )
usb_SaveCalData( dev );
DBG( _DBG_INFO, "calibration done.\n" );
if( usb_InCalibrationMode(dev))
return 0;
if( !( scan->dwFlag & SCANFLAG_Scanning )) {
if( !(scan->dwFlag & SCANFLAG_Scanning)) {
usleep( 10 * 1000 );
@ -1342,7 +1367,8 @@ static int usbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf )
/** as the name says, read one line...
*/
static int usbDev_ReadLine( Plustek_Device *dev )
static int
usbDev_ReadLine( Plustek_Device *dev )
{
int wrap;
u_long cur;

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Main defines for the USB devices.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -40,6 +40,10 @@
* - 0.50 - cleanup
* - removed obsolete _WAF_BLACKFINE
* - added MODEL_CANON_LIDE25
* - 0.51 - added _WAF_MISC_IO_BUTTONS plus _BUTTON stuff
* - added _WAF_USE_ALT_DESC
* - added DEVCAPSFLAG_SheetFed
* - added dpi_thresh and lineend to motor structure
* .
* <hr>
* This file is part of the SANE package.
@ -181,9 +185,6 @@ typedef struct {
#define GAIN_Target 65535UL
#define DRAM_UsedByAsic8BitMode 216 /* in KB */
#define DRAM_UsedByAsic16BitMode 196 /*192*/ /* in KB */
/** Chip-types */
typedef enum _CHIPSET
{
@ -229,7 +230,8 @@ enum _DEVCAPSFLAG
DEVCAPSFLAG_Negative = 0x0004,
DEVCAPSFLAG_TPA = 0x0006,
DEVCAPSFLAG_Adf = 0x0008,
DEVCAPSFLAG_LargeTPA = 0x0010
DEVCAPSFLAG_LargeTPA = 0x0010,
DEVCAPSFLAG_SheetFed = 0x0020
};
/** to allow some workarounds */
@ -244,7 +246,9 @@ enum _WORKAROUNDS
_WAF_SKIP_FINE = 0x00000020, /* skip the fine calbration */
_WAF_SKIP_WHITEFINE = 0x00000040, /* skip the fine white calbration */
_WAF_BIN_FROM_COLOR = 0x00000080, /* generate binary & gray images */
_WAF_GRAY_FROM_COLOR = 0x00000100 /* from color scans */
_WAF_GRAY_FROM_COLOR = 0x00000100, /* from color scans */
_WAF_MISC_IO_BUTTONS = 0x00000200, /* special handling for buttons */
_WAF_USE_ALT_DESC = 0x00000400 /* use alternate manufacturer */
};
/** for lamps connected to the misc I/O pins*/
@ -259,14 +263,27 @@ enum _LAMPS
_MIO6 = 0x0020
};
#define _BUTTON_SHIFT 16
#define _BUTTON_MASK 0xFF0000
#define _TPA_SHIFT 8
#define _TPA_MASK 0xFF00
enum _BUTTONS
{
_NO_BUTTON = 0,
_PORT0 = ((_MIO1 | _MIO2) << _BUTTON_SHIFT),
_PORT1 = ((_MIO3 | _MIO4) << _BUTTON_SHIFT),
_PORT2 = ((_MIO5 | _MIO6) << _BUTTON_SHIFT)
};
/** for encoding a misc I/O register as TPA */
#define _TPA(register) ((u_long)(register << 16))
#define _TPA(register) ((u_long)(register << _TPA_SHIFT))
/** Mask to check for available TPA */
#define _HAS_TPA(flag) (flag & 0xFFFF0000)
#define _HAS_TPA(flag) (flag & _TPA_MASK)
/** Get the TPA misc I/O register */
#define _GET_TPALAMP(flag) (flag >> 16)
#define _GET_TPALAMP(flag) ((flag >> _TPA_SHIFT) & 0xFF)
/** motor types */
typedef enum
@ -284,6 +301,7 @@ typedef enum
MODEL_CANON_LIDE25, /**< for CanoScan LiDE25 */
MODEL_UMAX, /**< for UMAX 3400/3450 */
MODEL_UMAX1200, /**< for UMAX 5400 */
MODEL_TSCAN, /**< for Syscan Travelscan */
MODEL_LAST
} eModelDef;
@ -325,10 +343,11 @@ enum SCANFLAG
SCANFLAG_DWORDBoundary = 0x00020000,
SCANFLAG_RightAlign = 0x00040000,
SCANFLAG_StillModule = 0x00080000,
SCANFLAG_StartScan = 0x40000000,
SCANFLAG_Scanning = 0x20020000,
SCANFLAG_Pseudo48 = 0x08000000,
SCANFLAG_SampleY = 0x04000000
SCANFLAG_SampleY = 0x04000000,
SCANFLAG_Calibration = 0x10000000,
SCANFLAG_Scanning = 0x20020000,
SCANFLAG_StartScan = 0x40000000
};
typedef struct Origins
@ -347,7 +366,6 @@ typedef struct SrcAttr
short DarkShadOrgY; /**< if the device has a dark calibration strip */
XY Size; /**< Scanning width/height, in 300 DPI base. */
XY MinDpi; /**< Minimum dpi supported for scanning */
u_char bMinDataType; /**< Minimum data type supports */
} SrcAttrDef;
@ -635,14 +653,17 @@ typedef struct {
u_char pwm_duty_fast; /**< PWM duty during fast movement */
u_char mclk_fast; /**< MCLK during fast movement */
/**
* here we define some ranges for better supporting
* non-Plustek devices with it's different hardware
* we can set the MCLK and the motor PWM stuff for color
* and gray modes (8bit and 14/16bit modes)
* 0 1 2 3 4 5 6 7 8 9
* <= 75 <=100 <=150 <=200 <=300 <=400 <=600 <= 800 <=1200 <=2400DPI
*/
u_short dpi_thresh;
u_short lineend;
/**
* here we define some ranges for better supporting
* non-Plustek devices with it's different hardware
* we can set the MCLK and the motor PWM stuff for color
* and gray modes (8bit and 14/16bit modes)
* 0 1 2 3 4 5 6 7 8 9
* <= 75 <=100 <=150 <=200 <=300 <=400 <=600 <= 800 <=1200 <=2400DPI
*/
MDef motor_sets[_MAX_CLK]; /**< motor PWM settings during scan */
double color_mclk_8[_MAX_CLK]; /**< MCLK settings for color scan */
double color_mclk_16[_MAX_CLK]; /**< MCLK settings for color (16bit) scan*/

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Calibration routines for CanoScan CIS devices.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de><br>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de><br>
* Large parts Copyright (C) 2003 Christopher Montgomery <monty@xiph.org>
*
* Montys' comment:
@ -45,6 +45,8 @@
* lamp coarse calibration
* - added also speedtest
* - fixed segfault in fine calibration
* - 0.51 - added fine calibration cache
* - usb_SwitchLamp() now really switches off the sensor
*
* This file is part of the SANE package.
*
@ -97,20 +99,29 @@ static int strip_state = 0;
/** depending on the strip state, the sensor is moved to the shading position
* and the lamp ist switched on
*/
static int cano_PrepareToReadWhiteCal( Plustek_Device *dev )
static int
cano_PrepareToReadWhiteCal( Plustek_Device *dev, SANE_Bool mv2shading_pos )
{
HWDef *hw = &dev->usbDev.HwSetting;
SANE_Bool goto_shading_pos = SANE_TRUE;
HWDef *hw = &dev->usbDev.HwSetting;
switch (strip_state) {
case 0:
if(!usb_ModuleToHome( dev, SANE_TRUE )) {
DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" );
return _E_LAMP_NOT_IN_POS;
if( !usb_IsSheetFedDevice(dev)) {
if(!usb_ModuleToHome( dev, SANE_TRUE )) {
DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" );
return _E_LAMP_NOT_IN_POS;
}
} else {
goto_shading_pos = mv2shading_pos;
}
if( !usb_ModuleMove(dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" );
return _E_LAMP_NOT_IN_POS;
if( goto_shading_pos ) {
if( !usb_ModuleMove(dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" );
return _E_LAMP_NOT_IN_POS;
}
}
break;
case 2:
@ -127,12 +138,14 @@ static int cano_PrepareToReadWhiteCal( Plustek_Device *dev )
return 0;
}
/**
/** also here, depending on the strip state, the sensor will be moved to
* the shading position and the lamp will be switched off
*/
static int cano_PrepareToReadBlackCal( Plustek_Device *dev )
static int
cano_PrepareToReadBlackCal( Plustek_Device *dev )
{
if( strip_state == 0 )
if(cano_PrepareToReadWhiteCal(dev))
if(cano_PrepareToReadWhiteCal(dev, SANE_FALSE))
return SANE_FALSE;
if( strip_state != 2 ) {
@ -142,7 +155,8 @@ static int cano_PrepareToReadBlackCal( Plustek_Device *dev )
*/
if( dev->usbDev.pSource->DarkShadOrgY >= 0 ) {
usb_ModuleToHome( dev, SANE_TRUE );
if( !usb_IsSheetFedDevice(dev))
usb_ModuleToHome( dev, SANE_TRUE );
usb_ModuleMove ( dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->DarkShadOrgY );
dev->usbDev.a_bRegs[0x45] &= ~0x10;
@ -159,9 +173,10 @@ static int cano_PrepareToReadBlackCal( Plustek_Device *dev )
return 0;
}
/**
/** according to the strip-state we switch the lamp on
*/
static int cano_LampOnAfterCalibration( Plustek_Device *dev )
static int
cano_LampOnAfterCalibration( Plustek_Device *dev )
{
HWDef *hw = &dev->usbDev.HwSetting;
@ -231,10 +246,11 @@ cano_adjLampSetting( u_short *min, u_short *max, u_short *off, u_short val )
* [Monty changes]: On the CanoScan at least, the default lamp
* settings are several *hundred* percent too high and vary from
* scanner-to-scanner by 20-50%. This is only for CIS devices
* where the lamp_off parameter is adjustable; I'd make it more general,
* where the lamp_off parameter is adjustable; I'd make it more general,
* but I only have the CIS hardware to test.
*/
static int cano_AdjustLightsource( Plustek_Device *dev )
static int
cano_AdjustLightsource( Plustek_Device *dev )
{
char tmp[40];
int i;
@ -250,17 +266,16 @@ static int cano_AdjustLightsource( Plustek_Device *dev )
DBG( _DBG_INFO, "cano_AdjustLightsource()\n" );
if( !(hw->bReg_0x26 & _ONE_CH_COLOR)) {
if( !usb_IsCISDevice(dev)) {
DBG( _DBG_INFO, "- function skipped, CCD device!\n" );
if( !usb_Wait4Warmup( dev )) {
DBG( _DBG_ERROR, "cano_AdjustLightsource() - CANCEL detected\n" );
return SANE_FALSE;
}
return SANE_TRUE;
/* HEINER: we might have to tweak the PWM for the lamps */
return SANE_TRUE;
}
/* define the strip to scan for coarse calibration; done at 300dpi */
/* define the strip to scan for coarse calibration
* done at optical resolution.
*/
m_ScanParam.Size.dwLines = 1;
m_ScanParam.Size.dwPixels = scaps->Normal.Size.x *
scaps->OpticDpi.x / 300UL;
@ -341,7 +356,8 @@ static int cano_AdjustLightsource( Plustek_Device *dev )
for (dwLoop2 = dwDiv, dwR = dwG = dwB = 0; dwLoop2; dwLoop2--, dw++) {
if( m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
dwR += ((u_short*)scanbuf)[dw];
dwG += ((u_short*)scanbuf)
[dw+m_ScanParam.Size.dwPhyPixels+1];
@ -410,7 +426,7 @@ static int cano_AdjustLightsource( Plustek_Device *dev )
if((res_r == 10) && (res_g == 10) && (res_b == 10))
break;
/* we raise the gain for channel, that have been limited */
/* we raise the gain for channels, that have been limited */
#ifdef _TWEAK_GAIN
if( res_r == 10 ) {
if( dev->usbDev.a_bRegs[0x3b] < 0xf)
@ -436,7 +452,7 @@ static int cano_AdjustLightsource( Plustek_Device *dev )
DBG(_DBG_INFO, "* 10 times limit reached, still too dark!!!\n");
break;
}
usb_AdjustLamps(dev);
usb_AdjustLamps(dev, SANE_TRUE);
}
DBG( _DBG_INFO, "* red_lamp_on = %u\n", hw->red_lamp_on );
@ -486,7 +502,8 @@ cano_adjGainSetting( u_char *min, u_char *max, u_char *gain,u_long val )
*
* adjLightsource, above, steals most of this function's thunder.
*/
static SANE_Bool cano_AdjustGain( Plustek_Device *dev )
static SANE_Bool
cano_AdjustGain( Plustek_Device *dev )
{
char tmp[40];
int i = 0, adj = 1;
@ -524,10 +541,8 @@ static SANE_Bool cano_AdjustGain( Plustek_Device *dev )
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color)
m_ScanParam.Size.dwBytes *=3;
}
m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart *
300UL / scaps->OpticDpi.x);
@ -579,7 +594,7 @@ static SANE_Bool cano_AdjustGain( Plustek_Device *dev )
/* do some averaging... */
for (dwLoop2 = dwDiv, dwR=dwG=dwB=0; dwLoop2; dwLoop2--, dw++) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
dwR += ((u_short*)scanbuf)[dw];
dwG += ((u_short*)scanbuf)
[dw+m_ScanParam.Size.dwPhyPixels+1];
@ -636,8 +651,9 @@ static SANE_Bool cano_AdjustGain( Plustek_Device *dev )
/**
*/
static int cano_GetNewOffset( Plustek_Device *dev, u_long *val, int channel,
signed char *low, signed char *now, signed char *high )
static int
cano_GetNewOffset( Plustek_Device *dev, u_long *val, int channel,
signed char *low, signed char *now, signed char *high )
{
/* if we're too black, we're likely off the low end */
if( val[channel] <= 16 ) {
@ -677,7 +693,8 @@ static int cano_GetNewOffset( Plustek_Device *dev, u_long *val, int channel,
Plustek's example code disagrees with NatSemi's docs; going by the
docs works better, I will assume the docs are correct. --Monty */
static int cano_AdjustOffset( Plustek_Device *dev )
static int
cano_AdjustOffset( Plustek_Device *dev )
{
char tmp[40];
int i, adj;
@ -709,17 +726,15 @@ static int cano_AdjustOffset( Plustek_Device *dev )
m_ScanParam.Size.dwLines = 1;
m_ScanParam.Size.dwPixels = scaps->Normal.Size.x*scaps->OpticDpi.x/300UL;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
dwPixels = m_ScanParam.Size.dwPixels;
else
dwPixels = (u_long)(hw->bOpticBlackEnd - hw->bOpticBlackStart );
dwPixels = (u_long)(hw->bOpticBlackEnd - hw->bOpticBlackStart);
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color)
m_ScanParam.Size.dwBytes *= 3;
}
m_ScanParam.Origin.x = (u_short)((u_long)hw->bOpticBlackStart * 300UL /
dev->usbDev.Caps.OpticDpi.x);
@ -759,7 +774,7 @@ static int cano_AdjustOffset( Plustek_Device *dev )
for (dw = 0; dw < dwPixels; dw++) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
r = ((u_short*)scanbuf)[dw];
g = ((u_short*)scanbuf)[dw+m_ScanParam.Size.dwPhyPixels+1];
@ -841,15 +856,13 @@ static int cano_AdjustOffset( Plustek_Device *dev )
/** usb_AdjustDarkShading
* fine calibration part 1
*
*/
static SANE_Bool cano_AdjustDarkShading( Plustek_Device *dev )
static SANE_Bool
cano_AdjustDarkShading( Plustek_Device *dev, u_short cal_dpi )
{
char tmp[40];
ScanParam *param = &dev->scanning.sParam;
ScanDef *scan = &dev->scanning;
DCapsDef *scaps = &dev->usbDev.Caps;
HWDef *hw = &dev->usbDev.HwSetting;
u_char *scanbuf = scan->pScanBuffer;
u_short *bufp;
unsigned int i, j;
@ -860,27 +873,8 @@ static SANE_Bool cano_AdjustDarkShading( Plustek_Device *dev )
if( usb_IsEscPressed())
return SANE_FALSE;
m_ScanParam = scan->sParam;
#if 0
if( m_ScanParam.PhyDpi.x > 75)
m_ScanParam.Size.dwLines = 64;
else
#endif
m_ScanParam.Size.dwLines = 32;
m_ScanParam.Origin.y = 0;
m_ScanParam.bBitDepth = 16;
m_ScanParam.UserDpi.y = scaps->OpticDpi.y;
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
m_ScanParam.Size.dwBytes *= 3;
}
usb_PrepareFineCal( dev, &m_ScanParam, cal_dpi );
m_ScanParam.bCalibration = PARAM_DarkShading;
m_ScanParam.dMCLK = dMCLK;
sprintf( tmp, "fine-dark.raw" );
dumpPicInit( &m_ScanParam, tmp );
@ -903,7 +897,7 @@ static SANE_Bool cano_AdjustDarkShading( Plustek_Device *dev )
if( scan->sParam.bDataType == SCANDATATYPE_Color ) {
stepW = m_ScanParam.Size.dwPhyPixels;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
step = m_ScanParam.Size.dwPhyPixels + 1;
else
step = (m_ScanParam.Size.dwPhyPixels*3) + 1;
@ -913,14 +907,14 @@ static SANE_Bool cano_AdjustDarkShading( Plustek_Device *dev )
red = 0;
green = 0;
blue = 0;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
bufp = ((u_short *)scanbuf)+i;
else
bufp = ((u_short *)scanbuf)+(i*3);
for( j=0; j<m_ScanParam.Size.dwPhyLines; j++ ) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
red += *bufp; bufp+=step;
green += *bufp; bufp+=step;
blue += *bufp; bufp+=step;
@ -991,13 +985,12 @@ static SANE_Bool cano_AdjustDarkShading( Plustek_Device *dev )
* fine calibration part 2 - read the white calibration area and calculate
* the gain coefficient for each pixel
*/
static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
static SANE_Bool
cano_AdjustWhiteShading( Plustek_Device *dev, u_short cal_dpi )
{
char tmp[40];
ScanParam *param = &dev->scanning.sParam;
ScanDef *scan = &dev->scanning;
DCapsDef *scaps = &dev->usbDev.Caps;
HWDef *hw = &dev->usbDev.HwSetting;
u_char *scanbuf = scan->pScanBuffer;
u_short *bufp;
unsigned int i, j;
@ -1008,27 +1001,8 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
if( usb_IsEscPressed())
return SANE_FALSE;
m_ScanParam = scan->sParam;
#if 0
if( m_ScanParam.PhyDpi.x > 75)
m_ScanParam.Size.dwLines = 64;
else
#endif
m_ScanParam.Size.dwLines = 32;
m_ScanParam.Origin.y = 0;
m_ScanParam.bBitDepth = 16;
m_ScanParam.UserDpi.y = scaps->OpticDpi.y;
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
m_ScanParam.Size.dwBytes *= 3;
}
usb_PrepareFineCal( dev, &m_ScanParam, cal_dpi );
m_ScanParam.bCalibration = PARAM_WhiteShading;
m_ScanParam.dMCLK = dMCLK;
sprintf( tmp, "fine-white.raw" );
DBG( _DBG_INFO2, "FINE WHITE Calibration Strip: %s\n", tmp );
@ -1060,7 +1034,7 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
if( scan->sParam.bDataType == SCANDATATYPE_Color ) {
stepW = m_ScanParam.Size.dwPhyPixels;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
step = m_ScanParam.Size.dwPhyPixels + 1;
else
step = (m_ScanParam.Size.dwPhyPixels*3) + 1;
@ -1070,14 +1044,14 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
red = 0;
green = 0;
blue = 0;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
bufp = ((u_short *)scanbuf)+i;
else
bufp = ((u_short *)scanbuf)+(i*3);
for( j=0; j<m_ScanParam.Size.dwPhyLines; j++ ) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
red += *bufp; bufp+=step;
green += *bufp; bufp+=step;
blue += *bufp; bufp+=step;
@ -1099,8 +1073,6 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
a_wWhiteShading[i+stepW*2] = (blue > 65535 ? 65535:blue );
}
if(usb_HostSwap())
usb_Swap(a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2 * 3 );
} else {
step = m_ScanParam.Size.dwPhyPixels + 1;
@ -1117,8 +1089,6 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
a_wWhiteShading[i]= (gray > 65535 ? 65535:gray);
}
if(usb_HostSwap())
usb_Swap(a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2 );
memcpy( a_wWhiteShading + m_ScanParam.Size.dwPhyPixels,
a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2);
@ -1126,6 +1096,11 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2);
}
if(usb_HostSwap())
usb_Swap(a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2 * 3 );
usb_SaveCalSetShading( dev, &m_ScanParam );
usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels,
scan->sParam.bDataType == SCANDATATYPE_Color?1:0);
@ -1135,8 +1110,11 @@ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev )
/** the entry function for the CIS calibration stuff.
*/
static int cano_DoCalibration( Plustek_Device *dev )
static int
cano_DoCalibration( Plustek_Device *dev )
{
u_short dpi, idx, idx_end;
SANE_Bool skip_fine;
ScanDef *scan = &dev->scanning;
HWDef *hw = &dev->usbDev.HwSetting;
DCapsDef *scaps = &dev->usbDev.Caps;
@ -1147,18 +1125,24 @@ static int cano_DoCalibration( Plustek_Device *dev )
DBG( _DBG_INFO, "cano_DoCalibration()\n" );
if( _IS_PLUSTEKMOTOR(hw->motorModel)){
DBG( _DBG_ERROR, "altCalibration can't work with this Plustek motor control setup\n" );
DBG( _DBG_ERROR, "altCalibration can't work with this "
"Plustek motor control setup\n" );
return SANE_FALSE; /* can't cal this */
}
/* Don't allow calibration settings from the other driver to confuse our use of
* a few of its functions.
*/
scaps->workaroundFlag &= ~_WAF_SKIP_WHITEFINE;
scaps->workaroundFlag &= ~_WAF_SKIP_FINE;
scaps->workaroundFlag &= ~_WAF_BYPASS_CALIBRATION;
scaps->workaroundFlag &= ~_WAF_SKIP_WHITEFINE;
scaps->workaroundFlag &= ~_WAF_SKIP_FINE;
scaps->workaroundFlag &= ~_WAF_BYPASS_CALIBRATION;
usb_SpeedTest( dev );
if( !dev->adj.cacheCalData )
usb_SpeedTest( dev );
/* here we handle that warmup stuff for CCD devices */
if( !usb_AutoWarmup( dev ))
return SANE_FALSE;
/* Set the shading position to undefined */
strip_state = 0;
@ -1167,14 +1151,18 @@ static int cano_DoCalibration( Plustek_Device *dev )
usb_SetMCLK( dev, &scan->sParam );
if( !scan->skipCoarseCalib ) {
if( !usb_Wait4ScanSample( dev ))
return SANE_FALSE;
DBG( _DBG_INFO2, "###### ADJUST LAMP (COARSE)#######\n" );
if( cano_PrepareToReadWhiteCal(dev))
if( cano_PrepareToReadWhiteCal(dev, SANE_TRUE))
return SANE_FALSE;
dev->usbDev.a_bRegs[0x45] &= ~0x10;
if( !cano_AdjustLightsource(dev)) {
DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" );
return _E_INTERNAL;
return SANE_FALSE;
}
DBG( _DBG_INFO2, "###### ADJUST OFFSET (COARSE) ####\n" );
@ -1183,46 +1171,96 @@ static int cano_DoCalibration( Plustek_Device *dev )
if( !cano_AdjustOffset(dev)) {
DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" );
return _E_INTERNAL;
return SANE_FALSE;
}
DBG( _DBG_INFO2, "###### ADJUST GAIN (COARSE)#######\n" );
if(cano_PrepareToReadWhiteCal(dev))
if(cano_PrepareToReadWhiteCal(dev, SANE_FALSE))
return SANE_FALSE;
if( !cano_AdjustGain(dev)) {
DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" );
return _E_INTERNAL;
return SANE_FALSE;
}
} else {
strip_state = 1;
DBG( _DBG_INFO2, "###### COARSE calibration skipped #######\n" );
}
DBG( _DBG_INFO2, "###### ADJUST DARK (FINE) ########\n" );
if(cano_PrepareToReadBlackCal(dev))
return SANE_FALSE;
skip_fine = SANE_FALSE;
idx_end = 2;
if( dev->adj.cacheCalData || usb_IsSheetFedDevice(dev)) {
dev->usbDev.a_bRegs[0x45] |= 0x10;
if( !cano_AdjustDarkShading(dev)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return _E_INTERNAL;
skip_fine = usb_FineShadingFromFile(dev);
/* we recalibrate in any case ! */
if( usb_InCalibrationMode(dev)) {
skip_fine = SANE_FALSE;
idx_end = DIVIDER+1;
} else if( usb_IsSheetFedDevice(dev)) {
/* we only to the calibration upon request !*/
if( !skip_fine ) {
DBG( _DBG_INFO2, "SHEET-FED device, skip fine calibration!\n" );
skip_fine = SANE_TRUE;
scaps->workaroundFlag |= _WAF_BYPASS_CALIBRATION;
}
}
}
DBG( _DBG_INFO2, "###### ADJUST WHITE (FINE) #######\n" );
if(cano_PrepareToReadWhiteCal(dev))
return SANE_FALSE;
if( !skip_fine ) {
if(!usb_ModuleToHome( dev, SANE_TRUE ))
return SANE_FALSE;
for( idx = 1; idx < idx_end; idx++ ) {
if( !usb_ModuleMove(dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
return _E_INTERNAL;
}
if( !cano_AdjustWhiteShading(dev)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return _E_INTERNAL;
dpi = 0;
if( usb_InCalibrationMode(dev))
dpi = usb_get_res( scaps->OpticDpi.x, idx );
DBG( _DBG_INFO2, "###### ADJUST DARK (FINE) ########\n" );
if(cano_PrepareToReadBlackCal(dev))
return SANE_FALSE;
dev->usbDev.a_bRegs[0x45] |= 0x10;
if( !cano_AdjustDarkShading(dev, dpi)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return SANE_FALSE;
}
DBG( _DBG_INFO2, "###### ADJUST WHITE (FINE) #######\n" );
if(cano_PrepareToReadWhiteCal(dev, SANE_FALSE))
return SANE_FALSE;
if( !usb_IsSheetFedDevice(dev)) {
if(!usb_ModuleToHome( dev, SANE_TRUE ))
return SANE_FALSE;
if( !usb_ModuleMove(dev, MOVE_Forward,
(u_long)dev->usbDev.pSource->ShadingOriginY)) {
return SANE_FALSE;
}
}
if( !cano_AdjustWhiteShading(dev, dpi)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return SANE_FALSE;
}
/* force to go back */
strip_state = 0;
}
} else {
DBG( _DBG_INFO2, "###### FINE calibration skipped #######\n" );
dev->usbDev.a_bRegs[0x45] |= 0x10;
strip_state = 2;
m_ScanParam = scan->sParam;
usb_GetPhyPixels( dev, &m_ScanParam );
usb_line_statistics( "Dark", a_wDarkShading, m_ScanParam.Size.dwPhyPixels,
m_ScanParam.bDataType == SCANDATATYPE_Color?1:0);
usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels,
m_ScanParam.bDataType == SCANDATATYPE_Color?1:0);
}
/* Lamp on if it's not */
@ -1231,7 +1269,8 @@ static int cano_DoCalibration( Plustek_Device *dev )
/* home the sensor after calibration
*/
usb_ModuleToHome( dev, SANE_TRUE );
if( !usb_IsSheetFedDevice(dev))
usb_ModuleToHome( dev, SANE_TRUE );
scan->fCalibrated = SANE_TRUE;
DBG( _DBG_INFO, "cano_DoCalibration() done\n" );
@ -1241,9 +1280,9 @@ static int cano_DoCalibration( Plustek_Device *dev )
DBG( _DBG_INFO, "REG[0x3c] = %u\n", dev->usbDev.a_bRegs[0x3c] );
DBG( _DBG_INFO, "REG[0x3d] = %u\n", dev->usbDev.a_bRegs[0x3d] );
DBG( _DBG_INFO, "Static Offset:\n" );
DBG( _DBG_INFO, "REG[0x38] = %u\n", dev->usbDev.a_bRegs[0x38] );
DBG( _DBG_INFO, "REG[0x39] = %u\n", dev->usbDev.a_bRegs[0x39] );
DBG( _DBG_INFO, "REG[0x3a] = %u\n", dev->usbDev.a_bRegs[0x3a] );
DBG( _DBG_INFO, "REG[0x38] = %i\n", dev->usbDev.a_bRegs[0x38] );
DBG( _DBG_INFO, "REG[0x39] = %i\n", dev->usbDev.a_bRegs[0x39] );
DBG( _DBG_INFO, "REG[0x3a] = %i\n", dev->usbDev.a_bRegs[0x3a] );
DBG( _DBG_INFO, "-------------------------\n" );
return SANE_TRUE;

Wyświetl plik

@ -6,7 +6,7 @@
/** @file plustek-usbcalfile.c
* @brief Functions for saving/restoring calibration settings
*
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.46 - first version
@ -14,6 +14,8 @@
* - 0.48 - no changes
* - 0.49 - a_bRegs is now part of the device structure
* - 0.50 - cleanup
* - 0.51 - added functions for saving, reading and restoring
* fine calibration data
* .
* <hr>
* This file is part of the SANE package.
@ -55,7 +57,7 @@
* If you do not wish that, delete this exception notice.
* <hr>
*/
typedef struct {
u_long red_light_on;
u_long red_light_off;
@ -65,10 +67,10 @@ typedef struct {
u_long blue_light_off;
u_long green_pwm_duty;
} LightCtrl, *pLightCtrl;
} LightCtrl;
typedef struct {
u_short version;
u_short version;
u_short red_gain;
u_short green_gain;
@ -80,9 +82,14 @@ typedef struct {
LightCtrl light;
} CalData, *pCalData;
} CalData;
#define _PT_CF_VERSION 0x0001
/* our shading buffers */
static u_short a_wWhiteShading[_SHADING_BUF] = {0};
static u_short a_wDarkShading[_SHADING_BUF] = {0};
/* the version the the calibration files */
#define _PT_CF_VERSION 0x0002
/** function to read a text file and returns the string which starts which
* 'id' string.
@ -93,7 +100,8 @@ typedef struct {
* @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 )
static SANE_Bool
usb_ReadSpecLine( FILE *fp, char *id, char* res )
{
char tmp[1024];
char *ptr;
@ -107,12 +115,13 @@ static SANE_Bool usb_ReadSpecLine( FILE *fp, char *id, char* res )
/* roam through the file and examine each line... */
while( !feof( fp )) {
memset( tmp, 0, sizeof(tmp));
if( NULL != fgets( tmp, 1024, fp )) {
if( 0 == strncmp( tmp, id, strlen(id))) {
ptr = &tmp[strlen(id)];
if( '\0' == *ptr )
if( '\0' == *ptr )
break;
strcpy( res, ptr );
@ -121,23 +130,28 @@ static SANE_Bool usb_ReadSpecLine( FILE *fp, char *id, char* res )
}
}
}
return SANE_FALSE;
}
/**
/** function to read data from a file and excluding certain stuff like
* the version lines
* @param fp - file pointer of file to read
* @param except - what to exclude
* @return Pointer to the allocated memory for the data, NULL on any error.
*/
static char *usb_ReadOtherLines( FILE *fp, char *except )
static char*
usb_ReadOtherLines( FILE *fp, char *except )
{
char tmp[1024];
char *ptr, *ptr_base;
int ignore;
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;
@ -148,34 +162,141 @@ static char *usb_ReadOtherLines( FILE *fp, char *except )
ptr = (char*)malloc(len);
if( NULL == ptr )
return NULL;
ptr_base = ptr;
ptr_base = ptr;
*ptr = '\0';
ignore = 0;
/* roam through the file and examine each line... */
while( !feof( fp )) {
if( NULL != fgets( tmp, 1024, fp )) {
if( 0 == strncmp( tmp, "version=", 8 ))
/* we ignore the version line... */
if( 0 == strncmp( tmp, "version=", 8 ))
continue;
if( 0 != strncmp( tmp, except, strlen(except))) {
if( !ignore ) {
if(0 != strncmp(tmp, except, strlen(except))) {
if( strlen( tmp ) > 0 ) {
strcpy( ptr, tmp );
ptr += strlen(tmp);
*ptr = '\0';
if( strlen( tmp ) > 0 ) {
strcpy( ptr, tmp );
ptr += strlen(tmp);
*ptr = '\0';
}
} else {
ignore = 1;
}
}
/* newline in tmp string resets ignore flag */
if( strrchr(tmp, '\n')) {
ignore = 0;
}
}
}
return ptr_base;
return ptr_base;
}
/**
*/
static void usb_RestoreCalData( Plustek_Device *dev, CalData *cal )
static SANE_Bool
usb_ReadSamples( FILE *fp, char *which, u_long *dim, u_short *buffer )
{
char *p, *next, *rb;
char tmp[1024+30];
int ignore, diml, c;
u_long val;
/* rewind file pointer */
if( 0 != fseek( fp, 0L, SEEK_SET))
return SANE_FALSE;
ignore = 0;
diml = 0;
c = 0;
rb = tmp;
*dim = 0;
/* roam through the file and examine each line... */
while( !feof( fp )) {
if( NULL != fgets( rb, 1024, fp )) {
/* we ignore the version line... */
if( 0 == strncmp( tmp, "version=", 8 ))
continue;
p = tmp;
if( !ignore && diml == 0) {
if(0 == strncmp(tmp, which, strlen(which))) {
/* get dimension */
diml = strtol(&tmp[strlen(which)], NULL, 10);
p = strchr( &tmp[strlen(which)], ':' );
p++;
} else {
ignore = 1;
}
}
/* parse the values... */
if( !ignore ) {
rb = tmp;
while( *p ) {
val = strtoul( p, &next, 10 );
/* check for error condition */
if( val == 0 ) {
if( p == next ) {
if( c+1 == diml ) {
*dim = diml;
return SANE_TRUE;
}
break;
}
}
buffer[c] = (u_short)val;
/* more values? */
if( *next == ',') {
p = next+1;
c++;
} else {
p = next;
}
/* reached the end? */
if( *next == '\0' ) {
/* we probably have only parsed a part of a value
* so we copy that back to the input buffer and
* parse it the next time...
*/
if( c < diml ) {
sprintf( tmp, "%u", buffer[c] );
rb = &tmp[strlen(tmp)];
}
}
}
}
/* newline in tmp string resets ignore flag */
if( strrchr(tmp, '\n')) {
ignore = 0;
}
}
}
return SANE_FALSE;
}
/**
*/
static void
usb_RestoreCalData( Plustek_Device *dev, CalData *cal )
{
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
regs[0x3b] = (u_char)cal->red_gain;
@ -202,11 +323,19 @@ static void usb_RestoreCalData( Plustek_Device *dev, CalData *cal )
regs[0x35] = _LOBYTE((u_short)cal->light.blue_light_on);
regs[0x36] = _HIBYTE((u_short)cal->light.blue_light_off);
regs[0x37] = _LOBYTE((u_short)cal->light.blue_light_off);
hw->red_lamp_on = (u_short)cal->light.red_light_on;
hw->red_lamp_off = (u_short)cal->light.red_light_off;
hw->green_lamp_on = (u_short)cal->light.green_light_on;
hw->green_lamp_off = (u_short)cal->light.green_light_off;
hw->blue_lamp_on = (u_short)cal->light.blue_light_on;
hw->blue_lamp_off = (u_short)cal->light.blue_light_off;
}
/**
*/
static void usb_CreatePrefix( Plustek_Device *dev, char *pfx )
static void
usb_CreatePrefix( Plustek_Device *dev, char *pfx, SANE_Bool add_bitdepth )
{
char bd[5];
ScanDef *scanning = &dev->scanning;
@ -226,12 +355,14 @@ static void usb_CreatePrefix( Plustek_Device *dev, char *pfx )
else
strcat( pfx, "gray" );
strcat( pfx, bd );
if( add_bitdepth )
strcat( pfx, bd );
}
/** function to read and set the calibration data from external file
*/
static SANE_Bool usb_ReadAndSetCalData( Plustek_Device *dev )
static SANE_Bool
usb_ReadAndSetCalData( Plustek_Device *dev )
{
char pfx[20];
char tmp[1024];
@ -243,17 +374,23 @@ static SANE_Bool usb_ReadAndSetCalData( Plustek_Device *dev )
DBG( _DBG_INFO, "usb_ReadAndSetCalData()\n" );
if( usb_InCalibrationMode(dev)) {
DBG( _DBG_INFO, "- we are in calibration mode!\n" );
return SANE_FALSE;
}
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 );
sprintf( tmp, "%s-coarse.cal", dev->calFile );
DBG( _DBG_INFO, "- Reading coarse calibration data from file\n");
DBG( _DBG_INFO, " %s\n", tmp );
fp = fopen( dev->calFile, "r" );
fp = fopen( tmp, "r" );
if( NULL == fp ) {
DBG( _DBG_ERROR, "File %s not found\n", dev->calFile );
DBG( _DBG_ERROR, "File %s not found\n", tmp );
return SANE_FALSE;
}
@ -277,7 +414,7 @@ static SANE_Bool usb_ReadAndSetCalData( Plustek_Device *dev )
return SANE_FALSE;
}
usb_CreatePrefix( dev, pfx );
usb_CreatePrefix( dev, pfx, SANE_TRUE );
ret = SANE_FALSE;
if( usb_ReadSpecLine( fp, pfx, tmp )) {
@ -307,12 +444,13 @@ static SANE_Bool usb_ReadAndSetCalData( Plustek_Device *dev )
/**
*/
static void usb_PrepCalData( Plustek_Device *dev, CalData *cal )
static void
usb_PrepCalData( Plustek_Device *dev, CalData *cal )
{
u_char *regs = dev->usbDev.a_bRegs;
memset( cal, 0, sizeof(CalData));
cal->version = _PT_CF_VERSION;
cal->version = _PT_CF_VERSION;
cal->red_gain = (u_short)regs[0x3b];
cal->green_gain = (u_short)regs[0x3c];
@ -333,9 +471,11 @@ static void usb_PrepCalData( Plustek_Device *dev, CalData *cal )
/** function to save/update the calibration data
*/
static void usb_SaveCalData( Plustek_Device *dev )
static void
usb_SaveCalData( Plustek_Device *dev )
{
char pfx[20];
char fn[1024];
char tmp[1024];
char set_tmp[1024];
char *other_tmp;
@ -356,11 +496,14 @@ static void usb_SaveCalData( Plustek_Device *dev )
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 );
sprintf( fn, "%s-coarse.cal", dev->calFile );
DBG( _DBG_INFO, "- Saving coarse calibration data to file\n" );
DBG( _DBG_INFO, " %s\n", fn );
usb_PrepCalData ( dev, &cal );
usb_CreatePrefix( dev, pfx );
usb_CreatePrefix( dev, pfx, SANE_TRUE );
DBG( _DBG_INFO2, "- PFX: >%s<\n", pfx );
sprintf( set_tmp, "%s%u,%u,%u,%u,%u,%u,"
"%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", pfx,
@ -374,7 +517,7 @@ static void usb_SaveCalData( Plustek_Device *dev )
/* read complete old file if compatible... */
other_tmp = NULL;
fp = fopen( dev->calFile, "r+" );
fp = fopen( fn, "r+" );
if( NULL != fp ) {
if( usb_ReadSpecLine( fp, "version=", tmp )) {
@ -383,6 +526,7 @@ static void usb_SaveCalData( Plustek_Device *dev )
if( 1 == sscanf( tmp, "0x%04hx", &version )) {
if( version == cal.version ) {
DBG( _DBG_INFO, "- Versions do match\n" );
/* read the rest... */
@ -398,9 +542,9 @@ static void usb_SaveCalData( Plustek_Device *dev )
}
fclose( fp );
}
fp = fopen( dev->calFile, "w+" );
fp = fopen( fn, "w+" );
if( NULL == fp ) {
DBG( _DBG_ERROR, "- Cannot create file %s\n", dev->calFile );
DBG( _DBG_ERROR, "- Cannot create file %s\n", fn );
DBG( _DBG_ERROR, "- -> %s\n", strerror(errno));
if( other_tmp )
free( other_tmp );
@ -420,4 +564,275 @@ static void usb_SaveCalData( Plustek_Device *dev )
DBG( _DBG_INFO, "usb_SaveCalData() done.\n" );
}
/**
*/
static void
usb_SaveFineCalData( Plustek_Device *dev, int dpi,
u_short *dark, u_short *white, u_long vals )
{
char pfx[30];
char fn[1024];
char tmp[1024];
char *other_tmp;
u_short version;
u_long i;
FILE *fp;
if( NULL == dev->calFile ) {
DBG( _DBG_ERROR, "- No calibration filename set!\n" );
return;
}
sprintf( fn, "%s-fine.cal", dev->calFile );
DBG( _DBG_INFO, "- Saving fine calibration data to file\n" );
DBG( _DBG_INFO, " %s\n", fn );
usb_CreatePrefix( dev, pfx, SANE_FALSE );
sprintf( tmp, "%s:%u", pfx, dpi );
strcpy( pfx, tmp );
DBG( _DBG_INFO2, "- PFX: >%s<\n", pfx );
/* read complete old file if compatible... */
other_tmp = NULL;
fp = fopen( fn, "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 == _PT_CF_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( fn, "w+" );
if( NULL == fp ) {
DBG( _DBG_ERROR, "- Cannot create file %s\n", fn );
return;
}
/* rewrite the file again... */
fprintf( fp, "version=0x%04X\n", _PT_CF_VERSION );
if( other_tmp ) {
fprintf( fp, "%s", other_tmp );
free( other_tmp );
}
fprintf( fp, "%s:dark:dim=%lu:", pfx, vals );
for( i=0; i<vals-1; i++ )
fprintf( fp, "%u,", dark[i]);
fprintf( fp, "%u\n", dark[vals-1]);
fprintf( fp, "%s:white:dim=%lu:", pfx, vals );
for( i=0; i<vals-1; i++ )
fprintf( fp, "%u,", white[i]);
fprintf( fp, "%u\n", white[vals-1]);
fclose( fp );
}
/** function to read and set the calibration data from external file
*/
static SANE_Bool
usb_ReadFineCalData( Plustek_Device *dev, int dpi,
u_long *dim_d, u_short *dark,
u_long *dim_w, u_short *white )
{
char pfx[30];
char tmp[1024];
u_short version;
FILE *fp;
DBG( _DBG_INFO, "usb_ReadFineCalData()\n" );
if( usb_InCalibrationMode(dev)) {
DBG( _DBG_INFO, "- we are in calibration mode!\n" );
return SANE_FALSE;
}
if( NULL == dev->calFile ) {
DBG( _DBG_ERROR, "- No calibration filename set!\n" );
return SANE_FALSE;
}
sprintf( tmp, "%s-fine.cal", dev->calFile );
DBG( _DBG_INFO, "- Reading fine calibration data from file\n");
DBG( _DBG_INFO, " %s\n", tmp );
*dim_d = *dim_w = 0;
fp = fopen( tmp, "r" );
if( NULL == fp ) {
DBG( _DBG_ERROR, "File %s not found\n", tmp );
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, SANE_FALSE );
sprintf( tmp, "%s:%u:%s:dim=", pfx, dpi, "dark" );
if( !usb_ReadSamples( fp, tmp, dim_d, dark )) {
DBG( _DBG_ERROR, "Error reading dark-calibration data!\n" );
fclose( fp );
return SANE_FALSE;
}
sprintf( tmp, "%s:%u:%s:dim=", pfx, dpi, "white" );
if( !usb_ReadSamples( fp, tmp, dim_w, white )) {
DBG( _DBG_ERROR, "Error reading white-calibration data!\n" );
fclose( fp );
return SANE_FALSE;
}
fclose( fp );
return SANE_TRUE;
}
/**
*/
static void
usb_get_shading_part(u_short *buf, u_long offs, u_long src_len, int dst_len)
{
u_short *p_src, *p_dst;
int i, j;
if (src_len == 0 || dst_len == 0)
return;
p_dst = buf;
for (i=0; i<3; i++) {
p_src = buf + src_len * i + offs;
for (j=0; j<dst_len; j++) {
*(p_dst++) = *(p_src++);
}
}
}
/** function to read the fine calibration results from file
* and to set the correct part of the calibration buffers for
* storing in the device
* @param dev - the almigthy device structure
* @returns SANE_FALSE when the reading fails or SANE_TRUE on success
*/
static SANE_Bool
usb_FineShadingFromFile( Plustek_Device *dev )
{
ScanDef *scan = &dev->scanning;
ScanParam *sp = &scan->sParam;
u_short xdpi;
u_long dim_w, dim_d, offs;
xdpi = usb_SetAsicDpiX( dev, sp->UserDpi.x );
if( !usb_ReadFineCalData( dev, xdpi, &dim_d, a_wDarkShading,
&dim_w, a_wWhiteShading)) {
return SANE_FALSE;
}
/* now we need to get the correct part of the line... */
dim_d /= 3;
dim_w /= 3;
offs = ((u_long)sp->Origin.x * xdpi) / 300;
usb_GetPhyPixels( dev, sp );
DBG( _DBG_INFO2, "FINE Calibration from file:\n" );
DBG( _DBG_INFO2, "XDPI = %u\n", xdpi );
DBG( _DBG_INFO2, "Dim = %lu\n", dim_d );
DBG( _DBG_INFO2, "Pixels = %lu\n", sp->Size.dwPixels );
DBG( _DBG_INFO2, "PhyPixels = %lu\n", sp->Size.dwPhyPixels );
DBG( _DBG_INFO2, "Origin.X = %u\n", sp->Origin.x );
DBG( _DBG_INFO2, "Offset = %lu\n", offs );
usb_get_shading_part(a_wDarkShading, offs, dim_d, sp->Size.dwPhyPixels);
usb_get_shading_part(a_wWhiteShading, offs, dim_w, sp->Size.dwPhyPixels);
return SANE_TRUE;
}
/** function to save the fine calibration results and to set the correct part
* of the calibration buffers for storing in the device
* @param dev - the almigthy device structure
* @param tmp_sp - intermediate scan parameter
*/
static void
usb_SaveCalSetShading( Plustek_Device *dev, ScanParam *tmp_sp )
{
ScanParam *sp = &dev->scanning.sParam;
u_short xdpi;
u_long offs;
if( !dev->adj.cacheCalData )
return;
/* save the values */
xdpi = usb_SetAsicDpiX( dev, tmp_sp->UserDpi.x );
usb_SaveFineCalData( dev, xdpi, a_wDarkShading,
a_wWhiteShading, tmp_sp->Size.dwPixels*3 );
/* now we need to get the correct part of the line... */
xdpi = usb_SetAsicDpiX( dev, sp->UserDpi.x );
offs = ((u_long)sp->Origin.x * xdpi) / 300;
usb_GetPhyPixels( dev, sp );
DBG( _DBG_INFO2, "FINE Calibration area after saving:\n" );
DBG( _DBG_INFO2, "XDPI = %u\n", xdpi );
DBG( _DBG_INFO2, "Dim = %lu\n", tmp_sp->Size.dwPixels );
DBG( _DBG_INFO2, "Pixels = %lu\n", sp->Size.dwPixels );
DBG( _DBG_INFO2, "PhyPixels = %lu\n", sp->Size.dwPhyPixels );
DBG( _DBG_INFO2, "Origin.X = %u\n", sp->Origin.x );
DBG( _DBG_INFO2, "Offset = %lu\n", offs );
if (!usb_InCalibrationMode(dev)) {
usb_get_shading_part( a_wDarkShading, offs,
tmp_sp->Size.dwPixels, sp->Size.dwPhyPixels );
usb_get_shading_part( a_wWhiteShading, offs,
tmp_sp->Size.dwPixels, sp->Size.dwPhyPixels );
memcpy( tmp_sp, sp, sizeof(ScanParam));
tmp_sp->bBitDepth = 16;
usb_GetPhyPixels( dev, tmp_sp );
}
}
/* END PLUSTEK-USBCALFILE.C .................................................*/

Plik diff jest za duży Load Diff

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Functions to control the scanner hardware.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -46,6 +46,8 @@
* - 0.50 - added button support for Plustek/Genius devices
* - changed behaviour of usb_IsScannerReady
* - added special misc I/O setup for CIS devices (usb_ResetRegisters)
* - 0.51 - change usb_AdjustLamps() and use it now in usb_switchLamp()
* - added usb_Wait4ScanSample() and usb_InCalibrationMode()
* .
* <hr>
* This file is part of the SANE package.
@ -97,12 +99,11 @@
#define DEV_LampPositive 4
#define DEV_LampNegative 5
/* HEINER: check the tick counts 'cause 1 tick on NT is about 10ms */
/** the NatSemi 983x is a big endian chip, and the line protocol data all
* arrives big-endian. This determines if we need to swap to host-order
*/
static SANE_Bool usb_HostSwap( void )
static SANE_Bool
usb_HostSwap( void )
{
u_short pattern = 0xfeed; /* deadbeef */
unsigned char *bytewise = (unsigned char *)&pattern;
@ -118,17 +119,42 @@ static SANE_Bool usb_HostSwap( void )
/** as the name says..
*/
static void usb_Swap( u_short *pw, u_long dwBytes )
static void
usb_Swap( u_short *pw, u_long dwBytes )
{
for( dwBytes /= 2; dwBytes--; pw++ )
_SWAP(((u_char*) pw)[0], ((u_char*)pw)[1]);
}
/**
* This function is used to detect a cancel condition,
* our ESC key is the SIGUSR1 signal. It is sent by the backend when the
* cancel button has been pressed
*
* @param - none
* @return the function returns SANE_TRUE if a cancel condition has been
* detected, if not, it returns SANE_FALSE
*/
static SANE_Bool
usb_IsEscPressed( void )
{
sigset_t sigs;
sigpending( &sigs );
if( sigismember( &sigs, SIGUSR1 )) {
DBG( _DBG_INFO, "SIGUSR1 is pending --> Cancel detected\n" );
return SANE_TRUE;
}
return SANE_FALSE;
}
/** usb_GetMotorSet
* according to the model, the function returns the address of
* the corresponding entry of the Motor table
*/
static ClkMotorDef *usb_GetMotorSet( eModelDef model )
static ClkMotorDef*
usb_GetMotorSet( eModelDef model )
{
int i;
@ -146,7 +172,8 @@ static ClkMotorDef *usb_GetMotorSet( eModelDef model )
* @param fOn - SANE_TRUE means motor on, SANE_FALSE means motor off
* @return always SANE_TRUE
*/
static SANE_Bool usb_MotorOn( Plustek_Device *dev, SANE_Bool fOn )
static SANE_Bool
usb_MotorOn( Plustek_Device *dev, SANE_Bool fOn )
{
if( fOn )
dev->usbDev.a_bRegs[0x45] |= 0x10;
@ -159,14 +186,35 @@ static SANE_Bool usb_MotorOn( Plustek_Device *dev, SANE_Bool fOn )
/**
*/
static SANE_Bool usb_IsCISDevice( Plustek_Device *dev )
static SANE_Bool
usb_IsCISDevice( Plustek_Device *dev )
{
return ( dev->usbDev.HwSetting.bReg_0x26 & _ONE_CH_COLOR );
}
/**
*/
static SANE_Bool
usb_IsSheetFedDevice( Plustek_Device *dev )
{
return ( dev->usbDev.Caps.wFlags & DEVCAPSFLAG_SheetFed );
}
/**
*/
static SANE_Bool
usb_InCalibrationMode( Plustek_Device *dev )
{
if((dev->scanning.dwFlag & SCANFLAG_Calibration) == 0)
return SANE_FALSE;
return SANE_TRUE;
}
/** check if scanner is ready
*/
static SANE_Bool usb_IsScannerReady( Plustek_Device *dev )
static SANE_Bool
usb_IsScannerReady( Plustek_Device *dev )
{
u_char value;
double len;
@ -217,7 +265,8 @@ static SANE_Bool usb_IsScannerReady( Plustek_Device *dev )
/**
*/
static SANE_Bool usb_SensorAdf( int handle )
static SANE_Bool
usb_SensorAdf( int handle )
{
u_char value;
@ -228,19 +277,56 @@ static SANE_Bool usb_SensorAdf( int handle )
/**
*/
static SANE_Bool usb_SensorPaper( int handle )
static SANE_Bool
usb_SensorPaper( Plustek_Device *dev )
{
u_char value;
u_char val, mask = 0x02;
usbio_ReadReg( handle, 0x02, &value );
usbio_ReadReg( dev->fd, 0x02, &val );
return (value & 0x02);
if( usb_IsSheetFedDevice(dev))
mask = 0x08;
return (val & mask);
}
/** function for sheet-fed devices, to make sure, that there's
* something to scan
*/
static SANE_Bool
usb_Wait4ScanSample( Plustek_Device *dev )
{
struct timeval start_time, t2;
/* we wait about 10s for something to scan... */
if( !usb_IsSheetFedDevice(dev))
return SANE_TRUE;
DBG( _DBG_INFO2, "Waiting for something to scan...\n" );
gettimeofday( &start_time, NULL );
do {
gettimeofday( &t2, NULL );
if( t2.tv_sec > start_time.tv_sec + 10 ) {
DBG( _DBG_ERROR, "Nothing to scan!!!\n" );
return SANE_FALSE;
}
if( usb_IsEscPressed())
return SANE_FALSE;
}
while( !usb_SensorPaper( dev ));
/* just a little delay, to make sure the paper is taken by the scanner */
usleep(100* 1000);
DBG( _DBG_INFO2, "... okay, scanning now!\n" );
return SANE_TRUE;
}
/** function to move the sensor and to speed it up to a certain speed until
* the position is reached
*/
static SANE_Bool usb_WaitPos( Plustek_Device *dev, u_long to, SANE_Bool stay )
static SANE_Bool
usb_WaitPos( Plustek_Device *dev, u_long to, SANE_Bool stay )
{
SANE_Bool retval;
u_char value, mclk_div, mch;
@ -344,17 +430,14 @@ static SANE_Bool usb_WaitPos( Plustek_Device *dev, u_long to, SANE_Bool stay )
return retval;
}
/**
* Home sensor always on when backward move.
* dwStep is steps to move and based on 300 dpi, but
* if the action is MOVE_Both, it becomes the times
* to repeatly move the module around the scanner and
* 0 means forever.
/** function to move the sensor or if sheet-fed device, to move the paper.
* In moving backward-mode, the home sensor is always turned on.
* @param action - what to do
* @param steps - steps to move, based on 300dpi, 0 means move forever
*/
static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
u_char bAction, u_long dwStep )
static SANE_Bool
usb_ModuleMove( Plustek_Device *dev, u_char action, u_long dwStep )
{
SANE_Status res;
SANE_Bool retval;
u_char bReg2, reg7, mclk_div;
u_short wFastFeedStepSize;
@ -363,10 +446,10 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
if( bAction != MOVE_ToPaperSensor &&
bAction != MOVE_EjectAllPapers &&
bAction != MOVE_SkipPaperSensor &&
bAction != MOVE_ToShading && !dwStep ) {
if( action != MOVE_ToPaperSensor &&
action != MOVE_EjectAllPapers &&
action != MOVE_SkipPaperSensor &&
action != MOVE_ToShading && !dwStep ) {
return SANE_TRUE;
}
@ -376,35 +459,51 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
return SANE_FALSE;
}
if( bAction == MOVE_EjectAllPapers ) {
if( action == MOVE_EjectAllPapers ) {
double d = hw->dMaxMoveSpeed;
hw->dMaxMoveSpeed += 0.6;
hw->dMaxMoveSpeed += 0.8; /* was 0.6 */
DBG( _DBG_INFO2, "Ejecting paper...\n" );
retval = SANE_TRUE;
do {
if( usb_SensorPaper(dev->fd) &&
!usb_ModuleMove(dev,MOVE_SkipPaperSensor, 0 )) {
if( usb_SensorPaper(dev) &&
!usb_ModuleMove(dev,MOVE_SkipPaperSensor, 0 )) {
hw->dMaxMoveSpeed = d;
return SANE_FALSE;
}
if( usb_SensorAdf(dev->fd) &&
!usb_ModuleMove(dev,MOVE_ToPaperSensor, 0 )) {
!usb_ModuleMove(dev,MOVE_ToPaperSensor, 0 )) {
hw->dMaxMoveSpeed = d;
return SANE_FALSE;
}
}
} while( usb_SensorPaper(dev->fd));
if( usb_IsEscPressed()) {
retval = SANE_FALSE;
break;
}
} while( usb_SensorPaper(dev));
if(!usb_ModuleMove( dev, MOVE_Forward, 300 * 3))
return SANE_FALSE;
/* when the paper is beyond the sensor, we move another 300 steps
* to make sure, that the scanned sheet is out of the scanner
* BUT: not at startup
*/
if (dev->initialized >= 0) {
if(!usb_ModuleMove( dev, MOVE_Forward, 300 /* *3 */)) {
hw->dMaxMoveSpeed = d;
return SANE_FALSE;
}
}
usbio_WriteReg( dev->fd, 0x07, 0);
usbio_WriteReg( dev->fd, 0x58, regs[0x58]);
usbio_ReadReg( dev->fd, 0x02, &bReg2 );
hw->dMaxMoveSpeed = d;
return SANE_TRUE;
DBG( _DBG_INFO2, "...done\n" );
return retval;
}
usbio_WriteReg( dev->fd, 0x0a, 0 );
@ -412,7 +511,7 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
/* Compute fast feed step size, use equation 3 and equation 8 */
dMaxMoveSpeed = hw->dMaxMoveSpeed;
if( bAction == MOVE_ToShading ) {
if( action == MOVE_ToShading ) {
if( hw->dMaxMoveSpeed > 0.5 )
dMaxMoveSpeed = hw->dMaxMoveSpeed - 0.5;
}
@ -476,12 +575,12 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
if( !usbio_WriteReg(dev->fd, 0x45, regs[0x45] ))
return SANE_FALSE;
if( bAction == MOVE_Forward || bAction == MOVE_ToShading )
if( action == MOVE_Forward || action == MOVE_ToShading )
reg7 = 5;
else if( bAction == MOVE_Backward )
else if( action == MOVE_Backward )
reg7 = 6;
else if( bAction == MOVE_ToPaperSensor || bAction == MOVE_EjectAllPapers ||
bAction == MOVE_SkipPaperSensor ) {
else if( action == MOVE_ToPaperSensor || action == MOVE_EjectAllPapers ||
action == MOVE_SkipPaperSensor ) {
reg7 = 1;
} else {
return SANE_TRUE;
@ -489,21 +588,21 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
retval = SANE_FALSE;
/* start the sensor... */
if( usbio_WriteReg( dev->fd, 0x07, reg7 )) {
long dwTicks;
long secs;
struct timeval start_time, t2;
res = gettimeofday( &start_time, NULL );
/* at least we move 20 seconds before timeout... */
gettimeofday( &start_time, NULL );
secs = start_time.tv_sec + 20;
/* 20000 NT-Ticks means 200s */
dwTicks = start_time.tv_sec + 200;
if( action == MOVE_ToPaperSensor ) {
if( bAction == MOVE_ToPaperSensor ) {
for(;;) {
for(;;) {
if( usb_SensorPaper( dev->fd )) {
if( usb_SensorPaper( dev )) {
usbio_WriteReg( dev->fd, 0x07, 0 );
usbio_WriteReg( dev->fd, 0x58, regs[0x58] );
usbio_ReadReg ( dev->fd, 0x02, &bReg2 );
@ -511,14 +610,14 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
}
gettimeofday(&t2, NULL);
if( t2.tv_sec > dwTicks )
if( t2.tv_sec > secs )
break;
}
} else if( bAction == MOVE_SkipPaperSensor ) {
} else if( action == MOVE_SkipPaperSensor ) {
for(;;) {
for(;;) {
if( usb_SensorPaper( dev->fd )) {
if( !usb_SensorPaper( dev )) {
usbio_WriteReg( dev->fd, 0x07, 0 );
usbio_WriteReg( dev->fd, 0x58, regs[0x58] );
usbio_ReadReg ( dev->fd, 0x02, &bReg2 );
@ -526,8 +625,8 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
}
gettimeofday(&t2, NULL);
if( t2.tv_sec > dwTicks )
break;
if( t2.tv_sec > secs )
break;
}
} else {
@ -545,7 +644,8 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
/**
*/
static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
static SANE_Bool
usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
{
u_char mclk_div;
u_char value;
@ -553,10 +653,13 @@ static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
if( usb_IsSheetFedDevice(dev)) {
return usb_ModuleMove( dev, MOVE_EjectAllPapers, 0 );
}
/* Check if merlin is ready for setting command */
usbio_WriteReg( dev->fd, 0x58, hw->bReg_0x58 );
usbio_ReadReg ( dev->fd, 2, &value );
if( value & 1 ) {
dev->usbDev.fModFirstHome = SANE_FALSE;
return SANE_TRUE;
@ -590,7 +693,7 @@ static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
regs[0x56] = clk->pwm_fast;
regs[0x57] = clk->pwm_duty_fast;
mclk_div = clk->mclk_fast;
mclk_div = clk->mclk_fast;
} else {
@ -719,7 +822,8 @@ static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
/**
*/
static SANE_Bool usb_MotorSelect( Plustek_Device *dev, SANE_Bool fADF )
static SANE_Bool
usb_MotorSelect( Plustek_Device *dev, SANE_Bool fADF )
{
DCapsDef *sCaps = &dev->usbDev.Caps;
HWDef *hw = &dev->usbDev.HwSetting;
@ -760,39 +864,61 @@ static SANE_Bool usb_MotorSelect( Plustek_Device *dev, SANE_Bool fADF )
return SANE_TRUE;
}
/** function to adjust the lamp settings of a device
/** function to adjust the lamp settings of a CIS device without tweaking
* the driver-device settings
* @param dev - our almitghty device structure
* @param on - switch the lamp on or off
*/
static SANE_Bool usb_AdjustLamps( Plustek_Device *dev )
static SANE_Bool
usb_AdjustLamps( Plustek_Device *dev, SANE_Bool on )
{
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
regs[0x2c] = _HIBYTE(hw->red_lamp_on);
regs[0x2d] = _LOBYTE(hw->red_lamp_on);
regs[0x2e] = _HIBYTE(hw->red_lamp_off);
regs[0x2f] = _LOBYTE(hw->red_lamp_off);
if( !usb_IsCISDevice(dev))
return SANE_TRUE;
regs[0x30] = _HIBYTE(hw->green_lamp_on);
regs[0x31] = _LOBYTE(hw->green_lamp_on);
regs[0x32] = _HIBYTE(hw->green_lamp_off);
regs[0x33] = _LOBYTE(hw->green_lamp_off);
DBG(_DBG_INFO2, "usb_AdjustLamps(%u)\n", on );
regs[0x34] = _HIBYTE(hw->blue_lamp_on);
regs[0x35] = _LOBYTE(hw->blue_lamp_on);
regs[0x36] = _HIBYTE(hw->blue_lamp_off);
regs[0x37] = _LOBYTE(hw->blue_lamp_off);
if( on ) {
regs[0x2c] = _HIBYTE(hw->red_lamp_on);
regs[0x2d] = _LOBYTE(hw->red_lamp_on);
regs[0x2e] = _HIBYTE(hw->red_lamp_off);
regs[0x2f] = _LOBYTE(hw->red_lamp_off);
return sanei_lm983x_write( dev->fd, 0x2c,
regs[0x30] = _HIBYTE(hw->green_lamp_on);
regs[0x31] = _LOBYTE(hw->green_lamp_on);
regs[0x32] = _HIBYTE(hw->green_lamp_off);
regs[0x33] = _LOBYTE(hw->green_lamp_off);
regs[0x34] = _HIBYTE(hw->blue_lamp_on);
regs[0x35] = _LOBYTE(hw->blue_lamp_on);
regs[0x36] = _HIBYTE(hw->blue_lamp_off);
regs[0x37] = _LOBYTE(hw->blue_lamp_off);
} else {
memset( &regs[0x2c], 0, 12 );
regs[0x2c] = 0x3f;
regs[0x2d] = 0xff;
regs[0x30] = 0x3f;
regs[0x31] = 0xff;
regs[0x34] = 0x3f;
regs[0x35] = 0xff;
}
return sanei_lm983x_write( dev->fd, 0x2c,
&regs[0x2c], 0x37-0x2c+1, SANE_TRUE );
}
/**
*/
static void usb_AdjustCISLampSettings( Plustek_Device *dev, SANE_Bool on )
static void
usb_AdjustCISLampSettings( Plustek_Device *dev, SANE_Bool on )
{
HWDef *hw = &dev->usbDev.HwSetting;
if( !(hw->bReg_0x26 & _ONE_CH_COLOR))
if( !usb_IsCISDevice(dev))
return;
DBG( _DBG_INFO2, "AdjustCISLamps(%u)\n", on );
@ -854,17 +980,18 @@ static void usb_AdjustCISLampSettings( Plustek_Device *dev, SANE_Bool on )
}
dev->usbDev.a_bRegs[0x29] = hw->bReg_0x29;
usb_AdjustLamps( dev );
usb_AdjustLamps( dev, on );
}
/** according to the flag field, we return the register and
* it's maks to turn on/off the lamp.
* it's mask to turn on/off the lamp.
* @param flag - field to check
* @param reg - pointer to a var to receive the register value
* @param msk - pointer to a var to receive the mask value
* @return Nothing
*/
static void usb_GetLampRegAndMask( u_long flag, SANE_Byte *reg, SANE_Byte *msk )
static void
usb_GetLampRegAndMask( u_long flag, SANE_Byte *reg, SANE_Byte *msk )
{
if( _MIO6 == ( _MIO6 & flag )) {
*reg = 0x5b;
@ -905,14 +1032,14 @@ static void usb_GetLampRegAndMask( u_long flag, SANE_Byte *reg, SANE_Byte *msk )
* for the normal lamp, or DEV_LampTPA for negative/transparency
* lamp
*/
static int usb_GetLampStatus( Plustek_Device *dev )
static int
usb_GetLampStatus( Plustek_Device *dev )
{
int iLampStatus = 0;
u_char *regs = dev->usbDev.a_bRegs;
HWDef *hw = &dev->usbDev.HwSetting;
DCapsDef *sc = &dev->usbDev.Caps;
SANE_Byte reg, msk, val;
int iLampStatus = 0;
u_char *regs = dev->usbDev.a_bRegs;
HWDef *hw = &dev->usbDev.HwSetting;
DCapsDef *sc = &dev->usbDev.Caps;
SANE_Byte reg, msk, val;
if( NULL == hw ) {
DBG( _DBG_ERROR, "NULL-Pointer detected: usb_GetLampStatus()\n" );
@ -928,6 +1055,7 @@ static int usb_GetLampStatus( Plustek_Device *dev )
usbio_ReadReg( dev->fd, 0x29, &reg );
if( reg & 3 )
iLampStatus |= DEV_LampReflection;
} else {
/* check if the lamp is on */
@ -948,9 +1076,10 @@ static int usb_GetLampStatus( Plustek_Device *dev )
iLampStatus |= DEV_LampTPA;
}
/* CanoScan D660U extra vaganza... */
if((dev->usbDev.vendor == 0x04A9) && (dev->usbDev.product==0x2208)) {
sanei_lm983x_read( dev->fd, 0x29, &regs[0x29], 3, SANE_TRUE );
DBG( _DBG_INFO, "[29]=0x%02x, [2A]=0x%02x, [2B]=0x%02x\n",
DBG( _DBG_INFO, "[29]=0x%02x, [2A]=0x%02x, [2B]=0x%02x\n",
regs[0x29], regs[0x2a], regs[0x2b] );
}
}
@ -982,8 +1111,8 @@ static int usb_GetLampStatus( Plustek_Device *dev )
/** usb_switchLampX
* used for all devices that use some misc I/O pins to switch the lamp
*/
static SANE_Bool usb_switchLampX( Plustek_Device *dev,
SANE_Bool on, SANE_Bool tpa )
static SANE_Bool
usb_switchLampX( Plustek_Device *dev, SANE_Bool on, SANE_Bool tpa )
{
SANE_Byte reg, msk;
DCapsDef *sc = &dev->usbDev.Caps;
@ -1013,7 +1142,8 @@ static SANE_Bool usb_switchLampX( Plustek_Device *dev,
/** usb_switchLamp
* used for all devices that use some misc I/O pins to switch the lamp
*/
static SANE_Bool usb_switchLamp( Plustek_Device *dev, SANE_Bool on )
static SANE_Bool
usb_switchLamp( Plustek_Device *dev, SANE_Bool on )
{
SANE_Bool result;
@ -1023,12 +1153,16 @@ static SANE_Bool usb_switchLamp( Plustek_Device *dev, SANE_Bool on )
} else {
result = usb_switchLampX( dev, on, SANE_FALSE );
}
/* to switch off CIS, we need to tweak the lampoff/on regs */
usb_AdjustLamps( dev, on );
return result;
}
/** usb_LedOn
*/
static void usb_LedOn( Plustek_Device *dev, SANE_Bool fOn )
static void
usb_LedOn( Plustek_Device *dev, SANE_Bool fOn )
{
u_char value;
@ -1049,7 +1183,8 @@ static void usb_LedOn( Plustek_Device *dev, SANE_Bool fOn )
/** usb_FillLampRegs
* set all the registers controlling the lamps
*/
static void usb_FillLampRegs( Plustek_Device *dev )
static void
usb_FillLampRegs( Plustek_Device *dev )
{
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
@ -1075,8 +1210,8 @@ static void usb_FillLampRegs( Plustek_Device *dev )
/** usb_LampOn
*/
static SANE_Bool usb_LampOn( Plustek_Device *dev,
SANE_Bool fOn, SANE_Bool fResetTimer )
static SANE_Bool
usb_LampOn( Plustek_Device *dev, SANE_Bool fOn, SANE_Bool fResetTimer )
{
DCapsDef *sc = &dev->usbDev.Caps;
ScanDef *scanning = &dev->scanning;
@ -1210,7 +1345,8 @@ static SANE_Bool usb_LampOn( Plustek_Device *dev,
* it should contain all we need
* @return - Nothing
*/
static void usb_ResetRegisters( Plustek_Device *dev )
static void
usb_ResetRegisters( Plustek_Device *dev )
{
int linend;
@ -1224,7 +1360,11 @@ static void usb_ResetRegisters( Plustek_Device *dev )
memcpy( regs+0x0f, &hw->bReg_0x0f_Color, 10 );
regs[0x1a] = _HIBYTE( hw->StepperPhaseCorrection );
regs[0x1b] = _LOBYTE( hw->StepperPhaseCorrection );
#if 0
regs[0x1c] = hw->bOpticBlackStart;
regs[0x1d] = hw->bOpticBlackEnd;
regs[0x1e] = _HIBYTE( hw->wActivePixelsStart );
regs[0x1f] = _LOBYTE( hw->wActivePixelsStart );
#endif
@ -1232,7 +1372,7 @@ static void usb_ResetRegisters( Plustek_Device *dev )
regs[0x21] = _LOBYTE( hw->wLineEnd );
regs[0x22] = _HIBYTE( hw->bOpticBlackStart );
regs[0x22] = _LOBYTE( hw->bOpticBlackStart );
regs[0x23] = _LOBYTE( hw->bOpticBlackStart );
linend = hw->bOpticBlackStart + hw->wLineEnd;
if( linend < (hw->wLineEnd-20))
@ -1282,9 +1422,11 @@ static void usb_ResetRegisters( Plustek_Device *dev )
regs[0x59], regs[0x5a], regs[0x5b] );
}
/** usb_ModuleStatus
/** function which checks if we are already in home position or not.
*
*/
static SANE_Bool usb_ModuleStatus( Plustek_Device *dev )
static SANE_Bool
usb_SensorStatus( Plustek_Device *dev )
{
u_char value;
HWDef *hw = &dev->usbDev.HwSetting;
@ -1295,12 +1437,11 @@ static SANE_Bool usb_ModuleStatus( Plustek_Device *dev )
return SANE_TRUE;
#endif
/* read the status register */
_UIO( usbio_ReadReg( dev->fd, 2, &value ));
if( value & 1 ) {
if( value & 1 ) {
_UIO( usbio_ReadReg( dev->fd, 0x7, &value));
if( value ) {
usbio_WriteReg( dev->fd, 0x07, 0 );
@ -1319,15 +1460,17 @@ static SANE_Bool usb_ModuleStatus( Plustek_Device *dev )
_UIO( usbio_ReadReg( dev->fd, 0x7, &value ));
if( !(value & 2))
if( !(value & 2)) {
usb_ModuleToHome( dev, SANE_FALSE );
}
return SANE_FALSE;
}
/**
*/
static void usb_LampSwitch( Plustek_Device *dev, SANE_Bool sw )
static void
usb_LampSwitch( Plustek_Device *dev, SANE_Bool sw )
{
int handle = -1;
@ -1355,10 +1498,11 @@ static Plustek_Device *dev_xxx = NULL;
/** ISR to switch lamp off after time has elapsed
*/
static void usb_LampTimerIrq( int sig )
static void
usb_LampTimerIrq( int sig )
{
if( NULL == dev_xxx )
return;
return;
_VAR_NOT_USED( sig );
DBG( _DBG_INFO, "LAMP OFF!!!\n" );
@ -1368,7 +1512,8 @@ static void usb_LampTimerIrq( int sig )
/** usb_StartLampTimer
*/
static void usb_StartLampTimer( Plustek_Device *dev )
static void
usb_StartLampTimer( Plustek_Device *dev )
{
sigset_t block, pause_mask;
struct sigaction s;
@ -1414,7 +1559,8 @@ static void usb_StartLampTimer( Plustek_Device *dev )
/** usb_StopLampTimer
*/
static void usb_StopLampTimer( Plustek_Device *dev )
static void
usb_StopLampTimer( Plustek_Device *dev )
{
sigset_t block, pause_mask;
@ -1435,38 +1581,15 @@ static void usb_StopLampTimer( Plustek_Device *dev )
DBG( _DBG_INFO, "Lamp-Timer stopped\n" );
}
/**
* This function is used to detect a cancel condition,
* our ESC key is the SIGUSR1 signal. It is sent by the backend when the
* cancel button has been pressed
*
* @param - none
* @return the function returns SANE_TRUE if a cancel condition has been
* detected, if not, it returns SANE_FALSE
*/
static SANE_Bool usb_IsEscPressed( void )
{
sigset_t sigs;
sigpending( &sigs );
if( sigismember( &sigs, SIGUSR1 )) {
DBG( _DBG_INFO, "SIGUSR1 is pending --> Cancel detected\n" );
return SANE_TRUE;
}
return SANE_FALSE;
}
/** wait until warmup has been done
*/
static SANE_Bool usb_Wait4Warmup( Plustek_Device *dev )
static SANE_Bool
usb_Wait4Warmup( Plustek_Device *dev )
{
u_long dw;
struct timeval t;
HWDef *hw = &dev->usbDev.HwSetting;
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
DBG(_DBG_INFO,"Warmup: skipped for CIS devices\n" );
return SANE_TRUE;
}
@ -1499,7 +1622,8 @@ static SANE_Bool usb_Wait4Warmup( Plustek_Device *dev )
/** function for TPA autodection (EPSON & UMAX devices)
*/
static SANE_Bool usb_HasTPA( Plustek_Device *dev )
static SANE_Bool
usb_HasTPA( Plustek_Device *dev )
{
static char model[] = { "3450" };
u_char val;
@ -1559,7 +1683,8 @@ static SANE_Bool usb_HasTPA( Plustek_Device *dev )
/** function for reading the button states
*/
static SANE_Bool usb_UpdateButtonStatus( Plustek_Scanner *s )
static SANE_Bool
usb_UpdateButtonStatus( Plustek_Scanner *s )
{
u_char mio[3];
SANE_Byte val, mask;
@ -1628,7 +1753,17 @@ static SANE_Bool usb_UpdateButtonStatus( Plustek_Scanner *s )
/* the generic section... */
val >>= 2;
bc = 0;
bc = 0;
/* only use the "valid" ports, that reflect a button */
if( _WAF_MISC_IO_BUTTONS & caps->workaroundFlag ) {
if((caps->lamp & _PORT0) == 0)
mio[0] = 0xff;
if((caps->lamp & _PORT1) == 0)
mio[1] = 0xff;
if((caps->lamp & _PORT2) == 0)
mio[2] = 0xff;
}
for( i = 0; i < 3; i++ ) {
@ -1661,4 +1796,5 @@ static SANE_Bool usb_UpdateButtonStatus( Plustek_Scanner *s )
sanei_access_unlock( dev->sane.name );
return SANE_TRUE;
}
/* END PLUSTEK-USBHW.C ......................................................*/

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Image processing functions for copying and scaling image lines.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -26,10 +26,12 @@
* - 0.47 - added big-endian/little endian stuff
* - 0.48 - fixed usb_ColorDuplicateGray16() and
* usb_ColorScaleGray16()
* - added usb_BWScaleFromColor() and usb_BWDuplicateFromColor
* - added usb_BWScaleFromColor() and usb_BWDuplicateFromColor()
* - cleanup
* - 0.49 - a_bRegs is now part of the device structure
* - 0.50 - cleanup
* - 0.51 - added usb_ColorDuplicateGray16_2(), usb_ColorScaleGray16_2()
* usb_BWScaleFromColor_2() and usb_BWDuplicateFromColor_2()
* .
* <hr>
* This file is part of the SANE package.
@ -579,7 +581,7 @@ static void usb_ColorDuplicateGray16( Plustek_Device *dev )
ScanDef *scan = &dev->scanning;
SANE_Bool swap = usb_HostSwap();
usb_AverageColorByte( dev );
usb_AverageColorWord( dev );
if (scan->sParam.bSource == SOURCE_ADF) {
next = -1;
@ -628,6 +630,71 @@ static void usb_ColorDuplicateGray16( Plustek_Device *dev )
}
}
/**
*/
static void usb_ColorDuplicateGray16_2( Plustek_Device *dev )
{
int next;
u_char ls;
u_long dw, pixels;
HiLoDef tmp;
ScanDef *scan = &dev->scanning;
SANE_Bool swap = usb_HostSwap();
usb_AverageColorWord( dev );
if (scan->sParam.bSource == SOURCE_ADF) {
next = -1;
pixels = scan->sParam.Size.dwPixels - 1;
} else {
next = 1;
pixels = 0;
}
if( scan->dwFlag & SCANFLAG_RightAlign )
ls = Shift;
else
ls = 0;
switch(scan->fGrayFromColor) {
case 1:
if( swap ) {
for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
tmp = *((HiLoDef*)&scan->Red.pw[dw]);
scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
}
} else {
for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls;
}
}
break;
case 2:
if( swap ) {
for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
tmp = *((HiLoDef*)&scan->Green.pw[dw]);
scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
}
} else {
for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
scan->UserBuf.pw[pixels] = scan->Green.pw[dw] >> ls;
}
}
break;
case 3:
if( swap ) {
for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
tmp = *((HiLoDef*)&scan->Blue.pw[dw]);
scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
}
} else {
for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) {
scan->UserBuf.pw[pixels] = scan->Blue.pw[dw] >> ls;
}
}
break;
}
}
/**
*/
static void usb_GrayDuplicate8( Plustek_Device *dev )
@ -735,7 +802,7 @@ static void usb_BWDuplicate( Plustek_Device *dev )
}
/** generate binary data from one of the three color inputs according to the
* value in fGrayFromColor
* value in fGrayFromColor (CCD version)
*/
static void usb_BWDuplicateFromColor( Plustek_Device *dev )
{
@ -776,6 +843,46 @@ static void usb_BWDuplicateFromColor( Plustek_Device *dev )
}
}
/** generate binary data from one of the three color inputs according to the
* value in fGrayFromColor (CIS version)
*/
static void usb_BWDuplicateFromColor_2( Plustek_Device *dev )
{
int next;
u_char d, *dest, *src;
u_short j;
u_long pixels;
ScanDef *scan = &dev->scanning;
if( scan->sParam.bSource == SOURCE_ADF ) {
dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
next = -1;
} else {
dest = scan->UserBuf.pb;
next = 1;
}
switch(scan->fGrayFromColor) {
case 1: src = scan->Red.pb; break;
case 3: src = scan->Blue.pb; break;
default: src = scan->Green.pb; break;
}
d = j = 0;
for( pixels = scan->sParam.Size.dwPixels; pixels; pixels--, src++ ) {
if( *src != 0 )
d |= BitTable[j];
j++;
if( j == 8 ) {
*dest = d;
dest += next;
d = j = 0;
}
}
}
/************************** the scaling functions ****************************/
/**
@ -954,6 +1061,97 @@ static void usb_ColorScaleGray16( Plustek_Device *dev )
}
}
/**
*/
static void usb_ColorScaleGray16_2( Plustek_Device *dev )
{
u_char ls;
int izoom, ddax, next;
u_long dw, pixels, bitsput;
HiLoDef tmp;
SANE_Bool swap = usb_HostSwap();
ScanDef *scan = &dev->scanning;
usb_AverageColorByte( dev );
dw = scan->sParam.Size.dwPixels;
if( scan->sParam.bSource == SOURCE_ADF ) {
next = -1;
pixels = scan->sParam.Size.dwPixels - 1;
} else {
next = 1;
pixels = 0;
}
izoom = usb_GetScaler( scan );
if( scan->dwFlag & SCANFLAG_RightAlign )
ls = Shift;
else
ls = 0;
switch( scan->fGrayFromColor ) {
case 1:
for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
ddax -= _SCALER;
while((ddax < 0) && (dw > 0)) {
if( swap ) {
tmp = *((HiLoDef*)&scan->Red.pw[bitsput]);
scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
} else {
scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls;
}
pixels += next;
ddax += izoom;
dw--;
}
}
break;
case 2:
for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
ddax -= _SCALER;
while((ddax < 0) && (dw > 0)) {
if( swap ) {
tmp = *((HiLoDef*)&scan->Green.pw[bitsput]);
scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
} else {
scan->UserBuf.pw[pixels] = scan->Green.pw[bitsput] >> ls;
}
pixels += next;
ddax += izoom;
dw--;
}
}
break;
case 3:
for( bitsput = 0, ddax = 0; dw; bitsput++ ) {
ddax -= _SCALER;
while((ddax < 0) && (dw > 0)) {
if( swap ) {
tmp = *((HiLoDef*)&scan->Blue.pw[bitsput]);
scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls;
} else {
scan->UserBuf.pw[pixels] = scan->Blue.pw[bitsput] >> ls;
}
pixels += next;
ddax += izoom;
dw--;
}
}
break;
}
}
/** here we copy and scale from scanner world to user world...
*/
static void usb_ColorScale8( Plustek_Device *dev )
@ -1300,6 +1498,55 @@ static void usb_BWScaleFromColor( Plustek_Device *dev )
}
}
/**
*/
static void usb_BWScaleFromColor_2( Plustek_Device *dev )
{
u_char d, *dest, *src;
u_short j;
u_long pixels;
int izoom, ddax, next;
ScanDef *scan = &dev->scanning;
if (scan->sParam.bSource == SOURCE_ADF) {
dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1;
next = -1;
} else {
dest = scan->UserBuf.pb;
next = 1;
}
/* setup the source buffer */
switch(scan->fGrayFromColor) {
case 1: src = scan->Red.pb; break;
case 3: src = scan->Blue.pb; break;
default: src = scan->Green.pb; break;
}
izoom = usb_GetScaler( scan );
ddax = 0;
d = j = 0;
for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) {
ddax -= _SCALER;
while((ddax < 0) && (pixels > 0)) {
if( *src != 0 )
d |= BitTable[j];
j++;
if( j == 8 ) {
*dest = d;
dest += next;
d = j = 0;
}
ddax += izoom;
pixels--;
}
}
}
/**
*/
static void usb_GrayScale8( Plustek_Device *dev )
@ -1455,8 +1702,13 @@ static void usb_GetImageProc( Plustek_Device *dev )
DBG( _DBG_INFO, "ImageProc is: ColorScale16\n" );
}
if (scan->fGrayFromColor) {
scan->pfnProcess = usb_ColorScaleGray16;
DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16\n" );
if( usb_IsCISDevice(dev)){
scan->pfnProcess = usb_ColorScaleGray16_2;
DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16_2\n" );
} else {
scan->pfnProcess = usb_ColorScaleGray16;
DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16\n" );
}
}
} else if (scan->dwFlag & SCANFLAG_Pseudo48) {
scan->pfnProcess = usb_ColorScalePseudo16;
@ -1464,9 +1716,14 @@ static void usb_GetImageProc( Plustek_Device *dev )
} else if (scan->fGrayFromColor) {
if( usb_IsCISDevice(dev)){
scan->pfnProcess = usb_ColorScaleGray_2;
DBG( _DBG_INFO, "ImageProc is: ColorScaleGray_2\n" );
if( usb_IsCISDevice(dev)){
if (scan->fGrayFromColor > 7 ) {
scan->pfnProcess = usb_BWScaleFromColor_2;
DBG( _DBG_INFO, "ImageProc is: BWScaleFromColor_2\n" );
} else {
scan->pfnProcess = usb_ColorScaleGray_2;
DBG( _DBG_INFO, "ImageProc is: ColorScaleGray_2\n" );
}
} else {
if (scan->fGrayFromColor > 7 ) {
scan->pfnProcess = usb_BWScaleFromColor;
@ -1517,7 +1774,7 @@ static void usb_GetImageProc( Plustek_Device *dev )
case SCANDATATYPE_Color:
if (scan->sParam.bBitDepth > 8) {
if( usb_IsCISDevice(dev)){
if( usb_IsCISDevice(dev)){
scan->pfnProcess = usb_ColorDuplicate16_2;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicate16_2\n" );
} else {
@ -1525,16 +1782,26 @@ static void usb_GetImageProc( Plustek_Device *dev )
DBG( _DBG_INFO, "ImageProc is: ColorDuplicate16\n" );
}
if (scan->fGrayFromColor) {
scan->pfnProcess = usb_ColorDuplicateGray16;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16\n" );
if( usb_IsCISDevice(dev)){
scan->pfnProcess = usb_ColorDuplicateGray16_2;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16_2\n" );
} else {
scan->pfnProcess = usb_ColorDuplicateGray16;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16\n" );
}
}
} else if (scan->dwFlag & SCANFLAG_Pseudo48) {
scan->pfnProcess = usb_ColorDuplicatePseudo16;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicatePseudo16\n" );
} else if (scan->fGrayFromColor) {
if( usb_IsCISDevice(dev)){
scan->pfnProcess = usb_ColorDuplicateGray_2;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray_2\n" );
if( usb_IsCISDevice(dev)){
if (scan->fGrayFromColor > 7 ) {
scan->pfnProcess = usb_BWDuplicateFromColor_2;
DBG( _DBG_INFO, "ImageProc is: BWDuplicateFromColor_2\n" );
} else {
scan->pfnProcess = usb_ColorDuplicateGray_2;
DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray_2\n" );
}
} else {
if (scan->fGrayFromColor > 7 ) {
scan->pfnProcess = usb_BWDuplicateFromColor;

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Some I/O stuff.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* History:
@ -26,6 +26,7 @@
* - 0.50 - usbio_DetectLM983x() now returns error if register
* could not be red
* - usbio_ResetLM983x() checks for reg7 value before writing
* - 0.51 - allow dumpRegs to be called without valid fd
* .
* <hr>
* This file is part of the SANE package.
@ -165,37 +166,38 @@ static void dumpregs( int fd, SANE_Byte *cmp )
buf[0] = '\0';
usbio_ReadReg(fd, 0x01, &regs[0x01]);
usbio_ReadReg(fd, 0x02, &regs[0x02]);
usbio_ReadReg(fd, 0x03, &regs[0x03]);
usbio_ReadReg(fd, 0x04, &regs[0x04]);
usbio_ReadReg(fd, 0x07, &regs[0x07]);
if( fd >= 0 ) {
usbio_ReadReg(fd, 0x01, &regs[0x01]);
usbio_ReadReg(fd, 0x02, &regs[0x02]);
usbio_ReadReg(fd, 0x03, &regs[0x03]);
usbio_ReadReg(fd, 0x04, &regs[0x04]);
usbio_ReadReg(fd, 0x07, &regs[0x07]);
sanei_lm983x_read( fd, 0x08, &regs[0x8], 0x80-0x8, SANE_TRUE );
sanei_lm983x_read( fd, 0x08, &regs[0x8], 0x80-0x8, SANE_TRUE );
for( i = 0x0; i < 0x80; i++ ) {
for( i = 0x0; i < 0x80; i++ ) {
if((i%16) ==0 ) {
if((i%16) ==0 ) {
if( buf[0] )
DBG( _DBG_DREGS, "%s\n", buf );
sprintf( buf, "0x%02x:", i );
if( buf[0] )
DBG( _DBG_DREGS, "%s\n", buf );
sprintf( buf, "0x%02x:", i );
}
if((i%8)==0)
strcat( buf, " ");
/* the dataport read returns with "0 Bytes read", of course. */
if((i == 0) || (i == 5) || (i == 6))
strcat( buf, "XX ");
else {
sprintf( b2, "%02x ", regs[i]);
strcat( buf, b2 );
}
}
if((i%8)==0)
strcat( buf, " ");
/* the dataport read returns with "0 Bytes read", of course. */
if((i == 0) || (i == 5) || (i == 6))
strcat( buf, "XX ");
else {
sprintf( b2, "%02x ", regs[i]);
strcat( buf, b2 );
}
DBG( _DBG_DREGS, "%s\n", buf );
}
DBG( _DBG_DREGS, "%s\n", buf );
if( cmp ) {

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Creating and manipulating lookup tables.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -21,6 +21,7 @@
* - 0.48 - added support for binary from color scans
* - 0.49 - changed usb_MapDownload
* - 0.50 - cleanup
* - 0.51 - no changes
* .
* <hr>
* This file is part of the SANE package.

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Scanning...
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -28,6 +28,7 @@
* - using now PhyDpi.y as selector for the motor MCLK range
* - changed usb_MapDownload prototype
* - 0.50 - cleanup
* - 0.51 - added usb_get_res() and usb_GetPhyPixels()
* .
* <hr>
* This file is part of the SANE package.
@ -70,6 +71,8 @@
* <hr>
*/
#define DIVIDER 8
/** array used to get motor-settings and mclk-settings
*/
static int dpi_ranges[] = { 75,100,150,200,300,400,600,800,1200,2400 };
@ -100,7 +103,8 @@ static SANE_Bool usb_DownloadShadingData( Plustek_Device*, u_char );
* @param val2 - second parameter
* @return val1 if val1 < val2, else val1
*/
static u_long usb_min( u_long val1, u_long val2 )
static u_long
usb_min( u_long val1, u_long val2 )
{
if( val1 > val2 )
return val2;
@ -112,13 +116,30 @@ static u_long usb_min( u_long val1, u_long val2 )
* @param val2 - second parameter
* @return val1 if val1 > val2, else val2
*/
static u_long usb_max( u_long val1, u_long val2 )
static u_long
usb_max( u_long val1, u_long val2 )
{
if( val1 > val2 )
return val1;
return val2;
}
/** function to get the possible resolution for a specific base resolution,
* according to the dividers a LM983x offers.
* @param base - scanners optical resolution
* @param idx - which divider to use
*/
static u_short
usb_get_res( u_short base, u_short idx )
{
double div_list[DIVIDER] = { 12.0, 8.0, 6.0, 4.0, 3.0, 2.0, 1.5, 1.0 };
if( idx == 0 || idx > DIVIDER )
return 0;
return (u_short)((double)base/div_list[idx-1]);
}
/** Set the horizontal DPI divider.
* Affected registers:<br>
* 0x09 - Horizontal DPI divider HDPI_DIV<br>
@ -128,7 +149,8 @@ static u_long usb_max( u_long val1, u_long val2 )
* @param xdpi - user specified horizontal resolution
* @return - the function returns the "normalized" horizontal resolution.
*/
static u_short usb_SetAsicDpiX( Plustek_Device *dev, u_short xdpi )
static u_short
usb_SetAsicDpiX( Plustek_Device *dev, u_short xdpi )
{
u_short res;
ScanDef *scanning = &dev->scanning;
@ -205,7 +227,8 @@ static u_short usb_SetAsicDpiX( Plustek_Device *dev, u_short xdpi )
* @param ydpi - user specified vertical resolution
* @return -
*/
static u_short usb_SetAsicDpiY( Plustek_Device *dev, u_short ydpi )
static u_short
usb_SetAsicDpiY( Plustek_Device *dev, u_short ydpi )
{
ScanDef *scanning = &dev->scanning;
DCapsDef *sCaps = &dev->usbDev.Caps;
@ -257,7 +280,8 @@ static u_short usb_SetAsicDpiY( Plustek_Device *dev, u_short ydpi )
* @param pParam - pointer to the current scan parameters
* @return - Nothing
*/
static void usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam )
static void
usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam )
{
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
@ -269,9 +293,9 @@ static void usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam )
regs[0x26] = hw->bReg_0x26 & 0x7;
/* if set to one channel color, we select the blue channel
* as input source, this is the default, but I don't know
* what happens, if we deselect this
*/
* as input source, this is the default, but I don't know
* what happens, if we deselect this
*/
if( regs[0x26] & _ONE_CH_COLOR )
regs[0x26] |= (_BLUE_CH | 0x01);
@ -290,7 +314,7 @@ static void usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam )
memcpy( &regs[0x0f], hw->bReg_0x0f_Mono, 10 );
break;
}
regs[0x27] = hw->bReg_0x27;
if( pParam->bBitDepth > 8 ) {
@ -301,6 +325,45 @@ static void usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam )
}
}
/**
* Data output from NS983X should be times of 2-byte and every line
* will append 2 status bytes
*/
static void
usb_GetPhyPixels( Plustek_Device *dev, ScanParam *sp )
{
sp->Size.dwValidPixels = sp->Size.dwPixels * sp->PhyDpi.x / sp->UserDpi.x;
if (sp->bBitDepth == 1) {
/* Pixels should be times of 16 */
sp->Size.dwPhyPixels =
(sp->Size.dwValidPixels + 15UL) & 0xfffffff0UL;
sp->Size.dwPhyBytes = sp->Size.dwPhyPixels / 8UL + 2UL;
} else if (sp->bBitDepth == 8) {
/* Pixels should be times of 2 */
sp->Size.dwPhyPixels = (sp->Size.dwValidPixels + 1UL) & 0xfffffffeUL;
sp->Size.dwPhyBytes = sp->Size.dwPhyPixels * sp->bChannels + 2UL;
/* need to be adjusted fo CIS devices in color mode */
if(usb_IsCISDevice( dev ) && (sp->bDataType == SCANDATATYPE_Color)) {
sp->Size.dwPhyBytes *= 3;
}
}
else /* sp->bBitDepth == 16 */
{
sp->Size.dwPhyPixels = sp->Size.dwValidPixels;
sp->Size.dwPhyBytes = sp->Size.dwPhyPixels * 2 * sp->bChannels + 2UL;
/* need to be adjusted fo CIS devices in color mode */
if(usb_IsCISDevice( dev ) && (sp->bDataType == SCANDATATYPE_Color)) {
sp->Size.dwPhyBytes *= 3;
}
}
}
/** Calculate basic image settings like the number of physical bytes per line
* etc...
* Affected registers:<br>
@ -313,7 +376,8 @@ static void usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam )
* @param pParam - pointer to the current scan parameters
* @return - Nothing
*/
static void usb_GetScanRect( Plustek_Device *dev, ScanParam *pParam )
static void
usb_GetScanRect( Plustek_Device *dev, ScanParam *sp )
{
u_short wDataPixelStart, wLineEnd;
@ -322,75 +386,35 @@ static void usb_GetScanRect( Plustek_Device *dev, ScanParam *pParam )
u_char *regs = dev->usbDev.a_bRegs;
/* Convert pixels to physical dpi based */
pParam->Size.dwValidPixels = pParam->Size.dwPixels *
pParam->PhyDpi.x / pParam->UserDpi.x;
/* HEINER: check ADF stuff... */
#if 0
if(pParam->bCalibration != PARAM_Gain &&
pParam->bCalibration != PARAM_Offset && ScanInf.m_fADF)
wDataPixelStart = 2550 * sCaps->OpticDpi.x / 300UL -
(u_short)(m_dHDPIDivider * pParam->Size.dwValidPixels + 0.5);
else
#endif
wDataPixelStart = (u_short)((u_long) pParam->Origin.x *
sCaps->OpticDpi.x / 300UL);
/* Data output from NS983X should be times of 2-byte and every line
* will append 2 status bytes
*/
if (pParam->bBitDepth == 1)
{
/* Pixels should be times of 16 */
pParam->Size.dwPhyPixels =
(pParam->Size.dwValidPixels + 15UL) & 0xfffffff0UL;
pParam->Size.dwPhyBytes = pParam->Size.dwPhyPixels / 8UL + 2UL;
}
else if (pParam->bBitDepth == 8)
{
/* Pixels should be times of 2 */
pParam->Size.dwPhyPixels =
(pParam->Size.dwValidPixels + 1UL) & 0xfffffffeUL;
pParam->Size.dwPhyBytes =
pParam->Size.dwPhyPixels * pParam->bChannels + 2UL;
if((hw->bReg_0x26 & _ONE_CH_COLOR) &&
(pParam->bDataType == SCANDATATYPE_Color)) {
pParam->Size.dwPhyBytes *= 3;
}
}
else /* pParam->bBitDepth == 16 */
{
pParam->Size.dwPhyPixels = pParam->Size.dwValidPixels;
pParam->Size.dwPhyBytes =
pParam->Size.dwPhyPixels * 2 * pParam->bChannels + 2UL;
if((hw->bReg_0x26 & _ONE_CH_COLOR) &&
(pParam->bDataType == SCANDATATYPE_Color)) {
pParam->Size.dwPhyBytes *= 3;
}
}
usb_GetPhyPixels( dev, sp );
/* Compute data start pixel */
wDataPixelStart = (u_short)((u_long)pParam->Origin.x *
sCaps->OpticDpi.x / 300UL);
#if 0
/* HEINER: check ADF stuff... */
if(sp->bCalibration != PARAM_Gain &&
sp->bCalibration != PARAM_Offset && ScanInf.m_fADF)
wDataPixelStart = 2550 * sCaps->OpticDpi.x / 300UL -
(u_short)(m_dHDPIDivider * sp->Size.dwValidPixels + 0.5);
else
#endif
wDataPixelStart = (u_short)((u_long)sp->Origin.x *
sCaps->OpticDpi.x / 300UL);
/* during the calibration steps, we read the entire CCD data
*/
if((pParam->bCalibration != PARAM_Gain) &&
(pParam->bCalibration != PARAM_Offset)) {
if((sp->bCalibration != PARAM_Gain)&&(sp->bCalibration != PARAM_Offset)) {
/* HEINER: check ADF stuff... */
#if 0
if(ScanInf.m_fADF) {
wDataPixelStart = 2550 * sCaps->OpticDpi.x / 300UL -
(u_short)(m_dHDPIDivider * pParam->Size.dwValidPixels + 0.5);
(u_short)(m_dHDPIDivider * sp->Size.dwValidPixels + 0.5);
}
#endif
wDataPixelStart += hw->wActivePixelsStart;
}
wLineEnd = wDataPixelStart + (u_short)(m_dHDPIDivider *
pParam->Size.dwPhyPixels + 0.5);
sp->Size.dwPhyPixels + 0.5);
DBG( _DBG_INFO2, "* DataPixelStart=%u, LineEnd=%u\n",
wDataPixelStart, wLineEnd );
@ -414,76 +438,77 @@ static void usb_GetScanRect( Plustek_Device *dev, ScanParam *pParam )
wLineEnd-wDataPixelStart, m_dHDPIDivider);
/* Y origin */
if( pParam->bCalibration == PARAM_Scan ) {
if( sp->bCalibration == PARAM_Scan ) {
if( hw->motorModel == MODEL_Tokyo600 ) {
if(pParam->PhyDpi.x <= 75)
pParam->Origin.y += 20;
else if(pParam->PhyDpi.x <= 100)
if(sp->PhyDpi.x <= 75)
sp->Origin.y += 20;
else if(sp->PhyDpi.x <= 100)
{
if (pParam->bDataType == SCANDATATYPE_Color)
pParam->Origin.y += 0;
if (sp->bDataType == SCANDATATYPE_Color)
sp->Origin.y += 0;
else
pParam->Origin.y -= 6;
sp->Origin.y -= 6;
}
else if(pParam->PhyDpi.x <= 150)
else if(sp->PhyDpi.x <= 150)
{
if (pParam->bDataType == SCANDATATYPE_Color)
pParam->Origin.y -= 0;
if (sp->bDataType == SCANDATATYPE_Color)
sp->Origin.y -= 0;
}
else if(pParam->PhyDpi.x <= 200)
else if(sp->PhyDpi.x <= 200)
{
if (pParam->bDataType == SCANDATATYPE_Color)
pParam->Origin.y -= 10;
if (sp->bDataType == SCANDATATYPE_Color)
sp->Origin.y -= 10;
else
pParam->Origin.y -= 4;
sp->Origin.y -= 4;
}
else if(pParam->PhyDpi.x <= 300)
else if(sp->PhyDpi.x <= 300)
{
if (pParam->bDataType == SCANDATATYPE_Color)
pParam->Origin.y += 16;
if (sp->bDataType == SCANDATATYPE_Color)
sp->Origin.y += 16;
else
pParam->Origin.y -= 18;
sp->Origin.y -= 18;
}
else if(pParam->PhyDpi.x <= 400)
else if(sp->PhyDpi.x <= 400)
{
if (pParam->bDataType == SCANDATATYPE_Color)
pParam->Origin.y += 15;
else if(pParam->bDataType == SCANDATATYPE_BW)
pParam->Origin.y += 4;
if (sp->bDataType == SCANDATATYPE_Color)
sp->Origin.y += 15;
else if(sp->bDataType == SCANDATATYPE_BW)
sp->Origin.y += 4;
}
else /* if(pParam->PhyDpi.x <= 600) */
else /* if(sp->PhyDpi.x <= 600) */
{
if (pParam->bDataType == SCANDATATYPE_Gray)
pParam->Origin.y += 4;
if (sp->bDataType == SCANDATATYPE_Gray)
sp->Origin.y += 4;
}
}
/* Add gray mode offset (Green offset, we assume the CCD are
* always be RGB or BGR order).
*/
if (pParam->bDataType != SCANDATATYPE_Color)
pParam->Origin.y += (u_long)(300UL *
if (sp->bDataType != SCANDATATYPE_Color)
sp->Origin.y += (u_long)(300UL *
sCaps->bSensorDistance / sCaps->OpticDpi.y);
}
pParam->Origin.y=(u_short)((u_long)pParam->Origin.y * hw->wMotorDpi/300UL);
sp->Origin.y=(u_short)((u_long)sp->Origin.y * hw->wMotorDpi/300UL);
/* Something wrong, but I can not find it. */
if( hw->motorModel == MODEL_HuaLien && sCaps->OpticDpi.x == 600)
pParam->Origin.y = pParam->Origin.y * 297 / 298;
sp->Origin.y = sp->Origin.y * 297 / 298;
DBG(_DBG_INFO2,"* Full Steps to Skip at Start = 0x%04x\n",
pParam->Origin.y);
sp->Origin.y);
regs[0x4a] = _HIBYTE( pParam->Origin.y );
regs[0x4b] = _LOBYTE( pParam->Origin.y );
regs[0x4a] = _HIBYTE( sp->Origin.y );
regs[0x4b] = _LOBYTE( sp->Origin.y );
}
/** preset scan stepsize and fastfeed stepsize
*/
static void usb_PresetStepSize( Plustek_Device *dev, ScanParam *pParam )
static void
usb_PresetStepSize( Plustek_Device *dev, ScanParam *pParam )
{
u_short ssize;
double mclkdiv = pParam->dMCLK;
@ -503,7 +528,8 @@ static void usb_PresetStepSize( Plustek_Device *dev, ScanParam *pParam )
/** calculate default phase difference DPD
*/
static void usb_GetDPD( Plustek_Device *dev )
static void
usb_GetDPD( Plustek_Device *dev )
{
int qtcnt; /* quarter speed count count reg 51 b2..3 */
int hfcnt; /* half speed count reg 51 b0..1 */
@ -556,7 +582,8 @@ static void usb_GetDPD( Plustek_Device *dev )
/**
*/
static int usb_GetMCLKDiv( Plustek_Device *dev )
static int
usb_GetMCLKDiv( Plustek_Device *dev )
{
int j, pixelbits, pixelsperline, r;
int minmclk, maxmclk, mclkdiv;
@ -627,7 +654,8 @@ static int usb_GetMCLKDiv( Plustek_Device *dev )
* at least we give the master clock divider and adjust the step size
* and integration time (for 14/16 bit modes)
*/
static double usb_GetMCLKDivider( Plustek_Device *dev, ScanParam *pParam )
static double
usb_GetMCLKDivider( Plustek_Device *dev, ScanParam *pParam )
{
double dMaxIntegrationTime;
double dMaxMCLKDivider;
@ -729,9 +757,10 @@ static double usb_GetMCLKDivider( Plustek_Device *dev, ScanParam *pParam )
/** calculate the step size of each scan step
*/
static void usb_GetStepSize( Plustek_Device *dev, ScanParam *pParam )
static void
usb_GetStepSize( Plustek_Device *dev, ScanParam *pParam )
{
HWDef *hw = &dev->usbDev.HwSetting;
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
/* Compute step size using equation 1 */
@ -758,7 +787,8 @@ static void usb_GetStepSize( Plustek_Device *dev, ScanParam *pParam )
/**
*/
static void usb_GetLineLength( Plustek_Device *dev )
static void
usb_GetLineLength( Plustek_Device *dev, ScanParam *param )
{
/* [note]
* The ITA in this moment is always 0, it will be changed later when we
@ -767,21 +797,22 @@ static void usb_GetLineLength( Plustek_Device *dev )
* never call again, maybe we remove all factor with ITA here.
*/
int tr;
int tpspd; /* turbo/preview mode speed reg 0a b2..3 */
int tpsel; /* turbo/preview mode select reg 0a b0..1 */
int gbnd; /* guardband duration reg 0e b4..7 */
int dur; /* pulse duration reg 0e b0..3 */
int ntr; /* number of tr pulses reg 0d b7 */
int afeop; /* scan mode, 0=pixel rate, 1=line rate, */
/* 4=1 channel mode a, 5=1 channel mode b, reg 26 b0..2 */
int ctmode; /* CIS tr timing mode reg 19 b0..1 */
int tp; /* tpspd or 1 if tpsel=0 */
int b; /* if ctmode=0, (ntr+1)*((2*gbnd)+dur+1), otherwise 1 */
int tradj; /* ITA */
int tpspd; /* turbo/preview mode speed reg 0a b2..3 */
int tpsel; /* turbo/preview mode select reg 0a b0..1 */
int gbnd; /* guardband duration reg 0e b4..7 */
int dur; /* pulse duration reg 0e b0..3 */
int ntr; /* number of tr pulses reg 0d b7 */
int afeop; /* scan mode, 0=pixel rate, 1=line rate, */
/* 4=1 channel mode a, 5=1 channel mode b, reg 26 b0..2 */
int ctmode; /* CIS tr timing mode reg 19 b0..1 */
int tp; /* tpspd or 1 if tpsel=0 */
int b; /* if ctmode=0, (ntr+1)*((2*gbnd)+dur+1), otherwise 1 */
int tradj; /* ITA */
int en_tradj;
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
u_short le;
HWDef *hw = &dev->usbDev.HwSetting;
ClkMotorDef *motor = usb_GetMotorSet( hw->motorModel );
u_char *regs = dev->usbDev.a_bRegs;
tpspd = (regs[0x0a] & 0x0c) >> 2; /* turbo/preview mode speed */
tpsel = regs[0x0a] & 3; /* turbo/preview mode select */
@ -819,8 +850,21 @@ static void usb_GetLineLength( Plustek_Device *dev )
}
if( ctmode == 2 ) /* CIS mode scanner */
b = 3;
tr = m_bLineRateColor * (hw->wLineEnd + tp * (b + 3 - ntr));
/* it might be necessary to tweak this value, to keep the
* MCLK constant - see some sheet-fed devices
*/
le = hw->wLineEnd;
if (motor->dpi_thresh != 0) {
if( param->PhyDpi.y <= motor->dpi_thresh) {
le = motor->lineend;
DBG( _DBG_INFO2, "* Adjusting lineend: %u\n", le);
}
regs[0x20] = _HIBYTE( le );
regs[0x21] = _LOBYTE( le );
}
tr = m_bLineRateColor * (le + tp * (b + 3 - ntr));
if( tradj == 0 ) {
if( ctmode == 0 )
@ -833,7 +877,7 @@ static void usb_GetLineLength( Plustek_Device *dev )
if( afeop != 0 ) {
le_phi = (tradj + 1) / 2 + 1 + 6;
num_byteclk = ((le_phi + 8 * hw->wLineEnd + 8 * b + 4) /
num_byteclk = ((le_phi + 8 * le + 8 * b + 4) /
(8 * tradj)) + 1;
num_mclkf = 8 * tradj * num_byteclk;
tr_fast_pix = num_byteclk;
@ -842,14 +886,14 @@ static void usb_GetLineLength( Plustek_Device *dev )
else /* 3 channel pixel rate color */
{
le_phi = (tradj + 1) / 2 + 1 + 10 + 12;
num_byteclk = ((le_phi + 3 * 8 * hw->wLineEnd + 3 * 8 * b + 3 * 4) /
num_byteclk = ((le_phi + 3 * 8 * le + 3 * 8 * b + 3 * 4) /
(3 * 8 * tradj)) + 1;
num_mclkf = 3 * 8 * tradj * num_byteclk;
tr_fast_pix = num_byteclk;
extra_pix = (num_mclkf - le_phi) % (3 * 8);
}
tr = b + hw->wLineEnd + 4 + tr_fast_pix;
tr = b + le + 4 + tr_fast_pix;
if (extra_pix == 0)
tr++;
tr *= m_bLineRateColor;
@ -863,7 +907,8 @@ static void usb_GetLineLength( Plustek_Device *dev )
/** usb_GetMotorParam
* registers 0x56, 0x57
*/
static void usb_GetMotorParam( Plustek_Device *dev, ScanParam *pParam )
static void
usb_GetMotorParam( Plustek_Device *dev, ScanParam *pParam )
{
int idx, i;
ClkMotorDef *clk;
@ -872,14 +917,14 @@ static void usb_GetMotorParam( Plustek_Device *dev, ScanParam *pParam )
HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs;
if( !_IS_PLUSTEKMOTOR(hw->motorModel)) {
if (!_IS_PLUSTEKMOTOR(hw->motorModel)) {
clk = usb_GetMotorSet( hw->motorModel );
md = clk->motor_sets;
idx = 0;
idx = 0;
for( i = 0; i < _MAX_CLK; i++ ) {
if( pParam->PhyDpi.y <= dpi_ranges[i] )
break;
break;
idx++;
}
if( idx >= _MAX_CLK )
@ -900,44 +945,44 @@ static void usb_GetMotorParam( Plustek_Device *dev, ScanParam *pParam )
regs[0x44] = md[idx].scan_lines_per_line;
DBG( _DBG_INFO2, "* Line Skipping : 0x43=0x%02x, 0x44=0x%02x\n",
regs[0x43], regs[0x44] );
regs[0x43], regs[0x44] );
}
}
} else {
} else {
if( sCaps->OpticDpi.x == 1200 ) {
if( sCaps->OpticDpi.x == 1200 ) {
switch( hw->motorModel ) {
switch( hw->motorModel ) {
case MODEL_HuaLien:
case MODEL_KaoHsiung:
default:
if(pParam->PhyDpi.x <= 200)
{
regs[0x56] = 1;
regs[0x57] = 48; /* 63; */
}
else if(pParam->PhyDpi.x <= 300)
{
regs[0x56] = 2; /* 8; */
regs[0x57] = 48; /* 56; */
}
else if(pParam->PhyDpi.x <= 400)
{
regs[0x56] = 8;
regs[0x57] = 48;
}
else if(pParam->PhyDpi.x <= 600)
{
regs[0x56] = 2; /* 10; */
regs[0x57] = 48; /* 56; */
}
else /* pParam->PhyDpi.x == 1200) */
{
regs[0x56] = 1; /* 8; */
regs[0x57] = 48; /* 56; */
}
break;
case MODEL_HuaLien:
case MODEL_KaoHsiung:
default:
if(pParam->PhyDpi.x <= 200)
{
regs[0x56] = 1;
regs[0x57] = 48; /* 63; */
}
else if(pParam->PhyDpi.x <= 300)
{
regs[0x56] = 2; /* 8; */
regs[0x57] = 48; /* 56; */
}
else if(pParam->PhyDpi.x <= 400)
{
regs[0x56] = 8;
regs[0x57] = 48;
}
else if(pParam->PhyDpi.x <= 600)
{
regs[0x56] = 2; /* 10; */
regs[0x57] = 48; /* 56; */
}
else /* pParam->PhyDpi.x == 1200) */
{
regs[0x56] = 1; /* 8; */
regs[0x57] = 48; /* 56; */
}
break;
}
} else {
switch ( hw->motorModel ) {
@ -1007,14 +1052,15 @@ static void usb_GetMotorParam( Plustek_Device *dev, ScanParam *pParam )
}
}
}
DBG( _DBG_INFO2, "* MOTOR-Settings: PWM=0x%02x, PWM_DUTY=0x%02x\n",
regs[0x56], regs[0x57] );
}
/**
*/
static void usb_GetPauseLimit( Plustek_Device *dev, ScanParam *pParam )
static void
usb_GetPauseLimit( Plustek_Device *dev, ScanParam *pParam )
{
int coeffsize, scaler;
HWDef *hw = &dev->usbDev.HwSetting;
@ -1074,7 +1120,8 @@ static void usb_GetPauseLimit( Plustek_Device *dev, ScanParam *pParam )
/** usb_GetScanLinesAndSize
*/
static void usb_GetScanLinesAndSize( Plustek_Device *dev, ScanParam *pParam )
static void
usb_GetScanLinesAndSize( Plustek_Device *dev, ScanParam *pParam )
{
DCapsDef *sCaps = &dev->usbDev.Caps;
@ -1100,7 +1147,8 @@ static void usb_GetScanLinesAndSize( Plustek_Device *dev, ScanParam *pParam )
/** function to preset/reset the merlin registers
*/
static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
static SANE_Bool
usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
{
static u_char reg8, reg38[6], reg48[2];
@ -1126,8 +1174,8 @@ static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
}
/*
* calculate the basic settings...
*/
* calculate the basic settings...
*/
pParam->PhyDpi.x = usb_SetAsicDpiX( dev, pParam->UserDpi.x );
pParam->PhyDpi.y = usb_SetAsicDpiY( dev, pParam->UserDpi.y );
@ -1169,7 +1217,7 @@ static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
pParam->bSource == SOURCE_ADF && dev->usbDev.fLastScanIsAdf )) {
DBG( _DBG_INFO2, "* Scan calculations...\n" );
usb_GetLineLength ( dev );
usb_GetLineLength ( dev, pParam );
usb_GetStepSize ( dev, pParam );
usb_GetDPD ( dev );
usb_GetMCLKDivider( dev, pParam );
@ -1209,7 +1257,7 @@ static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
usb_GetPauseLimit( dev, pParam );
/* For ADF .... */
if(pParam->bCalibration == PARAM_Scan && pParam->bSource == SOURCE_ADF) {
if(pParam->bCalibration == PARAM_Scan && pParam->bSource == SOURCE_ADF) {
if( dev->usbDev.fLastScanIsAdf ) {
@ -1245,19 +1293,21 @@ static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
memset( &regs[0x03], 0, 3 );
memset( &regs[0x5f], 0, 0x7f-0x5f+1 );
/* we limit the possible scansteps to avoid, that the sensors bumps
* against the scanbed
*/
if(pParam->bCalibration == PARAM_Scan && pParam->bSource != SOURCE_ADF) {
if( !usb_IsSheetFedDevice(dev)) {
/* we limit the possible scansteps to avoid, that the sensors bumps
* against the scanbed - not necessary for sheet-fed devices
*/
if(pParam->bCalibration==PARAM_Scan && pParam->bSource!=SOURCE_ADF) {
u_long lines = pParam->Size.dwPhyLines + scan->bLinesToSkip +
scan->dwLinesDiscard + 5;
u_short scansteps = (u_short)ceil((double)lines*
hw->wMotorDpi / pParam->PhyDpi.y);
DBG( _DBG_INFO, "* Scansteps=%u (%lu*%u/%u)\n", scansteps, lines,
hw->wMotorDpi, pParam->PhyDpi.y );
regs[0x4c] = _HIBYTE(scansteps);
regs[0x4d] = _LOBYTE(scansteps);
u_long lines = pParam->Size.dwPhyLines + scan->bLinesToSkip +
scan->dwLinesDiscard + 5;
u_short scansteps = (u_short)ceil((double)lines*
hw->wMotorDpi / pParam->PhyDpi.y);
DBG( _DBG_INFO, "* Scansteps=%u (%lu*%u/%u)\n", scansteps, lines,
hw->wMotorDpi, pParam->PhyDpi.y );
regs[0x4c] = _HIBYTE(scansteps);
regs[0x4d] = _LOBYTE(scansteps);
}
}
/* set the merlin registers */
@ -1275,7 +1325,8 @@ static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam )
/**
*/
static SANE_Bool usb_ScanBegin( Plustek_Device *dev, SANE_Bool auto_park )
static SANE_Bool
usb_ScanBegin( Plustek_Device *dev, SANE_Bool auto_park )
{
u_char value;
u_short inches;
@ -1285,6 +1336,9 @@ static SANE_Bool usb_ScanBegin( Plustek_Device *dev, SANE_Bool auto_park )
DBG( _DBG_INFO, "usb_ScanBegin()\n" );
if( !usb_Wait4ScanSample( dev ))
return SANE_FALSE;
/* save the request for usb_ScanEnd () */
m_fAutoPark = auto_park;
@ -1299,7 +1353,7 @@ static SANE_Bool usb_ScanBegin( Plustek_Device *dev, SANE_Bool auto_park )
if( !usb_IsScannerReady(dev))
return SANE_FALSE;
/* Flush cache - only LM9831 (Source: National Semiconductors */
/* Flush cache - only LM9831 (Source: National Semiconductors) */
if( _LM9831 == hw->chip ) {
for(;;) {
@ -1357,7 +1411,8 @@ static SANE_Bool usb_ScanBegin( Plustek_Device *dev, SANE_Bool auto_park )
/** usb_ScanEnd
* stop all the processing stuff and reposition sensor back home
*/
static SANE_Bool usb_ScanEnd( Plustek_Device *dev )
static SANE_Bool
usb_ScanEnd( Plustek_Device *dev )
{
u_char value;
@ -1382,7 +1437,8 @@ static SANE_Bool usb_ScanEnd( Plustek_Device *dev )
/**
*/
static SANE_Bool usb_IsDataAvailableInDRAM( Plustek_Device *dev )
static SANE_Bool
usb_IsDataAvailableInDRAM( Plustek_Device *dev )
{
/* Compute polling timeout
* Height (Inches) / MaxScanSpeed (Inches/Second) = Seconds to move the
@ -1435,8 +1491,8 @@ static SANE_Bool usb_IsDataAvailableInDRAM( Plustek_Device *dev )
/**
*/
static SANE_Bool usb_ScanReadImage( Plustek_Device *dev,
void *pBuf, u_long dwSize )
static SANE_Bool
usb_ScanReadImage( Plustek_Device *dev, void *pBuf, u_long dwSize )
{
static u_long dwBytes = 0;
u_char *regs = dev->usbDev.a_bRegs;
@ -1525,7 +1581,8 @@ static SANE_Bool usb_ScanReadImage( Plustek_Device *dev,
/** calculate the number of pixels per line and lines out of a given
* crop-area. The size of the area is given on a 300dpi base!
*/
static void usb_GetImageInfo( Plustek_Device *dev, ImgDef *pInfo, WinInfo *pSize )
static void
usb_GetImageInfo( Plustek_Device *dev, ImgDef *pInfo, WinInfo *pSize )
{
DBG( _DBG_INFO, "usb_GetImageInfo()\n" );
@ -1566,7 +1623,8 @@ static void usb_GetImageInfo( Plustek_Device *dev, ImgDef *pInfo, WinInfo *pSize
/**
*/
static void usb_SaveImageInfo( Plustek_Device *dev, ImgDef *pInfo )
static void
usb_SaveImageInfo( Plustek_Device *dev, ImgDef *pInfo )
{
HWDef *hw = &dev->usbDev.HwSetting;
ScanParam *pParam = &dev->scanning.sParam;
@ -1622,6 +1680,34 @@ static void usb_SaveImageInfo( Plustek_Device *dev, ImgDef *pInfo )
pParam->bSource = SOURCE_ADF;
else
pParam->bSource = SOURCE_Reflection;
/* it seems, that we need to adjust the Origin.x when we have a
* sheetfed device to avoid stripes in the resulting pictures
*/
if( usb_IsSheetFedDevice(dev)) {
int step, div, org, xdpi;
xdpi = usb_SetAsicDpiX( dev, pParam->UserDpi.x );
if ((xdpi * 2) <= 300)
div = 300;
else if ((xdpi * 2) <= 600)
div = 600;
else if ((xdpi * 2) <= 1200)
div = 1200;
else
div = 2400;
step = div / xdpi;
org = pParam->Origin.x;
pParam->Origin.x = (pParam->Origin.x / step) * step;
if (org != pParam->Origin.x)
DBG(_DBG_INFO, "* Origin.x adjusted: %i -> %i\n",
org, pParam->Origin.x);
}
}
/* END PLUSTEK-USBSCAN.C ....................................................*/

Wyświetl plik

@ -7,7 +7,7 @@
* @brief Calibration routines.
*
* Based on sources acquired from Plustek Inc.<br>
* Copyright (C) 2001-2005 Gerhard Jaeger <gerhard@gjaeger.de>
* Copyright (C) 2001-2006 Gerhard Jaeger <gerhard@gjaeger.de>
*
* History:
* - 0.40 - starting version of the USB support
@ -30,6 +30,7 @@
* - using now PhyDpi.y as selector for the motor MCLK range
* - 0.50 - readded kCIS670 to add 5% extra to LiDE20 fine calibration
* - fixed line statistics and added data output
* - 0.51 - added fine calibration cache
* .
* <hr>
* This file is part of the SANE package.
@ -85,9 +86,6 @@
#define SWAP_COARSE
#define SWAP_FINE
static u_short a_wWhiteShading[_SHADING_BUF] = {0};
static u_short a_wDarkShading[_SHADING_BUF] = {0};
/************************** static variables *********************************/
static RGBUShortDef Gain_Hilight;
@ -183,7 +181,7 @@ static void usb_line_statistics( char *cmt, u_short* buf,
if( tmp < lbd ) cld++;
}
DBG( _DBG_INFO2, "Color[%u] (%s): %lu pixels "
DBG( _DBG_INFO2, "Color[%u] (%s): %lu all "
"min=%u(%lu) max=%u(%lu) ave=%u\n",
i, cmt, dim_x, mid, imid, mad, imad, aved);
DBG( _DBG_INFO2, "5%%: low@%u (count=%lu), upper@%u (count=%lu)\n",
@ -191,6 +189,51 @@ static void usb_line_statistics( char *cmt, u_short* buf,
}
}
/**
*/
static void
usb_PrepareFineCal( Plustek_Device *dev, ScanParam *tmp_sp, u_short cal_dpi )
{
ScanParam *sp = &dev->scanning.sParam;
DCapsDef *scaps = &dev->usbDev.Caps;
*tmp_sp = *sp;
if( dev->adj.cacheCalData ) {
DBG( _DBG_INFO2, "* Cal-cache active, tweaking scanparams"
" - DPI=%u!\n", cal_dpi );
tmp_sp->UserDpi.x = usb_SetAsicDpiX(dev, sp->UserDpi.x );
if( cal_dpi != 0 )
tmp_sp->UserDpi.x = cal_dpi;
tmp_sp->PhyDpi = scaps->OpticDpi;
tmp_sp->Origin.x = 0;
tmp_sp->Size.dwPixels = scaps->Normal.Size.x *
usb_SetAsicDpiX(dev, tmp_sp->UserDpi.x)/ 300UL;
}
#if 0
if( tmp_sp->PhyDpi.x > 75)
tmp_sp->Size.dwLines = 64;
else
#endif
tmp_sp->Size.dwLines = 32;
tmp_sp->Origin.y = 0;
tmp_sp->bBitDepth = 16;
tmp_sp->UserDpi.y = scaps->OpticDpi.y;
tmp_sp->Size.dwBytes = tmp_sp->Size.dwPixels * 2 * tmp_sp->bChannels;
if( usb_IsCISDevice(dev) && (tmp_sp->bDataType == SCANDATATYPE_Color)) {
tmp_sp->Size.dwBytes *= 3;
}
tmp_sp->dMCLK = dMCLK;
}
/**
*/
static double usb_GetMCLK( Plustek_Device *dev, ScanParam *param )
@ -231,7 +274,7 @@ static double usb_GetMCLK( Plustek_Device *dev, ScanParam *param )
/** usb_SetMCLK
* get the MCLK out of our table
*/
static void usb_SetMCLK( Plustek_Device *dev, ScanParam *param )
static void usb_SetMCLK( Plustek_Device *dev, ScanParam *param )
{
HWDef *hw = &dev->usbDev.HwSetting;
@ -280,7 +323,7 @@ static SANE_Bool usb_SetDarkShading( Plustek_Device *dev, u_char channel,
return SANE_FALSE;
}
/** usb_SetWhiteShading
/** usb_SetWhiteShading
* download the white shading data to Merlins' DRAM
*/
static SANE_Bool usb_SetWhiteShading( Plustek_Device *dev, u_char channel,
@ -380,7 +423,7 @@ static void usb_GetSWOffsetGain( Plustek_Device *dev )
param->swGain[0] = 960;
param->swGain[1] = 970;
param->swGain[2] = 1000;
} else if (param->PhyDpi.x <= 300) {
} else if (param->PhyDpi.x <= 300) {
param->swOffset[0] = 700;
param->swOffset[1] = 600;
param->swOffset[2] = 400;
@ -702,7 +745,7 @@ static SANE_Bool adjLampSetting( Plustek_Device *dev, int channel, u_long max,
*l_off = l_on + lamp_on;
DBG( _DBG_INFO2,
"lamp(%u) adjust (-3%%): %i %i\n", channel, l_on, *l_off );
adj = SANE_TRUE;
adj = SANE_TRUE;
}
/* if the image was too dull, increase lamp by 1% */
@ -768,10 +811,8 @@ static SANE_Bool usb_AdjustGain( Plustek_Device *dev, int fNegative )
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels *
2 * m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color)
m_ScanParam.Size.dwBytes *= 3;
}
m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart *
300UL / scaps->OpticDpi.x);
@ -917,8 +958,8 @@ TOGAIN:
/* do some averaging... */
for (dwLoop2 = dwDiv, dwR = dwG = dwB = 0;
dwLoop2; dwLoop2--, dw++) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
dwLoop2; dwLoop2--, dw++) {
if( usb_IsCISDevice(dev)) {
dwR += ((u_short*)scanbuf)[dw];
dwG += ((u_short*)scanbuf)[dw+m_ScanParam.Size.dwPhyPixels+1];
dwB += ((u_short*)scanbuf)[dw+(m_ScanParam.Size.dwPhyPixels+1)*2];
@ -958,7 +999,7 @@ TOGAIN:
* for adjusting the gain
*/
tmp_rgb = max_rgb;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
tmp_rgb = min_rgb;
DBG(_DBG_INFO2, "CUR(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n",
@ -977,7 +1018,7 @@ TOGAIN:
SANE_Bool adj = SANE_FALSE;
/* on CIS devices, we can control the lamp off settings */
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
/* m_dwIdealGain = IDEAL_GainNormal;
*/
@ -998,7 +1039,7 @@ TOGAIN:
/* on any adjustment, set the registers... */
if( adj ) {
usb_AdjustLamps( dev );
usb_AdjustLamps( dev, SANE_TRUE );
if( i < _MAX_GAIN_LOOPS )
goto TOGAIN;
@ -1075,7 +1116,7 @@ TOGAIN:
}
w_tmp = w_max;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
w_tmp = w_min;
regs[0x3b] =
@ -1093,7 +1134,7 @@ TOGAIN:
SANE_Bool adj = SANE_FALSE;
/* on CIS devices, we can control the lamp off settings */
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
if( adjLampSetting( dev, CHANNEL_green, w_tmp, m_dwIdealGain,
hw->green_lamp_on, &hw->green_lamp_off )) {
@ -1102,7 +1143,7 @@ TOGAIN:
/* on any adjustment, set the registers... */
if( adj ) {
usb_AdjustLamps( dev );
usb_AdjustLamps( dev, SANE_TRUE );
if( i < _MAX_GAIN_LOOPS )
goto TOGAIN;
@ -1233,7 +1274,7 @@ static SANE_Bool usb_AdjustOffset( Plustek_Device *dev )
m_ScanParam.Size.dwLines = 1;
m_ScanParam.Size.dwPixels = 2550;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
dwPixels = m_ScanParam.Size.dwPixels;
else
dwPixels = (u_long)(hw->bOpticBlackEnd - hw->bOpticBlackStart );
@ -1241,10 +1282,8 @@ static SANE_Bool usb_AdjustOffset( Plustek_Device *dev )
m_ScanParam.Size.dwPixels = 2550;
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 *
m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color )
m_ScanParam.Size.dwBytes *= 3;
}
m_ScanParam.Origin.x = (u_short)((u_long)hw->bOpticBlackStart * 300UL /
dev->usbDev.Caps.OpticDpi.x);
@ -1257,7 +1296,7 @@ static SANE_Bool usb_AdjustOffset( Plustek_Device *dev )
regs[0x38] = regs[0x39] = regs[0x3a] = 0;
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
/*
* if we have dark shading strip, there's no need to switch
* the lamp off
@ -1389,7 +1428,7 @@ static SANE_Bool usb_AdjustOffset( Plustek_Device *dev )
DBG( _DBG_INFO, "usb_AdjustOffset() done.\n" );
/* switch it on again on CIS based scanners */
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
if( dev->usbDev.pSource->DarkShadOrgY < 0 ) {
regs[0x29] = hw->bReg_0x29;
@ -1547,13 +1586,10 @@ static SANE_Bool usb_AdjustDarkShading( Plustek_Device *dev )
DBG( _DBG_INFO2, "* MCLK = %f (scanparam-MCLK=%f)\n",
dMCLK, scanning->sParam.dMCLK );
m_ScanParam = scanning->sParam;
m_ScanParam.Origin.y = 0;
m_ScanParam.UserDpi.y = scaps->OpticDpi.y;
usb_PrepareFineCal( dev, &m_ScanParam, 0 );
m_ScanParam.Size.dwLines = 1; /* for gain */
m_ScanParam.bBitDepth = 16;
m_ScanParam.bCalibration = PARAM_DarkShading;
m_ScanParam.dMCLK = dMCLK;
if( _LM9831 == hw->chip ) {
@ -1570,14 +1606,9 @@ static SANE_Bool usb_AdjustDarkShading( Plustek_Device *dev )
2UL * m_ScanParam.bChannels;
m_dwPixels = scanning->sParam.Size.dwPixels *
m_ScanParam.UserDpi.x / scanning->sParam.UserDpi.x;
} else {
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels *
2 * m_ScanParam.bChannels;
}
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
m_ScanParam.Size.dwBytes *= 3;
if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color )
m_ScanParam.Size.dwBytes *= 3;
}
/* if we have dark shading strip, there's no need to switch
@ -1634,7 +1665,7 @@ static SANE_Bool usb_AdjustDarkShading( Plustek_Device *dev )
if( m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
usb_GetDarkShading( dev, a_wDarkShading, (HiLoDef*)scanbuf,
m_ScanParam.Size.dwPhyPixels, 1,
@ -1845,6 +1876,8 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
if( usb_IsEscPressed())
return SANE_FALSE;
usb_PrepareFineCal( dev, &m_ScanParam, 0 );
if( m_ScanParam.PhyDpi.x > 75)
shading_lines = 64;
else
@ -1854,29 +1887,8 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
hilight = 4;
shadow = 4;
m_ScanParam = scan->sParam;
m_ScanParam.Origin.y = 0;
m_ScanParam.bBitDepth = 16;
/* HEINER: check ADF stuff... */
#if 0
if( ScanInf.m_fADF ) {
/* avoid ADF WhiteShading big noise */
m_ScanParam.UserDpi.y = Device.Caps.OpticDpi.y - 200;
} else {
#endif
m_ScanParam.UserDpi.y = scaps->OpticDpi.y;
/* } */
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 *
m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
m_ScanParam.Size.dwBytes *= 3;
}
m_ScanParam.bCalibration = PARAM_WhiteShading;
m_ScanParam.dMCLK = dMCLK;
m_ScanParam.Size.dwLines = shading_lines;
if( _LM9831 == hw->chip ) {
@ -1888,24 +1900,15 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
m_ScanParam.Origin.x = m_ScanParam.Origin.x % (u_short)m_dHDPIDivider;
m_ScanParam.Size.dwPixels = (u_long)scaps->Normal.Size.x * m_ScanParam.UserDpi.x / 300UL;
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2UL * m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color )
m_ScanParam.Size.dwBytes *= 3;
}
m_dwPixels = scan->sParam.Size.dwPixels * m_ScanParam.UserDpi.x /
scan->sParam.UserDpi.x;
dw = (u_long)(hw->wDRAMSize - DRAM_UsedByAsic16BitMode) * 1024UL;
m_ScanParam.Size.dwLines = shading_lines;
dw = (u_long)(hw->wDRAMSize - 196 /*192 KiB*/) * 1024UL;
for( dwLines = dw / m_ScanParam.Size.dwBytes;
dwLines < m_ScanParam.Size.dwLines; m_ScanParam.Size.dwLines>>=1);
} else {
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 * m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR &&
m_ScanParam.bDataType == SCANDATATYPE_Color ) {
m_ScanParam.Size.dwBytes *= 3;
}
m_ScanParam.Size.dwLines = shading_lines;
}
/* goto the correct position again... */
@ -1932,7 +1935,7 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
DBG(_DBG_INFO2,"TotalBytes = %lu\n",m_ScanParam.Size.dwTotalBytes);
if( _LM9831 == hw->chip ) {
/* Delay for white shading hold for 9831-1200 scanner */
usleep(250 * 10000);
usleep(900000);
}
if( usb_ScanReadImage( dev, pBuf + dwRead,
@ -1940,7 +1943,7 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
if( _LM9831 == hw->chip ) {
/* Delay for white shading hold for 9831-1200 scanner */
usleep(10 * 1000);
usleep(10000);
}
if( 0 == dwRead ) {
@ -1967,7 +1970,7 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
* from RRRRRRR.... GGGGGGGG.... BBBBBBBBB, create RGB RGB RGB ...
* to use the following code, originally written for CCD devices...
*/
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
u_short *dest, *src;
u_long dww;
@ -2179,6 +2182,9 @@ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev )
}
}
}
usb_SaveCalSetShading( dev, &m_ScanParam );
if( scan->sParam.bSource != SOURCE_Negative ) {
usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels,
scan->sParam.bDataType == SCANDATATYPE_Color?1:0);
@ -2214,15 +2220,15 @@ static void usb_ResizeWhiteShading( double dAmp, u_short *pwShading, int iGain )
}
#ifdef SWAP_FINE
if( usb_HostSwap()) {
if( usb_HostSwap())
usb_Swap( pwShading, m_ScanParam.Size.dwPhyPixels );
}
#endif
}
/** do the base settings for calibration scans
*/
static void usb_PrepareCalibration( Plustek_Device *dev )
static void
usb_PrepareCalibration( Plustek_Device *dev )
{
ScanDef *scan = &dev->scanning;
DCapsDef *scaps = &dev->usbDev.Caps;
@ -2259,11 +2265,35 @@ static void usb_PrepareCalibration( Plustek_Device *dev )
if( dev->adj.cacheCalData )
if( usb_ReadAndSetCalData( dev ))
scan->skipCoarseCalib = SANE_TRUE;
/* as sheet-fed device we use the cached values, or
* perform the calibration upon request
*/
if( usb_IsSheetFedDevice(dev)) {
if( !scan->skipCoarseCalib && !usb_InCalibrationMode(dev)) {
DBG(_DBG_INFO2,"SHEET-FED device, skip coarse calibration!\n");
scan->skipCoarseCalib = SANE_TRUE;
regs[0x3b] = 0x0a;
regs[0x3c] = 0x0a;
regs[0x3d] = 0x0a;
/* use frontend values... */
if((dev->adj.rgain != -1) &&
(dev->adj.ggain != -1) && (dev->adj.bgain != -1)) {
setAdjGain( dev->adj.rgain, &regs[0x3b] );
setAdjGain( dev->adj.ggain, &regs[0x3c] );
setAdjGain( dev->adj.bgain, &regs[0x3d] );
}
}
}
}
/**
*/
static SANE_Bool usb_SpeedTest( Plustek_Device *dev )
static SANE_Bool
usb_SpeedTest( Plustek_Device *dev )
{
int i;
double s, e, r, tr;
@ -2303,7 +2333,7 @@ static SANE_Bool usb_SpeedTest( Plustek_Device *dev )
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels *
2 * m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
m_ScanParam.Size.dwBytes *= 3;
m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart *
@ -2347,7 +2377,8 @@ static SANE_Bool usb_SpeedTest( Plustek_Device *dev )
/** read the white calibration strip until the lamp seems to be stable
* the timed warmup will be used, when the warmup time is set to -1
*/
static SANE_Bool usb_AutoWarmup( Plustek_Device *dev )
static SANE_Bool
usb_AutoWarmup( Plustek_Device *dev )
{
int i, stable_count;
ScanDef *scanning = &dev->scanning;
@ -2369,13 +2400,17 @@ static SANE_Bool usb_AutoWarmup( Plustek_Device *dev )
DBG( _DBG_INFO, "#########################\n" );
DBG( _DBG_INFO, "usb_AutoWarmup()\n" );
if( usb_IsCISDevice(dev)) {
DBG( _DBG_INFO, "- function skipped, CIS device!\n" );
return SANE_TRUE;
}
if( dev->adj.warmup >= 0 ) {
DBG( _DBG_INFO, "... using timed warmup: %ds\n", dev->adj.warmup );
DBG( _DBG_INFO, "- using timed warmup: %ds\n", dev->adj.warmup );
if( !usb_Wait4Warmup( dev )) {
DBG( _DBG_ERROR, "usb_AutoWarmup() - CANCEL detected\n" );
DBG( _DBG_ERROR, "- CANCEL detected\n" );
return SANE_FALSE;
}
DBG( _DBG_INFO, "usb_AutoWarmup() done.\n" );
return SANE_TRUE;
}
@ -2395,7 +2430,7 @@ static SANE_Bool usb_AutoWarmup( Plustek_Device *dev )
m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels *
2 * m_ScanParam.bChannels;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
m_ScanParam.Size.dwBytes *= 3;
m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart *
@ -2443,7 +2478,7 @@ static SANE_Bool usb_AutoWarmup( Plustek_Device *dev )
curR = curG = curB = 0;
for( dw = start; dw < end; dw++ ) {
if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
if( usb_IsCISDevice(dev)) {
curR += ((u_short*)scanbuf)[dw];
curG += ((u_short*)scanbuf)[dw+m_ScanParam.Size.dwPhyPixels+1];
curB += ((u_short*)scanbuf)[dw+(m_ScanParam.Size.dwPhyPixels+1)*2];
@ -2463,7 +2498,7 @@ static SANE_Bool usb_AutoWarmup( Plustek_Device *dev )
DBG( _DBG_INFO2, "%i/%i-AVE(R,G,B)= %lu(%ld), %lu(%ld), %lu(%ld)\n",
i, stable_count, curR, diffR, curG, diffG, curB, diffB );
/* we consider the lamp to be stable,
/* we consider the lamp to be stable,
* when the diffs are less than thresh for at least 3 loops
*/
if((diffR < thresh) && (diffG < thresh) && (diffB < thresh)) {
@ -2487,12 +2522,14 @@ static SANE_Bool usb_AutoWarmup( Plustek_Device *dev )
/**
*/
static int usb_DoIt( Plustek_Device *dev )
static int
usb_DoIt( Plustek_Device *dev )
{
ScanDef *scanning = &dev->scanning;
SANE_Bool skip_fine;
ScanDef *scan = &dev->scanning;
DBG( _DBG_INFO, "Settings done, so start...\n" );
if( !scanning->skipCoarseCalib ) {
if( !scan->skipCoarseCalib ) {
DBG( _DBG_INFO2, "###### ADJUST GAIN (COARSE)#######\n" );
if( !usb_AdjustGain(dev, 0)) {
DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" );
@ -2506,22 +2543,43 @@ static int usb_DoIt( Plustek_Device *dev )
} else {
DBG( _DBG_INFO2, "Coarse Calibration skipped, using saved data\n" );
}
DBG( _DBG_INFO2, "###### ADJUST DARK (FINE) ########\n" );
if( !usb_AdjustDarkShading(dev)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return _E_INTERNAL;
skip_fine = SANE_FALSE;
if( dev->adj.cacheCalData ) {
skip_fine = usb_FineShadingFromFile(dev);
}
DBG( _DBG_INFO2, "###### ADJUST WHITE (FINE) #######\n" );
if( !usb_AdjustWhiteShading(dev)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return _E_INTERNAL;
if( !skip_fine ) {
DBG( _DBG_INFO2, "###### ADJUST DARK (FINE) ########\n" );
if( !usb_AdjustDarkShading(dev)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return _E_INTERNAL;
}
DBG( _DBG_INFO2, "###### ADJUST WHITE (FINE) #######\n" );
if( !usb_AdjustWhiteShading(dev)) {
DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" );
return _E_INTERNAL;
}
} else {
DBG( _DBG_INFO2, "###### FINE calibration skipped #######\n" );
m_ScanParam = scan->sParam;
usb_GetPhyPixels( dev, &m_ScanParam );
usb_line_statistics( "Dark", a_wDarkShading, m_ScanParam.Size.dwPhyPixels,
m_ScanParam.bDataType == SCANDATATYPE_Color?1:0);
usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels,
m_ScanParam.bDataType == SCANDATATYPE_Color?1:0);
/* dev->usbDev.a_bRegs[0x45] &= ~0x10;*/
}
return 0;
}
/** usb_DoCalibration
*/
static int usb_DoCalibration( Plustek_Device *dev )
static int
usb_DoCalibration( Plustek_Device *dev )
{
int result;
ScanDef *scanning = &dev->scanning;
@ -2926,9 +2984,9 @@ static int usb_DoCalibration( Plustek_Device *dev )
DBG( _DBG_INFO, "REG[0x3c] = %u\n", regs[0x3c] );
DBG( _DBG_INFO, "REG[0x3d] = %u\n", regs[0x3d] );
DBG( _DBG_INFO, "Static Offset:\n" );
DBG( _DBG_INFO, "REG[0x38] = %u\n", regs[0x38] );
DBG( _DBG_INFO, "REG[0x39] = %u\n", regs[0x39] );
DBG( _DBG_INFO, "REG[0x3a] = %u\n", regs[0x3a] );
DBG( _DBG_INFO, "REG[0x38] = %i\n", regs[0x38] );
DBG( _DBG_INFO, "REG[0x39] = %i\n", regs[0x39] );
DBG( _DBG_INFO, "REG[0x3a] = %i\n", regs[0x3a] );
DBG( _DBG_INFO, "MCLK = %.2f\n", scanning->sParam.dMCLK );
DBG( _DBG_INFO, "-----------------------\n" );
return SANE_TRUE;
@ -2949,7 +3007,7 @@ static SANE_Bool usb_DownloadShadingData( Plustek_Device *dev, u_char what )
DBG( _DBG_INFO, "usb_DownloadShadingData(%u)\n", what );
channel = CHANNEL_green;
if( hw->bReg_0x26 & _ONE_CH_COLOR )
if( usb_IsCISDevice(dev))
channel = CHANNEL_blue;
switch( what ) {

Wyświetl plik

@ -3,7 +3,7 @@
;
:backend "plustek"
:version "0.50"
:version "0.51"
:manpage "sane-plustek"
; backend's web page
:url "http://www.gjaeger.de/scanner/plustek/"
@ -16,7 +16,6 @@
:url "http://www.plustek.de/"
:url "http://www.plustek.com/"
;name models for above-specified mfg.
:model "OpticPro U12"
:interface "USB"
:usbid "0x07b3" "0x0010"
@ -56,32 +55,32 @@
:model "Colorpage HR6 V2"
:interface "USB"
:usbid "0x0458" "0x2007"
:usbid "0x0458" "0x2007"
:status :complete
:model "Colorpage HR6 V2"
:interface "USB"
:usbid "0x0458" "0x2008"
:usbid "0x0458" "0x2008"
:status :complete
:model "Colorpage HR7"
:interface "USB"
:usbid "0x0458" "0x2013"
:usbid "0x0458" "0x2013"
:status :complete
:model "Colorpage HR6A"
:interface "USB"
:usbid "0x0458" "0x2009"
:usbid "0x0458" "0x2009"
:status :untested
:model "Colorpage HR7LE"
:interface "USB"
:usbid "0x0458" "0x2015"
:usbid "0x0458" "0x2015"
:status :untested
:model "Colorpage HR6X"
:interface "USB"
:usbid "0x0458" "0x2016"
:usbid "0x0458" "0x2016"
:status :untested
;* MUSTEK ***********************************************************************************
@ -91,19 +90,19 @@
:model "BearPaw 1200"
:interface "USB"
:usbid "0x0400" "0x1000"
:usbid "0x0400" "0x1000"
:status :complete
:comment "both product versions are supported, see backends' man-page"
:model "BearPaw 1200"
:interface "USB"
:usbid "0x0400" "0x1001"
:usbid "0x0400" "0x1001"
:status :complete
:comment "both product versions are supported, see backends' man-page"
:model "BearPaw 2400"
:interface "USB"
:usbid "0x0400" "0x1001"
:usbid "0x0400" "0x1001"
:status :complete
;* Hewlett-Packard **************************************************************************
@ -113,12 +112,12 @@
:model "ScanJet 2100C"
:interface "USB"
:usbid "0x03f0" "0x0505"
:usbid "0x03f0" "0x0505"
:status :complete
:model "ScanJet 2200C"
:interface "USB"
:usbid "0x03f0" "0x0605"
:usbid "0x03f0" "0x0605"
:status :complete
;* EPSON *******************************************************************************************
@ -128,48 +127,42 @@
:model "Perfection 1250"
:interface "USB"
:usbid "0x04b8" "0x010f"
:usbid "0x04b8" "0x010f"
:status :complete
:model "Perfection 1250Photo"
:interface "USB"
:usbid "0x04b8" "0x010f"
:usbid "0x04b8" "0x010f"
:status :good
:comment "TPA scans not perfect"
:model "Perfection 1260"
:interface "USB"
:usbid "0x04b8" "0x011d"
:usbid "0x04b8" "0x011d"
:status :complete
:model "Perfection 1260Photo"
:interface "USB"
:usbid "0x04b8" "0x011d"
:usbid "0x04b8" "0x011d"
:status :good
:comment "TPA scans not perfect"
;* UMAX *************************************************************************************
:mfg "UMAX"
:mfg "Umax"
:url "http://www.umax.com/"
:model "UMAX 3400"
:interface "USB"
:usbid "0x1606" "0x0050"
:status :complete
:comment "there are some UMAX 3400 sold outside the U.S. with product id 0x0050 which are not supported, as they use another chipset than the LM983x"
:comment "there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x"
:model "UMAX 3400"
:interface "USB"
:usbid "0x1606" "0x0060"
:status :complete
:comment "there are some UMAX 3400 sold outside the U.S. with product id 0x0050 which are not supported, as they use another chipset than the LM983x"
:model "UMAX Astranet ia101"
:interface "USB"
:usbid "0x1606" "0x0050"
:status :complete
:comment "seems to be a renamed UMAX 3400"
:comment "there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x"
:model "UMAX Astranet ia101"
:interface "USB"
@ -184,7 +177,7 @@
:model "UMAX 5400"
:interface "USB"
:usbid "0x1606" "0x0160"
:usbid "0x1606" "0x0160"
:status :complete
;* COMPAQ ******************************************************************************************
@ -198,6 +191,7 @@
:status :complete
:comment "Identical to UMAX 3400"
;* CANON *******************************************************************************************
:mfg "Canon"
@ -205,41 +199,41 @@
:model "CanoScan N650U/N656U"
:interface "USB"
:usbid "0x04a9" "0x2206"
:usbid "0x04a9" "0x2206"
:status :complete
:model "CanoScan N1220U"
:interface "USB"
:usbid "0x04a9" "0x2207"
:usbid "0x04a9" "0x2207"
:status :complete
:model "CanoScan N670U/N676U"
:model "CanoScan N670U/N676U/LiDE20"
:interface "USB"
:usbid "0x04a9" "0x220d"
:usbid "0x04a9" "0x220d"
:status :complete
:model "CanoScan N1240U"
:model "CanoScan N1240U/LiDE30"
:interface "USB"
:usbid "0x04a9" "0x220e"
:status :complete
:model "CanoScan LiDE20"
:interface "USB"
:usbid "0x04a9" "0x220d"
:usbid "0x04a9" "0x220e"
:status :complete
:model "CanoScan LiDE25"
:interface "USB"
:usbid "0x04a9" "0x2220"
:usbid "0x04a9" "0x2220"
:status :good
:model "CanoScan LiDE30"
:interface "USB"
:usbid "0x04a9" "0x220e"
:status :complete
:model "CanoScan D660U"
:interface "USB"
:usbid "0x04a9" "0x2208"
:usbid "0x04a9" "0x2208"
:status :good
:comment "TPA scans not perfect"
;* SYSCAN *******************************************************************************************
:mfg "Syscan"
:url "http://www.syscaninc.com"
:model "TravelScan 662"
:interface "USB"
:usbid "0x0a82" "0x6620"
:status :complete

Wyświetl plik

@ -1,4 +1,4 @@
.TH sane-plustek 5 "08 August 2005" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.TH sane-plustek 5 "09 April 2006" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.IX sane-plustek
.SH NAME
sane-plustek \- SANE backend for LM983[1/2/3] based
@ -142,6 +142,18 @@ CanoScan LIDE25 LM9833 1200x2400dpi 48bit 512Kb 0x2220
CanoScan LIDE30 LM9833 1200x2400dpi 48bit 512Kb 0x220E
.fi
.ft R
.PP
Vendor Syscan \- ID: 0x0A82
.br
.ft CR
.nf
----------------------------------------------------------
USB Model: ASIC: Properties: Prod-ID
----------------------------------------------------------
Travelscan 662 LM9833 600x1200dpi 48bit 512Kb 0x6620
.fi
.ft R
.SH "OTHER PLUSTEK SCANNERS"
For parallelport device support see the
@ -247,8 +259,8 @@ option invertNegatives b
option cacheCalData b
.RS
.I b
0 --> do not save coarse calibration results,
1 --> save results of coarse calibration in ~/.sane/ directory
0 --> do not save calibration results,
1 --> save results of calibration in ~/.sane/ directory
.RE
.PP
option altCalibration b
@ -447,11 +459,11 @@ For problem reports it should be enough the set the verbosity to
* The driver does not support these manic scalings up
to 16 times the physical resolution. The only scaling
is done on resolutions between the physical resolution
of the CDD-sensor and the stepper motor i.e. you have a
600x1200 dpi scanner and you are scanning using 800dpi,
so scaling is necessary, because the sensor only delivers
600dpi but the motor is capable of performing 1200dpi
steps.
of the CCD-/CIS-sensor and the stepper motor i.e. you
have a 600x1200 dpi scanner and you are scanning using
800dpi, so scaling is necessary, because the sensor only
delivers 600dpi but the motor is capable to perform
1200dpi steps.
.PP
* Plusteks' model policy is somewhat inconsistent. They
sell technically different devices under the

Wyświetl plik

@ -488,7 +488,7 @@ to other printers too, using bidirectional protocol
* The driver does not support these manic scalings up
to 16 times the physical resolution. The only scaling
is done on resolutions between the physical resolution
of the CDD-sensor and the stepper motor i.e. you have a
of the CCD-sensor and the stepper motor i.e. you have a
600x1200 dpi scanner and you are scanning using 800dpi,
so scaling is necessary, because the sensor only delivers
600dpi but the motor is capable to perform 800dpi steps.