/* HP Scanjet 3900 series - RTS8822 Core Copyright (C) 2005-2013 Jonathan Bravo Lopez 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 code is still a bit ugly due to it's the result of applying reverse engineering techniques to windows driver. So at this moment what you see is exactly what windows driver does. And so many global vars exist that will be erased when driver is entirely debugged. There are some variables with unknown purpose. So they have no meaning name in form v+address. I hope to change their names when driver is debugged completely. */ #ifndef RTS8822_CORE #define RTS8822_CORE #define GetTickCount() (time(0) * 1000) #define min(A,B) (((A)<(B)) ? (A) : (B)) #define max(A,B) (((A)>(B)) ? (A) : (B)) #define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_)) #define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4) #include #include #include /* bzero() */ #include /* clock() */ #include /* truncf() */ #include /* tolower() */ #include /* usleep() */ #include #include "hp3900_types.c" #include "hp3900_debug.c" #include "hp3900_config.c" #include "hp3900_usb.c" /*-------------------- Exported function headers --------------------*/ #ifdef developing static SANE_Int hp4370_prueba (struct st_device *dev); static void prueba (SANE_Byte * a); void shadingtest1 (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib); static SANE_Int Calib_test (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg); static SANE_Int Calib_BlackShading_jkd (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg); #endif /*static void show_diff(struct st_device *dev, SANE_Byte *original);*/ /* functions to allocate and free space for a device */ static struct st_device *RTS_Alloc (void); static void RTS_Free (struct st_device *dev); /* Scanner level commands */ static SANE_Int RTS_Scanner_Init (struct st_device *dev); static SANE_Int RTS_Scanner_SetParams (struct st_device *dev, struct params *param); static SANE_Int RTS_Scanner_StartScan (struct st_device *dev); static void RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait); static void RTS_Scanner_End (struct st_device *dev); /* loading configuration functions */ static SANE_Int Load_Buttons (struct st_device *dev); static SANE_Int Load_Chipset (struct st_device *dev); static SANE_Int Load_Config (struct st_device *dev); static SANE_Int Load_Constrains (struct st_device *dev); static SANE_Int Load_Motor (struct st_device *dev); static SANE_Int Load_MotorCurves (struct st_device *dev); static SANE_Int Load_Motormoves (struct st_device *dev); static SANE_Int Load_Scanmodes (struct st_device *dev); static SANE_Int Load_Sensor (struct st_device *dev); static SANE_Int Load_Timings (struct st_device *dev); /* freeing configuration functions */ static void Free_Buttons (struct st_device *dev); static void Free_Chipset (struct st_device *dev); static void Free_Config (struct st_device *dev); static void Free_Constrains (struct st_device *dev); static void Free_Motor (struct st_device *dev); static void Free_MotorCurves (struct st_device *dev); static void Free_Motormoves (struct st_device *dev); static void Free_Scanmodes (struct st_device *dev); static void Free_Sensor (struct st_device *dev); static void Free_Timings (struct st_device *dev); static void Free_Vars (void); /* Functions to manage data */ static SANE_Byte data_bitget (SANE_Byte * address, SANE_Int mask); static void data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data); static SANE_Int data_lsb_get (SANE_Byte * address, SANE_Int size); static void data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size); static void data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size); static void data_wide_bitset (SANE_Byte * address, SANE_Int mask, SANE_Int data); static SANE_Int data_swap_endianess (SANE_Int address, SANE_Int size); static SANE_Int Device_get (SANE_Int product, SANE_Int vendor); /* Chipset related commands */ static SANE_Int Chipset_ID (struct st_device *dev); static SANE_Int Chipset_Name (struct st_device *dev, char *name, SANE_Int size); static SANE_Int Chipset_Reset (struct st_device *dev); /* Initializing functions */ static SANE_Int Init_Registers (struct st_device *dev); static SANE_Int Init_USBData (struct st_device *dev); static SANE_Int Init_Vars (void); /* scanmode functions */ static SANE_Int Scanmode_fitres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution); static SANE_Int Scanmode_maxres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode); static SANE_Int Scanmode_minres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode); /* Chipset management useful commands*/ static SANE_Int RTS_USBType (struct st_device *dev); static SANE_Byte RTS_Sensor_Type (USB_Handle usb_handle); static void RTS_DebugInit (void); static SANE_Int RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels); /* DMA management commands */ static SANE_Int RTS_DMA_Cancel (struct st_device *dev); static SANE_Int RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs); static SANE_Int RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options); static SANE_Int RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options); static SANE_Int RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer); static SANE_Int RTS_DMA_Reset (struct st_device *dev); static SANE_Int RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, SANE_Byte ramtype); static SANE_Int RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs); static SANE_Int RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer); /* EEPROM management commands */ static SANE_Int RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data); static SANE_Int RTS_EEPROM_ReadInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int * data); static SANE_Int RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, SANE_Int * data); static SANE_Int RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, SANE_Int size); static SANE_Int RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data); static SANE_Int RTS_EEPROM_WriteInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int data); static SANE_Int RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, SANE_Int data); static SANE_Int RTS_Execute (struct st_device *dev); static SANE_Int RTS_Warm_Reset (struct st_device *dev); static SANE_Byte RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs); static SANE_Int RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution); static SANE_Int RTS_GetImage (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_gain_offset *gain_offset, SANE_Byte * buffer, struct st_calibration *myCalib, SANE_Int options, SANE_Int gainmode); static SANE_Int RTS_GetImage_GetBuffer (struct st_device *dev, double dSize, SANE_Byte * buffer, double *transferred); static SANE_Int RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer, struct st_scanparams *myvar, struct st_hwdconfig *hwdcfg); static SANE_Int RTS_isTmaAttached (struct st_device *dev); /* functions to wait for a process tp finish */ static SANE_Int RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs); static SANE_Int RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs); /* functions to read/write control registers */ static SANE_Int RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer); static SANE_Int RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer); /* functions to manage the scan counter */ static SANE_Int RTS_ScanCounter_Inc (struct st_device *dev); static SANE_Int RTS_ScanCounter_Get (struct st_device *dev); /* functions to setup control registers */ static SANE_Int RTS_Setup (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, struct st_hwdconfig *hwdcfg, struct st_gain_offset *gain_offset); static void RTS_Setup_Arrangeline (struct st_device *dev, struct st_hwdconfig *hwdcfg, SANE_Int colormode); static void RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode); static void RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop, SANE_Int width, SANE_Int height); static SANE_Int RTS_Setup_Depth (SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode); static void RTS_Setup_Exposure_Times (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_scanmode *sm); static void RTS_Setup_GainOffset (SANE_Byte * Regs, struct st_gain_offset *gain_offset); static void RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *lowcfg); static SANE_Int RTS_Setup_Line_Distances (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int mycolormode, SANE_Int arrangeline); static SANE_Int RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, SANE_Int somevalue); static void RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs); static void RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming, SANE_Byte * Regs); static void RTS_Setup_Shading (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int bytes_per_line); static SANE_Int Scan_Start (struct st_device *dev); static void SetLock (USB_Handle usb_handle, SANE_Byte * Regs, SANE_Byte Enable); static SANE_Int fn3330 (struct st_device *dev, SANE_Byte * Regs, struct st_cal2 *calbuffers, SANE_Int sensorchannelcolor, SANE_Int * tablepos, SANE_Int data); static SANE_Int fn3560 (USHORT * table, struct st_cal2 *calbuffers, SANE_Int * tablepos); static SANE_Int fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, SANE_Byte * Regs, USHORT * table, SANE_Int sensorchannelcolor, SANE_Int data); static SANE_Int Reading_CreateBuffers (struct st_device *dev); static SANE_Int Reading_DestroyBuffers (struct st_device *dev); static SANE_Int Reading_BufferSize_Get (struct st_device *dev, SANE_Byte channels_per_dot, SANE_Int channel_size); static SANE_Int Reading_BufferSize_Notify (struct st_device *dev, SANE_Int data, SANE_Int size); static SANE_Int Reading_Wait (struct st_device *dev, SANE_Byte Channels_per_dot, SANE_Byte Channel_size, SANE_Int size, SANE_Int * last_amount, SANE_Int seconds, SANE_Byte op); static SANE_Int Read_Image (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred); static SANE_Int Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); static SANE_Int Read_Block (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred); static SANE_Int Read_NonColor_Block (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Byte ColorMode, SANE_Int * transferred); /* Ref functions */ static SANE_Int Refs_Analyze_Pattern (struct st_scanparams *scancfg, SANE_Byte * scanned_pattern, SANE_Int * ler1, SANE_Int ler1order, SANE_Int * ser1, SANE_Int ser1order); static SANE_Int Refs_Counter_Inc (struct st_device *dev); static SANE_Byte Refs_Counter_Load (struct st_device *dev); static SANE_Int Refs_Counter_Save (struct st_device *dev, SANE_Byte data); static SANE_Int Refs_Detect (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution_x, SANE_Int resolution_y, SANE_Int * x, SANE_Int * y); static SANE_Int Refs_Load (struct st_device *dev, SANE_Int * x, SANE_Int * y); static SANE_Int Refs_Save (struct st_device *dev, SANE_Int left_leading, SANE_Int start_pos); static SANE_Int Refs_Set (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myscan); /* Coordinates' constrains functions */ static SANE_Int Constrains_Check (struct st_device *dev, SANE_Int Resolution, SANE_Int scantype, struct st_coords *mycoords); static struct st_coords *Constrains_Get (struct st_device *dev, SANE_Byte scantype); /* Gain and offset functions */ static SANE_Int GainOffset_Clear (struct st_device *dev); static SANE_Int GainOffset_Get (struct st_device *dev); static SANE_Int GainOffset_Save (struct st_device *dev, SANE_Int * offset, SANE_Byte * gain); static SANE_Int GainOffset_Counter_Inc (struct st_device *dev, SANE_Int * arg1); static SANE_Byte GainOffset_Counter_Load (struct st_device *dev); static SANE_Int GainOffset_Counter_Save (struct st_device *dev, SANE_Byte data); /* Gamma functions*/ static SANE_Int Gamma_AllocTable (SANE_Byte * table); static SANE_Int Gamma_Apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, struct st_gammatables *mygamma); static void Gamma_FreeTables (void); static SANE_Int Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs, SANE_Byte * gammatable, SANE_Int size); static SANE_Int Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer); /* Lamp functions */ static SANE_Byte Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution, SANE_Byte scantype); static void Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution, SANE_Byte gainmode); static SANE_Int Lamp_PWM_DutyCycle_Get (struct st_device *dev, SANE_Int * data); static SANE_Int Lamp_PWM_DutyCycle_Set (struct st_device *dev, SANE_Int duty_cycle); static SANE_Int Lamp_PWM_Setup (struct st_device *dev, SANE_Int lamp); static SANE_Int Lamp_PWM_use (struct st_device *dev, SANE_Int enable); static SANE_Int Lamp_PWM_CheckStable (struct st_device *dev, SANE_Int resolution, SANE_Int lamp); static SANE_Int Lamp_PWM_Save (struct st_device *dev, SANE_Int fixedpwm); static SANE_Int Lamp_PWM_SaveStatus (struct st_device *dev, SANE_Byte status); static SANE_Int Lamp_Status_Get (struct st_device *dev, SANE_Byte * flb_lamp, SANE_Byte * tma_lamp); static SANE_Int Lamp_Status_Set (struct st_device *dev, SANE_Byte * Regs, SANE_Int turn_on, SANE_Int lamp); static SANE_Int Lamp_Status_Timer_Set (struct st_device *dev, SANE_Int minutes); static SANE_Int Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, SANE_Int lamp, SANE_Int resolution); /* Head related functions */ static SANE_Int Head_IsAtHome (struct st_device *dev, SANE_Byte * Regs); static SANE_Int Head_ParkHome (struct st_device *dev, SANE_Int bWait, SANE_Int movement); static SANE_Int Head_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction, SANE_Int ypos); /* Motor functions */ static SANE_Byte *Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, SANE_Int step); static SANE_Int Motor_Change (struct st_device *dev, SANE_Byte * buffer, SANE_Byte value); static SANE_Int Motor_GetFromResolution (SANE_Int resolution); static SANE_Int Motor_Move (struct st_device *dev, SANE_Byte * Regs, struct st_motormove *mymotor, struct st_motorpos *mtrpos); static void Motor_Release (struct st_device *dev); static SANE_Int Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs, SANE_Int mysetting); static SANE_Int Motor_Curve_Equal (struct st_device *dev, SANE_Int motorsetting, SANE_Int direction, SANE_Int curve1, SANE_Int curve2); static void Motor_Curve_Free (struct st_motorcurve **motorcurves, SANE_Int * mtc_count); static struct st_curve *Motor_Curve_Get (struct st_device *dev, SANE_Int motorcurve, SANE_Int direction, SANE_Int itype); static struct st_motorcurve **Motor_Curve_Parse (SANE_Int * mtc_count, SANE_Int * buffer); /* Functions to arrange scanned lines */ static SANE_Int Arrange_Colour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); static SANE_Int Arrange_Compose (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); static SANE_Int Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); /* Composing RGB triplet functions */ static void Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count); static void Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count); static void Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots); static void Triplet_Compose_HRes (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * pPointer3, SANE_Byte * pPointer4, SANE_Byte * pPointer5, SANE_Byte * pPointer6, SANE_Byte * buffer, SANE_Int Width); static void Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots); static void Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int Width); static void Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, SANE_Byte * pBlue1, SANE_Byte * pRed2, SANE_Byte * pGreen2, SANE_Byte * pBlue2, SANE_Byte * buffer, SANE_Int Width); static void Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer, SANE_Byte * pChannel1, SANE_Byte * pChannel2, SANE_Byte * pChannel3); /* Timing functions */ static SANE_Int Timing_SetLinearImageSensorClock (SANE_Byte * Regs, struct st_cph *cph); /* Functions used to resize retrieved image */ static SANE_Int Resize_Start (struct st_device *dev, SANE_Int * transferred); static SANE_Int Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, SANE_Int size2, SANE_Int size3); static SANE_Int Resize_DestroyBuffers (struct st_device *dev); static SANE_Int Resize_Increase (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode); static SANE_Int Resize_Decrease (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode); /* Scanner buttons support */ static SANE_Int Buttons_Count (struct st_device *dev); static SANE_Int Buttons_Enable (struct st_device *dev); static SANE_Int Buttons_Order (struct st_device *dev, SANE_Int mask); static SANE_Int Buttons_Status (struct st_device *dev); static SANE_Int Buttons_Released (struct st_device *dev); /* Calibration functions */ static SANE_Int Calib_CreateBuffers (struct st_device *dev, struct st_calibration *buffer, SANE_Int my14b4); static SANE_Int Calib_CreateFixedBuffers (void); static void Calib_FreeBuffers (struct st_calibration *caltables); static void Calib_LoadCut (struct st_device *dev, struct st_scanparams *scancfg, SANE_Int scantype, struct st_calibration_config *calibcfg); static SANE_Int Calib_AdcGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int arg2, SANE_Int gainmode); static SANE_Int Calib_AdcOffsetRT (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int value); static SANE_Int Calib_BlackShading (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode); static SANE_Int Calib_BWShading (struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode); static SANE_Int Calib_WhiteShading_3 (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode); static void Calibrate_Free (struct st_cal2 *calbuffers); static SANE_Int Calibrate_Malloc (struct st_cal2 *calbuffers, SANE_Byte * Regs, struct st_calibration *myCalib, SANE_Int somelength); static SANE_Int Calib_ReadTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data); static SANE_Int Calib_WriteTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data); static SANE_Int Calib_LoadConfig (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int scantype, SANE_Int resolution, SANE_Int bitmode); static SANE_Int Calib_PAGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int gainmode); static SANE_Int Calibration (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_calibration *myCalib, SANE_Int value); /* function for white shading correction */ static SANE_Int WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg); static void WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, SANE_Int size, SANE_Int depth); /* functions for shading calibration */ static SANE_Int Shading_apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, struct st_calibration *myCalib); static SANE_Int Shading_black_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers); static SANE_Int Shading_white_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers); /* Spread-Spectrum Clock Generator functions */ static SANE_Int SSCG_Enable (struct st_device *dev); static void Split_into_12bit_channels (SANE_Byte * destino, SANE_Byte * fuente, SANE_Int size); static SANE_Int Scan_Read_BufferA (struct st_device *dev, SANE_Int buffer_size, SANE_Int arg2, SANE_Byte * pBuffer, SANE_Int * bytes_transfered); static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transfered); static SANE_Int Get_PAG_Value (SANE_Byte scantype, SANE_Byte color); static SANE_Int GetOneLineInfo (struct st_device *dev, SANE_Int resolution, SANE_Int * maximus, SANE_Int * minimus, double *average); static SANE_Int Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, SANE_Int * xpos); /*static SANE_Int Free_Fixed_CalBuffer(void);*/ static SANE_Int SetMultiExposure (struct st_device *dev, SANE_Byte * Regs); static void Set_E950_Mode (struct st_device *dev, SANE_Byte mode); static SANE_Int LoadImagingParams (struct st_device *dev, SANE_Int inifile); static SANE_Int SetScanParams (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg); static SANE_Int IsScannerLinked (struct st_device *dev); static SANE_Int Read_FE3E (struct st_device *dev, SANE_Byte * destino); static double get_shrd (double value, SANE_Int desp); static char get_byte (double value); /*static SANE_Int RTS8822_GetRegisters(SANE_Byte *buffer);*/ /* ----------------- Implementation ------------------*/ static void RTS_Free (struct st_device *dev) { /* this function frees space of devices's variable */ if (dev != NULL) { /* next function shouldn't be necessary but I can NOT assure that other programmers will call Free_Config before this function */ Free_Config (dev); if (dev->init_regs != NULL) free (dev->init_regs); if (dev->Resize != NULL) free (dev->Resize); if (dev->Reading != NULL) free (dev->Reading); if (dev->scanning != NULL) free (dev->scanning); if (dev->status != NULL) free (dev->status); free (dev); } } static struct st_device * RTS_Alloc () { /* this function allocates space for device's variable */ struct st_device *dev = NULL; dev = malloc (sizeof (struct st_device)); if (dev != NULL) { SANE_Int rst = OK; bzero (dev, sizeof (struct st_device)); /* initial registers */ dev->init_regs = malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN); if (dev->init_regs != NULL) bzero (dev->init_regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); else rst = ERROR; if (rst == OK) { dev->scanning = malloc (sizeof (struct st_scanning)); if (dev->scanning != NULL) bzero (dev->scanning, sizeof (struct st_scanning)); else rst = ERROR; } if (rst == OK) { dev->Reading = malloc (sizeof (struct st_readimage)); if (dev->Reading != NULL) bzero (dev->Reading, sizeof (struct st_readimage)); else rst = ERROR; } if (rst == OK) { dev->Resize = malloc (sizeof (struct st_resize)); if (dev->Resize != NULL) bzero (dev->Resize, sizeof (struct st_resize)); else rst = ERROR; } if (rst == OK) { dev->status = malloc (sizeof (struct st_status)); if (dev->status != NULL) bzero (dev->status, sizeof (struct st_status)); else rst = ERROR; } /* if something fails, free space */ if (rst != OK) { RTS_Free (dev); dev = NULL; } } return dev; } static void RTS_Scanner_End (struct st_device *dev) { Gamma_FreeTables (); Free_Config (dev); Free_Vars (); } static SANE_Int Device_get (SANE_Int product, SANE_Int vendor) { return cfg_device_get (product, vendor); } static SANE_Int RTS_Scanner_Init (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "> RTS_Scanner_Init:\n"); DBG (DBG_FNC, "> Backend version: %s\n", BACKEND_VRSN); rst = ERROR; /* gets usb type of this scanner if it's not already set by user */ if (RTS_Debug->usbtype == -1) RTS_Debug->usbtype = RTS_USBType (dev); if (RTS_Debug->usbtype != ERROR) { DBG (DBG_FNC, " -> Chipset model ID: %i\n", Chipset_ID (dev)); Chipset_Reset (dev); if (Load_Config (dev) == OK) { if (IsScannerLinked (dev) == OK) { Set_E950_Mode (dev, 0); Gamma_AllocTable (NULL); rst = OK; } else Free_Config (dev); } } return rst; } static SANE_Int RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer) { SANE_Int rst = ERROR; if (buffer != NULL) rst = Write_Buffer (usb_handle, 0xe800, buffer, RT_BUFFER_LEN * sizeof (SANE_Byte)); return rst; } static SANE_Int RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer) { SANE_Int rst = ERROR; if (buffer != NULL) rst = Read_Buffer (usb_handle, 0xe800, buffer, RT_BUFFER_LEN * sizeof (SANE_Byte)); return rst; } static void SetLock (USB_Handle usb_handle, SANE_Byte * Regs, SANE_Byte Enable) { SANE_Byte lock; DBG (DBG_FNC, "+ SetLock(*Regs, Enable=%i):\n", Enable); if (Regs == NULL) { if (Read_Byte (usb_handle, 0xee00, &lock) != OK) lock = 0; } else lock = Regs[0x600]; if (Enable == FALSE) lock &= 0xfb; else lock |= 4; if (Regs != NULL) Regs[0x600] = lock; Write_Byte (usb_handle, 0xee00, lock); DBG (DBG_FNC, "- SetLock\n"); } static void Set_E950_Mode (struct st_device *dev, SANE_Byte mode) { SANE_Int data; DBG (DBG_FNC, "+ Set_E950_Mode(mode=%i):\n", mode); if (Read_Word (dev->usb_handle, 0xe950, &data) == OK) { data = (mode == 0) ? data & 0xffbf : data | 0x40; Write_Word (dev->usb_handle, 0xe950, data); } DBG (DBG_FNC, "- Set_E950_Mode\n"); } static struct st_curve * Motor_Curve_Get (struct st_device *dev, SANE_Int motorcurve, SANE_Int direction, SANE_Int itype) { struct st_curve *rst = NULL; if (dev != NULL) { if ((dev->mtrsetting != NULL) && (motorcurve < dev->mtrsetting_count)) { struct st_motorcurve *mtc = dev->mtrsetting[motorcurve]; if (mtc != NULL) { if ((mtc->curve != NULL) && (mtc->curve_count > 0)) { struct st_curve *crv; SANE_Int a = 0; while (a < mtc->curve_count) { /* get each curve */ crv = mtc->curve[a]; if (crv != NULL) { /* check direction and type */ if ((crv->crv_speed == direction) && (crv->crv_type == itype)) { /* found ! */ rst = crv; break; } } a++; } } } } } return rst; } static SANE_Int Motor_Curve_Equal (struct st_device *dev, SANE_Int motorsetting, SANE_Int direction, SANE_Int curve1, SANE_Int curve2) { /* compares two curves of the same direction returns TRUE if both buffers are equal */ SANE_Int rst = FALSE; struct st_curve *crv1 = Motor_Curve_Get (dev, motorsetting, direction, curve1); struct st_curve *crv2 = Motor_Curve_Get (dev, motorsetting, direction, curve2); if ((crv1 != NULL) && (crv2 != NULL)) { if (crv1->step_count == crv2->step_count) { rst = TRUE; if (crv1->step_count > 0) { SANE_Int a = 0; while ((a < crv1->step_count) && (rst == TRUE)) { rst = (crv1->step[a] == crv2->step[a]) ? TRUE : FALSE; a++; } } } } return rst; } static struct st_motorcurve ** Motor_Curve_Parse (SANE_Int * mtc_count, SANE_Int * buffer) { /* this function parses motorcurve buffer to get all motor settings */ struct st_motorcurve **rst = NULL; *mtc_count = 0; if (buffer != NULL) { /* phases: -1 : null phase 0 : -3 : initial config */ struct st_motorcurve *mtc = NULL; SANE_Int phase; phase = -1; while (*buffer != -1) { if (*buffer == -2) { /* end of motorcurve */ /* complete any openned phase */ /* close phase */ phase = -1; } else { /* step */ if (phase == -1) { /* new motorcurve */ phase = 0; mtc = (struct st_motorcurve *) malloc (sizeof (struct st_motorcurve)); if (mtc != NULL) { *mtc_count += 1; rst = realloc (rst, sizeof (struct st_motorcurve **) * *mtc_count); if (rst != NULL) { rst[*mtc_count - 1] = mtc; memset (mtc, 0, sizeof (struct st_motorcurve)); phase = -3; /* initial config */ } else { /* memory error */ *mtc_count = 0; break; } } else break; /* some error */ } if (mtc != NULL) { switch (phase) { case -3: /* initial config */ mtc->mri = *(buffer); mtc->msi = *(buffer + 1); mtc->skiplinecount = *(buffer + 2); mtc->motorbackstep = *(buffer + 3); buffer += 3; phase = -4; break; case -4: /**/ { /* create new step curve */ struct st_curve *curve = malloc (sizeof (struct st_curve)); if (curve != NULL) { /* add to step curve list */ mtc->curve = (struct st_curve **) realloc (mtc->curve, sizeof (struct st_curve **) * (mtc-> curve_count + 1)); if (mtc->curve != NULL) { mtc->curve_count++; mtc->curve[mtc->curve_count - 1] = curve; memset (curve, 0, sizeof (struct st_curve)); /* read crv speed and type */ curve->crv_speed = *buffer; curve->crv_type = *(buffer + 1); buffer += 2; /* get length of step buffer */ while (*(buffer + curve->step_count) != 0) curve->step_count++; if (curve->step_count > 0) { /* allocate step buffer */ curve->step = (SANE_Int *) malloc (sizeof (SANE_Int) * curve->step_count); if (curve->step != NULL) { memcpy (curve->step, buffer, sizeof (SANE_Int) * curve->step_count); buffer += curve->step_count; } else curve->step_count = 0; } } else { mtc->curve_count = 0; free (curve); } } else break; } break; } } } buffer++; } } return rst; } static void Motor_Curve_Free (struct st_motorcurve **motorcurves, SANE_Int * mtc_count) { if ((motorcurves != NULL) && (mtc_count != NULL)) { struct st_motorcurve *mtc; struct st_curve *curve; while (*mtc_count > 0) { mtc = motorcurves[*mtc_count - 1]; if (mtc != NULL) { if (mtc->curve != NULL) { while (mtc->curve_count > 0) { curve = mtc->curve[mtc->curve_count - 1]; if (curve != NULL) { if (curve->step != NULL) free (curve->step); free (curve); } mtc->curve_count--; } } free (mtc); } *mtc_count -= 1; } free (motorcurves); } } static SANE_Byte RTS_Sensor_Type (USB_Handle usb_handle) { /* Returns sensor type 01 = CCD 00 = CIS */ SANE_Int a, b, c; SANE_Byte rst; DBG (DBG_FNC, "+ RTS_Sensor_Type:\n"); a = b = c = 0; /* Save data first */ Read_Word (usb_handle, 0xe950, &a); Read_Word (usb_handle, 0xe956, &b); /* Enables GPIO 0xe950 writing directly 0x13ff */ Write_Word (usb_handle, 0xe950, 0x13ff); /* Sets GPIO 0xe956 writing 0xfcf0 */ Write_Word (usb_handle, 0xe956, 0xfcf0); /* Makes a sleep of 200 ms */ usleep (1000 * 200); /* Get GPIO 0xe968 */ Read_Word (usb_handle, 0xe968, &c); /* Restore data */ Write_Word (usb_handle, 0xe950, a); Write_Word (usb_handle, 0xe956, b); rst = ((_B1 (c) & 1) == 0) ? CCD_SENSOR : CIS_SENSOR; DBG (DBG_FNC, "- RTS_Sensor_Type: %s\n", (rst == CCD_SENSOR) ? "CCD" : "CIS"); return rst; } static void Free_Scanmodes (struct st_device *dev) { DBG (DBG_FNC, "> Free_Scanmodes\n"); if (dev->scanmodes != NULL) { if (dev->scanmodes_count > 0) { SANE_Int a; for (a = 0; a < dev->scanmodes_count; a++) if (dev->scanmodes[a] != NULL) free (dev->scanmodes[a]); } free (dev->scanmodes); dev->scanmodes = NULL; } dev->scanmodes_count = 0; } static SANE_Int Load_Scanmodes (struct st_device *dev) { SANE_Int rst = OK; SANE_Int a, b; struct st_scanmode reg, *mode; DBG (DBG_FNC, "> Load_Scanmodes\n"); if ((dev->scanmodes != NULL) || (dev->scanmodes_count > 0)) Free_Scanmodes (dev); a = 0; while ((cfg_scanmode_get (dev->sensorcfg->type, a, ®) == OK) && (rst == OK)) { mode = (struct st_scanmode *) malloc (sizeof (struct st_scanmode)); if (mode != NULL) { memcpy (mode, ®, sizeof (struct st_scanmode)); for (b = 0; b < 3; b++) { if (mode->mexpt[b] == 0) { mode->mexpt[b] = mode->ctpc; if (mode->multiexposure != 1) mode->expt[b] = mode->ctpc; } } mode->ctpc = ((mode->ctpc + 1) * mode->multiexposure) - 1; dev->scanmodes = (struct st_scanmode **) realloc (dev->scanmodes, (dev->scanmodes_count + 1) * sizeof (struct st_scanmode **)); if (dev->scanmodes != NULL) { dev->scanmodes[dev->scanmodes_count] = mode; dev->scanmodes_count++; } else rst = ERROR; } else rst = ERROR; a++; } if (rst == ERROR) Free_Scanmodes (dev); DBG (DBG_FNC, " -> Found %i scanmodes\n", dev->scanmodes_count); dbg_scanmodes (dev); return rst; } static void Free_Config (struct st_device *dev) { DBG (DBG_FNC, "+ Free_Config\n"); /* free buttons */ Free_Buttons (dev); /* free motor general configuration */ Free_Motor (dev); /* free sensor main configuration */ Free_Sensor (dev); /* free ccd sensor timing tables */ Free_Timings (dev); /* free motor curves */ Free_MotorCurves (dev); /* free motor movements */ Free_Motormoves (dev); /* free scan modes */ Free_Scanmodes (dev); /* free constrains */ Free_Constrains (dev); /* free chipset configuration */ Free_Chipset (dev); DBG (DBG_FNC, "- Free_Config\n"); } static void Free_Chipset (struct st_device *dev) { DBG (DBG_FNC, "> Free_Chipset\n"); if (dev->chipset != NULL) { if (dev->chipset->name != NULL) free (dev->chipset->name); free (dev->chipset); dev->chipset = NULL; } } static SANE_Int Load_Chipset (struct st_device *dev) { SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Chipset\n"); if (dev->chipset != NULL) Free_Chipset (dev); dev->chipset = malloc (sizeof (struct st_chip)); if (dev->chipset != NULL) { SANE_Int model; bzero (dev->chipset, sizeof (struct st_chip)); /* get chipset model of selected scanner */ model = cfg_chipset_model_get (RTS_Debug->dev_model); /* get configuration for selected chipset */ rst = cfg_chipset_get (model, dev->chipset); } /* if rst == ERROR may be related to allocating space for chipset name */ return rst; } static SANE_Int Load_Config (struct st_device *dev) { DBG (DBG_FNC, "+ Load_Config\n"); /* load chipset configuration */ Load_Chipset (dev); /* load scanner's buttons */ Load_Buttons (dev); /* load scanner area constrains */ Load_Constrains (dev); /* load motor general configuration */ Load_Motor (dev); /* load sensor main configuration */ Load_Sensor (dev); if (dev->sensorcfg->type == -1) /* get sensor from gpio */ dev->sensorcfg->type = RTS_Sensor_Type (dev->usb_handle); /* load ccd sensor timing tables */ Load_Timings (dev); /* load motor curves */ Load_MotorCurves (dev); /* load motor movements */ Load_Motormoves (dev); /* load scan modes */ Load_Scanmodes (dev); /* deprecated */ if (dev->sensorcfg->type == CCD_SENSOR) /* ccd */ usbfile = (RTS_Debug->usbtype == USB20) ? T_RTINIFILE : T_USB1INIFILE; else /* cis */ usbfile = (RTS_Debug->usbtype == USB20) ? S_RTINIFILE : S_USB1INIFILE; scantype = ST_NORMAL; pwmlamplevel = get_value (SCAN_PARAM, PWMLAMPLEVEL, 1, usbfile); arrangeline2 = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, usbfile); shadingbase = get_value (TRUE_GRAY_PARAM, SHADINGBASE, 3, usbfile); shadingfact[0] = get_value (TRUE_GRAY_PARAM, SHADINGFACT1, 1, usbfile); shadingfact[1] = get_value (TRUE_GRAY_PARAM, SHADINGFACT2, 1, usbfile); shadingfact[2] = get_value (TRUE_GRAY_PARAM, SHADINGFACT3, 1, usbfile); LoadImagingParams (dev, usbfile); DBG (DBG_FNC, "- Load_Config\n"); return OK; } static SANE_Int LoadImagingParams (struct st_device *dev, SANE_Int inifile) { DBG (DBG_FNC, "> LoadImagingParams(inifile='%i'):\n", inifile); scan.startpos = get_value (SCAN_PARAM, STARTPOS, 0, inifile); scan.leftleading = get_value (SCAN_PARAM, LEFTLEADING, 0, inifile); arrangeline = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, inifile); compression = get_value (SCAN_PARAM, COMPRESSION, 0, inifile); /* get default gain and offset values */ cfg_gainoffset_get (dev->sensorcfg->type, default_gain_offset); linedarlampoff = get_value (CALI_PARAM, LINEDARLAMPOFF, 0, inifile); pixeldarklevel = get_value (CALI_PARAM, PIXELDARKLEVEL, 0x00ffff, inifile); binarythresholdh = get_value (PLATFORM, BINARYTHRESHOLDH, 0x80, inifile); binarythresholdl = get_value (PLATFORM, BINARYTHRESHOLDL, 0x7f, inifile); return OK; } static SANE_Int Arrange_Colour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /* 05F0FA78 04EC00D8 /CALL to Assumed StdFunc2 from hpgt3970.04EC00D3 05F0FA7C 05D10048 |Arg1 = 05D10048 05F0FA80 0000F906 \Arg2 = 0000F906 */ SANE_Int mydistance; SANE_Int Lines_Count; SANE_Int space; SANE_Int rst = OK; SANE_Int c; struct st_scanning *scn; DBG (DBG_FNC, "> Arrange_Colour(*buffer, buffer_size=%i, *transferred)\n", buffer_size); /* this is just to make code more legible */ scn = dev->scanning; if (scn->imagebuffer == NULL) { if (dev->sensorcfg->type == CCD_SENSOR) mydistance = (dev->sensorcfg->line_distance * scan2.resolution_y) / dev->sensorcfg->resolution; else mydistance = 0; /*aafa */ if (mydistance != 0) { scn->bfsize = (scn->arrange_hres == TRUE) ? scn->arrange_sensor_evenodd_dist : 0; scn->bfsize = (scn->bfsize + (mydistance * 2) + 1) * line_size; } else scn->bfsize = line_size * 2; /*ab3c */ space = (((scn->bfsize / line_size) * bytesperline) > scn->bfsize) ? (scn->bfsize / line_size) * bytesperline : scn->bfsize; scn->imagebuffer = (SANE_Byte *) malloc (space * sizeof (SANE_Byte)); if (scn->imagebuffer == NULL) return ERROR; scn->imagepointer = scn->imagebuffer; if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) != OK) return ERROR; scn->arrange_orderchannel = FALSE; scn->channel_size = (scan2.depth == 8) ? 1 : 2; /* Calculate channel displacements */ for (c = CL_RED; c <= CL_BLUE; c++) { if (mydistance == 0) { /*ab9b */ if (scn->arrange_hres == FALSE) { if ((((dev->sensorcfg->line_distance * scan2.resolution_y) * 2) / dev->sensorcfg->resolution) == 1) scn->arrange_orderchannel = TRUE; if (scn->arrange_orderchannel == TRUE) scn->desp[c] = ((dev->sensorcfg->rgb_order[c] / 2) * line_size) + (scn->channel_size * c); else scn->desp[c] = scn->channel_size * c; } } else { /*ac32 */ scn->desp[c] = (dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) + (scn->channel_size * c); if (scn->arrange_hres == TRUE) { scn->desp1[c] = scn->desp[c]; scn->desp2[c] = ((scn->channel_size * 3) + scn->desp[c]) + (scn->arrange_sensor_evenodd_dist * line_size); } } } /*ace2 */ for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*ad91 */ Lines_Count = buffer_size / line_size; while (Lines_Count > 0) { if (scn->arrange_orderchannel == FALSE) { if (scn->arrange_hres == TRUE) Triplet_Colour_HRes (scn->pColour1[CL_RED], scn->pColour1[CL_GREEN], scn->pColour1[CL_BLUE], scn->pColour2[CL_RED], scn->pColour2[CL_GREEN], scn->pColour2[CL_BLUE], buffer, line_size / (scn->channel_size * 3)); else Triplet_Colour_LRes (line_size / (scn->channel_size * 3), buffer, scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE]); } else Triplet_Colour_Order (dev, scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], buffer, line_size / (scn->channel_size * 3)); scn->arrange_size -= bytesperline; if (scn->arrange_size < 0) v15bc--; buffer += line_size; Lines_Count--; if (Lines_Count == 0) { if ((scn->arrange_size | v15bc) == 0) return OK; } if (Read_Block (dev, line_size, scn->imagepointer, transferred) == ERROR) return ERROR; /* Update displacements */ for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { /*aeb7 */ scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize; scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize; scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else { /*af86 */ scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize; scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*aff3 */ scn->imagepointer += line_size; if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) scn->imagepointer = scn->imagebuffer; } return rst; } static SANE_Int RTS_Scanner_SetParams (struct st_device *dev, struct params *param) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_Scanner_SetParams:\n"); DBG (DBG_FNC, "-> param->resolution_x=%i\n", param->resolution_x); DBG (DBG_FNC, "-> param->resolution_y=%i\n", param->resolution_y); DBG (DBG_FNC, "-> param->left =%i\n", param->coords.left); DBG (DBG_FNC, "-> param->width =%i\n", param->coords.width); DBG (DBG_FNC, "-> param->top =%i\n", param->coords.top); DBG (DBG_FNC, "-> param->height =%i\n", param->coords.height); DBG (DBG_FNC, "-> param->colormode =%s\n", dbg_colour (param->colormode)); DBG (DBG_FNC, "-> param->scantype =%s\n", dbg_scantype (param->scantype)); DBG (DBG_FNC, "-> param->depth =%i\n", param->depth); DBG (DBG_FNC, "-> param->channel =%i\n", param->channel); /* validate area size to scan */ if ((param->coords.width != 0) && (param->coords.height != 0)) { SANE_Byte mybuffer[1]; struct st_hwdconfig hwdcfg; /* setting coordinates */ memcpy (&scan.coord, ¶m->coords, sizeof (struct st_coords)); /* setting resolution */ scan.resolution_x = param->resolution_x; scan.resolution_y = param->resolution_y; /* setting colormode and depth */ scan.colormode = param->colormode; scan.depth = (param->colormode == CM_LINEART) ? 8 : param->depth; /* setting color channel for non color scans */ scan.channel = _B0 (param->channel); arrangeline = FIX_BY_HARD; if ((scan.resolution_x == 2400) || ((scan.resolution_x == 4800))) { if (scan.colormode != CM_COLOR) { if (scan.colormode == CM_GRAY) { if (scan.channel == 3) arrangeline = FIX_BY_SOFT; } } else arrangeline = FIX_BY_SOFT; } /* setting scan type */ if ((param->scantype > 0) && (param->scantype < 4)) scan.scantype = param->scantype; else scan.scantype = ST_NORMAL; /* setting scanner lamp */ data_bitset (&dev->init_regs[0x146], 0x40, ((dev->sensorcfg->type == CIS_SENSOR) ? 0 : 1)); /* turn on appropiate lamp */ if (scan.scantype == ST_NORMAL) Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); else Lamp_Status_Set (dev, NULL, TRUE, TMA_LAMP); mybuffer[0] = 0; if (RTS_IsExecuting (dev, mybuffer) == FALSE) RTS_WriteRegs (dev->usb_handle, dev->init_regs); if (scan.depth == 16) compression = FALSE; /* resetting low level config */ bzero (&hwdcfg, sizeof (struct st_hwdconfig)); /* setting low level config */ hwdcfg.scantype = scan.scantype; hwdcfg.calibrate = mybuffer[0]; hwdcfg.arrangeline = arrangeline; /*1 */ hwdcfg.highresolution = (scan.resolution_x > 1200) ? TRUE : FALSE; hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance; SetScanParams (dev, dev->init_regs, &scan, &hwdcfg); scan.shadinglength = (((scan.sensorresolution * 17) / 2) + 3) & 0xfffffffc; rst = OK; } DBG (DBG_FNC, "- RTS_Scanner_SetParams: %i\n", rst); return rst; } static SANE_Int SetScanParams (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg) { struct st_coords mycoords; SANE_Int mycolormode; SANE_Int myvalue; SANE_Int mymode; SANE_Int channel_size; SANE_Int channel_count; SANE_Int dots_per_block; SANE_Int aditional_dots; DBG (DBG_FNC, "+ SetScanParams:\n"); dbg_ScanParams (scancfg); dbg_hwdcfg (hwdcfg); bzero (&mycoords, sizeof (struct st_coords)); /* Copy scancfg to scan2 */ memcpy (&scan2, scancfg, sizeof (struct st_scanparams)); mycolormode = scancfg->colormode; myvalue = scancfg->colormode; scantype = hwdcfg->scantype; if (scancfg->colormode == CM_LINEART) scan2.depth = 8; if ((scancfg->colormode != CM_COLOR) && (scancfg->channel == 3)) /*channel = 0x00 */ { if (scancfg->colormode == CM_GRAY) { mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR; } else mycolormode = 3; myvalue = mycolormode; } dev->Resize->resolution_x = scancfg->resolution_x; dev->Resize->resolution_y = scancfg->resolution_y; mymode = RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scancfg->resolution_x); /*0x0b */ if (mymode == -1) { /* Non supported resolution. We will resize image after scanning */ SANE_Int fitres; fitres = Scanmode_fitres (dev, hwdcfg->scantype, scancfg->colormode, scancfg->resolution_x); if (fitres != -1) { /* supported resolution found */ dev->Resize->type = RSZ_DECREASE; } else { dev->Resize->type = RSZ_INCREASE; fitres = Scanmode_maxres (dev, hwdcfg->scantype, scancfg->colormode); } scan2.resolution_x = fitres; scan2.resolution_y = fitres; mymode = RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scan2.resolution_x); if (mymode == -1) return ERROR; imageheight = scancfg->coord.height; dev->Resize->towidth = scancfg->coord.width; /* Calculate coords for new resolution */ mycoords.left = (scan2.resolution_x * scancfg->coord.left) / dev->Resize->resolution_x; mycoords.width = (scan2.resolution_x * scancfg->coord.width) / dev->Resize->resolution_x; mycoords.top = (scan2.resolution_y * scancfg->coord.top) / dev->Resize->resolution_y; mycoords.height = ((scan2.resolution_y * scancfg->coord.height) / dev->Resize->resolution_y) + 2; switch (scan2.colormode) { case CM_GRAY: if ((dev->scanmodes[mymode]->samplerate == PIXEL_RATE) && (mycolormode != 3)) dev->Resize->towidth *= 2; channel_size = (scan2.depth == 8) ? 1 : 2; dev->Resize->mode = (scan2.depth == 8) ? RSZ_GRAYL : RSZ_GRAYH; dev->Resize->bytesperline = dev->Resize->towidth * channel_size; break; case CM_LINEART: if (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) dev->Resize->towidth *= 2; dev->Resize->mode = RSZ_LINEART; dev->Resize->bytesperline = (dev->Resize->towidth + 7) / 8; break; default: /*CM_COLOR */ channel_count = 3; channel_size = (scan2.depth == 8) ? 1 : 2; dev->Resize->mode = (scan2.depth == 8) ? RSZ_COLOURL : RSZ_COLOURH; dev->Resize->bytesperline = scancfg->coord.width * (channel_count * channel_size); break; } } else { /* Supported scanmode */ dev->Resize->type = RSZ_NONE; scan2.resolution_x = scancfg->resolution_x; scan2.resolution_y = scancfg->resolution_y; mycoords.left = scancfg->coord.left; mycoords.top = scancfg->coord.top; mycoords.width = scancfg->coord.width; mycoords.height = scancfg->coord.height; } scancfg->timing = dev->scanmodes[mymode]->timing; scan2.sensorresolution = dev->timings[scancfg->timing]->sensorresolution; if ((scantype > 0) && (scantype < 5)) scan2.shadinglength = (((scan2.sensorresolution * 17) / 2) + 3) & 0xfffffffc; scancfg->sensorresolution = scan2.sensorresolution; scancfg->shadinglength = scan2.shadinglength; dev->scanning->arrange_compression = ((mycolormode != CM_LINEART) && (scan2.depth <= 8)) ? hwdcfg->compression : FALSE; if ((arrangeline2 == FIX_BY_HARD) || (mycolormode == CM_LINEART)) arrangeline2 = mycolormode; /*¿? */ else if ((mycolormode == CM_GRAY) && (hwdcfg->highresolution == FALSE)) arrangeline2 = 0; if (hwdcfg->highresolution == FALSE) { /* resolution < 1200 dpi */ dev->scanning->arrange_hres = FALSE; dev->scanning->arrange_sensor_evenodd_dist = 0; } else { /* resolution > 1200 dpi */ dev->scanning->arrange_hres = TRUE; dev->scanning->arrange_sensor_evenodd_dist = hwdcfg->sensorevenodddistance; } /* with must be adjusted to fit in the dots count per block */ aditional_dots = 0; if (mycolormode != CM_LINEART) { dots_per_block = ((scan2.resolution_x > 2400) && (scancfg->samplerate == PIXEL_RATE)) ? 8 : 4; /* fit width */ if ((mycoords.width % dots_per_block) != 0) { aditional_dots = dots_per_block - (mycoords.width % dots_per_block); mycoords.width += aditional_dots; } } else { /* Lineart */ dots_per_block = 32 - (mycoords.width & 0x1f); if (dots_per_block < 32) { mycoords.width += dots_per_block; aditional_dots = (dots_per_block / 8); } } DBG (DBG_FNC, " -> dots_per_block: %i\n", dots_per_block); DBG (DBG_FNC, " -> aditional_dots: %i\n", aditional_dots); if (mycolormode == CM_LINEART) { bytesperline = (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) ? mycoords.width / 4 : mycoords.width / 8; imagewidth3 = bytesperline; lineart_width = bytesperline * 8; line_size = bytesperline - aditional_dots; dev->Resize->fromwidth = line_size * 8; } else { /*4510 */ switch (mycolormode) { case CM_COLOR: channel_count = 3; break; case 3: channel_count = 1; break; case CM_GRAY: channel_count = (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) ? 2 : 1; /*1 */ break; } channel_size = (scan2.depth == 8) ? 1 : 2; bytesperline = mycoords.width * (channel_count * channel_size); imagewidth3 = bytesperline / channel_count; lineart_width = imagewidth3 / channel_size; line_size = bytesperline - (aditional_dots * (channel_count * channel_size)); dev->Resize->fromwidth = line_size / (channel_count * channel_size); } imagesize = mycoords.height * bytesperline; v15b4 = 0; dev->scanning->arrange_size = imagesize; v15bc = 0; /* set resolution ratio */ data_bitset (&Regs[0xc0], 0x1f, scancfg->sensorresolution / scancfg->resolution_x); scancfg->coord.left = mycoords.left; scancfg->coord.top = mycoords.top; scancfg->coord.width = mycoords.width; scancfg->coord.height = mycoords.height; scancfg->resolution_x = scan2.resolution_x; scancfg->resolution_y = scan2.resolution_y; myvalue = (dev->Resize->type == RSZ_NONE) ? line_size : dev->Resize->bytesperline; scancfg->bytesperline = bytesperline; scancfg->v157c = myvalue; if (scan.colormode != CM_COLOR) { if (mycolormode == CM_COLOR) scancfg->v157c = (scancfg->v157c / 3); } if (scan.colormode == CM_LINEART) { if (mycolormode == 3) { scancfg->v157c = (scancfg->v157c + 7) / 8; scancfg->bytesperline = (scancfg->bytesperline + 7) / 8; } } DBG (DBG_FNC, "- SetScanParams:\n"); return OK; } static SANE_Int GainOffset_Counter_Save (struct st_device *dev, SANE_Byte data) { SANE_Int rst = OK; DBG (DBG_FNC, "> GainOffset_Counter_Save(data=%i):\n", data); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { data = min (data, 0x0f); rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x0077, data); } return rst; } static SANE_Int GainOffset_Counter_Inc (struct st_device *dev, SANE_Int * arg1) { SANE_Byte count; SANE_Int rst; DBG (DBG_FNC, "+ GainOffset_Counter_Inc:\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { count = GainOffset_Counter_Load (dev); if ((count >= 0x0f) || (GainOffset_Get (dev) != OK)) { offset[CL_BLUE] = offset[CL_GREEN] = offset[CL_RED] = 0; gain[CL_BLUE] = gain[CL_GREEN] = gain[CL_RED] = 0; count = 0; } else { count++; if (arg1 != NULL) *arg1 = 1; } rst = GainOffset_Counter_Save (dev, count); } else rst = OK; DBG (DBG_FNC, "- GainOffset_Counter_Inc: %i\n", rst); return rst; } static SANE_Int GainOffset_Get (struct st_device *dev) { SANE_Int a, data, rst; SANE_Byte checksum; DBG (DBG_FNC, "+ GainOffset_Get:\n"); checksum = 0; /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { /* get current checksum */ if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x76, &checksum) == OK) { rst = OK; /* read gain and offset values from EEPROM */ for (a = CL_RED; a <= CL_BLUE; a++) { if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x70 + (2 * a), &data) == ERROR) { rst = ERROR; break; } else offset[a] = data; } /* check checksum */ checksum = _B0 (checksum + offset[CL_GREEN] + offset[CL_BLUE] + offset[CL_RED]); } else rst = ERROR; } else rst = ERROR; /* extract gain and offset values */ if ((rst == OK) && (checksum == 0x5b)) { for (a = CL_RED; a <= CL_BLUE; a++) { gain[a] = (offset[a] >> 9) & 0x1f; offset[a] &= 0x01ff; } } else { /* null values, let's reset them */ for (a = CL_RED; a <= CL_BLUE; a++) { gain[a] = 0; offset[a] = 0; } rst = ERROR; } DBG (DBG_FNC, "-> Preview gainR=%i, gainG=%i, gainB=%i, offsetR=%i, offsetG=%i, offsetB=%i\n", gain[CL_RED], gain[CL_GREEN], gain[CL_BLUE], offset[CL_RED], offset[CL_GREEN], offset[CL_BLUE]); DBG (DBG_FNC, "- GainOffset_Get: %i\n", rst); return rst; } static SANE_Int Scanmode_maxres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode) { /* returns position in scanmodes table where data fits with given arguments */ SANE_Int rst = 0; SANE_Int a; struct st_scanmode *reg; for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode)) rst = max (rst, reg->resolution); /* found ! */ } } if (rst == 0) { /* There isn't any mode for these arguments. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if (colormode == CM_LINEART) rst = Scanmode_maxres (dev, scantype, CM_GRAY); } DBG (DBG_FNC, "> Scanmode_maxres(scantype=%s, colormode=%s): %i\n", dbg_scantype (scantype), dbg_colour (colormode), rst); return rst; } static SANE_Int Scanmode_minres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode) { /* returns position in scanmodes table where data fits with given arguments */ SANE_Int rst, a; struct st_scanmode *reg; rst = Scanmode_maxres (dev, scantype, colormode); for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode)) rst = min (rst, reg->resolution); /* found ! */ } } if (rst == 0) { /* There isn't any mode for these arguments. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if (colormode == CM_LINEART) rst = Scanmode_minres (dev, scantype, CM_GRAY); } DBG (DBG_FNC, "> Scanmode_minres(scantype=%s, colormode=%s): %i\n", dbg_scantype (scantype), dbg_colour (colormode), rst); return rst; } static SANE_Int Scanmode_fitres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution) { /* returns a supported resolution */ SANE_Int rst; SANE_Int a, nullres; struct st_scanmode *reg; nullres = Scanmode_maxres (dev, scantype, colormode) + 1; rst = nullres; for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode)) { if ((reg->resolution < rst) && (resolution <= reg->resolution)) rst = reg->resolution; } } } if (rst == nullres) { /* There isn't any mode for these arguments. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if (colormode != CM_LINEART) { /* at this point, given resolution is bigger than maximum supported resolution */ rst = -1; } else rst = Scanmode_minres (dev, scantype, CM_GRAY); } DBG (DBG_FNC, "> Scanmode_fitres(scantype=%s, colormode=%s, resolution=%i): %i\n", dbg_scantype (scantype), dbg_colour (colormode), resolution, rst); return rst; } static SANE_Int RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution) { /* returns position in scanmodes table where data fits with given arguments */ SANE_Int rst = -1; SANE_Int a; struct st_scanmode *reg; for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode) && (reg->resolution == resolution)) { /* found ! */ rst = a; break; } } } if (rst == -1) { /* There isn't any mode for these arguments. May be given resolution isn't supported by chipset. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if ((colormode == CM_LINEART) || (colormode == 3)) rst = RTS_GetScanmode (dev, scantype, CM_GRAY, resolution); } DBG (DBG_FNC, "> RTS_GetScanmode(scantype=%s, colormode=%s, resolution=%i): %i\n", dbg_scantype (scantype), dbg_colour (colormode), resolution, rst); return rst; } static void Free_Motor (struct st_device *dev) { /* this function releases space for stepper motor */ DBG (DBG_FNC, "> Free_Motor\n"); if (dev->motorcfg != NULL) { free (dev->motorcfg); dev->motorcfg = NULL; } } static SANE_Int Load_Motor (struct st_device *dev) { /* this function loads general configuration for motor */ SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Motor\n"); if (dev->motorcfg != NULL) Free_Motor (dev); dev->motorcfg = malloc (sizeof (struct st_motorcfg)); if (dev->motorcfg != NULL) { rst = cfg_motor_get (dev->motorcfg); dbg_motorcfg (dev->motorcfg); } return rst; } static void Free_Sensor (struct st_device *dev) { /* this function releases space for ccd sensor */ DBG (DBG_FNC, "> Free_Sensor\n"); if (dev->sensorcfg != NULL) { free (dev->sensorcfg); dev->sensorcfg = NULL; } } static void Free_Buttons (struct st_device *dev) { /* this function releases space for buttons */ DBG (DBG_FNC, "> Free_Buttons\n"); if (dev->buttons != NULL) { free (dev->buttons); dev->buttons = NULL; } } static SANE_Int Load_Buttons (struct st_device *dev) { /* this function loads configuration for ccd sensor */ SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Buttons\n"); if (dev->buttons != NULL) Free_Buttons (dev); dev->buttons = malloc (sizeof (struct st_buttons)); if (dev->buttons != NULL) { rst = cfg_buttons_get (dev->buttons); dbg_buttons (dev->buttons); } return rst; } static SANE_Int Load_Sensor (struct st_device *dev) { /* this function loads configuration for ccd sensor */ SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Sensor\n"); if (dev->sensorcfg != NULL) Free_Sensor (dev); dev->sensorcfg = malloc (sizeof (struct st_sensorcfg)); if (dev->sensorcfg != NULL) { rst = cfg_sensor_get (dev->sensorcfg); dbg_sensor (dev->sensorcfg); } return rst; } static void Free_Timings (struct st_device *dev) { /* this function frees all ccd sensor timing tables */ DBG (DBG_FNC, "> Free_Timings\n"); if (dev->timings != NULL) { if (dev->timings_count > 0) { SANE_Int a; for (a = 0; a < dev->timings_count; a++) if (dev->timings[a] != NULL) free (dev->timings[a]); dev->timings_count = 0; } free (dev->timings); dev->timings = NULL; } } static SANE_Int Load_Timings (struct st_device *dev) { SANE_Int rst = OK; SANE_Int a; struct st_timing reg, *tmg; DBG (DBG_FNC, "> Load_Timings\n"); if (dev->timings != NULL) Free_Timings (dev); a = 0; while ((cfg_timing_get (dev->sensorcfg->type, a, ®) == OK) && (rst == OK)) { tmg = (struct st_timing *) malloc (sizeof (struct st_timing)); if (tmg != NULL) { memcpy (tmg, ®, sizeof (struct st_timing)); dev->timings_count++; dev->timings = (struct st_timing **) realloc (dev->timings, sizeof (struct st_timing **) * dev->timings_count); if (dev->timings == NULL) { rst = ERROR; dev->timings_count = 0; } else dev->timings[dev->timings_count - 1] = tmg; } else rst = ERROR; a++; } if (rst == ERROR) Free_Timings (dev); DBG (DBG_FNC, " -> Found %i timing registers\n", dev->timings_count); return rst; } static SANE_Int IsScannerLinked (struct st_device *dev) { SANE_Int var2; SANE_Byte lamp; DBG (DBG_FNC, "+ IsScannerLinked:\n"); Read_FE3E (dev, &v1619); Init_USBData (dev); scan.scantype = ST_NORMAL; RTS_WaitInitEnd (dev, 0x30000); lamp = FLB_LAMP; /* Comprobar si es la primera conexión con el escaner */ if (Read_Word (dev->usb_handle, 0xe829, &var2) == OK) { SANE_Int firstconnection; #ifdef STANDALONE firstconnection = TRUE; #else firstconnection = (var2 == 0) ? TRUE : FALSE; #endif if (firstconnection == TRUE) { /* primera conexión */ SANE_Byte flb_lamp, tma_lamp; flb_lamp = 0; tma_lamp = 0; Lamp_Status_Get (dev, &flb_lamp, &tma_lamp); if ((flb_lamp == 0) && (tma_lamp != 0)) lamp = TMA_LAMP; /*Clear GainOffset count */ GainOffset_Clear (dev); GainOffset_Counter_Save (dev, 0); /* Clear AutoRef count */ Refs_Counter_Save (dev, 0); Buttons_Enable (dev); Lamp_Status_Timer_Set (dev, 13); } else lamp = (_B0 (var2) == 0) ? FLB_LAMP : TMA_LAMP; } if (RTS_Warm_Reset (dev) != OK) return ERROR; Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); Lamp_Status_Timer_Set (dev, 13); /* Use fixed pwm? */ if (RTS_Debug->use_fixed_pwm != FALSE) { Lamp_PWM_Save (dev, cfg_fixedpwm_get (dev->sensorcfg->type, ST_NORMAL)); /* Lets enable using fixed pwm */ Lamp_PWM_SaveStatus (dev, TRUE); } Lamp_PWM_Setup (dev, lamp); DBG (DBG_FNC, "- IsScannerLinked:\n"); return OK; } static SANE_Int Lamp_PWM_SaveStatus (struct st_device *dev, SANE_Byte status) { SANE_Byte mypwm; SANE_Int rst = OK; DBG (DBG_FNC, "+ Lamp_PWM_SaveStatus(status=%i):\n", status); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { rst = ERROR; if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x007b, &mypwm) == OK) { mypwm = (status == FALSE) ? mypwm & 0x7f : mypwm | 0x80; if (RTS_EEPROM_WriteByte (dev->usb_handle, 0x007b, mypwm) == OK) rst = OK; } } DBG (DBG_FNC, "- Lamp_PWM_SaveStatus: %i\n", rst); return rst; } static SANE_Int Lamp_PWM_Save (struct st_device *dev, SANE_Int fixedpwm) { SANE_Int rst; DBG (DBG_FNC, "+ Lamp_PWM_Save(fixedpwm=%i):\n", fixedpwm); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x7b, ((fixedpwm << 2) | 0x80)); else rst = OK; DBG (DBG_FNC, "- Lamp_PWM_Save: %i\n", rst); return rst; } static SANE_Int Lamp_PWM_Setup (struct st_device *dev, SANE_Int lamp) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Lamp_PWM_Setup(lamp=%s):\n", (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP"); if (Lamp_PWM_use (dev, 1) == OK) { SANE_Int fixedpwm, currentpwd; currentpwd = 0; fixedpwm = cfg_fixedpwm_get (dev->sensorcfg->type, (lamp == FLB_LAMP) ? ST_NORMAL : ST_TA); if (Lamp_PWM_DutyCycle_Get (dev, ¤tpwd) == OK) { /* set duty cycle if current one is different */ if (currentpwd != fixedpwm) rst = Lamp_PWM_DutyCycle_Set (dev, fixedpwm); } else rst = Lamp_PWM_DutyCycle_Set (dev, fixedpwm); } DBG (DBG_FNC, "- Lamp_PWM_Setup: %i\n", rst); return rst; } static SANE_Int Lamp_PWM_DutyCycle_Get (struct st_device *dev, SANE_Int * data) { SANE_Byte a; SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Lamp_PWM_DutyCycle_Get:\n"); if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK) { *data = a & 0x3f; rst = OK; } DBG (DBG_FNC, "- Lamp_PWM_DutyCycle_Get = %i: %i\n", *data, rst); return rst; } static SANE_Int Lamp_PWM_DutyCycle_Set (struct st_device *dev, SANE_Int duty_cycle) { SANE_Byte *Regs; SANE_Int rst; DBG (DBG_FNC, "+ Lamp_PWM_DutyCycle_Set(duty_cycle=%i):\n", duty_cycle); rst = ERROR; Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { if (RTS_ReadRegs (dev->usb_handle, Regs) == OK) { data_bitset (&Regs[0x148], 0x3f, duty_cycle); if (pwmlamplevel == 0) { data_bitset (&Regs[0x148], 0x40, 0); Regs[0x1e0] |= ((duty_cycle >> 1) & 0x40); } data_bitset (&dev->init_regs[0x148], 0x7f, Regs[0x148]); data_bitset (&dev->init_regs[0x1e0], 0x3f, Regs[0x1e0]); Write_Byte (dev->usb_handle, 0xe948, Regs[0x0148]); rst = Write_Byte (dev->usb_handle, 0xe9e0, Regs[0x01e0]); } free (Regs); } DBG (DBG_FNC, "- Lamp_PWM_DutyCycle_Set: %i\n", rst); return rst; } static SANE_Int Head_ParkHome (struct st_device *dev, SANE_Int bWait, SANE_Int movement) { SANE_Int rst = ERROR; SANE_Byte *Regs; DBG (DBG_FNC, "+ Head_ParkHome(bWait=%i, movement=%i):\n", bWait, movement); Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { rst = OK; memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); /* Lets wait if it's required when is already executing */ if (bWait != FALSE) { if (RTS_WaitScanEnd (dev, 0x3a98) != OK) { DBG (DBG_FNC, " -> Head_ParkHome: RTS_WaitScanEnd Timeout\n"); rst = ERROR; /* timeout */ } } else { if (RTS_IsExecuting (dev, Regs) == FALSE) { DBG (DBG_FNC, " -> Head_ParkHome: RTS_IsExecuting = 0, exiting function\n"); rst = ERROR; /* if NOT executing */ } } /* Check if lamp is at home */ if ((rst == OK) && (Head_IsAtHome (dev, Regs) == FALSE)) { struct st_motormove mymotor; struct st_motorpos mtrpos; DBG (DBG_FNC, "-> Head_ParkHome: Lamp is not at home, lets move\n"); /* it isn't */ dev->status->parkhome = TRUE; if ((movement != -1) && (movement < dev->motormove_count)) { memcpy (&mymotor, dev->motormove[movement], sizeof (struct st_motormove)); } else { /* debug this code. Shouldn't have any relationship with offsets */ if (default_gain_offset->edcg2[CL_BLUE] < 4) mymotor.scanmotorsteptype = default_gain_offset->edcg2[CL_BLUE]; mymotor.ctpc = default_gain_offset->odcg2[1]; mymotor.systemclock = default_gain_offset->edcg2[1]; /*? */ } mtrpos.options = MTR_ENABLED | MTR_BACKWARD; mtrpos.v12e448 = 0x01; mtrpos.v12e44c = 0x00; mtrpos.coord_y = 0x4e20; Motor_Move (dev, Regs, &mymotor, &mtrpos); /* Should we wait? */ if (bWait != FALSE) rst = RTS_WaitScanEnd (dev, 15000); dev->status->parkhome = FALSE; } free (Regs); } DBG (DBG_FNC, "- Head_ParkHome: %i:\n", rst); return rst; } static SANE_Int Motor_Move (struct st_device *dev, SANE_Byte * Regs, struct st_motormove *mymotor, struct st_motorpos *mtrpos) { SANE_Byte *cpRegs; SANE_Int rst; DBG (DBG_FNC, "+ Motor_Move:\n"); rst = ERROR; cpRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (cpRegs != NULL) { SANE_Int data, v12dcf8, coord_y, step_type; memcpy (cpRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); v12dcf8 = 0; /* resolution = 1 dpi */ data_bitset (&cpRegs[0xc0], 0x1f, 1); /*---xxxxx*/ /* set motor step type */ data_bitset (&cpRegs[0xd9], 0x70, mymotor->scanmotorsteptype); /*-xxx----*/ /* set motor direction (polarity) */ data_bitset (&cpRegs[0xd9], 0x80, mtrpos->options >> 3); /*e------- */ /* next value doesn't seem to have any effect */ data_bitset (&cpRegs[0xd9], 0x0f, mtrpos->options); /*----efgh*/ /* 0 enable/1 disable motor */ data_bitset (&cpRegs[0xdd], 0x80, mtrpos->options >> 4); /*d------- */ /* next value doesn't seem to have any effect */ data_bitset (&cpRegs[0xdd], 0x40, mtrpos->options >> 4); /*-d------*/ switch (mymotor->scanmotorsteptype) { case STT_OCT: step_type = 8; break; case STT_QUART: step_type = 4; break; case STT_HALF: step_type = 2; break; case STT_FULL: step_type = 1; break; default: step_type = 0; break; /* shouldn't be used */ } coord_y = (mtrpos->coord_y * step_type) & 0xffff; if (coord_y < 2) coord_y = 2; /* Sets dummyline to 1 */ data_bitset (&cpRegs[0xd6], 0xf0, 1); /* set step_size - 1 */ cpRegs[0xe0] = 0; cpRegs[0x01] &= 0xf9; cpRegs[0x01] |= (mtrpos->v12e448 & 1) << 2; /* set dummy scan */ data_bitset (&cpRegs[0x01], 0x10, 1); /*---x----*/ /* set samplerate */ data_bitset (&cpRegs[0x1cf], 0x40, PIXEL_RATE); /*-x------*/ /* unknown data */ data_bitset (&cpRegs[0x1cf], 0x80, 1); /*x------- */ /* sets one chanel per color */ data_bitset (&cpRegs[0x12], 0x3f, 0); /* channel */ data_bitset (&cpRegs[0x12], 0xc0, 1); /* 1 channel */ /* timing cnpp */ data_bitset (&cpRegs[0x96], 0x3f, 0x0b); /*--001011*/ /* set systemclock */ data_bitset (&cpRegs[0x00], 0x0f, mymotor->systemclock); /*----xxxx*/ /* set last step of accurve.smearing table to 2 */ data_lsb_set (&cpRegs[0xe4], 2, 3); /* set last step of deccurve.scanbufferfull table to 16 */ data_lsb_set (&Regs[0xea], 0x10, 3); /* set last step of deccurve.normalscan table to 16 */ data_lsb_set (&Regs[0xed], 0x10, 3); /* set last step of deccurve.smearing table to 16 */ data_lsb_set (&Regs[0xf0], 0x10, 3); /* set last step of deccurve.parkhome table to 16 */ data_lsb_set (&Regs[0xf3], 0x10, 3); /* set msi */ cpRegs[0xda] = 2; cpRegs[0xdd] &= 0xfc; /* set if motor has motorcurves */ data_bitset (&cpRegs[0xdf], 0x10, ((mymotor->motorcurve != -1) ? 1 : 0)); if (mymotor->motorcurve != -1) { struct st_curve *crv; /* set last step of accurve.normalscan table */ crv = Motor_Curve_Get (dev, mymotor->motorcurve, ACC_CURVE, CRV_NORMALSCAN); if (crv != NULL) data_lsb_set (&cpRegs[0xe1], crv->step[crv->step_count - 1], 3); DBG (DBG_FNC, " -> Setting up stepper motor using motorcurve %i\n", mymotor->motorcurve); v12dcf8 = Motor_Setup_Steps (dev, cpRegs, mymotor->motorcurve); /* set step_size - 1 */ cpRegs[0xe0] = 0; crv = Motor_Curve_Get (dev, mymotor->motorcurve, DEC_CURVE, CRV_NORMALSCAN); if (crv != NULL) coord_y -= (v12dcf8 + crv->step_count); /* set line exposure time */ data_lsb_set (&cpRegs[0x30], mymotor->ctpc, 3); /* set last step of accurve.smearing table */ data_lsb_set (&cpRegs[0xe4], 0, 3); } else { /* Setting some motor step */ SANE_Int some_step; switch (Regs[0x00] & 0x0f) { case 0x00: some_step = 0x00895440; break; /* 3 x 0x2DC6C0 */ case 0x08: case 0x01: some_step = 0x00b71b00; break; /* 4 x 0x2DC6C0 */ case 0x02: some_step = 0x0112a880; break; /* 6 x 0x2DC6C0 */ case 0x0a: case 0x03: some_step = 0x016e3600; break; /* 8 x 0x2DC6C0 */ case 0x04: some_step = 0x02255100; break; /* 12 x 0x2DC6C0 */ case 0x0c: some_step = 0x02dc6c00; break; /* 16 x 0x2DC6C0 */ case 0x05: some_step = 0x044aa200; break; /* 24 x 0x2DC6C0 */ case 0x0d: some_step = 0x05b8d800; break; /* 32 x 0x2DC6C0 */ case 0x09: some_step = 0x00f42400; break; case 0x0b: some_step = 0x01e84800; break; /* = case 9 * 2 */ default: some_step = 0x0478f7f8; break; } /* divide by timing.cnpp */ some_step /= ((cpRegs[0x96] & 0x3f) + 1); if (mymotor->ctpc > 0) some_step /= mymotor->ctpc; /* set line exposure time */ data_lsb_set (&cpRegs[0x30], some_step, 3); /* set last step of accurve.normalscan table */ data_lsb_set (&cpRegs[0xe1], some_step, 3); } /* Setting coords */ RTS_Setup_Coords (cpRegs, 100, coord_y - 1, 800, 1); /* enable head movement */ data_bitset (&cpRegs[0xd8], 0x80, 1); /* release motor before executing */ Motor_Release (dev); RTS_Warm_Reset (dev); /* action! */ data = RTS_WriteRegs (dev->usb_handle, cpRegs); if (data == OK) RTS_Execute (dev); /* wait 10 seconds */ RTS_WaitScanEnd (dev, 10000); rst = (data != OK) ? v12dcf8 : RTS_WaitScanEnd (dev, 20000); free (cpRegs); } DBG (DBG_FNC, "- Motor_Move: %i\n", rst); return rst; } static void Free_Motormoves (struct st_device *dev) { DBG (DBG_FNC, "> Free_Motormoves\n"); if (dev->motormove != NULL) { SANE_Int a; struct st_motormove *ms; for (a = 0; a < dev->motormove_count; a++) { ms = dev->motormove[a]; if (ms != NULL) free (ms); } free (dev->motormove); dev->motormove = NULL; } dev->motormove_count = 0; } static void Free_MotorCurves (struct st_device *dev) { DBG (DBG_FNC, "> Free_MotorCurves\n"); if (dev->mtrsetting != NULL) Motor_Curve_Free (dev->mtrsetting, &dev->mtrsetting_count); dev->mtrsetting = NULL; dev->mtrsetting_count = 0; } static SANE_Int Load_MotorCurves (struct st_device *dev) { SANE_Int rst = ERROR; SANE_Int *mtc = NULL; if (dev->mtrsetting != NULL) Free_MotorCurves (dev); DBG (DBG_FNC, "> Load_MotorCurves\n"); /* get motor setttings buffer for this device */ mtc = cfg_motorcurve_get (); if (mtc != NULL) { /* parse buffer to get all motorcurves */ dev->mtrsetting = Motor_Curve_Parse (&dev->mtrsetting_count, mtc); if (dev->mtrsetting != NULL) rst = OK; } if (rst != ERROR) { DBG (DBG_FNC, " -> Found %i motor settings\n", dev->mtrsetting_count); dbg_motorcurves (dev); } else DBG (DBG_ERR, "- Load_MotorCurves error!!\n"); return rst; } static SANE_Int Load_Motormoves (struct st_device *dev) { SANE_Int rst = OK; SANE_Int a; struct st_motormove reg, *mm; DBG (DBG_FNC, "> Load_Motormoves\n"); /* if there is already any movement loaded let's free it */ if (dev->motormove != NULL) Free_Motormoves (dev); a = 0; while ((cfg_motormove_get (dev->sensorcfg->type, a, ®) != ERROR) && (rst == OK)) { dev->motormove_count++; dev->motormove = (struct st_motormove **) realloc (dev->motormove, sizeof (struct st_motormove **) * dev->motormove_count); if (dev->motormove != NULL) { mm = (struct st_motormove *) malloc (sizeof (struct st_motormove)); if (mm != NULL) { memcpy (mm, ®, sizeof (struct st_motormove)); dev->motormove[dev->motormove_count - 1] = mm; } else rst = ERROR; } else rst = ERROR; a++; } if (rst == ERROR) Free_Motormoves (dev); DBG (DBG_FNC, " -> Found %i motormoves\n", dev->motormove_count); dbg_motormoves (dev); return rst; } static SANE_Byte * Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, SANE_Int step) { steps = (SANE_Byte *) realloc (steps, sizeof (SANE_Byte) * (*bwriten + 3)); if (steps != NULL) { data_msb_set (&steps[*bwriten], step, 3); *bwriten += 3; } else *bwriten = 0; return steps; } static SANE_Int Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs, SANE_Int mysetting) { SANE_Int varx10, cont, last_acc_step, varx20, stepbuffer_size, mystep, bwriten; SANE_Int myvar, var1, myvalor, mybwriten; struct st_curve *mycurve; SANE_Byte *steps; DBG (DBG_FNC, "+ Motor_Setup_Steps(*Regs, motorsetting=%i):\n", mysetting); varx10 = 0; cont = 0; varx20 = 0; stepbuffer_size = (v15f8 << 4) & 0xffff; steps = NULL; bwriten = 0; deccurvecount = 0; acccurvecount = 0; last_acc_step = 0; /* mycurve points to acc normalscan steps table */ mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_NORMALSCAN); if (mycurve != NULL) { /* acccurvecount has the number of steps in acc normalscan table */ acccurvecount = mycurve->step_count; /* get last acccurve step from acc.normalscan step table */ last_acc_step = data_lsb_get (&Regs[0xe1], 3); /* sets pointer to acc.normalscan step table */ data_wide_bitset (&Regs[0xf6], 0x3fff, stepbuffer_size); /* Separate each step in three bytes */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) { mystep = mycurve->step[cont]; if (mystep <= last_acc_step) { acccurvecount = cont; break; } varx20 += mystep + 1; steps = Motor_AddStep (steps, &bwriten, mystep); } } if (acccurvecount == 0) { /* Write one step (last_acc_step + 0x01) to buffer */ acccurvecount++; varx20 += (last_acc_step + 1) + 1; steps = Motor_AddStep (steps, &bwriten, last_acc_step + 1); } /* write another step (last_acc_step) */ acccurvecount++; varx20 += last_acc_step + 1; steps = Motor_AddStep (steps, &bwriten, last_acc_step); /* get line exposure time */ myvar = data_lsb_get (&Regs[0x30], 3) + 1; var1 = (varx20 + myvar - 1) / myvar; var1 = ((var1 * myvar) + mycurve->step[0] - varx20) - 0x0d; if (steps != NULL) data_msb_set (&steps[0], var1, 3); /* dec.scanbufferfull step table */ /* set pointer to next table */ stepbuffer_size += (acccurvecount * 3); data_wide_bitset (&Regs[0xf8], 0x3fff, stepbuffer_size); /* set last step of deccurve.scanbufferfull table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_BUFFERFULL); deccurvecount = mycurve->step_count; data_lsb_set (&Regs[0xea], mycurve->step[mycurve->step_count - 1], 3); /* write another step mycurve->step_count,cont,last_acc_step */ deccurvecount++; steps = Motor_AddStep (steps, &bwriten, last_acc_step); /* Separate each step in three bytes */ if (mycurve->step_count > 1) for (cont = 0; cont < (mycurve->step_count - 1); cont++) { mystep = mycurve->step[cont]; if (mystep > last_acc_step) steps = Motor_AddStep (steps, &bwriten, mystep); else deccurvecount--; } myvalor = dev->mtrsetting[mysetting]->motorbackstep; if (myvalor > 0) { SANE_Int step_size = _B0 (Regs[0xe0]) + 1; myvalor = ((myvalor - deccurvecount) - acccurvecount) + 2; varx10 = myvalor; myvalor /= step_size; myvalor *= step_size; var1 = mycurve->step[mycurve->step_count - 1]; /* last deccurve step */ if (last_acc_step >= var1) var1 = last_acc_step + 1; deccurvecount += (varx10 - myvalor); myvalor = varx10 - myvalor; } else myvalor = varx10; if (myvalor > 0) for (cont = myvalor; cont > 0; cont--) steps = Motor_AddStep (steps, &bwriten, var1 - 1); /* write another step , bwriten tiene 4b */ steps = Motor_AddStep (steps, &bwriten, var1); /* acc.smearing step table */ if (Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING) != NULL) { /* acc.smearing curve enabled */ if (Motor_Curve_Equal (dev, mysetting, ACC_CURVE, CRV_SMEARING, CRV_NORMALSCAN) == TRUE) { /* acc.smearing pointer points to acc.normalscan table */ data_wide_bitset (&Regs[0xfa], 0x3fff, data_lsb_get (&Regs[0xf6], 2)); /* last step of acc.smearing table is the same as acc.normalscan */ data_lsb_set (&Regs[0xe4], data_lsb_get (&Regs[0xe1], 3), 3); } else { /* set pointer to next step table */ stepbuffer_size += (deccurvecount * 3); data_wide_bitset (&Regs[0xfa], 0x3fff, stepbuffer_size); /* set last step of acc.smearing table */ mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING); if (mycurve != NULL) { smearacccurvecount = mycurve->step_count; data_lsb_set (&Regs[0xe4], mycurve->step[mycurve->step_count - 1], 3); /* generate acc.smearing table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* acc.smearing curve disabled */ data_wide_bitset (&Regs[0xfa], 0x3fff, 0); } /* dec.smearing */ if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING) != NULL) { /* dec.smearing curve enabled */ if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_SMEARING, CRV_BUFFERFULL) == TRUE) { /* dec.smearing pointer points to dec.scanbufferfull table */ data_wide_bitset (&Regs[0x00fc], 0x3fff, data_lsb_get (&Regs[0x00f8], 2)); /* last step of dec.smearing table is the same as dec.scanbufferfull */ data_lsb_set (&Regs[0x00f0], data_lsb_get (&Regs[0x00ea], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0xfc], 0x3fff, stepbuffer_size); /* set last step of dec.smearing table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING); if (mycurve != NULL) { smeardeccurvecount = mycurve->step_count; data_lsb_set (&Regs[0xf0], mycurve->step[mycurve->step_count - 1], 3); /* generate dec.smearing table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* dec.smearing curve disabled */ data_wide_bitset (&Regs[0x00fc], 0x3fff, 0); } /* dec.normalscan */ if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN) != NULL) { /* dec.normalscan enabled */ if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_BUFFERFULL) == TRUE) { /* dec.normalscan pointer points to dec.scanbufferfull table */ data_wide_bitset (&Regs[0xfe], 0x3fff, data_lsb_get (&Regs[0xf8], 2)); /* last step of dec.normalscan table is the same as dec.scanbufferfull */ data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xea], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_SMEARING) == TRUE) { /* dec.normalscan pointer points to dec.smearing table */ data_wide_bitset (&Regs[0xfe], 0x3fff, data_lsb_get (&Regs[0xfc], 2)); /* last step of dec.normalscan table is the same as dec.smearing */ data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xf0], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0xfe], 0x3fff, stepbuffer_size); /* set last step of dec.normalscan table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN); if (mycurve != NULL) { data_lsb_set (&Regs[0xed], mycurve->step[mycurve->step_count - 1], 3); /* generate dec.normalscan table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* dec.normalscan disabled */ data_wide_bitset (&Regs[0xfe], 0x3fff, 0); } /* acc.parkhome */ if (Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME) != NULL) { /* parkhome curve enabled */ if (Motor_Curve_Equal (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE) { /* acc.parkhome pointer points to acc.normalscan table */ data_wide_bitset (&Regs[0x100], 0x3fff, data_lsb_get (&Regs[0xf6], 2)); /* last step of acc.parkhome table is the same as acc.normalscan */ data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe1], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE) { /* acc.parkhome pointer points to acc.smearing table */ data_wide_bitset (&Regs[0x100], 0x3fff, data_lsb_get (&Regs[0xfa], 2)); /* last step of acc.parkhome table is the same as acc.smearing */ data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe4], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0x100], 0x3fff, stepbuffer_size); /* set last step of acc.parkhome table */ mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME); if (mycurve != NULL) { data_lsb_set (&Regs[0xe7], mycurve->step[mycurve->step_count - 1], 3); /* generate acc.parkhome table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* parkhome curve is disabled */ /* acc.parkhome pointer points to 0 */ data_wide_bitset (&Regs[0x100], 0x3fff, 0); data_lsb_set (&Regs[0xe7], 16, 3); } /* dec.parkhome */ if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME) != NULL) { /* parkhome curve enabled */ if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_BUFFERFULL) == TRUE) { /* dec.parkhome pointer points to dec.scanbufferfull table */ data_wide_bitset (&Regs[0x102], 0x3fff, data_lsb_get (&Regs[0xf8], 2)); /* last step of dec.parkhome table is the same as dec.scanbufferfull */ data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xe4], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE) { /* dec.parkhome pointer points to dec.smearing table */ data_wide_bitset (&Regs[0x102], 0x3fff, data_lsb_get (&Regs[0xfe], 2)); /* last step of dec.parkhome table is the same as dec.smearing */ data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xf0], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE) { /* dec.parkhome pointer points to dec.normalscan table */ data_wide_bitset (&Regs[0x102], 0x3fff, data_lsb_get (&Regs[0xfe], 2)); /* last step of dec.parkhome table is the same as dec.normalscan */ data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xed], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0x102], 0x3fff, stepbuffer_size); /* set last step of dec.parkhome table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME); if (mycurve != NULL) { data_lsb_set (&Regs[0xf3], mycurve->step[mycurve->step_count - 1], 3); /* generate dec.parkhome table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* parkhome curve is disabled */ /* dec.parkhome pointer points to 0 */ data_wide_bitset (&Regs[0x102], 0x3fff, 0); data_lsb_set (&Regs[0xf3], 16, 3); } mybwriten = bwriten & 0x8000000f; if (mybwriten < 0) mybwriten = ((mybwriten - 1) | 0xfffffff0) + 1; if (mybwriten != 0) bwriten = (((bwriten & 0xffff) >> 0x04) + 1) << 0x04; bwriten = bwriten & 0xffff; /* display table */ DBG (DBG_FNC, " -> Direction Type Offset Last step\n"); DBG (DBG_FNC, " -> --------- -------------- ------ ---------\n"); DBG (DBG_FNC, " -> ACC_CURVE CRV_NORMALSCAN %6i %6i\n", data_lsb_get (&Regs[0x0f6], 2) & 0x3fff, data_lsb_get (&Regs[0x0e1], 3)); DBG (DBG_FNC, " -> ACC_CURVE CRV_SMEARING %6i %6i\n", data_lsb_get (&Regs[0x0fa], 2) & 0x3fff, data_lsb_get (&Regs[0x0e4], 3)); DBG (DBG_FNC, " -> ACC_CURVE CRV_PARKHOME %6i %6i\n", data_lsb_get (&Regs[0x100], 2) & 0x3fff, data_lsb_get (&Regs[0x0e7], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_NORMALSCAN %6i %6i\n", data_lsb_get (&Regs[0x0fe], 2) & 0x3fff, data_lsb_get (&Regs[0x0ed], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_SMEARING %6i %6i\n", data_lsb_get (&Regs[0x0fc], 2) & 0x3fff, data_lsb_get (&Regs[0x0f0], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_PARKHOME %6i %6i\n", data_lsb_get (&Regs[0x102], 2) & 0x3fff, data_lsb_get (&Regs[0x0f3], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_BUFFERFULL %6i %6i\n", data_lsb_get (&Regs[0x0f8], 2) & 0x3fff, data_lsb_get (&Regs[0x0ea], 3)); RTS_Warm_Reset (dev); /* send motor steps */ if (steps != NULL) { if (bwriten > 0) { /* lock */ SetLock (dev->usb_handle, Regs, TRUE); /* send steps */ RTS_DMA_Write (dev, 0x0000, v15f8, bwriten, steps); /* unlock */ SetLock (dev->usb_handle, Regs, FALSE); } free (steps); } DBG (DBG_FNC, "- Motor_Setup_Steps: %i\n", acccurvecount); return acccurvecount; } static SANE_Int Lamp_PWM_use (struct st_device *dev, SANE_Int enable) { SANE_Byte a, b; SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Lamp_PWM_use(enable=%i):\n", enable); if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK) { if (Read_Byte (dev->usb_handle, 0xe9e0, &b) == OK) { if (enable != 0) { if (pwmlamplevel != 0x00) { b |= 0x80; dev->init_regs[0x01e0] &= 0x3f; dev->init_regs[0x01e0] |= 0x80; } else { a |= 0x40; b &= 0x3f; dev->init_regs[0x0148] |= 0x40; dev->init_regs[0x01e0] &= 0x3f; } } else { b &= 0x7f; a &= 0xbf; } if (Write_Byte (dev->usb_handle, 0xe948, a) == OK) rst = Write_Byte (dev->usb_handle, 0xe9e0, b); } } DBG (DBG_FNC, "- Lamp_PWM_use: %i\n", rst); return rst; } static SANE_Int SSCG_Enable (struct st_device *dev) { SANE_Int rst; SANE_Int sscg; SANE_Byte data1, data2; SANE_Int enable, mode, clock; DBG (DBG_FNC, "+ SSCG_Enable:\n"); rst = cfg_sscg_get (&enable, &mode, &clock); if (rst == OK) { if ((Read_Byte (dev->usb_handle, 0xfe3a, &data1) == OK) && (Read_Byte (dev->usb_handle, 0xfe39, &data2) == OK)) { if (enable != FALSE) { /* clock values: 0=0.25%; 1=0.50%; 2=0.75%; 3=1.00% */ data2 = (mode == 0) ? data2 & 0x7f : data2 | 0x80; sscg = (data1 & 0xf3) | (((clock & 0x03) | 0x04) << 0x02); sscg = (sscg << 8) | data2; } else sscg = ((data1 & 0xef) << 8) | _B0 (data2); rst = Write_Word (dev->usb_handle, 0xfe39, sscg); } else rst = ERROR; } DBG (DBG_FNC, "- SSCG_Enable: %i\n", rst); return rst; } static void RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs) { /* this function sets top, midle and bottom reference voltages */ DBG (DBG_FNC, "> RTS_Setup_RefVoltages\n"); if (Regs != NULL) { SANE_Byte vrts, vrms, vrbs; cfg_refvoltages_get (dev->sensorcfg->type, &vrts, &vrms, &vrbs); /* Top Reference Voltage */ data_bitset (&Regs[0x14], 0xe0, vrts); /*xxx----- */ /* Middle Reference Voltage */ data_bitset (&Regs[0x15], 0xe0, vrms); /*xxx----- */ /* Bottom Reference Voltage */ data_bitset (&Regs[0x16], 0xe0, vrbs); /*xxx----- */ } } static SANE_Int Init_USBData (struct st_device *dev) { SANE_Byte data; SANE_Byte *resource; DBG (DBG_FNC, "+ Init_USBData:\n"); if (Read_Byte (dev->usb_handle, 0xf8ff, &data) != OK) return ERROR; data = (data | 1); if (Write_Byte (dev->usb_handle, 0xf8ff, data) != OK) return ERROR; if (SSCG_Enable (dev) != OK) return ERROR; Init_Registers (dev); /* Gamma table size = 0x100 */ data_bitset (&dev->init_regs[0x1d0], 0x30, 0x00); /*--00----*/ /* Set 3 channels_per_dot */ data_bitset (&dev->init_regs[0x12], 0xc0, 0x03); /*xx------ */ /* systemclock */ data_bitset (&dev->init_regs[0x00], 0x0f, 0x05); /*----xxxx*/ /* timing cnpp */ data_bitset (&dev->init_regs[0x96], 0x3f, 0x17); /*--xxxxxx*/ /* set sensor_channel_color_order */ data_bitset (&dev->init_regs[0x60a], 0x7f, 0x24); /*-xxxxxxx*/ /* set crvs */ data_bitset (&dev->init_regs[0x10], 0x1f, get_value (SCAN_PARAM, CRVS, 7, usbfile)); /*---xxxxx*/ /* set reference voltages */ RTS_Setup_RefVoltages (dev, dev->init_regs); dev->init_regs[0x11] |= 0x10; data_bitset (&dev->init_regs[0x26], 0x70, 5); /*-101----*/ dev->init_regs[0x185] = 0x88; dev->init_regs[0x186] = 0x88; /* SDRAM clock */ data = get_value (SCAN_PARAM, MCLKIOC, 8, usbfile); data_bitset (&dev->init_regs[0x187], 0x0f, 0x08); /*----xxxx*/ data_bitset (&dev->init_regs[0x187], 0xf0, data); /*xxxx---- */ data--; if (data < 7) { switch (data) { case 0: data |= 0xc0; break; case 1: data |= 0xa0; break; case 2: data |= 0xe0; break; case 3: data |= 0x90; break; case 4: data |= 0xd0; break; case 5: data |= 0xb0; break; case 6: data = (data & 0x0f); break; } dev->init_regs[0x187] = _B0 (data); } data_bitset (&dev->init_regs[0x26], 0x0f, 0); /*----0000*/ dev->init_regs[0x27] &= 0x3f; dev->init_regs[0x29] = 0x24; dev->init_regs[0x2a] = 0x10; dev->init_regs[0x150] = 0xff; dev->init_regs[0x151] = 0x13; dev->init_regs[0x156] = 0xf0; dev->init_regs[0x157] = 0xfd; if (dev->motorcfg->changemotorcurrent != FALSE) Motor_Change (dev, dev->init_regs, 3); dev->init_regs[0xde] = 0; data_bitset (&dev->init_regs[0xdf], 0x0f, 0); /* loads motor resource for this dev */ resource = cfg_motor_resource_get (&data); if ((resource != NULL) && (data > 1)) memcpy (&dev->init_regs[0x104], resource, data); /* this bit is set but I don't know its purpose */ dev->init_regs[0x01] |= 0x40; /*-1------*/ dev->init_regs[0x124] = 0x94; /* release motor */ Motor_Release (dev); DBG (DBG_FNC, "- Init_USBData:\n"); return OK; } static SANE_Int Init_Registers (struct st_device *dev) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Init_Registers:\n"); /* Lee dev->init_regs */ bzero (dev->init_regs, RT_BUFFER_LEN); RTS_ReadRegs (dev->usb_handle, dev->init_regs); Read_FE3E (dev, &v1619); if (dev->sensorcfg->type == CCD_SENSOR) { /* CCD sensor */ data_bitset (&dev->init_regs[0x11], 0xc0, 0); /*xx------ */ data_bitset (&dev->init_regs[0x146], 0x80, 1); /*x------- */ data_bitset (&dev->init_regs[0x146], 0x40, 1); /*-x------*/ } else { /* CIS sensor */ data_bitset (&dev->init_regs[0x146], 0x80, 0); /*0------- */ data_bitset (&dev->init_regs[0x146], 0x40, 0); /*-0------*/ data_bitset (&dev->init_regs[0x11], 0xc0, 2); /*xx------ */ data_bitset (&dev->init_regs[0xae], 0x3f, 0x14); /*--xxxxxx*/ data_bitset (&dev->init_regs[0xaf], 0x07, 1); /*-----xxx*/ dev->init_regs[0x9c] = dev->init_regs[0xa2] = dev->init_regs[0xa8] = (RTS_Debug->dev_model != UA4900) ? 1 : 0; dev->init_regs[0x9d] = dev->init_regs[0xa3] = dev->init_regs[0xa9] = 0; dev->init_regs[0x9e] = dev->init_regs[0xa4] = dev->init_regs[0xaa] = 0; dev->init_regs[0x9f] = dev->init_regs[0xa5] = dev->init_regs[0xab] = 0; dev->init_regs[0xa0] = dev->init_regs[0xa6] = dev->init_regs[0xac] = 0; dev->init_regs[0xa1] = dev->init_regs[0xa7] = dev->init_regs[0xad] = (RTS_Debug->dev_model != UA4900) ? 0x80 : 0; } /* disable CCD channels */ data_bitset (&dev->init_regs[0x10], 0xe0, 0); /*xxx----- */ data_bitset (&dev->init_regs[0x13], 0x80, 0); /*x------- */ /* enable timer to switch off lamp */ data_bitset (&dev->init_regs[0x146], 0x10, 1); /*---x----*/ /* set time to switch off lamp */ dev->init_regs[0x147] = 0xff; /* set last acccurve step */ data_lsb_set (&dev->init_regs[0xe1], 0x2af8, 3); /* set msi 0x02 */ dev->init_regs[0xda] = 0x02; data_bitset (&dev->init_regs[0xdd], 0x03, 0); /*------xx*/ /* set binary threshold high and low in little endian */ data_lsb_set (&dev->init_regs[0x19e], binarythresholdl, 2); data_lsb_set (&dev->init_regs[0x1a0], binarythresholdh, 2); data_bitset (&dev->init_regs[0x01], 0x08, 0); /*----x---*/ data_bitset (&dev->init_regs[0x16f], 0x40, 0); /*-x------*/ dev->init_regs[0x0bf] = (dev->init_regs[0x00bf] & 0xe0) | 0x20; dev->init_regs[0x163] = (dev->init_regs[0x0163] & 0x3f) | 0x40; data_bitset (&dev->init_regs[0xd6], 0x0f, 8); /*----xxxx*/ data_bitset (&dev->init_regs[0x164], 0x80, 1); /*x------- */ dev->init_regs[0x0bc] = 0x00; dev->init_regs[0x0bd] = 0x00; dev->init_regs[0x165] = (dev->init_regs[0x0165] & 0x3f) | 0x80; dev->init_regs[0x0ed] = 0x10; dev->init_regs[0x0be] = 0x00; dev->init_regs[0x0d5] = 0x00; dev->init_regs[0xee] = 0x00; dev->init_regs[0xef] = 0x00; dev->init_regs[0xde] = 0xff; /* set bit[4] has_curves = 0 | bit[0..3] unknown = 0 */ data_bitset (&dev->init_regs[0xdf], 0x10, 0); /*---x----*/ data_bitset (&dev->init_regs[0xdf], 0x0f, 0); /*----xxxx*/ /* Set motor type */ data_bitset (&dev->init_regs[0xd7], 0x80, dev->motorcfg->type); /*x------- */ if (dev->motorcfg->type == MT_ONCHIP_PWM) { data_bitset (&dev->init_regs[0x14e], 0x10, 1); /*---x----*/ /* set motorpwmfrequency */ data_bitset (&dev->init_regs[0xd7], 0x3f, dev->motorcfg->pwmfrequency); /*--xxxxxx*/ } dev->init_regs[0x600] &= 0xfb; dev->init_regs[0x1d8] |= 0x08; v160c_block_size = 0x04; mem_total = 0x80000; /* check and setup installed ram */ RTS_DMA_CheckType (dev, dev->init_regs); rst = RTS_DMA_WaitReady (dev, 1500); DBG (DBG_FNC, "- Init_Registers: %i\n", rst); return rst; } static SANE_Int Read_FE3E (struct st_device *dev, SANE_Byte * destino) { SANE_Int rst; DBG (DBG_FNC, "+ Read_FE3E:\n"); rst = ERROR; if (destino != NULL) { SANE_Byte data; if (Read_Byte (dev->usb_handle, 0xfe3e, &data) == 0) { *destino = data; rst = OK; DBG (DBG_FNC, " -> %02x\n", _B0 (data)); } } DBG (DBG_FNC, "- Read_FE3E: %i\n", rst); return rst; } static SANE_Int Head_IsAtHome (struct st_device *dev, SANE_Byte * Regs) { SANE_Int rst; DBG (DBG_FNC, "+ Head_IsAtHome:\n"); /* if returns TRUE, lamp is at home. Otherwise it returns FALSE */ rst = 0; if (Regs != NULL) { SANE_Byte data; if (Read_Byte (dev->usb_handle, 0xe96f, &data) == OK) { Regs[0x16f] = _B0 (data); rst = (data >> 6) & 1; } } rst = (rst == 1) ? TRUE : FALSE; DBG (DBG_FNC, "- Head_IsAtHome: %s\n", (rst == TRUE) ? "Yes" : "No"); return rst; } static SANE_Byte RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs) { SANE_Byte rst; DBG (DBG_FNC, "+ RTS_IsExecuting:\n"); rst = 0; if (Regs != NULL) { SANE_Byte data; if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) { Regs[0x00] = data; rst = (data >> 7) & 1; } } DBG (DBG_FNC, "- RTS_IsExecuting: %i\n", rst); return rst; } static SANE_Int RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs) { SANE_Byte data; SANE_Int rst; DBG (DBG_FNC, "+ RTS_WaitScanEnd(msecs=%i):\n", msecs); /* returns 0 if ok or timeout returns -1 if fails */ rst = ERROR; if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) { long ticks = GetTickCount () + msecs; rst = OK; while (((data & 0x80) != 0) && (ticks > GetTickCount ()) && (rst == OK)) { rst = Read_Byte (dev->usb_handle, 0xe800, &data); } } DBG (DBG_FNC, "- RTS_WaitScanEnd: Ending with rst=%i\n", rst); return rst; } static SANE_Int RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_Enable_CCD(*Regs, arg2=%i):\n", channels); if (Read_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4) == OK) { data_bitset (&Regs[0x10], 0xe0, channels); /*xxx----- */ data_bitset (&Regs[0x13], 0x80, channels >> 3); /*x------- */ Write_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4); rst = OK; } DBG (DBG_FNC, "- RTS_Enable_CCD: %i\n", rst); return rst; } static SANE_Int RTS_Warm_Reset (struct st_device *dev) { SANE_Byte data; SANE_Int rst; DBG (DBG_FNC, "+ RTS_Warm_Reset:\n"); rst = ERROR; if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) { data = (data & 0x3f) | 0x40; /*01------ */ if (Write_Byte (dev->usb_handle, 0xe800, data) == OK) { data &= 0xbf; /*-0------*/ rst = Write_Byte (dev->usb_handle, 0xe800, data); } } DBG (DBG_FNC, "- RTS_Warm_Reset: %i\n", rst); return rst; } static SANE_Int Lamp_Status_Timer_Set (struct st_device *dev, SANE_Int minutes) { SANE_Byte MyBuffer[2]; SANE_Int rst; DBG (DBG_FNC, "+ Lamp_Status_Timer_Set(minutes=%i):\n", minutes); MyBuffer[0] = dev->init_regs[0x0146] & 0xef; MyBuffer[1] = dev->init_regs[0x0147]; if (minutes > 0) { double rst, op2; minutes = _B0 (minutes); op2 = 2.682163611980331; MyBuffer[0x00] |= 0x10; rst = (minutes * op2); MyBuffer[0x01] = (SANE_Byte) floor (rst); } dev->init_regs[0x147] = MyBuffer[1]; dev->init_regs[0x146] = (dev->init_regs[0x146] & 0xef) | (MyBuffer[0] & 0x10); rst = Write_Word (dev->usb_handle, 0xe946, (SANE_Int) ((MyBuffer[1] << 8) + MyBuffer[0])); DBG (DBG_FNC, "- Lamp_Status_Timer_Set: %i\n", rst); return rst; } static SANE_Int Buttons_Enable (struct st_device *dev) { SANE_Int data, rst; DBG (DBG_FNC, "+ Buttons_Enable:\n"); if (Read_Word (dev->usb_handle, 0xe958, &data) == OK) { data |= 0x0f; rst = Write_Word (dev->usb_handle, 0xe958, data); } else rst = ERROR; DBG (DBG_FNC, "- Buttons_Enable: %i\n", rst); return rst; } static SANE_Int Buttons_Count (struct st_device *dev) { SANE_Int rst = 0; /* This chipset supports up to six buttons */ if (dev->buttons != NULL) rst = dev->buttons->count; DBG (DBG_FNC, "> Buttons_Count: %i\n", rst); return rst; } static SANE_Int Buttons_Status (struct st_device *dev) { SANE_Int rst = -1; SANE_Byte data; DBG (DBG_FNC, "+ Buttons_Status\n"); /* Each bit is 1 if button is not pressed, and 0 if it is pressed This chipset supports up to six buttons */ if (Read_Byte (dev->usb_handle, 0xe968, &data) == OK) rst = _B0 (data); DBG (DBG_FNC, "- Buttons_Status: %i\n", rst); return rst; } static SANE_Int Buttons_Released (struct st_device *dev) { SANE_Int rst = -1; SANE_Byte data; DBG (DBG_FNC, "+ Buttons_Released\n"); /* Each bit is 1 if button is released, until reading this register. Then entire register is cleared. This chipset supports up to six buttons */ if (Read_Byte (dev->usb_handle, 0xe96a, &data) == OK) rst = _B0 (data); DBG (DBG_FNC, "- Buttons_Released: %i\n", rst); return rst; } static SANE_Int Buttons_Order (struct st_device *dev, SANE_Int mask) { /* this is a way to order each button according to its bit in register 0xe968 */ SANE_Int rst = -1; if (dev->buttons != NULL) { SANE_Int a; for (a = 0; a < 6; a++) { if (dev->buttons->mask[a] == mask) { rst = a; break; } } } return rst; } static SANE_Int GainOffset_Clear (struct st_device *dev) { SANE_Int rst = OK; DBG (DBG_FNC, "+ GainOffset_Clear:\n"); /* clear offsets */ offset[CL_RED] = offset[CL_GREEN] = offset[CL_BLUE] = 0; /* save offsets */ /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { SANE_Int a; for (a = CL_RED; a <= CL_BLUE; a++) RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (2 * a), 0); /* update checksum */ rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, 0); } DBG (DBG_FNC, "- GainOffset_Clear: %i\n", rst); return rst; } static SANE_Int Lamp_Status_Get (struct st_device *dev, SANE_Byte * flb_lamp, SANE_Byte * tma_lamp) { /* The only reason that I think windows driver uses two variables to get which lamp is switched on instead of one variable is that some chipset model could have both lamps switched on, so I'm maintaining such var */ SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ Lamp_Status_Get:\n"); if ((flb_lamp != NULL) && (tma_lamp != NULL)) { SANE_Int data1; SANE_Byte data2; if (Read_Byte (dev->usb_handle, 0xe946, &data2) == OK) { if (Read_Word (dev->usb_handle, 0xe954, &data1) == OK) { rst = OK; *flb_lamp = 0; *tma_lamp = 0; switch (dev->chipset->model) { case RTS8822BL_03A: *flb_lamp = ((data2 & 0x40) != 0) ? 1 : 0; *tma_lamp = (((data2 & 0x20) != 0) && ((data1 & 0x10) == 1)) ? 1 : 0; break; default: if ((_B1 (data1) & 0x10) == 0) *flb_lamp = (data2 >> 6) & 1; else *tma_lamp = (data2 >> 6) & 1; break; } } } } DBG (DBG_FNC, "- Lamp_Status_Get: rst=%i flb=%i tma=%i\n", rst, _B0 (*flb_lamp), _B0 (*tma_lamp)); return rst; } static SANE_Int RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs) { SANE_Byte data; SANE_Int rst; long mytime; DBG (DBG_FNC, "+ RTS_DMA_WaitReady(msecs=%i):\n", msecs); rst = OK; mytime = GetTickCount () + msecs; while ((mytime > GetTickCount ()) && (rst == OK)) { if (Read_Byte (dev->usb_handle, 0xef09, &data) == OK) { if ((data & 1) == 0) usleep (1000 * 100); else break; } else rst = ERROR; } DBG (DBG_FNC, "- RTS_DMA_WaitReady: %i\n", rst); return rst; } static SANE_Int RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs) { SANE_Byte data; SANE_Int rst; long mytime; DBG (DBG_FNC, "+ RTS_WaitInitEnd(msecs=%i):\n", msecs); rst = OK; mytime = GetTickCount () + msecs; while ((mytime > GetTickCount ()) && (rst == OK)) { if (Read_Byte (dev->usb_handle, 0xf910, &data) == OK) { if ((data & 8) == 0) usleep (1000 * 100); else break; } else rst = ERROR; } DBG (DBG_FNC, "- RTS_WaitInitEnd: %i\n", rst); return rst; } static SANE_Int Motor_Change (struct st_device *dev, SANE_Byte * buffer, SANE_Byte value) { SANE_Int data, rst; DBG (DBG_FNC, "+ Motor_Change(*buffer, value=%i):\n", value); if (Read_Word (dev->usb_handle, 0xe954, &data) == OK) { data &= 0xcf; /*--00----*/ value--; switch (value) { case 2: data |= 0x30; break; /*--11----*/ case 1: data |= 0x20; break; /*--10----*/ case 0: data |= 0x10; break; /*--01----*/ } buffer[0x154] = _B0 (data); rst = Write_Byte (dev->usb_handle, 0xe954, buffer[0x154]); } else rst = ERROR; DBG (DBG_FNC, "- Motor_Change: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_DMA_Read(dmacs=%04x, options=%04x, size=%i., *buffer):\n", dmacs, options, size); /* is there any buffer to send? */ if ((buffer != NULL) && (size > 0)) { /* reset dma */ if (RTS_DMA_Reset (dev) == OK) { /* prepare dma to read */ if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == OK) { SANE_Int transferred; rst = Bulk_Operation (dev, BLK_READ, size, buffer, &transferred); } } } DBG (DBG_FNC, "- RTS_DMA_Read(): %i\n", rst); return rst; } static SANE_Int RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_DMA_Write(dmacs=%04x, options=%04x, size=%i., *buffer):\n", dmacs, options, size); /* is there any buffer to send? */ if ((buffer != NULL) && (size > 0)) { /* reset dma */ if (RTS_DMA_Reset (dev) == OK) { /* prepare dma to write */ if (RTS_DMA_Enable_Write (dev, dmacs, size, options) == OK) { SANE_Int transferred; SANE_Byte *check_buffer; check_buffer = (SANE_Byte *) malloc (size); if (check_buffer != NULL) { /* if some transfer fails we try again until ten times */ SANE_Int a; for (a = 10; a > 0; a--) { /* send buffer */ Bulk_Operation (dev, BLK_WRITE, size, buffer, &transferred); /* prepare dma to read */ if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == OK) { SANE_Int b = 0, diff = FALSE; /* read buffer */ Bulk_Operation (dev, BLK_READ, size, check_buffer, &transferred); /* check buffers */ while ((b < size) && (diff == FALSE)) { if (buffer[b] == check_buffer[b]) b++; else diff = TRUE; } /* if buffers are equal we can break loop */ if (diff == TRUE) { /* cancel dma */ RTS_DMA_Cancel (dev); /* prepare dma to write buffer again */ if (RTS_DMA_Enable_Write (dev, dmacs, size, options) != OK) break; } else { /* everything went ok */ rst = OK; break; } } else break; } /* free check buffer */ free (check_buffer); } else { /* for some reason it's not posible to allocate space to check sent buffer so we just write data */ Bulk_Operation (dev, BLK_WRITE, size, buffer, &transferred); rst = OK; } } } } DBG (DBG_FNC, "- RTS_DMA_Write(): %i\n", rst); return rst; } static SANE_Int RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs) { /* This function tries to detect what kind of RAM supports chipset */ /* Returns a value between 0 and 4. -1 means error */ SANE_Int rst = -1; DBG (DBG_FNC, "+ RTS_DMA_CheckType(*Regs):\n"); if (Regs != NULL) { SANE_Byte *out_buffer; /* define buffer to send */ out_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072); if (out_buffer != NULL) { SANE_Byte *in_buffer; /* define incoming buffer */ in_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072); if (in_buffer != NULL) { SANE_Int a, b, diff; /* fill outgoing buffer with a known pattern */ b = 0; for (a = 0; a < 2072; a++) { out_buffer[a] = b; b++; if (b == 0x61) b = 0; } /* let's send buffer with different ram types and compare incoming buffer until getting the right type */ for (a = 4; a >= 0; a--) { /* set ram type */ if (RTS_DMA_SetType (dev, Regs, a) != OK) break; /* wait 1500 miliseconds */ if (RTS_DMA_WaitReady (dev, 1500) == OK) { /* reset dma */ RTS_DMA_Reset (dev); /* write buffer */ RTS_DMA_Write (dev, 0x0004, 0x102, 2072, out_buffer); /* now read buffer */ RTS_DMA_Read (dev, 0x0004, 0x102, 2072, in_buffer); /* check buffers */ b = 0; diff = FALSE; while ((b < 2072) && (diff == FALSE)) { if (out_buffer[b] == in_buffer[b]) b++; else diff = TRUE; } /* if buffers are equal */ if (diff == FALSE) { SANE_Int data = 0; /* buffers are equal so we've found the right ram type */ memset (out_buffer, 0, 0x20); for (b = 0; b < 0x20; b += 2) out_buffer[b] = b; /* write buffer */ if (RTS_DMA_Write (dev, 0x0004, 0x0000, 0x20, out_buffer) == OK) { SANE_Int c = 0; diff = TRUE; do { c++; for (b = 1; b < 0x20; b += 2) out_buffer[b] = c; if (RTS_DMA_Write (dev, 0x0004, (_B0 (c) << 0x11) >> 0x04, 0x20, out_buffer) == OK) { if (RTS_DMA_Read (dev, 0x0004, 0x0000, 0x20, in_buffer) == OK) { b = 0; diff = FALSE; while ((b < 0x20) && (diff == FALSE)) { if (out_buffer[b] == in_buffer[b]) b++; else diff = TRUE; } if (diff == FALSE) data = c << 7; } } } while ((c < 0x80) && (diff == TRUE)); } switch (data) { case 16384: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x80; break; case 8192: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x60; break; case 4096: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x40; break; case 2048: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x20; break; case 1024: Regs[0x708] &= 0x1f; data = 0x200; break; case 128: Regs[0x708] &= 0x1f; break; } DBG (DBG_FNC, " -> data1 = 0x%08x\n", (data * 4) * 1024); DBG (DBG_FNC, " -> data2 = 0x%08x\n", data * 1024); DBG (DBG_FNC, " -> type = 0x%04x\n", Regs[0x708] >> 5); RTS_DMA_SetType (dev, Regs, Regs[0x708] >> 5); rst = OK; break; } } else break; } free (in_buffer); } free (out_buffer); } } DBG (DBG_FNC, "- RTS_DMA_CheckType(): %i\n", rst); return rst; } static SANE_Int RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, SANE_Byte ramtype) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_DMA_SetType(*Regs, ramtype=%i):\n", ramtype); if (Regs != NULL) { data_bitset (&Regs[0x708], 0x08, 0); /*----0---*/ if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK) { data_bitset (&Regs[0x708], 0xe0, ramtype); if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK) { data_bitset (&Regs[0x708], 0x08, 1); /*----1---*/ rst = Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]); } } } DBG (DBG_FNC, "- RTS_DMA_SetType: %i\n", rst); return rst; } static void Motor_Release (struct st_device *dev) { SANE_Byte data = 0; DBG (DBG_FNC, "+ Motor_Release:\n"); if (Read_Byte (dev->usb_handle, 0xe8d9, &data) == OK) { data |= 4; Write_Byte (dev->usb_handle, 0xe8d9, data); } DBG (DBG_FNC, "- Motor_Release:\n"); } static SANE_Byte GainOffset_Counter_Load (struct st_device *dev) { SANE_Byte data = 0x0f; DBG (DBG_FNC, "+ GainOffset_Counter_Load:\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x77, &data) != OK) data = 0x0f; DBG (DBG_FNC, "- GainOffset_Counter_Load: %i\n", _B0 (data)); return data; } static SANE_Int RTS_Execute (struct st_device *dev) { SANE_Byte e813, e800; SANE_Int ret; DBG (DBG_FNC, "+ RTS_Execute:\n"); e813 = 0; e800 = 0; ret = ERROR; if (Read_Byte (dev->usb_handle, 0xe800, &e800) == OK) { if (Read_Byte (dev->usb_handle, 0xe813, &e813) == OK) { e813 &= 0xbf; if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK) { e800 |= 0x40; if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK) { e813 |= 0x40; if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK) { e800 &= 0xbf; if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK) { usleep (1000 * 100); e800 |= 0x80; ret = Write_Byte (dev->usb_handle, 0xe800, e800); } } } } } } DBG (DBG_FNC, "- RTS_Execute: %i\n", ret); return ret; } static SANE_Int RTS_isTmaAttached (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_isTmaAttached:\n"); /* returns 0 if Tma is attached. Otherwise 1 */ if (Read_Word (dev->usb_handle, 0xe968, &rst) == OK) { rst = ((_B1 (rst) & 2) != 0) ? FALSE : TRUE; } else rst = TRUE; DBG (DBG_FNC, "- RTS_isTmaAttached: %s\n", (rst == TRUE) ? "Yes" : "No"); return rst; } static SANE_Int Gamma_AllocTable (SANE_Byte * table) { SANE_Int C; SANE_Int rst = OK; hp_gamma->depth = 8; for (C = 0; C < 3; C++) if (hp_gamma->table[C] == NULL) hp_gamma->table[C] = malloc (sizeof (SANE_Byte) * 256); if ((hp_gamma->table[CL_RED] != NULL) && (hp_gamma->table[CL_GREEN] != NULL) && (hp_gamma->table[CL_BLUE] != NULL)) { /* All tables allocated */ for (C = 0; C < 256; C++) { if ((table != NULL) && (RTS_Debug->EnableGamma == TRUE)) { /* fill gamma tables with user defined values */ hp_gamma->table[CL_RED][C] = table[C]; hp_gamma->table[CL_GREEN][C] = table[0x100 + C]; hp_gamma->table[CL_BLUE][C] = table[0x200 + C]; } else { hp_gamma->table[CL_RED][C] = C; hp_gamma->table[CL_GREEN][C] = C; hp_gamma->table[CL_BLUE][C] = C; } } /* Locate threshold of bw */ for (C = 0; C < 256; C++) if (hp_gamma->table[CL_RED][C] != 0) break; bw_threshold = C - 1; } else { /* Some alloc failed */ rst = ERROR; Gamma_FreeTables (); } DBG (DBG_FNC, "> Gamma_AllocTable: %i >> bw_threshold = %i\n", rst, bw_threshold); return rst; } static SANE_Int Gamma_Apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, struct st_gammatables *mygamma) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Gamma_Apply(*Regs, *scancfg, *hwdcfg, *mygamma):\n"); dbg_ScanParams (scancfg); if (hwdcfg->use_gamma_tables == FALSE) { DBG (DBG_FNC, "-> Gamma tables are not used\n"); v1600 = NULL; v1604 = NULL; v1608 = NULL; } else { /*390b */ SANE_Int table_size, buffersize, c; SANE_Byte channels, *gammabuffer; DBG (DBG_FNC, "-> Using gamma tables\n"); /* get channels count */ channels = 3; /* default */ if (scancfg->colormode != CM_COLOR) { if (scancfg->channel != 3) { if (scancfg->colormode != 3) channels = (scancfg->samplerate == PIXEL_RATE) ? 2 : 1; } } /* get size for gamma tables */ switch (mygamma->depth & 0x0c) { case 0: table_size = 0x100 + (mygamma->depth & 1); break; case 4: table_size = 0x400 + (mygamma->depth & 1); break; case 8: table_size = 0x1000 + (mygamma->depth & 1); break; default: table_size = 2; break; } /* allocate space for gamma buffer */ buffersize = table_size * channels; gammabuffer = (SANE_Byte *) malloc (buffersize * sizeof (SANE_Byte)); if (gammabuffer != NULL) { /* update gamma pointers for each channel */ v1600 = (SANE_Byte *) & mygamma->table[CL_RED]; v1604 = (SANE_Byte *) & mygamma->table[CL_GREEN]; v1608 = (SANE_Byte *) & mygamma->table[CL_BLUE]; /* include gamma tables into one buffer */ for (c = 0; c < channels; c++) memcpy (gammabuffer + (c * table_size), mygamma->table[c], table_size); /* send gamma buffer to scanner */ Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b] & 0xaf); rst = Gamma_SendTables (dev, Regs, gammabuffer, buffersize); Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); /* free gamma buffer */ free (gammabuffer); } else rst = ERROR; } return rst; } static SANE_Int Refs_Analyze_Pattern (struct st_scanparams *scancfg, SANE_Byte * scanned_pattern, SANE_Int * ler1, SANE_Int ler1order, SANE_Int * ser1, SANE_Int ser1order) { SANE_Int buffersize, xpos, ypos, coord, cnt, chn_size, dist, rst; double *color_sum, *color_dif, diff_max; SANE_Int vector[3]; DBG (DBG_FNC, "+ Refs_Analyze_Pattern(depth=%i, width=%i, height=%i, *scanned_pattern, *ler1, ler1order=%i, *ser1, ser1order=%i)\n", scancfg->depth, scancfg->coord.width, scancfg->coord.height, ler1order, ser1order); rst = ERROR; /* by default */ dist = 5; /* distance to compare */ chn_size = (scancfg->depth > 8) ? 2 : 1; buffersize = max (scancfg->coord.width, scancfg->coord.height); color_sum = (double *) malloc (sizeof (double) * buffersize); if (color_sum != NULL) { color_dif = (double *) malloc (sizeof (double) * buffersize); if (color_dif != NULL) { /*-------- 1st SER -------- */ coord = 1; if ((scancfg->coord.width - dist) > 1) { /* clear buffers */ bzero (color_sum, sizeof (double) * buffersize); bzero (color_dif, sizeof (double) * buffersize); for (xpos = 0; xpos < scancfg->coord.width; xpos++) { for (ypos = 0; ypos < 20; ypos++) color_sum[xpos] += data_lsb_get (scanned_pattern + (scancfg->coord.width * ypos) + xpos, chn_size); } diff_max = (ser1order != 0) ? color_sum[0] - color_sum[1] : color_sum[1] - color_sum[0]; color_dif[0] = diff_max; cnt = 1; do { color_dif[cnt] = (ser1order != 0) ? color_sum[cnt] - color_sum[cnt + dist] : color_sum[cnt + dist] - color_sum[cnt]; if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max)) { /*d4df */ diff_max = color_dif[cnt]; if (abs (color_dif[cnt] - color_dif[cnt - 1]) > abs (color_dif[coord] - color_dif[coord - 1])) coord = cnt; } cnt++; } while (cnt < (scancfg->coord.width - dist)); } vector[0] = coord + dist; /*-------- 1st LER -------- */ coord = 1; if ((scancfg->coord.height - dist) > 1) { /* clear buffers */ bzero (color_sum, sizeof (double) * buffersize); bzero (color_dif, sizeof (double) * buffersize); for (ypos = 0; ypos < scancfg->coord.height; ypos++) { for (xpos = vector[0]; xpos < scancfg->coord.width - dist; xpos++) color_sum[ypos] += data_lsb_get (scanned_pattern + (scancfg->coord.width * ypos) + xpos, chn_size); } diff_max = (ler1order != 0) ? color_sum[0] - color_sum[1] : color_sum[1] - color_sum[0]; color_dif[0] = diff_max; cnt = 1; do { color_dif[cnt] = (ler1order != 0) ? color_sum[cnt] - color_sum[cnt + dist] : color_sum[cnt + dist] - color_sum[cnt]; if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max)) { diff_max = color_dif[cnt]; if (abs (color_dif[cnt] - color_dif[cnt - 1]) > abs (color_dif[coord] - color_dif[coord - 1])) coord = cnt; } cnt++; } while (cnt < (scancfg->coord.height - dist)); } vector[1] = coord + dist; /*-------- 1st LER -------- */ if ((scancfg->coord.width - dist) > 1) { /* clear buffers */ bzero (color_sum, sizeof (double) * buffersize); bzero (color_dif, sizeof (double) * buffersize); for (xpos = 0; xpos < scancfg->coord.width; xpos++) { for (ypos = coord + 4; ypos < scancfg->coord.height; ypos++) color_sum[xpos] += data_lsb_get (scanned_pattern + (scancfg->coord.width * ypos) + xpos, chn_size); } diff_max = (ser1order != 0) ? color_sum[0] - color_sum[1] : color_sum[1] - color_sum[0]; color_dif[0] = diff_max; cnt = 1; do { color_dif[cnt] = (ser1order != 0) ? color_sum[cnt] - color_sum[cnt + dist] : color_sum[cnt + dist] - color_sum[cnt]; if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max)) { diff_max = color_dif[cnt]; if (abs (color_dif[cnt] - color_dif[cnt - 1]) > abs (color_dif[coord] - color_dif[coord - 1])) coord = cnt; } cnt++; } while (cnt < (scancfg->coord.width - dist)); } vector[2] = coord + dist; /* save image */ if (RTS_Debug->SaveCalibFile != FALSE) dbg_autoref (scancfg, scanned_pattern, vector[0], vector[2], vector[1]); /* assign values detected */ if (ser1 != NULL) *ser1 = vector[2]; if (ler1 != NULL) *ler1 = vector[1]; /* show values */ DBG (DBG_FNC, " -> Vectors found: x1=%i, x2=%i, y=%i\n", vector[0], vector[2], vector[1]); rst = OK; free (color_dif); } free (color_sum); } DBG (DBG_FNC, "- Refs_Analyze_Pattern: %i\n", rst); return rst; } static double get_shrd (double value, SANE_Int desp) { if (desp <= 0x40) return value / pow (2, desp); else return 0; } static char get_byte (double value) { unsigned int data; double temp; if (value > 0xffffffff) { temp = floor (get_shrd (value, 0x20)); temp *= pow (2, 32); value -= temp; } data = (unsigned int) value; data = _B0 (data); return data; } static SANE_Int Timing_SetLinearImageSensorClock (SANE_Byte * Regs, struct st_cph *cph) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Timing_SetLinearImageSensorClock(SANE_Byte *Regs, struct st_cph *cph)\n"); dbg_sensorclock (cph); if ((Regs != NULL) && (cph != NULL)) { Regs[0x00] = get_byte (cph->p1); Regs[0x01] = get_byte (get_shrd (cph->p1, 0x08)); Regs[0x02] = get_byte (get_shrd (cph->p1, 0x10)); Regs[0x03] = get_byte (get_shrd (cph->p1, 0x18)); Regs[0x04] &= 0x80; Regs[0x04] |= ((get_byte (get_shrd (cph->p1, 0x20))) & 0x0f); Regs[0x04] |= ((cph->ps & 1) << 6); Regs[0x04] |= ((cph->ge & 1) << 5); Regs[0x04] |= ((cph->go & 1) << 4); Regs[0x05] = get_byte (cph->p2); Regs[0x06] = get_byte (get_shrd (cph->p2, 0x08)); Regs[0x07] = get_byte (get_shrd (cph->p2, 0x10)); Regs[0x08] = get_byte (get_shrd (cph->p2, 0x18)); Regs[0x09] &= 0xf0; Regs[0x09] |= ((get_byte (get_shrd (cph->p2, 0x20))) & 0x0f); rst = OK; } DBG (DBG_FNC, "- Timing_SetLinearImageSensorClock: %i\n", rst); return rst; } static void RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming, SANE_Byte * Regs) { DBG (DBG_FNC, "+ RTS_Setup_SensorTiming(mytiming=%i, *Regs):\n", mytiming); if ((Regs != NULL) && (mytiming < dev->timings_count)) { struct st_timing *mt = dev->timings[mytiming]; if (mt != NULL) { dbg_timing (mt); /* Correlated-Double-Sample 1 & 2 */ data_bitset (&Regs[0x92], 0x3f, mt->cdss[0]); data_bitset (&Regs[0x93], 0x3f, mt->cdsc[0]); data_bitset (&Regs[0x94], 0x3f, mt->cdss[1]); data_bitset (&Regs[0x95], 0x3f, mt->cdsc[1]); data_bitset (&Regs[0x96], 0x3f, mt->cnpp); /* Linear image sensor transfer gates */ data_bitset (&Regs[0x45], 0x80, mt->cvtrp[0]); data_bitset (&Regs[0x45], 0x40, mt->cvtrp[1]); data_bitset (&Regs[0x45], 0x20, mt->cvtrp[2]); data_bitset (&Regs[0x45], 0x1f, mt->cvtrfpw); data_bitset (&Regs[0x46], 0x1f, mt->cvtrbpw); data_lsb_set (&Regs[0x47], mt->cvtrw, 1); data_lsb_set (&Regs[0x84], mt->cphbp2s, 3); data_lsb_set (&Regs[0x87], mt->cphbp2e, 3); data_lsb_set (&Regs[0x8a], mt->clamps, 3); data_lsb_set (&Regs[0x8d], mt->clampe, 3); if (dev->chipset->model == RTS8822L_02A) { if (mt->clampe == -1) data_lsb_set (&Regs[0x8d], mt->cphbp2e, 3); } Regs[0x97] = get_byte (mt->adcclkp[0]); Regs[0x98] = get_byte (get_shrd (mt->adcclkp[0], 0x08)); Regs[0x99] = get_byte (get_shrd (mt->adcclkp[0], 0x10)); Regs[0x9a] = get_byte (get_shrd (mt->adcclkp[0], 0x18)); Regs[0x9b] &= 0xf0; Regs[0x9b] |= ((get_byte (get_shrd (mt->adcclkp[0], 0x20))) & 0x0f); Regs[0xc1] = get_byte (mt->adcclkp[1]); Regs[0xc2] = get_byte (get_shrd (mt->adcclkp[1], 0x08)); Regs[0xc3] = get_byte (get_shrd (mt->adcclkp[1], 0x10)); Regs[0xc4] = get_byte (get_shrd (mt->adcclkp[1], 0x18)); Regs[0xc5] &= 0xe0; Regs[0xc5] |= ((get_byte (get_shrd (mt->adcclkp[1], 0x20))) & 0x0f); /* bit(4) = bit(0) */ Regs[0xc5] |= ((mt->adcclkp2e & 1) << 4); Timing_SetLinearImageSensorClock (&Regs[0x48], &mt->cph[0]); Timing_SetLinearImageSensorClock (&Regs[0x52], &mt->cph[1]); Timing_SetLinearImageSensorClock (&Regs[0x5c], &mt->cph[2]); Timing_SetLinearImageSensorClock (&Regs[0x66], &mt->cph[3]); Timing_SetLinearImageSensorClock (&Regs[0x70], &mt->cph[4]); Timing_SetLinearImageSensorClock (&Regs[0x7a], &mt->cph[5]); } } } static SANE_Int Motor_GetFromResolution (SANE_Int resolution) { SANE_Int ret; ret = 3; if (RTS_Debug->usbtype != USB11) { if (scan.scantype != ST_NORMAL) { /* scantype is ST_NEG or ST_TA */ if (resolution >= 600) ret = 0; } else if (resolution >= 1200) ret = 0; } else if (resolution >= 600) ret = 0; DBG (DBG_FNC, "> Motor_GetFromResolution(resolution=%i): %i\n", resolution, ret); return ret; } static SANE_Int SetMultiExposure (struct st_device *dev, SANE_Byte * Regs) { SANE_Int iValue, myctpc; DBG (DBG_FNC, "> SetMultiExposure:\n"); /* set motor has no curves */ data_bitset (&Regs[0xdf], 0x10, 0); /*---0----*/ /* select case systemclock */ switch (Regs[0x00] & 0x0f) { case 0x00: iValue = 0x00895440; break; /* 3 x 0x2DC6C0 */ case 0x08: case 0x01: iValue = 0x00b71b00; break; /* 4 x 0x2DC6C0 */ case 0x02: iValue = 0x0112a880; break; /* 6 x 0x2DC6C0 */ case 0x0a: case 0x03: iValue = 0x016e3600; break; /* 8 x 0x2DC6C0 */ case 0x04: iValue = 0x02255100; break; /* 12 x 0x2DC6C0 */ case 0x0c: iValue = 0x02dc6c00; break; /* 16 x 0x2DC6C0 */ case 0x05: iValue = 0x044aa200; break; /* 24 x 0x2DC6C0 */ case 0x0d: iValue = 0x05b8d800; break; /* 32 x 0x2DC6C0 */ case 0x09: iValue = 0x00f42400; break; case 0x0b: iValue = 0x01e84800; break; /* = case 9 * 2 */ default: iValue = 0x0478f7f8; break; } /* divide by timing.cnpp */ iValue /= ((Regs[0x96] & 0x3f) + 1); iValue /= dev->motorcfg->basespeedpps; /* get line exposure time */ myctpc = data_lsb_get (&Regs[0x30], 3) + 1; DBG (DBG_FNC, "CTPC -- SetMultiExposure -- 1 =%i\n", myctpc); /* if last step of accurve.normalscan table is lower than iValue ... */ if (data_lsb_get (&Regs[0xe1], 3) < iValue) { SANE_Int traget; SANE_Int step_size = _B0 (Regs[0xe0]) + 1; /* set exposure time [RED] if zero */ if (data_lsb_get (&Regs[0x36], 3) == 0) data_lsb_set (&Regs[0x36], myctpc - 1, 3); /* set exposure time [GREEN] if zero */ if (data_lsb_get (&Regs[0x3c], 3) == 0) data_lsb_set (&Regs[0x3c], myctpc - 1, 3); /* set exposure time [BLUE] if zero */ if (data_lsb_get (&Regs[0x42], 3) == 0) data_lsb_set (&Regs[0x42], myctpc - 1, 3); iValue = (iValue + 1) * step_size; /* update line exposure time */ traget = (((myctpc + iValue - 1) / myctpc) * myctpc); data_lsb_set (&Regs[0x30], traget - 1, 3); traget = (traget / step_size) - 1; data_lsb_set (&Regs[0x00e1], traget, 3); } /* 8300 */ return OK; } static SANE_Int data_lsb_get (SANE_Byte * address, SANE_Int size) { SANE_Int ret = 0; if ((address != NULL) && (size > 0) && (size < 5)) { SANE_Int a; SANE_Byte b; size--; for (a = size; a >= 0; a--) { b = address[a]; ret = (ret << 8) + b; } } return ret; } static SANE_Byte data_bitget (SANE_Byte * address, SANE_Int mask) { SANE_Int desp = 0; if (mask & 1); else if (mask & 2) desp = 1; else if (mask & 4) desp = 2; else if (mask & 8) desp = 3; else if (mask & 16) desp = 4; else if (mask & 32) desp = 5; else if (mask & 64) desp = 6; else if (mask & 128) desp = 7; return (*address & mask) >> desp; } static void data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data) { /* This function fills mask bits of just a byte with bits given in data */ if (mask & 1); else if (mask & 2) data <<= 1; else if (mask & 4) data <<= 2; else if (mask & 8) data <<= 3; else if (mask & 16) data <<= 4; else if (mask & 32) data <<= 5; else if (mask & 64) data <<= 6; else if (mask & 128) data <<= 7; *address = (*address & (0xff - mask)) | (data & mask); } static void data_wide_bitset (SANE_Byte * address, SANE_Int mask, SANE_Int data) { /* Setting bytes bit per bit mask is 4 bytes size Example: data = 0111010111 mask = 00000000 11111111 11000000 00000000 rst = 00000000 01110101 11000000 00000000 */ SANE_Int mymask, started = FALSE; if ((address != NULL) && (mask != 0)) { while (mask != 0) { mymask = _B0 (mask); if (started == FALSE) { if (mymask != 0) { SANE_Int a, myvalue; for (a = 0; a < 8; a++) if ((mymask & (1 << a)) != 0) break; myvalue = _B0 (data << a); myvalue >>= a; data_bitset (address, mymask, myvalue); data >>= (8 - a); started = TRUE; } } else { data_bitset (address, mymask, _B0 (data)); data >>= 8; } address++; mask >>= 8; } } } static void data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size) { if ((address != NULL) && (size > 0) && (size < 5)) { SANE_Int a; for (a = 0; a < size; a++) { address[a] = _B0 (data); data >>= 8; } } } static void data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size) { if ((address != NULL) && (size > 0) && (size < 5)) { SANE_Int a; for (a = size - 1; a >= 0; a--) { address[a] = _B0 (data); data >>= 8; } } } static SANE_Int data_swap_endianess (SANE_Int address, SANE_Int size) { SANE_Int rst = 0; if ((size > 0) && (size < 5)) { SANE_Int a; for (a = 0; a < size; a++) { rst = (rst << 8) | _B0 (address); address >>= 8; } } return rst; } static void Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution, SANE_Byte gainmode) { DBG (DBG_FNC, "> Lamp_SetGainMode(*Regs, resolution=%i, gainmode=%i):\n", resolution, gainmode); if (dev->chipset->model == RTS8822L_02A) { /* hp4370 */ SANE_Int data1, data2; data1 = data_lsb_get (&Regs[0x154], 2) & 0xfe7f; data2 = data_lsb_get (&Regs[0x156], 2); switch (resolution) { case 4800: data2 |= 0x40; data1 &= 0xffbf; break; case 100: case 150: case 200: case 300: case 600: case 1200: case 2400: data1 |= 0x40; data2 &= 0xffbf; break; } data_lsb_set (&Regs[0x154], data1, 2); data_lsb_set (&Regs[0x156], data2, 2); } else { /* hp3970 hp4070 ua4900 */ SANE_Int data; data = data_lsb_get (&Regs[0x154], 2) & 0xfe7f; data = (gainmode == FALSE) ? data | 0x0040 : data & 0xffbf; switch (resolution) { case 100: case 200: case 300: case 600: data |= 0x0100; break; case 2400: data |= 0x0180; break; case 1200: if (dev->sensorcfg->type == CIS_SENSOR) data |= 0x80; else if (dev->sensorcfg->type == CCD_SENSOR) data |= 0x0180; break; } data_lsb_set (&Regs[0x0154], data, 2); } } static SANE_Int RTS_Scanner_StartScan (struct st_device *dev) { SANE_Int rst = ERROR; /* default */ SANE_Int data; DBG (DBG_FNC, "+ RTS_Scanner_StartScan():\n"); v14b4 = 1; /* TEMPORAL */ data = 0; Lamp_PWM_DutyCycle_Get (dev, &data); data = _B0 (data); DBG (DBG_FNC, "-> Pwm used = %i\n", data); /* windows driver saves pwm used, in file usbfile Section [SCAN_PARAM], field PwmUsed */ dev->status->cancel = FALSE; if (Scan_Start (dev) == OK) { SANE_Int transferred; rst = OK; if (dev->scanning->imagebuffer != NULL) { free (dev->scanning->imagebuffer); dev->scanning->imagebuffer = NULL; } SetLock (dev->usb_handle, NULL, (scan2.depth == 16) ? FALSE : TRUE); /* Reservamos los buffers necesarios para leer la imagen */ Reading_CreateBuffers (dev); if (dev->Resize->type != RSZ_NONE) Resize_Start (dev, &transferred); /* 6729 */ RTS_ScanCounter_Inc (dev); } DBG (DBG_FNC, "- RTS_Scanner_StartScan: %i\n", rst); return rst; } static void Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count) { /* pPointer1 = FAB8 pPointer2 = FABC buffer = FAC0 channels_count = FAC4 */ SANE_Int value; SANE_Int channel_size; DBG (DBG_FNC, "> Triplet_Gray(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n", channels_count); channel_size = (scan2.depth > 8) ? 2 : 1; channels_count = channels_count / 2; while (channels_count > 0) { value = data_lsb_get (pPointer1, channel_size); data_lsb_set (buffer, value, channel_size); value = data_lsb_get (pPointer2, channel_size); data_lsb_set (buffer + channel_size, value, channel_size); pPointer1 += 2 * channel_size; pPointer2 += 2 * channel_size; buffer += 2 * channel_size; channels_count--; } } static void Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count) { /* Composing colour in lineart mode */ SANE_Int dots_count = 0; SANE_Int channel; SANE_Byte mask; SANE_Byte value; SANE_Int C; DBG (DBG_FNC, "> Triplet_Lineart(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n", channels_count); if (channels_count > 0) { dots_count = (channels_count + 1) / 2; while (dots_count > 0) { mask = 0x80; channel = 2; do { value = 0; for (C = 4; C > 0; C--) { value = (value << 2) + (((*pPointer2 & mask) << 1) | (*pPointer1 & mask)); mask = mask >> 1; } *buffer = value; buffer++; channel--; } while (channel > 0); pPointer2 += 2; pPointer1 += 2; dots_count--; } } } static SANE_Int Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /* buffer : fadc buffer_size : fae0 */ SANE_Int lines_count = 0; /* ebp */ SANE_Int channels_count = 0; /* fadc pisa buffer */ SANE_Int rst = ERROR; struct st_scanning *scn; DBG (DBG_FNC, "+ Arrange_NonColour(*buffer, buffer_size=%i, *transferred):\n", buffer_size); /* this is just to make code more legible */ scn = dev->scanning; if (scn->imagebuffer == NULL) { if ((scn->arrange_hres == TRUE) || (scan2.colormode == CM_LINEART)) { scn->bfsize = (scn->arrange_sensor_evenodd_dist + 1) * line_size; scn->imagebuffer = (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte)); if (scn->imagebuffer != NULL) { if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) == OK) { scn->channel_size = (scan2.depth == 8) ? 1 : 2; scn->desp1[CL_RED] = 0; scn->desp2[CL_RED] = scn->channel_size + (scn->arrange_sensor_evenodd_dist * line_size); scn->pColour2[CL_RED] = scn->imagebuffer + scn->desp2[CL_RED]; scn->pColour1[CL_RED] = scn->imagebuffer + scn->desp1[CL_RED]; rst = OK; } } } } else rst = OK; /* b0f4 */ if (rst == OK) { scn->imagepointer = scn->imagebuffer; lines_count = buffer_size / line_size; channels_count = line_size / scn->channel_size; while (lines_count > 0) { if (scan2.colormode == CM_LINEART) Triplet_Lineart (scn->pColour1[CL_RED], scn->pColour2[CL_RED], buffer, channels_count); else Triplet_Gray (scn->pColour1[CL_RED], scn->pColour2[CL_RED], buffer, channels_count); buffer += line_size; scn->arrange_size -= bytesperline; lines_count--; if (lines_count == 0) { if ((scn->arrange_size | v15bc) == 0) break; } rst = Read_Block (dev, line_size, scn->imagepointer, transferred); if (rst != OK) break; if (scn->arrange_hres == TRUE) { scn->desp2[CL_RED] = (line_size + scn->desp2[CL_RED]) % scn->bfsize; scn->desp1[CL_RED] = (line_size + scn->desp1[CL_RED]) % scn->bfsize; scn->pColour2[CL_RED] = scn->imagebuffer + scn->desp2[CL_RED]; scn->pColour1[CL_RED] = scn->imagebuffer + scn->desp1[CL_RED]; } /* b21d */ scn->imagepointer += line_size; if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) scn->imagepointer = scn->imagebuffer; } } /* 2246 */ DBG (DBG_FNC, "- Arrange_NonColour(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Resize_Decrease (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode) { /* to_buffer = FAC8 = 0x236200 to_resolution = FACC = 0x4b to_width = FAD0 = 0x352 from_buffer = FAD4 = 0x235460 from_resolution = FAD8 = 0x64 from_width = FADC = 0x46d myresize_mode = FAE0 = 1 */ SANE_Int rst = ERROR; SANE_Int channels = 0; /* fac8 */ SANE_Int depth = 0; /* fae0 */ SANE_Int color[3] = { 0, 0, 0 }; /* fab8 | fabc | fac0 */ SANE_Int to_pos = 0; /* fad4 */ SANE_Int rescont = 0; SANE_Int from_pos = 0; /* fab4 */ SANE_Int C; SANE_Int smres = 0; /* fab0 */ SANE_Int value; SANE_Int channel_size; to_resolution = to_resolution & 0xffff; from_resolution = from_resolution & 0xffff; DBG (DBG_FNC, "+ Resize_Decrease(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n", to_resolution, to_width, from_resolution, from_width, myresize_mode); if (myresize_mode != RSZ_LINEART) { switch (myresize_mode) { case RSZ_GRAYL: channels = 1; depth = 8; break; case RSZ_COLOURL: channels = 3; depth = 8; break; case RSZ_COLOURH: channels = 3; depth = 16; break; case RSZ_GRAYH: channels = 1; depth = 16; break; } channel_size = (depth > 8) ? 2 : 1; to_pos = 0; rescont = 0; while (to_pos < to_width) { from_pos++; if (from_pos > from_width) from_buffer -= (((depth + 7) / 8) * channels); rescont += to_resolution; if (rescont < from_resolution) { /* Adds 3 color channel values */ for (C = 0; C < channels; C++) { color[C] += data_lsb_get (from_buffer, channel_size) * to_resolution; from_buffer += channel_size; } } else { /* fc3c */ to_pos++; smres = to_resolution - (rescont - from_resolution); for (C = 0; C < channels; C++) { value = ((data_lsb_get (from_buffer, channel_size) * smres) + color[C]) / from_resolution; data_lsb_set (to_buffer, value, channel_size); color[C] = data_lsb_get (from_buffer, channel_size) * (rescont - from_resolution); to_buffer += channel_size; from_buffer += channel_size; } rescont -= from_resolution; } } rst = OK; } else { /* fd60 */ SANE_Int bit, pos, desp, rescont2; *to_buffer = 0; bit = 0; pos = 0; desp = 0; rescont = 0; rescont2 = 0; if (to_width > 0) { do { if (bit == 8) { /* fda6 */ bit = 0; to_buffer++; *to_buffer = 0; } rescont += to_resolution; if (rescont < from_resolution) { if ((*from_buffer & (0x80 >> desp)) != 0) rescont2 += to_resolution; } else { /*fdd5 */ pos++; rescont -= from_resolution; if ((*from_buffer & (0x80 >> desp)) != 0) /*fdee */ rescont2 += (to_resolution - rescont); if (rescont2 > (to_resolution / 2)) /* fe00 */ *to_buffer = _B0 (*to_buffer | (0x80 >> bit)); rescont2 = ((*from_buffer & (0x80 >> desp)) != 0) ? rescont : 0; bit++; } /* fe2f */ desp++; if (desp == 8) { desp = 0; from_buffer++; } } while (pos < to_width); } else rst = OK; } DBG (DBG_FNC, "- Resize_Decrease: %i\n", rst); return rst; } static SANE_Int Resize_Increase (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode) { /* to_buffer = FAC8 = 0x2353f0 to_resolution = FACC = 0x4b to_width = FAD0 = 0x352 from_buffer = FAD4 = 0x234650 from_resolution = FAD8 = 0x64 from_width = FADC = 0x46d myresize_mode = FAE0 = 1 */ SANE_Int rst = ERROR; SANE_Int desp; /* fac0 */ SANE_Byte *myp2; /* faac */ SANE_Int mywidth; /* fab4 fab8 */ SANE_Int mychannels; /* fabc */ SANE_Int channels = 0; /* faa4 */ SANE_Int depth = 0; /* faa8 */ SANE_Int pos = 0; /* fae0 */ SANE_Int rescount; SANE_Int val6 = 0; SANE_Int val7 = 0; SANE_Int value; /**/ DBG (DBG_FNC, "+ Resize_Increase(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n", to_resolution, to_width, from_resolution, from_width, myresize_mode); if (myresize_mode != RSZ_LINEART) { switch (myresize_mode) { case RSZ_GRAYL: channels = 1; depth = 8; break; case RSZ_COLOURL: channels = 3; depth = 8; break; case RSZ_COLOURH: channels = 3; depth = 16; break; case RSZ_GRAYH: channels = 1; depth = 16; break; } if (channels > 0) { SANE_Byte channel_size; SANE_Byte *p_dst; /* fac8 */ SANE_Byte *p_src; /* fad4 */ desp = to_buffer - from_buffer; myp2 = from_buffer; channel_size = (depth == 8) ? 1 : 2; for (mychannels = 0; mychannels < channels; mychannels++) { pos = 0; rescount = (from_resolution / 2) + to_resolution; p_src = myp2; p_dst = myp2 + desp; /* f938 */ val7 = data_lsb_get (p_src, channel_size); if (to_width > 0) { for (mywidth = 0; mywidth < to_width; mywidth++) { if (rescount >= to_resolution) { rescount -= to_resolution; val6 = val7; pos++; if (pos < from_width) { p_src += (channels * channel_size); val7 = data_lsb_get (p_src, channel_size); } } /*f9a5 */ data_lsb_set (p_dst, ((((to_resolution - rescount) * val6) + (val7 * rescount)) / to_resolution), channel_size); rescount += from_resolution; p_dst += (channels * channel_size); } } myp2 += channel_size; } rst = OK; } else rst = OK; } else { /* RSZ_LINEART mode */ /* fa02 */ /* to_buffer = FAC8 = 0x2353f0 to_resolution = FACC = 0x4b to_width = FAD0 = 0x352 from_buffer = FAD4 = 0x234650 from_resolution = FAD8 = 0x64 from_width = FADC = 0x46d myresize_mode = FAE0 = 1 */ SANE_Int myres2; /* fac8 */ SANE_Int sres; SANE_Int lfae0; SANE_Int lfad8; SANE_Int myres; SANE_Int cont = 1; SANE_Int someval; SANE_Int bit; /*lfaa8 */ myres2 = from_resolution; sres = (myres2 / 2) + to_resolution; value = _B0 (*from_buffer); bit = 0; lfae0 = 0; lfad8 = value >> 7; someval = lfad8; *to_buffer = 0; if (to_width > 0) { myres = to_resolution; to_resolution = myres / 2; do { if (sres >= myres) { sres -= myres; lfae0++; cont++; lfad8 = someval; if (lfae0 < from_width) { if (cont == 8) { cont = 0; from_buffer++; } bit = (((0x80 >> cont) & *from_buffer) != 0) ? 1 : 0; } } /*faa6 */ if ((((myres - sres) * lfad8) + (bit * sres)) > to_resolution) *to_buffer |= (0x80 >> bit); bit++; if (bit == 8) { bit = 0; to_buffer++; *to_buffer = 0; } to_width--; sres += myres2; } while (to_width > 0); rst = OK; } } DBG (DBG_FNC, "- Resize_Increase: %i\n", rst); return rst; } static SANE_Int Resize_Start (struct st_device *dev, SANE_Int * transferred) { SANE_Int rst = ERROR; struct st_resize *rz = dev->Resize; DBG (DBG_FNC, "+ Resize_Start(*transferred):\n"); if (Resize_CreateBuffers (dev, line_size, rz->bytesperline, rz->bytesperline) == ERROR) return ERROR; if (arrangeline2 == FIX_BY_SOFT) { /* fee0 */ if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); } else rst = Read_Block (dev, line_size, rz->v3624, transferred); /* ff03 */ /* Redimensionado */ switch (rz->type) { case RSZ_DECREASE: /* ff1b */ Resize_Decrease (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); break; case RSZ_INCREASE: /* ff69 */ rz->rescount = 0; Resize_Increase (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); if (arrangeline2 == FIX_BY_SOFT) { /* ffb1 */ if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); } else rst = Read_Block (dev, line_size, rz->v3624, transferred); /* ffe0 */ /* fff2 */ Resize_Increase (rz->v362c, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); break; } /* 002a */ DBG (DBG_FNC, "- Resize_Start(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, SANE_Int size2, SANE_Int size3) { SANE_Int rst = ERROR; struct st_resize *rz = dev->Resize; rz->v3624 = (SANE_Byte *) malloc ((size1 + 0x40) * sizeof (SANE_Byte)); rz->v3628 = (SANE_Byte *) malloc ((size2 + 0x40) * sizeof (SANE_Byte)); rz->v362c = (SANE_Byte *) malloc ((size3 + 0x40) * sizeof (SANE_Byte)); if ((rz->v3624 == NULL) || (rz->v3628 == NULL) || (rz->v362c == NULL)) Resize_DestroyBuffers (dev); else rst = OK; DBG (DBG_FNC, "> Resize_CreateBuffers(size1=%i, size2=%i, size3=%i): %i\n", size1, size2, size3, rst); return rst; } static SANE_Int Resize_DestroyBuffers (struct st_device *dev) { struct st_resize *rz = dev->Resize; if (rz->v3624 != NULL) free (rz->v3624); if (rz->v3628 != NULL) free (rz->v3628); if (rz->v362c != NULL) free (rz->v362c); rz->v3624 = NULL; rz->v3628 = NULL; rz->v362c = NULL; return OK; } static SANE_Int Reading_DestroyBuffers (struct st_device *dev) { DBG (DBG_FNC, "> Reading_DestroyBuffers():\n"); if (dev->Reading->DMABuffer != NULL) free (dev->Reading->DMABuffer); if (dev->scanning->imagebuffer != NULL) { free (dev->scanning->imagebuffer); dev->scanning->imagebuffer = NULL; } bzero (dev->Reading, sizeof (struct st_readimage)); return OK; } static SANE_Int Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs, SANE_Byte * gammatable, SANE_Int size) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Gamma_SendTables(*Regs, *gammatable, size=%i):\n", size); if ((gammatable != NULL) && (size > 0)) { SANE_Int transferred; SANE_Int first_table; SANE_Int cont = 0; SANE_Int retry = TRUE; SANE_Byte *mybuffer; /* lock */ SetLock (dev->usb_handle, Regs, TRUE); first_table = (data_lsb_get (&Regs[0x1b4], 2) & 0x3fff) >> 4; mybuffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * size); if (mybuffer != NULL) { /* Try to send buffer during 10 seconds */ long tick = GetTickCount () + 10000; while ((retry == TRUE) && (tick > GetTickCount ())) { retry = FALSE; /* Operation type 0x14 */ if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == OK) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, 0x0000, size, first_table) == OK) { /* Send data */ if (Bulk_Operation (dev, BLK_WRITE, size, gammatable, &transferred) == OK) { /* Send size to read */ if (RTS_DMA_Enable_Read (dev, 0x0000, size, first_table) == OK) { /* Retrieve data */ if (Bulk_Operation (dev, BLK_READ, size, mybuffer, &transferred) == OK) { /* Check data */ while ((cont < size) && (retry == FALSE)) { if (mybuffer[cont] != gammatable[cont]) retry = TRUE; cont++; } if (retry == FALSE) rst = OK; } } } } } } free (mybuffer); } /* unlock */ SetLock (dev->usb_handle, Regs, FALSE); } DBG (DBG_FNC, "- Gamma_SendTables: %i\n", rst); return rst; } static SANE_Int Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Gamma_GetTables(SANE_Byte *Gamma_buffer):\n"); if (Gamma_buffer == NULL) return ERROR; /* Operation type 0x14 */ if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == 0x00) { SANE_Int size = 768; if (RTS_DMA_Enable_Read (dev, 0x0000, size, 0) == OK) { SANE_Int transferred = 0; usleep (1000 * 500); /* Read buffer */ rst = Bulk_Operation (dev, BLK_READ, size, Gamma_buffer, &transferred); } } DBG (DBG_FNC, "- Gamma_GetTables: %i\n", rst); return rst; } static void Gamma_FreeTables () { SANE_Int c; DBG (DBG_FNC, "> Gamma_FreeTables()\n"); for (c = 0; c < 3; c++) { if (hp_gamma->table[c] != NULL) { free (hp_gamma->table[c]); hp_gamma->table[c] = NULL; } } use_gamma_tables = FALSE; } static void RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait) { SANE_Byte data; DBG (DBG_FNC, "+ RTS_Scanner_StopScan():\n"); data = 0; Reading_DestroyBuffers (dev); Resize_DestroyBuffers (dev); RTS_DMA_Reset (dev); data_bitset (&dev->init_regs[0x60b], 0x10, 0); data_bitset (&dev->init_regs[0x60a], 0x40, 0); if (Write_Buffer (dev->usb_handle, 0xee0a, &dev->init_regs[0x60a], 2) == OK) Motor_Change (dev, dev->init_regs, 3); usleep (1000 * 200); if (wait == FALSE) { Read_Byte (dev->usb_handle, 0xe801, &data); if ((data & 0x02) == 0) { if (Head_IsAtHome (dev, dev->init_regs) == FALSE) { /* clear execution bit */ data_bitset (&dev->init_regs[0x00], 0x80, 0); Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]); Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); } } } else { /*66a1 */ /* clear execution bit */ data_bitset (&dev->init_regs[0x00], 0x80, 0); Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]); if (Head_IsAtHome (dev, dev->init_regs) == FALSE) Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); } /*66e0 */ RTS_Enable_CCD (dev, dev->init_regs, 0); Lamp_Status_Timer_Set (dev, 13); DBG (DBG_FNC, "- RTS_Scanner_StopScan()\n"); } static SANE_Int Reading_CreateBuffers (struct st_device *dev) { SANE_Byte data; SANE_Int mybytesperline; SANE_Int mybuffersize, a, b; DBG (DBG_FNC, "+ Reading_CreateBuffers():\n"); data = 0; /* Gets BinarythresholdH */ if (Read_Byte (dev->usb_handle, 0xe9a1, &data) == OK) binarythresholdh = data; mybytesperline = (scan2.depth == 12) ? (bytesperline * 3) / 4 : bytesperline; dev->Reading->Max_Size = 0xfc00; dev->Reading->DMAAmount = 0; a = (RTS_Debug->dmabuffersize / 63); b = (((RTS_Debug->dmabuffersize - a) / 2) + a) >> 0x0f; mybuffersize = ((b << 6) - b) << 10; if (mybuffersize < 0x1f800) mybuffersize = 0x1f800; dev->Reading->DMABufferSize = mybuffersize; /*3FFC00 4193280 */ do { dev->Reading->DMABuffer = (SANE_Byte *) malloc (dev->Reading->DMABufferSize * sizeof (SANE_Byte)); if (dev->Reading->DMABuffer != NULL) break; dev->Reading->DMABufferSize -= dev->Reading->Max_Size; } while (dev->Reading->DMABufferSize >= dev->Reading->Max_Size); /* 6003 */ dev->Reading->Starting = TRUE; dev->Reading->Size4Lines = (mybytesperline > dev->Reading->Max_Size) ? mybytesperline : (dev->Reading->Max_Size / mybytesperline) * mybytesperline; dev->Reading->ImageSize = imagesize; read_v15b4 = v15b4; DBG (DBG_FNC, "- Reading_CreateBuffers():\n"); return OK; } static SANE_Int RTS_ScanCounter_Inc (struct st_device *dev) { /* Keep a count of the number of scans done by this scanner */ SANE_Int idata; DBG (DBG_FNC, "+ RTS_ScanCounter_Inc():\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { SANE_Byte cdata = 0; SANE_Byte somebuffer[26]; switch (dev->chipset->model) { case RTS8822L_02A: case RTS8822BL_03A: /* value is 4 bytes size starting from address 0x21 in msb format */ if (RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata) == OK) { idata = data_swap_endianess (idata, 4) + 1; idata = data_swap_endianess (idata, 4); RTS_EEPROM_WriteInteger (dev->usb_handle, 0x21, idata); } break; default: /* value is 4 bytes size starting from address 0x21 in lsb format */ bzero (&somebuffer, sizeof (somebuffer)); somebuffer[4] = 0x0c; RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata); data_lsb_set (&somebuffer[0], idata + 1, 4); RTS_EEPROM_ReadByte (dev->usb_handle, 0x003a, &cdata); somebuffer[25] = cdata; RTS_EEPROM_WriteBuffer (dev->usb_handle, 0x21, somebuffer, 0x1a); break; } } DBG (DBG_FNC, "- RTS_ScanCounter_Inc()\n"); return OK; } static SANE_Int RTS_ScanCounter_Get (struct st_device *dev) { /* Returns the number of scans done by this scanner */ SANE_Int idata = 0; DBG (DBG_FNC, "+ RTS_ScanCounter_Get():\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata); switch (dev->chipset->model) { case RTS8822L_02A: case RTS8822BL_03A: /* value is 4 bytes size starting from address 0x21 in msb format */ idata = data_swap_endianess (idata, 4); break; default: /* RTS8822L_01H */ /* value is 4 bytes size starting from address 0x21 in lsb format */ idata &= 0xffffffff; break; } } DBG (DBG_FNC, "- RTS_ScanCounter_Get(): %i\n", idata); return idata; } static SANE_Int Read_Image (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred) { SANE_Int rst; SANE_Byte mycolormode; DBG (DBG_FNC, "+ Read_Image(buffer_size=%i, *buffer, *transferred):\n", buffer_size); *transferred = 0; mycolormode = scan2.colormode; rst = ERROR; if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3)) mycolormode = 3; if (dev->Resize->type == RSZ_NONE) { if (arrangeline == FIX_BY_SOFT) { switch (mycolormode) { case CM_COLOR: rst = Arrange_Colour (dev, buffer, buffer_size, transferred); break; case 3: rst = Arrange_Compose (dev, buffer, buffer_size, transferred); break; default: rst = Arrange_NonColour (dev, buffer, buffer_size, transferred); break; } } else rst = Read_Block (dev, buffer_size, buffer, transferred); /*00fe */ } else rst = Read_ResizeBlock (dev, buffer, buffer_size, transferred); /*010d */ DBG (DBG_FNC, "- Read_Image(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Arrange_Compose (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /* fnb250 0600FA7C 05E10048 buffer 0600FA80 0000F906 buffer_size */ SANE_Byte *mybuffer = buffer; /* fa7c */ SANE_Int mydistance; /*ebp */ SANE_Int mydots; /*fa74 */ SANE_Int channel_size; SANE_Int c; struct st_scanning *scn; /*mywidth = fa70 */ DBG (DBG_FNC, "+ Arrange_Compose(*buffer, buffer_size=%i, *transferred):\n", buffer_size); channel_size = (scan2.depth == 8) ? 1 : 2; /* this is just to make code more legible */ scn = dev->scanning; if (scn->imagebuffer == NULL) { if (dev->sensorcfg->type == CCD_SENSOR) mydistance = (dev->sensorcfg->line_distance * scan2.resolution_y) / dev->sensorcfg->resolution; else mydistance = 0; if (mydistance != 0) { scn->bfsize = (scn->arrange_hres == TRUE) ? scn->arrange_sensor_evenodd_dist : 0; scn->bfsize = line_size * (scn->bfsize + (mydistance * 2) + 1); } else scn->bfsize = line_size * 2; /*b2f0 */ scn->imagebuffer = (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte)); if (scn->imagebuffer == NULL) return ERROR; scn->imagepointer = scn->imagebuffer; if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) == ERROR) return ERROR; /* Calculate channel displacements */ scn->arrange_orderchannel = FALSE; for (c = CL_RED; c <= CL_BLUE; c++) { if (mydistance == 0) { /*b34e */ if (scn->arrange_hres == FALSE) { if ((((dev->sensorcfg->line_distance * scan2.resolution_y) * 2) / dev->sensorcfg->resolution) == 1) scn->arrange_orderchannel = TRUE; if (scn->arrange_orderchannel == TRUE) scn->desp[c] = ((dev->sensorcfg->rgb_order[c] / 2) * line_size) + (channel_size * c); else scn->desp[c] = channel_size * c; } } else { /*b3e3 */ scn->desp[c] = (dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) + (channel_size * c); if (scn->arrange_hres == TRUE) { /*b43b */ scn->desp1[c] = scn->desp[c]; scn->desp2[c] = ((channel_size * 3) + scn->desp1[c]) + (scn->arrange_sensor_evenodd_dist * line_size); }; } } for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*b545 */ buffer_size /= line_size; mydots = line_size / (channel_size * 3); while (buffer_size > 0) { if (scn->arrange_orderchannel == FALSE) { /*b5aa */ if (scn->arrange_hres == TRUE) Triplet_Compose_HRes (scn->pColour1[CL_RED], scn->pColour1[CL_GREEN], scn->pColour1[CL_BLUE], scn->pColour2[CL_RED], scn->pColour2[CL_GREEN], scn->pColour2[CL_BLUE], mybuffer, mydots); else Triplet_Compose_LRes (scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], mybuffer, mydots); } else Triplet_Compose_Order (dev, scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], mybuffer, mydots); /*b5f8 */ mybuffer += line_size; scn->arrange_size -= bytesperline; if (scn->arrange_size < 0) v15bc--; buffer_size--; if (buffer_size == 0) { if ((scn->arrange_size | v15bc) == 0) return OK; } /*b63f */ if (Read_Block (dev, line_size, scn->imagepointer, transferred) == ERROR) return ERROR; for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { /*b663 */ scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize; scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize; scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else { /*b74a */ scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize; scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*b7be */ scn->imagepointer += line_size; if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) scn->imagepointer = scn->imagebuffer; } return OK; } static void Triplet_Compose_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, SANE_Byte * pBlue1, SANE_Byte * pRed2, SANE_Byte * pGreen2, SANE_Byte * pBlue2, SANE_Byte * buffer, SANE_Int Width) { SANE_Int Value; SANE_Int Channel_size; SANE_Int max_value; DBG (DBG_FNC, "> Triplet_Compose_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2 *pGreen2, *pBlue2, *buffer, Width=%i):\n", Width); Width /= 2; Channel_size = (scan2.depth > 8) ? 2 : 1; max_value = (1 << scan2.depth) - 1; while (Width > 0) { Value = data_lsb_get (pRed1, Channel_size) + data_lsb_get (pGreen1, Channel_size) + data_lsb_get (pBlue1, Channel_size); Value = min (Value, max_value); if (v1600 != NULL) { if (scan2.depth > 8) Value = *(v1600 + (Value >> 8)) | _B0 (Value); else Value = *(v1600 + Value); } data_lsb_set (buffer, Value, Channel_size); buffer += Channel_size; Value = data_lsb_get (pRed2, Channel_size) + data_lsb_get (pGreen2, Channel_size) + data_lsb_get (pBlue2, Channel_size); Value = min (Value, max_value); if (v1600 != NULL) { if (scan2.depth > 8) Value = *(v1600 + (Value >> 8)) | _B0 (Value); else Value = *(v1600 + Value); } data_lsb_set (buffer, Value, Channel_size); buffer += Channel_size; pRed1 += 6 * Channel_size; pGreen1 += 6 * Channel_size; pBlue1 += 6 * Channel_size; pRed2 += 6 * Channel_size; pGreen2 += 6 * Channel_size; pBlue2 += 6 * Channel_size; Width--; } } static void Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots) { SANE_Int Value; DBG (DBG_FNC, "> Triplet_Compose_Order(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n", dots); if (scan2.depth > 8) { /* c0fe */ dots = dots / 2; while (dots > 0) { Value = min (data_lsb_get (pRed, 2) + data_lsb_get (pGreen, 2) + data_lsb_get (pBlue, 2), 0xffff); if (v1600 != NULL) Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value); data_lsb_set (buffer, Value, 2); buffer += 2; pRed += 6; pGreen += 6; pBlue += 6; dots--; } } else { SANE_Byte *myp1, *myp2, *myp3; if (dev->sensorcfg->rgb_order[CL_RED] == 1) { myp1 = pRed; myp2 = pGreen; myp3 = pBlue; } else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1) { myp1 = pGreen; myp2 = pRed; myp3 = pBlue; } else { myp1 = pBlue; myp2 = pRed; myp3 = pGreen; } while (dots > 0) { Value = min (((*myp1 + *(line_size + myp1)) / 2) + *myp2 + *myp3, 0xff); *buffer = (v1600 == NULL) ? _B0 (Value) : *(v1600 + Value); buffer++; myp1 += 3; myp2 += 3; myp3 += 3; dots--; } } } static void Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots) { SANE_Int Value; SANE_Int Channel_size; SANE_Int max_value; DBG (DBG_FNC, "> Triplet_Compose_LRes(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n", dots); Channel_size = (scan2.depth > 8) ? 2 : 1; max_value = (1 << scan2.depth) - 1; /*bf59 */ while (dots > 0) { Value = data_lsb_get (pRed, Channel_size) + data_lsb_get (pGreen, Channel_size) + data_lsb_get (pBlue, Channel_size); Value = min (Value, max_value); if (v1600 != NULL) { if (scan2.depth > 8) Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value); else Value = _B0 (*(v1600 + Value)); } data_lsb_set (buffer, Value, Channel_size); buffer += Channel_size; pRed += Channel_size * 3; pGreen += Channel_size * 3; pBlue += Channel_size * 3; dots--; } } static void Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int Width) { SANE_Int Value; DBG (DBG_FNC, "> Triplet_Colour_Order(*pRed, *pGreen, *pBlue, *buffer, Width=%i):\n", Width); if (scan2.depth > 8) { Width = Width / 2; while (Width > 0) { Value = data_lsb_get (pRed, 2); data_lsb_set (buffer, Value, 2); Value = data_lsb_get (pGreen, 2); data_lsb_set (buffer + 2, Value, 2); Value = data_lsb_get (pBlue, 2); data_lsb_set (buffer + 4, Value, 2); pRed += 6; pGreen += 6; pBlue += 6; buffer += 6; Width--; } } else { SANE_Int Colour; if (dev->sensorcfg->rgb_order[CL_RED] == 1) Colour = CL_RED; else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1) Colour = CL_GREEN; else Colour = CL_BLUE; while (Width > 0) { switch (Colour) { case CL_RED: *buffer = (*pRed + *(pRed + line_size)) / 2; *(buffer + 1) = *pGreen; *(buffer + 2) = *pBlue; break; case CL_GREEN: *buffer = *pRed; *(buffer + 1) = ((*pGreen + *(pGreen + line_size)) / 2); *(buffer + 2) = *pBlue; break; case CL_BLUE: *buffer = *pRed; *(buffer + 1) = *pGreen; *(buffer + 2) = ((*pBlue + *(pBlue + line_size)) / 2); break; } pRed += 3; pGreen += 3; pBlue += 3; buffer += 3; Width--; } } } static void Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, SANE_Byte * pBlue1, SANE_Byte * pRed2, SANE_Byte * pGreen2, SANE_Byte * pBlue2, SANE_Byte * buffer, SANE_Int Width) { SANE_Int Value; SANE_Int channel_size; SANE_Int c; SANE_Byte *pPointers[6]; pPointers[0] = pRed1; pPointers[1] = pGreen1; pPointers[2] = pBlue1; pPointers[3] = pRed2; pPointers[4] = pGreen2; pPointers[5] = pBlue2; DBG (DBG_FNC, "> Triplet_Colour_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2, *pGreen2, *pBlue2, *buffer, Width=%i):\n", Width); channel_size = (scan2.depth > 8) ? 2 : 1; Width = Width / 2; while (Width > 0) { for (c = 0; c < 6; c++) { Value = data_lsb_get (pPointers[c], channel_size); data_lsb_set (buffer, Value, channel_size); pPointers[c] += (6 * channel_size); buffer += (channel_size); } Width--; } } static void Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer, SANE_Byte * pChannel1, SANE_Byte * pChannel2, SANE_Byte * pChannel3) { /* 05F0FA4C 04EBAE4A /CALL to Assumed StdFunc6 from hpgt3970.04EBAE45 05F0FA50 00234FF8 |Arg1 = 00234FF8 pChannel3 05F0FA54 002359EF |Arg2 = 002359EF pChannel2 05F0FA58 002363E6 |Arg3 = 002363E6 pChannel1 05F0FA5C 05D10048 |Arg4 = 05D10048 Buffer 05F0FA60 00000352 |Arg5 = 00000352 Width */ /* Esta funcion une los tres canales de color en un triplete Inicialmente cada color está separado en 3 buffers apuntados por pChannel1 ,2 y 3 */ SANE_Int Value; SANE_Int channel_size; SANE_Int c; SANE_Byte *pChannels[3]; pChannels[0] = pChannel3; pChannels[1] = pChannel2; pChannels[2] = pChannel1; DBG (DBG_FNC, "> Triplet_Colour_LRes(Width=%i, *Buffer2, *p1, *p2, *p3):\n", Width); channel_size = (scan2.depth > 8) ? 2 : 1; while (Width > 0) { /* ba74 */ for (c = 0; c < 3; c++) { Value = data_lsb_get (pChannels[c], channel_size); data_lsb_set (Buffer, Value, channel_size); pChannels[c] += channel_size; Buffer += channel_size; } Width--; } } static SANE_Int Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /*The Beach buffer = FA7C 05E30048 buffer_size = FA80 0000F906 */ SANE_Int rst = ERROR; /* fa68 */ SANE_Int lfa54; SANE_Int lfa58; SANE_Byte *pP1; /* fa5c */ SANE_Byte *pP2; /* fa60 */ SANE_Int bOk; struct st_resize *rz = dev->Resize; /* fa74 = Resize->resolution_y */ /* fa70 = Resize->resolution_x */ /* fa64 = scan2.resolution_y */ /* fa6c = scan2.resolution_x */ DBG (DBG_FNC, "+ Read_ResizeBlock(*buffer, buffer_size=%i, *transferred):\n", buffer_size); if (rz->type == RSZ_DECREASE) { lfa58 = 0; do { bOk = 1; if (arrangeline2 == FIX_BY_SOFT) { if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); } else rst = Read_Block (dev, line_size, rz->v3624, transferred); /*f2df */ Resize_Decrease (rz->v362c, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); rz->rescount += rz->resolution_y; if (rz->rescount > scan2.resolution_y) { /*f331 */ rz->rescount -= scan2.resolution_y; if (scan2.depth == 8) { /* f345 */ pP1 = rz->v3628; pP2 = rz->v362c; if (rz->mode == RSZ_LINEART) { /* f36b */ SANE_Int bit = 0; SANE_Byte *pP3 = rz->v362c; SANE_Int value; *buffer = 0; lfa54 = 0; while (lfa54 < rz->towidth) { if (bit == 8) { buffer++; *buffer = 0; pP1++; bit = 0; pP3++; } value = ((*pP1 & (0x80 >> bit)) != 0) ? rz->rescount : 0; if ((*pP3 & (0x80 >> bit)) != 0) value += (scan2.resolution_y - rz->rescount); if (value > rz->resolution_y) *buffer |= (0x80 >> bit); bit++; lfa54++; } } else { /* f414 */ lfa54 = 0; while (lfa54 < rz->bytesperline) { *buffer = _B0 ((((scan2.resolution_y - rz->rescount) * *pP2) + (*pP1 * rz->rescount)) / scan2.resolution_y); pP1++; pP2++; buffer++; lfa54++; } } } else { /* f47d */ lfa54 = 0; pP1 = rz->v3628; pP2 = rz->v362c; if ((rz->bytesperline & 0xfffffffe) > 0) { SANE_Int value; do { value = (((scan2.resolution_y - rz->rescount) * data_lsb_get (pP2, 2)) + (data_lsb_get (pP1, 2) * rz->rescount)) / scan2.resolution_y; data_lsb_set (buffer, value, 2); buffer += 2; pP1 += 2; pP2 += 2; lfa54++; } while (lfa54 < (rz->bytesperline / 2)); } } } else bOk = 0; /* f4fd f502 */ pP1 = rz->v3628; /* swap pointers */ rz->v3628 = rz->v362c; rz->v362c = pP1; } while (bOk == 0); } else { /*f530 */ SANE_Int lfa68; SANE_Int transferred; SANE_Int channel_size; rz->rescount += scan2.resolution_y; lfa58 = 0; if (rz->rescount > rz->resolution_y) { lfa68 = 1; rz->rescount -= rz->resolution_y; } else lfa68 = 0; pP1 = rz->v3628; pP2 = rz->v362c; if (rz->mode == RSZ_LINEART) { /*f592 */ *buffer = 0; if (rz->towidth > 0) { SANE_Int mask, mres; /* lfa60 = rz->resolution_y */ /* lfa7c = rz->resolution_y / 2 */ for (lfa54 = 0; lfa54 < rz->towidth; lfa54++) { mask = 0x80 >> lfa58; mres = ((mask & *pP1) != 0) ? rz->rescount : 0; if ((mask & *pP2) != 0) mres += (rz->resolution_y - rz->rescount); if (mres > (rz->resolution_y / 2)) *buffer = *buffer | mask; lfa58++; if (lfa58 == 8) { lfa58 = 0; buffer++; pP1++; pP2++; *buffer = 0; } } } } else { /*f633 */ channel_size = (scan2.depth > 8) ? 2 : 1; if (rz->rescount < scan2.resolution_y) { if (rz->bytesperline != 0) { SANE_Int value; for (lfa54 = 0; lfa54 < rz->bytesperline; lfa54++) { value = (((scan2.resolution_y - rz->rescount) * data_lsb_get (pP2, channel_size)) + (rz->rescount * data_lsb_get (pP1, channel_size))) / scan2.resolution_y; data_lsb_set (buffer, value, channel_size); pP1 += channel_size; pP2 += channel_size; buffer += channel_size; } } } else memcpy (buffer, rz->v3628, rz->bytesperline); /*f6a8 */ } /*f736 */ if (lfa68 != 0) { SANE_Byte *temp; if (arrangeline2 == FIX_BY_SOFT) { /*f74b */ if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, &transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, &transferred); } else rst = Read_Block (dev, line_size, rz->v3624, &transferred); /*f77a */ /*f78c */ /* swap buffers */ temp = rz->v3628; rz->v3628 = rz->v362c; rz->v362c = temp; Resize_Increase (temp, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); } else rst = OK; } DBG (DBG_FNC, "- Read_ResizeBlock(*transferred=%i): %i\n", *transferred, rst); return rst; } static void Split_into_12bit_channels (SANE_Byte * destino, SANE_Byte * fuente, SANE_Int size) { /* Each letter represents a bit abcdefgh 12345678 lmnopqrs << before splitting [efgh1234 0000abcd] [lmnopqrs 00005678] << after splitting, in memory [0000abcd efgh1234] [00005678 lmnopqrs] << resulting channels */ DBG (DBG_FNC, "> Split_into_12bit_channels(*destino, *fuente, size=%i\n", size); if ((destino != NULL) && (fuente != NULL)) { if ((size - (size & 0x03)) != 0) { SANE_Int C; C = (size - (size & 0x03) + 3) / 4; do { *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4)); *(destino + 1) = _B0 (*fuente >> 4); *(destino + 2) = _B0 (*(fuente + 2)); *(destino + 3) = *(fuente + 1) & 0x0f; destino += 4; fuente += 3; C--; } while (C > 0); } /**/ if ((size & 0x03) != 0) { *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4)); *(destino + 1) = _B0 (*fuente >> 4); } } } static SANE_Int Read_NonColor_Block (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Byte ColorMode, SANE_Int * transferred) { /* FA50 05DA0048 buffer FA54 0000F906 buffer_size FA58 00 ColorMode */ SANE_Int rst = OK; SANE_Int lfa38 = 0; SANE_Byte *gamma = v1600; SANE_Int block_bytes_per_line; SANE_Int mysize; SANE_Byte *mybuffer; DBG (DBG_FNC, "+ Read_NonColor_Block(*buffer, buffer_size=%i, ColorMode=%s):\n", buffer_size, dbg_colour (ColorMode)); if (ColorMode != CM_GRAY) { /* Lineart mode */ if ((lineart_width & 7) != 0) lfa38 = 8 - (lineart_width & 7); block_bytes_per_line = (lineart_width + 7) / 8; } else block_bytes_per_line = line_size; /*61b2 */ mysize = (buffer_size / block_bytes_per_line) * bytesperline; mybuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte)); /*fa40 */ if (mybuffer != NULL) { SANE_Int LinesCount; SANE_Int mysize4lines; SANE_Byte *pBuffer = buffer; SANE_Byte *pImage = NULL; /* fa30 */ SANE_Int puntero; SANE_Int value; do { mysize4lines = (mysize <= dev->Reading->Size4Lines) ? mysize : dev->Reading->Size4Lines; LinesCount = mysize4lines / bytesperline; if (ColorMode == CM_GRAY) { if (scan2.depth == 12) { /* 633b */ /*GRAY Bit mode 12 */ rst = Scan_Read_BufferA (dev, (mysize4lines * 3) / 4, 0, mybuffer, transferred); if (rst == OK) { pImage = mybuffer; pBuffer += LinesCount * block_bytes_per_line; while (LinesCount > 0) { Split_into_12bit_channels (mybuffer, pImage, line_size); pImage += (bytesperline * 3) / 4; LinesCount--; } } else break; } else { /* grayscale 8 and 16 bits */ SANE_Int channel_size; rst = Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer, transferred); if (rst == OK) { channel_size = (scan2.depth > 8) ? 2 : 1; pImage = mybuffer; /* No gamma tables */ while (LinesCount > 0) { if (line_size > 0) { puntero = 0; do { value = data_lsb_get (pImage + puntero, channel_size); if (gamma != NULL) value += *gamma << (8 * (channel_size - 1)); data_lsb_set (pBuffer, value, channel_size); pBuffer += channel_size; puntero += channel_size; } while (puntero < line_size); } pImage += bytesperline; LinesCount--; } } else break; } } else { /*6429 */ /* LINEART */ SANE_Int desp; rst = Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer, transferred); if (rst == OK) { pImage = mybuffer; while (LinesCount > 0) { if (lineart_width > 0) { desp = 0; do { if ((desp % 7) == 0) *pBuffer = 0; /* making a byte bit per bit */ *pBuffer = *pBuffer << 1; /* bit 1 if data is under thresholdh value */ if (*(pImage + desp) >= binarythresholdh) /* binarythresholdh = 0x0c */ *pBuffer = *pBuffer | 1; desp++; if ((desp % 7) == 0) pBuffer++; } while (desp < lineart_width); } if (lfa38 != 0) { *pBuffer = (*pBuffer << lfa38); pBuffer++; } /* 64b0 */ pImage += bytesperline; LinesCount--; } } else break; } /* 64c0 */ mysize -= mysize4lines; } while ((mysize > 0) && (dev->status->cancel == FALSE)); free (mybuffer); } else rst = ERROR; DBG (DBG_FNC, "- Read_NonColor_Block(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Read_Block (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred) { /* SANE_Int buffer_size fa80 SANE_Byte *buffer fa7c */ /* scan2: 04F0155C 01 08 00 02 03 00 58 02 ..X 04F01564 58 02 58 02 C5 00 00 00 XXÅ... 04F0156C B4 07 00 00 8B 01 00 00 ´..‹.. 04F01574 10 06 00 00 EC 13 00 00 ..ì.. 04F0157C B2 07 00 00 B4 07 00 00 ²..´.. 04F01584 CF 08 00 00 Ï.. arrangeline2 = 1 */ SANE_Int rst, LinesCount; SANE_Int mysize; SANE_Byte *readbuffer = NULL; SANE_Byte *pImage = NULL; DBG (DBG_FNC, "+ Read_Block(buffer_size=%i, *buffer):\n", buffer_size); rst = ERROR; *transferred = 0; if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3) && (arrangeline2 != FIX_BY_SOFT)) { /*6510 */ return Read_NonColor_Block (dev, buffer, buffer_size, scan2.colormode, transferred); } /*6544 */ mysize = (buffer_size / line_size) * bytesperline; readbuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte)); pImage = buffer; if (readbuffer != NULL) { do { buffer_size = (dev->Reading->Size4Lines < mysize) ? dev->Reading->Size4Lines : mysize; LinesCount = buffer_size / bytesperline; if (scan2.depth == 12) { rst = Scan_Read_BufferA (dev, buffer_size, 0, readbuffer, transferred); if (rst == OK) { if (LinesCount > 0) { SANE_Byte *destino, *fuente; destino = buffer; fuente = readbuffer; do { Split_into_12bit_channels (destino, fuente, line_size); destino += line_size; fuente += (bytesperline * 3) / 4; LinesCount--; } while (LinesCount > 0); } } else break; } else { /*65d9 */ rst = Scan_Read_BufferA (dev, buffer_size, 0, readbuffer, transferred); if (rst == OK) { memcpy (pImage, readbuffer, *transferred); /* apply white shading correction */ if ((RTS_Debug->wshading == TRUE) && (scan2.scantype == ST_NORMAL)) WShading_Emulate (pImage, &wshading->ptr, *transferred, scan2.depth); pImage += *transferred; } else break; } /*6629 */ mysize -= buffer_size; } while ((mysize > 0) && (dev->status->cancel == FALSE)); free (readbuffer); } DBG (DBG_FNC, "- Read_Block(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Scan_Read_BufferA (struct st_device *dev, SANE_Int buffer_size, SANE_Int arg2, SANE_Byte * pBuffer, SANE_Int * bytes_transfered) { SANE_Int rst = OK; SANE_Byte *ptBuffer = NULL; SANE_Byte *ptImg = NULL; struct st_readimage *rd = dev->Reading; DBG (DBG_FNC, "+ Scan_Read_BufferA(buffer_size=%i, arg2, *pBuffer, *bytes_transfered):\n", buffer_size); arg2 = arg2; /* silence gcc */ *bytes_transfered = 0; if (pBuffer != NULL) { ptBuffer = pBuffer; while ((buffer_size > 0) && (rst == OK) && (dev->status->cancel == FALSE)) { /* Check if we've already started */ if (rd->Starting == TRUE) { /* Get channels per dot and channel's size in bytes */ SANE_Byte data; rd->Channels_per_dot = 1; if (Read_Byte (dev->usb_handle, 0xe812, &data) == OK) { data = data >> 6; if (data != 0) rd->Channels_per_dot = data; } rd->Channel_size = 1; if (Read_Byte (dev->usb_handle, 0xee0b, &data) == OK) if (((data & 0x40) != 0) && ((data & 0x08) == 0)) rd->Channel_size = 2; rd->RDStart = rd->DMABuffer; rd->RDSize = 0; rd->DMAAmount = 0; rd->Starting = FALSE; } /* Is there any data to read from scanner? */ if ((rd->ImageSize > 0) && (rd->RDSize == 0)) { /* Try to read from scanner all possible data to fill DMABuffer */ if (rd->RDSize < rd->DMABufferSize) { SANE_Int iAmount, dofree; /* Check if we have already notify buffer size */ if (rd->DMAAmount <= 0) { /* Initially I suppose that I can read all image */ iAmount = min (rd->ImageSize, rd->Max_Size); rd->DMAAmount = ((RTS_Debug->dmasetlength * 2) / iAmount) * iAmount; rd->DMAAmount = min (rd->DMAAmount, rd->ImageSize); Reading_BufferSize_Notify (dev, 0, rd->DMAAmount); iAmount = min (iAmount, rd->DMABufferSize - rd->RDSize); } else { iAmount = min (rd->DMAAmount, rd->ImageSize); iAmount = min (iAmount, rd->Max_Size); } /* Allocate buffer to read image if it's necessary */ if ((rd->RDSize == 0) && (iAmount <= buffer_size)) { ptImg = ptBuffer; dofree = FALSE; } else { ptImg = (SANE_Byte *) malloc (iAmount * sizeof (SANE_Byte)); dofree = TRUE; } if (ptImg != NULL) { /* We must wait for scanner to get data */ SANE_Int opStatus, sc; sc = (iAmount < rd->Max_Size) ? TRUE : FALSE; opStatus = Reading_Wait (dev, rd->Channels_per_dot, rd->Channel_size, iAmount, &rd->Bytes_Available, 10, sc); /* If something fails, perhaps we can read some bytes... */ if (opStatus != OK) { if (rd->Bytes_Available > 0) iAmount = rd->Bytes_Available; else rst = ERROR; } if (rst == OK) { /* Try to read from scanner */ SANE_Int transferred = 0; opStatus = Bulk_Operation (dev, BLK_READ, iAmount, ptImg, &transferred); DBG (DBG_FNC, "> Scan_Read_BufferA: Bulk read %i bytes\n", transferred); /*if something fails may be we can read some bytes */ iAmount = (SANE_Int) transferred; if (iAmount != 0) { /* Lets copy data into DMABuffer if it's necessary */ if (ptImg != ptBuffer) { SANE_Byte *ptDMABuffer; ptDMABuffer = rd->RDStart + rd->RDSize; if ((ptDMABuffer - rd->DMABuffer) >= rd->DMABufferSize) ptDMABuffer -= rd->DMABufferSize; if ((ptDMABuffer + iAmount) >= (rd->DMABuffer + rd->DMABufferSize)) { SANE_Int rest = iAmount - (rd->DMABufferSize - (ptDMABuffer - rd->DMABuffer)); memcpy (ptDMABuffer, ptImg, iAmount - rest); memcpy (rd->DMABuffer, ptImg + (iAmount - rest), rest); } else memcpy (ptDMABuffer, ptImg, iAmount); rd->RDSize += iAmount; } else { *bytes_transfered += iAmount; buffer_size -= iAmount; } rd->DMAAmount -= iAmount; rd->ImageSize -= iAmount; } else rst = ERROR; } /* Lets free buffer */ if (dofree == TRUE) { free (ptImg); ptImg = NULL; } } else rst = ERROR; } } /* is there any data read from scanner? */ if (rd->RDSize > 0) { /* Add to the given buffer so many bytes as posible */ SANE_Int iAmount; iAmount = min (buffer_size, rd->RDSize); if ((rd->RDStart + iAmount) >= (rd->DMABuffer + rd->DMABufferSize)) { SANE_Int rest = rd->DMABufferSize - (rd->RDStart - rd->DMABuffer); memcpy (ptBuffer, rd->RDStart, rest); memcpy (ptBuffer + rest, rd->DMABuffer, iAmount - rest); rd->RDStart = rd->DMABuffer + (iAmount - rest); } else { memcpy (ptBuffer, rd->RDStart, iAmount); rd->RDStart += iAmount; } ptBuffer += iAmount; rd->RDSize -= iAmount; buffer_size -= iAmount; *bytes_transfered += iAmount; /* if there isn't any data in DMABuffer we can point RDStart to the begining of DMABuffer */ if (rd->RDSize == 0) rd->RDStart = rd->DMABuffer; } /* in case of all data is read we return OK with bytes_transfered = 0 */ if ((*bytes_transfered == 0) || ((rd->RDSize == 0) && (rd->ImageSize == 0))) break; } if (rst == ERROR) RTS_DMA_Cancel (dev); } DBG (DBG_FNC, "-> *bytes_transfered=%i\n", *bytes_transfered); DBG (DBG_FNC, "-> Reading->ImageSize=%i\n", rd->ImageSize); DBG (DBG_FNC, "-> Reading->DMAAmount=%i\n", rd->DMAAmount); DBG (DBG_FNC, "-> Reading->RDSize =%i\n", rd->RDSize); DBG (DBG_FNC, "- Scan_Read_BufferA: %i\n", rst); return rst; } static SANE_Int Reading_BufferSize_Get (struct st_device *dev, SANE_Byte channels_per_dot, SANE_Int channel_size) { /* returns the ammount of bytes in scanner's buffer ready to be read */ SANE_Int rst; DBG (DBG_FNC, "+ Reading_BufferSize_Get(channels_per_dot=%i, channel_size=%i):\n", channels_per_dot, channel_size); rst = 0; if (channel_size > 0) { SANE_Int myAmount; if (channels_per_dot < 1) { /* read channels per dot from registers */ if (Read_Byte (dev->usb_handle, 0xe812, &channels_per_dot) == OK) channels_per_dot = _B0 (channels_per_dot >> 6); if (channels_per_dot == 0) channels_per_dot++; } if (Read_Integer (dev->usb_handle, 0xef16, &myAmount) == OK) rst = ((channels_per_dot * 32) / channel_size) * myAmount; } DBG (DBG_FNC, "- Reading_BufferSize_Get: %i bytes\n", rst); return rst; } static SANE_Int Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, SANE_Int lamp, SANE_Int resolution) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Lamp_Warmup(*Regs, lamp=%i, resolution=%i)\n", lamp, resolution); if (Regs != NULL) { SANE_Byte flb_lamp, tma_lamp; SANE_Int overdrivetime; Lamp_Status_Get (dev, &flb_lamp, &tma_lamp); /* ensure that selected lamp is switched on */ if (lamp == FLB_LAMP) { overdrivetime = RTS_Debug->overdrive_flb; if (flb_lamp == 0) { /* FLB-Lamp is turned off, lets turn on */ Lamp_Status_Set (dev, Regs, TRUE, FLB_LAMP); waitforpwm = TRUE; } } else { /* is tma device attached to scanner ? */ if (RTS_isTmaAttached (dev) == TRUE) { overdrivetime = RTS_Debug->overdrive_ta; if (tma_lamp == 0) { /* tma lamp is turned off */ Lamp_Status_Set (dev, Regs, FALSE, TMA_LAMP); waitforpwm = TRUE; } } else rst = ERROR; } /* perform warmup process */ if (rst == OK) { Lamp_PWM_Setup (dev, lamp); if (waitforpwm == TRUE) { /*Lamp_PWM_DutyCycle_Set(dev, (lamp == TMA_LAMP)? 0x0e : 0x00); */ if (RTS_Debug->warmup == TRUE) { long ticks = GetTickCount () + overdrivetime; DBG (DBG_VRB, "- Lamp Warmup process. Please wait...\n"); dev->status->warmup = TRUE; while (GetTickCount () <= ticks) usleep (1000 * 200); Lamp_PWM_CheckStable (dev, resolution, lamp); } else DBG (DBG_VRB, "- Lamp Warmup process disabled.\n"); } /*Lamp_PWM_Setup(dev, lamp); if (waitforpwm == TRUE) { if (RTS_Debug->warmup == TRUE) Lamp_PWM_CheckStable(dev, resolution, lamp); waitforpwm = FALSE; } */ } } else rst = ERROR; dev->status->warmup = FALSE; DBG (DBG_FNC, "- Lamp_Warmup: %i\n", rst); return rst; } static SANE_Int Scan_Start (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ Scan_Start:\n"); rst = ERROR; if (RTS_Enable_CCD (dev, dev->init_regs, 0x0f) == OK) { SANE_Byte Regs[RT_BUFFER_LEN], mlock; SANE_Int ypos, xpos, runb1; struct st_scanparams scancfg; struct st_hwdconfig hwdcfg; struct st_calibration myCalib; long tick; memcpy (&Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &scan, sizeof (struct st_scanparams)); dbg_ScanParams (&scancfg); /* reserva buffer 6 dwords en fa84-fa9f */ bzero (&hwdcfg, sizeof (struct st_hwdconfig)); /* wait till lamp is at home (should use timeout windows driver doesn't use it) */ tick = GetTickCount () + 10000; while ((Head_IsAtHome (dev, Regs) == FALSE) && (tick > GetTickCount ())); if (v14b4 != 0) { SANE_Int lfaa0 = 0; if (GainOffset_Counter_Inc (dev, &lfaa0) != OK) return 0x02; } tick = GetTickCount (); /* set margin references */ Refs_Set (dev, Regs, &scancfg); /* locate head to right position */ Load_StripCoords (scantype, &ypos, &xpos); if (ypos != 0) Head_Relocate (dev, dev->motorcfg->parkhomemotormove, MTR_FORWARD, ypos); /* perform lamp warmup */ if (Lamp_Warmup (dev, Regs, (scancfg.scantype == ST_NORMAL) ? FLB_LAMP : TMA_LAMP, scan.resolution_x) == ERROR) return ERROR; /* Calibration process */ /*592c */ if (Calib_CreateBuffers (dev, &myCalib, v14b4) != OK) return ERROR; /*5947 */ /* if (Calib_BlackShading_jkd(dev, Regs, &myCalib, &scancfg) == OK) Head_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove); */ /* if (Calib_test(dev, Regs, &myCalib, &scancfg) == OK ) Head_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove); */ /* Calibrate White shading correction */ if ((RTS_Debug->wshading == TRUE) && (scan.scantype == ST_NORMAL)) if (WShading_Calibrate (dev, Regs, &myCalib, &scancfg) == OK) Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); hwdcfg.calibrate = RTS_Debug->calibrate; if (RTS_Debug->calibrate != 0) { /* Let's calibrate */ if ((scancfg.colormode != CM_COLOR) && (scancfg.channel == 3)) scancfg.colormode = CM_COLOR; hwdcfg.arrangeline = 0; if (scan.scantype == ST_NORMAL) { /* Calibration for reflective type */ /*59e3 */ memcpy (&Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Calibration (dev, Regs, &scancfg, &myCalib, 0) != OK) { if (v14b4 == 0) Calib_FreeBuffers (&myCalib); return ERROR; } } else { /*59ed */ /* Calibration for negative/slide type */ } /*5af1 */ if (RTS_Debug->ScanWhiteBoard != FALSE) { Head_ParkHome (dev, TRUE, dev->motorcfg->basespeedmotormove); scan.ler = 1; } scancfg.colormode = scan.colormode; } else { /*5b1e */ /*Don't calibrate */ if (scan.scantype == ST_NORMAL) { Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); } else { if ((scan.scantype == ST_TA) || (scan.scantype == ST_NEG)) { /*SANE_Int ta_y_start; */ Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP); /*ta_y_start = get_value(SCAN_PARAM, TA_Y_START, 0x2508, usbfile); ta_y_start += (((((scan.coord.top * 3) * 5) * 5) * 32) / scancfg.resolution_x); if (ta_y_start >= 500) { Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, ta_y_start); scancfg.coord.top = 1; scan.ler = 1; } else { / *5ba9* / if (ta_y_start > 0) { Head_Relocate(dev, dev->motorcfg->basespeedmotormove, MTR_FORWARD, ta_y_start); scancfg.coord.top = 1; scan.ler = 1; } } */ } } } /*5bd0 */ usleep (1000 * 200); hwdcfg.scantype = scan.scantype; hwdcfg.motor_direction = MTR_FORWARD; /* Set Origin */ if ((scan.scantype >= ST_NORMAL) || (scan.scantype <= ST_NEG)) { scancfg.coord.left += scan.ser; scancfg.coord.top += scan.ler; } hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance; hwdcfg.highresolution = (scancfg.resolution_x <= 1200) ? FALSE : TRUE; /*5c55 */ /* if (RTS_Debug->calibrate == FALSE) { SANE_Int mytop = (((scancfg.coord.top * 5) * 5) * 16) / scancfg.resolution_y; if ((scancfg.resolution_y <= 150)&&(mytop < 300)) { scancfg.coord.top = scancfg.resolution_y / 4; } else { if (mytop < 100) scancfg.coord.top = scancfg.resolution_y / 12; } } */ /*5cd9 */ if (compression != FALSE) hwdcfg.compression = TRUE; /* setting arrangeline option */ hwdcfg.arrangeline = arrangeline; if (scancfg.resolution_x == 2400) { /* 5cfa */ if (scancfg.colormode != CM_COLOR) { if ((scancfg.colormode == CM_GRAY) && (scancfg.channel == 3)) hwdcfg.arrangeline = FIX_BY_SOFT; } else hwdcfg.arrangeline = FIX_BY_SOFT; } /*5d12 */ if (dev->sensorcfg->type == CCD_SENSOR) { /*5d3a */ scancfg.coord.left += 24; switch (scancfg.resolution_x) { case 1200: scancfg.coord.left -= 63; break; case 2400: scancfg.coord.left -= 127; break; } } else { /*5d5a */ /* CIS sensor */ /*5d6d */ scancfg.coord.left += 50; switch (scancfg.resolution_x) { case 1200: scancfg.coord.left -= 63; break; case 2400: scancfg.coord.left -= 127; break; } } /* 5d92 */ DBG (DBG_FNC, " ->Scan_Start xStart=%i, xExtent=%i\n", scancfg.coord.left, scancfg.coord.width); runb1 = 1; if (scan.scantype == ST_NORMAL) { /*5db7 */ if ((scancfg.resolution_x == 1200) || (scancfg.resolution_x == 2400)) { /*5e41 */ if ((scancfg.resolution_y / 10) > scancfg.coord.top) runb1 = 0; } else { if ((scancfg.resolution_x == 600) && (RTS_Debug->usbtype == USB11) && (scancfg.colormode == CM_COLOR)) { /*5ded */ if ((scancfg.resolution_y / 10) > scancfg.coord.top) runb1 = 0; } else { if ((scancfg.resolution_x == 600) || (scancfg.resolution_x == 300)) { /*5e11 */ if (scancfg.resolution_y > scancfg.coord.top) runb1 = 0; } else runb1 = 0; } } } else { /*5e7c *//* entra aquí */ if ((scancfg.resolution_y / 10) > scancfg.coord.top) runb1 = 0; } /*5eb1 */ if (runb1 == 1) /*entra */ { SANE_Int val1 = scancfg.coord.top - (scancfg.resolution_y / 10); scancfg.coord.top -= val1; Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, (dev->motorcfg->resolution / scancfg.resolution_y) * val1); /*x168 */ } /*5efe */ if (RTS_Debug->calibrate != FALSE) { if (use_gamma_tables != FALSE) { hwdcfg.use_gamma_tables = TRUE; hp_gamma->depth = 0; } /*5f24 */ hwdcfg.white_shading = TRUE; hwdcfg.black_shading = TRUE; hwdcfg.unk3 = 0; RTS_Setup (dev, Regs, &scancfg, &hwdcfg, &calibdata->gain_offset); myCalib.shading_type = 0; myCalib.shadinglength = min (myCalib.shadinglength, scan.shadinglength); if (scancfg.colormode != CM_COLOR) { if ((scancfg.channel > 0) && (scancfg.channel < 3)) myCalib.WRef[0] = myCalib.WRef[scancfg.channel]; } RTS_WriteRegs (dev->usb_handle, Regs); /* apply gamma if required */ Gamma_Apply (dev, Regs, &scancfg, &hwdcfg, hp_gamma); Shading_apply (dev, Regs, &scancfg, &myCalib); /* Save to file? */ if (RTS_Debug->DumpShadingData != FALSE) dump_shading (&myCalib); /*5ff9 */ } else RTS_Setup (dev, Regs, &scancfg, &hwdcfg, default_gain_offset); /*602a */ RTS_Debug->calibrate = hwdcfg.calibrate; binarythresholdh = bw_threshold; binarythresholdl = bw_threshold; DBG (DBG_FNC, "> bw threshold -- hi=%i, lo=%i\n", binarythresholdh, binarythresholdl); /* set threshold high */ data_lsb_set (&Regs[0x1a0], binarythresholdh, 2); /* set threshold low */ data_lsb_set (&Regs[0x19e], binarythresholdl, 2); /* if has motorcurves... */ if ((Regs[0xdf] & 0x10) != 0) data_bitset (&Regs[0x01], 0x02, 1); /* Set MLOCK */ mlock = get_value (SCAN_PARAM, MLOCK, 0, usbfile) & 1; data_bitset (&Regs[0x00], 0x10, mlock); /*---x----*/ if (dev->motorcfg->changemotorcurrent != FALSE) Motor_Change (dev, Regs, Motor_GetFromResolution (scancfg.resolution_x)); /* set gain control mode */ Lamp_SetGainMode (dev, Regs, scancfg.resolution_x, Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype)); RTS_WaitScanEnd (dev, 15000); if (v14b4 == 0) Calib_FreeBuffers (&myCalib); /* release motor */ Motor_Release (dev); #ifdef developing /* prueba(Regs); dbg_registers(Regs);*/ /*WShading_Calibrate(dev, Regs, &myCalib, &scancfg); */ /*shadingtest1(dev, Regs, &myCalib); */ #endif if (RTS_Warm_Reset (dev) == OK) { RTS_WriteRegs (dev->usb_handle, Regs); usleep (1000 * 500); if (RTS_Execute (dev) == OK) { Lamp_Status_Timer_Set (dev, 0); /* Let scanner some time to store some data */ if ((dev->chipset->model == RTS8822L_02A) && (scancfg.resolution_x > 2400)) usleep (1000 * 5000); rst = OK; } } } DBG (DBG_FNC, "- Scan_Start: %i\n", rst); return rst; } static SANE_Int RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int somevalue) { SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ RTS_Setup_Motor(*Regs, *scancfg, somevalue=%i):\n", somevalue); dbg_ScanParams (scancfg); if ((Regs != NULL) && (scancfg != NULL)) { SANE_Int colormode, mymode; colormode = ((scancfg->colormode != CM_COLOR) && (scancfg->channel == 3)) ? 3 : scancfg->colormode; mymode = RTS_GetScanmode (dev, scantype, colormode, scancfg->resolution_x); if (mymode != -1) { SANE_Int mbs[2] = { 0 }; /* motor back steps */ SANE_Int step_size, step_type, dummyline, myvalue, lf02c; struct st_scanmode *sm; sm = dev->scanmodes[mymode]; /* set motor step type */ data_bitset (&Regs[0xd9], 0x70, sm->scanmotorsteptype); /*-xxx----*/ /* set motor direction (polarity) */ data_bitset (&Regs[0xd9], 0x80, somevalue >> 3); /*e------- */ /* next value doesn't seem to have any effect */ data_bitset (&Regs[0xd9], 0x0f, somevalue); /*----efgh*/ /* 0 enable/1 disable motor */ data_bitset (&Regs[0xdd], 0x80, somevalue >> 4); /*d------- */ /* next value doesn't seem to have any effect */ data_bitset (&Regs[0xdd], 0x40, somevalue >> 4); /*-d------*/ switch (sm->scanmotorsteptype) { case STT_OCT: step_type = 8; break; case STT_QUART: step_type = 4; break; case STT_HALF: step_type = 2; break; default: step_type = 1; break; /* STT_FULL */ } /* set dummy lines */ dummyline = sm->dummyline; if (dummyline == 0) dummyline++; data_bitset (&Regs[0xd6], 0xf0, dummyline); /*xxxx---- */ /* Set if motor has curves */ data_bitset (&Regs[0xdf], 0x10, ((sm->motorcurve != -1) ? 1 : 0)); /*---x----*/ /* set last step of deccurve.scanbufferfull table to 16 */ data_lsb_set (&Regs[0xea], 0x10, 3); /* set last step of deccurve.normalscan table to 16 */ data_lsb_set (&Regs[0xed], 0x10, 3); /* set last step of deccurve.smearing table to 16 */ data_lsb_set (&Regs[0xf0], 0x10, 3); /* set last step of deccurve.parkhome table to 16 */ data_lsb_set (&Regs[0xf3], 0x10, 3); /* set step size */ step_size = _B0 ((dev->motorcfg->resolution * step_type) / (dummyline * scancfg->resolution_y)); data_lsb_set (&Regs[0xe0], step_size - 1, 1); /* set line exposure time */ myvalue = data_lsb_get (&Regs[0x30], 3); myvalue += ((myvalue + 1) % step_size); data_lsb_set (&Regs[0x30], myvalue, 3); /* set last step of accurve.normalscan table */ myvalue = ((myvalue + 1) / step_size) - 1; data_lsb_set (&Regs[0xe1], myvalue, 3); /* 42b30eb */ lf02c = 0; if (sm->motorcurve != -1) { if (sm->motorcurve < dev->mtrsetting_count) { struct st_motorcurve *ms = dev->mtrsetting[sm->motorcurve]; ms->motorbackstep = sm->motorbackstep; } DBG (DBG_FNC, " -> Setting up step motor using motorcurve %i\n", sm->motorcurve); lf02c = Motor_Setup_Steps (dev, Regs, sm->motorcurve); /* set motor back steps */ mbs[1] = sm->motorbackstep; if (mbs[1] >= (smeardeccurvecount + smearacccurvecount)) mbs[0] = mbs[1] - (smeardeccurvecount + smearacccurvecount) + 2; else mbs[0] = 0; if (mbs[1] >= (deccurvecount + acccurvecount)) mbs[1] -= (deccurvecount + acccurvecount) + 2; else mbs[1] = 0; } else { /* this scanner hasn't got any motorcurve */ /* set last step of accurve.smearing table (same as accurve.normalscan) */ data_lsb_set (&Regs[0xe4], myvalue, 3); /* set last step of accurve.parkhome table (same as accurve.normalscan) */ data_lsb_set (&Regs[0xe7], myvalue, 3); /* both motorbacksteps are equal */ mbs[0] = sm->motorbackstep; mbs[1] = sm->motorbackstep; } /* show msi and motorbacksteps */ DBG (DBG_FNC, " -> msi = %i\n", sm->msi); DBG (DBG_FNC, " -> motorbackstep1 = %i\n", mbs[0]); DBG (DBG_FNC, " -> motorbackstep2 = %i\n", mbs[1]); /* set msi */ data_bitset (&Regs[0xda], 0xff, _B0 (sm->msi)); /*xxxxxxxx */ data_bitset (&Regs[0xdd], 0x03, _B1 (sm->msi)); /*------xx*/ /* set motorbackstep (a) */ data_bitset (&Regs[0xdb], 0xff, _B0 (mbs[0])); /*xxxxxxxx */ data_bitset (&Regs[0xdd], 0x0c, _B1 (mbs[0])); /*----xx--*/ /* set motorbackstep (b) */ data_bitset (&Regs[0xdc], 0xff, _B0 (mbs[1])); /*xxxxxxxx */ data_bitset (&Regs[0xdd], 0x30, _B1 (mbs[1])); /*--xx----*/ /* 328b */ /* get dummy lines count */ dummyline = data_bitget (&Regs[0xd6], 0xf0); myvalue = scancfg->coord.top * (dummyline * step_size); if (lf02c >= myvalue) scancfg->coord.top = 1; else scancfg->coord.top -= (lf02c / (dummyline * step_size)) - 1; rst = lf02c; /* Result from Motor_Setup_Steps */ } } DBG (DBG_FNC, "- RTS_Setup_Motor: %i\n", rst); return rst; } static void RTS_Setup_Exposure_Times (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_scanmode *sm) { DBG (DBG_FNC, "> RTS_Setup_Exposure_Times\n"); if ((sm != NULL) && (Regs != NULL) && (scancfg != NULL)) { SANE_Int myexpt[3], linexpt, a; /* calculate line exposure time */ linexpt = sm->ctpc + 1; if (RTS_Debug->usbtype == USB11) linexpt *= sm->multiexposureforfullspeed; if (scancfg->depth > 8) linexpt *= sm->multiexposurefor16bitmode; linexpt--; /* generate exposure times for each channel color */ for (a = CL_RED; a <= CL_BLUE; a++) { if ((linexpt > sm->mexpt[a]) && (sm->expt[a] == 0)) sm->expt[a] = sm->mexpt[a]; myexpt[a] = (sm->expt[a] == 0) ? sm->mexpt[a] : sm->expt[a]; } /* save exposure times */ DBG (DBG_FNC, "-> Exposure times : %04x, %04x, %04x\n", sm->expt[0], sm->expt[1], sm->expt[2]); data_lsb_set (&Regs[0x36], sm->expt[CL_RED], 3); data_lsb_set (&Regs[0x3c], sm->expt[CL_GREEN], 3); data_lsb_set (&Regs[0x42], sm->expt[CL_BLUE], 3); /* save maximum exposure times */ DBG (DBG_FNC, "-> Maximum exposure times: %04x, %04x, %04x\n", sm->mexpt[0], sm->mexpt[1], sm->mexpt[2]); data_lsb_set (&Regs[0x33], sm->mexpt[CL_RED], 3); data_lsb_set (&Regs[0x39], sm->mexpt[CL_GREEN], 3); data_lsb_set (&Regs[0x3f], sm->mexpt[CL_BLUE], 3); /* save line exposure time */ data_lsb_set (&Regs[0x30], linexpt, 3); /* scancfg->expt = lowest value */ scancfg->expt = min (min (myexpt[1], myexpt[2]), myexpt[0]); } } static SANE_Int RTS_Setup_Line_Distances (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int mycolormode, SANE_Int arrangeline) { SANE_Int iLineDistance = 0; if (arrangeline == FIX_BY_HARD) { /* we don't need to arrange retrieved line */ SANE_Int mylinedistance, myevenodddist; mylinedistance = (dev->sensorcfg->line_distance * scancfg->resolution_y) / dev->sensorcfg->resolution; if (hwdcfg->highresolution == TRUE) myevenodddist = (hwdcfg->sensorevenodddistance * scancfg->resolution_y) / dev->sensorcfg->resolution; else myevenodddist = 0; data_bitset (&Regs[0x149], 0x3f, myevenodddist); data_bitset (&Regs[0x14a], 0x3f, mylinedistance); data_bitset (&Regs[0x14b], 0x3f, mylinedistance + myevenodddist); data_bitset (&Regs[0x14c], 0x3f, mylinedistance * 2); data_bitset (&Regs[0x14d], 0x3f, (mylinedistance * 2) + myevenodddist); } else { /* arrange retrieved line */ data_bitset (&Regs[0x149], 0x3f, 0); data_bitset (&Regs[0x14a], 0x3f, 0); data_bitset (&Regs[0x14b], 0x3f, 0); data_bitset (&Regs[0x14c], 0x3f, 0); data_bitset (&Regs[0x14d], 0x3f, 0); if (arrangeline == FIX_BY_SOFT) { if (hwdcfg->highresolution == FALSE) { if (mycolormode == CM_COLOR) { iLineDistance = (dev->sensorcfg->line_distance * scan2.resolution_y) * 2; iLineDistance = (iLineDistance / dev->sensorcfg->resolution) + 1; if (iLineDistance < 2) iLineDistance = 2; } } else { /* bcc */ if (mycolormode == CM_COLOR) iLineDistance = ((dev->sensorcfg->line_distance * 2) + hwdcfg->sensorevenodddistance) * scan2.resolution_y; else iLineDistance = dev->sensorcfg->line_distance * scan2.resolution_y; iLineDistance = (iLineDistance / dev->sensorcfg->resolution) + 1; if (iLineDistance < 2) iLineDistance = 2; } /* c25 */ iLineDistance &= 0xffff; v15b4 = (iLineDistance > 0) ? 1 : 0; imagesize += iLineDistance * bytesperline; } } DBG (DBG_FNC, "> RTS_Setup_Line_Distances(*Regs, *scancfg, *hwdcfg, mycolormode=%i, arrangeline=%i): %i\n", mycolormode, arrangeline, iLineDistance); return iLineDistance; } static SANE_Int RTS_Setup_Depth (SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode) { /* channels_per_line = channels_per_dot * scan.width bytes_per_line = channels_per_line * bits_per_channel */ SANE_Int bytes_per_line = 0; if ((scancfg != NULL) && (Regs != NULL)) { SANE_Int channels_per_line = data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width; bytes_per_line = channels_per_line; /* set bits per channel in shading correction's register (0x1cf) */ if (mycolormode == CM_LINEART) { /* lineart mode */ bytes_per_line = (bytes_per_line + 7) / 8; data_bitset (&Regs[0x1cf], 0x30, 3); /*--11----*/ } else { /*f0c */ switch (scancfg->depth) { case 16: /* 16 bits per channel */ bytes_per_line *= 2; data_bitset (&Regs[0x1cf], 0x30, 2); /*--10----*/ break; case 12: /* 12 bits per channel */ bytes_per_line *= 2; data_bitset (&Regs[0x1cf], 0x30, 1); /*--01----*/ break; default: /* 8 bits per channel */ data_bitset (&Regs[0x1cf], 0x30, 0); /*--00----*/ break; } } } return bytes_per_line; } static void RTS_Setup_Shading (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int bytes_per_line) { DBG (DBG_FNC, "> RTS_Setup_Shading(*Regs, *scancfg, *hwdcfg, bytes_per_line=%i)\n", bytes_per_line); if ((Regs != NULL) && (hwdcfg != NULL)) { SANE_Int dots_count, myvalue, myvalue2, mem_available, resolution_ratio, sensor_line_distance; SANE_Int channels, table_size; resolution_ratio = Regs[0x0c0] & 0x1f; /* 50de */ data_bitset (&Regs[0x1bf], 0x18, hwdcfg->unk3); /*---xx---*/ /* Enable black shading correction ? */ data_bitset (&Regs[0x1cf], 0x08, hwdcfg->black_shading); /*----x---*/ /* Enable white shading correction ? */ data_bitset (&Regs[0x1cf], 0x04, hwdcfg->white_shading); /*-----x--*/ if ((hwdcfg->white_shading != FALSE) && (hwdcfg->black_shading != FALSE) && (hwdcfg->unk3 != 0)) data_bitset (&Regs[0x1cf], 0x04, 0); /*-----x--*/ table_size = 0; /* if hwdcfg->black_shading */ if ((Regs[0x1cf] & 8) != 0) table_size = (resolution_ratio * scancfg->coord.width) * 2; /* black shading buffer size? */ /* if hwdcfg->white_shading */ if ((Regs[0x1cf] & 4) != 0) table_size += (resolution_ratio * scancfg->coord.width) * 2; /* white shading buffer size? */ /* Regs 0x1ba, 0x1bb, 0x1bd, 0x1c0 seem to be 4 pointers to some buffer related to shading correction */ Regs[0x1ba] = 0x00; table_size = (table_size + v160c_block_size - 1) / v160c_block_size; table_size = ((table_size + 15) / 16) + 16; Regs[0x1bf] &= 0xfe; Regs[0x1bb] = _B0 (table_size); Regs[0x1bc] = _B1 (table_size); Regs[0x1bf] |= _B2 (table_size) & 1; /*-------x*/ Regs[0x1bf] &= 0xf9; Regs[0x1bd] = _B0 (table_size * 2); Regs[0x1be] = _B1 (table_size * 2); Regs[0x1bf] |= (_B2 (table_size * 2) & 3) << 1; /*-----xx-*/ data_wide_bitset (&Regs[0x1c0], 0xfffff, table_size * 3); mem_available = mem_total - ((table_size * 3) * 16); sensor_line_distance = Regs[0x14a] & 0x3f; /* select case channels_per_dot */ channels = data_lsb_get (&Regs[0x12], 1) >> 6; switch (channels) { case 3: /* 3 channels per dot */ /* 528d */ dots_count = bytes_per_line / 3; /* 882 */ myvalue = (((sensor_line_distance + 1) * dots_count) + v160c_block_size - 1) / v160c_block_size; myvalue2 = myvalue; mem_available = (mem_available - (myvalue * 3) + 2) / 3; myvalue += (table_size * 3) * 8; myvalue = ((myvalue * 2) + mem_available); data_bitset (&Regs[0x1c2], 0xf0, _B2 ((myvalue / 16) + 1)); /* 4 higher bits xxxx---- */ data_wide_bitset (&Regs[0x1c3], 0xffff, (myvalue / 16) + 1); /* 16 lower bits */ myvalue = myvalue + myvalue2 + mem_available; data_wide_bitset (&Regs[0x1c5], 0xfffff, (myvalue / 16) + 1); break; case 2: /* 2 channels per dot */ dots_count = bytes_per_line / 2; myvalue = (((sensor_line_distance + 1) * dots_count) + v160c_block_size - 1) / v160c_block_size; mem_available = ((mem_available - myvalue) + 1) / 2; myvalue += (((table_size * 3) + mem_available) / 16) + 1; data_bitset (&Regs[0x1c2], 0xf0, _B2 (myvalue)); /* 4 higher bits xxxx---- */ data_wide_bitset (&Regs[0x1c3], 0xffff, myvalue); /* 16 lower bits */ break; default: dots_count = bytes_per_line; break; } Regs[0x01c7] &= 0x0f; Regs[0x01c8] = _B0 ((mem_total - 1) / 16); Regs[0x01c9] = _B1 ((mem_total - 1) / 16); Regs[0x01c7] |= (_B2 ((mem_total - 1) / 16) & 0x0f) << 4; mem_available -= (dots_count + v160c_block_size - 1) / v160c_block_size; mem_available /= 16; Regs[0x0712] &= 0x0f; Regs[0x0710] = _B0 (mem_available); Regs[0x0711] = _B1 (mem_available); Regs[0x0712] |= _B0 (_B2 (mem_available) << 4); /*xxxx---- */ Regs[0x0713] = 0x00; Regs[0x0714] = 0x10; Regs[0x0715] &= 0xf0; } } static void RTS_Setup_Arrangeline (struct st_device *dev, struct st_hwdconfig *hwdcfg, SANE_Int colormode) { dev->scanning->arrange_compression = (colormode == CM_LINEART) ? FALSE : hwdcfg->compression; if ((colormode == CM_LINEART) || ((colormode == CM_GRAY) && (hwdcfg->highresolution == FALSE))) arrangeline2 = 0; else arrangeline2 = hwdcfg->arrangeline; dev->scanning->arrange_hres = hwdcfg->highresolution; dev->scanning->arrange_sensor_evenodd_dist = (hwdcfg->highresolution == FALSE) ? 0 : hwdcfg->sensorevenodddistance; } static void RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode) { DBG (DBG_FNC, "> RTS_Setup_Channels(colormode=%i)\n", mycolormode); if ((scancfg != NULL) && (Regs != NULL)) { if ((mycolormode != CM_COLOR) && (mycolormode != 3)) { /* CM_GRAY || CM_LINEART */ if (scancfg->samplerate == LINE_RATE) { /* Setting channels_per_dot to 1 */ data_bitset (&Regs[0x12], 0xc0, 1); /*01------ */ /* setting one rgb_channel_order */ data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[scancfg->channel]); /*------xx*/ /* set sensor_channel_color_order */ data_bitset (&Regs[0x60a], 0x3f, 6); /*--xxxxxx*/ /* set samplerate */ data_bitset (&Regs[0x1cf], 0x40, PIXEL_RATE); /*-x------*/ /* set unknown data */ data_bitset (&Regs[0x1cf], 0x80, 1); /*x------- */ if (scancfg->channel == dev->sensorcfg->rgb_order[1]) { /* mexpts[CL_RED] = mexpts[CL_GREEN] */ data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x39], 3), 3); /* expts[CL_RED] = expts[CL_GREEN] */ data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x3c], 3), 3); } else if (scancfg->channel == dev->sensorcfg->rgb_order[2]) { /* mexpts[CL_RED] = mexpts[CL_BLUE] */ data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x3f], 3), 3); /* expts[CL_RED] = expts[CL_BLUE] */ data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x42], 3), 3); } } else { /* e01 */ /* setting channels_per_dot to 2 */ data_bitset (&Regs[0x12], 0xc0, 2); /* set two channel color order */ data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->channel_gray[0]); /*------xx*/ data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->channel_gray[1]); /*----xx--*/ /* set samplerate */ data_bitset (&Regs[0x1cf], 0x40, LINE_RATE); /* set unknown data */ data_bitset (&Regs[0x1cf], 0x80, 1); } } else { /* CM_COLOR || 3 */ /* e42 */ /* setting channels_per_dot to 3 */ data_bitset (&Regs[0x12], 0xc0, 3); /* setting samplerate */ data_bitset (&Regs[0x1cf], 0x40, scancfg->samplerate); /* set unknown data */ data_bitset (&Regs[0x1cf], 0x80, 0); /* set sensor chanel_color_order */ data_bitset (&Regs[0x60a], 0x03, dev->sensorcfg->channel_color[2]); /*------xx*/ data_bitset (&Regs[0x60a], 0x0c, dev->sensorcfg->channel_color[1]); /*----xx--*/ data_bitset (&Regs[0x60a], 0x30, dev->sensorcfg->channel_color[0]); /*--xx----*/ /* set rgb_channel_order */ data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[0]); /*------xx*/ data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->rgb_order[1]); /*----xx--*/ data_bitset (&Regs[0x12], 0x30, dev->sensorcfg->rgb_order[2]); /*--xx----*/ } } } static SANE_Int RTS_Setup (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, struct st_gain_offset *gain_offset) { SANE_Int rst = ERROR; /* default */ SANE_Int lSMode; SANE_Byte mycolormode; DBG (DBG_FNC, "+ RTS_Setup:\n"); dbg_ScanParams (scancfg); dbg_hwdcfg (hwdcfg); mycolormode = scancfg->colormode; if (scancfg->colormode != CM_COLOR) { if (scancfg->colormode == CM_LINEART) scancfg->depth = 8; if (scancfg->channel == 3) { if (scancfg->colormode == CM_GRAY) mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR; else mycolormode = 3; } } /* 42b47d6 */ memcpy (&scan2, scancfg, sizeof (struct st_scanparams)); scantype = hwdcfg->scantype; lSMode = RTS_GetScanmode (dev, scantype, mycolormode, scancfg->resolution_x); if (lSMode >= 0) { struct st_scanmode *sm = dev->scanmodes[lSMode]; if (sm != NULL) { SANE_Int dummyline, iLineDistance, resolution_ratio, bytes_per_line; struct st_coords rts_coords; iLineDistance = 0; scancfg->timing = sm->timing; scancfg->sensorresolution = dev->timings[scancfg->timing]->sensorresolution; scancfg->shadinglength = (((scancfg->sensorresolution * 17) / 2) + 3) & 0xfffffffc; scancfg->samplerate = sm->samplerate; hwdcfg->motorplus = sm->motorplus; /* set systemclock */ data_bitset (&Regs[0x00], 0x0f, sm->systemclock); /* setting exposure times */ RTS_Setup_Exposure_Times (Regs, scancfg, sm); /* setting arranges */ RTS_Setup_Arrangeline (dev, hwdcfg, mycolormode); /* set up line distances */ iLineDistance = RTS_Setup_Line_Distances (dev, Regs, scancfg, hwdcfg, mycolormode, arrangeline); /* 4c67 */ /* setup channel colors */ RTS_Setup_Channels (dev, Regs, scancfg, mycolormode); /* setup depth */ bytes_per_line = RTS_Setup_Depth (Regs, scancfg, mycolormode); /* f61 */ /* Set resolution ratio */ resolution_ratio = (scancfg->sensorresolution / scancfg->resolution_x) & 0x1f; data_bitset (&Regs[0xc0], 0x1f, resolution_ratio); /* set sensor timing values */ RTS_Setup_SensorTiming (dev, scancfg->timing, Regs); data_bitset (&Regs[0xd8], 0x40, ((scantype == ST_NORMAL) ? 0 : 1)); /*-x------*/ /* Use static head ? */ data_bitset (&Regs[0xd8], 0x80, ((hwdcfg->static_head == FALSE) ? 1 : 0)); /*x------- */ /* Setting up gamma */ RTS_Setup_Gamma (Regs, hwdcfg); /* setup shading correction */ RTS_Setup_Shading (Regs, scancfg, hwdcfg, bytes_per_line); /* setup stepper motor */ hwdcfg->startpos = RTS_Setup_Motor (dev, Regs, scancfg, hwdcfg->motor_direction | MTR_ENABLED); /* set coordinates */ dummyline = data_bitget (&Regs[0xd6], 0xf0); if (scancfg->coord.left == 0) scancfg->coord.left++; if (scancfg->coord.top == 0) scancfg->coord.top++; rts_coords.left = scancfg->coord.left * resolution_ratio; rts_coords.width = scancfg->coord.width * resolution_ratio; rts_coords.top = scancfg->coord.top * dummyline; rts_coords.height = ((Regs[0x14d] & 0x3f) + scancfg->coord.height + iLineDistance) * dummyline; if ((rts_coords.left & 1) == 0) rts_coords.left++; RTS_Setup_Coords (Regs, rts_coords.left, rts_coords.top, rts_coords.width, rts_coords.height); data_bitset (&Regs[0x01], 0x06, 0); /*-----xx-*/ /* dummy_scan? */ data_bitset (&Regs[0x01], 0x10, hwdcfg->dummy_scan); /*---x----*/ data_bitset (&Regs[0x163], 0xc0, 1); /*xx------ */ if (dev->scanning->arrange_compression != FALSE) { Regs[0x60b] &= 0x8f; data_bitset (&Regs[0x60b], 0x10, 1); /*-001----*/ } else data_bitset (&Regs[0x60b], 0x7f, 0); /*-0000000*/ if (mycolormode == 3) { SANE_Int channels_per_line; /* Set channels_per_line = channels_per_dot * scan_width */ channels_per_line = data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width; data_wide_bitset (&Regs[0x060c], 0x3ffff, channels_per_line); /* Sets 16 bits per channel */ data_bitset (&Regs[0x1cf], 0x30, 2); /*--10----*/ Regs[0x60b] |= 0x40; if (v1619 == 0x21) { dev->scanning->arrange_compression = FALSE; data_bitset (&Regs[0x60b], 0x10, 0); /*---0----*/ } switch (scancfg->depth) { case 8: case 16: Regs[0x060b] &= 0xf3; break; case 12: Regs[0x060b] = (Regs[0x060b] & 0xfb) | 0x08; break; } if (scancfg->colormode == CM_LINEART) data_bitset (&Regs[0x60b], 0x0c, 0); /* disable gamma correction ¿? */ data_bitset (&Regs[0x1d0], 0x40, 0); } /* 5683 */ /* Set calibration table */ RTS_Setup_GainOffset (Regs, gain_offset); rst = OK; } } DBG (DBG_FNC, "- RTS_Setup: %i\n", rst); return rst; } static void RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop, SANE_Int width, SANE_Int height) { DBG (DBG_FNC, "> RTS_Setup_Coords(*Regs, iLeft=%i, iTop=%i, width=%i, height=%i)\n", iLeft, iTop, width, height); if (Regs != NULL) { /* Set Left coord */ data_lsb_set (&Regs[0xb0], iLeft, 2); /* Set Right coord */ data_lsb_set (&Regs[0xb2], iLeft + width, 2); /* Set Top coord */ data_lsb_set (&Regs[0xd0], iTop, 2); data_bitset (&Regs[0xd4], 0x0f, _B2 (iTop)); /* Set Down coord */ data_lsb_set (&Regs[0xd2], iTop + height, 2); data_bitset (&Regs[0xd4], 0xf0, _B2 (iTop + height)); } } static void RTS_Setup_GainOffset (SANE_Byte * Regs, struct st_gain_offset *gain_offset) { SANE_Byte fake[] = { 0x19, 0x15, 0x19, 0x64, 0x64, 0x64, 0x74, 0xc0, 0x74, 0xc0, 0x6d, 0xc0, 0x6d, 0xc0, 0x5f, 0xc0, 0x5f, 0xc0 }; DBG (DBG_FNC, "> RTS_Setup_GainOffset(*Regs, *gain_offset)\n"); dbg_calibtable (gain_offset); if ((Regs != NULL) && (gain_offset != NULL)) { if (RTS_Debug->calibrate == FALSE) { data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]); /*------xx*/ data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]); /*----xx--*/ data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]); /*--xx----*/ memcpy (&Regs[0x14], &fake, 18); } else { SANE_Int a; for (a = CL_RED; a <= CL_BLUE; a++) { /* Offsets */ Regs[0x1a + (a * 4)] = _B0 (gain_offset->edcg1[a]); Regs[0x1b + (a * 4)] = ((gain_offset->edcg1[a] >> 1) & 0x80) | (gain_offset-> edcg2[a] & 0x7f); Regs[0x1c + (a * 4)] = _B0 (gain_offset->odcg1[a]); Regs[0x1d + (a * 4)] = ((gain_offset->odcg1[a] >> 1) & 0x80) | (gain_offset-> odcg2[a] & 0x7f); /* Variable Gain Amplifier */ data_bitset (&Regs[0x14 + a], 0x1f, gain_offset->vgag1[a]); data_bitset (&Regs[0x17 + a], 0x1f, gain_offset->vgag2[a]); } data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]); /*------xx*/ data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]); /*----xx--*/ data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]); /*--xx----*/ } } } static void Calibrate_Free (struct st_cal2 *calbuffers) { DBG (DBG_FNC, "> Calibrate_Free(*calbuffers)\n"); if (calbuffers != NULL) { SANE_Int c; if (calbuffers->table2 != NULL) { free (calbuffers->table2); calbuffers->table2 = NULL; } for (c = 0; c < 4; c++) { if (calbuffers->tables[c] != NULL) { free (calbuffers->tables[c]); calbuffers->tables[c] = NULL; } } calbuffers->shadinglength1 = 0; calbuffers->tables_size = 0; calbuffers->shadinglength3 = 0; } } static SANE_Int Calibrate_Malloc (struct st_cal2 *calbuffers, SANE_Byte * Regs, struct st_calibration *myCalib, SANE_Int somelength) { SANE_Int myshadinglength, pos; SANE_Int rst; if ((calbuffers != NULL) && (Regs != NULL) && (myCalib != NULL)) { if ((Regs[0x1bf] & 0x18) == 0) { if ((((Regs[0x1cf] >> 1) & Regs[0x1cf]) & 0x04) != 0) calbuffers->table_count = 2; else calbuffers->table_count = 4; } else calbuffers->table_count = 4; /*365d */ myshadinglength = myCalib->shadinglength * 2; calbuffers->shadinglength1 = min (myshadinglength, somelength); if ((myshadinglength % somelength) != 0) calbuffers->tables_size = (myshadinglength >= somelength) ? somelength * 2 : somelength; else calbuffers->tables_size = somelength; if (myshadinglength >= somelength) { calbuffers->shadinglength1 = (myshadinglength % calbuffers->shadinglength1) + calbuffers->shadinglength1; calbuffers->shadinglength3 = ((myCalib->shadinglength * 2) / somelength) - 1; } else calbuffers->shadinglength3 = 0; calbuffers->shadinglength3 = (somelength / 16) * calbuffers->shadinglength3; rst = OK; for (pos = 0; pos < calbuffers->table_count; pos++) { calbuffers->tables[pos] = (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT)); if (calbuffers->tables[pos] == NULL) { rst = ERROR; break; } } if (rst == OK) { calbuffers->table2 = (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT)); if (calbuffers->table2 == NULL) rst = ERROR; } if (rst != OK) Calibrate_Free (calbuffers); } else rst = ERROR; DBG (DBG_FNC, "> Calibrate_Malloc(*calbuffers, *Regs, *myCalib, somelength=%i): %i\n", somelength, rst); return rst; } static SANE_Int fn3560 (USHORT * table, struct st_cal2 *calbuffers, SANE_Int * tablepos) { /*05FEF974 001F99B0 |table = 001F99B0 05FEF978 05FEFA08 |calbuffers->tables[0] = 05FEFA08 05FEF97C 000000A0 |calbuffers->shadinglength3 = 000000A0 05FEF980 00000348 |calbuffers->shadinglength1 = 00000348 05FEF984 04F01502 |calbuffers->table_count = 04F01502 05FEF988 05FEF998 \Arg6 = 05FEF998 */ if (table != NULL) { SANE_Int pos[4] = { 0, 0, 0, 0 }; /*f960 f964 f968 f96c */ SANE_Int usetable = 0; SANE_Int a; SANE_Int mylength3 = calbuffers->shadinglength1; /*f97c */ SANE_Byte *pPointer = (SANE_Byte *) (table + (calbuffers->shadinglength3 * 16)); DBG (DBG_FNC, "> fn3560(*table, *calbuffers, *tablepos)\n"); if (mylength3 > 0) { do { if (calbuffers->tables[usetable] != NULL) { if (mylength3 <= 16) { if (mylength3 > 0) { do { *(calbuffers->tables[usetable] + pos[usetable]) = _B0 (*pPointer); pPointer++; pos[usetable]++; mylength3--; } while (mylength3 > 0); } break; } for (a = 0; a < 16; a++) { *(calbuffers->tables[usetable] + pos[usetable]) = _B0 (*pPointer); pPointer++; pos[usetable]++; } } mylength3 -= 16; usetable++; if (usetable == calbuffers->table_count) usetable = 0; } while (mylength3 > 0); } /*35f8 */ if (calbuffers->table_count > 0) { /* Return position of each table */ memcpy (tablepos, pos, sizeof (SANE_Int) * 4); } } return OK; } static SANE_Int Calib_WriteTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Calib_WriteTable(*table, size=%i):\n", size); if ((table != NULL) && (size > 0)) { SANE_Int transferred; if (RTS_DMA_Reset (dev) == OK) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, 0x0004, size, data) == OK) /* Send data */ rst = Bulk_Operation (dev, BLK_WRITE, size, table, &transferred); } } DBG (DBG_FNC, "- Calib_WriteTable: %i\n", rst); return rst; } static SANE_Int Calib_ReadTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Calib_ReadTable(*table, size=%i):\n", size); if ((table != NULL) && (size > 0)) { SANE_Int transferred; if (RTS_DMA_Reset (dev) == OK) { /* Send size to read */ if (RTS_DMA_Enable_Read (dev, 0x0004, size, data) == OK) /* Retrieve data */ rst = Bulk_Operation (dev, BLK_READ, size, table, &transferred); } } DBG (DBG_FNC, "- Calib_ReadTable: %i\n", rst); return rst; } static SANE_Int fn3330 (struct st_device *dev, SANE_Byte * Regs, struct st_cal2 *calbuffers, SANE_Int sensorchannelcolor, SANE_Int * tablepos, SANE_Int data) { /*05EEF968 04F0F7F8 |Regs = 04F0F7F8 05EEF96C 02DEC838 |calbuffers->table2 = 02DEC838 05EEF970 05EEFA08 |calbuffers->tables[] = 05EEFA08 05EEF974 00000000 |sensorchannelcolor = 00000000 05EEF978 000000A0 |calbuffers->shadinglength3 = 000000A0 05EEF97C 00000400 |calbuffers->tables_size = 00000400 05EEF980 05EEF998 |&pos = 05EEF998 05EEF984 00221502 |calbuffers->table_count = 00221502 05EEF988 00000000 \data = 00000000 */ SANE_Int table_count = calbuffers->table_count; /*f960 */ SANE_Int schcolor = _B0 (sensorchannelcolor); SANE_Int a = 0; SANE_Int tablelength = calbuffers->shadinglength3 / table_count; /*f954 */ SANE_Int val_color = 0; /*f974 */ SANE_Int val_lineart = 0; /*f978 */ SANE_Int val_gray = 0; /*ebx */ SANE_Int value4 = 0; /*ebp */ SANE_Int size; SANE_Int rst = OK; DBG (DBG_FNC, "+ fn3330(*Regs, *calbuffers, sensorchannelcolor=%i, *tablepos, data=%i):\n", sensorchannelcolor, data); if (calbuffers->table_count > 0) { do { if (calbuffers->table_count == 2) { /*338c */ if (a != 0) { /*3394 */ if (_B0 (data) == 0) { val_color = 0x100000; val_lineart = 0x100000; val_gray = 0x200000; } else { /*343a */ val_color = 0x300000; val_lineart = 0x300000; val_gray = 0; } } else { /*33be */ if (_B0 (data) == 0) { val_color = 0; val_lineart = 0; val_gray = 0x300000; } else { /*342a */ val_color = 0x200000; val_lineart = 0x200000; val_gray = 0x100000; } } } else { /*33d5 */ switch (a) { case 0: val_color = 0; val_lineart = 0; val_gray = 0x300000; break; case 1: val_color = 0x200000; val_lineart = 0x200000; val_gray = 0x100000; break; case 2: val_color = 0x100000; val_lineart = 0x100000; val_gray = 0x200000; break; case 3: val_color = 0x300000; val_lineart = 0x300000; val_gray = 0; break; } } /*3449 */ switch (schcolor) { case CM_LINEART: size = (((Regs[0x1bf] >> 1) & 3) << 0x10) | (Regs[0x1be] << 0x08) | Regs[0x1bd]; value4 = (tablelength + size) | val_lineart; break; case CM_GRAY: size = ((Regs[0x1bf] & 1) << 0x10) | (Regs[0x1bc] << 0x08) | Regs[0x1bb]; value4 = (tablelength + size) | val_gray; break; default: size = _B0 (Regs[0x1ba]); value4 = (tablelength + size) | val_color; break; } if (Calib_ReadTable (dev, (SANE_Byte *) calbuffers->table2, calbuffers->tables_size, value4) != OK) { rst = ERROR; break; } memcpy (calbuffers->tables[a], calbuffers->table2, tablepos[a]); if (tablepos[a + 1] == 0) break; a++; } while (a < calbuffers->table_count); } DBG (DBG_FNC, "- fn3330: %i\n", rst); return rst; } static SANE_Int fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, SANE_Byte * Regs, USHORT * table, SANE_Int sensorchannelcolor, SANE_Int data) { /*05FEF9AC |calbuffers = 05FEF9F8 05FEF9B0 |Regs = 04EFF7F8 05FEF9B4 |table = 001F99B0 05FEF9B8 |sensorchannelcolor = 00000000 05FEF9BC |data = 00000000 */ SANE_Int pos[4] = { 0, 0, 0, 0 }; /*f998 f99c f9a0 f9a4 */ SANE_Int rst; DBG (DBG_FNC, "+ fn3730(*calbuffers, *Regs, *table, sensorchannelcolor=%i, data=%i):\n", sensorchannelcolor, data); fn3560 (table, calbuffers, pos); rst = fn3330 (dev, Regs, calbuffers, sensorchannelcolor, pos, data); DBG (DBG_FNC, "- fn3730: %i\n", rst); return rst; } static SANE_Int Shading_white_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Shading_white_apply(channels=%i)\n", channels); /*3e7f */ Calibrate_Malloc (calbuffers, Regs, myCalib, (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40); if (channels > 0) { /*int a; */ SANE_Int chnl; SANE_Int pos; /*fa2c */ SANE_Int transferred; rst = ERROR; for (chnl = 0; chnl < channels; chnl++) { /*for (a = 0; a < myCalib->shadinglength; a++) myCalib->black_shading[chnl][a] = 0x2000; */ /* 11 tries */ for (pos = 0; pos <= 10; pos++) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, dev->sensorcfg->channel_color[chnl] | 0x14, myCalib->shadinglength, 0) == OK) /* Send data */ Bulk_Operation (dev, BLK_WRITE, myCalib->shadinglength * sizeof (USHORT), (SANE_Byte *) & myCalib-> white_shading[chnl][myCalib->first_position - 1], &transferred); /*3df7 */ if (fn3730 (dev, calbuffers, Regs, &myCalib->white_shading[chnl][myCalib->first_position - 1], dev->sensorcfg->channel_color[chnl], 1) == OK) { rst = OK; break; } RTS_DMA_Cancel (dev); } } } Calibrate_Free (calbuffers); DBG (DBG_FNC, "- Shading_white_apply: %i\n", rst); return OK; } static SANE_Int Shading_black_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Shading_black_apply(channels=%i)\n", channels); /* 3d79 */ Calibrate_Malloc (calbuffers, Regs, myCalib, (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40); if (channels > 0) { /*int a; */ SANE_Int chnl; SANE_Int pos; /*fa2c */ SANE_Int transferred; rst = ERROR; for (chnl = 0; chnl < channels; chnl++) { /* 11 tries */ /*for (a = 0; a < myCalib->shadinglength; a++) myCalib->black_shading[chnl][a] = 0x2000; */ for (pos = 0; pos <= 10; pos++) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, dev->sensorcfg->channel_color[chnl] | 0x10, myCalib->shadinglength, 0) == OK) /* Send data */ Bulk_Operation (dev, BLK_WRITE, myCalib->shadinglength * sizeof (USHORT), (SANE_Byte *) & myCalib-> black_shading[chnl][myCalib->first_position - 1], &transferred); /*3df7 */ if (fn3730 (dev, calbuffers, Regs, &myCalib->black_shading[chnl][myCalib->first_position - 1], dev->sensorcfg->channel_color[chnl], 0) == OK) { rst = OK; break; } RTS_DMA_Cancel (dev); } } } /*3e62 */ Calibrate_Free (calbuffers); DBG (DBG_FNC, "- Shading_black_apply: %i\n", rst); return OK; } static SANE_Int Shading_apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, struct st_calibration *myCalib) { /* Regs f1bc myvar f020 hwdcfg e838 arg4 e81c myCalib e820 */ SANE_Int rst; /* lf9e0 */ SANE_Int myfact; /* e820 */ SANE_Int shadata; SANE_Byte channels; /* f9d4 */ SANE_Int myShadingBase; /* e818 */ char lf9d1; char lf9d0; DBG (DBG_FNC, "+ Shading_apply(*Regs, *myvar, *mygamma, *myCalib):\n"); dbg_ScanParams (myvar); lf9d0 = (Regs[0x60b] >> 6) & 1; lf9d1 = (Regs[0x60b] >> 4) & 1; Regs[0x060b] &= 0xaf; rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); if (rst == OK) { SANE_Byte colormode = myvar->colormode; /*fa24 */ SANE_Int le7cc, le7d8; struct st_cal2 calbuffers; /* f9f8 */ if (colormode != CM_COLOR) { if (myvar->channel != 3) { if (colormode != 3) channels = (myvar->samplerate == PIXEL_RATE) ? 2 : 1; else channels = 3; } else { colormode = 3; channels = 3; } } else channels = 3; /* White shading formula : 2000H x Target / (Wn-Dn) = White Gain data ----- for 8 times system White shading formula : 4000H x Target / (Wn-Dn) = White Gain data ----- for 4 times system For example : Target = 3FFFH Wn = 2FFFH Dn = 0040H and 8 times system operation then White Gain = 2000H x 3FFFH / (2FFFH-0040H) = 2AE4H (1.34033 times) */ /* 3aad */ if (colormode == 3) { /* SANE_Int pos; SANE_Int colour; myShadingBase = shadingbase; for (colour = 0; colour < channels; colour++) { if (myCalib->white_shading[colour] != NULL) { myfact = shadingfact[colour]; if (myCalib->shadinglength > 0) { for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) myCalib->white_shading[colour][pos] = (myCalib->white_shading[colour][pos] * myfact) / myShadingBase; } } else break; } */ } /* 3b3b */ if (myCalib->shading_enabled != FALSE) { /* 3b46 */ SANE_Int colour, pos; le7cc = shadingbase; le7d8 = shadingbase; DBG (DBG_FNC, "-> Shading type: %i\n", myCalib->shading_type); for (colour = 0; colour < channels; colour++) { if (colormode == 3) le7cc = shadingfact[colour]; myShadingBase = ((Regs[0x1cf] & 2) != 0) ? 0x2000 : 0x4000; myfact = myCalib->WRef[colour] * myShadingBase; if (myCalib->shading_type == 2) { /*3bd8 */ if ((myCalib->black_shading[colour] != NULL) && (myCalib->white_shading[colour] != NULL)) { for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) { if (myCalib->white_shading[colour][pos] == 0) shadata = myShadingBase; else shadata = myfact / myCalib->white_shading[colour][pos]; shadata = min ((shadata * le7cc) / le7d8, 0xff00); myCalib->black_shading[colour][pos] &= 0xff; myCalib->black_shading[colour][pos] |= shadata & 0xff00; } } else break; } else { /*3c63 */ if (myCalib->shading_type == 3) { /*3c68 */ if (myCalib->black_shading[colour] != NULL) { for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) { if (myCalib->black_shading[colour][pos] == 0) shadata = myShadingBase; else shadata = myfact / myCalib->black_shading[colour][pos]; shadata = min ((shadata * le7cc) / le7d8, 0xffc0); myCalib->black_shading[colour][pos] &= 0x3f; myCalib->black_shading[colour][pos] |= shadata & 0xffc0; } } else break; } else { /*3ce3 */ if (myCalib->white_shading[colour] != NULL) { for (pos = 0; pos < myCalib->shadinglength; pos++) { if (myCalib->white_shading[colour][pos] == 0) shadata = myShadingBase; else shadata = myfact / myCalib->white_shading[colour][pos]; shadata = min ((shadata * le7cc) / le7d8, 0xffff); myCalib->white_shading[colour][pos] = shadata; } } else break; } } } } /*3d4c */ bzero (&calbuffers, sizeof (struct st_cal2)); /* If black shading correction is enabled ... */ if ((Regs[0x1cf] & 8) != 0) Shading_black_apply (dev, Regs, channels, myCalib, &calbuffers); /*3e6e */ /* If white shading correction is enabled ... */ if ((Regs[0x1cf] & 4) != 0) Shading_white_apply (dev, Regs, channels, myCalib, &calbuffers); /* 3f74 */ if (rst == 0) { data_bitset (&Regs[0x60b], 0x40, lf9d0); /*-x------*/ data_bitset (&Regs[0x60b], 0x10, lf9d1); /*---x----*/ rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); } } /*3fb5 */ DBG (DBG_FNC, "- Shading_apply: %i\n", rst); return rst; } static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transfered) { SANE_Int iTransferSize, iBytesToTransfer, iPos, rst, iBytesTransfered; DBG (DBG_FNC, "+ Bulk_Operation(op=%s, buffer_size=%i, buffer):\n", ((op & 0x01) != 0) ? "READ" : "WRITE", buffer_size); iBytesToTransfer = buffer_size; iPos = 0; rst = OK; iBytesTransfered = 0; if (transfered != NULL) *transfered = 0; iTransferSize = min (buffer_size, RTS_Debug->dmatransfersize); if (op != 0) { /* Lectura */ do { iTransferSize = min (iTransferSize, iBytesToTransfer); iBytesTransfered = Read_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize); if (iBytesTransfered < 0) { rst = ERROR; break; } else { if (transfered != NULL) *transfered += iBytesTransfered; } iPos += iTransferSize; iBytesToTransfer -= iTransferSize; } while (iBytesToTransfer > 0); } else { /* Escritura */ do { iTransferSize = min (iTransferSize, iBytesToTransfer); if (Write_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize) != OK) { rst = ERROR; break; } else { if (transfered != NULL) *transfered += iTransferSize; } iPos += iTransferSize; iBytesToTransfer -= iTransferSize; } while (iBytesToTransfer > 0); } DBG (DBG_FNC, "- Bulk_Operation: %i\n", rst); return rst; } static SANE_Int Reading_BufferSize_Notify (struct st_device *dev, SANE_Int data, SANE_Int size) { SANE_Int rst; DBG (DBG_FNC, "+ Reading_BufferSize_Notify(data=%i, size=%i):\n", data, size); rst = RTS_DMA_Enable_Read (dev, 0x0008, size, data); DBG (DBG_FNC, "- Reading_BufferSize_Notify: %i\n", rst); return rst; } static SANE_Int Reading_Wait (struct st_device *dev, SANE_Byte Channels_per_dot, SANE_Byte Channel_size, SANE_Int size, SANE_Int * last_amount, SANE_Int seconds, SANE_Byte op) { SANE_Int rst; SANE_Byte cTimeout, executing; SANE_Int lastAmount, myAmount; long tick; DBG (DBG_FNC, "+ Reading_Wait(Channels_per_dot=%i, Channel_size=%i, size=%i, *last_amount, seconds=%i, op=%i):\n", Channels_per_dot, Channel_size, size, seconds, op); rst = OK; cTimeout = FALSE; lastAmount = 0; myAmount = Reading_BufferSize_Get (dev, Channels_per_dot, Channel_size); if (myAmount < size) { /* Wait until scanner fills its buffer */ if (seconds == 0) seconds = 10; tick = GetTickCount () + (seconds * 1000); while (cTimeout == FALSE) { myAmount = Reading_BufferSize_Get (dev, Channels_per_dot, Channel_size); /* check special case */ if (op == TRUE) { if (((myAmount + 0x450) > size) || (RTS_IsExecuting (dev, &executing) == FALSE)) break; } if (myAmount < size) { /* Check timeout */ if (myAmount == lastAmount) { /* we are in timeout? */ if (tick < GetTickCount ()) { /* TIMEOUT */ rst = ERROR; cTimeout = TRUE; } else usleep (100 * 1000); } else { /* Amount increased, update tick */ lastAmount = myAmount; tick = GetTickCount () + (seconds * 1000); } } else { lastAmount = myAmount; break; /* buffer full */ } } } if (last_amount != NULL) *last_amount = myAmount; DBG (DBG_FNC, "- Reading_Wait: %i , last_amount=%i\n", rst, myAmount); return rst; } static SANE_Int RTS_GetImage_GetBuffer (struct st_device *dev, double dSize, char unsigned *buffer, double *transferred) { SANE_Int rst = ERROR; SANE_Int itransferred; double dtransferred = 0; DBG (DBG_FNC, "+ RTS_GetImage_GetBuffer(dSize=%f, buffer, transferred):\n", dSize); rst = OK; dSize /= 2; if (dSize > 0) { SANE_Int myLength; SANE_Int iPos = 0; do { itransferred = 0; myLength = (dSize <= RTS_Debug->dmasetlength) ? dSize : RTS_Debug->dmasetlength; if (myLength > 0x1ffe0) myLength = 0x1ffe0; rst = ERROR; if (Reading_Wait (dev, 0, 1, myLength * 2, NULL, 5, FALSE) == OK) { if (Reading_BufferSize_Notify (dev, 0, myLength * 2) == OK) rst = Bulk_Operation (dev, BLK_READ, myLength * 2, &buffer[iPos], &itransferred); } if (rst != OK) break; iPos += itransferred; dSize -= itransferred; dtransferred += itransferred * 2; } while (dSize > 0); } /* Return bytes transferred */ if (transferred != NULL) *transferred = dtransferred; if (rst != OK) RTS_DMA_Cancel (dev); DBG (DBG_FNC, "- RTS_GetImage_GetBuffer: %i\n", rst); return rst; } static SANE_Int RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg) { /*buffer f80c = esp+14 scancfg f850 = esp+18 hwdcfg faac = */ SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_GetImage_Read(buffer, scancfg, hwdcfg):\n"); if (buffer != NULL) { double dSize = scancfg->bytesperline * scancfg->coord.height; SANE_Byte exfn; if (scancfg->depth == 12) dSize = (dSize * 3) / 4; /*3ff6 */ exfn = 1; if (hwdcfg != NULL) if (hwdcfg->compression != FALSE) exfn = 0; if (exfn != 0) { double transferred; rst = RTS_GetImage_GetBuffer (dev, dSize, buffer, &transferred); } if (rst == OK) RTS_WaitScanEnd (dev, 1500); } DBG (DBG_FNC, "- RTS_GetImage_Read: %i\n", rst); return rst; } static SANE_Int RTS_GetImage (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_gain_offset *gain_offset, SANE_Byte * buffer, struct st_calibration *myCalib, SANE_Int options, SANE_Int gaincontrol) { /* 42b8e10 */ SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ RTS_GetImage(*Regs, *scancfg, *gain_offset, *buffer, myCalib, options=0x%08x, gaincontrol=%i):\n", options, gaincontrol); dbg_ScanParams (scancfg); /* validate arguments */ if ((Regs != NULL) && (scancfg != NULL)) { if ((scancfg->coord.width != 0) && (scancfg->coord.height != 0)) { struct st_scanparams *myscancfg; /* let's make a copy of scan config */ myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); if (myscancfg != NULL) { struct st_hwdconfig *hwdcfg; memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); /* Allocate space for low level config */ hwdcfg = (struct st_hwdconfig *) malloc (sizeof (struct st_hwdconfig)); if (hwdcfg != NULL) { bzero (hwdcfg, sizeof (struct st_hwdconfig)); if (((options & 2) != 0) || ((_B1 (options) & 1) != 0)) { /* switch off lamp */ data_bitset (&Regs[0x146], 0x40, 0); Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]); usleep (1000 * ((v14b4 == 0) ? 500 : 300)); } hwdcfg->scantype = scan.scantype; hwdcfg->use_gamma_tables = ((options & OP_USE_GAMMA) != 0) ? 1 : 0; hwdcfg->white_shading = ((options & OP_WHITE_SHAD) != 0) ? 1 : 0; hwdcfg->black_shading = ((options & OP_BLACK_SHAD) != 0) ? 1 : 0; hwdcfg->motor_direction = ((options & OP_BACKWARD) != 0) ? MTR_BACKWARD : MTR_FORWARD; hwdcfg->compression = ((options & OP_COMPRESSION) != 0) ? 1 : 0; hwdcfg->static_head = ((options & OP_STATIC_HEAD) != 0) ? 1 : 0; hwdcfg->dummy_scan = (buffer == NULL) ? TRUE : FALSE; hwdcfg->arrangeline = 0; hwdcfg->highresolution = (myscancfg->resolution_x > 1200) ? TRUE : FALSE; hwdcfg->unk3 = 0; /* Set Left coord */ myscancfg->coord.left += ((dev->sensorcfg->type == CCD_SENSOR) ? 24 : 50); switch (myscancfg->resolution_x) { case 1200: myscancfg->coord.left -= 63; break; case 2400: myscancfg->coord.left -= 126; break; } if (myscancfg->coord.left < 0) myscancfg->coord.left = 0; RTS_Setup (dev, Regs, myscancfg, hwdcfg, gain_offset); /* Setting exposure time */ switch (scan.scantype) { case ST_NORMAL: if (scan.resolution_x == 100) { SANE_Int iValue; SANE_Byte *myRegs; myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (myRegs != NULL) { bzero (myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte)); RTS_Setup (dev, myRegs, &scan, hwdcfg, gain_offset); iValue = data_lsb_get (&myRegs[0x30], 3); data_lsb_set (&Regs[0x30], iValue, 3); /*Copy myregisters mexpts to Regs mexpts */ iValue = data_lsb_get (&myRegs[0x33], 3); data_lsb_set (&Regs[0x33], iValue, 3); iValue = data_lsb_get (&myRegs[0x39], 3); data_lsb_set (&Regs[0x39], iValue, 3); iValue = data_lsb_get (&myRegs[0x3f], 3); data_lsb_set (&Regs[0x3f], iValue, 3); free (myRegs); } } break; case ST_NEG: { SANE_Int myvalue; /* Setting exposure times for Negative scans */ data_lsb_set (&Regs[0x30], myscancfg->expt, 3); data_lsb_set (&Regs[0x33], myscancfg->expt, 3); data_lsb_set (&Regs[0x39], myscancfg->expt, 3); data_lsb_set (&Regs[0x3f], myscancfg->expt, 3); data_lsb_set (&Regs[0x36], 0, 3); data_lsb_set (&Regs[0x3c], 0, 3); data_lsb_set (&Regs[0x42], 0, 3); myvalue = ((myscancfg->expt + 1) / (data_lsb_get (&Regs[0xe0], 1) + 1)) - 1; data_lsb_set (&Regs[0xe1], myvalue, 3); } break; } /* 91a0 */ if (myscancfg->resolution_y > 600) { options |= 0x20000000; if (options != 0) /* Always true ... */ SetMultiExposure (dev, Regs); else myscancfg->coord.top += hwdcfg->startpos; } else SetMultiExposure (dev, Regs); /* 91e2 */ RTS_WriteRegs (dev->usb_handle, Regs); if (myCalib != NULL) Shading_apply (dev, Regs, myscancfg, myCalib); if (dev->motorcfg->changemotorcurrent != FALSE) Motor_Change (dev, Regs, Motor_GetFromResolution (myscancfg-> resolution_x)); /* mlock = 0 */ data_bitset (&Regs[0x00], 0x10, 0); data_wide_bitset (&Regs[0xde], 0xfff, 0); /* release motor */ Motor_Release (dev); if (RTS_Warm_Reset (dev) == OK) { rst = OK; SetLock (dev->usb_handle, Regs, (myscancfg->depth == 16) ? FALSE : TRUE); /* set gain control */ Lamp_SetGainMode (dev, Regs, myscancfg->resolution_x, gaincontrol); /* send registers to scanner */ if (RTS_WriteRegs (dev->usb_handle, Regs) == OK) { /* execute! */ if (RTS_Execute (dev) == OK) RTS_GetImage_Read (dev, buffer, myscancfg, hwdcfg); /*92e7 */ } /*92fc */ SetLock (dev->usb_handle, Regs, FALSE); if ((options & 0x200) != 0) { /* switch on lamp */ data_bitset (&Regs[0x146], 0x40, 1); Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]); /* Wait 3 seconds */ usleep (1000 * 3000); } /*9351 */ if (dev->motorcfg->changemotorcurrent == TRUE) Motor_Change (dev, dev->init_regs, 3); } /* free low level configuration */ free (hwdcfg); } /* free scanning configuration */ free (myscancfg); } } } DBG (DBG_FNC, "- RTS_GetImage: %i\n", rst); return rst; } static SANE_Int Refs_Detect (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution_x, SANE_Int resolution_y, SANE_Int * x, SANE_Int * y) { SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ Refs_Detect(*Regs, resolution_x=%i, resolution_y=%i):\n", resolution_x, resolution_y); if ((x != NULL) && (y != NULL)) { SANE_Byte *image; struct st_scanparams scancfg; *x = *y = 0; /* default */ /* set configuration to scan a little area at the top-left corner */ bzero (&scancfg, sizeof (struct st_scanparams)); scancfg.depth = 8; scancfg.colormode = CM_GRAY; scancfg.channel = CL_RED; scancfg.resolution_x = resolution_x; scancfg.resolution_y = resolution_y; scancfg.coord.left = 4; scancfg.coord.width = (resolution_x * 3) / 10; scancfg.coord.top = 1; scancfg.coord.height = (resolution_y * 4) / 10; scancfg.shadinglength = (resolution_x * 17) / 2; scancfg.bytesperline = scancfg.coord.width; /* allocate space to store image */ image = (SANE_Byte *) malloc ((scancfg.coord.height * scancfg.coord.width) * sizeof (SANE_Byte)); if (image != NULL) { struct st_gain_offset gain_offset; SANE_Int gaincontrol, pwmlamplevel_backup, C; gaincontrol = 0; if (RTS_Debug->use_fixed_pwm == FALSE) { /* 3877 */ gaincontrol = Lamp_GetGainMode (dev, resolution_x, ST_NORMAL); /* scan.scantype */ pwmlamplevel = 0; Lamp_PWM_use (dev, 1); Lamp_PWM_DutyCycle_Set (dev, (gaincontrol == 0) ? 0x12 : 0x26); /* Enciende flb lamp */ Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); usleep (1000 * 2000); } /* 38d6 */ pwmlamplevel_backup = pwmlamplevel; pwmlamplevel = 0; Lamp_PWM_use (dev, 1); bzero (&gain_offset, sizeof (struct st_gain_offset)); for (C = CL_RED; C <= CL_BLUE; C++) { gain_offset.pag[C] = 3; gain_offset.vgag1[C] = 4; gain_offset.vgag2[C] = 4; } /* perform lamp warmup */ Lamp_Warmup (dev, Regs, FLB_LAMP, resolution_x); /* retrieve image from scanner */ if (RTS_GetImage (dev, Regs, &scancfg, &gain_offset, image, 0, 0x20000000, gaincontrol) == OK) { SANE_Int ser1, ler1; /* same image to disk if required by user */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("pre-autoref.tiff", scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_GRAY, scancfg.resolution_x, scancfg.resolution_y, image, scancfg.coord.height * scancfg.coord.width); } /* calculate reference position */ if (Refs_Analyze_Pattern (&scancfg, image, &ler1, 1, &ser1, 0) == OK) { *y = scancfg.coord.top + ler1; *x = scancfg.coord.left + ser1; rst = OK; } } free (image); pwmlamplevel = pwmlamplevel_backup; } DBG (DBG_FNC, " -> Detected refs: x=%i , y=%i\n", *x, *y); } DBG (DBG_FNC, "- Refs_Detect: %i\n", rst); return rst; } static SANE_Int Refs_Set (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg) { SANE_Int rst; SANE_Int y, x; struct st_autoref refcfg; DBG (DBG_FNC, "+ Refs_Set(*Regs, *scancfg):\n"); dbg_ScanParams (scancfg); rst = OK; /* get fixed references for given resolution */ cfg_vrefs_get (dev->sensorcfg->type, scancfg->resolution_x, &scan.ler, &scan.ser); scan.leftleading = scan.ser; scan.startpos = scan.ler; /* get auto reference configuration */ cfg_autoref_get (&refcfg); if (refcfg.type != REF_NONE) { /* if reference counter is == 0 perform auto detection */ if (Refs_Counter_Load (dev) == 0) { DBG (DBG_FNC, " -> Refs_Set - Autodetection mandatory (counter == 0)\n"); refcfg.type = REF_AUTODETECT; } switch (refcfg.type) { case REF_AUTODETECT: /* try to autodetect references scanning a little area */ if (Refs_Detect (dev, Regs, refcfg.resolution, refcfg.resolution, &x, &y) == OK) Refs_Save (dev, x, y); else rst = ERROR; Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); break; case REF_TAKEFROMSCANNER: /* Try to get values from scanner */ if (Refs_Load (dev, &x, &y) == ERROR) { if (Refs_Detect (dev, Regs, refcfg.resolution, refcfg.resolution, &x, &y) == OK) Refs_Save (dev, x, y); else rst = ERROR; Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); } break; } if (rst == OK) { /* values are based on resolution given by refcfg.resolution. offset_x and y are based on 2400 dpi so convert values to that dpi before adding offsets and then return to resolution given by user */ x *= (2400 / refcfg.resolution); y *= (2400 / refcfg.resolution); scan.leftleading = x; scan.startpos = y; scan.ser = ((x + refcfg.offset_x) * scancfg->resolution_x) / 2400; scan.ler = ((y + refcfg.offset_y) * scancfg->resolution_y) / 2400; DBG (DBG_FNC, " -> After SEROffset and LEROffset, xoffset = %i, yoffset =%i\n", scan.ser, scan.ler); } /* increase refs counter */ Refs_Counter_Inc (dev); } DBG (DBG_FNC, "- Refs_Set: %i\n", rst); return rst; } static SANE_Int Lamp_Status_Set (struct st_device *dev, SANE_Byte * Regs, SANE_Int turn_on, SANE_Int lamp) { SANE_Int rst = ERROR; /* default */ SANE_Byte freevar = FALSE; DBG (DBG_FNC, "+ Lamp_Status_Set(*Regs, turn_on=%i->%s, lamp=%s)\n", turn_on, ((((lamp - 1) | turn_on) & 1) == 1) ? "Yes" : "No", (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP"); if (Regs == NULL) { Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) freevar = TRUE; } if (Regs != NULL) { RTS_ReadRegs (dev->usb_handle, Regs); /* next op depends on chipset */ switch (dev->chipset->model) { case RTS8822BL_03A: /* register 0xe946 has 2 bits and each one referres one lamp 0x40: FLB_LAMP | 0x20 : TMA_LAMP if both were enabled both lamps would be switched on */ data_bitset (&Regs[0x146], 0x20, ((lamp == TMA_LAMP) && (turn_on == TRUE)) ? 1 : 0); /* TMA */ data_bitset (&Regs[0x146], 0x40, ((lamp == FLB_LAMP) && (turn_on == TRUE)) ? 1 : 0); /* FLB */ data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0); break; default: /* the other chipsets only use one bit to indicate when a lamp is switched on or not being bit 0x10 in 0xe955 who decides which lamp is affected */ /* switch on lamp? yes if TMA_LAMP, else whatever turn_on says */ data_bitset (&Regs[0x146], 0x40, ((lamp - 1) | turn_on)); /* what lamp must be switched on? */ if ((Regs[0x146] & 0x40) != 0) data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0); break; } /*42b8cd1 */ /* switch on/off lamp */ /*dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0xbf) | (Regs[0x146] & 0x40); */ dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0x9f) | (Regs[0x146] & 0x60); /*-xx-----*/ /* Which lamp */ dev->init_regs[0x0155] = Regs[0x0155]; Write_Byte (dev->usb_handle, 0xe946, Regs[0x0146]); usleep (1000 * 200); Write_Buffer (dev->usb_handle, 0xe954, &Regs[0x0154], 2); } if (freevar != FALSE) { free (Regs); Regs = NULL; } DBG (DBG_FNC, "- Lamp_Status_Set: %i\n", rst); return rst; } static SANE_Int Get_PAG_Value (SANE_Byte scantype, SANE_Byte color) { SANE_Int rst, iType, iColor; switch (scantype) { case ST_NEG: iType = CALIBNEGATIVEFILM; break; case ST_TA: iType = CALIBTRANSPARENT; break; case ST_NORMAL: iType = CALIBREFLECTIVE; break; default: iType = CALIBREFLECTIVE; break; } switch (color) { case CL_BLUE: iColor = PAGB; break; case CL_GREEN: iColor = PAGG; break; case CL_RED: iColor = PAGR; break; default: iColor = PAGR; break; } rst = get_value (iType, iColor, 1, FITCALIBRATE); DBG (DBG_FNC, "> Get_PAG_Value(scantype=%s, color=%i): %i\n", dbg_scantype (scantype), color, rst); return rst; } static SANE_Byte Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution, SANE_Byte scantype) { SANE_Byte ret; SANE_Int mygain, iValue; switch (scantype) { case ST_TA: ret = 0; iValue = DPIGAINCONTROL_TA600; break; case ST_NEG: ret = 1; iValue = DPIGAINCONTROL_NEG600; break; default: /* Reflective */ ret = 1; iValue = DPIGAINCONTROL600; break; } mygain = get_value (SCAN_PARAM, iValue, ret, usbfile); ret = 0; /* */ if (scantype == ST_NORMAL) { if (dev->chipset->model == RTS8822L_02A) { switch (resolution) { case 100: case 150: case 300: case 600: case 1200: case 2400: case 4800: ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; break; } } else { switch (resolution) { case 100: case 200: case 300: case 600: if (RTS_Debug->usbtype != USB11) ret = (mygain != 0) ? 1 : 0; else ret = (resolution == 100) ? 1 : 0; break; case 1200: case 2400: ret = 0; break; } } } else if (scantype == ST_TA) { switch (resolution) { /*hp3970 */ case 100: case 200: /*common */ case 300: case 600: case 1200: case 2400: /*hp4370 */ case 150: case 4800: ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; break; } } else { /* ST_NEG */ switch (resolution) { case 100: case 200: case 300: case 600: ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; break; case 1200: case 2400: case 4800: /*hp4370 */ ret = 0; break; } } DBG (DBG_FNC, "> Lamp_GetGainMode(resolution=%i, scantype=%s): %i\n", resolution, dbg_scantype (scantype), ret); return ret; } static SANE_Int GetOneLineInfo (struct st_device *dev, SANE_Int resolution, SANE_Int * maximus, SANE_Int * minimus, double *average) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ GetOneLineInfo(resolution=%i, *maximus, *minimus, *average):\n", resolution); /* Check parameters */ if ((maximus != NULL) && (minimus != NULL) && (average != NULL)) { SANE_Byte *Regs, *image; SANE_Int a, gainmode; struct st_gain_offset gain_offset; struct st_scanparams scancfg; Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { /* Copy scanner registers */ memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); /* Setting some registers */ for (a = 0x192; a <= 0x19d; a++) Regs[a] = 0; /* Create calibration table */ for (a = CL_RED; a <= CL_BLUE; a++) { gain_offset.edcg1[a] = 256; gain_offset.edcg2[a] = 0; gain_offset.odcg1[a] = 256; gain_offset.odcg2[a] = 0; gain_offset.vgag1[a] = 4; gain_offset.vgag2[a] = 4; gain_offset.pag[a] = Get_PAG_Value (scan.scantype, a); } RTS_GetScanmode (dev, scantype, 0, resolution); /* Setting scanning params */ memset (&scancfg, 0, sizeof (struct st_scanparams)); scancfg.colormode = CM_COLOR; scancfg.resolution_x = resolution; scancfg.resolution_y = resolution; scancfg.coord.left = 100; scancfg.coord.width = (resolution * 8.5) - 100; scancfg.coord.top = 1; scancfg.coord.height = 1; scancfg.depth = 8; scancfg.shadinglength = resolution * 8.5; scancfg.v157c = scancfg.coord.width * 3; scancfg.bytesperline = scancfg.v157c; /* Reserve buffer for line */ image = (SANE_Byte *) malloc (((scancfg.coord.width * 0x21) * 3) * sizeof (SANE_Byte)); if (image != NULL) { gainmode = Lamp_GetGainMode (dev, resolution & 0xffff, scan.scantype); if (RTS_GetImage (dev, Regs, &scancfg, &gain_offset, image, 0, OP_STATIC_HEAD, gainmode) != ERROR) { /* Read all image to take max min and average colours */ SANE_Byte *pointer1 = image; SANE_Byte *pointer2; SANE_Byte *pointer3; SANE_Int cmin[3]; /* min values */ SANE_Int cmax[3]; /* max values */ double cave[3]; /* average values */ SANE_Int mysize; if (scancfg.colormode != CM_GRAY) { pointer2 = image; pointer3 = image; } else { pointer2 = image + 1; pointer3 = image + 2; } for (a = CL_RED; a <= CL_BLUE; a++) { cmin[a] = 255; cmax[a] = 0; cave[a] = 0; } if (scancfg.coord.height > 0) { SANE_Int y, x; SANE_Byte *mypointer; SANE_Byte color; SANE_Int desp[3]; desp[CL_RED] = pointer1 - pointer3; desp[CL_GREEN] = pointer2 - pointer3; desp[CL_BLUE] = 0; for (y = 0; y < scancfg.coord.height; y++) { if (scancfg.coord.width > 0) { mypointer = pointer3; for (x = 0; x < scancfg.coord.width; x++) { for (a = CL_RED; a <= CL_BLUE; a++) { /* Take colour values */ color = *(mypointer + desp[a]); /* Take max values for each color */ cmax[a] = max (cmax[a], color); /* Take min values for each color */ cmin[a] = min (cmin[a], color); /* Average */ cave[a] += color; } mypointer += 3; } } /* point to the pixel that is below */ pointer1 += scancfg.coord.width * 3; pointer2 += scancfg.coord.width * 3; pointer3 += scancfg.coord.width * 3; } } mysize = scancfg.coord.height * scancfg.coord.width; if (mysize < 1) mysize = 1; for (a = CL_RED; a <= CL_BLUE; a++) { maximus[a] = cmax[a]; minimus[a] = cmin[a]; average[a] = cave[a] / mysize; } DBG (DBG_FNC, " -> GetOneLineInfo: max r=%3i g=%3i b=%3i\n", maximus[CL_RED], maximus[CL_GREEN], maximus[CL_BLUE]); DBG (DBG_FNC, " -> min r=%3i g=%3i b=%3i\n", minimus[CL_RED], minimus[CL_GREEN], minimus[CL_BLUE]); DBG (DBG_FNC, " -> avg r=%3.0f g=%3.0f b=%3.0f\n", average[CL_RED], average[CL_GREEN], average[CL_BLUE]); rst = OK; } free (image); } free (Regs); } } DBG (DBG_FNC, "- GetOneLineInfo: %i\n", rst); return OK; } static SANE_Int Lamp_PWM_CheckStable (struct st_device *dev, SANE_Int resolution, SANE_Int lamp) { struct st_checkstable check; SANE_Int rst; DBG (DBG_FNC, "+ Lamp_PWM_CheckStable(resolution=%i, lamp=%i):\n", resolution, lamp); rst = cfg_checkstable_get (lamp, &check); if (rst == OK) { SANE_Int maximus[3] = { 0 }; SANE_Int minimus[3] = { 0 }; double average[3] = { 0 }; SANE_Int maxbigger; SANE_Int last_colour = 0; double diff = check.diff * 0.01; long tottime = GetTickCount () + check.tottime; while (GetTickCount () <= tottime) { rst = GetOneLineInfo (dev, resolution, maximus, minimus, average); if (rst == OK) { /* Takes maximal colour value */ maxbigger = max (maximus[CL_GREEN], max (maximus[CL_BLUE], maximus[CL_RED])); /*breaks when colour intensity increases 'diff' or lower */ if (abs (maxbigger - last_colour) < diff) { DBG (DBG_FNC, " -> PWM is ready\n"); break; } last_colour = maxbigger; } usleep (1000 * check.interval); } } DBG (DBG_FNC, "- Lamp_PWM_CheckStable: %i\n", rst); return OK; } static SANE_Byte Refs_Counter_Load (struct st_device *dev) { SANE_Byte data = 15; DBG (DBG_FNC, "+ Refs_Counter_Load:\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x78, &data) != OK) data = 15; DBG (DBG_FNC, "- Refs_Counter_Load: %i\n", _B0 (data)); return data; } static SANE_Int Refs_Counter_Save (struct st_device *dev, SANE_Byte data) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Refs_Counter_Save(data=%i):\n", data); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { if (data > 15) data = 15; rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x78, data); } DBG (DBG_FNC, "- Refs_Counter_Save: %i\n", rst); return rst; } static SANE_Int Refs_Counter_Inc (struct st_device *dev) { SANE_Byte data; DBG (DBG_FNC, "+ Refs_Counter_Inc:\n"); data = Refs_Counter_Load (dev) + 1; if (data >= 15) data = 0; Refs_Counter_Save (dev, data); DBG (DBG_FNC, "- Refs_Counter_Inc() : Count=%i\n", data); return OK; } static SANE_Int Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, SANE_Int * xpos) { SANE_Int iType; switch (scantype) { case 3: iType = CALIBNEGATIVEFILM; break; case 2: iType = CALIBTRANSPARENT; break; default: iType = CALIBREFLECTIVE; break; } *xpos = get_value (iType, WSTRIPXPOS, 0, FITCALIBRATE); *ypos = get_value (iType, WSTRIPYPOS, 0, FITCALIBRATE); DBG (DBG_FNC, "> Load_StripCoords(scantype=%s): ypos=%i, xpos=%i\n", dbg_scantype (scantype), *ypos, *xpos); return OK; } static SANE_Int Head_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction, SANE_Int ypos) { SANE_Int rst; SANE_Byte *Regs; DBG (DBG_FNC, "+ Head_Relocate(speed=%i, direction=%i, ypos=%i):\n", speed, direction, ypos); rst = ERROR; Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { struct st_motormove mymotor; struct st_motorpos mtrpos; bzero (&mymotor, sizeof (struct st_motormove)); memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); if (speed < dev->motormove_count) memcpy (&mymotor, dev->motormove[speed], sizeof (struct st_motormove)); /*83fe */ mtrpos.coord_y = ypos; mtrpos.options = MTR_ENABLED | ((direction == MTR_BACKWARD) ? MTR_BACKWARD : MTR_FORWARD); mtrpos.v12e448 = 0; mtrpos.v12e44c = 1; Motor_Move (dev, Regs, &mymotor, &mtrpos); /* waits 15 seconds */ RTS_WaitScanEnd (dev, 15000); free (Regs); rst = OK; } DBG (DBG_FNC, "- Head_Relocate: %i\n", rst); return rst; } static SANE_Int Calib_CreateFixedBuffers () { SANE_Byte channel; SANE_Int ret; DBG (DBG_FNC, "> Calib_CreateFixedBuffers()\n"); ret = OK; channel = 0; while ((channel < 3) && (ret == OK)) { /* First table */ if (fixed_black_shading[channel] == NULL) fixed_black_shading[channel] = (USHORT *) malloc (0x7f8 * sizeof (USHORT)); if (fixed_black_shading[channel] != NULL) bzero (fixed_black_shading[channel], 0x7f8 * sizeof (USHORT)); else ret = ERROR; /* Second table */ if (fixed_white_shading[channel] == NULL) fixed_white_shading[channel] = (USHORT *) malloc (0x7f8 * sizeof (USHORT)); if (fixed_white_shading[channel] != NULL) bzero (fixed_white_shading[channel], 0x7f8 * sizeof (USHORT)); else ret = ERROR; channel++; } return ret; } static SANE_Int Calib_CreateBuffers (struct st_device *dev, struct st_calibration *buffer, SANE_Int my14b4) { SANE_Int ebp, ret, channel; ret = ERROR; dev = dev; buffer->shadinglength = scan.coord.width; ebp = 0x14; if (my14b4 != 0) { /* 673d */ if (Calib_CreateFixedBuffers () == OK) { for (channel = 0; channel < 3; channel++) { buffer->white_shading[channel] = fixed_white_shading[channel]; buffer->black_shading[channel] = fixed_black_shading[channel]; } ret = OK; } } else { /* 677f */ SANE_Int pos; channel = 0; while ((channel < 3) && (ret == OK)) { buffer->black_shading[channel] = (USHORT *) malloc (ebp + (buffer->shadinglength * sizeof (USHORT))); buffer->white_shading[channel] = (USHORT *) malloc (ebp + (buffer->shadinglength * sizeof (USHORT))); if ((buffer->black_shading[channel] != NULL) && (buffer->white_shading[channel] != NULL)) { for (pos = 0; pos < buffer->shadinglength; pos++) { buffer->black_shading[channel][pos] = 0x00; buffer->white_shading[channel][pos] = 0x4000; } ret = OK; } else Calib_FreeBuffers (buffer); channel++; } } DBG (DBG_FNC, "> Calib_CreateBuffers: *buffer, my14b4=%i): %i\n", my14b4, ret); return ret; } static void Calib_FreeBuffers (struct st_calibration *caltables) { DBG (DBG_FNC, "> Calib_FreeBuffers(*caltables)\n"); if (caltables != NULL) { SANE_Int channel; for (channel = 0; channel < 3; channel++) { if (caltables->black_shading[channel] != NULL) { free (caltables->black_shading[channel]); caltables->black_shading[channel] = NULL; } if (caltables->white_shading[channel] != NULL) { free (caltables->white_shading[channel]); caltables->white_shading[channel] = NULL; } } } } static SANE_Int Calib_LoadConfig (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int scantype, SANE_Int resolution, SANE_Int bitmode) { SANE_Int section, a; struct st_autoref refcfg; DBG (DBG_FNC, "> Calib_LoadConfig(*calibcfg, scantype=%s, resolution=%i, bitmode=%i)\n", dbg_scantype (scantype), resolution, bitmode); switch (scantype) { case ST_NEG: section = CALIBNEGATIVEFILM; break; case ST_TA: section = CALIBTRANSPARENT; break; default: section = CALIBREFLECTIVE; break; } calibcfg->WStripXPos = get_value (section, WSTRIPXPOS, 0, FITCALIBRATE); calibcfg->WStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE); calibcfg->BStripXPos = get_value (section, BSTRIPXPOS, 0, FITCALIBRATE); calibcfg->BStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE); /* get calibration wrefs */ cfg_wrefs_get (dev->sensorcfg->type, bitmode, resolution, scantype, &calibcfg->WRef[CL_RED], &calibcfg->WRef[CL_GREEN], &calibcfg->WRef[CL_BLUE]); /* 4913 */ for (a = CL_RED; a <= CL_BLUE; a++) { WRef[a] = _B0 (calibcfg->WRef[a]); calibcfg->BRef[a] = get_value (section, BREFR + a, 10, FITCALIBRATE); calibcfg->OffsetEven1[a] = get_value (section, OFFSETEVEN1R + a, 256, FITCALIBRATE); calibcfg->OffsetEven2[a] = get_value (section, OFFSETEVEN2R + a, 0, FITCALIBRATE); calibcfg->OffsetOdd1[a] = get_value (section, OFFSETODD1R + a, 256, FITCALIBRATE); calibcfg->OffsetOdd2[a] = get_value (section, OFFSETODD2R + a, 0, FITCALIBRATE); } calibcfg->RefBitDepth = _B0 (get_value (section, REFBITDEPTH, 8, FITCALIBRATE)); calibcfg->CalibOffset10n = _B0 (get_value (section, CALIBOFFSET10N, 3, FITCALIBRATE)); calibcfg->CalibOffset20n = _B0 (get_value (section, CALIBOFFSET20N, 0, FITCALIBRATE)); calibcfg->OffsetHeight = get_value (section, OFFSETHEIGHT, 10, FITCALIBRATE); /* 4ae9 */ /* get left coordinate and length to calibrate offset */ cfg_offset_get (dev->sensorcfg->type, resolution, scantype, &calibcfg->OffsetPixelStart, &calibcfg->OffsetNPixel); /*4c49 */ calibcfg->OffsetNSigma = get_value (section, OFFSETNSIGMA, 2, FITCALIBRATE); calibcfg->OffsetTargetMax = get_value (section, OFFSETTARGETMAX, 0x32, FITCALIBRATE) * 0.01; calibcfg->OffsetTargetMin = get_value (section, OFFSETTARGETMIN, 2, FITCALIBRATE) * 0.01; calibcfg->OffsetBoundaryRatio1 = get_value (section, OFFSETBOUNDARYRATIO1, 0x64, FITCALIBRATE) * 0.01; calibcfg->OffsetBoundaryRatio2 = get_value (section, OFFSETBOUNDARYRATIO2, 0x64, FITCALIBRATE) * 0.01; calibcfg->OffsetAvgRatio1 = get_value (section, OFFSETAVGRATIO1, 0x64, FITCALIBRATE) * 0.01; calibcfg->OffsetAvgRatio2 = get_value (section, OFFSETAVGRATIO2, 0x64, FITCALIBRATE) * 0.01; calibcfg->AdcOffQuickWay = get_value (section, ADCOFFQUICKWAY, 1, FITCALIBRATE); calibcfg->AdcOffPredictStart = get_value (section, ADCOFFPREDICTSTART, 0xc8, FITCALIBRATE); calibcfg->AdcOffPredictEnd = get_value (section, ADCOFFPREDICTEND, 0x1f4, FITCALIBRATE); calibcfg->AdcOffEvenOdd = get_value (section, ADCOFFEVENODD, 1, FITCALIBRATE); calibcfg->OffsetTuneStep1 = _B0 (get_value (section, OFFSETTUNESTEP1, 1, FITCALIBRATE)); calibcfg->OffsetTuneStep2 = _B0 (get_value (section, OFFSETTUNESTEP2, 1, FITCALIBRATE)); calibcfg->CalibGain10n = get_value (section, CALIBGAIN10N, 1, FITCALIBRATE); calibcfg->CalibGain20n = get_value (section, CALIBGAIN20N, 0, FITCALIBRATE); calibcfg->CalibPAGOn = get_value (section, CALIBPAGON, 0, FITCALIBRATE); for (a = CL_RED; a <= CL_BLUE; a++) { calibcfg->OffsetAvgTarget[a] = _B0 (get_value (section, OFFSETAVGTARGETR + a, 0x0d, FITCALIBRATE)); calibcfg->PAG[a] = get_value (section, PAGR + a, 3, FITCALIBRATE); calibcfg->Gain1[a] = get_value (section, GAIN1R + a, 4, FITCALIBRATE); calibcfg->Gain2[a] = get_value (section, GAIN2R + a, 4, FITCALIBRATE); calibcfg->WShadingPreDiff[a] = get_value (section, WSHADINGPREDIFFR + a, -1, FITCALIBRATE); calibcfg->BShadingPreDiff[a] = get_value (section, BSHADINGPREDIFFR + a, 2, FITCALIBRATE); } calibcfg->GainHeight = get_value (section, GAINHEIGHT, 0x1e, FITCALIBRATE); calibcfg->GainTargetFactor = get_value (section, GAINTARGETFACTOR, 0x5a, FITCALIBRATE) * 0.01; calibcfg->TotShading = get_value (section, TOTSHADING, 0, FITCALIBRATE); /* White shading */ calibcfg->WShadingOn = get_value (section, WSHADINGON, 3, FITCALIBRATE); calibcfg->WShadingHeight = get_value (section, WSHADINGHEIGHT, 0x18, FITCALIBRATE); /* Black shading */ calibcfg->BShadingOn = get_value (section, BSHADINGON, 2, FITCALIBRATE); calibcfg->BShadingHeight = get_value (section, BSHADINGHEIGHT, 0x1e, FITCALIBRATE); calibcfg->BShadingDefCutOff = get_value (section, BSHADINGDEFCUTOFF, 0, FITCALIBRATE); refcfg.extern_boundary = 0; cfg_autoref_get (&refcfg); calibcfg->ExternBoundary = refcfg.extern_boundary * 0.01; calibcfg->EffectivePixel = cfg_effectivepixel_get (dev->sensorcfg->type, resolution); return OK; } static SANE_Int Calib_AdcGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int arg2, SANE_Int gaincontrol) { /* 0606F8E0 04F60738 |Arg1 = 04F60738 0606F8E4 0606F90C |Arg2 = 0606F90C calibcfg 0606F8E8 00000001 |Arg3 = 00000001 arg2 0606F8EC 00000001 \Arg4 = 00000001 gaincontrol */ SANE_Int rst = ERROR; SANE_Byte *myRegs; /*f1c0 */ DBG (DBG_FNC, "+ Calib_AdcGain(*calibcfg, arg2=%i, gaincontrol=%i)\n", arg2, gaincontrol); myRegs = (SANE_Byte *) malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN); if (myRegs != NULL) { struct st_scanparams *scancfg; /*f17c */ SANE_Int bytes_per_line, bytes_to_next_colour, bytes_per_pixel; /* get register values to perform adc gain calibration */ memcpy (myRegs, &calibdata->Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); scancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); if (scancfg != NULL) { SANE_Byte *image, *pgain, *pcalgain; /* get proper scan configuration */ memcpy (scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); /* set gain control type */ Lamp_SetGainMode (dev, myRegs, scancfg->resolution_x, gaincontrol); /* 8-bit depth */ scancfg->depth = 8; /* set coordinates */ if ((scan.scantype > 0) && (scan.scantype < 4)) scancfg->coord.left += scan.ser; if ((scancfg->coord.width & 1) == 0) scancfg->coord.width++; scancfg->coord.top = 1; scancfg->coord.height = calibcfg->OffsetHeight; /* three more values to read image data after getting image from scanner */ switch (scancfg->colormode) { case CM_GRAY: case CM_LINEART: bytes_to_next_colour = 0; bytes_per_pixel = 1; bytes_per_line = scancfg->coord.width; break; default: /* CM_COLOR */ /* c027 */ bytes_to_next_colour = 1; bytes_per_line = scancfg->coord.width * 3; if (scancfg->samplerate == LINE_RATE) { bytes_to_next_colour = scancfg->coord.width; bytes_per_pixel = 1; } else bytes_per_pixel = 3; break; } /*7fc7 */ scancfg->v157c = bytes_per_line; scancfg->bytesperline = bytes_per_line; /* select type of gain parameters to set */ if (arg2 != 0) { pgain = calibdata->gain_offset.vgag1; pcalgain = calibcfg->Gain1; } else { /*7ff2 */ pgain = calibdata->gain_offset.vgag2; pcalgain = calibcfg->Gain2; } /*8002 */ /* Allocate space for image | size = 132912 */ image = (SANE_Byte *) malloc (sizeof (SANE_Byte) * ((scancfg->coord.height + 16) * bytes_per_line)); if (image != NULL) { /* Lets read image */ if (RTS_GetImage (dev, myRegs, scancfg, &calibdata->gain_offset, image, NULL, OP_STATIC_HEAD, gaincontrol) == OK) { SANE_Int a; SANE_Int vmin[3], vmax[3]; double dval[3] = { 0.0 }; /*f1a8 f1b0 f1b8 */ SANE_Byte *pimage = image; /* initialize values */ for (a = CL_RED; a <= CL_BLUE; a++) { calibcfg->unk1[a] = 0; calibcfg->unk2[a] = 0xff; vmin[a] = 0xff; vmax[a] = 0; } /* process image data */ if (scancfg->coord.width > 0) { /*8104 */ SANE_Int pos, myheight /*f164 */ ; SANE_Int chn_sum[3]; for (pos = scancfg->coord.width; pos > 0; pos--) { chn_sum[CL_RED] = chn_sum[CL_GREEN] = chn_sum[CL_BLUE] = 0; if (scancfg->coord.height > 0) for (myheight = 0; myheight < scancfg->coord.height; myheight++) for (a = CL_RED; a <= CL_BLUE; a++) chn_sum[a] += *(pimage + (bytes_per_line * myheight) + (bytes_to_next_colour * a)); /*816e */ for (a = CL_RED; a <= CL_BLUE; a++) { vmin[a] = min (vmin[a], chn_sum[a] / scancfg->coord.height); vmax[a] = max (vmax[a], chn_sum[a] / scancfg->coord.height); calibcfg->unk1[a] = max (calibcfg->unk1[a], vmax[a]); calibcfg->unk2[a] = min (calibcfg->unk1[a], vmin[a]); dval[a] += vmax[a] & 0xffff; } pimage += bytes_per_pixel; } } /*82b0 */ dval[CL_RED] /= scancfg->coord.width; dval[CL_GREEN] /= scancfg->coord.width; dval[CL_BLUE] /= scancfg->coord.width; DBG (DBG_FNC, " -> adcgain (av/l): r=%f, g=%f, b=%f\n", dval[CL_RED], dval[CL_GREEN], dval[CL_BLUE]); DBG (DBG_FNC, " -> (max ): R=%i, G=%i, B=%i\n", calibcfg->unk1[CL_RED], calibcfg->unk1[CL_GREEN], calibcfg->unk1[CL_BLUE]); DBG (DBG_FNC, " -> (min ): r=%i, g=%i, b=%i\n", calibcfg->unk2[CL_RED], calibcfg->unk2[CL_GREEN], calibcfg->unk2[CL_BLUE]); if (scancfg->colormode == CM_COLOR) { /*8353 */ double dvalue; SANE_Int ival; for (a = CL_RED; a <= CL_BLUE; a++) { dvalue = ((((calibcfg->WRef[a] * (1 << scancfg->depth)) * calibcfg->GainTargetFactor) * 0.00390625) / dval[a]) * ((44 - pgain[a]) / 40); if (dvalue > 0.9090909090909091) { /*83d7 */ dvalue = min (44 - (40 / dvalue), 31); ival = dvalue; pgain[a] = _B0 (ival); pcalgain[a] = _B0 (ival); } else { pgain[a] = 0; pcalgain[a] = 0; } } } else { /*843c */ /*falta codigo */ double dvalue; SANE_Int ival; dvalue = ((44 - pgain[CL_RED]) / 40) * ((((1 << scancfg->depth) * calibcfg->WRef[scancfg-> channel]) * 0.9) * 0.00390625) / 17.08509389671362; for (a = CL_RED; a <= CL_BLUE; a++) { if (dvalue > 0.9090909090909091) { dvalue = min (44 - (40 / dvalue), 31); ival = dvalue; pgain[a] = _B0 (ival); pcalgain[a] = _B0 (ival); } else { /*84e3 */ pgain[a] = 0; pcalgain[a] = 0; } } } /*84fa */ /* Save buffer */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("adcgain.tiff", scancfg->coord.width, scancfg->coord.height, scancfg->depth, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, image, (scancfg->coord.height + 16) * bytes_per_line); } /* check if peak values are above offset average target + 5 */ for (a = CL_RED; a <= CL_BLUE; a++) if (calibcfg->unk1[a] >= calibcfg->OffsetAvgTarget[a] + 5) { rst = OK; break; } } free (image); } free (scancfg); } free (myRegs); } /* v14b8 = (rst == OK)? 0: 1; */ /* show */ dbg_calibtable (&calibdata->gain_offset); DBG (DBG_FNC, "- Calib_AdcGain: %i\n", rst); return rst; } static SANE_Int GainOffset_Save (struct st_device *dev, SANE_Int * offset, SANE_Byte * gain) { SANE_Int rst = OK; DBG (DBG_FNC, "+ GainOffset_Save(*offset, *gain):\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { if ((offset != NULL) && (gain != NULL)) { SANE_Int a, crc, value; crc = 0x5B; for (a = CL_RED; a <= CL_BLUE; a++) { value = (*gain << 9) | *offset; crc = _B0 (abs (crc - _B0 (value))); rst = RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (a * 2), value); } if (rst == OK) rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, crc); } else rst = ERROR; } DBG (DBG_FNC, "- GainOffset_Save: %i\n", rst); return rst; } static SANE_Int Calib_PAGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int gainmode) { SANE_Byte *Regs; struct st_scanparams *scancfg; SANE_Int channel_size; SANE_Int bytes_to_next_colour = 0; SANE_Int bytes_per_pixel = 0; SANE_Int length = 0; SANE_Byte *image; double rst; SANE_Int ret = ERROR; DBG (DBG_FNC, "+ Calib_PAGain(*calibcfg, gainmode=%i)\n", gainmode); Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { scancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); if (scancfg != NULL) { memcpy (Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); if (scan.scantype == ST_NORMAL) { /* bfa5 */ scancfg->coord.left = scan.ser; scancfg->coord.width = (scancfg->sensorresolution * 17) / 2; } else { scancfg->coord.left = scan.ser + v0750; scancfg->coord.width = (scancfg->sensorresolution * 3) / 2; } /* bfca */ if ((scancfg->coord.width & 1) == 1) scancfg->coord.width++; scancfg->coord.top = 1; scancfg->coord.height = calibcfg->OffsetHeight; channel_size = (scancfg->depth > 8) ? 2 : 1; switch (scancfg->colormode) { case CM_GRAY: case CM_LINEART: bytes_to_next_colour = 0; bytes_per_pixel = 1; length = channel_size * scancfg->coord.width; break; default: /* CM_COLOR */ /* c027 */ bytes_to_next_colour = 1; length = (channel_size * scancfg->coord.width) * 3; if (scancfg->samplerate == LINE_RATE) { bytes_to_next_colour = scancfg->coord.width; bytes_per_pixel = 1; } else bytes_per_pixel = 3; break; } /* c070 */ scancfg->v157c = length; image = (SANE_Byte *) malloc ((scancfg->coord.height * length) * sizeof (SANE_Byte)); if (image != NULL) { ret = RTS_GetImage (dev, Regs, scancfg, &calibdata->gain_offset, image, 0, OP_STATIC_HEAD, gainmode); if (ret == OK) { /* 429c105 */ SANE_Int a; SANE_Byte *ptr[3]; SANE_Int vmin[3] = { 255, 255, 255 }; /* f16c|f16e|f170 */ SANE_Int vmax[3] = { 0, 0, 0 }; /* f164|f166|f168 */ SANE_Int total[3]; ptr[CL_RED] = image; ptr[CL_GREEN] = image + bytes_to_next_colour; ptr[CL_BLUE] = image + (bytes_to_next_colour * 2); if (scancfg->coord.width > 0) { SANE_Int pos, b; for (pos = 0; pos < scancfg->coord.width; pos++) { total[CL_BLUE] = 0; total[CL_GREEN] = 0; total[CL_RED] = 0; for (a = 0; a < scancfg->coord.height; a++) { for (b = CL_RED; b <= CL_BLUE; b++) total[b] += *(ptr[b] + ((scancfg->coord.height - a) * length)); } /* c1a5 */ for (a = CL_RED; a <= CL_BLUE; a++) { total[a] /= scancfg->coord.height; vmin[a] = min (vmin[a], total[a]); vmax[a] = max (vmax[a], total[a]); ptr[a] += bytes_per_pixel; } } } /* 429c234 */ for (a = CL_RED; a <= CL_BLUE; a++) { rst = (calibcfg->WRef[a] * calibcfg->GainTargetFactor) / vmax[a]; if (rst <= 1.5) { if (rst <= 1.286) { if (rst <= 1.125) calibdata->gain_offset.pag[a] = 0; else calibdata->gain_offset.pag[a] = 1; } else calibdata->gain_offset.pag[a] = 2; } else calibdata->gain_offset.pag[a] = 3; } } free (image); } free (scancfg); } free (Regs); } DBG (DBG_FNC, "- Calib_PAGain: %i\n", ret); return ret; } static SANE_Int Chipset_ID (struct st_device *dev) { SANE_Int ret; if (Read_Word (dev->usb_handle, 0xfe3c, &ret) == OK) ret = _B0 (ret); else ret = 0; DBG (DBG_FNC, "> Chipset_ID(): %i\n", ret); return ret; } static SANE_Int Chipset_Name (struct st_device *dev, char *name, SANE_Int size) { SANE_Int rst = ERROR; if (name != NULL) { strncpy (name, dev->chipset->name, size); rst = OK; } return rst; } static SANE_Int Refs_Load (struct st_device *dev, SANE_Int * x, SANE_Int * y) { SANE_Int ret = OK; DBG (DBG_FNC, "+ Refs_Load:\n"); *y = *x = 0; /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { SANE_Int data; ret = ERROR; if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6a, &data) == OK) { *x = data; if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6c, &data) == OK) { *y = data; if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6e, &data) == OK) { if ((_B0 (*y + *x + data)) == 0x5a) ret = OK; } } } } DBG (DBG_FNC, "- Refs_Load(y=%i, x=%i) : %i\n", *y, *x, ret); return ret; } static SANE_Int Refs_Save (struct st_device *dev, SANE_Int left_leading, SANE_Int start_pos) { SANE_Int ret = OK; DBG (DBG_FNC, "+ Refs_Save(left_leading=%i, start_pos=%i)\n", left_leading, start_pos); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { ret = ERROR; if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6a, left_leading) == OK) { if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6c, start_pos) == OK) { SANE_Byte data = _B0 (0x5a - (start_pos + left_leading)); ret = RTS_EEPROM_WriteByte (dev->usb_handle, 0x6e, data); } } } DBG (DBG_FNC, "- Refs_Save: %i\n", ret); return ret; } static SANE_Int Calib_AdcOffsetRT (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int value) { /* 05EFF8E4 04F10738 |Arg1 = 04F10738 05EFF8E8 05EFF90C |Arg2 = 05EFF90C calibcfg 05EFF8EC 00000001 \Arg3 = 00000001 value */ SANE_Byte Regs[RT_BUFFER_LEN]; /*f1c4 */ SANE_Int channels_per_dot; /*f108 */ struct st_scanparams scancfg; /*f18c */ SANE_Int *pedcg; /*f114 */ SANE_Int *podcg; /*f118 */ SANE_Int *poffseteven; /*f130 */ SANE_Int *poffsetodd; /*f128 */ SANE_Int channel; SANE_Int avgtarget[3]; /*f1b8 f1bc f1c0 */ SANE_Byte *scanbuffer; /*f0f8 */ SANE_Int scan_options; /*f12c */ SANE_Int highresolution; /*f144 */ double dbValues[3] = { 0, 0, 0 }; /*f148 f14c f150 */ SANE_Int do_loop; /*f0ec */ SANE_Int gainmode; SANE_Byte *ptr; /*f0f4 */ SANE_Byte *mvgag; /*f0e4 *//*f10c */ USHORT wvalues[9]; /*0856 0858 085a 085c 085e 0860 0862 0864 0866 */ SANE_Int imgcount = 0; /* myoffsetnpixel = f120 */ /* desp f0e8 & f140 */ DBG (DBG_FNC, "+ Calib_AdcOffsetRT(*calibcfg, value=%i)\n", value); memcpy (&Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); channels_per_dot = (calibdata->scancfg.colormode == CM_COLOR) ? 3 : 1; if (value != 0) { pedcg = &calibdata->gain_offset.edcg1[CL_RED]; podcg = &calibdata->gain_offset.odcg1[CL_RED]; poffseteven = &calibcfg->OffsetEven1[CL_RED]; poffsetodd = &calibcfg->OffsetOdd1[CL_RED]; } else { /*c37c */ pedcg = &calibdata->gain_offset.edcg2[CL_RED]; podcg = &calibdata->gain_offset.odcg2[CL_RED]; poffseteven = &calibcfg->OffsetEven2[CL_RED]; poffsetodd = &calibcfg->OffsetOdd2[CL_RED]; } /*c3a4 */ scancfg.coord.left = calibcfg->OffsetPixelStart; if (channels_per_dot > 0) { for (channel = 0; channel < channels_per_dot; channel++) { avgtarget[channel] = calibcfg->OffsetAvgTarget[channel] << 8; if (avgtarget[channel] == 0) avgtarget[channel] = 0x80; } } /* set image coordinates to scan */ scancfg.coord.width = calibcfg->OffsetNPixel; if ((scancfg.coord.width & 1) == 0) scancfg.coord.width++; scancfg.bytesperline = channels_per_dot * scancfg.coord.width; scancfg.coord.top = 1; scancfg.coord.height = calibcfg->OffsetHeight; scancfg.depth = 8; /* allocate memory to store image */ scanbuffer = (SANE_Byte *) malloc ((scancfg.bytesperline * calibcfg->OffsetHeight) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /*42ac477 */ scan_options = (linedarlampoff == 1) ? 1 : 0x101; highresolution = (scancfg.sensorresolution >= 1200) ? TRUE : FALSE; do { if (channels_per_dot > 0) { for (channel = 0; channel < channels_per_dot; channel++) dbValues[channel] = (40 / (44 - calibdata->gain_offset.vgag2[channel])) * (40 / (44 - calibdata-> gain_offset. vgag1 [channel])); } /*429c50f */ /* Get Image */ gainmode = Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype); if (RTS_GetImage (dev, Regs, &scancfg, &calibdata->gain_offset, scanbuffer, 0, scan_options, gainmode) != OK) { free (scanbuffer); return ERROR; } /*429c55f */ /* Save retrieved image */ if (RTS_Debug->SaveCalibFile != FALSE) { char fname[30]; imgcount++; if (snprintf (fname, 30, "adcoffset_rt%i.tiff", imgcount) > 0) dbg_tiff_save (fname, scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_COLOR, scancfg.resolution_x, scancfg.resolution_y, scanbuffer, scancfg.bytesperline * calibcfg->OffsetHeight); } /*429c5a5 */ do_loop = FALSE; if (highresolution == TRUE) { /* f0fc = f0e4 = channel */ SANE_Int lf104; SANE_Int *mydcg; /*f0f4 */ USHORT *mywvalue; /*ebp */ SANE_Byte is_ready[6]; /*f174 f178 f17c f180 f184 f18c */ SANE_Byte *ptr_ready; /*f11c */ SANE_Int colour; for (channel = 0; channel < 6; channel++) is_ready[channel] = FALSE; if (channels_per_dot <= 0) break; ptr = scanbuffer; mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1; for (channel = 0; channel < channels_per_dot; channel++) { for (lf104 = 0; lf104 < 2; lf104++) { if (lf104 == 0) { mywvalue = &wvalues[channel]; mydcg = pedcg; ptr_ready = &is_ready[0]; } else { /*1645 */ mywvalue = &wvalues[3]; mydcg = podcg; ptr_ready = &is_ready[3]; } /*1658 */ if (ptr_ready[channel] == FALSE) { colour = 0; if (lf104 < calibcfg->OffsetNPixel) { SANE_Int dot; for (dot = 0; dot < (calibcfg->OffsetNPixel - lf104 + 1) / 2; dot++) colour += scanbuffer[mvgag[(lf104 * channels_per_dot)] + (dot * (channels_per_dot * 2))]; } /*c6b2 */ colour = colour << 8; if (colour == 0) { /*c6b9 */ if (mydcg[channel] != 0x1ff) { /*c6d5 */ mydcg[channel] = 0x1ff; do_loop = TRUE; } else ptr_ready[channel] = TRUE; } else { SANE_Int myesi; SANE_Int d; /*c6e8 */ if (*mywvalue == 0) mywvalue += 2; colour /= (calibcfg->OffsetNPixel / 2); if (colour >= avgtarget[channel]) { colour -= avgtarget[channel]; myesi = 0; } else { colour = avgtarget[channel] - colour; myesi = 1; } d = mydcg[channel]; if (d < 0x100) d = 0xff - d; if (myesi != 0) { /*c76e */ if ((d + colour) > 0x1ff) { if (*mvgag > 0) { *mvgag = *mvgag - 1; do_loop = TRUE; } else ptr_ready[channel] = TRUE; /*c7a0 */ } else d += colour; } else { /*c7ad */ if (colour > d) { if (*mvgag > 0) { *mvgag = *mvgag - 1; do_loop = TRUE; } else ptr_ready[channel] = TRUE; } else d -= colour; } /*c7dd */ mydcg[channel] = (d < 0x100) ? 0x100 - d : d; } dbg_calibtable (&calibdata->gain_offset); } } /*c804 */ mvgag++; } } else { /* Low resolution */ SANE_Byte is_ready[3]; SANE_Int colour; /*429c845 */ for (channel = 0; channel < channels_per_dot; channel++) is_ready[channel] = FALSE; if (channels_per_dot <= 0) break; ptr = scanbuffer; mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1; for (channel = 0; channel < channels_per_dot; channel++) { if (is_ready[channel] == FALSE) { colour = 0; if (calibcfg->OffsetNPixel > 0) { SANE_Int dot; /* Take one channel colour values from offsetnpixel pixels */ for (dot = 0; dot < calibcfg->OffsetNPixel; dot++) colour += *(ptr + (dot * channels_per_dot)); } colour <<= 8; if (colour == 0) { if (pedcg[channel] != 0x1ff) { do_loop = TRUE; podcg[channel] = 0x1ff; pedcg[channel] = 0x1ff; } else is_ready[channel] = TRUE; } else { /*c8f7 */ SANE_Int myesi; SANE_Int op1, op2, op3; /* Get colour average */ colour /= calibcfg->OffsetNPixel; /* get absolute difference with avgtarget */ myesi = (colour > avgtarget[channel]) ? 0 : 1; colour = abs (avgtarget[channel] - colour); if (scancfg.resolution_x > 600) { /*c923 */ if (wvalues[channel + 3] == 0) wvalues[channel + 3]++; if (wvalues[channel] == 0) wvalues[channel]++; op3 = max (wvalues[channel], wvalues[channel + 3]); } else { if (wvalues[channel + 6] == 0) wvalues[channel + 6]++; op3 = wvalues[channel + 6]; } /*c9d3 */ op1 = (SANE_Int) (colour / (dbValues[channel] * op3)); op2 = (pedcg[channel] < 0x100) ? pedcg[channel] - 0xff : pedcg[channel]; if (myesi != 0) { /*c9f5 */ if (((op2 + op1) & 0xffff) > 0x1ff) { if (*mvgag != 0) { do_loop = TRUE; *mvgag = *mvgag - 1; } else is_ready[channel] = TRUE; } else op2 += op1; } else { /*ca31 */ if (op1 > op2) { if (*mvgag > 0) { do_loop = TRUE; *mvgag = *mvgag - 1; } else is_ready[channel] = TRUE; } else op2 -= op1; } /*ca54 */ if (op2 < 0x100) op2 = 0x100 - op2; pedcg[channel] = op2; podcg[channel] = op2; } } /*ca6f */ ptr++; mvgag++; dbg_calibtable (&calibdata->gain_offset); } } } while (do_loop != FALSE); /*429cad1 */ for (channel = 0; channel < 3; channel++) { poffseteven[channel] = (pedcg[channel] < 0x100) ? 0xff - pedcg[channel] : pedcg[channel]; poffsetodd[channel] = (podcg[channel] < 0x100) ? 0xff - podcg[channel] : podcg[channel]; } free (scanbuffer); return OK; } static void Calib_LoadCut (struct st_device *dev, struct st_scanparams *scancfg, SANE_Int scantype, struct st_calibration_config *calibcfg) { double mylong; /*ee78 */ double mylong2; /**/ SANE_Int channel[3]; SANE_Int a; cfg_shading_cut_get (dev->sensorcfg->type, scancfg->depth, scancfg->resolution_x, scantype, &channel[0], &channel[1], &channel[2]); mylong = 1 << scancfg->depth; for (a = CL_RED; a <= CL_BLUE; a++) { mylong2 = channel[a]; calibcfg->ShadingCut[a] = (mylong * mylong2) * 0.000390625; } } static SANE_Int Calib_BWShading (struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode) { /* 0603F8E4 0603F90C |Arg1 = 0603F90C calibcfg 0603F8E8 0603FAAC |Arg2 = 0603FAAC myCalib 0603F8EC 00000001 \Arg3 = 00000001 gainmode */ /*falta codigo */ /*silence gcc */ calibcfg = calibcfg; myCalib = myCalib; gainmode = gainmode; return OK; } static SANE_Int Calib_WhiteShading_3 (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode) { /* 05EDF8E0 04F00738 |Arg1 = 04F00738 05EDF8E4 05EDF90C |Arg2 = 05EDF90C calibcfg 05EDF8E8 05EDFAAC |Arg3 = 05EDFAAC myCalib 05EDF8EC 00000001 \Arg4 = 00000001 gainmode */ SANE_Byte *myRegs; /*f1bc */ struct st_scanparams scancfg; /*f170 */ SANE_Int myWidth; /*f14c */ SANE_Int lf168, bytes_per_pixel; SANE_Int bytes_per_line; /**/ SANE_Int a; double lf1a4[3]; SANE_Int otherheight; /*f150 */ SANE_Int otherheight2; SANE_Int lf12c; SANE_Int lf130; double *buffer1; /*f138 */ double *buffer2; /*f144 */ SANE_Byte *scanbuffer; /*f164 */ SANE_Byte *ptr; /*f148 */ SANE_Int position; /*f140 */ SANE_Int lf13c, myHeight; SANE_Int myESI, myEDI; SANE_Int channel; /*f134 */ double myst; double sumatorio; SANE_Int rst; DBG (DBG_FNC, "> Calib_WhiteShading3(*calibcfg, *myCalib, gainmode=%i)\n", gainmode); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode); rst = OK; scancfg.resolution_y = 200; switch (scan.scantype) { case ST_NORMAL: /*a184 */ scancfg.coord.left += scan.ser; scancfg.coord.width &= 0xffff; break; case ST_TA: case ST_NEG: scancfg.coord.left += scan.ser; break; } /*a11b */ if ((scancfg.coord.width & 1) != 0) scancfg.coord.width++; scancfg.coord.top = 1; scancfg.coord.height = calibcfg->WShadingHeight; switch (scancfg.colormode) { case CM_GRAY: case CM_LINEART: myWidth = scancfg.coord.width; lf168 = 0; bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth; bytes_per_pixel = 1; break; default: /* CM_COLOR */ myWidth = scancfg.coord.width * 3; bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth; lf168 = (scancfg.samplerate == LINE_RATE) ? scancfg.coord.width : 1; bytes_per_pixel = (scancfg.samplerate == PIXEL_RATE) ? 3 : 1; break; } /*a1e8 */ scancfg.v157c = bytes_per_line; scancfg.bytesperline = bytes_per_line; for (a = 0; a < 3; a++) lf1a4[a] = (calibcfg->WRef[a] * (1 << scancfg.depth)) >> 8; /* debug this code because if it's correct, lf130 and lf12c are always 2 */ otherheight = calibcfg->WShadingHeight - 3; otherheight -= (otherheight - 4); otherheight2 = otherheight / 2; otherheight -= otherheight2; lf130 = otherheight2; lf12c = otherheight; buffer1 = (double *) malloc (otherheight * sizeof (double)); if (buffer1 == NULL) return ERROR; buffer2 = (double *) malloc (otherheight * sizeof (double)); if (buffer2 == NULL) { free (buffer1); return ERROR; } scanbuffer = (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) { free (buffer1); free (buffer2); return ERROR; } /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, scanbuffer, myCalib, 0x20000080, gainmode); for (a = 0; a < 3; a++) myCalib->WRef[a] *= ((1 << scancfg.depth) >> 8); if (rst == ERROR) { free (buffer1); free (buffer2); free (scanbuffer); return ERROR; } if (scancfg.depth > 8) { /*a6d9 */ position = 0; sumatorio = 0; if (myWidth > 0) { do { switch (scancfg.colormode) { case CM_GRAY: case CM_LINEART: channel = 0; lf13c = position; break; default: /*CM_COLOR */ if (scancfg.samplerate == PIXEL_RATE) { /* pixel rate */ channel = position % bytes_per_pixel; lf13c = position / bytes_per_pixel; } else { /* line rate */ channel = position / lf168; lf13c = position % lf168; } break; } /*a743 */ if (lf130 > 0) bzero (buffer1, lf130 * sizeof (double)); /*a761 */ if (lf12c > 0) { for (a = 0; a < lf12c; a++) buffer2[a] = (1 << scancfg.depth) - 1.0; } /*a78f */ myESI = 0; myEDI = 0; ptr = scanbuffer + (position * 2); myHeight = 0; if (otherheight > 0) { do { myst = 0; for (a = 0; a < 4; a++) myst += data_lsb_get (ptr + (a * (myWidth * 2)), 2); myEDI = 0; myst = myst * 0.25; if (myHeight < (otherheight - 4)) { if (myst < buffer2[myESI]) { buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] < buffer2[a]) myESI = a; } } /*a820 */ if (myst >= buffer1[myEDI]) { buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] >= buffer1[a]) myEDI = a; } } sumatorio += myst; } else { /*a853 */ if (myHeight == (otherheight - 4)) { if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } /*a895 */ if (myst >= buffer2[myESI]) { /*a89c */ sumatorio -= buffer2[myESI]; sumatorio += myst; buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } } else { if (myst < buffer1[myEDI]) { sumatorio -= buffer1[myEDI]; sumatorio += myst; buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } } } /*a901 */ ptr += (myWidth * 2); myHeight++; } while (myHeight < otherheight); } /*a924 */ scancfg.ser = 0; scancfg.startpos = otherheight - 4; sumatorio = sumatorio / scancfg.startpos; if (myCalib->shading_enabled != FALSE) { /*a94a */ myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } else { /*a967 */ if ((scancfg.colormode != CM_GRAY) && (scancfg.colormode != CM_LINEART)) sumatorio /= lf1a4[channel]; else sumatorio /= lf1a4[scancfg.channel]; sumatorio = min (sumatorio * 0x4000, 65535); if (myRegs[0x1bf] != 0x18) myCalib->black_shading[channel][lf13c] |= (0x140 - ((((myRegs[0x1bf] >> 3) & 3) * 3) << 6)) & ((int) sumatorio); else myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } /*a9fd */ position++; } while (position < myWidth); } } else { /*a6d9 */ position = 0; sumatorio = 0; if (myWidth > 0) { do { switch (scancfg.colormode) { case CM_GRAY: case CM_LINEART: channel = 0; lf13c = position; break; default: /*CM_COLOR */ if (scancfg.samplerate == PIXEL_RATE) { channel = position % bytes_per_pixel; lf13c = position / bytes_per_pixel; } else { channel = position / lf168; lf13c = position % lf168; } break; } /*a743 */ if (lf130 > 0) bzero (buffer1, lf130 * sizeof (double)); /*a761 */ if (lf12c > 0) { for (a = 0; a < lf12c; a++) buffer2[a] = (1 << scancfg.depth) - 1.0; } /*a78f */ myESI = 0; myEDI = 0; ptr = scanbuffer + position; myHeight = 0; if (otherheight > 0) { do { myst = 0; for (a = 0; a < 4; a++) myst += *(ptr + (a * myWidth)); myEDI = 0; myst *= 0.25; if (myHeight < (otherheight - 4)) { if (myst < buffer2[myESI]) { buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] < buffer2[a]) myESI = a; } } /*a820 */ if (myst >= buffer1[myEDI]) { buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] >= buffer1[a]) myEDI = a; } } sumatorio += myst; } else { /*a853 */ if (myHeight == (otherheight - 4)) { if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } /*a895 */ if (myst >= buffer2[myESI]) { /*a89c */ sumatorio -= buffer2[myESI]; sumatorio += myst; buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } } else { if (myst < buffer1[myEDI]) { sumatorio -= buffer1[myEDI]; sumatorio += myst; buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } } } /*a901 */ ptr += myWidth; myHeight++; } while (myHeight < otherheight); } /*a924 */ scancfg.ser = 0; scancfg.startpos = otherheight - 4; sumatorio /= scancfg.startpos; if (myCalib->shading_enabled != FALSE) { /*a94a */ myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } else { /*a967 */ if ((scancfg.colormode != CM_GRAY) && (scancfg.colormode != CM_LINEART)) sumatorio /= lf1a4[channel]; else sumatorio /= lf1a4[scancfg.channel]; sumatorio = min (sumatorio * 0x4000, 65535); if (myRegs[0x1bf] != 0x18) myCalib->black_shading[channel][lf13c] |= (0x140 - ((((myRegs[0x1bf] >> 3) & 0x03) * 3) << 6)) & ((int) sumatorio); else myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } /*a9fd */ position++; } while (position < myWidth); } } /*aa12 */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("whiteshading3.tiff", scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_COLOR, scancfg.resolution_x, scancfg.resolution_y, scanbuffer, (scancfg.coord.height + 16) * bytes_per_line); } free (buffer1); free (buffer2); free (scanbuffer); return OK; } static SANE_Int Calib_BlackShading (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode) { /* gainmode f8ec myCalib f8e8 calibcfg f8e4 */ SANE_Byte *myRegs; /*f1bc */ struct st_scanparams scancfg; /*f020 */ double shadingprediff[6]; /*f08c f094 f09c f0a4 f0ac f0b4 */ double mylong; /*f018 */ double maxvalue; /*eff8 */ double sumatorio = 0.0; double myst; SANE_Int rst; SANE_Int a; SANE_Int mheight; /*efe0 */ SANE_Int current_line; /*efe4 */ SANE_Int bytes_per_line; /*efd8 */ SANE_Int position; /*lefcc */ SANE_Int leff0, lf010, lefd0; SANE_Byte *buffer; /*efd4 */ SANE_Byte buff2[256]; /*F0BC */ SANE_Int buff3[0x8000]; SANE_Byte *ptr; /*f008 */ SANE_Int my14b4; /*f008 pisa ptr */ SANE_Int biggest; /*bx */ SANE_Int lowest; /*dx */ SANE_Int lefdc; SANE_Int channel; SANE_Int smvalues[3]; /*f04c f04e f050 */ double dbvalue[6]; /*lf05c lf060, lf064 lf068, lf06c lf070, lf074 lf078, lf07c lf080, lf084 lf088 */ DBG (DBG_FNC, "> Calib_BlackShading(*calibcfg, *myCalib, gainmode=%i)\n", gainmode); rst = OK; myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode); for (a = CL_RED; a <= CL_BLUE; a++) shadingprediff[a + 3] = calibcfg->BShadingPreDiff[a]; if ((scan.scantype >= ST_NORMAL) && (scan.scantype <= ST_NEG)) scancfg.coord.left += scan.ser; if ((scancfg.coord.width & 1) != 0) scancfg.coord.width++; scancfg.coord.top = 1; scancfg.depth = 8; scancfg.coord.height = calibcfg->BShadingHeight; if (scancfg.colormode != CM_COLOR) { bytes_per_line = scancfg.coord.width; leff0 = 0; lf010 = 1; } else { /*876c */ bytes_per_line = scancfg.coord.width * 3; if (scancfg.samplerate == LINE_RATE) { leff0 = scancfg.coord.width; lf010 = 1; } else { leff0 = 1; lf010 = 3; } } scancfg.v157c = bytes_per_line; scancfg.bytesperline = bytes_per_line; mylong = 1 << (16 - scancfg.depth); if ((myRegs[0x1bf] & 0x18) != 0) mylong /= 1 << (((myRegs[0x1bf] >> 5) & 3) + 4); lefd0 = ((((myRegs[0x1bf] >> 3) & 2) << 8) - ((((myRegs[0x1bf] >> 3) & 1) * 3) << 6)) - 1; if (scancfg.depth >= 8) maxvalue = ((1 << (scancfg.depth - 8)) << 8) - 1; else maxvalue = (256 / (1 << (8 - scancfg.depth))) - 1; Calib_LoadCut (dev, &scancfg, scan.scantype, calibcfg); for (a = CL_RED; a <= CL_BLUE; a++) shadingprediff[a] = calibcfg->ShadingCut[a]; if (calibcfg->BShadingOn == -1) { SANE_Int b, d; double e; for (a = CL_RED; a <= CL_BLUE; a++) { myst = max (shadingprediff[a], 0); myst = (maxvalue >= myst) ? shadingprediff[a] : maxvalue; shadingprediff[a] = max (myst, 0); } b = 0; while (b < bytes_per_line) { if (scancfg.colormode != CM_COLOR) { channel = 0; d = b; } else { if (scancfg.samplerate == PIXEL_RATE) { channel = (b % lf010) & 0xffff; d = (b / lf010) & 0xffff; } else { channel = (b / leff0) & 0xffff; d = (b % leff0) & 0xffff; } } /*89d0 */ e = min (lefd0, mylong * shadingprediff[channel]); myCalib->black_shading[channel][d] |= (unsigned short) e & 0xffff; b++; } return OK; } /* Allocate buffer to read image */ mheight = scancfg.coord.height; buffer = (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (buffer == NULL) return ERROR; /* Turn off lamp */ Lamp_Status_Set (dev, NULL, FALSE, FLB_LAMP); usleep (200 * 1000); /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, buffer, myCalib, 0x101, gainmode); if (rst == ERROR) { /*8ac2 */ free (buffer); memcpy (&calibdata->Regs, myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte)); free (myRegs); return ERROR; } /* myRegs isn't going to be used anymore */ free (myRegs); myRegs = NULL; /* Turn on lamp again */ if (scan.scantype != ST_NORMAL) { Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP); usleep (1000 * 1000); } else Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); /* Save buffer */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("blackshading.tiff", scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_COLOR, scancfg.resolution_x, scancfg.resolution_y, buffer, (scancfg.coord.height + 16) * bytes_per_line); } if (scancfg.depth > 8) { /*8bb2 */ bzero (&dbvalue, 6 * sizeof (double)); position = 0; if (bytes_per_line > 0) { do { bzero (&buff3, 0x8000 * sizeof (SANE_Int)); sumatorio = 0; ptr = buffer + position; current_line = 0; biggest = 0; lowest = (int) maxvalue; /* Toma los valores de una columna */ if (mheight > 0) { SANE_Int value; do { value = data_lsb_get (ptr, 2); biggest = max (biggest, value); if (current_line < mheight) { sumatorio += value; lowest = min (lowest, value); biggest = max (biggest, value); buff3[value]++; } else { /*8cab */ if (value > lowest) { buff3[lowest]--; buff3[value]++; sumatorio += value; sumatorio -= lowest; if (buff3[lowest] != 0) { do { lowest++; } while (buff3[lowest] == 0); } } } /*8d0b */ ptr += (bytes_per_line * 2); current_line++; } while (current_line < mheight); } /*8d27 */ sumatorio /= mheight; if (scancfg.colormode != CM_COLOR) { channel = 0; lefdc = position; } else { /*8d5f */ if (scancfg.samplerate == PIXEL_RATE) { channel = position % lf010; lefdc = (position / lf010) & 0xffff; } else { channel = position / leff0; lefdc = position % leff0; } } dbvalue[channel] += sumatorio; if ((scancfg.colormode == CM_GRAY) || (scancfg.colormode == CM_LINEART)) sumatorio += shadingprediff[scancfg.channel]; else sumatorio += shadingprediff[channel]; myst = min (max (0, sumatorio), maxvalue); dbvalue[channel + 3] = myst; if ((calibcfg->BShadingOn == 1) || (calibcfg->BShadingOn == 2)) { if (calibcfg->BShadingOn == 2) { myst -= calibcfg->BRef[channel] * (1 << (scancfg.depth - 8)); myst = max (myst, 0); } /*8e6d */ myst *= mylong; myCalib->black_shading[channel][lefdc] = min (myst, lefd0); } position++; } while (position < bytes_per_line); } } else { /*8eb6 */ bzero (&dbvalue, 6 * sizeof (double)); position = 0; if (bytes_per_line > 0) { do { bzero (&buff2, 256 * sizeof (SANE_Byte)); sumatorio = 0; /* ptr points to the next position of the first line */ ptr = buffer + position; biggest = 0; lowest = (int) maxvalue; current_line = 0; /* Toma los valores de una columna */ if (mheight > 0) { my14b4 = v14b4; do { biggest = max (biggest, *ptr); if (my14b4 == 0) { /*8fd7 */ if (current_line < mheight) { sumatorio += *ptr; lowest = min (lowest, *ptr); biggest = max (biggest, *ptr); buff2[*ptr]++; } else { /*9011 */ if (*ptr > lowest) { buff2[lowest]--; buff2[*ptr]++; sumatorio += *ptr; sumatorio -= lowest; if (buff2[lowest] != 0) { do { lowest++; } while (buff2[lowest] == 0); } } } } else sumatorio += *ptr; /*9067 */ /* Point to the next pixel under current line */ ptr += bytes_per_line; current_line++; } while (current_line < mheight); } /*908a */ /* Calculates average of each column */ sumatorio = sumatorio / mheight; if (scancfg.colormode != CM_COLOR) { channel = 0; lefdc = position; } else { /*90c5 */ if (scancfg.samplerate == PIXEL_RATE) { channel = position % lf010; lefdc = (position / lf010) & 0xffff; } else { /*90fb */ channel = position / leff0; lefdc = position % leff0; } } /*911f */ dbvalue[channel] += sumatorio; if ((scancfg.colormode == CM_GRAY) || (scancfg.colormode == CM_LINEART)) sumatorio += shadingprediff[scancfg.channel]; else sumatorio += shadingprediff[channel]; /*9151 */ myst = min (max (0, sumatorio), maxvalue); /*9198 */ if (position >= 3) { double myst2; myst -= dbvalue[channel + 3]; myst2 = myst; myst = min (myst, shadingprediff[channel + 3]); my14b4 = -shadingprediff[channel + 3]; if (myst >= my14b4) myst = min (myst2, shadingprediff[channel + 3]); else myst = my14b4; myst += dbvalue[channel + 3]; } /*9203 */ dbvalue[channel + 3] = myst; switch (calibcfg->BShadingOn) { case 1: myCalib->black_shading[channel][lefdc] |= (unsigned short) (((int) myst & 0xff) << 8) & 0xffff; break; case 2: /*9268 */ my14b4 = calibcfg->BRef[channel] / (1 << (8 - scancfg.depth)); myst -= my14b4; myst = max (myst, 0); myst *= mylong; myCalib->black_shading[channel][lefdc] = min (myst, lefd0); break; } /*92d8 */ position++; } while (position < bytes_per_line); } } /*9306 */ if (calibcfg->BShadingOn == -2) { for (a = 0; a < 3; a++) { dbvalue[a] = (dbvalue[a] / scancfg.coord.width) + calibcfg->ShadingCut[a]; if (dbvalue[a] < 0) dbvalue[a] = 0; smvalues[a] = min ((int) (dbvalue[a] + 0.5) & 0xffff, maxvalue); } if (scancfg.coord.width > 0) { SANE_Int b, c; for (c = 0; c < scancfg.coord.width; c++) for (b = 0; b < 3; b++) myCalib->black_shading[b][c] |= (unsigned short) min (smvalues[b] * mylong, lefd0); } } /*9425 */ free (buffer); return OK; } static SANE_Int Calibration (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_calibration *myCalib, SANE_Int value) { /*//SANE_Int Calibration([fa20]char *Regs, [fa24]struct st_scanparams *scancfg, [fa28]struct st_calibration myCalib, [fa2c]SANE_Int value) */ struct st_calibration_config calibcfg; /* f90c */ SANE_Int a; SANE_Byte gainmode; SANE_Int lf900; DBG (DBG_FNC, "> Calibration\n"); dbg_ScanParams (scancfg); value = value; /*silence gcc */ memcpy (&calibdata->Regs, Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); /*4213be8 */ memset (&calibcfg, 0x30, sizeof (struct st_calibration_config)); Calib_LoadConfig (dev, &calibcfg, scan.scantype, scancfg->resolution_x, scancfg->depth); bzero (&calibdata->gain_offset, sizeof (struct st_gain_offset)); /*[42b3654] */ for (a = CL_RED; a <= CL_BLUE; a++) { myCalib->WRef[a] = calibcfg.WRef[a]; calibdata->gain_offset.edcg1[a] = 256; calibdata->gain_offset.odcg1[a] = 256; calibdata->gain_offset.vgag1[a] = 4; calibdata->gain_offset.vgag2[a] = 4; /*3654|3656|3658 365a|365c|365e 3660|3662|3664 3666|3668|366a 366c|366d|366e 366f|3670|3671 3672|3673|3674 */ } memcpy (&calibdata->scancfg, scancfg, sizeof (struct st_scanparams)); gainmode = Lamp_GetGainMode (dev, scancfg->resolution_x, scan.scantype); /* [lf904] = 1 */ /* 3cf3 */ myCalib->first_position = 1; myCalib->shading_type = 0; if (calibdata->scancfg.colormode == CM_LINEART) { calibdata->scancfg.colormode = CM_GRAY; calibcfg.GainTargetFactor = 1.3; } lf900 = OK; if (calibcfg.CalibPAGOn != 0) { if (Calib_PAGain (dev, &calibcfg, gainmode) != 0) lf900 = ERROR; /*ERROR*/} else { /*3da7 */ if ((calibdata->scancfg.colormode != CM_GRAY) && (calibdata->scancfg.colormode != CM_LINEART)) { for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.pag[a] = calibcfg.PAG[a]; } else { /* 3dd3 */ /* Default PAGain */ if (calibdata->scancfg.channel > 2) calibdata->scancfg.channel = 0; for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.pag[a] = calibcfg.PAG[calibdata->scancfg.channel]; } } /* 3e01 */ if (calibcfg.CalibOffset10n != 0) /*==2*/ { /*v14b4=1 offset[CL_RED]=0x174 offset[CL_GREEN]=0x16d offset[CL_BLUE]=0x160 */ if ((v14b4 != 0) && (offset[CL_RED] != 0) && (offset[CL_GREEN] != 0) && (offset[CL_BLUE] != 0)) { for (a = CL_RED; a <= CL_BLUE; a++) { calibdata->gain_offset.edcg1[a] = offset[a]; calibdata->gain_offset.odcg1[a] = offset[a]; } } else { /* 3e84 */ if ((calibcfg.CalibOffset10n > 0) && (calibcfg.CalibOffset10n < 4)) { /*if (calibcfg.CalibOffset10n != 0) */ if (calibcfg.CalibOffset10n == 3) { lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 1); } else { /* 3eb2 */ /*falta codigo */ } } } } else { /* 3faf */ for (a = CL_RED; a <= CL_BLUE; a++) { calibdata->gain_offset.edcg1[a] = abs (calibcfg.OffsetEven1[a] - 0x100); calibdata->gain_offset.odcg1[a] = abs (calibcfg.OffsetOdd1[a] - 0x100); } } /* 3f13 3f0b */ if ((gainmode != 0) && (calibcfg.CalibGain10n != 0)) { /*gain[CL_RED]=0x17 gain[CL_GREEN]=0x12 gain[CL_BLUE]=0x17 */ if ((v14b4 != 0) && (gain[CL_RED] != 0) && (gain[CL_GREEN] != 0) && (gain[CL_BLUE] != 0)) { for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.vgag1[a] = gain[a]; } else { /*4025 */ lf900 = Calib_AdcGain (dev, &calibcfg, 1, gainmode); if ((v14b4 != 0) && (lf900 == OK)) GainOffset_Save (dev, &calibdata->gain_offset.edcg1[0], &calibdata->gain_offset.vgag1[0]); } } else { /*4089 */ for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.vgag1[a] = calibcfg.Gain1[a]; } /*40a5 */ if ((gainmode != 0) && (calibcfg.CalibOffset20n != 0)) { switch (calibcfg.CalibOffset20n) { case 3: lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 2); break; } /*4140 */ /*falta codigo */ } else { /*4162 */ for (a = CL_RED; a <= CL_BLUE; a++) { calibdata->gain_offset.edcg2[a] = abs (calibcfg.OffsetEven2[a] - 0x40); calibdata->gain_offset.odcg2[a] = abs (calibcfg.OffsetOdd2[a] - 0x40); } } /*41d6 */ if ((gainmode != 0) && (calibcfg.CalibGain20n != 0)) { lf900 = Calib_AdcGain (dev, &calibcfg, 0, gainmode); } else { /*423c */ for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.vgag2[a] = calibcfg.Gain2[a]; } /*4258 */ if (calibcfg.TotShading != 0) { lf900 = Calib_BWShading (&calibcfg, myCalib, gainmode); /*falta codigo */ } else { /*428f */ if (gainmode != 0) { if (calibcfg.BShadingOn != 0) lf900 = Calib_BlackShading (dev, &calibcfg, myCalib, gainmode); /*42fd */ if ((lf900 != ERROR) && (calibcfg.WShadingOn != 0)) { switch (calibcfg.WShadingOn) { default: break; case 3: lf900 = Calib_WhiteShading_3 (dev, &calibcfg, myCalib, gainmode); break; case 2: break; } } else myCalib->shading_enabled = FALSE; } else myCalib->shading_enabled = FALSE; } /*43ca */ memcpy (&myCalib->gain_offset, &calibdata->gain_offset, sizeof (struct st_gain_offset)); memcpy (&mitabla2, &calibdata->gain_offset, sizeof (struct st_gain_offset)); /*4424 */ /* Park home after calibration */ if (get_value (SCANINFO, PARKHOMEAFTERCALIB, TRUE, FITCALIBRATE) == FALSE) scan.ler -= calibcfg.WShadingHeight; else Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); return OK; } /*static void show_diff(struct st_device *dev, SANE_Byte *original) { SANE_Byte *buffer = (SANE_Byte *)malloc(RT_BUFFER_LEN * sizeof(SANE_Byte)); SANE_Int a; if ((buffer == NULL)||(original == NULL)) return; if (RTS_ReadRegs(dev->usb_handle, buffer) != OK) { free(buffer); return; } for (a = 0; a < RT_BUFFER_LEN; a++) { if ((original[a] & 0xff) != (buffer[a] & 0xff)) { printf("%5i: %i -> %i\n", a, original[a] & 0xff, buffer[a] & 0xff); original[a] = buffer[a] & 0xff; } } free(buffer); } */ static SANE_Int Load_Constrains (struct st_device *dev) { SANE_Int rst = ERROR; if (dev->constrains != NULL) Free_Constrains (dev); DBG (DBG_FNC, "> Load_Constrains\n"); dev->constrains = (struct st_constrains *) malloc (sizeof (struct st_constrains)); if (dev->constrains != NULL) { cfg_constrains_get (dev->constrains); rst = OK; } return rst; } static SANE_Int Constrains_Check (struct st_device *dev, SANE_Int Resolution, SANE_Int scantype, struct st_coords *mycoords) { /* Constrains: 100 dpi 850 x 1170 | 164 x 327 300 dpi 2550 x 3510 600 dpi 5100 x 7020 1200 dpi 10200 x 14040 */ SANE_Int rst = ERROR; if (dev->constrains != NULL) { struct st_coords coords; struct st_coords *mc; if ((scantype < ST_NORMAL) || (scantype > ST_NEG)) scantype = ST_NORMAL; switch (scantype) { case ST_TA: mc = &dev->constrains->slide; break; case ST_NEG: mc = &dev->constrains->negative; break; default: mc = &dev->constrains->reflective; break; } coords.left = MM_TO_PIXEL (mc->left, Resolution); coords.width = MM_TO_PIXEL (mc->width, Resolution); coords.top = MM_TO_PIXEL (mc->top, Resolution); coords.height = MM_TO_PIXEL (mc->height, Resolution); /* Check left and top */ if (mycoords->left < 0) mycoords->left = 0; mycoords->left += coords.left; if (mycoords->top < 0) mycoords->top = 0; mycoords->top += coords.top; /* Check width and height */ if ((mycoords->width < 0) || (mycoords->width > coords.width)) mycoords->width = coords.width; if ((mycoords->height < 0) || (mycoords->height > coords.height)) mycoords->height = coords.height; rst = OK; } DBG (DBG_FNC, "> Constrains_Check: Source=%s, Res=%i, LW=(%i,%i), TH=(%i,%i): %i\n", dbg_scantype (scantype), Resolution, mycoords->left, mycoords->width, mycoords->top, mycoords->height, rst); return rst; } static struct st_coords * Constrains_Get (struct st_device *dev, SANE_Byte scantype) { static struct st_coords *rst = NULL; if (dev->constrains != NULL) { switch (scantype) { case ST_TA: rst = &dev->constrains->slide; break; case ST_NEG: rst = &dev->constrains->negative; break; default: rst = &dev->constrains->reflective; break; } } return rst; } static void Free_Constrains (struct st_device *dev) { DBG (DBG_FNC, "> Free_Constrains\n"); if (dev->constrains != NULL) { free (dev->constrains); dev->constrains = NULL; } } static void RTS_DebugInit () { /* Default vaules */ RTS_Debug->dev_model = HP3970; RTS_Debug->DumpShadingData = FALSE; RTS_Debug->SaveCalibFile = FALSE; RTS_Debug->ScanWhiteBoard = FALSE; RTS_Debug->EnableGamma = TRUE; RTS_Debug->use_fixed_pwm = TRUE; RTS_Debug->dmatransfersize = 0x80000; RTS_Debug->dmasetlength = 0x7c0000; RTS_Debug->dmabuffersize = 0x400000; RTS_Debug->usbtype = -1; /* Lamp settings */ RTS_Debug->overdrive_flb = 10000; /* msecs */ RTS_Debug->overdrive_ta = 10000; /* msecs */ RTS_Debug->warmup = TRUE; /* Calibration settings */ RTS_Debug->calibrate = FALSE; RTS_Debug->wshading = TRUE; } static void RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *hwdcfg) { DBG (DBG_FNC, "> RTS_Setup_Gamma(*Regs, *hwdcfg)\n"); if ((hwdcfg != NULL) && (Regs != NULL)) { if (hwdcfg->use_gamma_tables != FALSE) { SANE_Int table_size; /* set set table size */ data_bitset (&Regs[0x1d0], 0x0f, hwdcfg->gamma_tablesize); /* enable gamma correction */ data_bitset (&Regs[0x1d0], 0x40, 1); switch (Regs[0x1d0] & 0x0c) { case 0: table_size = (Regs[0x1d0] & 1) | 0x0100; break; case 4: table_size = (Regs[0x1d0] & 1) | 0x0400; break; case 8: table_size = (Regs[0x1d0] & 1) | 0x1000; break; default: table_size = hwdcfg->startpos & 0xffff; break; } /* 5073 */ /* points to red gamma table */ data_wide_bitset (&Regs[0x1b4], 0x3fff, 0); /* points to green gamma table */ data_wide_bitset (&Regs[0x1b6], 0x3fff, table_size); /* points to blue gamma table */ data_wide_bitset (&Regs[0x1b8], 0x3fff, table_size * 2); v15f8 = (((table_size * 3) + 15) / 16) & 0xffff; } else { /* disable gamma correction */ data_bitset (&Regs[0x1d0], 0x40, 0); v15f8 = 0; } } } static SANE_Int RTS_USBType (struct st_device *dev) { /* Gets USB type of this scanner */ SANE_Int rst = ERROR; SANE_Byte data; DBG (DBG_FNC, "+ RTS_USBType\n"); if (Read_Byte (dev->usb_handle, 0xfe11, &data) == OK) rst = (data & 1); DBG (DBG_FNC, "- RTS_USBType(void): %s\n", (rst == USB11) ? "USB1.1" : "USB2.0"); return rst; } static SANE_Int Init_Vars (void) { SANE_Int rst = OK; hp_gamma = malloc (sizeof (struct st_gammatables)); if (hp_gamma != NULL) bzero (hp_gamma, sizeof (struct st_gammatables)); else rst = ERROR; if (rst == OK) { RTS_Debug = malloc (sizeof (struct st_debug_opts)); if (RTS_Debug != NULL) bzero (RTS_Debug, sizeof (struct st_debug_opts)); else rst = ERROR; } if (rst == OK) { default_gain_offset = malloc (sizeof (struct st_gain_offset)); if (default_gain_offset != NULL) bzero (default_gain_offset, sizeof (struct st_gain_offset)); else rst = ERROR; } if (rst == OK) { calibdata = malloc (sizeof (struct st_calibration_data)); if (calibdata != NULL) bzero (calibdata, sizeof (struct st_calibration_data)); else rst = ERROR; } if (rst == OK) { wshading = malloc (sizeof (struct st_shading)); if (wshading != NULL) bzero (wshading, sizeof (struct st_shading)); else rst = ERROR; } waitforpwm = TRUE; use_gamma_tables = TRUE; if (rst == OK) RTS_DebugInit (); else Free_Vars (); return rst; } static void Free_Vars (void) { if (RTS_Debug != NULL) { free (RTS_Debug); RTS_Debug = NULL; } if (hp_gamma != NULL) { free (hp_gamma); hp_gamma = NULL; } if (calibdata != NULL) { free (calibdata); calibdata = NULL; } if (wshading != NULL) { if (wshading->rates != NULL) free (wshading->rates); free (wshading); wshading = NULL; } if (default_gain_offset != NULL) { free (default_gain_offset); default_gain_offset = NULL; } } static SANE_Int Chipset_Reset (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ Chipset_Reset:\n"); /* I've found two ways to reset chipset. Next one will stay commented rst = ERROR; if (Read_Byte(dev->usb_handle, 0xe800, &data) == OK) { data |= 0x20; if (Write_Byte(dev->usb_handle, 0xe800, data) == OK) { data &= 0xdf; rst = Write_Byte(dev->usb_handle, 0xe800, data); } } */ rst = IWrite_Buffer (dev->usb_handle, 0x0000, NULL, 0, 0x0801); DBG (DBG_FNC, "- Chipset_Reset: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options) { SANE_Int rst = ERROR; SANE_Byte buffer[6]; DBG (DBG_FNC, "+ RTS_DMA_Enable_Read(dmacs=0x%04x, size=%i, options=0x%06x)\n", dmacs, size, options); data_msb_set (&buffer[0], options, 3); /* buffer size divided by 2 (words count) */ data_lsb_set (&buffer[3], size / 2, 3); rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0400); DBG (DBG_FNC, "- RTS_DMA_Enable_Read: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options) { SANE_Int rst = ERROR; SANE_Byte buffer[6]; DBG (DBG_FNC, "+ RTS_DMA_Enable_Write(dmacs=0x%04x, size=%i, options=0x%06x)\n", dmacs, size, options); data_msb_set (&buffer[0], options, 3); /* buffer size divided by 2 (words count) */ data_lsb_set (&buffer[3], size / 2, 3); rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0401); DBG (DBG_FNC, "- RTS_DMA_Enable_Write: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Cancel (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_DMA_Cancel:\n"); rst = IWrite_Word (dev->usb_handle, 0x0000, 0, 0x0600); DBG (DBG_FNC, "- RTS_DMA_Cancel: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Reset (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_DMA_Reset:\n"); rst = IWrite_Word (dev->usb_handle, 0x0000, 0x0000, 0x0800); DBG (DBG_FNC, "- RTS_DMA_Reset: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteByte(address=%04x, data=%i):\n", address, data); rst = IWrite_Byte (usb_handle, address, data, 0x200, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_WriteByte: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_ReadWord(address=%04x, data):\n", address); rst = IRead_Word (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_ReadWord: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_ReadByte(address=%04x, data):\n", address); rst = IRead_Byte (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_ReadByte: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, SANE_Int data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteWord(address=%04x, data=%i):\n", address, data); rst = IWrite_Word (usb_handle, address, data, 0x0200); DBG (DBG_FNC, "- RTS_EEPROM_WriteWord: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_ReadInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_ReadInteger(address=%04x, data):\n", address); rst = IRead_Integer (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_ReadInteger: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteInteger(address=%04x, data):\n", address); rst = IWrite_Integer (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_WriteInteger: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, SANE_Int size) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteBuffer(address=%04x, data, size=%i):\n", address, size); rst = IWrite_Buffer (usb_handle, address, data, size, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_WriteBuffer: %i\n", rst); return rst; } static void WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, SANE_Int size, SANE_Int depth) { if ((wshading->rates != NULL) && (chnptr != NULL)) { if (*chnptr < wshading->count) { double maxvalue, chncolor; SANE_Int chnsize; SANE_Int pos; SANE_Int icolor; maxvalue = (1 << depth) - 1; chnsize = (depth > 8) ? 2 : 1; pos = 0; while (pos < size) { /* get channel color */ chncolor = data_lsb_get (buffer + pos, chnsize); /* apply shading coeficient */ chncolor *= wshading->rates[*chnptr]; /* care about limits */ chncolor = min (chncolor, maxvalue); /* save color */ icolor = chncolor; data_lsb_set (buffer + pos, icolor, chnsize); *chnptr = *chnptr + 1; if (*chnptr >= wshading->count) *chnptr = 0; pos += chnsize; } } } } static SANE_Int WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int x, y, a, C; SANE_Byte *pattern; /*f164 */ double sumatorio; SANE_Int gainmode; SANE_Int rst; SANE_Byte *avg_colors; DBG (DBG_FNC, "> WShading_Calibrate(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; } calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 1; myscancfg->coord.height = calibcfg->WShadingHeight; myscancfg->sensorresolution = 0; bytes_per_line = myscancfg->coord.width * (((myscancfg->colormode == CM_COLOR) ? 3 : 1) * ((myscancfg->depth > 8) ? 2 : 1)); /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; /* allocate space for pattern */ pattern = (SANE_Byte *) malloc (((myscancfg->coord.height) * bytes_per_line) * sizeof (SANE_Byte)); if (pattern == NULL) return ERROR; /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, pattern, myCalib, 0x20000000, gainmode); if (rst != ERROR) { SANE_Int chn; double colors[3] = { 0, 0, 0 }; double prueba; SANE_Int data; SANE_Int bytes_per_channel; bytes_per_channel = (myscancfg->depth > 8) ? 2 : 1; avg_colors = (SANE_Byte *) malloc (sizeof (SANE_Byte) * bytes_per_line); if (avg_colors != NULL) { wshading->ptr = 0; wshading->count = bytes_per_line / bytes_per_channel; if (wshading->rates != NULL) { free (wshading->rates); wshading->rates = NULL; } wshading->rates = (double *) malloc (sizeof (double) * wshading->count); chn = 0; for (x = 0; x < wshading->count; x++) { sumatorio = 0; for (y = 0; y < myscancfg->coord.height; y++) { data = data_lsb_get (pattern + ((x * bytes_per_channel) + (bytes_per_line * y)), bytes_per_channel); sumatorio += data; } sumatorio /= myscancfg->coord.height; a = sumatorio; colors[chn] = max (colors[chn], sumatorio); chn++; if (chn > 2) chn = 0; data_lsb_set (avg_colors + (x * bytes_per_channel), a, bytes_per_channel); } DBG (DBG_FNC, " -> max colors RGB= %f %f %f\n", colors[0], colors[1], colors[2]); chn = 0; for (x = 0; x < wshading->count; x++) { data = data_lsb_get (avg_colors + (x * bytes_per_channel), bytes_per_channel); prueba = data; *(wshading->rates + x) = colors[chn] / prueba; chn++; if (chn > 2) chn = 0; } } if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("whiteshading_jkd.tiff", myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, pattern, (myscancfg->coord.height) * bytes_per_line); } #ifdef developing { FILE *archivo; char texto[1024]; /* apply correction to the pattern to see the result */ chn = 0; for (x = 0; x < myscancfg->coord.height * wshading->count; x++) { data = data_lsb_get (pattern + (x * bytes_per_channel), bytes_per_channel); sumatorio = data; sumatorio *= wshading->rates[chn]; if (sumatorio > ((1 << myscancfg->depth) - 1)) sumatorio = (1 << myscancfg->depth) - 1; a = sumatorio; data_lsb_set (pattern + (x * bytes_per_channel), a, bytes_per_channel); chn++; if (chn == wshading->count) chn = 0; } /* save corrected pattern */ dbg_tiff_save ("onwhiteshading_jkd.tiff", myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, pattern, (myscancfg->coord.height) * bytes_per_line); /* export coefficients */ archivo = fopen ("wShading.txt", "w"); for (x = 0; x < wshading->count; x++) { snprintf (texto, 1024, "%f", wshading->rates[x]); fprintf (archivo, "%s\n", texto); } fclose (archivo); } #endif } free (pattern); return OK; } #ifdef developing static SANE_Int motor_pos (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int a, C; SANE_Byte *scanbuffer; /*f164 */ SANE_Int gainmode; SANE_Int rst; DBG (DBG_FNC, "> Calib_test(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 100; myscancfg->coord.height = 30; bytes_per_line = myscancfg->coord.width * 3; /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; scanbuffer = (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /* Scan image */ myCalib->shading_enabled = FALSE; /*Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */ for (a = 0; a < 10; a++) { for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; myCalibTable.edcg1[C] = a * 20; } dbg_ScanParams (myscancfg); Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5000); rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, 0x20000000, gainmode); Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); if (rst != ERROR) { char name[30]; snprintf (name, 30, "calibtest-%i.tiff", a); dbg_tiff_save (name, myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, myscancfg->resolution_x, myscancfg->resolution_y, scanbuffer, (myscancfg->coord.height + 16) * bytes_per_line); } } free (scanbuffer); exit (0); return OK; } static SANE_Int hp4370_prueba (struct st_device *dev) { SANE_Int rst; SANE_Int data = 0x0530, a; SANE_Int transferred; SANE_Byte buffer[512]; for (a = 0; a < 256; a++) data_lsb_set (buffer + (a * 2), 0x9d7, 2); rst = IWrite_Word (dev->usb_handle, 0x0000, data, 0x0800); RTS_DMA_Enable_Write (dev, 0x4, 512, 0); Bulk_Operation (dev, BLK_WRITE, 512, buffer, &transferred); return rst; } static SANE_Int Calib_BlackShading_jkd (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int x, y, a, C; SANE_Byte *scanbuffer; /*f164 */ double sumatorio; SANE_Int gainmode; SANE_Int rst; DBG (DBG_FNC, "> Calib_BlackShading_jkd(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; } calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 1; myscancfg->coord.height = calibcfg->BShadingHeight; bytes_per_line = myscancfg->coord.width * 3; /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; scanbuffer = (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /* Turn off lamp */ Lamp_Status_Set (dev, NULL, FALSE, FLB_LAMP); usleep (200 * 1000); /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, 0x101, gainmode); /* Turn on lamp again */ if (scan.scantype != ST_NORMAL) { Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP); usleep (1000 * 1000); } else Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); if (rst != ERROR) { jkd_black = (SANE_Byte *) malloc (bytes_per_line); if (jkd_black != NULL) { jkd_blackbpl = bytes_per_line; for (x = 0; x < bytes_per_line; x++) { sumatorio = 0; for (y = 0; y < myscancfg->coord.height + 16; y++) sumatorio += scanbuffer[x + (bytes_per_line * y)]; sumatorio /= myscancfg->coord.height + 16; a = sumatorio; *(jkd_black + x) = _B0 (a); } } /*if (RTS_Debug->SaveCalibFile != FALSE) */ { dbg_tiff_save ("blackshading_jkd.tiff", myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, myscancfg->resolution_x, myscancfg->resolution_y, scanbuffer, (myscancfg->coord.height + 16) * bytes_per_line); } } free (scanbuffer); return OK; } static SANE_Int Calib_test (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int a, C; SANE_Byte *scanbuffer; /*f164 */ SANE_Int gainmode; SANE_Int rst; DBG (DBG_FNC, "> Calib_test(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 100; myscancfg->coord.height = 30; bytes_per_line = myscancfg->coord.width * 3; /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; scanbuffer = (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /* Scan image */ myCalib->shading_enabled = FALSE; /*Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */ for (a = 0; a < 10; a++) { for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; myCalibTable.edcg1[C] = a * 20; } Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5000); rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, 0x20000000, gainmode); Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); if (rst != ERROR) { char name[30]; snprintf (name, 30, "calibtest-%i.tiff", a); dbg_tiff_save (name, myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, myscancfg->resolution_x, myscancfg->resolution_y, scanbuffer, (myscancfg->coord.height + 16) * bytes_per_line); } } free (scanbuffer); exit (0); return OK; } static void prueba (SANE_Byte * a) { /* SANE_Byte p[] = {}; */ /*int z = 69; */ /*(a + 11) = 0x0; */ /*a[1] = a[1] | 0x40; */ /*memcpy(a, &p, sizeof(p)); */ /*memcpy(a + 0x12, p, 10); */ /*a[0x146] &= 0xdf; */ } void shadingtest1 (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib) { USHORT *buffer; int a; int bit[2]; DBG (DBG_FNC, "+ shadingtest1(*Regs, *myCalib):\n"); if ((Regs == NULL) || (myCalib == NULL)) return; RTS_DMA_Reset (dev); bit[0] = (Regs[0x60b] >> 6) & 1; bit[1] = (Regs[0x60b] >> 4) & 1; Regs[0x060b] &= 0xaf; Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); Regs[0x1cf] = 0; /* reset config. By default black shading disabled and pixel-rate */ /*Regs[0x1cf] |= 2; shadingbase 0x2000 */ Regs[0x1cf] |= 4; /* White shading enabled */ Regs[0x1cf] |= 0x20; /* 16 bits per channel */ Write_Byte (dev->usb_handle, 0xe9cf, Regs[0x01cf]); buffer = (USHORT *) malloc (sizeof (USHORT) * myCalib->shadinglength); DBG (DBG_FNC, " -> shading length = %i\n", myCalib->shadinglength); /* fill buffer */ for (a = 0; a < myCalib->shadinglength; a++) buffer[a] = RTS_Debug->shd + (a * 500); for (a = 0; a < 3; a++) { RTS_DMA_Write (dev, a | 0x14, 0, sizeof (USHORT) * myCalib->shadinglength, (SANE_Byte *) buffer); } data_bitset (&Regs[0x60b], 0x40, bit[0]); /*-x------*/ data_bitset (&Regs[0x60b], 0x10, bit[1]); /*---x----*/ Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); DBG (DBG_FNC, "- shadingtest1\n"); } #endif #endif /* RTS8822_CORE */