Added button support for Plustek/Genius devices.

Changed behaviour of usb_IsScannerReady().
Added special misc I/O setup for CIS devices (usb_ResetRegisters).
merge-requests/1/head
Gerhard Jaeger 2005-08-15 14:48:28 +00:00
rodzic 39b37d80f6
commit 168204528d
1 zmienionych plików z 124 dodań i 89 usunięć

Wyświetl plik

@ -43,6 +43,9 @@
* - 0.49 - a_bRegs is now part of the device structure * - 0.49 - a_bRegs is now part of the device structure
* - fixed problem in backtracking, when speedup is enabled * - fixed problem in backtracking, when speedup is enabled
* - added usb_UpdateButtonStatus() * - added usb_UpdateButtonStatus()
* - 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)
* . * .
* <hr> * <hr>
* This file is part of the SANE package. * This file is part of the SANE package.
@ -125,7 +128,7 @@ static void usb_Swap( u_short *pw, u_long dwBytes )
* according to the model, the function returns the address of * according to the model, the function returns the address of
* the corresponding entry of the Motor table * the corresponding entry of the Motor table
*/ */
static pClkMotorDef usb_GetMotorSet( eModelDef model ) static ClkMotorDef *usb_GetMotorSet( eModelDef model )
{ {
int i; int i;
@ -151,7 +154,6 @@ static SANE_Bool usb_MotorOn( Plustek_Device *dev, SANE_Bool fOn )
dev->usbDev.a_bRegs[0x45] &= ~0x10; dev->usbDev.a_bRegs[0x45] &= ~0x10;
usbio_WriteReg( dev->fd, 0x45, dev->usbDev.a_bRegs[0x45] ); usbio_WriteReg( dev->fd, 0x45, dev->usbDev.a_bRegs[0x45] );
return SANE_TRUE; return SANE_TRUE;
} }
@ -169,7 +171,8 @@ static SANE_Bool usb_IsScannerReady( Plustek_Device *dev )
u_char value; u_char value;
double len; double len;
long timeout; long timeout;
struct timeval t; struct timeval t;
SANE_Status res;
/* time in s = 1000*scanner length in inches/max step speed/in */ /* time in s = 1000*scanner length in inches/max step speed/in */
len = (dev->usbDev.Caps.Normal.Size.y/(double)_MEASURE_BASE) + 5; len = (dev->usbDev.Caps.Normal.Size.y/(double)_MEASURE_BASE) + 5;
@ -184,23 +187,26 @@ static SANE_Bool usb_IsScannerReady( Plustek_Device *dev )
timeout = t.tv_sec + len; timeout = t.tv_sec + len;
do { do {
_UIO( usbio_ReadReg( dev->fd, 7, &value)); res = usbio_ReadReg( dev->fd, 7, &value);
if( res != SANE_STATUS_GOOD ) {
if( value == 0 ) { sleep(1);
_UIO( usbio_ResetLM983x( dev )); } else {
return SANE_TRUE; if( value == 0 ) {
} _UIO( usbio_ResetLM983x( dev ));
if((value == 0) || (value >= 0x20) || (value == 0x03)) {
if( !usbio_WriteReg( dev->fd, 0x07, 0 )) {
DBG( _DBG_ERROR, "Scanner not ready!!!\n" );
return SANE_FALSE;
}
else
return SANE_TRUE; return SANE_TRUE;
} }
if((value == 0) || (value >= 0x20) || (value == 0x03)) {
if( !usbio_WriteReg( dev->fd, 0x07, 0 )) {
DBG( _DBG_ERROR, "Scanner not ready!!!\n" );
return SANE_FALSE;
}
else {
return SANE_TRUE;
}
}
}
gettimeofday( &t, NULL); gettimeofday( &t, NULL);
} while( t.tv_sec < timeout ); } while( t.tv_sec < timeout );
@ -284,7 +290,7 @@ static SANE_Bool usb_WaitPos( Plustek_Device *dev, u_long to, SANE_Bool stay )
} }
gettimeofday( &start_time, NULL ); gettimeofday( &start_time, NULL );
dwTicks = start_time.tv_sec + to; dwTicks = start_time.tv_sec + to;
step = 1; step = 1;
retval = SANE_FALSE; retval = SANE_FALSE;
@ -353,8 +359,8 @@ static SANE_Bool usb_ModuleMove( Plustek_Device *dev,
u_char bReg2, reg7, mclk_div; u_char bReg2, reg7, mclk_div;
u_short wFastFeedStepSize; u_short wFastFeedStepSize;
double dMaxMoveSpeed; double dMaxMoveSpeed;
pClkMotorDef clk; ClkMotorDef *clk;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
if( bAction != MOVE_ToPaperSensor && if( bAction != MOVE_ToPaperSensor &&
@ -543,8 +549,8 @@ static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
{ {
u_char mclk_div; u_char mclk_div;
u_char value; u_char value;
pDCapsDef scaps = &dev->usbDev.Caps; DCapsDef *scaps = &dev->usbDev.Caps;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
/* Check if merlin is ready for setting command */ /* Check if merlin is ready for setting command */
@ -578,7 +584,7 @@ static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait )
if(!_IS_PLUSTEKMOTOR(hw->motorModel)) { if(!_IS_PLUSTEKMOTOR(hw->motorModel)) {
pClkMotorDef clk; ClkMotorDef *clk;
clk = usb_GetMotorSet( hw->motorModel ); clk = usb_GetMotorSet( hw->motorModel );
@ -715,8 +721,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 )
{ {
pDCapsDef sCaps = &dev->usbDev.Caps; DCapsDef *sCaps = &dev->usbDev.Caps;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
if(!_IS_PLUSTEKMOTOR(hw->motorModel)) { if(!_IS_PLUSTEKMOTOR(hw->motorModel)) {
@ -758,7 +764,7 @@ static SANE_Bool usb_MotorSelect( Plustek_Device *dev, SANE_Bool fADF )
*/ */
static SANE_Bool usb_AdjustLamps( Plustek_Device *dev ) static SANE_Bool usb_AdjustLamps( Plustek_Device *dev )
{ {
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
regs[0x2c] = _HIBYTE(hw->red_lamp_on); regs[0x2c] = _HIBYTE(hw->red_lamp_on);
@ -784,7 +790,7 @@ static SANE_Bool usb_AdjustLamps( Plustek_Device *dev )
*/ */
static void usb_AdjustCISLampSettings( Plustek_Device *dev, SANE_Bool on ) static void usb_AdjustCISLampSettings( Plustek_Device *dev, SANE_Bool on )
{ {
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
if( !(hw->bReg_0x26 & _ONE_CH_COLOR)) if( !(hw->bReg_0x26 & _ONE_CH_COLOR))
return; return;
@ -864,29 +870,29 @@ static void usb_GetLampRegAndMask( u_long flag, SANE_Byte *reg, SANE_Byte *msk )
*reg = 0x5b; *reg = 0x5b;
*msk = 0x80; *msk = 0x80;
} else if( _MIO5 == ( _MIO5 & flag )) { } else if( _MIO5 == ( _MIO5 & flag )) {
*reg = 0x5b; *reg = 0x5b;
*msk = 0x08; *msk = 0x08;
} else if( _MIO4 == ( _MIO4 & flag )) { } else if( _MIO4 == ( _MIO4 & flag )) {
*reg = 0x5a; *reg = 0x5a;
*msk = 0x80; *msk = 0x80;
} else if( _MIO3 == ( _MIO3 & flag )) { } else if( _MIO3 == ( _MIO3 & flag )) {
*reg = 0x5a; *reg = 0x5a;
*msk = 0x08; *msk = 0x08;
} else if( _MIO2 == ( _MIO2 & flag )) { } else if( _MIO2 == ( _MIO2 & flag )) {
*reg = 0x59; *reg = 0x59;
*msk = 0x80; *msk = 0x80;
} else if( _MIO1 == ( _MIO1 & flag )) { } else if( _MIO1 == ( _MIO1 & flag )) {
*reg = 0x59; *reg = 0x59;
*msk = 0x08; *msk = 0x08;
} else { } else {
*reg = 0; *reg = 0;
*msk = 0; *msk = 0;
} }
} }
@ -901,10 +907,10 @@ static void usb_GetLampRegAndMask( u_long flag, SANE_Byte *reg, SANE_Byte *msk )
*/ */
static int usb_GetLampStatus( Plustek_Device *dev ) static int usb_GetLampStatus( Plustek_Device *dev )
{ {
int iLampStatus = 0; int iLampStatus = 0;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
pDCapsDef sc = &dev->usbDev.Caps; DCapsDef *sc = &dev->usbDev.Caps;
SANE_Byte reg, msk, val; SANE_Byte reg, msk, val;
@ -913,28 +919,14 @@ static int usb_GetLampStatus( Plustek_Device *dev )
return -1; return -1;
} }
#if 0
/* on the CanoScan D660U switch always... */
if((dev->usbDev.vendor == 0x04A9) && (dev->usbDev.product==0x2208)) {
DBG( _DBG_INFO, "CanoScan D660U -> Lamp is off!!!\n" );
return 0;
}
#endif
/* do we use the misc I/O pins for switching the lamp ? */ /* do we use the misc I/O pins for switching the lamp ? */
if( _WAF_MISC_IO_LAMPS & sc->workaroundFlag ) { if( _WAF_MISC_IO_LAMPS & sc->workaroundFlag ) {
usb_GetLampRegAndMask( sc->lamp, &reg, &msk ); usb_GetLampRegAndMask( sc->lamp, &reg, &msk );
if( 0 == reg ) { if( 0 == reg ) {
#if 0
/* probably not correct, esp. when changing from color to gray...*/
usbio_ReadReg( dev->fd, 0x29, &regs[0x29] );
if( regs[0x29] & 3 )
#else
usbio_ReadReg( dev->fd, 0x29, &reg ); usbio_ReadReg( dev->fd, 0x29, &reg );
if( reg & 3 ) if( reg & 3 )
#endif
iLampStatus |= DEV_LampReflection; iLampStatus |= DEV_LampReflection;
} else { } else {
@ -957,10 +949,9 @@ static int usb_GetLampStatus( Plustek_Device *dev )
} }
if((dev->usbDev.vendor == 0x04A9) && (dev->usbDev.product==0x2208)) { if((dev->usbDev.vendor == 0x04A9) && (dev->usbDev.product==0x2208)) {
/* DBG( _DBG_INFO, "CanoScan D660U -> Lamp is off!!! (STATUS=%i)\n", iLampStatus );*/
sanei_lm983x_read( dev->fd, 0x29, &regs[0x29], 3, SANE_TRUE ); sanei_lm983x_read( dev->fd, 0x29, &regs[0x29], 3, SANE_TRUE );
DBG( _DBG_INFO, "[29]=0x%02x, [2A]=0x%02x, [2B]=0x%02x\n", regs[0x29], regs[0x2a], regs[0x2b] ); DBG( _DBG_INFO, "[29]=0x%02x, [2A]=0x%02x, [2B]=0x%02x\n",
/*return 0;*/ regs[0x29], regs[0x2a], regs[0x2b] );
} }
} }
} else { } else {
@ -973,7 +964,7 @@ static int usb_GetLampStatus( Plustek_Device *dev )
if(!_IS_PLUSTEKMOTOR(hw->motorModel)) { if(!_IS_PLUSTEKMOTOR(hw->motorModel)) {
iLampStatus |= DEV_LampReflection; iLampStatus |= DEV_LampReflection;
} else { } else {
if((regs[0x2e] * 256 + regs[0x2f]) > hw->wLineEnd ) if((regs[0x2e] * 256 + regs[0x2f]) > hw->wLineEnd )
iLampStatus |= DEV_LampReflection; iLampStatus |= DEV_LampReflection;
@ -995,7 +986,7 @@ static SANE_Bool usb_switchLampX( Plustek_Device *dev,
SANE_Bool on, SANE_Bool tpa ) SANE_Bool on, SANE_Bool tpa )
{ {
SANE_Byte reg, msk; SANE_Byte reg, msk;
pDCapsDef sc = &dev->usbDev.Caps; DCapsDef *sc = &dev->usbDev.Caps;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
if( tpa ) if( tpa )
@ -1060,7 +1051,7 @@ static void usb_LedOn( Plustek_Device *dev, SANE_Bool fOn )
*/ */
static void usb_FillLampRegs( Plustek_Device *dev ) static void usb_FillLampRegs( Plustek_Device *dev )
{ {
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
regs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleLow ); regs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleLow );
@ -1087,9 +1078,9 @@ static void usb_FillLampRegs( Plustek_Device *dev )
static SANE_Bool usb_LampOn( Plustek_Device *dev, static SANE_Bool usb_LampOn( Plustek_Device *dev,
SANE_Bool fOn, SANE_Bool fResetTimer ) SANE_Bool fOn, SANE_Bool fResetTimer )
{ {
pDCapsDef sc = &dev->usbDev.Caps; DCapsDef *sc = &dev->usbDev.Caps;
pScanDef scanning = &dev->scanning; ScanDef *scanning = &dev->scanning;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
int iLampStatus = usb_GetLampStatus( dev ); int iLampStatus = usb_GetLampStatus( dev );
int lampId = -1; int lampId = -1;
@ -1223,7 +1214,7 @@ static void usb_ResetRegisters( Plustek_Device *dev )
{ {
int linend; int linend;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
u_char *regs = dev->usbDev.a_bRegs; u_char *regs = dev->usbDev.a_bRegs;
DBG( _DBG_INFO, "RESETTING REGISTERS(%i) - 0x%02x\n", dev->initialized,sizeof(dev->usbDev.a_bRegs)); DBG( _DBG_INFO, "RESETTING REGISTERS(%i) - 0x%02x\n", dev->initialized,sizeof(dev->usbDev.a_bRegs));
@ -1274,7 +1265,18 @@ static void usb_ResetRegisters( Plustek_Device *dev )
DBG( _DBG_INFO2, "SETTING THE MISC I/Os\n" ); DBG( _DBG_INFO2, "SETTING THE MISC I/Os\n" );
memcpy( regs+0x54, &hw->bReg_0x54, 0x5e - 0x54 + 1 ); memcpy( regs+0x54, &hw->bReg_0x54, 0x5e - 0x54 + 1 );
sanei_lm983x_write( dev->fd, 0x59, &regs[0x59], 3, SANE_TRUE );
if( usb_IsCISDevice( dev )) {
/* this sequence seems to be needed at least for the
* CanoScan devices to work properly after power-up
*/
sanei_lm983x_write_byte( dev->fd, 0x5b, regs[0x5b] );
sanei_lm983x_write_byte( dev->fd, 0x59, regs[0x59] );
sanei_lm983x_write_byte( dev->fd, 0x5a, regs[0x5a] );
} else {
sanei_lm983x_write( dev->fd, 0x59, &regs[0x59], 3, SANE_TRUE );
}
} }
DBG( _DBG_INFO, "MISC I/O after RESET: 0x%02x, 0x%02x, 0x%02x\n", DBG( _DBG_INFO, "MISC I/O after RESET: 0x%02x, 0x%02x, 0x%02x\n",
regs[0x59], regs[0x5a], regs[0x5b] ); regs[0x59], regs[0x5a], regs[0x5b] );
@ -1285,7 +1287,7 @@ static void usb_ResetRegisters( Plustek_Device *dev )
static SANE_Bool usb_ModuleStatus( Plustek_Device *dev ) static SANE_Bool usb_ModuleStatus( Plustek_Device *dev )
{ {
u_char value; u_char value;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
/* HEINER: Maybe needed to avoid recalibration!!! */ /* HEINER: Maybe needed to avoid recalibration!!! */
#if 0 #if 0
@ -1462,7 +1464,7 @@ static SANE_Bool usb_Wait4Warmup( Plustek_Device *dev )
u_long dw; u_long dw;
struct timeval t; struct timeval t;
pHWDef hw = &dev->usbDev.HwSetting; HWDef *hw = &dev->usbDev.HwSetting;
if( hw->bReg_0x26 & _ONE_CH_COLOR ) { if( hw->bReg_0x26 & _ONE_CH_COLOR ) {
DBG(_DBG_INFO,"Warmup: skipped for CIS devices\n" ); DBG(_DBG_INFO,"Warmup: skipped for CIS devices\n" );
@ -1564,9 +1566,10 @@ static SANE_Bool usb_UpdateButtonStatus( Plustek_Scanner *s )
int i, j, bc; int i, j, bc;
int handle = -1; int handle = -1;
SANE_Status status; SANE_Status status;
Plustek_Device *dev = s->hw; Plustek_Device *dev = s->hw;
DCapsDef *caps = &dev->usbDev.Caps;
if (dev->usbDev.Caps.bButtons == 0) if (caps->bButtons == 0)
return SANE_FALSE; return SANE_FALSE;
status = sanei_access_lock( dev->sane.name, 3 ); status = sanei_access_lock( dev->sane.name, 3 );
@ -1593,25 +1596,57 @@ static SANE_Bool usb_UpdateButtonStatus( Plustek_Scanner *s )
/* first read clears the status... */ /* first read clears the status... */
usbio_ReadReg( dev->fd, 0x02, &val ); usbio_ReadReg( dev->fd, 0x02, &val );
val >>= 2;
bc = 0;
for( i = 0; i < 3; i++ ) { /* Plustek and KYE/Genius use altnernative button handling */
if((dev->usbDev.vendor == 0x07B3) || (dev->usbDev.vendor == 0x0458)) {
DBG( _DBG_INFO2, "Checking MISC IO[%u]=0x%02x\n", i, mio[i] ); /* no button pressed so far */
mask = 0x01; for( i = 0; i < caps->bButtons; i++ )
s->val[OPT_BUTTON_0 + i].w = 0;
for( j = 0; j < 2; j++ ) { if (caps->bButtons == 2 || caps->bButtons == 5) {
val >>= 2;
if((mio[i] & mask) == 0) { switch( val ) {
DBG( _DBG_INFO2, "* port %u configured as input," case 1: s->val[OPT_BUTTON_1].w = 1; break;
" status: %s (%u)\n", (i*2)+j+1, case 2: s->val[OPT_BUTTON_0].w = 1; break;
((val & 1)?"PRESSED":"RELEASED"), (OPT_BUTTON_0 + bc)); case 3: s->val[OPT_BUTTON_2].w = 1; break;
s->val[OPT_BUTTON_0 + bc].w = val & 1; case 4: s->val[OPT_BUTTON_3].w = 1; break;
bc++; case 6: s->val[OPT_BUTTON_4].w = 1; break;
}
} else if (caps->bButtons == 4 ) {
val >>= 5;
switch( val ) {
case 1: s->val[OPT_BUTTON_0].w = 1; break;
case 2: s->val[OPT_BUTTON_1].w = 1; break;
case 4: s->val[OPT_BUTTON_2].w = 1; break;
case 6: s->val[OPT_BUTTON_3].w = 1; break;
}
}
} else {
/* the generic section... */
val >>= 2;
bc = 0;
for( i = 0; i < 3; i++ ) {
DBG( _DBG_INFO2, "Checking MISC IO[%u]=0x%02x\n", i, mio[i] );
mask = 0x01;
for( j = 0; j < 2; j++ ) {
if((mio[i] & mask) == 0) {
DBG( _DBG_INFO2, "* port %u configured as input,"
" status: %s (%u)\n", (i*2)+j+1,
((val & 1)?"PRESSED":"RELEASED"), (OPT_BUTTON_0 + bc));
s->val[OPT_BUTTON_0 + bc].w = val & 1;
bc++;
}
val >>= 1;
mask <<= 4;
} }
val >>= 1;
mask <<= 4;
} }
} }
} else { } else {