/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the hardware driver scanners using a 300dpi CCD */ #include "../include/sane/config.h" #if defined(HAVE_STDLIB_H) # include #endif #include #include #if defined(HAVE_STRING_H) # include #elif defined(HAVE_STRINGS_H) # include #endif #include #if defined(HAVE_UNISTD_H) # include #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_pa4s2.h" #define DEBUG_DECLARE_ONLY #include "mustek_pp.h" #include "mustek_pp_decl.h" #include "mustek_pp_ccd300.h" /* A4SII300 driver */ static unsigned char ChannelCode[] = { 0x82, 0x42, 0xc2 }; static unsigned char ChannelCode_1015[] = { 0x80, 0x40, 0xc0 }; static unsigned char MotorPhase[] = { 0x09, 0x0c, 0x06, 0x03 }; static unsigned char MotorPhase_HalfStep[] = { 0x01, 0x09, 0x08, 0x0c, 0x04, 0x06, 0x02, 0x03 }; static SANE_Status ParRead (mustek_pp_ccd300_priv * dev) { unsigned char ASICId; Switch_To_Scanner (dev); ASICId = ReadID1 (0, dev); Switch_To_Printer (dev); if (ASICId != 0xA8 && ASICId != 0xA5) return SANE_STATUS_INVAL; else return SANE_STATUS_GOOD; } static void Switch_To_Scanner (mustek_pp_ccd300_priv * dev) { sanei_pa4s2_enable (dev->fd, SANE_TRUE); } static void Switch_To_Printer (mustek_pp_ccd300_priv * dev) { sanei_pa4s2_enable (dev->fd, SANE_FALSE); } static void LampPowerOn (mustek_pp_ccd300_priv * dev) { LampOnOP (dev); } static void LampOnOP (mustek_pp_ccd300_priv * dev) { int btLoop; dev->m_wMotorStepNo = 1; SetLed_OnOff (dev); OutChar (6, 0xC3, dev); for (btLoop = 0; btLoop < 3; btLoop++) { OutChar (6, 0x47, dev); OutChar (6, 0x77, dev); } } static void LampPowerOff (mustek_pp_ccd300_priv * dev) { LampOffOP (dev); } static void LampOffOP (mustek_pp_ccd300_priv * dev) { int btLoop; dev->m_wMotorStepNo = 0; SetLed_OnOff (dev); OutChar (6, 0xC3, dev); for (btLoop = 0; btLoop < 3; btLoop++) { OutChar (6, 0x57, dev); OutChar (6, 0x77, dev); } } static void SetCCDInfo (mustek_pp_ccd300_priv * dev) { dev->CCD_Type = CheckCCD_Kind (dev); SetCCDDPI (dev); if (dev->IsGa1013) { SetCCDMode (dev); SetCCDInvert (dev); } else { dev->ImageCtrl = 0; dev->DataValue = dev->ImageCtrl; SetCCDMode_1015 (dev); SetCCDInvert_1015 (dev); OutChar (6, 0xf6, dev); OutChar (6, 0x23, dev); OutChar (5, 0x00, dev); OutChar (6, 0x43, dev); if (dev->CCD_Type == 1) OutChar (5, 0x6b, dev); else if (dev->CCD_Type == 4) OutChar (5, 0x9f, dev); else OutChar (5, 0x92, dev); OutChar (6, 0x03, dev); } OutChar (6, 0x37, dev); ClearBankCount (dev); OutChar (6, 0x27, dev); OutChar (6, 0x67, dev); OutChar (6, 0x17, dev); OutChar (6, 0x77, dev); SetDummyCount (dev); OutChar (6, 0x81, dev); if (!dev->IsGa1013) { if (dev->CCD_Type == 1) OutChar (5, 0x90, dev); else if (dev->CCD_Type == 4) OutChar (5, 0xA8, dev); else OutChar (5, 0x8A, dev); } else OutChar (5, 0x70, dev); OutChar (6, 0x01, dev); SetScanByte (dev); } static void SetCCDDPI (mustek_pp_ccd300_priv * dev) { unsigned char ucRes = 0x00; OutChar (6, 0x80, dev); switch (dev->ASICResolution) { case 100: if (dev->CCD_Type == 1) ucRes = 0x01; else ucRes = 0x00; break; case 200: if (dev->CCD_Type == 1) ucRes = 0x11; else ucRes = 0x10; break; case 300: if (dev->CCD_Type == 1) ucRes = 0x21; else ucRes = 0x20; break; } OutChar (5, ucRes, dev); OutChar (6, 0x00, dev); } static void SetCCDMode (mustek_pp_ccd300_priv * dev) { unsigned char ucMode = 0x00; switch (dev->ScanMode) { case 0: ucMode = 0x15; dev->RGBChannel = 1; break; case 1: dev->RGBChannel = 1; ucMode = 0x05; break; case 2: dev->RGBChannel = 0; ucMode = 0x05; break; } OutChar (6, ucMode, dev); SetCCD_Channel (dev); } static void SetCCDMode_1015 (mustek_pp_ccd300_priv * dev) { switch (dev->ScanMode) { case 0: dev->ImageCtrl = 0x24; dev->RGBChannel = 1; break; case 1: dev->ImageCtrl = 0x04; dev->RGBChannel = 1; break; case 2: dev->ImageCtrl = 0x04; dev->RGBChannel = 0; break; } dev->DataValue = dev->ImageCtrl; SetCCD_Channel (dev); } static void SetCCDInvert_1015 (mustek_pp_ccd300_priv * dev) { dev->ImageCtrl &= 0xe4; dev->DataValue = dev->ImageCtrl; if (dev->PixelFlavor == 1) dev->ImageCtrl |= 0x14; dev->DataValue = dev->ImageCtrl; OutChar (6, dev->ImageCtrl, dev); } static void SetPixelAverage (mustek_pp_ccd300_priv * dev) { OutChar (6, 0x15, dev); } static void SetCCD_Channel_WriteSRAM (mustek_pp_ccd300_priv * dev) { unsigned char ucChannelCode; ucChannelCode = ChannelCode[dev->RGBChannel]; ucChannelCode |= 0x22; OutChar (6, ucChannelCode, dev); } static void SetCCD_Channel (mustek_pp_ccd300_priv * dev) { unsigned char ucChannelCode; if (dev->IsGa1013) { ucChannelCode = ChannelCode[dev->RGBChannel]; OutChar (6, ucChannelCode, dev); } else { dev->ImageCtrl &= 0x34; dev->DataValue = dev->ImageCtrl; ucChannelCode = ChannelCode_1015[dev->RGBChannel]; dev->DataValue = ucChannelCode; dev->ImageCtrl |= ucChannelCode; dev->DataValue = dev->ImageCtrl; OutChar (6, dev->ImageCtrl, dev); } } static void SetCCDInvert (mustek_pp_ccd300_priv * dev) { if (dev->PixelFlavor == 1) OutChar (6, 0x14, dev); else OutChar (6, 0x04, dev); } static void ClearBankCount (mustek_pp_ccd300_priv * dev) { OutChar (6, 0x07, dev); } static void SetDummyCount (mustek_pp_ccd300_priv * dev) { unsigned char ucTotalDummy; unsigned int wTotalSkipCount; OutChar (6, 0x41, dev); wTotalSkipCount = dev->SkipCount + dev->Skip_ImageBytes; dev->m_wByteCount = dev->Skip_ImageBytes; if (dev->IsGa1013) { ucTotalDummy = (unsigned char) (wTotalSkipCount / 16); dev->DataValue = ucTotalDummy; ucTotalDummy = ucTotalDummy + 2; dev->DataValue = ucTotalDummy; dev->SkipCount = wTotalSkipCount % 16; dev->m_wByteCount = dev->SkipCount; OutChar (5, ucTotalDummy, dev); } else { ucTotalDummy = (unsigned char) (wTotalSkipCount / 32); ucTotalDummy = (ucTotalDummy + 2) / 2; dev->SkipCount = wTotalSkipCount % 32; OutChar (5, ucTotalDummy, dev); } OutChar (6, 0x01, dev); } static void SetScanByte (mustek_pp_ccd300_priv * dev) { unsigned int wASICScanBytes, wTmp; unsigned char ucSetRegBytes; dev->Scan_Bytes = CalScanParameter (dev->ASICResolution, dev->Scan_Bytes); dev->SkipCount = CalScanParameter (dev->ASICResolution, dev->SkipCount); wASICScanBytes = dev->Scan_Bytes + dev->SkipCount; OutChar (6, 0x11, dev); wTmp = wASICScanBytes; ucSetRegBytes = (unsigned char) (wTmp >> 8); OutChar (5, ucSetRegBytes, dev); OutChar (6, 0x21, dev); ucSetRegBytes = (unsigned char) wASICScanBytes; OutChar (5, ucSetRegBytes, dev); OutChar (6, 0x01, dev); } static void SetRGBRefVoltage (mustek_pp_ccd300_priv * dev) { dev->CCD_Type = CheckCCD_Kind (dev); if (dev->CCD_Type == 4) { OutChar (6, 0x10, dev); OutChar (5, 180, dev); OutChar (6, 0x20, dev); OutChar (5, 180, dev); OutChar (6, 0x40, dev); OutChar (5, 180, dev); } else if (dev->CCD_Type == 1) { OutChar (6, 0x10, dev); OutChar (5, 230, dev); OutChar (6, 0x20, dev); OutChar (5, 180, dev); OutChar (6, 0x40, dev); OutChar (5, 190, dev); } else { OutChar (6, 0x10, dev); OutChar (5, 92, dev); OutChar (6, 0x20, dev); OutChar (5, 90, dev); OutChar (6, 0x40, dev); OutChar (5, 99, dev); } OutChar (6, 0x00, dev); } static void SetLed_OnOff (mustek_pp_ccd300_priv * dev) { unsigned int wModNo; wModNo = dev->m_wMotorStepNo % 5; if (wModNo == 0) OutChar (6, 0x03, dev); else OutChar (6, 0x13, dev); } void OutChar (unsigned char RegNo, unsigned char OutData, mustek_pp_ccd300_priv * dev) { sanei_pa4s2_writebyte (dev->fd, RegNo, OutData); } unsigned char Read_a_Byte (mustek_pp_ccd300_priv * dev, unsigned char RegNo) { unsigned char Data; InChar_Begin_Dispatch (dev->PM, dev, RegNo); Data = InChar_Do_Dispatch (dev->PM, dev); InChar_End_Dispatch (dev->PM, dev); return (Data); } /*ARGSUSED*/ void InChar_Begin_Dispatch (unsigned char Mode __UNUSED__, mustek_pp_ccd300_priv * dev, unsigned char RegNo) { sanei_pa4s2_readbegin (dev->fd, RegNo); } /*ARGSUSED*/ unsigned char InChar_Do_Dispatch (unsigned char Mode __UNUSED__, mustek_pp_ccd300_priv * dev) { unsigned char val; sanei_pa4s2_readbyte (dev->fd, &val); return val; } /*ARGSUSED*/ void InChar_End_Dispatch (unsigned char Mode __UNUSED__, mustek_pp_ccd300_priv * dev) { sanei_pa4s2_readend (dev->fd); } unsigned char Change_Mode (mustek_pp_ccd300_priv * dev) { unsigned char ID; ID = ReadID1 (0, dev); if (ID == 0xA8) dev->IsGa1013 = 1; if (ID == 0xA5) dev->IsGa1013 = 0; dev->PM = 0; return ID; } unsigned char ReadID1 (unsigned char Mode, mustek_pp_ccd300_priv * dev) { unsigned char ID; InChar_Begin_Dispatch (Mode, dev, 0); ID = InChar_Do_Dispatch (Mode, dev); InChar_End_Dispatch (Mode, dev); return (ID); } void CheckMotorSatus (mustek_pp_ccd300_priv * dev) { unsigned char ucDataValue; while (1) { ucDataValue = Read_a_Byte (dev, 2); ucDataValue &= 0x08; if (ucDataValue == 0) break; } } void CheckPIPStatus (mustek_pp_ccd300_priv * dev) { unsigned char ucOldPM, ucDataValue; ucOldPM = dev->PM; dev->PM = 0; ucDataValue = Read_a_Byte (dev, 2); if (dev->IsGa1013) { ucDataValue &= 0x01; } else { ucDataValue >>= 1; ucDataValue ^= 0xff; ucDataValue &= 0x01; } dev->AtHomeSensor = (unsigned int) ucDataValue; dev->PM = ucOldPM; } unsigned char GetBankCount (mustek_pp_ccd300_priv * dev) { unsigned char ucDataValue; ucDataValue = Read_a_Byte (dev, 3); ucDataValue &= 0x07; return ucDataValue; } unsigned char CheckCCDBit (mustek_pp_ccd300_priv * dev) { unsigned char ucDataValue; ucDataValue = Read_a_Byte (dev, 2); ucDataValue &= 0x04; if (ucDataValue == 0) ucDataValue = 8; else ucDataValue = 10; return ucDataValue; } unsigned char CheckCCD_Kind (mustek_pp_ccd300_priv * dev) { unsigned char ucDataValue; ucDataValue = Read_a_Byte (dev, 2); if (dev->IsGa1013) { ucDataValue &= 0x04; } else { ucDataValue &= 0x05; } return ucDataValue; } void WaitBankCountChange (mustek_pp_ccd300_priv * dev) { unsigned char ucASICBCValue; int test0r=100; while (test0r--) { ucASICBCValue = GetBankCount (dev); if (ucASICBCValue == dev->bankcountValue) break; } } void GetDeviceInfo (mustek_pp_ccd300_priv * dev) { unsigned char ucID1; ucID1 = Change_Mode (dev); if (ucID1 != 0xA8 && ucID1 != 0xA5) { dev->PM = 0; ucID1 = ReadID1 (dev->PM, dev); if (ucID1 == 0xA8) dev->IsGa1013 = 1; if (ucID1 == 0xA5) dev->IsGa1013 = 0; } if (ucID1 != 0xA8 && ucID1 != 0xA5) dev->ErrorCode = 1; else { dev->ErrorCode = 0; } dev->ScanMode = 2; dev->PixelFlavor = 1; dev->scan_source = 0; dev->Frame_Left = 0; dev->Skip_ImageBytes = dev->Frame_Left; dev->Frame_Right = 1200; dev->Frame_Top = 0; dev->Frame_Bottom = 100; dev->ScanResolution = 300; dev->Scan_Bytes = dev->Total_lineBytes; SetCCDInfo (dev); } /*ARGSUSED*/ void SetScanParameter (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { unsigned char ucDataValue; dev->ErrorCode = 0; dev->Skip_ImageBytes = dev->Frame_Left; if (0 != dev->scan_source && 99 != dev->scan_source) dev->Skip_ImageBytes += 560; SetASICRes (dev); dev->Total_lineBytes = dev->Frame_Right - dev->Frame_Left; dev->Scan_Bytes = dev->Total_lineBytes; dev->Total_Scanlines = dev->Frame_Bottom - dev->Frame_Top; SetCCDInfo (dev); SetRGBRefVoltage (dev); ucDataValue = GetBankCount (dev); dev->bankcountValue = ucDataValue; if (ucDataValue != 0) dev->ErrorCode = 1; } /*ARGSUSED*/ void GetScanParameter (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { dev->Scan_Lines = CalScanParameter (dev->ScanResolution, dev->Total_Scanlines); dev->Scan_Linebytes = CalScanParameter (dev->ScanResolution, dev->Total_lineBytes); } /*ARGSUSED*/ void A4StartScan (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { dev->Total_Scanlines = dev->Scan_Lines; dev->CatchDataFirst = 1; dev->SkipCount = 0; dev->Catch_R_TmpC = 0; dev->Catch_B_TmpC = 0; dev->MotorPhaseStatus = 0; dev->m_wMotorStepNo = 0; IO_FindBlack_Data (dev); } /*ARGSUSED*/ void A4StopScan (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { dev->Catch_R_TmpC = 0; dev->Catch_B_TmpC = 0; dev->SkipCount = 0; dev->Skip_ImageBytes = 0; dev->m_wMotorStepNo = 0; PullCarriage_ToHome (dev); if (dev->IsGa1013) Motor_Off (dev); } /*ARGSUSED*/ void A4CheckScanner_HomeSensor (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { CheckPIPStatus (dev); } /*ARGSUSED*/ void A4CarriageTo_Home (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { LampOnOP (dev); PullCarriage_ToHome (dev); } void PullCarriage_ToHome (mustek_pp_ccd300_priv * dev) { if (dev->IsGa1013) { Motor_BackHome (dev); } else { dev->AtHomeSensor = 0; SetCCDInfo (dev); Asic1015_Motor_Ctrl (dev, 0xc3); } } void Motor_BackHome (mustek_pp_ccd300_priv * dev) { while (1) { CheckPIPStatus (dev); if (dev->AtHomeSensor == 0) break; Backward_onestep (dev); WaitBankCountChange (dev); ClearBankCount (dev); } } /*ARGSUSED*/ void A4GetImage (int DeviceObject __UNUSED__, int Irp __UNUSED__, mustek_pp_ccd300_priv * dev) { if (dev->Total_Scanlines == 0) { dev->txf_lines = dev->Catch_G_Count; return; } switch (dev->ScanMode) { case 2: if (dev->ASICResolution > 100) IO_GetColorData (dev); else IO_GetColorData_100 (dev); break; case 1: case 0: if (dev->ASICResolution > 100) IO_GetGrayData (dev); else IO_GetGrayData_100 (dev); break; } dev->txf_lines = dev->Catch_G_Count; dev->Catch_G_Count = 0; } void SetASICRes (mustek_pp_ccd300_priv * dev) { if (dev->ScanResolution > 100) { if (dev->ScanResolution > 200) { dev->ASICResolution = 300; } else { dev->ASICResolution = 200; } } else { dev->ASICResolution = 100; } } int CalScanParameter (int wResolution, int wPar) { switch (wResolution) { case 50: wPar = wPar / 6; break; case 100: wPar = wPar / 3; break; case 150: wPar = wPar / 2; break; case 200: wPar = wPar * 2 / 3; break; case 250: wPar = wPar * 5 / 6; break; default: break; } return wPar; } void Forward_onestep (mustek_pp_ccd300_priv * dev) { unsigned char ucPhase; dev->m_wMotorStepNo++; SetLed_OnOff (dev); if (dev->IsGa1013) { SetCCD_Channel_WriteSRAM (dev); ucPhase = MotorPhase[dev->MotorPhaseStatus]; if (dev->MotorPhaseStatus >= 3) dev->MotorPhaseStatus = 0; else dev->MotorPhaseStatus++; OutChar (5, ucPhase, dev); } else { Asic1015_Motor_Ctrl (dev, 0x1b); } SetCCD_Channel (dev); SetSTI (dev); } void Backward_onestep (mustek_pp_ccd300_priv * dev) { unsigned char ucPhase; dev->m_wMotorStepNo++; SetLed_OnOff (dev); if (dev->IsGa1013) { SetCCD_Channel_WriteSRAM (dev); ucPhase = MotorPhase[dev->MotorPhaseStatus]; if (dev->MotorPhaseStatus == 0) dev->MotorPhaseStatus = 3; else dev->MotorPhaseStatus--; OutChar (5, ucPhase, dev); SetCCD_Channel (dev); SetSTI (dev); } else { Asic1015_Motor_Ctrl (dev, 0x43); } } void Asic1015_Motor_Ctrl (mustek_pp_ccd300_priv * dev, unsigned char ucMotorCtrl) { OutChar (6, 0xf6, dev); OutChar (6, 0x22, dev); OutChar (5, ucMotorCtrl, dev); OutChar (6, 0x02, dev); CheckMotorSatus (dev); } void Delay_nTimes_mSec (unsigned int wTimes) { unsigned int wmSec, wLoop; wmSec = wTimes * 100; for (wLoop = 0; wLoop < wTimes; wLoop++) usleep (100); } void SetSTI (mustek_pp_ccd300_priv * dev) { OutChar (3, 0x00, dev); dev->bankcountValue++; dev->bankcountValue &= 0x07; } void Motor_StepLoop (mustek_pp_ccd300_priv * dev, unsigned char ucForBackFlag, unsigned int wStepNo) { unsigned int wMotorStepNo; for (wMotorStepNo = 0; wMotorStepNo < wStepNo; wMotorStepNo++) { if (ucForBackFlag == 0) Forward_onestep (dev); else Backward_onestep (dev); WaitBankCountChange (dev); ClearBankCount (dev); } } void Motor_Off (mustek_pp_ccd300_priv * dev) { unsigned char ucDataValue; OutChar (6, 0x22, dev); OutChar (5, 0x00, dev); OutChar (6, 0x82, dev); ucDataValue = GetBankCount (dev); dev->bankcountValue = ucDataValue; SetSTI (dev); WaitBankCountChange (dev); ClearBankCount (dev); dev->m_wMotorStepNo = 1; SetLed_OnOff (dev); } void Store_Tmp_Data (mustek_pp_ccd300_priv * dev) { dev->ResolutionTmp = dev->ASICResolution; dev->ScanModeTmp = dev->ScanMode; dev->Skip_ImageTmp = dev->Skip_ImageBytes; } void Restore_Tmp_Data (mustek_pp_ccd300_priv * dev) { dev->ASICResolution = dev->ResolutionTmp; dev->ScanMode = dev->ScanModeTmp; dev->Skip_ImageBytes = dev->Skip_ImageTmp; } void IO_FindBlack_Data (mustek_pp_ccd300_priv * dev) { unsigned int MotrStep; Store_Tmp_Data (dev); dev->Real_Scan_Bytes = CalScanParameter (dev->ScanResolution, dev->Total_lineBytes); Check_DataPar (dev); dev->Scan_Bytes = 2550; dev->ASICResolution = 300; dev->ScanMode = 1; dev->Skip_ImageBytes = 0; dev->SkipCount = 0; SetCCDInfo (dev); dev->bankcountValue = GetBankCount (dev); FindHorBlackPos (dev); Restore_Tmp_Data (dev); dev->Scan_Bytes = dev->Total_lineBytes; Motor_StepLoop (dev, 0, 4); dev->SkipCountTmp = dev->SkipCount; GetCalibData (dev); dev->SkipCount = dev->SkipCountTmp; FindVerBlackPos (dev); Restore_Tmp_Data (dev); MotrStep = 47; if (0 != dev->scan_source) { LampOffOP (dev); if (99 != dev->scan_source) { MotrStep += 460; Motor_StepLoop (dev, 0, MotrStep); dev->Scan_Bytes = dev->Total_lineBytes; GetCalibData (dev); MotrStep = 240; } } if (dev->ScanMode != 2) MotrStep += 16; MotrStep += dev->Frame_Top; Motor_StepLoop (dev, 0, MotrStep); RestoreCCDInfo_Set (dev); if (CheckCCD_Kind (dev) == 1) SetPixelAverage (dev); } void CalRefBlack (mustek_pp_ccd300_priv * dev) { dev->RefBlack = 0; dev->SkipCount = 0; dev->Skip_ImageBytes = 0; dev->Scan_Bytes = dev->Total_lineBytes; SetCCDInfo (dev); dev->bankcountValue = GetBankCount (dev); GetRefBlack (dev); dev->Skip_ImageBytes = dev->Skip_ImageTmp; dev->SkipCount = dev->SkipCountTmp; dev->Scan_Bytes = dev->Total_lineBytes; SetCCDInfo (dev); dev->bankcountValue = GetBankCount (dev); } void GetRefBlack (mustek_pp_ccd300_priv * dev) { unsigned char *pucBuf, *pucBufTmp; unsigned int wLoop, wTemp; pucBuf = malloc (2550); pucBufTmp = pucBuf; wTemp = 0; for (wLoop = 0; wLoop < 8; wLoop++) { dev->AbortDataLine = 0; dev->RGBChannel = 0; GetChannelData (dev, pucBuf); wTemp += (unsigned int) (*(pucBufTmp + 3)); } wTemp /= (unsigned int) 8; dev->RefBlack_R = (unsigned char) wTemp; dev->DataValue = dev->RefBlack_R; wTemp = 0; for (wLoop = 0; wLoop < 8; wLoop++) { dev->AbortDataLine = 0; dev->RGBChannel = 1; GetChannelData (dev, pucBuf); wTemp += (unsigned int) (*(pucBufTmp + 3)); } wTemp /= (unsigned int) 8; dev->RefBlack_G = (unsigned char) wTemp; dev->DataValue = dev->RefBlack_G; wTemp = 0; for (wLoop = 0; wLoop < 8; wLoop++) { dev->AbortDataLine = 0; dev->RGBChannel = 2; GetChannelData (dev, pucBuf); wTemp += (unsigned int) (*(pucBufTmp + 3)); } wTemp /= (unsigned int) 8; dev->RefBlack_B = (unsigned char) wTemp; dev->DataValue = dev->RefBlack_B; free (pucBuf); } void RestoreCCDInfo_Set (mustek_pp_ccd300_priv * dev) { dev->Scan_Bytes = dev->Total_lineBytes; dev->Skip_ImageBytes = dev->Skip_ImageTmp; SetCCDInfo (dev); dev->bankcountValue = GetBankCount (dev); } void FindHorBlackPos (mustek_pp_ccd300_priv * dev) { unsigned int wLoop, wCount; unsigned int wByteCount; wCount = 0; wByteCount = sizeof (unsigned char) * 2550; dev->lpFind_black_Buf = malloc (wByteCount); memset (dev->lpFind_black_Buf, 0, wByteCount); for (wLoop = 0; wLoop < 20; wLoop++) { dev->RefBlack = 0; dev->SkipCount = 0; Forward_onestep (dev); WaitBankCountChange (dev); IO_GetData (dev, dev->lpFind_black_Buf); ClearBankCount (dev); FindHBlackPos (dev, dev->lpFind_black_Buf); if (dev->SkipCount > 2) { dev->BubbleSortAry[wCount] = (unsigned char) (dev->SkipCount); wCount++; } if (wCount >= 5) break; } Bubble_Sort_Arg (dev, 5); dev->SkipCount = (unsigned int) (dev->BubbleSortAry[0] + 11); dev->BlackPos = (unsigned int) (dev->BubbleSortAry[0]); free (dev->lpFind_black_Buf); } void FindVerBlackPos (mustek_pp_ccd300_priv * dev) { unsigned int wSkipTmp, wFindVerBkCount; unsigned int wBufSize; wFindVerBkCount = 0; wSkipTmp = dev->SkipCount; dev->Scan_Bytes = 2550; dev->ASICResolution = 300; dev->ScanMode = 1; dev->Skip_ImageBytes = 0; dev->SkipCount = 0; SetCCDInfo (dev); dev->bankcountValue = GetBankCount (dev); dev->DataValue = dev->bankcountValue; wBufSize = sizeof (unsigned char) * 2550; dev->lpFind_black_Buf = malloc (wBufSize); memset (dev->lpFind_black_Buf, 0, wBufSize); while (1) { Forward_onestep (dev); WaitBankCountChange (dev); IO_GetData (dev, dev->lpFind_black_Buf); ClearBankCount (dev); if (!FindVBlackPos (dev, dev->lpFind_black_Buf)) break; wFindVerBkCount++; if (wFindVerBkCount > 76) break; } free (dev->lpFind_black_Buf); dev->SkipCount = wSkipTmp; } static void AllocBuffer (mustek_pp_ccd300_priv * dev) { unsigned long wBufSize; wBufSize = 16 * sizeof (unsigned char) * 2550; dev->lpTmpBuf_R = malloc (wBufSize); memset (dev->lpTmpBuf_R, 0, wBufSize); wBufSize = 8 * sizeof (unsigned char) * 2550; dev->lpTmpBuf_B = malloc (wBufSize); memset (dev->lpTmpBuf_B, 0, wBufSize); wBufSize = 32 * sizeof (unsigned char) * 2550; dev->Calib_Buffer_R = malloc (wBufSize); memset (dev->Calib_Buffer_R, 0, wBufSize); dev->Calib_Buffer_G = malloc (wBufSize); memset (dev->Calib_Buffer_G, 0, wBufSize); dev->Calib_Buffer_B = malloc (wBufSize); memset (dev->Calib_Buffer_B, 0, wBufSize); dev->Calib_Gray_Buf = malloc (wBufSize); memset (dev->Calib_Gray_Buf, 0, wBufSize); } static void FreeBuf (mustek_pp_ccd300_priv * dev) { free (dev->lpTmpBuf_R); free (dev->lpTmpBuf_B); free (dev->Calib_Buffer_R); free (dev->Calib_Buffer_G); free (dev->Calib_Buffer_B); free (dev->Calib_Gray_Buf); } static void IO_GetGrayData (mustek_pp_ccd300_priv * dev) { unsigned int wLineCount; unsigned long dwPtrAddr; unsigned char *lpImagePtr; wLineCount = dev->BufferLine_Count; if (dev->BufferLine_Count > dev->Total_Scanlines) wLineCount = dev->Total_Scanlines; dev->Catch_Count = 0; dev->Catch_G_Count = 0; if (dev->CatchDataFirst) { Forward_onestep (dev); WaitBankCountChange (dev); } while (1) { dev->AbortDataLine = 0; Whether_Skip_One_Line (dev, dev->Catch_Count); Forward_onestep (dev); dev->Catch_Count++; if (!dev->AbortDataLine) { lpImagePtr = dev->ImageBuffer; dwPtrAddr = dev->Catch_G_Count; dwPtrAddr *= dev->Real_Scan_Bytes; lpImagePtr += dwPtrAddr; if (dev->ASICRes == 0) IO_GetData_SPEC (dev, lpImagePtr); else IO_GetData (dev, lpImagePtr); dev->Catch_G_Count++; } ClearBankCount (dev); WaitBankCountChange (dev); if (dev->Catch_G_Count == wLineCount) break; } lpImagePtr = dev->ImageBuffer; CalibrationData_Gray (dev, lpImagePtr); dev->Total_Scanlines -= dev->Catch_G_Count; dev->Catch_Count = 0; dev->CatchDataFirst = 0; } static void IO_GetGrayData_100 (mustek_pp_ccd300_priv * dev) { unsigned int wLineCount; unsigned long dwPtrAddr; unsigned char *lpImagePtr; wLineCount = dev->BufferLine_Count; if (dev->BufferLine_Count > dev->Total_Scanlines) wLineCount = dev->Total_Scanlines; dev->Catch_Count = 0; dev->Catch_G_Count = 0; while (1) { dev->AbortDataLine = 0; Whether_Skip_One_Line (dev, dev->Catch_Count); Forward_onestep (dev); WaitBankCountChange (dev); dev->Catch_Count++; if (!dev->AbortDataLine) { lpImagePtr = dev->ImageBuffer; dwPtrAddr = dev->Catch_G_Count; dwPtrAddr *= dev->Real_Scan_Bytes; lpImagePtr += dwPtrAddr; IO_GetData (dev, lpImagePtr); dev->Catch_G_Count++; } ClearBankCount (dev); if (dev->Catch_G_Count == wLineCount) break; } lpImagePtr = dev->ImageBuffer; CalibrationData_Gray (dev, lpImagePtr); dev->Total_Scanlines -= dev->Catch_G_Count; dev->Catch_Count = 0; dev->CatchDataFirst = 0; } static void IO_GetColorData (mustek_pp_ccd300_priv * dev) { unsigned int wLineCount; unsigned char *lpImagePtr; wLineCount = dev->BufferLine_Count; if (dev->BufferLine_Count > dev->Total_Scanlines) wLineCount = dev->Total_Scanlines; dev->Catch_Count = 0; dev->Catch_R_Count = 0; dev->Catch_G_Count = 0; dev->Catch_B_Count = 0; if (dev->CatchDataFirst) { Forward_onestep (dev); WaitBankCountChange (dev); } else { lpImagePtr = dev->ImageBuffer; MoveR_Tmp_Image_Buffer (dev, lpImagePtr, dev->lpTmpBuf_R); lpImagePtr = dev->ImageBuffer; MoveB_Tmp_Image_Buffer (dev, lpImagePtr, dev->lpTmpBuf_B); } while (1) { dev->RGBChannel = 2; SetCCD_Channel (dev); SetSTI (dev); dev->RGBChannel = 0; Catch_Red_Line (dev); ClearBankCount (dev); WaitBankCountChange (dev); dev->RGBChannel = 1; SetCCD_Channel (dev); SetSTI (dev); dev->RGBChannel = 2; Catch_Blue_Line (dev); ClearBankCount (dev); WaitBankCountChange (dev); dev->RGBChannel = 0; Forward_onestep (dev); dev->RGBChannel = 1; Catch_Green_Line (dev); ClearBankCount (dev); WaitBankCountChange (dev); dev->Catch_Count++; if (dev->Catch_G_Count == wLineCount) break; } lpImagePtr = dev->ImageBuffer; CalibrationData_Color (dev, lpImagePtr); dev->Total_Scanlines -= dev->Catch_G_Count; dev->Catch_Count = 0; dev->CatchDataFirst = 0; } static void IO_GetColorData_100 (mustek_pp_ccd300_priv * dev) { unsigned int wLineCount; unsigned char *lpImagePtr; wLineCount = dev->BufferLine_Count; if (dev->BufferLine_Count > dev->Total_Scanlines) wLineCount = dev->Total_Scanlines; dev->Catch_Count = 0; dev->Catch_R_Count = 0; dev->Catch_G_Count = 0; dev->Catch_B_Count = 0; if (dev->CatchDataFirst) { Forward_onestep (dev); WaitBankCountChange (dev); } else { lpImagePtr = dev->ImageBuffer; MoveR_Tmp_Image_Buffer (dev, lpImagePtr, dev->lpTmpBuf_R); lpImagePtr = dev->ImageBuffer; MoveB_Tmp_Image_Buffer (dev, lpImagePtr, dev->lpTmpBuf_B); } while (1) { dev->RGBChannel = 2; Forward_onestep (dev); dev->RGBChannel = 0; Catch_Red_Line (dev); ClearBankCount (dev); dev->Catch_Count++; WaitBankCountChange (dev); dev->RGBChannel = 1; Forward_onestep (dev); dev->RGBChannel = 2; Catch_Blue_Line (dev); ClearBankCount (dev); dev->Catch_Count++; WaitBankCountChange (dev); dev->RGBChannel = 0; Forward_onestep (dev); dev->RGBChannel = 1; Catch_Green_Line (dev); ClearBankCount (dev); dev->Catch_Count++; WaitBankCountChange (dev); if (dev->ScanResolution == 50) Res50_Go_3_step (dev); if (dev->Catch_G_Count == wLineCount) break; } lpImagePtr = dev->ImageBuffer; CalibrationData_Color (dev, lpImagePtr); dev->Total_Scanlines -= dev->Catch_G_Count; dev->Catch_Count = 0; dev->CatchDataFirst = 0; } static void Res50_Go_3_step (mustek_pp_ccd300_priv * dev) { unsigned int wLoop; dev->RGBChannel = 0; for (wLoop = 0; wLoop < 3; wLoop++) { ClearBankCount (dev); dev->Catch_Count++; Forward_onestep (dev); WaitBankCountChange (dev); } } static void MoveR_Tmp_Image_Buffer (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr, unsigned char * pBufferPtr) { unsigned int wLoop, wLoop1; if (dev->reverse_rgb == 1) pImagePtr += 2; dev->m_wByteCount = dev->Catch_R_TmpC; for (wLoop = 0; wLoop < dev->Catch_R_TmpC; wLoop++) { for (wLoop1 = 0; wLoop1 < dev->Real_Scan_Bytes; wLoop1++) { *pImagePtr = *pBufferPtr; pImagePtr += 3; pBufferPtr++; } dev->Catch_R_Count++; } dev->Catch_R_TmpC = 0; } static void MoveB_Tmp_Image_Buffer (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr, unsigned char * pBufferPtr) { unsigned int wLoop, wLoop1; if (dev->reverse_rgb == 0) pImagePtr += 2; dev->m_wByteCount = dev->Catch_B_TmpC; for (wLoop = 0; wLoop < dev->Catch_B_TmpC; wLoop++) { for (wLoop1 = 0; wLoop1 < dev->Real_Scan_Bytes; wLoop1++) { *pImagePtr = *pBufferPtr; pImagePtr += 3; pBufferPtr++; } dev->Catch_B_Count++; } dev->Catch_B_TmpC = 0; } static void Catch_Red_Line (mustek_pp_ccd300_priv * dev) { unsigned int wBuf_Lines; unsigned long dwPtrAddr; unsigned char *lpImagePtr; dev->AbortDataLine = 0; Whether_Skip_One_Line (dev, dev->Catch_Count); if (dev->AbortDataLine) return; wBuf_Lines = dev->BufferLine_Count - 1; dev->RefBlack = dev->RefBlack_R; if (dev->Catch_R_Count <= wBuf_Lines) { dwPtrAddr = dev->Catch_R_Count * 3; dwPtrAddr = dwPtrAddr * dev->Real_Scan_Bytes; lpImagePtr = dev->ImageBuffer + dwPtrAddr; if (dev->ASICRes == 1) IO_Color_Line (dev, lpImagePtr); else IO_Color_Line_SPEC (dev, lpImagePtr); dev->Catch_R_Count++; } else { dwPtrAddr = dev->Catch_R_TmpC; dwPtrAddr *= dev->Real_Scan_Bytes; lpImagePtr = dev->lpTmpBuf_R + dwPtrAddr; if (dev->ASICRes == 0) IO_GetData_SPEC (dev, lpImagePtr); else IO_GetData (dev, lpImagePtr); dev->Catch_R_TmpC++; } } static void Catch_Blue_Line (mustek_pp_ccd300_priv * dev) { unsigned int wCatch_Count, wBuf_Lines; unsigned long dwPtrAddr; unsigned char *lpImagePtr; unsigned int wLineDiff; if (dev->CCD_Type == 1) wLineDiff = 4; else wLineDiff = 8; dev->AbortDataLine = 1; wCatch_Count = dev->Catch_Count; if (!dev->CatchDataFirst) { dev->AbortDataLine = 0; } else { if (wCatch_Count >= wLineDiff) { dev->AbortDataLine = 0; wCatch_Count -= wLineDiff; } } Whether_Skip_One_Line (dev, wCatch_Count); if (dev->AbortDataLine) return; dev->RefBlack = dev->RefBlack_B; wBuf_Lines = dev->BufferLine_Count - 1; if (dev->Catch_B_Count <= wBuf_Lines) { dwPtrAddr = dev->Catch_B_Count * 3; dwPtrAddr = dwPtrAddr * dev->Real_Scan_Bytes; lpImagePtr = dev->ImageBuffer + dwPtrAddr; if (dev->ASICRes == 1) IO_Color_Line (dev, lpImagePtr); else IO_Color_Line_SPEC (dev, lpImagePtr); dev->Catch_B_Count++; } else { dwPtrAddr = dev->Catch_B_TmpC; dwPtrAddr *= dev->Real_Scan_Bytes; lpImagePtr = dev->lpTmpBuf_B + dwPtrAddr; if (dev->ASICRes == 0) IO_GetData_SPEC (dev, lpImagePtr); else IO_GetData (dev, lpImagePtr); dev->Catch_B_TmpC++; } } static void Catch_Green_Line (mustek_pp_ccd300_priv * dev) { unsigned int wCatch_Count; unsigned long dwPtrAddr; unsigned char *lpImagePtr; unsigned int wLineDiff; if (dev->CCD_Type == 1) wLineDiff = 8; else wLineDiff = 16; dev->AbortDataLine = 1; wCatch_Count = dev->Catch_Count; if (!dev->CatchDataFirst) { dev->AbortDataLine = 0; } else { if (wCatch_Count >= wLineDiff) { dev->AbortDataLine = 0; wCatch_Count -= wLineDiff; } } Whether_Skip_One_Line (dev, wCatch_Count); if (dev->AbortDataLine) return; dev->RefBlack = dev->RefBlack_G; dwPtrAddr = dev->Catch_G_Count * 3; dwPtrAddr = dwPtrAddr * dev->Real_Scan_Bytes; lpImagePtr = dev->ImageBuffer + dwPtrAddr; if (dev->ASICRes == 1) IO_Color_Line (dev, lpImagePtr); else IO_Color_Line_SPEC (dev, lpImagePtr); dev->Catch_G_Count++; } static void IO_GetData (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wByteCount; InChar_Begin_Dispatch (dev->PM, dev, 1); IO_SkipData (dev); for (wByteCount = 0; wByteCount < dev->Scan_Bytes; wByteCount++) { dev->DataValue = InChar_Do_Dispatch (dev->PM, dev); usleep (100); dev->DataValue = SubRefBlack (dev, dev->DataValue); *pImagePtr = dev->DataValue; pImagePtr++; } InChar_End_Dispatch (dev->PM, dev); } static void IO_GetData_SPEC (mustek_pp_ccd300_priv * dev, unsigned char *pImagePtr) { unsigned int wByteCount; InChar_Begin_Dispatch (dev->PM, dev, 1); IO_SkipData (dev); for (wByteCount = 0; wByteCount < dev->Scan_Bytes; wByteCount++) { dev->DataValue = InChar_Do_Dispatch (dev->PM, dev); usleep (100); if ((wByteCount % dev->Data_Get_Multi) != 0) { dev->DataValue = SubRefBlack (dev, dev->DataValue); *pImagePtr = dev->DataValue; pImagePtr++; } } InChar_End_Dispatch (dev->PM, dev); } static void IO_Color_Line (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wLoop; switch (dev->RGBChannel) { case 0: if (dev->reverse_rgb == 1) pImagePtr += 2; break; case 1: pImagePtr++; break; case 2: if (dev->reverse_rgb == 0) pImagePtr += 2; break; } InChar_Begin_Dispatch (dev->PM, dev, 1); IO_SkipData (dev); for (wLoop = 0; wLoop < dev->Scan_Bytes; wLoop++) { dev->DataValue = InChar_Do_Dispatch (dev->PM, dev); usleep (100); dev->DataValue = SubRefBlack (dev, dev->DataValue); *pImagePtr = dev->DataValue; pImagePtr += 3; } InChar_End_Dispatch (dev->PM, dev); } static void IO_Color_Line_SPEC (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wByteCount; switch (dev->RGBChannel) { case 0: if (dev->reverse_rgb == 1) pImagePtr += 2; break; case 1: pImagePtr++; break; case 2: if (dev->reverse_rgb == 0) pImagePtr += 2; break; } InChar_Begin_Dispatch (dev->PM, dev, 1); IO_SkipData (dev); for (wByteCount = 0; wByteCount < dev->Scan_Bytes; wByteCount++) { dev->DataValue = InChar_Do_Dispatch (dev->PM, dev); usleep (100); if ((wByteCount % dev->Data_Get_Multi) != 0) { dev->DataValue = SubRefBlack (dev, dev->DataValue); *pImagePtr = dev->DataValue; pImagePtr += 3; } } InChar_End_Dispatch (dev->PM, dev); } static void IO_SkipData (mustek_pp_ccd300_priv * dev) { unsigned int wLoop, wSkipCount; wSkipCount = dev->SkipCount + 1; for (wLoop = 0; wLoop < wSkipCount; wLoop++) { InChar_Do_Dispatch (dev->PM, dev); } } static void Check_DataPar (mustek_pp_ccd300_priv * dev) { dev->ASICRes = 1; switch (dev->ScanResolution) { case 50: dev->Data_Get_Multi = 2; dev->ASICRes = 0; break; case 150: dev->Data_Get_Multi = 4; dev->ASICRes = 0; break; case 250: dev->Data_Get_Multi = 6; dev->ASICRes = 0; break; default: break; } } static void Whether_Skip_One_Line (mustek_pp_ccd300_priv * dev, int wCatch_Count) { switch (dev->ScanResolution) { case 100: if (dev->ScanMode == 2) { if (dev->CCD_Type == 1) Chk_Color_100_Abort_3794 (dev, wCatch_Count); else Chk_Color_100_Abort (dev, wCatch_Count); } else { if ((wCatch_Count % 3) != 0) dev->AbortDataLine = 1; } break; case 150: if ((wCatch_Count % 2) == 1) dev->AbortDataLine = 1; break; case 200: if ((wCatch_Count % 3) == 2) dev->AbortDataLine = 1; break; case 250: if ((wCatch_Count % 6) == 2) dev->AbortDataLine = 1; break; default: break; } } static void Chk_Color_100_Abort (mustek_pp_ccd300_priv * dev, int wCatch_Count) { unsigned int wModNo; wModNo = wCatch_Count % 3; switch (dev->RGBChannel) { case 0: if (wModNo != 0) dev->AbortDataLine = 1; break; case 1: if (dev->CatchDataFirst) { if (wModNo != 1) dev->AbortDataLine = 1; } else { if (wModNo != 2) dev->AbortDataLine = 1; } break; case 2: if (dev->CatchDataFirst) { if (wModNo != 2) dev->AbortDataLine = 1; } else { if (wModNo != 1) dev->AbortDataLine = 1; } break; } } static void Chk_Color_100_Abort_3794 (mustek_pp_ccd300_priv * dev, int wCatch_Count) { unsigned int wModNo; wModNo = wCatch_Count % 3; switch (dev->RGBChannel) { case 0: if (wModNo != 0) dev->AbortDataLine = 1; break; case 1: if (dev->CatchDataFirst) { if (wModNo != 0) dev->AbortDataLine = 1; } else { if (wModNo != 2) dev->AbortDataLine = 1; } break; case 2: if (dev->CatchDataFirst) { if (wModNo != 0) dev->AbortDataLine = 1; } else { if (wModNo != 1) dev->AbortDataLine = 1; } break; } } /*ARGSUSED*/ static void Delay_Motor_Times (mustek_pp_ccd300_priv * dev __UNUSED__, unsigned long lgScanTime) { unsigned long lgTimes; unsigned long dwScanTime; unsigned int wScanTime; lgTimes = lgScanTime / 10000; dwScanTime = lgTimes; if (dwScanTime < 2) return; if (dwScanTime < 5) { return; } if (dwScanTime < 12) { wScanTime = (unsigned int) (12 - dwScanTime); } } static void GetCalibData (mustek_pp_ccd300_priv * dev) { unsigned long dwLoop; unsigned char *pCalibPtr; SetCCDInfo (dev); dev->bankcountValue = GetBankCount (dev); if ((dev->ScanMode == 2) && (CheckCCD_Kind (dev) != 0)) CalRefBlack (dev); for (dwLoop = 0; dwLoop < 32; dwLoop++) { if (dev->ScanMode != 2) { pCalibPtr = dev->Calib_Gray_Buf + dev->Real_Scan_Bytes * dwLoop; Forward_onestep (dev); Get_Line_ntimes (dev, pCalibPtr); } else { pCalibPtr = dev->Calib_Buffer_R + dev->Real_Scan_Bytes * dwLoop; dev->RGBChannel = 0; Forward_onestep (dev); dev->RefBlack = dev->RefBlack_R; Get_Line_ntimes (dev, pCalibPtr); pCalibPtr = dev->Calib_Buffer_G + dev->Real_Scan_Bytes * dwLoop; dev->RGBChannel = 1; SetCCD_Channel (dev); SetSTI (dev); dev->RefBlack = dev->RefBlack_G; Get_Line_ntimes (dev, pCalibPtr); pCalibPtr = dev->Calib_Buffer_B + dev->Real_Scan_Bytes * dwLoop; dev->RGBChannel = 2; SetCCD_Channel (dev); SetSTI (dev); dev->RefBlack = dev->RefBlack_B; Get_Line_ntimes (dev, pCalibPtr); } } if (dev->ScanMode != 2) { pCalibPtr = dev->Calib_Gray_Buf; GetMaxData (dev, pCalibPtr); } else { pCalibPtr = dev->Calib_Buffer_R; GetMaxData (dev, pCalibPtr); pCalibPtr = dev->Calib_Buffer_G; GetMaxData (dev, pCalibPtr); pCalibPtr = dev->Calib_Buffer_B; GetMaxData (dev, pCalibPtr); } } static void GetChannelData (mustek_pp_ccd300_priv * dev, unsigned char * pucBuf) { SetCCD_Channel (dev); SetSTI (dev); WaitBankCountChange (dev); if (dev->ASICRes == 0) IO_GetData_SPEC (dev, pucBuf); else IO_GetData (dev, pucBuf); ClearBankCount (dev); } static void GetMaxData (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wLoop, wLoop1; unsigned long wJumpPointer; unsigned int wTemp; for (wLoop = 0; wLoop < dev->Real_Scan_Bytes; wLoop++) { for (wLoop1 = 0; wLoop1 < 32; wLoop1++) { wJumpPointer = (unsigned long) wLoop1 *dev->Real_Scan_Bytes; dev->BubbleSortAry[wLoop1] = *(pImagePtr + wJumpPointer); } Bubble_Sort_Arg (dev, 32); wTemp = (unsigned int) dev->BubbleSortAry[4]; wTemp += (unsigned int) dev->BubbleSortAry[5]; wTemp += (unsigned int) dev->BubbleSortAry[6]; wTemp += (unsigned int) dev->BubbleSortAry[7]; wTemp /= (unsigned int) 4; *pImagePtr = (unsigned char) wTemp; pImagePtr++; } } static void Get_Line_ntimes (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned char *pucCalib_Buf, *pCalibPtr; unsigned long dwLoop; unsigned long wBufSize; pCalibPtr = 0; wBufSize = 4 * sizeof (unsigned char) * dev->Real_Scan_Bytes; pucCalib_Buf = malloc (wBufSize); memset (pucCalib_Buf, 0, wBufSize); for (dwLoop = 0; dwLoop < 4; dwLoop++) { pCalibPtr = pucCalib_Buf + dev->Real_Scan_Bytes * dwLoop; WaitBankCountChange (dev); if (dev->ASICRes == 0) IO_GetData_SPEC (dev, pCalibPtr); else IO_GetData (dev, pCalibPtr); ClearBankCount (dev); if (dwLoop < 3) SetSTI (dev); } Average_Data (dev, pucCalib_Buf, pImagePtr); free (pucCalib_Buf); } static void Average_Data (mustek_pp_ccd300_priv * dev, unsigned char * pInImagePtr, unsigned char * pOutImagePtr) { unsigned int wLoop, wJumpPointer; unsigned int wAvgSum; for (wLoop = 0; wLoop < dev->Real_Scan_Bytes; wLoop++) { wJumpPointer = 0; wAvgSum = *pInImagePtr; wJumpPointer += dev->Real_Scan_Bytes; wAvgSum += *(pInImagePtr + wJumpPointer); wJumpPointer += dev->Real_Scan_Bytes; wAvgSum += *(pInImagePtr + wJumpPointer); wJumpPointer += dev->Real_Scan_Bytes; wAvgSum += *(pInImagePtr + wJumpPointer); wAvgSum /= 4; *pOutImagePtr = (unsigned char) wAvgSum; pInImagePtr++; pOutImagePtr++; } } static void FindHBlackPos (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned char *pImagePtrTmp; unsigned int wByteCount, wLoop; wByteCount = dev->Scan_Bytes / 4; dev->RefBlack = *pImagePtr; dev->RefBlack_R = *pImagePtr; dev->RefBlack_G = *pImagePtr; dev->RefBlack_B = *pImagePtr; pImagePtrTmp = pImagePtr; pImagePtr = pImagePtr + wByteCount; for (wLoop = wByteCount; wLoop > 0; wLoop--) { if (ABSCompute (*pImagePtr, dev->RefBlack) < 15) break; pImagePtr--; } dev->SkipCount = wLoop; pImagePtr = pImagePtrTmp; } static int FindVBlackPos (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wBkPos, wFindBkCount; pImagePtr = pImagePtr + dev->BlackPos; wFindBkCount = 0; for (wBkPos = 0; wBkPos < 10; wBkPos++) { if (*pImagePtr < 15) wFindBkCount++; pImagePtr--; } if (wFindBkCount >= 7) return 1; else return 0; } static unsigned char ABSCompute (unsigned char ucData1, unsigned char ucData2) { unsigned char ucData; if (ucData1 > ucData2) ucData = ucData1 - ucData2; else ucData = ucData2 - ucData1; return ucData; } static unsigned char SubRefBlack (mustek_pp_ccd300_priv * dev, unsigned char ucData) { if (ucData > dev->RefBlack) ucData -= dev->RefBlack; else ucData = 0; return ucData; } static void Bubble_Sort_Arg (mustek_pp_ccd300_priv * dev, unsigned int wCount) { unsigned int wLoop, wLoop1; unsigned char ucTmp; for (wLoop = 0; wLoop < wCount; wLoop++) { for (wLoop1 = 0; wLoop1 < wCount - 1; wLoop1++) { if (dev->BubbleSortAry[wLoop1] < dev->BubbleSortAry[wLoop1 + 1]) { ucTmp = dev->BubbleSortAry[wLoop1]; dev->BubbleSortAry[wLoop1] = dev->BubbleSortAry[wLoop1 + 1]; dev->BubbleSortAry[wLoop1 + 1] = ucTmp; } } } } static void CalibrationData_Gray (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wLoop; unsigned long dwPtrAddr; unsigned char *pImageTmp; pImageTmp = pImagePtr; for (wLoop = 0; wLoop < dev->Catch_G_Count; wLoop++) { dwPtrAddr = wLoop; dwPtrAddr *= dev->Real_Scan_Bytes; pImagePtr = pImageTmp + dwPtrAddr; CalibrationData (dev, pImagePtr, dev->Calib_Gray_Buf); } } static void CalibrationData_Color (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned char *lpImageTmp; lpImageTmp = pImagePtr; if (dev->reverse_rgb == 1) lpImageTmp += 2; dev->RefBlack = dev->RefBlack_R; CalibrationData_R (dev, lpImageTmp); lpImageTmp = pImagePtr; lpImageTmp++; dev->RefBlack = dev->RefBlack_G; CalibrationData_G (dev, lpImageTmp); lpImageTmp = pImagePtr; if (dev->reverse_rgb == 0) lpImageTmp += 2; dev->RefBlack = dev->RefBlack_B; CalibrationData_B (dev, lpImageTmp); } static void CalibrationData_R (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wLoop; unsigned long dwPtrAddr; unsigned char *pImageTmp; pImageTmp = pImagePtr; for (wLoop = 0; wLoop < dev->Catch_G_Count; wLoop++) { dwPtrAddr = wLoop * 3; dwPtrAddr *= dev->Real_Scan_Bytes; pImagePtr = pImageTmp + dwPtrAddr; CalibrationData (dev, pImagePtr, dev->Calib_Buffer_R); } } static void CalibrationData_G (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wLoop; unsigned long dwPtrAddr; unsigned char *pImageTmp; pImageTmp = pImagePtr; for (wLoop = 0; wLoop < dev->Catch_G_Count; wLoop++) { dwPtrAddr = wLoop * 3; dwPtrAddr *= dev->Real_Scan_Bytes; pImagePtr = pImageTmp + dwPtrAddr; CalibrationData (dev, pImagePtr, dev->Calib_Buffer_G); } } static void CalibrationData_B (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr) { unsigned int wLoop; unsigned long dwPtrAddr; unsigned char *pImageTmp; pImageTmp = pImagePtr; for (wLoop = 0; wLoop < dev->Catch_G_Count; wLoop++) { dwPtrAddr = wLoop * 3; dwPtrAddr *= dev->Real_Scan_Bytes; pImagePtr = pImageTmp + dwPtrAddr; CalibrationData (dev, pImagePtr, dev->Calib_Buffer_B); } } static void CalibrationData (mustek_pp_ccd300_priv * dev, unsigned char * pImagePtr, unsigned char * pCaliBufPtr) { unsigned int wLoop, wImage; unsigned char ucCalib; for (wLoop = 0; wLoop < dev->Real_Scan_Bytes; wLoop++) { wImage = (unsigned int) (*pImagePtr); ucCalib = *pCaliBufPtr; dev->DataValue = ucCalib; dev->DataValue = *pImagePtr; if (*pImagePtr > ucCalib) { *pImagePtr = 255; } else { if (ucCalib == 0) wImage = 255; else wImage = (wImage * 255) / ((unsigned int) (ucCalib)); *pImagePtr = (unsigned char) wImage; } pImagePtr++; pCaliBufPtr++; if (dev->ScanMode == 2) pImagePtr += 2; } } /* mustek_pp interface */ #define MUSTEK_PP_CCD300 4 static SANE_Status ccd300_init (SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach) { SANE_Status status; mustek_pp_ccd300_priv *dev; if ((options != CAP_NOTHING) && (options != CAP_TA)) { DBG (1, "ccd300_init: called with unkown options (0x%02x)\n", options); return SANE_STATUS_INVAL; } if ((dev = malloc (sizeof (mustek_pp_ccd300_priv))) == NULL) { DBG (2, "ccd300_init: not enough free memory\n"); return SANE_STATUS_NO_MEM; } /* try to attach to the supplied port */ status = sanei_pa4s2_open (port, &dev->fd); if (status != SANE_STATUS_GOOD) { DBG (2, "ccd300_init: couldn't attach to port ``%s'' (%s)\n", port, sane_strstatus(status)); free (dev); return status; } status = ParRead (dev); sanei_pa4s2_close (dev->fd); free (dev); if (status != SANE_STATUS_GOOD) { DBG (2, "ccd300_init: scanner not recognized (%s)\n", sane_strstatus (status)); return status; } DBG (3, "ccd300_init: found scanner on port ``%s''\n", port); return attach (port, name, MUSTEK_PP_CCD300, options); } static void ccd300_capabilities (SANE_Int info, SANE_String * model, SANE_String * vendor, SANE_String * type, SANE_Int * maxres, SANE_Int * minres, SANE_Int * maxhsize, SANE_Int * maxvsize, SANE_Int * caps) { *model = strdup ("600 III EP Plus"); *vendor = strdup ("Mustek"); if (info & CAP_TA) { *type = strdup ("flatbed with TA (CCD 300 dpi)"); DBG (3, "ccd300_capabilities: 600 III EP Plus with TA\n"); } else { *type = strdup ("flatbed (CCD 300 dpi)"); DBG (3, "ccd300_capabilities: 600 III EP Plus\n"); } *maxres = 300; *minres = 50; *maxhsize = 2550; /* FIXME: validate these constants */ *maxvsize = 3500; *caps = info | CAP_INVERT | CAP_LAMP_OFF; } static SANE_Status ccd300_open (SANE_String port, SANE_Int caps, SANE_Int * fd) { SANE_Status status; if (caps - (caps & (CAP_NOTHING | CAP_INVERT | CAP_LAMP_OFF | CAP_TA))) { DBG (1, "ccd300_open: called with unknown capabilities (0x%02X)\n", caps); return SANE_STATUS_INVAL; } DBG (3, "ccd300_open: called for port %s\n", port); status = sanei_pa4s2_open (port, fd); if (status != SANE_STATUS_GOOD) DBG (2, "ccd300_open: open failed (%s)\n", sane_strstatus (status)); return status; } static void ccd300_setup (SANE_Handle hndl) { Mustek_pp_Handle *handle = hndl; mustek_pp_ccd300_priv *dev; handle->lamp_on = 0; handle->priv = NULL; if ((dev = malloc (sizeof (mustek_pp_ccd300_priv))) == NULL) { DBG (2, "ccd300_setup: not enough memory"); return; } handle->priv = dev; dev->fd = handle->fd; dev->bw = 127; Switch_To_Scanner(dev); GetDeviceInfo(dev); LampPowerOn(dev); PullCarriage_ToHome(dev); Switch_To_Printer(dev); dev->LampOnTime = time(NULL); } static SANE_Status ccd300_config (SANE_Handle handle, SANE_String_Const optname, SANE_String_Const optval) { Mustek_pp_Handle *hndl = handle; mustek_pp_ccd300_priv *dev = hndl->priv; int value; DBG (4, "ccd300_config: %s %s %s", optname, (optval ? "=" : ""), (optval ? optval : "")); if (!strcmp(optname,"bw")) { if (!optval) { DBG (1, "ccd300_config: missing value for option bw"); return SANE_STATUS_INVAL; } value = atoi(optval); if ((value < 0) || (value > 255)) { DBG (1, "ccd300_config: value %d for option bw out of range (0 <= bw <= 255)\n", value); return SANE_STATUS_INVAL; } dev->bw = value; } else { DBG (1, "ccd300_config: unkown option %s", optname); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } static void ccd300_close(SANE_Handle handle) { Mustek_pp_Handle *hndl = handle; mustek_pp_ccd300_priv *dev = hndl->priv; DBG(4, "ccd300_close: turning scanner offline\n"); Switch_To_Scanner(dev); A4StopScan(0, 0, dev); LampPowerOff(dev); Switch_To_Printer(dev); } static SANE_Status ccd300_start (SANE_Handle handle) { Mustek_pp_Handle *hndl = handle; mustek_pp_ccd300_priv *dev = hndl->priv; int bitsperpixel, samplesperpixel; DBG(4, "ccd300_start: starting scanner\n"); Switch_To_Scanner(dev); PullCarriage_ToHome (dev); dev->ErrorCode = 0; dev->ScanResolution = hndl->res; dev->Skip_ImageBytes = hndl->topX; dev->Frame_Top = hndl->topY; dev->Frame_Left = hndl->topX; dev->Frame_Bottom = hndl->bottomY; dev->Frame_Right = hndl->bottomX; dev->scan_source = 0; switch (hndl->mode) { case MODE_BW: dev->ScanMode = 0; bitsperpixel = 1; samplesperpixel = 1; break; case MODE_GRAYSCALE: dev->ScanMode = 1; bitsperpixel = 8; samplesperpixel = 1; break; case MODE_COLOR: dev->ScanMode = 2; bitsperpixel = 24; samplesperpixel = 3; break; } SetScanParameter(0, 0, dev); A4StartScan(0, 0, dev); DBG(4, "scan started\n"); Switch_To_Printer(dev); return SANE_STATUS_GOOD; } static void ccd300_read (SANE_Handle handle, SANE_Byte *buffer) { Mustek_pp_Handle *hndl = handle; mustek_pp_ccd300_priv *dev = hndl->priv; DBG(4, "ccd300_read: reading one line\n"); dev->ImageBuffer = buffer; dev->BufferLine_Count = 1; dev->ErrorCode = 0; dev->reverse_rgb = 0; Switch_To_Scanner(dev); A4GetImage(0, 0, dev); Switch_To_Printer(dev); } static void ccd300_stop (SANE_Handle handle) { Mustek_pp_Handle *hndl = handle; mustek_pp_ccd300_priv *dev = hndl->priv; DBG(4, "ccd300_stop: stoping scanner\n"); Switch_To_Scanner(dev); A4StopScan(0, 0, dev); Switch_To_Printer(dev); }