kopia lustrzana https://gitlab.com/sane-project/backends
15124 wiersze
363 KiB
C
15124 wiersze
363 KiB
C
/* HP Scanjet 3900 series - RTS8822 Core
|
||
|
||
Copyright (C) 2005-2013 Jonathan Bravo Lopez <jkdsoft@gmail.com>
|
||
|
||
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 <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h> /* memset() */
|
||
#include <time.h> /* clock() */
|
||
#include <math.h> /* truncf() */
|
||
#include <ctype.h> /* tolower() */
|
||
#include <unistd.h> /* usleep() */
|
||
#include <sys/types.h>
|
||
|
||
#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_transferred);
|
||
|
||
static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op,
|
||
SANE_Int buffer_size, SANE_Byte * buffer,
|
||
SANE_Int * transferred);
|
||
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;
|
||
|
||
memset (dev, 0, sizeof (struct st_device));
|
||
|
||
/* initial registers */
|
||
dev->init_regs = malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN);
|
||
if (dev->init_regs != NULL)
|
||
memset (dev->init_regs, 0, sizeof (SANE_Byte) * RT_BUFFER_LEN);
|
||
else
|
||
rst = ERROR;
|
||
|
||
if (rst == OK)
|
||
{
|
||
dev->scanning = malloc (sizeof (struct st_scanning));
|
||
if (dev->scanning != NULL)
|
||
memset (dev->scanning, 0, sizeof (struct st_scanning));
|
||
else
|
||
rst = ERROR;
|
||
}
|
||
|
||
if (rst == OK)
|
||
{
|
||
dev->Reading = malloc (sizeof (struct st_readimage));
|
||
if (dev->Reading != NULL)
|
||
memset (dev->Reading, 0, sizeof (struct st_readimage));
|
||
else
|
||
rst = ERROR;
|
||
}
|
||
|
||
if (rst == OK)
|
||
{
|
||
dev->Resize = malloc (sizeof (struct st_resize));
|
||
if (dev->Resize != NULL)
|
||
memset (dev->Resize, 0, sizeof (struct st_resize));
|
||
else
|
||
rst = ERROR;
|
||
}
|
||
|
||
if (rst == OK)
|
||
{
|
||
dev->status = malloc (sizeof (struct st_status));
|
||
if (dev->status != NULL)
|
||
memset (dev->status, 0, 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 opened 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;
|
||
|
||
memset (dev->chipset, 0, 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 appropriate 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 */
|
||
memset (&hwdcfg, 0, 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);
|
||
|
||
memset (&mycoords, 0, 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 channel 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 settings 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 */
|
||
memset (dev->init_regs, 0, 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) != 0)) ? 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 possible 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 milliseconds */
|
||
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 */
|
||
memset (color_sum, 0, sizeof (double) * buffersize);
|
||
memset (color_dif, 0, 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 */
|
||
memset (color_sum, 0, sizeof (double) * buffersize);
|
||
memset (color_dif, 0, 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 */
|
||
memset (color_sum, 0, sizeof (double) * buffersize);
|
||
memset (color_dif, 0, 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;
|
||
}
|
||
|
||
memset (dev->Reading, 0, 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 */
|
||
memset (&somebuffer, 0, 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_transferred)
|
||
{
|
||
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_transferred):\n",
|
||
buffer_size);
|
||
|
||
arg2 = arg2; /* silence gcc */
|
||
*bytes_transferred = 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, 60, 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_transferred += 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 as many bytes as possible */
|
||
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_transferred += iAmount;
|
||
|
||
/* if there isn't any data in DMABuffer we can point RDStart
|
||
to the beginning of DMABuffer */
|
||
if (rd->RDSize == 0)
|
||
rd->RDStart = rd->DMABuffer;
|
||
}
|
||
|
||
/* in case of all data is read we return OK with bytes_transferred = 0 */
|
||
if ((*bytes_transferred == 0)
|
||
|| ((rd->RDSize == 0) && (rd->ImageSize == 0)))
|
||
break;
|
||
}
|
||
|
||
if (rst == ERROR)
|
||
RTS_DMA_Cancel (dev);
|
||
}
|
||
|
||
DBG (DBG_FNC, "-> *bytes_transferred=%i\n", *bytes_transferred);
|
||
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 amount 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 */
|
||
memset (&hwdcfg, 0, 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 */
|
||
memset (&calbuffers, 0, 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 * transferred)
|
||
{
|
||
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 (transferred != NULL)
|
||
*transferred = 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 (transferred != NULL)
|
||
*transferred += 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 (transferred != NULL)
|
||
*transferred += 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)
|
||
{
|
||
memset (hwdcfg, 0, 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)
|
||
{
|
||
memset (myRegs, 0,
|
||
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 */
|
||
memset (&scancfg, 0, 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);
|
||
|
||
memset (&gain_offset, 0, 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 refers 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;
|
||
|
||
memset (&mymotor, 0, 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)
|
||
memset (fixed_black_shading[channel], 0, 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)
|
||
memset (fixed_white_shading[channel], 0, 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)
|
||
memset (buffer1, 0, 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)
|
||
memset (buffer1, 0, 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 */
|
||
memset (&dbvalue, 0, 6 * sizeof (double));
|
||
position = 0;
|
||
|
||
if (bytes_per_line > 0)
|
||
{
|
||
do
|
||
{
|
||
memset (&buff3, 0, 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 */
|
||
memset (&dbvalue, 0, 6 * sizeof (double));
|
||
position = 0;
|
||
|
||
if (bytes_per_line > 0)
|
||
{
|
||
do
|
||
{
|
||
memset (&buff2, 0, 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);
|
||
|
||
memset (&calibdata->gain_offset, 0, 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 values */
|
||
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)
|
||
memset (hp_gamma, 0, sizeof (struct st_gammatables));
|
||
else
|
||
rst = ERROR;
|
||
|
||
if (rst == OK)
|
||
{
|
||
RTS_Debug = malloc (sizeof (struct st_debug_opts));
|
||
if (RTS_Debug != NULL)
|
||
memset (RTS_Debug, 0, 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)
|
||
memset (default_gain_offset, 0, sizeof (struct st_gain_offset));
|
||
else
|
||
rst = ERROR;
|
||
}
|
||
|
||
if (rst == OK)
|
||
{
|
||
calibdata = malloc (sizeof (struct st_calibration_data));
|
||
if (calibdata != NULL)
|
||
memset (calibdata, 0, sizeof (struct st_calibration_data));
|
||
else
|
||
rst = ERROR;
|
||
}
|
||
|
||
if (rst == OK)
|
||
{
|
||
wshading = malloc (sizeof (struct st_shading));
|
||
if (wshading != NULL)
|
||
memset (wshading, 0, 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 coefficient */
|
||
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");
|
||
|
||
memset (&myCalibTable, 0, 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");
|
||
|
||
memset (&myCalibTable, 0, 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");
|
||
|
||
memset (&myCalibTable, 0, 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");
|
||
|
||
memset (&myCalibTable, 0, 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 */
|