1/* HP Scanjet 3900 series - RTS8822 Core
2
3   Copyright (C) 2005-2013 Jonathan Bravo Lopez <jkdsoft@gmail.com>
4
5   This file is part of the SANE package.
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License
9   as published by the Free Software Foundation; either version 2
10   of the License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
20   As a special exception, the authors of SANE give permission for
21   additional uses of the libraries contained in this release of SANE.
22
23   The exception is that, if you link a SANE library with other files
24   to produce an executable, this does not by itself cause the
25   resulting executable to be covered by the GNU General Public
26   License.  Your use of that executable is in no way restricted on
27   account of linking the SANE library code into it.
28
29   This exception does not, however, invalidate any other reasons why
30   the executable file might be covered by the GNU General Public
31   License.
32
33   If you submit changes to SANE to the maintainers to be included in
34   a subsequent release, you agree by submitting the changes that
35   those changes may be distributed with this exception intact.
36
37   If you write modifications of your own for SANE, it is your choice
38   whether to permit this exception to apply to your modifications.
39   If you do not wish that, delete this exception notice.
40*/
41
42
43/*
44 This code is still a bit ugly due to it's the result of applying
45 reverse engineering techniques to windows driver. So at this
46 moment what you see is exactly what windows driver does.
47 And so many global vars exist that will be erased when driver
48 is entirely debugged. There are some variables with unknown
49 purpose. So they have no meaning name in form v+address. I
50 hope to change their names when driver is debugged completely.
51*/
52
53#ifndef RTS8822_CORE
54
55#define RTS8822_CORE
56
57#define GetTickCount() (time(0) * 1000)
58#define min(A,B) (((A)<(B)) ? (A) : (B))
59#define max(A,B) (((A)>(B)) ? (A) : (B))
60#define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_))
61#define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4)
62
63#include <stdio.h>
64#include <stdlib.h>
65#include <string.h>		/* memset()   */
66#include <time.h>		/* clock()   */
67#include <math.h>		/* truncf()  */
68#include <ctype.h>		/* tolower() */
69#include <unistd.h>		/* usleep()  */
70#include <sys/types.h>
71
72#include "hp3900_types.c"
73#include "hp3900_debug.c"
74#include "hp3900_config.c"
75#include "hp3900_usb.c"
76
77/*-------------------- Exported function headers --------------------*/
78
79#ifdef developing
80static SANE_Int hp4370_prueba (struct st_device *dev);
81static void prueba (SANE_Byte * a);
82void shadingtest1 (struct st_device *dev, SANE_Byte * Regs,
83		   struct st_calibration *myCalib);
84static SANE_Int Calib_test (struct st_device *dev, SANE_Byte * Regs,
85			    struct st_calibration *myCalib,
86			    struct st_scanparams *scancfg);
87static SANE_Int Calib_BlackShading_jkd (struct st_device *dev,
88					SANE_Byte * Regs,
89					struct st_calibration *myCalib,
90					struct st_scanparams *scancfg);
91#endif
92
93/*static void show_diff(struct st_device *dev, SANE_Byte *original);*/
94
95/* functions to allocate and free space for a device */
96static struct st_device *RTS_Alloc (void);
97static void RTS_Free (struct st_device *dev);
98
99/* Scanner level commands */
100static SANE_Int RTS_Scanner_Init (struct st_device *dev);
101static SANE_Int RTS_Scanner_SetParams (struct st_device *dev,
102				       struct params *param);
103static SANE_Int RTS_Scanner_StartScan (struct st_device *dev);
104static void RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait);
105static void RTS_Scanner_End (struct st_device *dev);
106
107/* loading configuration functions */
108static SANE_Int Load_Buttons (struct st_device *dev);
109static SANE_Int Load_Chipset (struct st_device *dev);
110static SANE_Int Load_Config (struct st_device *dev);
111static SANE_Int Load_Constrains (struct st_device *dev);
112static SANE_Int Load_Motor (struct st_device *dev);
113static SANE_Int Load_MotorCurves (struct st_device *dev);
114static SANE_Int Load_Motormoves (struct st_device *dev);
115static SANE_Int Load_Scanmodes (struct st_device *dev);
116static SANE_Int Load_Sensor (struct st_device *dev);
117static SANE_Int Load_Timings (struct st_device *dev);
118
119/* freeing configuration functions */
120static void Free_Buttons (struct st_device *dev);
121static void Free_Chipset (struct st_device *dev);
122static void Free_Config (struct st_device *dev);
123static void Free_Constrains (struct st_device *dev);
124static void Free_Motor (struct st_device *dev);
125static void Free_MotorCurves (struct st_device *dev);
126static void Free_Motormoves (struct st_device *dev);
127static void Free_Scanmodes (struct st_device *dev);
128static void Free_Sensor (struct st_device *dev);
129static void Free_Timings (struct st_device *dev);
130static void Free_Vars (void);
131
132/* Functions to manage data */
133static SANE_Byte data_bitget (SANE_Byte * address, SANE_Int mask);
134static void data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data);
135static SANE_Int data_lsb_get (SANE_Byte * address, SANE_Int size);
136static void data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size);
137static void data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size);
138static void data_wide_bitset (SANE_Byte * address, SANE_Int mask,
139			      SANE_Int data);
140static SANE_Int data_swap_endianess (SANE_Int address, SANE_Int size);
141
142static SANE_Int Device_get (SANE_Int product, SANE_Int vendor);
143
144/* Chipset related commands */
145static SANE_Int Chipset_ID (struct st_device *dev);
146static SANE_Int Chipset_Name (struct st_device *dev, char *name,
147			      SANE_Int size);
148static SANE_Int Chipset_Reset (struct st_device *dev);
149
150/* Initializing functions */
151static SANE_Int Init_Registers (struct st_device *dev);
152static SANE_Int Init_USBData (struct st_device *dev);
153static SANE_Int Init_Vars (void);
154
155/* scanmode functions */
156static SANE_Int Scanmode_fitres (struct st_device *dev, SANE_Int scantype,
157				 SANE_Int colormode, SANE_Int resolution);
158static SANE_Int Scanmode_maxres (struct st_device *dev, SANE_Int scantype,
159				 SANE_Int colormode);
160static SANE_Int Scanmode_minres (struct st_device *dev, SANE_Int scantype,
161				 SANE_Int colormode);
162
163/* Chipset management useful commands*/
164static SANE_Int RTS_USBType (struct st_device *dev);
165static SANE_Byte RTS_Sensor_Type (USB_Handle usb_handle);
166static void RTS_DebugInit (void);
167static SANE_Int RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs,
168				SANE_Int channels);
169
170/* DMA management commands */
171static SANE_Int RTS_DMA_Cancel (struct st_device *dev);
172static SANE_Int RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs);
173static SANE_Int RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs,
174				     SANE_Int size, SANE_Int options);
175static SANE_Int RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs,
176				      SANE_Int size, SANE_Int options);
177static SANE_Int RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs,
178			      SANE_Int options, SANE_Int size,
179			      SANE_Byte * buffer);
180static SANE_Int RTS_DMA_Reset (struct st_device *dev);
181static SANE_Int RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs,
182				 SANE_Byte ramtype);
183static SANE_Int RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs);
184static SANE_Int RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs,
185			       SANE_Int options, SANE_Int size,
186			       SANE_Byte * buffer);
187
188/* EEPROM management commands */
189static SANE_Int RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address,
190				     SANE_Byte * data);
191static SANE_Int RTS_EEPROM_ReadInteger (USB_Handle usb_handle,
192					SANE_Int address, SANE_Int * data);
193static SANE_Int RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address,
194				     SANE_Int * data);
195static SANE_Int RTS_EEPROM_WriteBuffer (USB_Handle usb_handle,
196					SANE_Int address, SANE_Byte * data,
197					SANE_Int size);
198static SANE_Int RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address,
199				      SANE_Byte data);
200static SANE_Int RTS_EEPROM_WriteInteger (USB_Handle usb_handle,
201					 SANE_Int address, SANE_Int data);
202static SANE_Int RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address,
203				      SANE_Int data);
204
205static SANE_Int RTS_Execute (struct st_device *dev);
206static SANE_Int RTS_Warm_Reset (struct st_device *dev);
207static SANE_Byte RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs);
208
209static SANE_Int RTS_GetScanmode (struct st_device *dev, SANE_Int scantype,
210				 SANE_Int colormode, SANE_Int resolution);
211static SANE_Int RTS_GetImage (struct st_device *dev, SANE_Byte * Regs,
212			      struct st_scanparams *scancfg,
213			      struct st_gain_offset *gain_offset,
214			      SANE_Byte * buffer,
215			      struct st_calibration *myCalib,
216			      SANE_Int options, SANE_Int gainmode);
217static SANE_Int RTS_GetImage_GetBuffer (struct st_device *dev, double dSize,
218					SANE_Byte * buffer,
219					double *transferred);
220static SANE_Int RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer,
221				   struct st_scanparams *myvar,
222				   struct st_hwdconfig *hwdcfg);
223
224static SANE_Int RTS_isTmaAttached (struct st_device *dev);
225
226/* functions to wait for a process tp finish */
227static SANE_Int RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs);
228static SANE_Int RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs);
229
230/* functions to read/write control registers */
231static SANE_Int RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer);
232static SANE_Int RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer);
233
234/* functions to manage the scan counter */
235static SANE_Int RTS_ScanCounter_Inc (struct st_device *dev);
236static SANE_Int RTS_ScanCounter_Get (struct st_device *dev);
237
238/* functions to setup control registers */
239static SANE_Int RTS_Setup (struct st_device *dev, SANE_Byte * Regs,
240			   struct st_scanparams *myvar,
241			   struct st_hwdconfig *hwdcfg,
242			   struct st_gain_offset *gain_offset);
243static void RTS_Setup_Arrangeline (struct st_device *dev,
244				   struct st_hwdconfig *hwdcfg,
245				   SANE_Int colormode);
246static void RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs,
247				struct st_scanparams *scancfg,
248				SANE_Int mycolormode);
249static void RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop,
250			      SANE_Int width, SANE_Int height);
251static SANE_Int RTS_Setup_Depth (SANE_Byte * Regs,
252				 struct st_scanparams *scancfg,
253				 SANE_Int mycolormode);
254static void RTS_Setup_Exposure_Times (SANE_Byte * Regs,
255				      struct st_scanparams *scancfg,
256				      struct st_scanmode *sm);
257static void RTS_Setup_GainOffset (SANE_Byte * Regs,
258				  struct st_gain_offset *gain_offset);
259static void RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *lowcfg);
260static SANE_Int RTS_Setup_Line_Distances (struct st_device *dev,
261					  SANE_Byte * Regs,
262					  struct st_scanparams *scancfg,
263					  struct st_hwdconfig *hwdcfg,
264					  SANE_Int mycolormode,
265					  SANE_Int arrangeline);
266static SANE_Int RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs,
267				 struct st_scanparams *myvar,
268				 SANE_Int somevalue);
269static void RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs);
270static void RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming,
271				    SANE_Byte * Regs);
272static void RTS_Setup_Shading (SANE_Byte * Regs,
273			       struct st_scanparams *scancfg,
274			       struct st_hwdconfig *hwdcfg,
275			       SANE_Int bytes_per_line);
276
277static SANE_Int Scan_Start (struct st_device *dev);
278
279static void SetLock (USB_Handle usb_handle, SANE_Byte * Regs,
280		     SANE_Byte Enable);
281static SANE_Int fn3330 (struct st_device *dev, SANE_Byte * Regs,
282			struct st_cal2 *calbuffers,
283			SANE_Int sensorchannelcolor, SANE_Int * tablepos,
284			SANE_Int data);
285static SANE_Int fn3560 (USHORT * table, struct st_cal2 *calbuffers,
286			SANE_Int * tablepos);
287static SANE_Int fn3730 (struct st_device *dev, struct st_cal2 *calbuffers,
288			SANE_Byte * Regs, USHORT * table,
289			SANE_Int sensorchannelcolor, SANE_Int data);
290
291static SANE_Int Reading_CreateBuffers (struct st_device *dev);
292static SANE_Int Reading_DestroyBuffers (struct st_device *dev);
293static SANE_Int Reading_BufferSize_Get (struct st_device *dev,
294					SANE_Byte channels_per_dot,
295					SANE_Int channel_size);
296static SANE_Int Reading_BufferSize_Notify (struct st_device *dev,
297					   SANE_Int data, SANE_Int size);
298static SANE_Int Reading_Wait (struct st_device *dev,
299			      SANE_Byte Channels_per_dot,
300			      SANE_Byte Channel_size, SANE_Int size,
301			      SANE_Int * last_amount, SANE_Int seconds,
302			      SANE_Byte op);
303
304static SANE_Int Read_Image (struct st_device *dev, SANE_Int buffer_size,
305			    SANE_Byte * buffer, SANE_Int * transferred);
306static SANE_Int Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer,
307				  SANE_Int buffer_size,
308				  SANE_Int * transferred);
309static SANE_Int Read_Block (struct st_device *dev, SANE_Int buffer_size,
310			    SANE_Byte * buffer, SANE_Int * transferred);
311static SANE_Int Read_NonColor_Block (struct st_device *dev,
312				     SANE_Byte * buffer, SANE_Int buffer_size,
313				     SANE_Byte ColorMode,
314				     SANE_Int * transferred);
315
316/* Ref functions */
317static SANE_Int Refs_Analyze_Pattern (struct st_scanparams *scancfg,
318				      SANE_Byte * scanned_pattern,
319				      SANE_Int * ler1, SANE_Int ler1order,
320				      SANE_Int * ser1, SANE_Int ser1order);
321static SANE_Int Refs_Counter_Inc (struct st_device *dev);
322static SANE_Byte Refs_Counter_Load (struct st_device *dev);
323static SANE_Int Refs_Counter_Save (struct st_device *dev, SANE_Byte data);
324static SANE_Int Refs_Detect (struct st_device *dev, SANE_Byte * Regs,
325			     SANE_Int resolution_x, SANE_Int resolution_y,
326			     SANE_Int * x, SANE_Int * y);
327static SANE_Int Refs_Load (struct st_device *dev, SANE_Int * x, SANE_Int * y);
328static SANE_Int Refs_Save (struct st_device *dev, SANE_Int left_leading,
329			   SANE_Int start_pos);
330static SANE_Int Refs_Set (struct st_device *dev, SANE_Byte * Regs,
331			  struct st_scanparams *myscan);
332
333/* Coordinates' constrains functions */
334static SANE_Int Constrains_Check (struct st_device *dev, SANE_Int Resolution,
335				  SANE_Int scantype,
336				  struct st_coords *mycoords);
337static struct st_coords *Constrains_Get (struct st_device *dev,
338					 SANE_Byte scantype);
339
340/* Gain and offset functions */
341static SANE_Int GainOffset_Clear (struct st_device *dev);
342static SANE_Int GainOffset_Get (struct st_device *dev);
343static SANE_Int GainOffset_Save (struct st_device *dev, SANE_Int * offset,
344				 SANE_Byte * gain);
345static SANE_Int GainOffset_Counter_Inc (struct st_device *dev,
346					SANE_Int * arg1);
347static SANE_Byte GainOffset_Counter_Load (struct st_device *dev);
348static SANE_Int GainOffset_Counter_Save (struct st_device *dev,
349					 SANE_Byte data);
350
351/* Gamma functions*/
352static SANE_Int Gamma_AllocTable (SANE_Byte * table);
353static SANE_Int Gamma_Apply (struct st_device *dev, SANE_Byte * Regs,
354			     struct st_scanparams *scancfg,
355			     struct st_hwdconfig *hwdcfg,
356			     struct st_gammatables *mygamma);
357static void Gamma_FreeTables (void);
358static SANE_Int Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs,
359				  SANE_Byte * gammatable, SANE_Int size);
360static SANE_Int Gamma_GetTables (struct st_device *dev,
361				 SANE_Byte * Gamma_buffer);
362
363/* Lamp functions */
364static SANE_Byte Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution,
365				   SANE_Byte scantype);
366static void Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs,
367			      SANE_Int resolution, SANE_Byte gainmode);
368static SANE_Int Lamp_PWM_DutyCycle_Get (struct st_device *dev,
369					SANE_Int * data);
370static SANE_Int Lamp_PWM_DutyCycle_Set (struct st_device *dev,
371					SANE_Int duty_cycle);
372static SANE_Int Lamp_PWM_Setup (struct st_device *dev, SANE_Int lamp);
373static SANE_Int Lamp_PWM_use (struct st_device *dev, SANE_Int enable);
374static SANE_Int Lamp_PWM_CheckStable (struct st_device *dev,
375				      SANE_Int resolution, SANE_Int lamp);
376static SANE_Int Lamp_PWM_Save (struct st_device *dev, SANE_Int fixedpwm);
377static SANE_Int Lamp_PWM_SaveStatus (struct st_device *dev, SANE_Byte status);
378static SANE_Int Lamp_Status_Get (struct st_device *dev, SANE_Byte * flb_lamp,
379				 SANE_Byte * tma_lamp);
380static SANE_Int Lamp_Status_Set (struct st_device *dev, SANE_Byte * Regs,
381				 SANE_Int turn_on, SANE_Int lamp);
382static SANE_Int Lamp_Status_Timer_Set (struct st_device *dev,
383				       SANE_Int minutes);
384static SANE_Int Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs,
385			     SANE_Int lamp, SANE_Int resolution);
386
387/* Head related functions */
388static SANE_Int Head_IsAtHome (struct st_device *dev, SANE_Byte * Regs);
389static SANE_Int Head_ParkHome (struct st_device *dev, SANE_Int bWait,
390			       SANE_Int movement);
391static SANE_Int Head_Relocate (struct st_device *dev, SANE_Int speed,
392			       SANE_Int direction, SANE_Int ypos);
393
394/* Motor functions */
395static SANE_Byte *Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten,
396				 SANE_Int step);
397static SANE_Int Motor_Change (struct st_device *dev, SANE_Byte * buffer,
398			      SANE_Byte value);
399static SANE_Int Motor_GetFromResolution (SANE_Int resolution);
400static SANE_Int Motor_Move (struct st_device *dev, SANE_Byte * Regs,
401			    struct st_motormove *mymotor,
402			    struct st_motorpos *mtrpos);
403static void Motor_Release (struct st_device *dev);
404static SANE_Int Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs,
405				   SANE_Int mysetting);
406static SANE_Int Motor_Curve_Equal (struct st_device *dev,
407				   SANE_Int motorsetting, SANE_Int direction,
408				   SANE_Int curve1, SANE_Int curve2);
409static void Motor_Curve_Free (struct st_motorcurve **motorcurves,
410			      SANE_Int * mtc_count);
411static struct st_curve *Motor_Curve_Get (struct st_device *dev,
412					 SANE_Int motorcurve,
413					 SANE_Int direction, SANE_Int itype);
414static struct st_motorcurve **Motor_Curve_Parse (SANE_Int * mtc_count,
415						 SANE_Int * buffer);
416
417/* Functions to arrange scanned lines */
418static SANE_Int Arrange_Colour (struct st_device *dev, SANE_Byte * buffer,
419				SANE_Int buffer_size, SANE_Int * transferred);
420static SANE_Int Arrange_Compose (struct st_device *dev, SANE_Byte * buffer,
421				 SANE_Int buffer_size,
422				 SANE_Int * transferred);
423static SANE_Int Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer,
424				   SANE_Int buffer_size,
425				   SANE_Int * transferred);
426
427/* Composing RGB triplet functions */
428static void Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2,
429			  SANE_Byte * buffer, SANE_Int channels_count);
430static void Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2,
431			     SANE_Byte * buffer, SANE_Int channels_count);
432static void Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed,
433				   SANE_Byte * pGreen, SANE_Byte * pBlue,
434				   SANE_Byte * buffer, SANE_Int dots);
435static void Triplet_Compose_HRes (SANE_Byte * pPointer1,
436				  SANE_Byte * pPointer2,
437				  SANE_Byte * pPointer3,
438				  SANE_Byte * pPointer4,
439				  SANE_Byte * pPointer5,
440				  SANE_Byte * pPointer6, SANE_Byte * buffer,
441				  SANE_Int Width);
442static void Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen,
443				  SANE_Byte * pBlue, SANE_Byte * buffer,
444				  SANE_Int dots);
445static void Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed,
446				  SANE_Byte * pGreen, SANE_Byte * pBlue,
447				  SANE_Byte * buffer, SANE_Int Width);
448static void Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1,
449				 SANE_Byte * pBlue1, SANE_Byte * pRed2,
450				 SANE_Byte * pGreen2, SANE_Byte * pBlue2,
451				 SANE_Byte * buffer, SANE_Int Width);
452static void Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer,
453				 SANE_Byte * pChannel1, SANE_Byte * pChannel2,
454				 SANE_Byte * pChannel3);
455
456/* Timing functions */
457static SANE_Int Timing_SetLinearImageSensorClock (SANE_Byte * Regs,
458						  struct st_cph *cph);
459
460/* Functions used to resize retrieved image */
461static SANE_Int Resize_Start (struct st_device *dev, SANE_Int * transferred);
462static SANE_Int Resize_CreateBuffers (struct st_device *dev, SANE_Int size1,
463				      SANE_Int size2, SANE_Int size3);
464static SANE_Int Resize_DestroyBuffers (struct st_device *dev);
465static SANE_Int Resize_Increase (SANE_Byte * to_buffer,
466				 SANE_Int to_resolution, SANE_Int to_width,
467				 SANE_Byte * from_buffer,
468				 SANE_Int from_resolution,
469				 SANE_Int from_width, SANE_Int myresize_mode);
470static SANE_Int Resize_Decrease (SANE_Byte * to_buffer,
471				 SANE_Int to_resolution, SANE_Int to_width,
472				 SANE_Byte * from_buffer,
473				 SANE_Int from_resolution,
474				 SANE_Int from_width, SANE_Int myresize_mode);
475
476/* Scanner buttons support */
477static SANE_Int Buttons_Count (struct st_device *dev);
478static SANE_Int Buttons_Enable (struct st_device *dev);
479static SANE_Int Buttons_Order (struct st_device *dev, SANE_Int mask);
480static SANE_Int Buttons_Status (struct st_device *dev);
481static SANE_Int Buttons_Released (struct st_device *dev);
482
483/* Calibration functions */
484static SANE_Int Calib_CreateBuffers (struct st_device *dev,
485				     struct st_calibration *buffer,
486				     SANE_Int my14b4);
487static SANE_Int Calib_CreateFixedBuffers (void);
488static void Calib_FreeBuffers (struct st_calibration *caltables);
489static void Calib_LoadCut (struct st_device *dev,
490			   struct st_scanparams *scancfg, SANE_Int scantype,
491			   struct st_calibration_config *calibcfg);
492static SANE_Int Calib_AdcGain (struct st_device *dev,
493			       struct st_calibration_config *calibcfg,
494			       SANE_Int arg2, SANE_Int gainmode);
495static SANE_Int Calib_AdcOffsetRT (struct st_device *dev,
496				   struct st_calibration_config *calibcfg,
497				   SANE_Int value);
498static SANE_Int Calib_BlackShading (struct st_device *dev,
499				    struct st_calibration_config *calibcfg,
500				    struct st_calibration *myCalib,
501				    SANE_Int gainmode);
502static SANE_Int Calib_BWShading (struct st_calibration_config *calibcfg,
503				 struct st_calibration *myCalib,
504				 SANE_Int gainmode);
505static SANE_Int Calib_WhiteShading_3 (struct st_device *dev,
506				      struct st_calibration_config *calibcfg,
507				      struct st_calibration *myCalib,
508				      SANE_Int gainmode);
509static void Calibrate_Free (struct st_cal2 *calbuffers);
510static SANE_Int Calibrate_Malloc (struct st_cal2 *calbuffers,
511				  SANE_Byte * Regs,
512				  struct st_calibration *myCalib,
513				  SANE_Int somelength);
514static SANE_Int Calib_ReadTable (struct st_device *dev, SANE_Byte * table,
515				 SANE_Int size, SANE_Int data);
516static SANE_Int Calib_WriteTable (struct st_device *dev, SANE_Byte * table,
517				  SANE_Int size, SANE_Int data);
518static SANE_Int Calib_LoadConfig (struct st_device *dev,
519				  struct st_calibration_config *calibcfg,
520				  SANE_Int scantype, SANE_Int resolution,
521				  SANE_Int bitmode);
522static SANE_Int Calib_PAGain (struct st_device *dev,
523			      struct st_calibration_config *calibcfg,
524			      SANE_Int gainmode);
525static SANE_Int Calibration (struct st_device *dev, SANE_Byte * Regs,
526			     struct st_scanparams *scancfg,
527			     struct st_calibration *myCalib, SANE_Int value);
528
529/* function for white shading correction */
530static SANE_Int WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs,
531				    struct st_calibration *myCalib,
532				    struct st_scanparams *scancfg);
533static void WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr,
534			      SANE_Int size, SANE_Int depth);
535
536/* functions for shading calibration */
537static SANE_Int Shading_apply (struct st_device *dev, SANE_Byte * Regs,
538			       struct st_scanparams *myvar,
539			       struct st_calibration *myCalib);
540static SANE_Int Shading_black_apply (struct st_device *dev, SANE_Byte * Regs,
541				     SANE_Int channels,
542				     struct st_calibration *myCalib,
543				     struct st_cal2 *calbuffers);
544static SANE_Int Shading_white_apply (struct st_device *dev, SANE_Byte * Regs,
545				     SANE_Int channels,
546				     struct st_calibration *myCalib,
547				     struct st_cal2 *calbuffers);
548
549/* Spread-Spectrum Clock Generator functions */
550static SANE_Int SSCG_Enable (struct st_device *dev);
551
552static void Split_into_12bit_channels (SANE_Byte * destino,
553				       SANE_Byte * fuente, SANE_Int size);
554static SANE_Int Scan_Read_BufferA (struct st_device *dev,
555				   SANE_Int buffer_size, SANE_Int arg2,
556				   SANE_Byte * pBuffer,
557				   SANE_Int * bytes_transferred);
558
559static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op,
560				SANE_Int buffer_size, SANE_Byte * buffer,
561				SANE_Int * transferred);
562static SANE_Int Get_PAG_Value (SANE_Byte scantype, SANE_Byte color);
563static SANE_Int GetOneLineInfo (struct st_device *dev, SANE_Int resolution,
564				SANE_Int * maximus, SANE_Int * minimus,
565				double *average);
566
567static SANE_Int Load_StripCoords (SANE_Int scantype, SANE_Int * ypos,
568				  SANE_Int * xpos);
569
570/*static SANE_Int Free_Fixed_CalBuffer(void);*/
571static SANE_Int SetMultiExposure (struct st_device *dev, SANE_Byte * Regs);
572
573static void Set_E950_Mode (struct st_device *dev, SANE_Byte mode);
574
575static SANE_Int LoadImagingParams (struct st_device *dev, SANE_Int inifile);
576
577static SANE_Int SetScanParams (struct st_device *dev, SANE_Byte * Regs,
578			       struct st_scanparams *scancfg,
579			       struct st_hwdconfig *hwdcfg);
580static SANE_Int IsScannerLinked (struct st_device *dev);
581
582static SANE_Int Read_FE3E (struct st_device *dev, SANE_Byte * destino);
583
584static double get_shrd (double value, SANE_Int desp);
585static char get_byte (double value);
586/*static SANE_Int RTS8822_GetRegisters(SANE_Byte *buffer);*/
587
588/* ----------------- Implementation ------------------*/
589
590static void
591RTS_Free (struct st_device *dev)
592{
593  /* this function frees space of devices's variable */
594
595  if (dev != NULL)
596    {
597      /* next function shouldn't be necessary but I can NOT assure that other
598         programmers will call Free_Config before this function */
599      Free_Config (dev);
600
601      if (dev->init_regs != NULL)
602	free (dev->init_regs);
603
604      if (dev->Resize != NULL)
605	free (dev->Resize);
606
607      if (dev->Reading != NULL)
608	free (dev->Reading);
609
610      if (dev->scanning != NULL)
611	free (dev->scanning);
612
613      if (dev->status != NULL)
614	free (dev->status);
615
616      free (dev);
617    }
618}
619
620static struct st_device *
621RTS_Alloc ()
622{
623  /* this function allocates space for device's variable */
624
625  struct st_device *dev = NULL;
626
627  dev = malloc (sizeof (struct st_device));
628  if (dev != NULL)
629    {
630      SANE_Int rst = OK;
631
632      memset (dev, 0, sizeof (struct st_device));
633
634      /* initial registers */
635      dev->init_regs = malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN);
636      if (dev->init_regs != NULL)
637	memset (dev->init_regs, 0, sizeof (SANE_Byte) * RT_BUFFER_LEN);
638      else
639	rst = ERROR;
640
641      if (rst == OK)
642	{
643	  dev->scanning = malloc (sizeof (struct st_scanning));
644	  if (dev->scanning != NULL)
645	    memset (dev->scanning, 0, sizeof (struct st_scanning));
646	  else
647	    rst = ERROR;
648	}
649
650      if (rst == OK)
651	{
652	  dev->Reading = malloc (sizeof (struct st_readimage));
653	  if (dev->Reading != NULL)
654	    memset (dev->Reading, 0, sizeof (struct st_readimage));
655	  else
656	    rst = ERROR;
657	}
658
659      if (rst == OK)
660	{
661	  dev->Resize = malloc (sizeof (struct st_resize));
662	  if (dev->Resize != NULL)
663	    memset (dev->Resize, 0, sizeof (struct st_resize));
664	  else
665	    rst = ERROR;
666	}
667
668      if (rst == OK)
669	{
670	  dev->status = malloc (sizeof (struct st_status));
671	  if (dev->status != NULL)
672	    memset (dev->status, 0, sizeof (struct st_status));
673	  else
674	    rst = ERROR;
675	}
676
677      /* if something fails, free space */
678      if (rst != OK)
679	{
680	  RTS_Free (dev);
681	  dev = NULL;
682	}
683    }
684
685  return dev;
686}
687
688static void
689RTS_Scanner_End (struct st_device *dev)
690{
691  Gamma_FreeTables ();
692  Free_Config (dev);
693  Free_Vars ();
694}
695
696static SANE_Int
697Device_get (SANE_Int product, SANE_Int vendor)
698{
699  return cfg_device_get (product, vendor);
700}
701
702static SANE_Int
703RTS_Scanner_Init (struct st_device *dev)
704{
705  SANE_Int rst;
706
707  DBG (DBG_FNC, "> RTS_Scanner_Init:\n");
708  DBG (DBG_FNC, "> Backend version: %s\n", BACKEND_VRSN);
709
710  rst = ERROR;
711
712  /* gets usb type of this scanner if it's not already set by user */
713  if (RTS_Debug->usbtype == -1)
714    RTS_Debug->usbtype = RTS_USBType (dev);
715
716  if (RTS_Debug->usbtype != ERROR)
717    {
718      DBG (DBG_FNC, " -> Chipset model ID: %i\n", Chipset_ID (dev));
719
720      Chipset_Reset (dev);
721
722      if (Load_Config (dev) == OK)
723	{
724	  if (IsScannerLinked (dev) == OK)
725	    {
726	      Set_E950_Mode (dev, 0);
727	      Gamma_AllocTable (NULL);
728	      rst = OK;
729	    }
730	  else
731	    Free_Config (dev);
732	}
733    }
734
735  return rst;
736}
737
738static SANE_Int
739RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer)
740{
741  SANE_Int rst = ERROR;
742
743  if (buffer != NULL)
744    rst =
745      Write_Buffer (usb_handle, 0xe800, buffer,
746		    RT_BUFFER_LEN * sizeof (SANE_Byte));
747
748  return rst;
749}
750
751static SANE_Int
752RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer)
753{
754  SANE_Int rst = ERROR;
755
756  if (buffer != NULL)
757    rst =
758      Read_Buffer (usb_handle, 0xe800, buffer,
759		   RT_BUFFER_LEN * sizeof (SANE_Byte));
760
761  return rst;
762}
763
764static void
765SetLock (USB_Handle usb_handle, SANE_Byte * Regs, SANE_Byte Enable)
766{
767  SANE_Byte lock;
768
769  DBG (DBG_FNC, "+ SetLock(*Regs, Enable=%i):\n", Enable);
770
771  if (Regs == NULL)
772    {
773      if (Read_Byte (usb_handle, 0xee00, &lock) != OK)
774	lock = 0;
775    }
776  else
777    lock = Regs[0x600];
778
779  if (Enable == FALSE)
780    lock &= 0xfb;
781  else
782    lock |= 4;
783
784  if (Regs != NULL)
785    Regs[0x600] = lock;
786
787  Write_Byte (usb_handle, 0xee00, lock);
788
789  DBG (DBG_FNC, "- SetLock\n");
790}
791
792static void
793Set_E950_Mode (struct st_device *dev, SANE_Byte mode)
794{
795  SANE_Int data;
796
797  DBG (DBG_FNC, "+ Set_E950_Mode(mode=%i):\n", mode);
798
799  if (Read_Word (dev->usb_handle, 0xe950, &data) == OK)
800    {
801      data = (mode == 0) ? data & 0xffbf : data | 0x40;
802      Write_Word (dev->usb_handle, 0xe950, data);
803    }
804
805  DBG (DBG_FNC, "- Set_E950_Mode\n");
806}
807
808static struct st_curve *
809Motor_Curve_Get (struct st_device *dev, SANE_Int motorcurve,
810		 SANE_Int direction, SANE_Int itype)
811{
812  struct st_curve *rst = NULL;
813
814  if (dev != NULL)
815    {
816      if ((dev->mtrsetting != NULL) && (motorcurve < dev->mtrsetting_count))
817	{
818	  struct st_motorcurve *mtc = dev->mtrsetting[motorcurve];
819
820	  if (mtc != NULL)
821	    {
822	      if ((mtc->curve != NULL) && (mtc->curve_count > 0))
823		{
824		  struct st_curve *crv;
825		  SANE_Int a = 0;
826
827		  while (a < mtc->curve_count)
828		    {
829		      /* get each curve */
830		      crv = mtc->curve[a];
831		      if (crv != NULL)
832			{
833			  /* check direction and type */
834			  if ((crv->crv_speed == direction)
835			      && (crv->crv_type == itype))
836			    {
837			      /* found ! */
838			      rst = crv;
839			      break;
840			    }
841			}
842		      a++;
843		    }
844		}
845	    }
846	}
847    }
848
849  return rst;
850}
851
852static SANE_Int
853Motor_Curve_Equal (struct st_device *dev, SANE_Int motorsetting,
854		   SANE_Int direction, SANE_Int curve1, SANE_Int curve2)
855{
856  /* compares two curves of the same direction
857     returns TRUE if both buffers are equal */
858
859  SANE_Int rst = FALSE;
860  struct st_curve *crv1 =
861    Motor_Curve_Get (dev, motorsetting, direction, curve1);
862  struct st_curve *crv2 =
863    Motor_Curve_Get (dev, motorsetting, direction, curve2);
864
865  if ((crv1 != NULL) && (crv2 != NULL))
866    {
867      if (crv1->step_count == crv2->step_count)
868	{
869	  rst = TRUE;
870
871	  if (crv1->step_count > 0)
872	    {
873	      SANE_Int a = 0;
874
875	      while ((a < crv1->step_count) && (rst == TRUE))
876		{
877		  rst = (crv1->step[a] == crv2->step[a]) ? TRUE : FALSE;
878		  a++;
879		}
880	    }
881	}
882    }
883
884  return rst;
885}
886
887static struct st_motorcurve **
888Motor_Curve_Parse (SANE_Int * mtc_count, SANE_Int * buffer)
889{
890  /* this function parses motorcurve buffer to get all motor settings */
891  struct st_motorcurve **rst = NULL;
892
893  *mtc_count = 0;
894
895  if (buffer != NULL)
896    {
897      /* phases:
898         -1 : null phase
899         0 :
900         -3 : initial config
901       */
902      struct st_motorcurve *mtc = NULL;
903      SANE_Int phase;
904
905      phase = -1;
906      while (*buffer != -1)
907	{
908	  if (*buffer == -2)
909	    {
910	      /* end of motorcurve */
911	      /* complete any opened phase */
912	      /* close phase */
913	      phase = -1;
914	    }
915	  else
916	    {
917	      /* step */
918	      if (phase == -1)
919		{
920		  /* new motorcurve */
921		  phase = 0;
922		  mtc =
923		    (struct st_motorcurve *)
924		    malloc (sizeof (struct st_motorcurve));
925		  if (mtc != NULL)
926		    {
927		      *mtc_count += 1;
928		      rst =
929			realloc (rst,
930				 sizeof (struct st_motorcurve **) *
931				 *mtc_count);
932		      if (rst != NULL)
933			{
934			  rst[*mtc_count - 1] = mtc;
935			  memset (mtc, 0, sizeof (struct st_motorcurve));
936			  phase = -3;	/* initial config */
937			}
938		      else
939			{
940			  /* memory error */
941			  *mtc_count = 0;
942			  break;
943			}
944		    }
945		  else
946		    break;	/* some error */
947		}
948
949	      if (mtc != NULL)
950		{
951		  switch (phase)
952		    {
953		    case -3:	/* initial config */
954		      mtc->mri = *(buffer);
955		      mtc->msi = *(buffer + 1);
956		      mtc->skiplinecount = *(buffer + 2);
957		      mtc->motorbackstep = *(buffer + 3);
958		      buffer += 3;
959
960		      phase = -4;
961		      break;
962
963		    case -4:
964		      /**/
965		      {
966			/* create new step curve */
967			struct st_curve *curve =
968			  malloc (sizeof (struct st_curve));
969			if (curve != NULL)
970			  {
971			    /* add to step curve list */
972			    mtc->curve =
973			      (struct st_curve **) realloc (mtc->curve,
974							    sizeof (struct
975								    st_curve
976								    **) *
977							    (mtc->
978							     curve_count +
979							     1));
980			    if (mtc->curve != NULL)
981			      {
982				mtc->curve_count++;
983				mtc->curve[mtc->curve_count - 1] = curve;
984
985				memset (curve, 0, sizeof (struct st_curve));
986				/* read crv speed and type */
987				curve->crv_speed = *buffer;
988				curve->crv_type = *(buffer + 1);
989				buffer += 2;
990
991				/* get length of step buffer */
992				while (*(buffer + curve->step_count) != 0)
993				  curve->step_count++;
994
995				if (curve->step_count > 0)
996				  {
997				    /* allocate step buffer */
998				    curve->step =
999				      (SANE_Int *) malloc (sizeof (SANE_Int) *
1000							   curve->step_count);
1001				    if (curve->step != NULL)
1002				      {
1003					memcpy (curve->step, buffer,
1004						sizeof (SANE_Int) *
1005						curve->step_count);
1006					buffer += curve->step_count;
1007				      }
1008				    else
1009				      curve->step_count = 0;
1010				  }
1011			      }
1012			    else
1013			      {
1014				mtc->curve_count = 0;
1015				free (curve);
1016			      }
1017			  }
1018			else
1019			  break;
1020		      }
1021		      break;
1022		    }
1023		}
1024	    }
1025	  buffer++;
1026	}
1027    }
1028
1029  return rst;
1030}
1031
1032static void
1033Motor_Curve_Free (struct st_motorcurve **motorcurves, SANE_Int * mtc_count)
1034{
1035  if ((motorcurves != NULL) && (mtc_count != NULL))
1036    {
1037      struct st_motorcurve *mtc;
1038      struct st_curve *curve;
1039
1040      while (*mtc_count > 0)
1041	{
1042	  mtc = motorcurves[*mtc_count - 1];
1043	  if (mtc != NULL)
1044	    {
1045	      if (mtc->curve != NULL)
1046		{
1047		  while (mtc->curve_count > 0)
1048		    {
1049		      curve = mtc->curve[mtc->curve_count - 1];
1050		      if (curve != NULL)
1051			{
1052			  if (curve->step != NULL)
1053			    free (curve->step);
1054
1055			  free (curve);
1056			}
1057		      mtc->curve_count--;
1058		    }
1059		}
1060	      free (mtc);
1061	    }
1062	  *mtc_count -= 1;
1063	}
1064
1065      free (motorcurves);
1066    }
1067}
1068
1069static SANE_Byte
1070RTS_Sensor_Type (USB_Handle usb_handle)
1071{
1072  /*
1073     Returns sensor type
1074     01 = CCD
1075     00 = CIS
1076   */
1077
1078  SANE_Int a, b, c;
1079  SANE_Byte rst;
1080
1081  DBG (DBG_FNC, "+ RTS_Sensor_Type:\n");
1082
1083  a = b = c = 0;
1084
1085  /* Save data first */
1086  Read_Word (usb_handle, 0xe950, &a);
1087  Read_Word (usb_handle, 0xe956, &b);
1088
1089  /* Enables GPIO 0xe950 writing directly 0x13ff */
1090  Write_Word (usb_handle, 0xe950, 0x13ff);
1091  /* Sets GPIO 0xe956 writing 0xfcf0 */
1092  Write_Word (usb_handle, 0xe956, 0xfcf0);
1093  /* Makes a sleep of 200 ms */
1094  usleep (1000 * 200);
1095  /* Get GPIO 0xe968 */
1096  Read_Word (usb_handle, 0xe968, &c);
1097  /* Restore data */
1098  Write_Word (usb_handle, 0xe950, a);
1099  Write_Word (usb_handle, 0xe956, b);
1100
1101  rst = ((_B1 (c) & 1) == 0) ? CCD_SENSOR : CIS_SENSOR;
1102
1103  DBG (DBG_FNC, "- RTS_Sensor_Type: %s\n",
1104       (rst == CCD_SENSOR) ? "CCD" : "CIS");
1105
1106  return rst;
1107}
1108
1109static void
1110Free_Scanmodes (struct st_device *dev)
1111{
1112  DBG (DBG_FNC, "> Free_Scanmodes\n");
1113
1114  if (dev->scanmodes != NULL)
1115    {
1116      if (dev->scanmodes_count > 0)
1117	{
1118	  SANE_Int a;
1119	  for (a = 0; a < dev->scanmodes_count; a++)
1120	    if (dev->scanmodes[a] != NULL)
1121	      free (dev->scanmodes[a]);
1122	}
1123
1124      free (dev->scanmodes);
1125      dev->scanmodes = NULL;
1126    }
1127
1128  dev->scanmodes_count = 0;
1129}
1130
1131static SANE_Int
1132Load_Scanmodes (struct st_device *dev)
1133{
1134  SANE_Int rst = OK;
1135  SANE_Int a, b;
1136  struct st_scanmode reg, *mode;
1137
1138  DBG (DBG_FNC, "> Load_Scanmodes\n");
1139
1140  if ((dev->scanmodes != NULL) || (dev->scanmodes_count > 0))
1141    Free_Scanmodes (dev);
1142
1143  a = 0;
1144  while ((cfg_scanmode_get (dev->sensorcfg->type, a, &reg) == OK)
1145	 && (rst == OK))
1146    {
1147      mode = (struct st_scanmode *) malloc (sizeof (struct st_scanmode));
1148      if (mode != NULL)
1149	{
1150	  memcpy (mode, &reg, sizeof (struct st_scanmode));
1151
1152	  for (b = 0; b < 3; b++)
1153	    {
1154	      if (mode->mexpt[b] == 0)
1155		{
1156		  mode->mexpt[b] = mode->ctpc;
1157		  if (mode->multiexposure != 1)
1158		    mode->expt[b] = mode->ctpc;
1159		}
1160	    }
1161
1162	  mode->ctpc = ((mode->ctpc + 1) * mode->multiexposure) - 1;
1163
1164	  dev->scanmodes =
1165	    (struct st_scanmode **) realloc (dev->scanmodes,
1166					     (dev->scanmodes_count +
1167					      1) *
1168					     sizeof (struct st_scanmode **));
1169	  if (dev->scanmodes != NULL)
1170	    {
1171	      dev->scanmodes[dev->scanmodes_count] = mode;
1172	      dev->scanmodes_count++;
1173	    }
1174	  else
1175	    rst = ERROR;
1176	}
1177      else
1178	rst = ERROR;
1179
1180      a++;
1181    }
1182
1183  if (rst == ERROR)
1184    Free_Scanmodes (dev);
1185
1186  DBG (DBG_FNC, " -> Found %i scanmodes\n", dev->scanmodes_count);
1187  dbg_scanmodes (dev);
1188
1189  return rst;
1190}
1191
1192static void
1193Free_Config (struct st_device *dev)
1194{
1195  DBG (DBG_FNC, "+ Free_Config\n");
1196
1197  /* free buttons */
1198  Free_Buttons (dev);
1199
1200  /* free motor general configuration */
1201  Free_Motor (dev);
1202
1203  /* free sensor main configuration */
1204  Free_Sensor (dev);
1205
1206  /* free ccd sensor timing tables */
1207  Free_Timings (dev);
1208
1209  /* free motor curves */
1210  Free_MotorCurves (dev);
1211
1212  /* free motor movements */
1213  Free_Motormoves (dev);
1214
1215  /* free scan modes */
1216  Free_Scanmodes (dev);
1217
1218  /* free constrains */
1219  Free_Constrains (dev);
1220
1221  /* free chipset configuration */
1222  Free_Chipset (dev);
1223
1224  DBG (DBG_FNC, "- Free_Config\n");
1225}
1226
1227static void
1228Free_Chipset (struct st_device *dev)
1229{
1230  DBG (DBG_FNC, "> Free_Chipset\n");
1231
1232  if (dev->chipset != NULL)
1233    {
1234      if (dev->chipset->name != NULL)
1235	free (dev->chipset->name);
1236
1237      free (dev->chipset);
1238      dev->chipset = NULL;
1239    }
1240}
1241
1242static SANE_Int
1243Load_Chipset (struct st_device *dev)
1244{
1245  SANE_Int rst = ERROR;
1246
1247  DBG (DBG_FNC, "> Load_Chipset\n");
1248
1249  if (dev->chipset != NULL)
1250    Free_Chipset (dev);
1251
1252  dev->chipset = malloc (sizeof (struct st_chip));
1253  if (dev->chipset != NULL)
1254    {
1255      SANE_Int model;
1256
1257      memset (dev->chipset, 0, sizeof (struct st_chip));
1258
1259      /* get chipset model of selected scanner */
1260      model = cfg_chipset_model_get (RTS_Debug->dev_model);
1261
1262      /* get configuration for selected chipset */
1263      rst = cfg_chipset_get (model, dev->chipset);
1264    }
1265
1266  /* if rst == ERROR may be related to allocating space for chipset name */
1267
1268  return rst;
1269}
1270
1271static SANE_Int
1272Load_Config (struct st_device *dev)
1273{
1274  DBG (DBG_FNC, "+ Load_Config\n");
1275
1276  /* load chipset configuration */
1277  Load_Chipset (dev);
1278
1279  /* load scanner's buttons */
1280  Load_Buttons (dev);
1281
1282  /* load scanner area constrains */
1283  Load_Constrains (dev);
1284
1285  /* load motor general configuration */
1286  Load_Motor (dev);
1287
1288  /* load sensor main configuration */
1289  Load_Sensor (dev);
1290
1291  if (dev->sensorcfg->type == -1)
1292    /* get sensor from gpio */
1293    dev->sensorcfg->type = RTS_Sensor_Type (dev->usb_handle);
1294
1295  /* load ccd sensor timing tables */
1296  Load_Timings (dev);
1297
1298  /* load motor curves */
1299  Load_MotorCurves (dev);
1300
1301  /* load motor movements */
1302  Load_Motormoves (dev);
1303
1304  /* load scan modes */
1305  Load_Scanmodes (dev);
1306
1307  /* deprecated */
1308  if (dev->sensorcfg->type == CCD_SENSOR)
1309    /* ccd */ usbfile =
1310      (RTS_Debug->usbtype == USB20) ? T_RTINIFILE : T_USB1INIFILE;
1311  else				/* cis */
1312    usbfile = (RTS_Debug->usbtype == USB20) ? S_RTINIFILE : S_USB1INIFILE;
1313
1314  scantype = ST_NORMAL;
1315
1316  pwmlamplevel = get_value (SCAN_PARAM, PWMLAMPLEVEL, 1, usbfile);
1317
1318  arrangeline2 = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, usbfile);
1319
1320  shadingbase = get_value (TRUE_GRAY_PARAM, SHADINGBASE, 3, usbfile);
1321  shadingfact[0] = get_value (TRUE_GRAY_PARAM, SHADINGFACT1, 1, usbfile);
1322  shadingfact[1] = get_value (TRUE_GRAY_PARAM, SHADINGFACT2, 1, usbfile);
1323  shadingfact[2] = get_value (TRUE_GRAY_PARAM, SHADINGFACT3, 1, usbfile);
1324
1325  LoadImagingParams (dev, usbfile);
1326
1327  DBG (DBG_FNC, "- Load_Config\n");
1328
1329  return OK;
1330}
1331
1332static SANE_Int
1333LoadImagingParams (struct st_device *dev, SANE_Int inifile)
1334{
1335  DBG (DBG_FNC, "> LoadImagingParams(inifile='%i'):\n", inifile);
1336
1337  scan.startpos = get_value (SCAN_PARAM, STARTPOS, 0, inifile);
1338  scan.leftleading = get_value (SCAN_PARAM, LEFTLEADING, 0, inifile);
1339  arrangeline = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, inifile);
1340  compression = get_value (SCAN_PARAM, COMPRESSION, 0, inifile);
1341
1342  /* get default gain and offset values */
1343  cfg_gainoffset_get (dev->sensorcfg->type, default_gain_offset);
1344
1345  linedarlampoff = get_value (CALI_PARAM, LINEDARLAMPOFF, 0, inifile);
1346
1347  pixeldarklevel = get_value (CALI_PARAM, PIXELDARKLEVEL, 0x00ffff, inifile);
1348
1349  binarythresholdh = get_value (PLATFORM, BINARYTHRESHOLDH, 0x80, inifile);
1350  binarythresholdl = get_value (PLATFORM, BINARYTHRESHOLDL, 0x7f, inifile);
1351
1352  return OK;
1353}
1354
1355static SANE_Int
1356Arrange_Colour (struct st_device *dev, SANE_Byte * buffer,
1357		SANE_Int buffer_size, SANE_Int * transferred)
1358{
1359  /*
1360     05F0FA78   04EC00D8  /CALL to Assumed StdFunc2 from hpgt3970.04EC00D3
1361     05F0FA7C   05D10048  |Arg1 = 05D10048
1362     05F0FA80   0000F906  \Arg2 = 0000F906
1363   */
1364  SANE_Int mydistance;
1365  SANE_Int Lines_Count;
1366  SANE_Int space;
1367  SANE_Int rst = OK;
1368  SANE_Int c;
1369  struct st_scanning *scn;
1370
1371  DBG (DBG_FNC, "> Arrange_Colour(*buffer, buffer_size=%i, *transferred)\n",
1372       buffer_size);
1373
1374  /* this is just to make code more legible */
1375  scn = dev->scanning;
1376
1377  if (scn->imagebuffer == NULL)
1378    {
1379      if (dev->sensorcfg->type == CCD_SENSOR)
1380	mydistance =
1381	  (dev->sensorcfg->line_distance * scan2.resolution_y) /
1382	  dev->sensorcfg->resolution;
1383      else
1384	mydistance = 0;
1385
1386      /*aafa */
1387      if (mydistance != 0)
1388	{
1389	  scn->bfsize =
1390	    (scn->arrange_hres ==
1391	     TRUE) ? scn->arrange_sensor_evenodd_dist : 0;
1392	  scn->bfsize = (scn->bfsize + (mydistance * 2) + 1) * line_size;
1393	}
1394      else
1395	scn->bfsize = line_size * 2;
1396
1397      /*ab3c */
1398      space =
1399	(((scn->bfsize / line_size) * bytesperline) >
1400	 scn->bfsize) ? (scn->bfsize / line_size) *
1401	bytesperline : scn->bfsize;
1402
1403      scn->imagebuffer = (SANE_Byte *) malloc (space * sizeof (SANE_Byte));
1404      if (scn->imagebuffer == NULL)
1405	return ERROR;
1406
1407      scn->imagepointer = scn->imagebuffer;
1408
1409      if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) != OK)
1410	return ERROR;
1411
1412      scn->arrange_orderchannel = FALSE;
1413      scn->channel_size = (scan2.depth == 8) ? 1 : 2;
1414
1415      /* Calculate channel displacements */
1416      for (c = CL_RED; c <= CL_BLUE; c++)
1417	{
1418	  if (mydistance == 0)
1419	    {
1420	      /*ab9b */
1421	      if (scn->arrange_hres == FALSE)
1422		{
1423		  if ((((dev->sensorcfg->line_distance * scan2.resolution_y) *
1424			2) / dev->sensorcfg->resolution) == 1)
1425		    scn->arrange_orderchannel = TRUE;
1426
1427		  if (scn->arrange_orderchannel == TRUE)
1428		    scn->desp[c] =
1429		      ((dev->sensorcfg->rgb_order[c] / 2) * line_size) +
1430		      (scn->channel_size * c);
1431		  else
1432		    scn->desp[c] = scn->channel_size * c;
1433		}
1434	    }
1435	  else
1436	    {
1437	      /*ac32 */
1438	      scn->desp[c] =
1439		(dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) +
1440		(scn->channel_size * c);
1441
1442	      if (scn->arrange_hres == TRUE)
1443		{
1444		  scn->desp1[c] = scn->desp[c];
1445		  scn->desp2[c] =
1446		    ((scn->channel_size * 3) + scn->desp[c]) +
1447		    (scn->arrange_sensor_evenodd_dist * line_size);
1448		}
1449	    }
1450	}
1451
1452      /*ace2 */
1453      for (c = CL_RED; c <= CL_BLUE; c++)
1454	{
1455	  if (scn->arrange_hres == TRUE)
1456	    {
1457	      scn->pColour2[c] = scn->imagebuffer + scn->desp2[c];
1458	      scn->pColour1[c] = scn->imagebuffer + scn->desp1[c];
1459	    }
1460	  else
1461	    scn->pColour[c] = scn->imagebuffer + scn->desp[c];
1462	}
1463    }
1464
1465  /*ad91 */
1466  Lines_Count = buffer_size / line_size;
1467  while (Lines_Count > 0)
1468    {
1469      if (scn->arrange_orderchannel == FALSE)
1470	{
1471	  if (scn->arrange_hres == TRUE)
1472	    Triplet_Colour_HRes (scn->pColour1[CL_RED],
1473				 scn->pColour1[CL_GREEN],
1474				 scn->pColour1[CL_BLUE],
1475				 scn->pColour2[CL_RED],
1476				 scn->pColour2[CL_GREEN],
1477				 scn->pColour2[CL_BLUE], buffer,
1478				 line_size / (scn->channel_size * 3));
1479	  else
1480	    Triplet_Colour_LRes (line_size / (scn->channel_size * 3), buffer,
1481				 scn->pColour[CL_RED], scn->pColour[CL_GREEN],
1482				 scn->pColour[CL_BLUE]);
1483	}
1484      else
1485	Triplet_Colour_Order (dev, scn->pColour[CL_RED],
1486			      scn->pColour[CL_GREEN], scn->pColour[CL_BLUE],
1487			      buffer, line_size / (scn->channel_size * 3));
1488
1489      scn->arrange_size -= bytesperline;
1490      if (scn->arrange_size < 0)
1491	v15bc--;
1492
1493      buffer += line_size;
1494
1495      Lines_Count--;
1496      if (Lines_Count == 0)
1497	{
1498	  if ((scn->arrange_size | v15bc) == 0)
1499	    return OK;
1500	}
1501
1502      if (Read_Block (dev, line_size, scn->imagepointer, transferred) ==
1503	  ERROR)
1504	return ERROR;
1505
1506      /* Update displacements */
1507      for (c = CL_RED; c <= CL_BLUE; c++)
1508	{
1509	  if (scn->arrange_hres == TRUE)
1510	    {
1511	      /*aeb7 */
1512	      scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize;
1513	      scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize;
1514
1515	      scn->pColour2[c] = scn->imagebuffer + scn->desp2[c];
1516	      scn->pColour1[c] = scn->imagebuffer + scn->desp1[c];
1517	    }
1518	  else
1519	    {
1520	      /*af86 */
1521	      scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize;
1522	      scn->pColour[c] = scn->imagebuffer + scn->desp[c];
1523	    }
1524	}
1525
1526      /*aff3 */
1527      scn->imagepointer += line_size;
1528      if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize))
1529	scn->imagepointer = scn->imagebuffer;
1530    }
1531
1532  return rst;
1533}
1534
1535static SANE_Int
1536RTS_Scanner_SetParams (struct st_device *dev, struct params *param)
1537{
1538  SANE_Int rst = ERROR;
1539
1540  DBG (DBG_FNC, "+ RTS_Scanner_SetParams:\n");
1541  DBG (DBG_FNC, "->  param->resolution_x=%i\n", param->resolution_x);
1542  DBG (DBG_FNC, "->  param->resolution_y=%i\n", param->resolution_y);
1543  DBG (DBG_FNC, "->  param->left        =%i\n", param->coords.left);
1544  DBG (DBG_FNC, "->  param->width       =%i\n", param->coords.width);
1545  DBG (DBG_FNC, "->  param->top         =%i\n", param->coords.top);
1546  DBG (DBG_FNC, "->  param->height      =%i\n", param->coords.height);
1547  DBG (DBG_FNC, "->  param->colormode   =%s\n",
1548       dbg_colour (param->colormode));
1549  DBG (DBG_FNC, "->  param->scantype    =%s\n",
1550       dbg_scantype (param->scantype));
1551  DBG (DBG_FNC, "->  param->depth       =%i\n", param->depth);
1552  DBG (DBG_FNC, "->  param->channel     =%i\n", param->channel);
1553
1554  /* validate area size to scan */
1555  if ((param->coords.width != 0) && (param->coords.height != 0))
1556    {
1557      SANE_Byte mybuffer[1];
1558      struct st_hwdconfig hwdcfg;
1559
1560      /* setting coordinates */
1561      memcpy (&scan.coord, &param->coords, sizeof (struct st_coords));
1562
1563      /* setting resolution */
1564      scan.resolution_x = param->resolution_x;
1565      scan.resolution_y = param->resolution_y;
1566
1567      /* setting colormode and depth */
1568      scan.colormode = param->colormode;
1569      scan.depth = (param->colormode == CM_LINEART) ? 8 : param->depth;
1570
1571      /* setting color channel for non color scans */
1572      scan.channel = _B0 (param->channel);
1573
1574      arrangeline = FIX_BY_HARD;
1575      if ((scan.resolution_x == 2400) || ((scan.resolution_x == 4800)))
1576	{
1577	  if (scan.colormode != CM_COLOR)
1578	    {
1579	      if (scan.colormode == CM_GRAY)
1580		{
1581		  if (scan.channel == 3)
1582		    arrangeline = FIX_BY_SOFT;
1583		}
1584	    }
1585	  else
1586	    arrangeline = FIX_BY_SOFT;
1587	}
1588
1589      /* setting scan type */
1590      if ((param->scantype > 0) && (param->scantype < 4))
1591	scan.scantype = param->scantype;
1592      else
1593	scan.scantype = ST_NORMAL;
1594
1595      /* setting scanner lamp */
1596      data_bitset (&dev->init_regs[0x146], 0x40,
1597		   ((dev->sensorcfg->type == CIS_SENSOR) ? 0 : 1));
1598
1599      /* turn on appropriate lamp */
1600      if (scan.scantype == ST_NORMAL)
1601	Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP);
1602      else
1603	Lamp_Status_Set (dev, NULL, TRUE, TMA_LAMP);
1604
1605      mybuffer[0] = 0;
1606      if (RTS_IsExecuting (dev, mybuffer) == FALSE)
1607	RTS_WriteRegs (dev->usb_handle, dev->init_regs);
1608
1609      if (scan.depth == 16)
1610	compression = FALSE;
1611
1612      /* resetting low level config */
1613      memset (&hwdcfg, 0, sizeof (struct st_hwdconfig));
1614
1615      /* setting low level config */
1616      hwdcfg.scantype = scan.scantype;
1617      hwdcfg.calibrate = mybuffer[0];
1618      hwdcfg.arrangeline = arrangeline;	/*1 */
1619      hwdcfg.highresolution = (scan.resolution_x > 1200) ? TRUE : FALSE;
1620      hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance;
1621
1622      SetScanParams (dev, dev->init_regs, &scan, &hwdcfg);
1623
1624      scan.shadinglength =
1625	(((scan.sensorresolution * 17) / 2) + 3) & 0xfffffffc;
1626
1627      rst = OK;
1628    }
1629
1630  DBG (DBG_FNC, "- RTS_Scanner_SetParams: %i\n", rst);
1631
1632  return rst;
1633}
1634
1635static SANE_Int
1636SetScanParams (struct st_device *dev, SANE_Byte * Regs,
1637	       struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg)
1638{
1639  struct st_coords mycoords;
1640  SANE_Int mycolormode;
1641  SANE_Int myvalue;
1642  SANE_Int mymode;
1643  SANE_Int channel_size;
1644  SANE_Int channel_count;
1645  SANE_Int dots_per_block;
1646  SANE_Int aditional_dots;
1647
1648  DBG (DBG_FNC, "+ SetScanParams:\n");
1649  dbg_ScanParams (scancfg);
1650  dbg_hwdcfg (hwdcfg);
1651
1652  memset (&mycoords, 0, sizeof (struct st_coords));
1653  /* Copy scancfg to scan2 */
1654  memcpy (&scan2, scancfg, sizeof (struct st_scanparams));
1655
1656  mycolormode = scancfg->colormode;
1657  myvalue = scancfg->colormode;
1658  scantype = hwdcfg->scantype;
1659
1660  if (scancfg->colormode == CM_LINEART)
1661    scan2.depth = 8;
1662
1663  if ((scancfg->colormode != CM_COLOR) && (scancfg->channel == 3))	/*channel = 0x00 */
1664    {
1665      if (scancfg->colormode == CM_GRAY)
1666	{
1667	  mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR;
1668	}
1669      else
1670	mycolormode = 3;
1671      myvalue = mycolormode;
1672    }
1673
1674  dev->Resize->resolution_x = scancfg->resolution_x;
1675  dev->Resize->resolution_y = scancfg->resolution_y;
1676
1677  mymode = RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scancfg->resolution_x);	/*0x0b */
1678  if (mymode == -1)
1679    {
1680      /* Non supported resolution. We will resize image after scanning */
1681      SANE_Int fitres;
1682
1683      fitres =
1684	Scanmode_fitres (dev, hwdcfg->scantype, scancfg->colormode,
1685			 scancfg->resolution_x);
1686      if (fitres != -1)
1687	{
1688	  /* supported resolution found */
1689	  dev->Resize->type = RSZ_DECREASE;
1690	}
1691      else
1692	{
1693	  dev->Resize->type = RSZ_INCREASE;
1694	  fitres =
1695	    Scanmode_maxres (dev, hwdcfg->scantype, scancfg->colormode);
1696	}
1697
1698      scan2.resolution_x = fitres;
1699      scan2.resolution_y = fitres;
1700
1701      mymode =
1702	RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scan2.resolution_x);
1703      if (mymode == -1)
1704	return ERROR;
1705
1706      imageheight = scancfg->coord.height;
1707      dev->Resize->towidth = scancfg->coord.width;
1708
1709      /* Calculate coords for new resolution */
1710      mycoords.left =
1711	(scan2.resolution_x * scancfg->coord.left) /
1712	dev->Resize->resolution_x;
1713      mycoords.width =
1714	(scan2.resolution_x * scancfg->coord.width) /
1715	dev->Resize->resolution_x;
1716      mycoords.top =
1717	(scan2.resolution_y * scancfg->coord.top) / dev->Resize->resolution_y;
1718      mycoords.height =
1719	((scan2.resolution_y * scancfg->coord.height) /
1720	 dev->Resize->resolution_y) + 2;
1721
1722      switch (scan2.colormode)
1723	{
1724	case CM_GRAY:
1725	  if ((dev->scanmodes[mymode]->samplerate == PIXEL_RATE)
1726	      && (mycolormode != 3))
1727	    dev->Resize->towidth *= 2;
1728
1729	  channel_size = (scan2.depth == 8) ? 1 : 2;
1730	  dev->Resize->mode = (scan2.depth == 8) ? RSZ_GRAYL : RSZ_GRAYH;
1731	  dev->Resize->bytesperline = dev->Resize->towidth * channel_size;
1732	  break;
1733	case CM_LINEART:
1734	  if (dev->scanmodes[mymode]->samplerate == PIXEL_RATE)
1735	    dev->Resize->towidth *= 2;
1736
1737	  dev->Resize->mode = RSZ_LINEART;
1738	  dev->Resize->bytesperline = (dev->Resize->towidth + 7) / 8;
1739	  break;
1740	default:		/*CM_COLOR */
1741	  channel_count = 3;
1742	  channel_size = (scan2.depth == 8) ? 1 : 2;
1743	  dev->Resize->mode = (scan2.depth == 8) ? RSZ_COLOURL : RSZ_COLOURH;
1744	  dev->Resize->bytesperline =
1745	    scancfg->coord.width * (channel_count * channel_size);
1746	  break;
1747	}
1748    }
1749  else
1750    {
1751      /* Supported scanmode */
1752      dev->Resize->type = RSZ_NONE;
1753      scan2.resolution_x = scancfg->resolution_x;
1754      scan2.resolution_y = scancfg->resolution_y;
1755      mycoords.left = scancfg->coord.left;
1756      mycoords.top = scancfg->coord.top;
1757      mycoords.width = scancfg->coord.width;
1758      mycoords.height = scancfg->coord.height;
1759    }
1760
1761  scancfg->timing = dev->scanmodes[mymode]->timing;
1762
1763  scan2.sensorresolution = dev->timings[scancfg->timing]->sensorresolution;
1764  if ((scantype > 0) && (scantype < 5))
1765    scan2.shadinglength =
1766      (((scan2.sensorresolution * 17) / 2) + 3) & 0xfffffffc;
1767
1768  scancfg->sensorresolution = scan2.sensorresolution;
1769  scancfg->shadinglength = scan2.shadinglength;
1770
1771  dev->scanning->arrange_compression = ((mycolormode != CM_LINEART)
1772					&& (scan2.depth <=
1773					    8)) ? hwdcfg->compression : FALSE;
1774
1775  if ((arrangeline2 == FIX_BY_HARD) || (mycolormode == CM_LINEART))
1776    arrangeline2 = mycolormode;	/*¿? */
1777  else if ((mycolormode == CM_GRAY) && (hwdcfg->highresolution == FALSE))
1778    arrangeline2 = 0;
1779
1780  if (hwdcfg->highresolution == FALSE)
1781    {
1782      /* resolution < 1200 dpi */
1783      dev->scanning->arrange_hres = FALSE;
1784      dev->scanning->arrange_sensor_evenodd_dist = 0;
1785    }
1786  else
1787    {
1788      /* resolution > 1200 dpi */
1789      dev->scanning->arrange_hres = TRUE;
1790      dev->scanning->arrange_sensor_evenodd_dist =
1791	hwdcfg->sensorevenodddistance;
1792    }
1793
1794  /* with must be adjusted to fit in the dots count per block */
1795  aditional_dots = 0;
1796  if (mycolormode != CM_LINEART)
1797    {
1798      dots_per_block = ((scan2.resolution_x > 2400)
1799			&& (scancfg->samplerate == PIXEL_RATE)) ? 8 : 4;
1800
1801      /* fit width */
1802      if ((mycoords.width % dots_per_block) != 0)
1803	{
1804	  aditional_dots = dots_per_block - (mycoords.width % dots_per_block);
1805	  mycoords.width += aditional_dots;
1806	}
1807    }
1808  else
1809    {
1810      /* Lineart */
1811      dots_per_block = 32 - (mycoords.width & 0x1f);
1812      if (dots_per_block < 32)
1813	{
1814	  mycoords.width += dots_per_block;
1815	  aditional_dots = (dots_per_block / 8);
1816	}
1817    }
1818
1819  DBG (DBG_FNC, " -> dots_per_block: %i\n", dots_per_block);
1820  DBG (DBG_FNC, " -> aditional_dots: %i\n", aditional_dots);
1821
1822  if (mycolormode == CM_LINEART)
1823    {
1824      bytesperline =
1825	(dev->scanmodes[mymode]->samplerate ==
1826	 PIXEL_RATE) ? mycoords.width / 4 : mycoords.width / 8;
1827      imagewidth3 = bytesperline;
1828      lineart_width = bytesperline * 8;
1829      line_size = bytesperline - aditional_dots;
1830      dev->Resize->fromwidth = line_size * 8;
1831    }
1832  else
1833    {
1834      /*4510 */
1835      switch (mycolormode)
1836	{
1837	case CM_COLOR:
1838	  channel_count = 3;
1839	  break;
1840	case 3:
1841	  channel_count = 1;
1842	  break;
1843	case CM_GRAY:
1844	  channel_count = (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) ? 2 : 1;	/*1 */
1845	  break;
1846	}
1847
1848      channel_size = (scan2.depth == 8) ? 1 : 2;
1849      bytesperline = mycoords.width * (channel_count * channel_size);
1850      imagewidth3 = bytesperline / channel_count;
1851      lineart_width = imagewidth3 / channel_size;
1852      line_size =
1853	bytesperline - (aditional_dots * (channel_count * channel_size));
1854      dev->Resize->fromwidth = line_size / (channel_count * channel_size);
1855    }
1856
1857  imagesize = mycoords.height * bytesperline;
1858  v15b4 = 0;
1859  dev->scanning->arrange_size = imagesize;
1860  v15bc = 0;
1861
1862  /* set resolution ratio */
1863  data_bitset (&Regs[0xc0], 0x1f,
1864	       scancfg->sensorresolution / scancfg->resolution_x);
1865
1866  scancfg->coord.left = mycoords.left;
1867  scancfg->coord.top = mycoords.top;
1868  scancfg->coord.width = mycoords.width;
1869  scancfg->coord.height = mycoords.height;
1870  scancfg->resolution_x = scan2.resolution_x;
1871  scancfg->resolution_y = scan2.resolution_y;
1872
1873  myvalue =
1874    (dev->Resize->type == RSZ_NONE) ? line_size : dev->Resize->bytesperline;
1875  scancfg->bytesperline = bytesperline;
1876
1877  scancfg->v157c = myvalue;
1878
1879  if (scan.colormode != CM_COLOR)
1880    {
1881      if (mycolormode == CM_COLOR)
1882	scancfg->v157c = (scancfg->v157c / 3);
1883    }
1884
1885  if (scan.colormode == CM_LINEART)
1886    {
1887      if (mycolormode == 3)
1888	{
1889	  scancfg->v157c = (scancfg->v157c + 7) / 8;
1890	  scancfg->bytesperline = (scancfg->bytesperline + 7) / 8;
1891	}
1892    }
1893
1894  DBG (DBG_FNC, "- SetScanParams:\n");
1895
1896  return OK;
1897}
1898
1899static SANE_Int
1900GainOffset_Counter_Save (struct st_device *dev, SANE_Byte data)
1901{
1902  SANE_Int rst = OK;
1903
1904  DBG (DBG_FNC, "> GainOffset_Counter_Save(data=%i):\n", data);
1905
1906  /* check if chipset supports accessing eeprom */
1907  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
1908    {
1909      data = min (data, 0x0f);
1910      rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x0077, data);
1911    }
1912
1913  return rst;
1914}
1915
1916static SANE_Int
1917GainOffset_Counter_Inc (struct st_device *dev, SANE_Int * arg1)
1918{
1919  SANE_Byte count;
1920  SANE_Int rst;
1921
1922  DBG (DBG_FNC, "+ GainOffset_Counter_Inc:\n");
1923
1924  /* check if chipset supports accessing eeprom */
1925  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
1926    {
1927      count = GainOffset_Counter_Load (dev);
1928      if ((count >= 0x0f) || (GainOffset_Get (dev) != OK))
1929	{
1930	  offset[CL_BLUE] = offset[CL_GREEN] = offset[CL_RED] = 0;
1931	  gain[CL_BLUE] = gain[CL_GREEN] = gain[CL_RED] = 0;
1932	  count = 0;
1933	}
1934      else
1935	{
1936	  count++;
1937	  if (arg1 != NULL)
1938	    *arg1 = 1;
1939	}
1940
1941      rst = GainOffset_Counter_Save (dev, count);
1942    }
1943  else
1944    rst = OK;
1945
1946  DBG (DBG_FNC, "- GainOffset_Counter_Inc: %i\n", rst);
1947
1948  return rst;
1949}
1950
1951static SANE_Int
1952GainOffset_Get (struct st_device *dev)
1953{
1954  SANE_Int a, data, rst;
1955  SANE_Byte checksum;
1956
1957  DBG (DBG_FNC, "+ GainOffset_Get:\n");
1958
1959  checksum = 0;
1960
1961  /* check if chipset supports accessing eeprom */
1962  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
1963    {
1964      /* get current checksum */
1965      if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x76, &checksum) == OK)
1966	{
1967	  rst = OK;
1968
1969	  /* read gain and offset values from EEPROM */
1970	  for (a = CL_RED; a <= CL_BLUE; a++)
1971	    {
1972	      if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x70 + (2 * a), &data)
1973		  == ERROR)
1974		{
1975		  rst = ERROR;
1976		  break;
1977		}
1978	      else
1979		offset[a] = data;
1980	    }
1981
1982	  /* check checksum */
1983	  checksum =
1984	    _B0 (checksum + offset[CL_GREEN] + offset[CL_BLUE] +
1985		 offset[CL_RED]);
1986	}
1987      else
1988	rst = ERROR;
1989    }
1990  else
1991    rst = ERROR;
1992
1993  /* extract gain and offset values */
1994  if ((rst == OK) && (checksum == 0x5b))
1995    {
1996      for (a = CL_RED; a <= CL_BLUE; a++)
1997	{
1998	  gain[a] = (offset[a] >> 9) & 0x1f;
1999	  offset[a] &= 0x01ff;
2000	}
2001    }
2002  else
2003    {
2004      /* null values, let's reset them */
2005      for (a = CL_RED; a <= CL_BLUE; a++)
2006	{
2007	  gain[a] = 0;
2008	  offset[a] = 0;
2009	}
2010
2011      rst = ERROR;
2012    }
2013
2014  DBG (DBG_FNC,
2015       "->   Preview gainR=%i, gainG=%i, gainB=%i, offsetR=%i, offsetG=%i, offsetB=%i\n",
2016       gain[CL_RED], gain[CL_GREEN], gain[CL_BLUE], offset[CL_RED],
2017       offset[CL_GREEN], offset[CL_BLUE]);
2018
2019  DBG (DBG_FNC, "- GainOffset_Get: %i\n", rst);
2020
2021  return rst;
2022}
2023
2024static SANE_Int
2025Scanmode_maxres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode)
2026{
2027  /* returns position in scanmodes table where data fits with given arguments */
2028  SANE_Int rst = 0;
2029  SANE_Int a;
2030  struct st_scanmode *reg;
2031
2032  for (a = 0; a < dev->scanmodes_count; a++)
2033    {
2034      reg = dev->scanmodes[a];
2035      if (reg != NULL)
2036	{
2037	  if ((reg->scantype == scantype) && (reg->colormode == colormode))
2038	    rst = max (rst, reg->resolution);	/* found ! */
2039	}
2040    }
2041
2042  if (rst == 0)
2043    {
2044      /* There isn't any mode for these arguments.
2045         Most devices doesn't support specific setup to scan in lineart mode
2046         so they use gray colormode. Lets check this case */
2047      if (colormode == CM_LINEART)
2048	rst = Scanmode_maxres (dev, scantype, CM_GRAY);
2049    }
2050
2051  DBG (DBG_FNC, "> Scanmode_maxres(scantype=%s, colormode=%s): %i\n",
2052       dbg_scantype (scantype), dbg_colour (colormode), rst);
2053
2054  return rst;
2055}
2056
2057static SANE_Int
2058Scanmode_minres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode)
2059{
2060  /* returns position in scanmodes table where data fits with given arguments */
2061  SANE_Int rst, a;
2062  struct st_scanmode *reg;
2063
2064  rst = Scanmode_maxres (dev, scantype, colormode);
2065
2066  for (a = 0; a < dev->scanmodes_count; a++)
2067    {
2068      reg = dev->scanmodes[a];
2069      if (reg != NULL)
2070	{
2071	  if ((reg->scantype == scantype) && (reg->colormode == colormode))
2072	    rst = min (rst, reg->resolution);	/* found ! */
2073	}
2074    }
2075
2076  if (rst == 0)
2077    {
2078      /* There isn't any mode for these arguments.
2079         Most devices doesn't support specific setup to scan in lineart mode
2080         so they use gray colormode. Lets check this case */
2081      if (colormode == CM_LINEART)
2082	rst = Scanmode_minres (dev, scantype, CM_GRAY);
2083    }
2084
2085  DBG (DBG_FNC, "> Scanmode_minres(scantype=%s, colormode=%s): %i\n",
2086       dbg_scantype (scantype), dbg_colour (colormode), rst);
2087
2088  return rst;
2089}
2090
2091static SANE_Int
2092Scanmode_fitres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode,
2093		 SANE_Int resolution)
2094{
2095  /* returns a supported resolution */
2096  SANE_Int rst;
2097  SANE_Int a, nullres;
2098  struct st_scanmode *reg;
2099
2100  nullres = Scanmode_maxres (dev, scantype, colormode) + 1;
2101  rst = nullres;
2102
2103  for (a = 0; a < dev->scanmodes_count; a++)
2104    {
2105      reg = dev->scanmodes[a];
2106      if (reg != NULL)
2107	{
2108	  if ((reg->scantype == scantype) && (reg->colormode == colormode))
2109	    {
2110	      if ((reg->resolution < rst) && (resolution <= reg->resolution))
2111		rst = reg->resolution;
2112	    }
2113	}
2114    }
2115
2116  if (rst == nullres)
2117    {
2118      /* There isn't any mode for these arguments.
2119         Most devices doesn't support specific setup to scan in lineart mode
2120         so they use gray colormode. Lets check this case */
2121      if (colormode != CM_LINEART)
2122	{
2123	  /* at this point, given resolution is bigger than maximum supported resolution */
2124	  rst = -1;
2125	}
2126      else
2127	rst = Scanmode_minres (dev, scantype, CM_GRAY);
2128    }
2129
2130  DBG (DBG_FNC,
2131       "> Scanmode_fitres(scantype=%s, colormode=%s, resolution=%i): %i\n",
2132       dbg_scantype (scantype), dbg_colour (colormode), resolution, rst);
2133
2134  return rst;
2135}
2136
2137static SANE_Int
2138RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, SANE_Int colormode,
2139		 SANE_Int resolution)
2140{
2141  /* returns position in scanmodes table where data fits with given arguments */
2142  SANE_Int rst = -1;
2143  SANE_Int a;
2144  struct st_scanmode *reg;
2145
2146  for (a = 0; a < dev->scanmodes_count; a++)
2147    {
2148      reg = dev->scanmodes[a];
2149      if (reg != NULL)
2150	{
2151	  if ((reg->scantype == scantype) && (reg->colormode == colormode)
2152	      && (reg->resolution == resolution))
2153	    {
2154	      /* found ! */
2155	      rst = a;
2156	      break;
2157	    }
2158	}
2159    }
2160
2161  if (rst == -1)
2162    {
2163      /* There isn't any mode for these arguments.
2164         May be given resolution isn't supported by chipset.
2165         Most devices doesn't support specific setup to scan in lineart mode
2166         so they use gray colormode. Lets check this case */
2167      if ((colormode == CM_LINEART) || (colormode == 3))
2168	rst = RTS_GetScanmode (dev, scantype, CM_GRAY, resolution);
2169    }
2170
2171  DBG (DBG_FNC,
2172       "> RTS_GetScanmode(scantype=%s, colormode=%s, resolution=%i): %i\n",
2173       dbg_scantype (scantype), dbg_colour (colormode), resolution, rst);
2174
2175  return rst;
2176}
2177
2178static void
2179Free_Motor (struct st_device *dev)
2180{
2181  /* this function releases space for stepper motor */
2182
2183  DBG (DBG_FNC, "> Free_Motor\n");
2184
2185  if (dev->motorcfg != NULL)
2186    {
2187      free (dev->motorcfg);
2188      dev->motorcfg = NULL;
2189    }
2190}
2191
2192static SANE_Int
2193Load_Motor (struct st_device *dev)
2194{
2195  /* this function loads general configuration for motor */
2196
2197  SANE_Int rst = ERROR;
2198
2199  DBG (DBG_FNC, "> Load_Motor\n");
2200
2201  if (dev->motorcfg != NULL)
2202    Free_Motor (dev);
2203
2204  dev->motorcfg = malloc (sizeof (struct st_motorcfg));
2205  if (dev->motorcfg != NULL)
2206    {
2207      rst = cfg_motor_get (dev->motorcfg);
2208      dbg_motorcfg (dev->motorcfg);
2209    }
2210
2211  return rst;
2212}
2213
2214static void
2215Free_Sensor (struct st_device *dev)
2216{
2217  /* this function releases space for ccd sensor */
2218
2219  DBG (DBG_FNC, "> Free_Sensor\n");
2220
2221  if (dev->sensorcfg != NULL)
2222    {
2223      free (dev->sensorcfg);
2224      dev->sensorcfg = NULL;
2225    }
2226}
2227
2228static void
2229Free_Buttons (struct st_device *dev)
2230{
2231  /* this function releases space for buttons */
2232
2233  DBG (DBG_FNC, "> Free_Buttons\n");
2234
2235  if (dev->buttons != NULL)
2236    {
2237      free (dev->buttons);
2238      dev->buttons = NULL;
2239    }
2240}
2241
2242static SANE_Int
2243Load_Buttons (struct st_device *dev)
2244{
2245  /* this function loads configuration for ccd sensor */
2246
2247  SANE_Int rst = ERROR;
2248
2249  DBG (DBG_FNC, "> Load_Buttons\n");
2250
2251  if (dev->buttons != NULL)
2252    Free_Buttons (dev);
2253
2254  dev->buttons = malloc (sizeof (struct st_buttons));
2255  if (dev->buttons != NULL)
2256    {
2257      rst = cfg_buttons_get (dev->buttons);
2258      dbg_buttons (dev->buttons);
2259    }
2260
2261  return rst;
2262}
2263
2264static SANE_Int
2265Load_Sensor (struct st_device *dev)
2266{
2267  /* this function loads configuration for ccd sensor */
2268
2269  SANE_Int rst = ERROR;
2270
2271  DBG (DBG_FNC, "> Load_Sensor\n");
2272
2273  if (dev->sensorcfg != NULL)
2274    Free_Sensor (dev);
2275
2276  dev->sensorcfg = malloc (sizeof (struct st_sensorcfg));
2277  if (dev->sensorcfg != NULL)
2278    {
2279      rst = cfg_sensor_get (dev->sensorcfg);
2280      dbg_sensor (dev->sensorcfg);
2281    }
2282
2283  return rst;
2284}
2285
2286static void
2287Free_Timings (struct st_device *dev)
2288{
2289  /* this function frees all ccd sensor timing tables */
2290  DBG (DBG_FNC, "> Free_Timings\n");
2291
2292  if (dev->timings != NULL)
2293    {
2294      if (dev->timings_count > 0)
2295	{
2296	  SANE_Int a;
2297	  for (a = 0; a < dev->timings_count; a++)
2298	    if (dev->timings[a] != NULL)
2299	      free (dev->timings[a]);
2300
2301	  dev->timings_count = 0;
2302	}
2303
2304      free (dev->timings);
2305      dev->timings = NULL;
2306    }
2307}
2308
2309static SANE_Int
2310Load_Timings (struct st_device *dev)
2311{
2312  SANE_Int rst = OK;
2313  SANE_Int a;
2314  struct st_timing reg, *tmg;
2315
2316  DBG (DBG_FNC, "> Load_Timings\n");
2317
2318  if (dev->timings != NULL)
2319    Free_Timings (dev);
2320
2321  a = 0;
2322
2323  while ((cfg_timing_get (dev->sensorcfg->type, a, &reg) == OK)
2324	 && (rst == OK))
2325    {
2326      tmg = (struct st_timing *) malloc (sizeof (struct st_timing));
2327      if (tmg != NULL)
2328	{
2329	  memcpy (tmg, &reg, sizeof (struct st_timing));
2330
2331	  dev->timings_count++;
2332	  dev->timings =
2333	    (struct st_timing **) realloc (dev->timings,
2334					   sizeof (struct st_timing **) *
2335					   dev->timings_count);
2336	  if (dev->timings == NULL)
2337	    {
2338	      rst = ERROR;
2339	      dev->timings_count = 0;
2340	    }
2341	  else
2342	    dev->timings[dev->timings_count - 1] = tmg;
2343	}
2344      else
2345	rst = ERROR;
2346
2347      a++;
2348    }
2349
2350  if (rst == ERROR)
2351    Free_Timings (dev);
2352
2353  DBG (DBG_FNC, " -> Found %i timing registers\n", dev->timings_count);
2354
2355  return rst;
2356}
2357
2358static SANE_Int
2359IsScannerLinked (struct st_device *dev)
2360{
2361  SANE_Int var2;
2362  SANE_Byte lamp;
2363
2364  DBG (DBG_FNC, "+ IsScannerLinked:\n");
2365
2366  Read_FE3E (dev, &v1619);
2367  Init_USBData (dev);
2368  scan.scantype = ST_NORMAL;
2369
2370  RTS_WaitInitEnd (dev, 0x30000);
2371
2372  lamp = FLB_LAMP;
2373
2374  /* Comprobar si es la primera conexión con el escaner */
2375  if (Read_Word (dev->usb_handle, 0xe829, &var2) == OK)
2376    {
2377      SANE_Int firstconnection;
2378
2379#ifdef STANDALONE
2380      firstconnection = TRUE;
2381#else
2382      firstconnection = (var2 == 0) ? TRUE : FALSE;
2383#endif
2384
2385      if (firstconnection == TRUE)
2386	{
2387	  /* primera conexión */
2388	  SANE_Byte flb_lamp, tma_lamp;
2389
2390	  flb_lamp = 0;
2391	  tma_lamp = 0;
2392	  Lamp_Status_Get (dev, &flb_lamp, &tma_lamp);
2393
2394	  if ((flb_lamp == 0) && (tma_lamp != 0))
2395	    lamp = TMA_LAMP;
2396
2397	  /*Clear GainOffset count */
2398	  GainOffset_Clear (dev);
2399	  GainOffset_Counter_Save (dev, 0);
2400
2401	  /* Clear AutoRef count */
2402	  Refs_Counter_Save (dev, 0);
2403
2404	  Buttons_Enable (dev);
2405	  Lamp_Status_Timer_Set (dev, 13);
2406	}
2407      else
2408	lamp = (_B0 (var2) == 0) ? FLB_LAMP : TMA_LAMP;
2409    }
2410
2411  if (RTS_Warm_Reset (dev) != OK)
2412    return ERROR;
2413
2414  Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
2415
2416  Lamp_Status_Timer_Set (dev, 13);
2417
2418  /* Use fixed pwm? */
2419  if (RTS_Debug->use_fixed_pwm != FALSE)
2420    {
2421      Lamp_PWM_Save (dev, cfg_fixedpwm_get (dev->sensorcfg->type, ST_NORMAL));
2422      /* Lets enable using fixed pwm */
2423      Lamp_PWM_SaveStatus (dev, TRUE);
2424    }
2425
2426  Lamp_PWM_Setup (dev, lamp);
2427
2428  DBG (DBG_FNC, "- IsScannerLinked:\n");
2429
2430  return OK;
2431}
2432
2433static SANE_Int
2434Lamp_PWM_SaveStatus (struct st_device *dev, SANE_Byte status)
2435{
2436  SANE_Byte mypwm;
2437  SANE_Int rst = OK;
2438
2439  DBG (DBG_FNC, "+ Lamp_PWM_SaveStatus(status=%i):\n", status);
2440
2441  /* check if chipset supports accessing eeprom */
2442  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
2443    {
2444      rst = ERROR;
2445
2446      if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x007b, &mypwm) == OK)
2447	{
2448	  mypwm = (status == FALSE) ? mypwm & 0x7f : mypwm | 0x80;
2449
2450	  if (RTS_EEPROM_WriteByte (dev->usb_handle, 0x007b, mypwm) == OK)
2451	    rst = OK;
2452	}
2453    }
2454
2455  DBG (DBG_FNC, "- Lamp_PWM_SaveStatus: %i\n", rst);
2456
2457  return rst;
2458}
2459
2460static SANE_Int
2461Lamp_PWM_Save (struct st_device *dev, SANE_Int fixedpwm)
2462{
2463  SANE_Int rst;
2464
2465  DBG (DBG_FNC, "+ Lamp_PWM_Save(fixedpwm=%i):\n", fixedpwm);
2466
2467  /* check if chipset supports accessing eeprom */
2468  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
2469    rst =
2470      RTS_EEPROM_WriteByte (dev->usb_handle, 0x7b, ((fixedpwm << 2) | 0x80));
2471  else
2472    rst = OK;
2473
2474  DBG (DBG_FNC, "- Lamp_PWM_Save: %i\n", rst);
2475
2476  return rst;
2477}
2478
2479static SANE_Int
2480Lamp_PWM_Setup (struct st_device *dev, SANE_Int lamp)
2481{
2482  SANE_Int rst = OK;
2483
2484  DBG (DBG_FNC, "+ Lamp_PWM_Setup(lamp=%s):\n",
2485       (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP");
2486
2487  if (Lamp_PWM_use (dev, 1) == OK)
2488    {
2489      SANE_Int fixedpwm, currentpwd;
2490
2491      currentpwd = 0;
2492      fixedpwm =
2493	cfg_fixedpwm_get (dev->sensorcfg->type,
2494			  (lamp == FLB_LAMP) ? ST_NORMAL : ST_TA);
2495
2496      if (Lamp_PWM_DutyCycle_Get (dev, &currentpwd) == OK)
2497	{
2498	  /* set duty cycle if current one is different */
2499	  if (currentpwd != fixedpwm)
2500	    rst = Lamp_PWM_DutyCycle_Set (dev, fixedpwm);
2501	}
2502      else
2503	rst = Lamp_PWM_DutyCycle_Set (dev, fixedpwm);
2504    }
2505
2506  DBG (DBG_FNC, "- Lamp_PWM_Setup: %i\n", rst);
2507
2508  return rst;
2509}
2510
2511static SANE_Int
2512Lamp_PWM_DutyCycle_Get (struct st_device *dev, SANE_Int * data)
2513{
2514  SANE_Byte a;
2515  SANE_Int rst = ERROR;
2516
2517  DBG (DBG_FNC, "+ Lamp_PWM_DutyCycle_Get:\n");
2518
2519  if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK)
2520    {
2521      *data = a & 0x3f;
2522      rst = OK;
2523    }
2524
2525  DBG (DBG_FNC, "- Lamp_PWM_DutyCycle_Get = %i: %i\n", *data, rst);
2526
2527  return rst;
2528}
2529
2530static SANE_Int
2531Lamp_PWM_DutyCycle_Set (struct st_device *dev, SANE_Int duty_cycle)
2532{
2533  SANE_Byte *Regs;
2534  SANE_Int rst;
2535
2536  DBG (DBG_FNC, "+ Lamp_PWM_DutyCycle_Set(duty_cycle=%i):\n", duty_cycle);
2537
2538  rst = ERROR;
2539
2540  Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
2541  if (Regs != NULL)
2542    {
2543      if (RTS_ReadRegs (dev->usb_handle, Regs) == OK)
2544	{
2545	  data_bitset (&Regs[0x148], 0x3f, duty_cycle);
2546
2547	  if (pwmlamplevel == 0)
2548	    {
2549	      data_bitset (&Regs[0x148], 0x40, 0);
2550	      Regs[0x1e0] |= ((duty_cycle >> 1) & 0x40);
2551	    }
2552
2553	  data_bitset (&dev->init_regs[0x148], 0x7f, Regs[0x148]);
2554	  data_bitset (&dev->init_regs[0x1e0], 0x3f, Regs[0x1e0]);
2555
2556	  Write_Byte (dev->usb_handle, 0xe948, Regs[0x0148]);
2557
2558	  rst = Write_Byte (dev->usb_handle, 0xe9e0, Regs[0x01e0]);
2559	}
2560
2561      free (Regs);
2562    }
2563
2564  DBG (DBG_FNC, "- Lamp_PWM_DutyCycle_Set: %i\n", rst);
2565
2566  return rst;
2567}
2568
2569static SANE_Int
2570Head_ParkHome (struct st_device *dev, SANE_Int bWait, SANE_Int movement)
2571{
2572  SANE_Int rst = ERROR;
2573  SANE_Byte *Regs;
2574
2575  DBG (DBG_FNC, "+ Head_ParkHome(bWait=%i, movement=%i):\n", bWait, movement);
2576
2577  Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
2578  if (Regs != NULL)
2579    {
2580      rst = OK;
2581
2582      memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
2583
2584      /* Lets wait if it's required when is already executing */
2585      if (bWait != FALSE)
2586	{
2587	  if (RTS_WaitScanEnd (dev, 0x3a98) != OK)
2588	    {
2589	      DBG (DBG_FNC, " -> Head_ParkHome: RTS_WaitScanEnd Timeout\n");
2590	      rst = ERROR;	/* timeout */
2591	    }
2592	}
2593      else
2594	{
2595	  if (RTS_IsExecuting (dev, Regs) == FALSE)
2596	    {
2597	      DBG (DBG_FNC,
2598		   " -> Head_ParkHome: RTS_IsExecuting = 0, exiting function\n");
2599	      rst = ERROR;	/* if NOT executing */
2600	    }
2601	}
2602
2603      /* Check if lamp is at home */
2604      if ((rst == OK) && (Head_IsAtHome (dev, Regs) == FALSE))
2605	{
2606	  struct st_motormove mymotor;
2607	  struct st_motorpos mtrpos;
2608
2609	  DBG (DBG_FNC,
2610	       "->   Head_ParkHome: Lamp is not at home, lets move\n");
2611
2612	  /* it isn't */
2613	  dev->status->parkhome = TRUE;
2614
2615	  if ((movement != -1) && (movement < dev->motormove_count))
2616	    {
2617	      memcpy (&mymotor, dev->motormove[movement],
2618		      sizeof (struct st_motormove));
2619	    }
2620	  else
2621	    {
2622	      /* debug this code. Shouldn't have any relationship with offsets */
2623	      if (default_gain_offset->edcg2[CL_BLUE] < 4)
2624		mymotor.scanmotorsteptype =
2625		  default_gain_offset->edcg2[CL_BLUE];
2626
2627	      mymotor.ctpc = default_gain_offset->odcg2[1];
2628	      mymotor.systemclock = default_gain_offset->edcg2[1];	/*? */
2629	    }
2630
2631	  mtrpos.options = MTR_ENABLED | MTR_BACKWARD;
2632	  mtrpos.v12e448 = 0x01;
2633	  mtrpos.v12e44c = 0x00;
2634	  mtrpos.coord_y = 0x4e20;
2635
2636	  Motor_Move (dev, Regs, &mymotor, &mtrpos);
2637
2638	  /* Should we wait? */
2639	  if (bWait != FALSE)
2640	    rst = RTS_WaitScanEnd (dev, 15000);
2641
2642	  dev->status->parkhome = FALSE;
2643	}
2644
2645      free (Regs);
2646    }
2647
2648  DBG (DBG_FNC, "- Head_ParkHome: %i:\n", rst);
2649
2650  return rst;
2651}
2652
2653static SANE_Int
2654Motor_Move (struct st_device *dev, SANE_Byte * Regs,
2655	    struct st_motormove *mymotor, struct st_motorpos *mtrpos)
2656{
2657  SANE_Byte *cpRegs;
2658  SANE_Int rst;
2659
2660  DBG (DBG_FNC, "+ Motor_Move:\n");
2661
2662  rst = ERROR;
2663
2664  cpRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
2665  if (cpRegs != NULL)
2666    {
2667      SANE_Int data, v12dcf8, coord_y, step_type;
2668
2669      memcpy (cpRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
2670      v12dcf8 = 0;
2671
2672      /* resolution = 1 dpi */
2673      data_bitset (&cpRegs[0xc0], 0x1f, 1);	     /*---xxxxx*/
2674
2675      /* set motor step type */
2676      data_bitset (&cpRegs[0xd9], 0x70, mymotor->scanmotorsteptype);	      /*-xxx----*/
2677
2678      /* set motor direction (polarity) */
2679      data_bitset (&cpRegs[0xd9], 0x80, mtrpos->options >> 3);	/*e------- */
2680
2681      /* next value doesn't seem to have any effect */
2682      data_bitset (&cpRegs[0xd9], 0x0f, mtrpos->options);		       /*----efgh*/
2683
2684      /* 0 enable/1 disable motor */
2685      data_bitset (&cpRegs[0xdd], 0x80, mtrpos->options >> 4);	/*d------- */
2686
2687      /* next value doesn't seem to have any effect */
2688      data_bitset (&cpRegs[0xdd], 0x40, mtrpos->options >> 4);		       /*-d------*/
2689
2690      switch (mymotor->scanmotorsteptype)
2691	{
2692	case STT_OCT:
2693	  step_type = 8;
2694	  break;
2695	case STT_QUART:
2696	  step_type = 4;
2697	  break;
2698	case STT_HALF:
2699	  step_type = 2;
2700	  break;
2701	case STT_FULL:
2702	  step_type = 1;
2703	  break;
2704	default:
2705	  step_type = 0;
2706	  break;		/* shouldn't be used */
2707	}
2708
2709      coord_y = (mtrpos->coord_y * step_type) & 0xffff;
2710      if (coord_y < 2)
2711	coord_y = 2;
2712
2713      /* Sets dummyline to 1 */
2714      data_bitset (&cpRegs[0xd6], 0xf0, 1);
2715
2716      /* set step_size - 1 */
2717      cpRegs[0xe0] = 0;
2718
2719      cpRegs[0x01] &= 0xf9;
2720      cpRegs[0x01] |= (mtrpos->v12e448 & 1) << 2;
2721
2722      /* set dummy scan */
2723      data_bitset (&cpRegs[0x01], 0x10, 1);	     /*---x----*/
2724
2725      /* set samplerate */
2726      data_bitset (&cpRegs[0x1cf], 0x40, PIXEL_RATE);	       /*-x------*/
2727
2728      /* unknown data */
2729      data_bitset (&cpRegs[0x1cf], 0x80, 1);	/*x------- */
2730
2731      /* sets one channel per color */
2732      data_bitset (&cpRegs[0x12], 0x3f, 0);	/* channel   */
2733      data_bitset (&cpRegs[0x12], 0xc0, 1);	/* 1 channel */
2734
2735      /* timing cnpp */
2736      data_bitset (&cpRegs[0x96], 0x3f, 0x0b);		/*--001011*/
2737
2738      /* set systemclock */
2739      data_bitset (&cpRegs[0x00], 0x0f, mymotor->systemclock);		/*----xxxx*/
2740
2741      /* set last step of accurve.smearing table to 2 */
2742      data_lsb_set (&cpRegs[0xe4], 2, 3);
2743
2744      /* set last step of deccurve.scanbufferfull table to 16 */
2745      data_lsb_set (&Regs[0xea], 0x10, 3);
2746
2747      /* set last step of deccurve.normalscan table to 16 */
2748      data_lsb_set (&Regs[0xed], 0x10, 3);
2749
2750      /* set last step of deccurve.smearing table to 16 */
2751      data_lsb_set (&Regs[0xf0], 0x10, 3);
2752
2753      /* set last step of deccurve.parkhome table to 16 */
2754      data_lsb_set (&Regs[0xf3], 0x10, 3);
2755
2756      /* set msi */
2757      cpRegs[0xda] = 2;
2758      cpRegs[0xdd] &= 0xfc;
2759
2760      /* set if motor has motorcurves */
2761      data_bitset (&cpRegs[0xdf], 0x10,
2762		   ((mymotor->motorcurve != -1) ? 1 : 0));
2763
2764      if (mymotor->motorcurve != -1)
2765	{
2766	  struct st_curve *crv;
2767
2768	  /* set last step of accurve.normalscan table */
2769	  crv =
2770	    Motor_Curve_Get (dev, mymotor->motorcurve, ACC_CURVE,
2771			     CRV_NORMALSCAN);
2772	  if (crv != NULL)
2773	    data_lsb_set (&cpRegs[0xe1], crv->step[crv->step_count - 1], 3);
2774
2775	  DBG (DBG_FNC, " -> Setting up stepper motor using motorcurve %i\n",
2776	       mymotor->motorcurve);
2777	  v12dcf8 = Motor_Setup_Steps (dev, cpRegs, mymotor->motorcurve);
2778
2779	  /* set step_size - 1 */
2780	  cpRegs[0xe0] = 0;
2781
2782	  crv =
2783	    Motor_Curve_Get (dev, mymotor->motorcurve, DEC_CURVE,
2784			     CRV_NORMALSCAN);
2785	  if (crv != NULL)
2786	    coord_y -= (v12dcf8 + crv->step_count);
2787
2788	  /* set line exposure time */
2789	  data_lsb_set (&cpRegs[0x30], mymotor->ctpc, 3);
2790
2791	  /* set last step of accurve.smearing table */
2792	  data_lsb_set (&cpRegs[0xe4], 0, 3);
2793	}
2794      else
2795	{
2796	  /* Setting some motor step */
2797	  SANE_Int some_step;
2798
2799	  switch (Regs[0x00] & 0x0f)
2800	    {
2801	    case 0x00:
2802	      some_step = 0x00895440;
2803	      break;		/*  3 x 0x2DC6C0 */
2804	    case 0x08:
2805	    case 0x01:
2806	      some_step = 0x00b71b00;
2807	      break;		/*  4 x 0x2DC6C0 */
2808	    case 0x02:
2809	      some_step = 0x0112a880;
2810	      break;		/*  6 x 0x2DC6C0 */
2811	    case 0x0a:
2812	    case 0x03:
2813	      some_step = 0x016e3600;
2814	      break;		/*  8 x 0x2DC6C0 */
2815	    case 0x04:
2816	      some_step = 0x02255100;
2817	      break;		/* 12 x 0x2DC6C0 */
2818	    case 0x0c:
2819	      some_step = 0x02dc6c00;
2820	      break;		/* 16 x 0x2DC6C0 */
2821	    case 0x05:
2822	      some_step = 0x044aa200;
2823	      break;		/* 24 x 0x2DC6C0 */
2824	    case 0x0d:
2825	      some_step = 0x05b8d800;
2826	      break;		/* 32 x 0x2DC6C0 */
2827
2828	    case 0x09:
2829	      some_step = 0x00f42400;
2830	      break;
2831	    case 0x0b:
2832	      some_step = 0x01e84800;
2833	      break;		/* = case 9 * 2 */
2834	    default:
2835	      some_step = 0x0478f7f8;
2836	      break;
2837	    }
2838
2839	  /* divide by timing.cnpp */
2840	  some_step /= ((cpRegs[0x96] & 0x3f) + 1);
2841	  if (mymotor->ctpc > 0)
2842	    some_step /= mymotor->ctpc;
2843
2844	  /* set line exposure time */
2845	  data_lsb_set (&cpRegs[0x30], some_step, 3);
2846
2847	  /* set last step of accurve.normalscan table */
2848	  data_lsb_set (&cpRegs[0xe1], some_step, 3);
2849	}
2850
2851      /* Setting coords */
2852      RTS_Setup_Coords (cpRegs, 100, coord_y - 1, 800, 1);
2853
2854      /* enable head movement */
2855      data_bitset (&cpRegs[0xd8], 0x80, 1);
2856
2857      /* release motor before executing */
2858      Motor_Release (dev);
2859
2860      RTS_Warm_Reset (dev);
2861
2862      /* action! */
2863      data = RTS_WriteRegs (dev->usb_handle, cpRegs);
2864      if (data == OK)
2865	RTS_Execute (dev);
2866
2867      /* wait 10 seconds */
2868      RTS_WaitScanEnd (dev, 10000);
2869
2870      rst = (data != OK) ? v12dcf8 : RTS_WaitScanEnd (dev, 20000);
2871
2872      free (cpRegs);
2873    }
2874
2875  DBG (DBG_FNC, "- Motor_Move: %i\n", rst);
2876
2877  return rst;
2878}
2879
2880static void
2881Free_Motormoves (struct st_device *dev)
2882{
2883  DBG (DBG_FNC, "> Free_Motormoves\n");
2884
2885  if (dev->motormove != NULL)
2886    {
2887      SANE_Int a;
2888      struct st_motormove *ms;
2889
2890      for (a = 0; a < dev->motormove_count; a++)
2891	{
2892	  ms = dev->motormove[a];
2893	  if (ms != NULL)
2894	    free (ms);
2895	}
2896
2897      free (dev->motormove);
2898      dev->motormove = NULL;
2899    }
2900
2901  dev->motormove_count = 0;
2902}
2903
2904static void
2905Free_MotorCurves (struct st_device *dev)
2906{
2907  DBG (DBG_FNC, "> Free_MotorCurves\n");
2908  if (dev->mtrsetting != NULL)
2909    Motor_Curve_Free (dev->mtrsetting, &dev->mtrsetting_count);
2910
2911  dev->mtrsetting = NULL;
2912  dev->mtrsetting_count = 0;
2913}
2914
2915static SANE_Int
2916Load_MotorCurves (struct st_device *dev)
2917{
2918  SANE_Int rst = ERROR;
2919  SANE_Int *mtc = NULL;
2920
2921  if (dev->mtrsetting != NULL)
2922    Free_MotorCurves (dev);
2923
2924  DBG (DBG_FNC, "> Load_MotorCurves\n");
2925
2926  /* get motor settings buffer for this device */
2927  mtc = cfg_motorcurve_get ();
2928  if (mtc != NULL)
2929    {
2930      /* parse buffer to get all motorcurves */
2931      dev->mtrsetting = Motor_Curve_Parse (&dev->mtrsetting_count, mtc);
2932      if (dev->mtrsetting != NULL)
2933	rst = OK;
2934    }
2935
2936  if (rst != ERROR)
2937    {
2938      DBG (DBG_FNC, " -> Found %i motor settings\n", dev->mtrsetting_count);
2939      dbg_motorcurves (dev);
2940    }
2941  else
2942    DBG (DBG_ERR, "- Load_MotorCurves error!!\n");
2943
2944  return rst;
2945}
2946
2947static SANE_Int
2948Load_Motormoves (struct st_device *dev)
2949{
2950  SANE_Int rst = OK;
2951  SANE_Int a;
2952  struct st_motormove reg, *mm;
2953
2954  DBG (DBG_FNC, "> Load_Motormoves\n");
2955
2956  /* if there is already any movement loaded let's free it */
2957  if (dev->motormove != NULL)
2958    Free_Motormoves (dev);
2959
2960  a = 0;
2961  while ((cfg_motormove_get (dev->sensorcfg->type, a, &reg) != ERROR)
2962	 && (rst == OK))
2963    {
2964      dev->motormove_count++;
2965      dev->motormove =
2966	(struct st_motormove **) realloc (dev->motormove,
2967					  sizeof (struct st_motormove **) *
2968					  dev->motormove_count);
2969      if (dev->motormove != NULL)
2970	{
2971	  mm = (struct st_motormove *) malloc (sizeof (struct st_motormove));
2972	  if (mm != NULL)
2973	    {
2974	      memcpy (mm, &reg, sizeof (struct st_motormove));
2975	      dev->motormove[dev->motormove_count - 1] = mm;
2976	    }
2977	  else
2978	    rst = ERROR;
2979	}
2980      else
2981	rst = ERROR;
2982
2983      a++;
2984    }
2985
2986  if (rst == ERROR)
2987    Free_Motormoves (dev);
2988
2989  DBG (DBG_FNC, " -> Found %i motormoves\n", dev->motormove_count);
2990  dbg_motormoves (dev);
2991
2992  return rst;
2993}
2994
2995static SANE_Byte *
2996Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, SANE_Int step)
2997{
2998  steps = (SANE_Byte *) realloc (steps, sizeof (SANE_Byte) * (*bwriten + 3));
2999  if (steps != NULL)
3000    {
3001      data_msb_set (&steps[*bwriten], step, 3);
3002      *bwriten += 3;
3003    }
3004  else
3005    *bwriten = 0;
3006
3007  return steps;
3008}
3009
3010static SANE_Int
3011Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs,
3012		   SANE_Int mysetting)
3013{
3014  SANE_Int varx10, cont, last_acc_step, varx20, stepbuffer_size,
3015    mystep, bwriten;
3016  SANE_Int myvar, var1, myvalor, mybwriten;
3017  struct st_curve *mycurve;
3018  SANE_Byte *steps;
3019
3020  DBG (DBG_FNC, "+ Motor_Setup_Steps(*Regs, motorsetting=%i):\n", mysetting);
3021
3022  varx10 = 0;
3023  cont = 0;
3024  varx20 = 0;
3025  stepbuffer_size = (v15f8 << 4) & 0xffff;
3026  steps = NULL;
3027  bwriten = 0;
3028  deccurvecount = 0;
3029  acccurvecount = 0;
3030  last_acc_step = 0;
3031
3032  /* mycurve points to acc normalscan steps table */
3033  mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_NORMALSCAN);
3034
3035  if (mycurve != NULL)
3036    {
3037      /* acccurvecount has the number of steps in acc normalscan table */
3038      acccurvecount = mycurve->step_count;
3039
3040      /* get last acccurve step from acc.normalscan step table */
3041      last_acc_step = data_lsb_get (&Regs[0xe1], 3);
3042
3043      /* sets pointer to acc.normalscan step table */
3044      data_wide_bitset (&Regs[0xf6], 0x3fff, stepbuffer_size);
3045
3046      /* Separate each step in three bytes */
3047      if (mycurve->step_count > 0)
3048	for (cont = 0; cont < mycurve->step_count; cont++)
3049	  {
3050	    mystep = mycurve->step[cont];
3051	    if (mystep <= last_acc_step)
3052	      {
3053		acccurvecount = cont;
3054		break;
3055	      }
3056	    varx20 += mystep + 1;
3057	    steps = Motor_AddStep (steps, &bwriten, mystep);
3058	  }
3059    }
3060
3061  if (acccurvecount == 0)
3062    {
3063      /* Write one step (last_acc_step + 0x01) to buffer */
3064      acccurvecount++;
3065      varx20 += (last_acc_step + 1) + 1;
3066      steps = Motor_AddStep (steps, &bwriten, last_acc_step + 1);
3067    }
3068
3069  /* write another step (last_acc_step) */
3070  acccurvecount++;
3071  varx20 += last_acc_step + 1;
3072  steps = Motor_AddStep (steps, &bwriten, last_acc_step);
3073
3074  /* get line exposure time */
3075  myvar = data_lsb_get (&Regs[0x30], 3) + 1;
3076
3077  var1 = (varx20 + myvar - 1) / myvar;
3078  var1 = ((var1 * myvar) + mycurve->step[0] - varx20) - 0x0d;
3079  if (steps != NULL)
3080    data_msb_set (&steps[0], var1, 3);
3081
3082  /* dec.scanbufferfull step table */
3083  /* set pointer to next table */
3084  stepbuffer_size += (acccurvecount * 3);
3085  data_wide_bitset (&Regs[0xf8], 0x3fff, stepbuffer_size);
3086
3087  /* set last step of deccurve.scanbufferfull table */
3088  mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_BUFFERFULL);
3089  deccurvecount = mycurve->step_count;
3090  data_lsb_set (&Regs[0xea], mycurve->step[mycurve->step_count - 1], 3);
3091
3092  /* write another step mycurve->step_count,cont,last_acc_step */
3093  deccurvecount++;
3094  steps = Motor_AddStep (steps, &bwriten, last_acc_step);
3095
3096  /* Separate each step in three bytes */
3097  if (mycurve->step_count > 1)
3098    for (cont = 0; cont < (mycurve->step_count - 1); cont++)
3099      {
3100	mystep = mycurve->step[cont];
3101	if (mystep > last_acc_step)
3102	  steps = Motor_AddStep (steps, &bwriten, mystep);
3103	else
3104	  deccurvecount--;
3105      }
3106
3107  myvalor = dev->mtrsetting[mysetting]->motorbackstep;
3108  if (myvalor > 0)
3109    {
3110      SANE_Int step_size = _B0 (Regs[0xe0]) + 1;
3111
3112      myvalor = ((myvalor - deccurvecount) - acccurvecount) + 2;
3113      varx10 = myvalor;
3114      myvalor /= step_size;
3115      myvalor *= step_size;
3116      var1 = mycurve->step[mycurve->step_count - 1];	/* last deccurve step */
3117      if (last_acc_step >= var1)
3118	var1 = last_acc_step + 1;
3119      deccurvecount += (varx10 - myvalor);
3120      myvalor = varx10 - myvalor;
3121    }
3122  else
3123    myvalor = varx10;
3124
3125  if (myvalor > 0)
3126    for (cont = myvalor; cont > 0; cont--)
3127      steps = Motor_AddStep (steps, &bwriten, var1 - 1);
3128
3129  /* write another step , bwriten tiene 4b */
3130  steps = Motor_AddStep (steps, &bwriten, var1);
3131
3132  /* acc.smearing step table */
3133  if (Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING) != NULL)
3134    {
3135      /* acc.smearing curve enabled */
3136      if (Motor_Curve_Equal
3137	  (dev, mysetting, ACC_CURVE, CRV_SMEARING, CRV_NORMALSCAN) == TRUE)
3138	{
3139	  /* acc.smearing pointer points to acc.normalscan table */
3140	  data_wide_bitset (&Regs[0xfa], 0x3fff,
3141			    data_lsb_get (&Regs[0xf6], 2));
3142	  /* last step of acc.smearing table is the same as acc.normalscan */
3143	  data_lsb_set (&Regs[0xe4], data_lsb_get (&Regs[0xe1], 3), 3);
3144	}
3145      else
3146	{
3147	  /* set pointer to next step table */
3148	  stepbuffer_size += (deccurvecount * 3);
3149	  data_wide_bitset (&Regs[0xfa], 0x3fff, stepbuffer_size);
3150
3151	  /* set last step of acc.smearing table */
3152	  mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING);
3153	  if (mycurve != NULL)
3154	    {
3155	      smearacccurvecount = mycurve->step_count;
3156	      data_lsb_set (&Regs[0xe4],
3157			    mycurve->step[mycurve->step_count - 1], 3);
3158
3159	      /* generate acc.smearing table */
3160	      if (mycurve->step_count > 0)
3161		for (cont = 0; cont < mycurve->step_count; cont++)
3162		  steps =
3163		    Motor_AddStep (steps, &bwriten, mycurve->step[cont]);
3164	    }
3165	}
3166    }
3167  else
3168    {
3169      /* acc.smearing curve disabled */
3170      data_wide_bitset (&Regs[0xfa], 0x3fff, 0);
3171    }
3172
3173  /* dec.smearing */
3174  if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING) != NULL)
3175    {
3176      /* dec.smearing curve enabled */
3177      if (Motor_Curve_Equal
3178	  (dev, mysetting, DEC_CURVE, CRV_SMEARING, CRV_BUFFERFULL) == TRUE)
3179	{
3180	  /* dec.smearing pointer points to dec.scanbufferfull table */
3181	  data_wide_bitset (&Regs[0x00fc], 0x3fff,
3182			    data_lsb_get (&Regs[0x00f8], 2));
3183	  /* last step of dec.smearing table is the same as dec.scanbufferfull */
3184	  data_lsb_set (&Regs[0x00f0], data_lsb_get (&Regs[0x00ea], 3), 3);
3185	}
3186      else
3187	{
3188	  /* set pointer to next step table */
3189	  if (mycurve != NULL)
3190	    stepbuffer_size += (mycurve->step_count * 3);
3191	  data_wide_bitset (&Regs[0xfc], 0x3fff, stepbuffer_size);
3192
3193	  /* set last step of dec.smearing table */
3194	  mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING);
3195	  if (mycurve != NULL)
3196	    {
3197	      smeardeccurvecount = mycurve->step_count;
3198	      data_lsb_set (&Regs[0xf0],
3199			    mycurve->step[mycurve->step_count - 1], 3);
3200
3201	      /* generate dec.smearing table */
3202	      if (mycurve->step_count > 0)
3203		for (cont = 0; cont < mycurve->step_count; cont++)
3204		  steps =
3205		    Motor_AddStep (steps, &bwriten, mycurve->step[cont]);
3206	    }
3207	}
3208    }
3209  else
3210    {
3211      /* dec.smearing curve disabled */
3212      data_wide_bitset (&Regs[0x00fc], 0x3fff, 0);
3213    }
3214
3215  /* dec.normalscan */
3216  if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN) != NULL)
3217    {
3218      /* dec.normalscan enabled */
3219      if (Motor_Curve_Equal
3220	  (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_BUFFERFULL) == TRUE)
3221	{
3222	  /* dec.normalscan pointer points to dec.scanbufferfull table */
3223	  data_wide_bitset (&Regs[0xfe], 0x3fff,
3224			    data_lsb_get (&Regs[0xf8], 2));
3225	  /* last step of dec.normalscan table is the same as dec.scanbufferfull */
3226	  data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xea], 3), 3);
3227	}
3228      else
3229	if (Motor_Curve_Equal
3230	    (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_SMEARING) == TRUE)
3231	{
3232	  /* dec.normalscan pointer points to dec.smearing table */
3233	  data_wide_bitset (&Regs[0xfe], 0x3fff,
3234			    data_lsb_get (&Regs[0xfc], 2));
3235	  /* last step of dec.normalscan table is the same as dec.smearing */
3236	  data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xf0], 3), 3);
3237	}
3238      else
3239	{
3240	  /* set pointer to next step table */
3241	  if (mycurve != NULL)
3242	    stepbuffer_size += (mycurve->step_count * 3);
3243	  data_wide_bitset (&Regs[0xfe], 0x3fff, stepbuffer_size);
3244
3245	  /* set last step of dec.normalscan table */
3246	  mycurve =
3247	    Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN);
3248	  if (mycurve != NULL)
3249	    {
3250	      data_lsb_set (&Regs[0xed],
3251			    mycurve->step[mycurve->step_count - 1], 3);
3252
3253	      /* generate dec.normalscan table */
3254	      if (mycurve->step_count > 0)
3255		for (cont = 0; cont < mycurve->step_count; cont++)
3256		  steps =
3257		    Motor_AddStep (steps, &bwriten, mycurve->step[cont]);
3258	    }
3259	}
3260    }
3261  else
3262    {
3263      /* dec.normalscan disabled */
3264      data_wide_bitset (&Regs[0xfe], 0x3fff, 0);
3265    }
3266
3267  /* acc.parkhome */
3268  if (Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME) != NULL)
3269    {
3270      /* parkhome curve enabled */
3271
3272      if (Motor_Curve_Equal
3273	  (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE)
3274	{
3275	  /* acc.parkhome pointer points to acc.normalscan table */
3276	  data_wide_bitset (&Regs[0x100], 0x3fff,
3277			    data_lsb_get (&Regs[0xf6], 2));
3278
3279	  /* last step of acc.parkhome table is the same as acc.normalscan */
3280	  data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe1], 3), 3);
3281	}
3282      else
3283	if (Motor_Curve_Equal
3284	    (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE)
3285	{
3286	  /* acc.parkhome pointer points to acc.smearing table */
3287	  data_wide_bitset (&Regs[0x100], 0x3fff,
3288			    data_lsb_get (&Regs[0xfa], 2));
3289	  /* last step of acc.parkhome table is the same as acc.smearing */
3290	  data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe4], 3), 3);
3291	}
3292      else
3293	{
3294	  /* set pointer to next step table */
3295	  if (mycurve != NULL)
3296	    stepbuffer_size += (mycurve->step_count * 3);
3297	  data_wide_bitset (&Regs[0x100], 0x3fff, stepbuffer_size);
3298
3299	  /* set last step of acc.parkhome table */
3300	  mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME);
3301	  if (mycurve != NULL)
3302	    {
3303	      data_lsb_set (&Regs[0xe7],
3304			    mycurve->step[mycurve->step_count - 1], 3);
3305
3306	      /* generate acc.parkhome table */
3307	      if (mycurve->step_count > 0)
3308		for (cont = 0; cont < mycurve->step_count; cont++)
3309		  steps =
3310		    Motor_AddStep (steps, &bwriten, mycurve->step[cont]);
3311	    }
3312	}
3313    }
3314  else
3315    {
3316      /* parkhome curve is disabled */
3317      /* acc.parkhome pointer points to 0 */
3318      data_wide_bitset (&Regs[0x100], 0x3fff, 0);
3319      data_lsb_set (&Regs[0xe7], 16, 3);
3320    }
3321
3322  /* dec.parkhome */
3323  if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME) != NULL)
3324    {
3325      /* parkhome curve enabled */
3326      if (Motor_Curve_Equal
3327	  (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_BUFFERFULL) == TRUE)
3328	{
3329	  /* dec.parkhome pointer points to dec.scanbufferfull table */
3330	  data_wide_bitset (&Regs[0x102], 0x3fff,
3331			    data_lsb_get (&Regs[0xf8], 2));
3332	  /* last step of dec.parkhome table is the same as dec.scanbufferfull */
3333	  data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xe4], 3), 3);
3334	}
3335      else
3336	if (Motor_Curve_Equal
3337	    (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE)
3338	{
3339	  /* dec.parkhome pointer points to dec.smearing table */
3340	  data_wide_bitset (&Regs[0x102], 0x3fff,
3341			    data_lsb_get (&Regs[0xfe], 2));
3342	  /* last step of dec.parkhome table is the same as dec.smearing */
3343	  data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xf0], 3), 3);
3344	}
3345      else
3346	if (Motor_Curve_Equal
3347	    (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE)
3348	{
3349	  /* dec.parkhome pointer points to dec.normalscan table */
3350	  data_wide_bitset (&Regs[0x102], 0x3fff,
3351			    data_lsb_get (&Regs[0xfe], 2));
3352	  /* last step of dec.parkhome table is the same as dec.normalscan */
3353	  data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xed], 3), 3);
3354	}
3355      else
3356	{
3357	  /* set pointer to next step table */
3358	  if (mycurve != NULL)
3359	    stepbuffer_size += (mycurve->step_count * 3);
3360	  data_wide_bitset (&Regs[0x102], 0x3fff, stepbuffer_size);
3361
3362	  /* set last step of dec.parkhome table */
3363	  mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME);
3364	  if (mycurve != NULL)
3365	    {
3366	      data_lsb_set (&Regs[0xf3],
3367			    mycurve->step[mycurve->step_count - 1], 3);
3368
3369	      /* generate dec.parkhome table */
3370	      if (mycurve->step_count > 0)
3371		for (cont = 0; cont < mycurve->step_count; cont++)
3372		  steps =
3373		    Motor_AddStep (steps, &bwriten, mycurve->step[cont]);
3374	    }
3375	}
3376    }
3377  else
3378    {
3379      /* parkhome curve is disabled */
3380
3381      /* dec.parkhome pointer points to 0 */
3382      data_wide_bitset (&Regs[0x102], 0x3fff, 0);
3383      data_lsb_set (&Regs[0xf3], 16, 3);
3384    }
3385
3386  mybwriten = bwriten & 0x8000000f;
3387  if (mybwriten < 0)
3388    mybwriten = ((mybwriten - 1) | 0xfffffff0) + 1;
3389
3390  if (mybwriten != 0)
3391    bwriten = (((bwriten & 0xffff) >> 0x04) + 1) << 0x04;
3392  bwriten = bwriten & 0xffff;
3393
3394  /* display table */
3395  DBG (DBG_FNC, " -> Direction Type           Offset Last step\n");
3396  DBG (DBG_FNC, " -> --------- -------------- ------ ---------\n");
3397  DBG (DBG_FNC, " -> ACC_CURVE CRV_NORMALSCAN %6i  %6i\n",
3398       data_lsb_get (&Regs[0x0f6], 2) & 0x3fff, data_lsb_get (&Regs[0x0e1],
3399							      3));
3400  DBG (DBG_FNC, " -> ACC_CURVE CRV_SMEARING   %6i  %6i\n",
3401       data_lsb_get (&Regs[0x0fa], 2) & 0x3fff, data_lsb_get (&Regs[0x0e4],
3402							      3));
3403  DBG (DBG_FNC, " -> ACC_CURVE CRV_PARKHOME   %6i  %6i\n",
3404       data_lsb_get (&Regs[0x100], 2) & 0x3fff, data_lsb_get (&Regs[0x0e7],
3405							      3));
3406  DBG (DBG_FNC, " -> DEC_CURVE CRV_NORMALSCAN %6i  %6i\n",
3407       data_lsb_get (&Regs[0x0fe], 2) & 0x3fff, data_lsb_get (&Regs[0x0ed],
3408							      3));
3409  DBG (DBG_FNC, " -> DEC_CURVE CRV_SMEARING   %6i  %6i\n",
3410       data_lsb_get (&Regs[0x0fc], 2) & 0x3fff, data_lsb_get (&Regs[0x0f0],
3411							      3));
3412  DBG (DBG_FNC, " -> DEC_CURVE CRV_PARKHOME   %6i  %6i\n",
3413       data_lsb_get (&Regs[0x102], 2) & 0x3fff, data_lsb_get (&Regs[0x0f3],
3414							      3));
3415  DBG (DBG_FNC, " -> DEC_CURVE CRV_BUFFERFULL %6i  %6i\n",
3416       data_lsb_get (&Regs[0x0f8], 2) & 0x3fff, data_lsb_get (&Regs[0x0ea],
3417							      3));
3418
3419  RTS_Warm_Reset (dev);
3420
3421  /* send motor steps */
3422  if (steps != NULL)
3423    {
3424      if (bwriten > 0)
3425	{
3426	  /* lock */
3427	  SetLock (dev->usb_handle, Regs, TRUE);
3428
3429	  /* send steps */
3430	  RTS_DMA_Write (dev, 0x0000, v15f8, bwriten, steps);
3431
3432	  /* unlock */
3433	  SetLock (dev->usb_handle, Regs, FALSE);
3434	}
3435
3436      free (steps);
3437    }
3438
3439  DBG (DBG_FNC, "- Motor_Setup_Steps: %i\n", acccurvecount);
3440
3441  return acccurvecount;
3442}
3443
3444static SANE_Int
3445Lamp_PWM_use (struct st_device *dev, SANE_Int enable)
3446{
3447  SANE_Byte a, b;
3448  SANE_Int rst = ERROR;
3449
3450  DBG (DBG_FNC, "+ Lamp_PWM_use(enable=%i):\n", enable);
3451
3452  if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK)
3453    {
3454      if (Read_Byte (dev->usb_handle, 0xe9e0, &b) == OK)
3455	{
3456	  if (enable != 0)
3457	    {
3458	      if (pwmlamplevel != 0x00)
3459		{
3460		  b |= 0x80;
3461		  dev->init_regs[0x01e0] &= 0x3f;
3462		  dev->init_regs[0x01e0] |= 0x80;
3463		}
3464	      else
3465		{
3466		  a |= 0x40;
3467		  b &= 0x3f;
3468		  dev->init_regs[0x0148] |= 0x40;
3469		  dev->init_regs[0x01e0] &= 0x3f;
3470		}
3471	    }
3472	  else
3473	    {
3474	      b &= 0x7f;
3475	      a &= 0xbf;
3476	    }
3477
3478	  if (Write_Byte (dev->usb_handle, 0xe948, a) == OK)
3479	    rst = Write_Byte (dev->usb_handle, 0xe9e0, b);
3480	}
3481    }
3482
3483  DBG (DBG_FNC, "- Lamp_PWM_use: %i\n", rst);
3484
3485  return rst;
3486}
3487
3488static SANE_Int
3489SSCG_Enable (struct st_device *dev)
3490{
3491  SANE_Int rst;
3492  SANE_Int sscg;
3493  SANE_Byte data1, data2;
3494  SANE_Int enable, mode, clock;
3495
3496  DBG (DBG_FNC, "+ SSCG_Enable:\n");
3497
3498  rst = cfg_sscg_get (&enable, &mode, &clock);
3499
3500  if (rst == OK)
3501    {
3502      if ((Read_Byte (dev->usb_handle, 0xfe3a, &data1) == OK)
3503	  && (Read_Byte (dev->usb_handle, 0xfe39, &data2) == OK))
3504	{
3505	  if (enable != FALSE)
3506	    {
3507	      /* clock values: 0=0.25%; 1=0.50%; 2=0.75%; 3=1.00% */
3508	      data2 = (mode == 0) ? data2 & 0x7f : data2 | 0x80;
3509
3510	      sscg = (data1 & 0xf3) | (((clock & 0x03) | 0x04) << 0x02);
3511	      sscg = (sscg << 8) | data2;
3512	    }
3513	  else
3514	    sscg = ((data1 & 0xef) << 8) | _B0 (data2);
3515
3516	  rst = Write_Word (dev->usb_handle, 0xfe39, sscg);
3517	}
3518      else
3519	rst = ERROR;
3520    }
3521
3522  DBG (DBG_FNC, "- SSCG_Enable: %i\n", rst);
3523
3524  return rst;
3525}
3526
3527static void
3528RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs)
3529{
3530  /* this function sets top, midle and bottom reference voltages */
3531
3532  DBG (DBG_FNC, "> RTS_Setup_RefVoltages\n");
3533
3534  if (Regs != NULL)
3535    {
3536      SANE_Byte vrts, vrms, vrbs;
3537
3538      cfg_refvoltages_get (dev->sensorcfg->type, &vrts, &vrms, &vrbs);
3539
3540      /* Top Reference Voltage */
3541      data_bitset (&Regs[0x14], 0xe0, vrts);	/*xxx----- */
3542
3543      /* Middle Reference Voltage */
3544      data_bitset (&Regs[0x15], 0xe0, vrms);	/*xxx----- */
3545
3546      /* Bottom Reference Voltage */
3547      data_bitset (&Regs[0x16], 0xe0, vrbs);	/*xxx----- */
3548    }
3549}
3550
3551static SANE_Int
3552Init_USBData (struct st_device *dev)
3553{
3554  SANE_Byte data;
3555  SANE_Byte *resource;
3556
3557  DBG (DBG_FNC, "+ Init_USBData:\n");
3558
3559  if (Read_Byte (dev->usb_handle, 0xf8ff, &data) != OK)
3560    return ERROR;
3561
3562  data = (data | 1);
3563  if (Write_Byte (dev->usb_handle, 0xf8ff, data) != OK)
3564    return ERROR;
3565
3566  if (SSCG_Enable (dev) != OK)
3567    return ERROR;
3568
3569  Init_Registers (dev);
3570
3571  /* Gamma table size = 0x100 */
3572  data_bitset (&dev->init_regs[0x1d0], 0x30, 0x00);	 /*--00----*/
3573
3574  /* Set 3 channels_per_dot */
3575  data_bitset (&dev->init_regs[0x12], 0xc0, 0x03);	/*xx------ */
3576
3577  /* systemclock */
3578  data_bitset (&dev->init_regs[0x00], 0x0f, 0x05);	 /*----xxxx*/
3579
3580  /* timing cnpp */
3581  data_bitset (&dev->init_regs[0x96], 0x3f, 0x17);	 /*--xxxxxx*/
3582
3583  /* set sensor_channel_color_order */
3584  data_bitset (&dev->init_regs[0x60a], 0x7f, 0x24);	 /*-xxxxxxx*/
3585
3586  /* set crvs */
3587  data_bitset (&dev->init_regs[0x10], 0x1f, get_value (SCAN_PARAM, CRVS, 7, usbfile));	   /*---xxxxx*/
3588
3589  /* set reference voltages */
3590  RTS_Setup_RefVoltages (dev, dev->init_regs);
3591
3592  dev->init_regs[0x11] |= 0x10;
3593
3594  data_bitset (&dev->init_regs[0x26], 0x70, 5);	     /*-101----*/
3595
3596  dev->init_regs[0x185] = 0x88;
3597  dev->init_regs[0x186] = 0x88;
3598
3599  /* SDRAM clock */
3600  data = get_value (SCAN_PARAM, MCLKIOC, 8, usbfile);
3601  data_bitset (&dev->init_regs[0x187], 0x0f, 0x08);	 /*----xxxx*/
3602  data_bitset (&dev->init_regs[0x187], 0xf0, data);	/*xxxx---- */
3603
3604  data--;
3605
3606  if (data < 7)
3607    {
3608      switch (data)
3609	{
3610	case 0:
3611	  data |= 0xc0;
3612	  break;
3613	case 1:
3614	  data |= 0xa0;
3615	  break;
3616	case 2:
3617	  data |= 0xe0;
3618	  break;
3619	case 3:
3620	  data |= 0x90;
3621	  break;
3622	case 4:
3623	  data |= 0xd0;
3624	  break;
3625	case 5:
3626	  data |= 0xb0;
3627	  break;
3628	case 6:
3629	  data = (data & 0x0f);
3630	  break;
3631	}
3632      dev->init_regs[0x187] = _B0 (data);
3633    }
3634
3635  data_bitset (&dev->init_regs[0x26], 0x0f, 0);	     /*----0000*/
3636
3637  dev->init_regs[0x27] &= 0x3f;
3638  dev->init_regs[0x29] = 0x24;
3639  dev->init_regs[0x2a] = 0x10;
3640  dev->init_regs[0x150] = 0xff;
3641  dev->init_regs[0x151] = 0x13;
3642  dev->init_regs[0x156] = 0xf0;
3643  dev->init_regs[0x157] = 0xfd;
3644
3645  if (dev->motorcfg->changemotorcurrent != FALSE)
3646    Motor_Change (dev, dev->init_regs, 3);
3647
3648  dev->init_regs[0xde] = 0;
3649  data_bitset (&dev->init_regs[0xdf], 0x0f, 0);
3650
3651  /* loads motor resource for this dev */
3652  resource = cfg_motor_resource_get (&data);
3653  if ((resource != NULL) && (data > 1))
3654    memcpy (&dev->init_regs[0x104], resource, data);
3655
3656  /* this bit is set but I don't know its purpose */
3657  dev->init_regs[0x01] |= 0x40;	      /*-1------*/
3658
3659  dev->init_regs[0x124] = 0x94;
3660
3661  /* release motor */
3662  Motor_Release (dev);
3663
3664  DBG (DBG_FNC, "- Init_USBData:\n");
3665
3666  return OK;
3667}
3668
3669static SANE_Int
3670Init_Registers (struct st_device *dev)
3671{
3672  SANE_Int rst = OK;
3673
3674  DBG (DBG_FNC, "+ Init_Registers:\n");
3675
3676  /* Lee dev->init_regs */
3677  memset (dev->init_regs, 0, RT_BUFFER_LEN);
3678  RTS_ReadRegs (dev->usb_handle, dev->init_regs);
3679  Read_FE3E (dev, &v1619);
3680
3681  if (dev->sensorcfg->type == CCD_SENSOR)
3682    {
3683      /* CCD sensor */
3684      data_bitset (&dev->init_regs[0x11], 0xc0, 0);	/*xx------ */
3685      data_bitset (&dev->init_regs[0x146], 0x80, 1);	/*x------- */
3686      data_bitset (&dev->init_regs[0x146], 0x40, 1);		/*-x------*/
3687
3688    }
3689  else
3690    {
3691      /* CIS sensor */
3692      data_bitset (&dev->init_regs[0x146], 0x80, 0);	/*0------- */
3693      data_bitset (&dev->init_regs[0x146], 0x40, 0);		/*-0------*/
3694      data_bitset (&dev->init_regs[0x11], 0xc0, 2);	/*xx------ */
3695      data_bitset (&dev->init_regs[0xae], 0x3f, 0x14);		/*--xxxxxx*/
3696      data_bitset (&dev->init_regs[0xaf], 0x07, 1);		/*-----xxx*/
3697
3698      dev->init_regs[0x9c] = dev->init_regs[0xa2] = dev->init_regs[0xa8] =
3699	(RTS_Debug->dev_model != UA4900) ? 1 : 0;
3700      dev->init_regs[0x9d] = dev->init_regs[0xa3] = dev->init_regs[0xa9] = 0;
3701      dev->init_regs[0x9e] = dev->init_regs[0xa4] = dev->init_regs[0xaa] = 0;
3702      dev->init_regs[0x9f] = dev->init_regs[0xa5] = dev->init_regs[0xab] = 0;
3703      dev->init_regs[0xa0] = dev->init_regs[0xa6] = dev->init_regs[0xac] = 0;
3704      dev->init_regs[0xa1] = dev->init_regs[0xa7] = dev->init_regs[0xad] =
3705	(RTS_Debug->dev_model != UA4900) ? 0x80 : 0;
3706    }
3707
3708  /* disable CCD channels */
3709  data_bitset (&dev->init_regs[0x10], 0xe0, 0);	/*xxx----- */
3710  data_bitset (&dev->init_regs[0x13], 0x80, 0);	/*x------- */
3711
3712  /* enable timer to switch off lamp */
3713  data_bitset (&dev->init_regs[0x146], 0x10, 1);	 /*---x----*/
3714
3715  /* set time to switch off lamp */
3716  dev->init_regs[0x147] = 0xff;
3717
3718  /* set last acccurve step */
3719  data_lsb_set (&dev->init_regs[0xe1], 0x2af8, 3);
3720
3721  /* set msi 0x02 */
3722  dev->init_regs[0xda] = 0x02;
3723  data_bitset (&dev->init_regs[0xdd], 0x03, 0);		/*------xx*/
3724
3725  /* set binary threshold high and low in little endian */
3726  data_lsb_set (&dev->init_regs[0x19e], binarythresholdl, 2);
3727  data_lsb_set (&dev->init_regs[0x1a0], binarythresholdh, 2);
3728
3729
3730  data_bitset (&dev->init_regs[0x01], 0x08, 0);		/*----x---*/
3731  data_bitset (&dev->init_regs[0x16f], 0x40, 0);	/*-x------*/
3732  dev->init_regs[0x0bf] = (dev->init_regs[0x00bf] & 0xe0) | 0x20;
3733  dev->init_regs[0x163] = (dev->init_regs[0x0163] & 0x3f) | 0x40;
3734
3735  data_bitset (&dev->init_regs[0xd6], 0x0f, 8);		/*----xxxx*/
3736  data_bitset (&dev->init_regs[0x164], 0x80, 1);	/*x------- */
3737
3738  dev->init_regs[0x0bc] = 0x00;
3739  dev->init_regs[0x0bd] = 0x00;
3740
3741  dev->init_regs[0x165] = (dev->init_regs[0x0165] & 0x3f) | 0x80;
3742  dev->init_regs[0x0ed] = 0x10;
3743  dev->init_regs[0x0be] = 0x00;
3744  dev->init_regs[0x0d5] = 0x00;
3745
3746  dev->init_regs[0xee] = 0x00;
3747  dev->init_regs[0xef] = 0x00;
3748  dev->init_regs[0xde] = 0xff;
3749
3750  /* set bit[4] has_curves = 0 | bit[0..3] unknown = 0 */
3751  data_bitset (&dev->init_regs[0xdf], 0x10, 0);		/*---x----*/
3752  data_bitset (&dev->init_regs[0xdf], 0x0f, 0);		/*----xxxx*/
3753
3754  /* Set motor type */
3755  data_bitset (&dev->init_regs[0xd7], 0x80, dev->motorcfg->type);	/*x------- */
3756
3757  if (dev->motorcfg->type == MT_ONCHIP_PWM)
3758    {
3759      data_bitset (&dev->init_regs[0x14e], 0x10, 1);	      /*---x----*/
3760
3761      /* set motorpwmfrequency */
3762      data_bitset (&dev->init_regs[0xd7], 0x3f, dev->motorcfg->pwmfrequency);	       /*--xxxxxx*/
3763    }
3764
3765  dev->init_regs[0x600] &= 0xfb;
3766  dev->init_regs[0x1d8] |= 0x08;
3767
3768  v160c_block_size = 0x04;
3769  mem_total = 0x80000;
3770
3771  /* check and setup installed ram */
3772  RTS_DMA_CheckType (dev, dev->init_regs);
3773  rst = RTS_DMA_WaitReady (dev, 1500);
3774
3775  DBG (DBG_FNC, "- Init_Registers: %i\n", rst);
3776
3777  return rst;
3778}
3779
3780static SANE_Int
3781Read_FE3E (struct st_device *dev, SANE_Byte * destino)
3782{
3783  SANE_Int rst;
3784
3785  DBG (DBG_FNC, "+ Read_FE3E:\n");
3786
3787  rst = ERROR;
3788  if (destino != NULL)
3789    {
3790      SANE_Byte data;
3791      if (Read_Byte (dev->usb_handle, 0xfe3e, &data) == 0)
3792	{
3793	  *destino = data;
3794	  rst = OK;
3795	  DBG (DBG_FNC, " -> %02x\n", _B0 (data));
3796	}
3797    }
3798
3799  DBG (DBG_FNC, "- Read_FE3E: %i\n", rst);
3800
3801  return rst;
3802}
3803
3804static SANE_Int
3805Head_IsAtHome (struct st_device *dev, SANE_Byte * Regs)
3806{
3807  SANE_Int rst;
3808
3809  DBG (DBG_FNC, "+ Head_IsAtHome:\n");
3810
3811  /* if returns TRUE, lamp is at home. Otherwise it returns FALSE */
3812  rst = 0;
3813
3814  if (Regs != NULL)
3815    {
3816      SANE_Byte data;
3817      if (Read_Byte (dev->usb_handle, 0xe96f, &data) == OK)
3818	{
3819	  Regs[0x16f] = _B0 (data);
3820	  rst = (data >> 6) & 1;
3821	}
3822    }
3823
3824  rst = (rst == 1) ? TRUE : FALSE;
3825
3826  DBG (DBG_FNC, "- Head_IsAtHome: %s\n", (rst == TRUE) ? "Yes" : "No");
3827
3828  return rst;
3829}
3830
3831static SANE_Byte
3832RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs)
3833{
3834  SANE_Byte rst;
3835
3836  DBG (DBG_FNC, "+ RTS_IsExecuting:\n");
3837
3838  rst = 0;
3839
3840  if (Regs != NULL)
3841    {
3842      SANE_Byte data;
3843      if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK)
3844	{
3845	  Regs[0x00] = data;
3846	  rst = (data >> 7) & 1;
3847	}
3848    }
3849
3850  DBG (DBG_FNC, "- RTS_IsExecuting: %i\n", rst);
3851
3852  return rst;
3853}
3854
3855static SANE_Int
3856RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs)
3857{
3858  SANE_Byte data;
3859  SANE_Int rst;
3860
3861  DBG (DBG_FNC, "+ RTS_WaitScanEnd(msecs=%i):\n", msecs);
3862
3863  /* returns 0 if ok or timeout
3864     returns -1 if fails */
3865
3866  rst = ERROR;
3867
3868  if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK)
3869    {
3870      long ticks = GetTickCount () + msecs;
3871      rst = OK;
3872      while (((data & 0x80) != 0) && (ticks > GetTickCount ()) && (rst == OK))
3873	{
3874	  rst = Read_Byte (dev->usb_handle, 0xe800, &data);
3875	}
3876    }
3877
3878  DBG (DBG_FNC, "- RTS_WaitScanEnd: Ending with rst=%i\n", rst);
3879
3880  return rst;
3881}
3882
3883static SANE_Int
3884RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels)
3885{
3886  SANE_Int rst = ERROR;
3887
3888  DBG (DBG_FNC, "+ RTS_Enable_CCD(*Regs, arg2=%i):\n", channels);
3889
3890  if (Read_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4) == OK)
3891    {
3892      data_bitset (&Regs[0x10], 0xe0, channels);	/*xxx----- */
3893      data_bitset (&Regs[0x13], 0x80, channels >> 3);	/*x------- */
3894
3895      Write_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4);
3896      rst = OK;
3897    }
3898
3899  DBG (DBG_FNC, "- RTS_Enable_CCD: %i\n", rst);
3900
3901  return rst;
3902}
3903
3904static SANE_Int
3905RTS_Warm_Reset (struct st_device *dev)
3906{
3907  SANE_Byte data;
3908  SANE_Int rst;
3909
3910  DBG (DBG_FNC, "+ RTS_Warm_Reset:\n");
3911
3912  rst = ERROR;
3913  if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK)
3914    {
3915      data = (data & 0x3f) | 0x40;	/*01------ */
3916      if (Write_Byte (dev->usb_handle, 0xe800, data) == OK)
3917	{
3918	  data &= 0xbf;		      /*-0------*/
3919	  rst = Write_Byte (dev->usb_handle, 0xe800, data);
3920	}
3921    }
3922
3923  DBG (DBG_FNC, "- RTS_Warm_Reset: %i\n", rst);
3924
3925  return rst;
3926}
3927
3928static SANE_Int
3929Lamp_Status_Timer_Set (struct st_device *dev, SANE_Int minutes)
3930{
3931  SANE_Byte MyBuffer[2];
3932  SANE_Int rst;
3933
3934  DBG (DBG_FNC, "+ Lamp_Status_Timer_Set(minutes=%i):\n", minutes);
3935
3936  MyBuffer[0] = dev->init_regs[0x0146] & 0xef;
3937  MyBuffer[1] = dev->init_regs[0x0147];
3938
3939  if (minutes > 0)
3940    {
3941      double rst, op2;
3942
3943      minutes = _B0 (minutes);
3944      op2 = 2.682163611980331;
3945      MyBuffer[0x00] |= 0x10;
3946      rst = (minutes * op2);
3947      MyBuffer[0x01] = (SANE_Byte) floor (rst);
3948    }
3949
3950  dev->init_regs[0x147] = MyBuffer[1];
3951  dev->init_regs[0x146] =
3952    (dev->init_regs[0x146] & 0xef) | (MyBuffer[0] & 0x10);
3953
3954  rst =
3955    Write_Word (dev->usb_handle, 0xe946,
3956		(SANE_Int) ((MyBuffer[1] << 8) + MyBuffer[0]));
3957
3958  DBG (DBG_FNC, "- Lamp_Status_Timer_Set: %i\n", rst);
3959
3960  return rst;
3961}
3962
3963static SANE_Int
3964Buttons_Enable (struct st_device *dev)
3965{
3966  SANE_Int data, rst;
3967
3968  DBG (DBG_FNC, "+ Buttons_Enable:\n");
3969
3970  if (Read_Word (dev->usb_handle, 0xe958, &data) == OK)
3971    {
3972      data |= 0x0f;
3973      rst = Write_Word (dev->usb_handle, 0xe958, data);
3974    }
3975  else
3976    rst = ERROR;
3977
3978  DBG (DBG_FNC, "- Buttons_Enable: %i\n", rst);
3979
3980  return rst;
3981}
3982
3983static SANE_Int
3984Buttons_Count (struct st_device *dev)
3985{
3986  SANE_Int rst = 0;
3987
3988  /* This chipset supports up to six buttons */
3989
3990  if (dev->buttons != NULL)
3991    rst = dev->buttons->count;
3992
3993  DBG (DBG_FNC, "> Buttons_Count: %i\n", rst);
3994
3995  return rst;
3996}
3997
3998static SANE_Int
3999Buttons_Status (struct st_device *dev)
4000{
4001  SANE_Int rst = -1;
4002  SANE_Byte data;
4003
4004  DBG (DBG_FNC, "+ Buttons_Status\n");
4005
4006  /* Each bit is 1 if button is not pressed, and 0 if it is pressed
4007     This chipset supports up to six buttons */
4008
4009  if (Read_Byte (dev->usb_handle, 0xe968, &data) == OK)
4010    rst = _B0 (data);
4011
4012  DBG (DBG_FNC, "- Buttons_Status: %i\n", rst);
4013
4014  return rst;
4015}
4016
4017static SANE_Int
4018Buttons_Released (struct st_device *dev)
4019{
4020  SANE_Int rst = -1;
4021  SANE_Byte data;
4022
4023  DBG (DBG_FNC, "+ Buttons_Released\n");
4024
4025  /* Each bit is 1 if button is released, until reading this register. Then
4026     entire register is cleared. This chipset supports up to six buttons */
4027
4028  if (Read_Byte (dev->usb_handle, 0xe96a, &data) == OK)
4029    rst = _B0 (data);
4030
4031  DBG (DBG_FNC, "- Buttons_Released: %i\n", rst);
4032
4033  return rst;
4034}
4035
4036static SANE_Int
4037Buttons_Order (struct st_device *dev, SANE_Int mask)
4038{
4039  /* this is a way to order each button according to its bit in register 0xe968 */
4040  SANE_Int rst = -1;
4041
4042  if (dev->buttons != NULL)
4043    {
4044      SANE_Int a;
4045
4046      for (a = 0; a < 6; a++)
4047	{
4048	  if (dev->buttons->mask[a] == mask)
4049	    {
4050	      rst = a;
4051	      break;
4052	    }
4053	}
4054    }
4055
4056  return rst;
4057}
4058
4059static SANE_Int
4060GainOffset_Clear (struct st_device *dev)
4061{
4062  SANE_Int rst = OK;
4063
4064  DBG (DBG_FNC, "+ GainOffset_Clear:\n");
4065
4066  /* clear offsets */
4067  offset[CL_RED] = offset[CL_GREEN] = offset[CL_BLUE] = 0;
4068
4069  /* save offsets */
4070  /* check if chipset supports accessing eeprom */
4071  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
4072    {
4073      SANE_Int a;
4074
4075      for (a = CL_RED; a <= CL_BLUE; a++)
4076	RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (2 * a), 0);
4077
4078      /* update checksum */
4079      rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, 0);
4080    }
4081
4082  DBG (DBG_FNC, "- GainOffset_Clear: %i\n", rst);
4083
4084  return rst;
4085}
4086
4087static SANE_Int
4088Lamp_Status_Get (struct st_device *dev, SANE_Byte * flb_lamp,
4089		 SANE_Byte * tma_lamp)
4090{
4091  /* The only reason that I think windows driver uses two variables to get
4092     which lamp is switched on instead of one variable is that some chipset
4093     model could have both lamps switched on, so I'm maintaining such var */
4094
4095  SANE_Int rst = ERROR;		/* default */
4096
4097  DBG (DBG_FNC, "+ Lamp_Status_Get:\n");
4098
4099  if ((flb_lamp != NULL) && (tma_lamp != NULL))
4100    {
4101      SANE_Int data1;
4102      SANE_Byte data2;
4103
4104      if (Read_Byte (dev->usb_handle, 0xe946, &data2) == OK)
4105	{
4106	  if (Read_Word (dev->usb_handle, 0xe954, &data1) == OK)
4107	    {
4108	      rst = OK;
4109
4110	      *flb_lamp = 0;
4111	      *tma_lamp = 0;
4112
4113	      switch (dev->chipset->model)
4114		{
4115		case RTS8822BL_03A:
4116		  *flb_lamp = ((data2 & 0x40) != 0) ? 1 : 0;
4117		  *tma_lamp = (((data2 & 0x20) != 0)
4118			       && ((data1 & 0x10) != 0)) ? 1 : 0;
4119		  break;
4120		default:
4121		  if ((_B1 (data1) & 0x10) == 0)
4122		    *flb_lamp = (data2 >> 6) & 1;
4123		  else
4124		    *tma_lamp = (data2 >> 6) & 1;
4125		  break;
4126		}
4127	    }
4128	}
4129    }
4130
4131  DBG (DBG_FNC, "- Lamp_Status_Get: rst=%i flb=%i tma=%i\n", rst,
4132       _B0 (*flb_lamp), _B0 (*tma_lamp));
4133
4134  return rst;
4135}
4136
4137static SANE_Int
4138RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs)
4139{
4140  SANE_Byte data;
4141  SANE_Int rst;
4142  long mytime;
4143
4144  DBG (DBG_FNC, "+ RTS_DMA_WaitReady(msecs=%i):\n", msecs);
4145
4146  rst = OK;
4147  mytime = GetTickCount () + msecs;
4148
4149  while ((mytime > GetTickCount ()) && (rst == OK))
4150    {
4151      if (Read_Byte (dev->usb_handle, 0xef09, &data) == OK)
4152	{
4153	  if ((data & 1) == 0)
4154	    usleep (1000 * 100);
4155	  else
4156	    break;
4157	}
4158      else
4159	rst = ERROR;
4160    }
4161
4162  DBG (DBG_FNC, "- RTS_DMA_WaitReady: %i\n", rst);
4163
4164  return rst;
4165}
4166
4167static SANE_Int
4168RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs)
4169{
4170  SANE_Byte data;
4171  SANE_Int rst;
4172  long mytime;
4173
4174  DBG (DBG_FNC, "+ RTS_WaitInitEnd(msecs=%i):\n", msecs);
4175
4176  rst = OK;
4177  mytime = GetTickCount () + msecs;
4178
4179  while ((mytime > GetTickCount ()) && (rst == OK))
4180    {
4181      if (Read_Byte (dev->usb_handle, 0xf910, &data) == OK)
4182	{
4183	  if ((data & 8) == 0)
4184	    usleep (1000 * 100);
4185	  else
4186	    break;
4187	}
4188      else
4189	rst = ERROR;
4190    }
4191
4192  DBG (DBG_FNC, "- RTS_WaitInitEnd: %i\n", rst);
4193
4194  return rst;
4195}
4196
4197static SANE_Int
4198Motor_Change (struct st_device *dev, SANE_Byte * buffer, SANE_Byte value)
4199{
4200  SANE_Int data, rst;
4201
4202  DBG (DBG_FNC, "+ Motor_Change(*buffer, value=%i):\n", value);
4203
4204  if (Read_Word (dev->usb_handle, 0xe954, &data) == OK)
4205    {
4206      data &= 0xcf;	      /*--00----*/
4207      value--;
4208      switch (value)
4209	{
4210	case 2:
4211	  data |= 0x30;
4212	  break;				     /*--11----*/
4213	case 1:
4214	  data |= 0x20;
4215	  break;				     /*--10----*/
4216	case 0:
4217	  data |= 0x10;
4218	  break;				     /*--01----*/
4219	}
4220
4221      buffer[0x154] = _B0 (data);
4222
4223      rst = Write_Byte (dev->usb_handle, 0xe954, buffer[0x154]);
4224    }
4225  else
4226    rst = ERROR;
4227
4228  DBG (DBG_FNC, "- Motor_Change: %i\n", rst);
4229
4230  return rst;
4231}
4232
4233static SANE_Int
4234RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int options,
4235	      SANE_Int size, SANE_Byte * buffer)
4236{
4237  SANE_Int rst = ERROR;
4238
4239  DBG (DBG_FNC,
4240       "+ RTS_DMA_Read(dmacs=%04x, options=%04x, size=%i., *buffer):\n",
4241       dmacs, options, size);
4242
4243  /* is there any buffer to send? */
4244  if ((buffer != NULL) && (size > 0))
4245    {
4246      /* reset dma */
4247      if (RTS_DMA_Reset (dev) == OK)
4248	{
4249	  /* prepare dma to read */
4250	  if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == OK)
4251	    {
4252	      SANE_Int transferred;
4253
4254	      rst =
4255		Bulk_Operation (dev, BLK_READ, size, buffer, &transferred);
4256	    }
4257	}
4258    }
4259
4260  DBG (DBG_FNC, "- RTS_DMA_Read(): %i\n", rst);
4261
4262  return rst;
4263}
4264
4265static SANE_Int
4266RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int options,
4267	       SANE_Int size, SANE_Byte * buffer)
4268{
4269  SANE_Int rst = ERROR;
4270
4271  DBG (DBG_FNC,
4272       "+ RTS_DMA_Write(dmacs=%04x, options=%04x, size=%i., *buffer):\n",
4273       dmacs, options, size);
4274
4275  /* is there any buffer to send? */
4276  if ((buffer != NULL) && (size > 0))
4277    {
4278      /* reset dma */
4279      if (RTS_DMA_Reset (dev) == OK)
4280	{
4281	  /* prepare dma to write */
4282	  if (RTS_DMA_Enable_Write (dev, dmacs, size, options) == OK)
4283	    {
4284	      SANE_Int transferred;
4285	      SANE_Byte *check_buffer;
4286
4287	      check_buffer = (SANE_Byte *) malloc (size);
4288	      if (check_buffer != NULL)
4289		{
4290		  /* if some transfer fails we try again until ten times */
4291		  SANE_Int a;
4292		  for (a = 10; a > 0; a--)
4293		    {
4294		      /* send buffer */
4295		      Bulk_Operation (dev, BLK_WRITE, size, buffer,
4296				      &transferred);
4297
4298		      /* prepare dma to read */
4299		      if (RTS_DMA_Enable_Read (dev, dmacs, size, options) ==
4300			  OK)
4301			{
4302			  SANE_Int b = 0, diff = FALSE;
4303
4304			  /* read buffer */
4305			  Bulk_Operation (dev, BLK_READ, size, check_buffer,
4306					  &transferred);
4307
4308			  /* check buffers */
4309			  while ((b < size) && (diff == FALSE))
4310			    {
4311			      if (buffer[b] == check_buffer[b])
4312				b++;
4313			      else
4314				diff = TRUE;
4315			    }
4316
4317			  /* if buffers are equal we can break loop */
4318			  if (diff == TRUE)
4319			    {
4320			      /* cancel dma */
4321			      RTS_DMA_Cancel (dev);
4322
4323			      /* prepare dma to write buffer again */
4324			      if (RTS_DMA_Enable_Write
4325				  (dev, dmacs, size, options) != OK)
4326				break;
4327			    }
4328			  else
4329			    {
4330			      /* everything went ok */
4331			      rst = OK;
4332			      break;
4333			    }
4334			}
4335		      else
4336			break;
4337		    }
4338
4339		  /* free check buffer */
4340		  free (check_buffer);
4341		}
4342	      else
4343		{
4344		  /* for some reason it's not possible to allocate space to check
4345		     sent buffer so we just write data */
4346		  Bulk_Operation (dev, BLK_WRITE, size, buffer, &transferred);
4347		  rst = OK;
4348		}
4349	    }
4350	}
4351    }
4352
4353  DBG (DBG_FNC, "- RTS_DMA_Write(): %i\n", rst);
4354
4355  return rst;
4356}
4357
4358static SANE_Int
4359RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs)
4360{
4361  /* This function tries to detect what kind of RAM supports chipset */
4362  /* Returns a value between 0 and 4. -1 means error */
4363
4364  SANE_Int rst = -1;
4365
4366  DBG (DBG_FNC, "+ RTS_DMA_CheckType(*Regs):\n");
4367
4368  if (Regs != NULL)
4369    {
4370      SANE_Byte *out_buffer;
4371
4372      /* define buffer to send */
4373      out_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072);
4374      if (out_buffer != NULL)
4375	{
4376	  SANE_Byte *in_buffer;
4377
4378	  /* define incoming buffer */
4379	  in_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072);
4380	  if (in_buffer != NULL)
4381	    {
4382	      SANE_Int a, b, diff;
4383
4384	      /* fill outgoing buffer with a known pattern */
4385	      b = 0;
4386	      for (a = 0; a < 2072; a++)
4387		{
4388		  out_buffer[a] = b;
4389		  b++;
4390		  if (b == 0x61)
4391		    b = 0;
4392		}
4393
4394	      /* let's send buffer with different ram types and compare
4395	         incoming buffer until getting the right type */
4396
4397	      for (a = 4; a >= 0; a--)
4398		{
4399		  /* set ram type */
4400		  if (RTS_DMA_SetType (dev, Regs, a) != OK)
4401		    break;
4402
4403		  /* wait 1500 milliseconds */
4404		  if (RTS_DMA_WaitReady (dev, 1500) == OK)
4405		    {
4406		      /* reset dma */
4407		      RTS_DMA_Reset (dev);
4408
4409		      /* write buffer */
4410		      RTS_DMA_Write (dev, 0x0004, 0x102, 2072, out_buffer);
4411
4412		      /* now read buffer */
4413		      RTS_DMA_Read (dev, 0x0004, 0x102, 2072, in_buffer);
4414
4415		      /* check buffers */
4416		      b = 0;
4417		      diff = FALSE;
4418		      while ((b < 2072) && (diff == FALSE))
4419			{
4420			  if (out_buffer[b] == in_buffer[b])
4421			    b++;
4422			  else
4423			    diff = TRUE;
4424			}
4425
4426		      /* if buffers are equal */
4427		      if (diff == FALSE)
4428			{
4429			  SANE_Int data = 0;
4430
4431			  /* buffers are equal so we've found the right ram type */
4432			  memset (out_buffer, 0, 0x20);
4433			  for (b = 0; b < 0x20; b += 2)
4434			    out_buffer[b] = b;
4435
4436			  /* write buffer */
4437			  if (RTS_DMA_Write
4438			      (dev, 0x0004, 0x0000, 0x20, out_buffer) == OK)
4439			    {
4440			      SANE_Int c = 0;
4441			      diff = TRUE;
4442
4443			      do
4444				{
4445				  c++;
4446				  for (b = 1; b < 0x20; b += 2)
4447				    out_buffer[b] = c;
4448
4449				  if (RTS_DMA_Write
4450				      (dev, 0x0004, (_B0 (c) << 0x11) >> 0x04,
4451				       0x20, out_buffer) == OK)
4452				    {
4453				      if (RTS_DMA_Read
4454					  (dev, 0x0004, 0x0000, 0x20,
4455					   in_buffer) == OK)
4456					{
4457					  b = 0;
4458					  diff = FALSE;
4459					  while ((b < 0x20)
4460						 && (diff == FALSE))
4461					    {
4462					      if (out_buffer[b] ==
4463						  in_buffer[b])
4464						b++;
4465					      else
4466						diff = TRUE;
4467					    }
4468
4469					  if (diff == FALSE)
4470					    data = c << 7;
4471					}
4472				    }
4473				}
4474			      while ((c < 0x80) && (diff == TRUE));
4475			    }
4476
4477			  switch (data)
4478			    {
4479			    case 16384:
4480			      Regs[0x708] &= 0x1f;
4481			      Regs[0x708] |= 0x80;
4482			      break;
4483			    case 8192:
4484			      Regs[0x708] &= 0x1f;
4485			      Regs[0x708] |= 0x60;
4486			      break;
4487			    case 4096:
4488			      Regs[0x708] &= 0x1f;
4489			      Regs[0x708] |= 0x40;
4490			      break;
4491			    case 2048:
4492			      Regs[0x708] &= 0x1f;
4493			      Regs[0x708] |= 0x20;
4494			      break;
4495			    case 1024:
4496			      Regs[0x708] &= 0x1f;
4497			      data = 0x200;
4498			      break;
4499			    case 128:
4500			      Regs[0x708] &= 0x1f;
4501			      break;
4502			    }
4503
4504			  DBG (DBG_FNC, " -> data1 = 0x%08x\n",
4505			       (data * 4) * 1024);
4506			  DBG (DBG_FNC, " -> data2 = 0x%08x\n", data * 1024);
4507			  DBG (DBG_FNC, " -> type  = 0x%04x\n",
4508			       Regs[0x708] >> 5);
4509
4510			  RTS_DMA_SetType (dev, Regs, Regs[0x708] >> 5);
4511
4512			  rst = OK;
4513			  break;
4514			}
4515		    }
4516		  else
4517		    break;
4518		}
4519
4520	      free (in_buffer);
4521	    }
4522
4523	  free (out_buffer);
4524	}
4525    }
4526
4527  DBG (DBG_FNC, "- RTS_DMA_CheckType(): %i\n", rst);
4528
4529  return rst;
4530}
4531
4532static SANE_Int
4533RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, SANE_Byte ramtype)
4534{
4535  SANE_Int rst = ERROR;
4536
4537  DBG (DBG_FNC, "+ RTS_DMA_SetType(*Regs, ramtype=%i):\n", ramtype);
4538
4539  if (Regs != NULL)
4540    {
4541      data_bitset (&Regs[0x708], 0x08, 0);	    /*----0---*/
4542
4543      if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK)
4544	{
4545	  data_bitset (&Regs[0x708], 0xe0, ramtype);
4546
4547	  if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK)
4548	    {
4549	      data_bitset (&Regs[0x708], 0x08, 1);		    /*----1---*/
4550	      rst = Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]);
4551	    }
4552	}
4553    }
4554
4555  DBG (DBG_FNC, "- RTS_DMA_SetType: %i\n", rst);
4556
4557  return rst;
4558}
4559
4560static void
4561Motor_Release (struct st_device *dev)
4562{
4563  SANE_Byte data = 0;
4564
4565  DBG (DBG_FNC, "+ Motor_Release:\n");
4566
4567  if (Read_Byte (dev->usb_handle, 0xe8d9, &data) == OK)
4568    {
4569      data |= 4;
4570      Write_Byte (dev->usb_handle, 0xe8d9, data);
4571    }
4572
4573  DBG (DBG_FNC, "- Motor_Release:\n");
4574}
4575
4576static SANE_Byte
4577GainOffset_Counter_Load (struct st_device *dev)
4578{
4579  SANE_Byte data = 0x0f;
4580
4581  DBG (DBG_FNC, "+ GainOffset_Counter_Load:\n");
4582
4583  /* check if chipset supports accessing eeprom */
4584  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
4585    if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x77, &data) != OK)
4586      data = 0x0f;
4587
4588  DBG (DBG_FNC, "- GainOffset_Counter_Load: %i\n", _B0 (data));
4589
4590  return data;
4591}
4592
4593static SANE_Int
4594RTS_Execute (struct st_device *dev)
4595{
4596  SANE_Byte e813, e800;
4597  SANE_Int ret;
4598
4599  DBG (DBG_FNC, "+ RTS_Execute:\n");
4600
4601  e813 = 0;
4602  e800 = 0;
4603  ret = ERROR;
4604
4605  if (Read_Byte (dev->usb_handle, 0xe800, &e800) == OK)
4606    {
4607      if (Read_Byte (dev->usb_handle, 0xe813, &e813) == OK)
4608	{
4609	  e813 &= 0xbf;
4610	  if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK)
4611	    {
4612	      e800 |= 0x40;
4613	      if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK)
4614		{
4615		  e813 |= 0x40;
4616		  if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK)
4617		    {
4618		      e800 &= 0xbf;
4619		      if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK)
4620			{
4621			  usleep (1000 * 100);
4622			  e800 |= 0x80;
4623			  ret = Write_Byte (dev->usb_handle, 0xe800, e800);
4624			}
4625		    }
4626		}
4627	    }
4628	}
4629    }
4630
4631  DBG (DBG_FNC, "- RTS_Execute: %i\n", ret);
4632
4633  return ret;
4634}
4635
4636static SANE_Int
4637RTS_isTmaAttached (struct st_device *dev)
4638{
4639  SANE_Int rst;
4640
4641  DBG (DBG_FNC, "+ RTS_isTmaAttached:\n");
4642
4643  /* returns 0 if Tma is attached. Otherwise 1 */
4644  if (Read_Word (dev->usb_handle, 0xe968, &rst) == OK)
4645    {
4646      rst = ((_B1 (rst) & 2) != 0) ? FALSE : TRUE;
4647    }
4648  else
4649    rst = TRUE;
4650
4651  DBG (DBG_FNC, "- RTS_isTmaAttached: %s\n", (rst == TRUE) ? "Yes" : "No");
4652
4653  return rst;
4654}
4655
4656static SANE_Int
4657Gamma_AllocTable (SANE_Byte * table)
4658{
4659  SANE_Int C;
4660  SANE_Int rst = OK;
4661
4662  hp_gamma->depth = 8;
4663
4664  for (C = 0; C < 3; C++)
4665    if (hp_gamma->table[C] == NULL)
4666      hp_gamma->table[C] = malloc (sizeof (SANE_Byte) * 256);
4667
4668  if ((hp_gamma->table[CL_RED] != NULL) &&
4669      (hp_gamma->table[CL_GREEN] != NULL) &&
4670      (hp_gamma->table[CL_BLUE] != NULL))
4671    {
4672      /* All tables allocated */
4673      for (C = 0; C < 256; C++)
4674	{
4675	  if ((table != NULL) && (RTS_Debug->EnableGamma == TRUE))
4676	    {
4677	      /* fill gamma tables with user defined values */
4678	      hp_gamma->table[CL_RED][C] = table[C];
4679	      hp_gamma->table[CL_GREEN][C] = table[0x100 + C];
4680	      hp_gamma->table[CL_BLUE][C] = table[0x200 + C];
4681	    }
4682	  else
4683	    {
4684	      hp_gamma->table[CL_RED][C] = C;
4685	      hp_gamma->table[CL_GREEN][C] = C;
4686	      hp_gamma->table[CL_BLUE][C] = C;
4687	    }
4688	}
4689
4690      /* Locate threshold of bw */
4691      for (C = 0; C < 256; C++)
4692	if (hp_gamma->table[CL_RED][C] != 0)
4693	  break;
4694
4695      bw_threshold = C - 1;
4696    }
4697  else
4698    {
4699      /* Some alloc failed */
4700      rst = ERROR;
4701
4702      Gamma_FreeTables ();
4703    }
4704
4705  DBG (DBG_FNC, "> Gamma_AllocTable: %i >> bw_threshold = %i\n", rst,
4706       bw_threshold);
4707
4708  return rst;
4709}
4710
4711static SANE_Int
4712Gamma_Apply (struct st_device *dev, SANE_Byte * Regs,
4713	     struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg,
4714	     struct st_gammatables *mygamma)
4715{
4716  SANE_Int rst = OK;
4717
4718  DBG (DBG_FNC, "+ Gamma_Apply(*Regs, *scancfg, *hwdcfg, *mygamma):\n");
4719  dbg_ScanParams (scancfg);
4720
4721  if (hwdcfg->use_gamma_tables == FALSE)
4722    {
4723      DBG (DBG_FNC, "-> Gamma tables are not used\n");
4724
4725      v1600 = NULL;
4726      v1604 = NULL;
4727      v1608 = NULL;
4728    }
4729  else
4730    {
4731      /*390b */
4732      SANE_Int table_size, buffersize, c;
4733      SANE_Byte channels, *gammabuffer;
4734
4735      DBG (DBG_FNC, "-> Using gamma tables\n");
4736
4737      /* get channels count */
4738      channels = 3;		/* default */
4739
4740      if (scancfg->colormode != CM_COLOR)
4741	{
4742	  if (scancfg->channel != 3)
4743	    {
4744	      if (scancfg->colormode != 3)
4745		channels = (scancfg->samplerate == PIXEL_RATE) ? 2 : 1;
4746	    }
4747	}
4748
4749      /* get size for gamma tables */
4750      switch (mygamma->depth & 0x0c)
4751	{
4752	case 0:
4753	  table_size = 0x100 + (mygamma->depth & 1);
4754	  break;
4755	case 4:
4756	  table_size = 0x400 + (mygamma->depth & 1);
4757	  break;
4758	case 8:
4759	  table_size = 0x1000 + (mygamma->depth & 1);
4760	  break;
4761	default:
4762	  table_size = 2;
4763	  break;
4764	}
4765
4766      /* allocate space for gamma buffer */
4767      buffersize = table_size * channels;
4768      gammabuffer = (SANE_Byte *) malloc (buffersize * sizeof (SANE_Byte));
4769      if (gammabuffer != NULL)
4770	{
4771	  /* update gamma pointers for each channel */
4772	  v1600 = (SANE_Byte *) & mygamma->table[CL_RED];
4773	  v1604 = (SANE_Byte *) & mygamma->table[CL_GREEN];
4774	  v1608 = (SANE_Byte *) & mygamma->table[CL_BLUE];
4775
4776	  /* include gamma tables into one buffer */
4777	  for (c = 0; c < channels; c++)
4778	    memcpy (gammabuffer + (c * table_size), mygamma->table[c],
4779		    table_size);
4780
4781	  /* send gamma buffer to scanner */
4782	  Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b] & 0xaf);
4783	  rst = Gamma_SendTables (dev, Regs, gammabuffer, buffersize);
4784	  Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]);
4785
4786	  /* free gamma buffer */
4787	  free (gammabuffer);
4788	}
4789      else
4790	rst = ERROR;
4791    }
4792
4793  return rst;
4794}
4795
4796static SANE_Int
4797Refs_Analyze_Pattern (struct st_scanparams *scancfg,
4798		      SANE_Byte * scanned_pattern, SANE_Int * ler1,
4799		      SANE_Int ler1order, SANE_Int * ser1, SANE_Int ser1order)
4800{
4801  SANE_Int buffersize, xpos, ypos, coord, cnt, chn_size, dist, rst;
4802  double *color_sum, *color_dif, diff_max;
4803  SANE_Int vector[3];
4804
4805  DBG (DBG_FNC,
4806       "+ Refs_Analyze_Pattern(depth=%i, width=%i, height=%i, *scanned_pattern, *ler1, ler1order=%i, *ser1, ser1order=%i)\n",
4807       scancfg->depth, scancfg->coord.width, scancfg->coord.height, ler1order,
4808       ser1order);
4809
4810  rst = ERROR;			/* by default */
4811  dist = 5;			/* distance to compare */
4812  chn_size = (scancfg->depth > 8) ? 2 : 1;
4813  buffersize = max (scancfg->coord.width, scancfg->coord.height);
4814
4815  color_sum = (double *) malloc (sizeof (double) * buffersize);
4816  if (color_sum != NULL)
4817    {
4818      color_dif = (double *) malloc (sizeof (double) * buffersize);
4819      if (color_dif != NULL)
4820	{
4821			/*-------- 1st SER -------- */
4822	  coord = 1;
4823
4824	  if ((scancfg->coord.width - dist) > 1)
4825	    {
4826	      /* clear buffers */
4827	      memset (color_sum, 0, sizeof (double) * buffersize);
4828	      memset (color_dif, 0, sizeof (double) * buffersize);
4829
4830	      for (xpos = 0; xpos < scancfg->coord.width; xpos++)
4831		{
4832		  for (ypos = 0; ypos < 20; ypos++)
4833		    color_sum[xpos] +=
4834		      data_lsb_get (scanned_pattern +
4835				    (scancfg->coord.width * ypos) + xpos,
4836				    chn_size);
4837		}
4838
4839	      diff_max =
4840		(ser1order !=
4841		 0) ? color_sum[0] - color_sum[1] : color_sum[1] -
4842		color_sum[0];
4843	      color_dif[0] = diff_max;
4844	      cnt = 1;
4845
4846	      do
4847		{
4848		  color_dif[cnt] =
4849		    (ser1order !=
4850		     0) ? color_sum[cnt] - color_sum[cnt +
4851						     dist] : color_sum[cnt +
4852								       dist] -
4853		    color_sum[cnt];
4854
4855		  if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max))
4856		    {
4857		      /*d4df */
4858		      diff_max = color_dif[cnt];
4859		      if (fabs (color_dif[cnt] - color_dif[cnt - 1]) >
4860			  fabs (color_dif[coord] - color_dif[coord - 1]))
4861			coord = cnt;
4862		    }
4863
4864		  cnt++;
4865		}
4866	      while (cnt < (scancfg->coord.width - dist));
4867	    }
4868
4869	  vector[0] = coord + dist;
4870
4871			/*-------- 1st LER -------- */
4872	  coord = 1;
4873
4874	  if ((scancfg->coord.height - dist) > 1)
4875	    {
4876	      /* clear buffers */
4877	      memset (color_sum, 0, sizeof (double) * buffersize);
4878	      memset (color_dif, 0, sizeof (double) * buffersize);
4879
4880	      for (ypos = 0; ypos < scancfg->coord.height; ypos++)
4881		{
4882		  for (xpos = vector[0]; xpos < scancfg->coord.width - dist;
4883		       xpos++)
4884		    color_sum[ypos] +=
4885		      data_lsb_get (scanned_pattern +
4886				    (scancfg->coord.width * ypos) + xpos,
4887				    chn_size);
4888		}
4889
4890	      diff_max =
4891		(ler1order !=
4892		 0) ? color_sum[0] - color_sum[1] : color_sum[1] -
4893		color_sum[0];
4894	      color_dif[0] = diff_max;
4895
4896	      cnt = 1;
4897
4898	      do
4899		{
4900		  color_dif[cnt] =
4901		    (ler1order !=
4902		     0) ? color_sum[cnt] - color_sum[cnt +
4903						     dist] : color_sum[cnt +
4904								       dist] -
4905		    color_sum[cnt];
4906
4907		  if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max))
4908		    {
4909		      diff_max = color_dif[cnt];
4910		      if (fabs (color_dif[cnt] - color_dif[cnt - 1]) >
4911			  fabs (color_dif[coord] - color_dif[coord - 1]))
4912			coord = cnt;
4913		    }
4914
4915		  cnt++;
4916		}
4917	      while (cnt < (scancfg->coord.height - dist));
4918	    }
4919
4920	  vector[1] = coord + dist;
4921
4922			/*-------- 1st LER -------- */
4923	  if ((scancfg->coord.width - dist) > 1)
4924	    {
4925	      /* clear buffers */
4926	      memset (color_sum, 0, sizeof (double) * buffersize);
4927	      memset (color_dif, 0, sizeof (double) * buffersize);
4928
4929	      for (xpos = 0; xpos < scancfg->coord.width; xpos++)
4930		{
4931		  for (ypos = coord + 4; ypos < scancfg->coord.height; ypos++)
4932		    color_sum[xpos] +=
4933		      data_lsb_get (scanned_pattern +
4934				    (scancfg->coord.width * ypos) + xpos,
4935				    chn_size);
4936		}
4937
4938	      diff_max =
4939		(ser1order !=
4940		 0) ? color_sum[0] - color_sum[1] : color_sum[1] -
4941		color_sum[0];
4942	      color_dif[0] = diff_max;
4943	      cnt = 1;
4944
4945	      do
4946		{
4947		  color_dif[cnt] =
4948		    (ser1order !=
4949		     0) ? color_sum[cnt] - color_sum[cnt +
4950						     dist] : color_sum[cnt +
4951								       dist] -
4952		    color_sum[cnt];
4953
4954		  if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max))
4955		    {
4956		      diff_max = color_dif[cnt];
4957		      if (fabs (color_dif[cnt] - color_dif[cnt - 1]) >
4958			  fabs (color_dif[coord] - color_dif[coord - 1]))
4959			coord = cnt;
4960		    }
4961
4962		  cnt++;
4963		}
4964	      while (cnt < (scancfg->coord.width - dist));
4965	    }
4966
4967	  vector[2] = coord + dist;
4968
4969	  /* save image */
4970	  if (RTS_Debug->SaveCalibFile != FALSE)
4971	    dbg_autoref (scancfg, scanned_pattern, vector[0], vector[2],
4972			 vector[1]);
4973
4974	  /* assign values detected */
4975	  if (ser1 != NULL)
4976	    *ser1 = vector[2];
4977
4978	  if (ler1 != NULL)
4979	    *ler1 = vector[1];
4980
4981	  /* show values */
4982	  DBG (DBG_FNC, " -> Vectors found: x1=%i, x2=%i, y=%i\n", vector[0],
4983	       vector[2], vector[1]);
4984
4985	  rst = OK;
4986
4987	  free (color_dif);
4988	}
4989
4990      free (color_sum);
4991    }
4992
4993  DBG (DBG_FNC, "- Refs_Analyze_Pattern: %i\n", rst);
4994
4995  return rst;
4996}
4997
4998static double
4999get_shrd (double value, SANE_Int desp)
5000{
5001  if (desp <= 0x40)
5002    return value / pow (2, desp);
5003  else
5004    return 0;
5005}
5006
5007static char
5008get_byte (double value)
5009{
5010  unsigned int data;
5011  double temp;
5012
5013  if (value > 0xffffffff)
5014    {
5015      temp = floor (get_shrd (value, 0x20));
5016      temp *= pow (2, 32);
5017      value -= temp;
5018    }
5019
5020  data = (unsigned int) value;
5021
5022  data = _B0 (data);
5023
5024  return data;
5025}
5026
5027static SANE_Int
5028Timing_SetLinearImageSensorClock (SANE_Byte * Regs, struct st_cph *cph)
5029{
5030  SANE_Int rst = ERROR;
5031
5032  DBG (DBG_FNC,
5033       "+ Timing_SetLinearImageSensorClock(SANE_Byte *Regs, struct st_cph *cph)\n");
5034
5035  dbg_sensorclock (cph);
5036
5037  if ((Regs != NULL) && (cph != NULL))
5038    {
5039      Regs[0x00] = get_byte (cph->p1);
5040      Regs[0x01] = get_byte (get_shrd (cph->p1, 0x08));
5041      Regs[0x02] = get_byte (get_shrd (cph->p1, 0x10));
5042      Regs[0x03] = get_byte (get_shrd (cph->p1, 0x18));
5043
5044      Regs[0x04] &= 0x80;
5045      Regs[0x04] |= ((get_byte (get_shrd (cph->p1, 0x20))) & 0x0f);
5046      Regs[0x04] |= ((cph->ps & 1) << 6);
5047      Regs[0x04] |= ((cph->ge & 1) << 5);
5048      Regs[0x04] |= ((cph->go & 1) << 4);
5049
5050      Regs[0x05] = get_byte (cph->p2);
5051      Regs[0x06] = get_byte (get_shrd (cph->p2, 0x08));
5052      Regs[0x07] = get_byte (get_shrd (cph->p2, 0x10));
5053      Regs[0x08] = get_byte (get_shrd (cph->p2, 0x18));
5054      Regs[0x09] &= 0xf0;
5055      Regs[0x09] |= ((get_byte (get_shrd (cph->p2, 0x20))) & 0x0f);
5056
5057      rst = OK;
5058    }
5059
5060  DBG (DBG_FNC, "- Timing_SetLinearImageSensorClock: %i\n", rst);
5061
5062  return rst;
5063}
5064
5065static void
5066RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming,
5067			SANE_Byte * Regs)
5068{
5069  DBG (DBG_FNC, "+ RTS_Setup_SensorTiming(mytiming=%i, *Regs):\n", mytiming);
5070
5071  if ((Regs != NULL) && (mytiming < dev->timings_count))
5072    {
5073      struct st_timing *mt = dev->timings[mytiming];
5074
5075      if (mt != NULL)
5076	{
5077	  dbg_timing (mt);
5078
5079	  /* Correlated-Double-Sample 1 & 2 */
5080	  data_bitset (&Regs[0x92], 0x3f, mt->cdss[0]);
5081	  data_bitset (&Regs[0x93], 0x3f, mt->cdsc[0]);
5082	  data_bitset (&Regs[0x94], 0x3f, mt->cdss[1]);
5083	  data_bitset (&Regs[0x95], 0x3f, mt->cdsc[1]);
5084
5085	  data_bitset (&Regs[0x96], 0x3f, mt->cnpp);
5086
5087	  /* Linear image sensor transfer gates */
5088	  data_bitset (&Regs[0x45], 0x80, mt->cvtrp[0]);
5089	  data_bitset (&Regs[0x45], 0x40, mt->cvtrp[1]);
5090	  data_bitset (&Regs[0x45], 0x20, mt->cvtrp[2]);
5091
5092	  data_bitset (&Regs[0x45], 0x1f, mt->cvtrfpw);
5093	  data_bitset (&Regs[0x46], 0x1f, mt->cvtrbpw);
5094
5095	  data_lsb_set (&Regs[0x47], mt->cvtrw, 1);
5096
5097	  data_lsb_set (&Regs[0x84], mt->cphbp2s, 3);
5098	  data_lsb_set (&Regs[0x87], mt->cphbp2e, 3);
5099
5100	  data_lsb_set (&Regs[0x8a], mt->clamps, 3);
5101	  data_lsb_set (&Regs[0x8d], mt->clampe, 3);
5102
5103	  if (dev->chipset->model == RTS8822L_02A)
5104	    {
5105	      if (mt->clampe == -1)
5106		data_lsb_set (&Regs[0x8d], mt->cphbp2e, 3);
5107	    }
5108
5109	  Regs[0x97] = get_byte (mt->adcclkp[0]);
5110	  Regs[0x98] = get_byte (get_shrd (mt->adcclkp[0], 0x08));
5111	  Regs[0x99] = get_byte (get_shrd (mt->adcclkp[0], 0x10));
5112	  Regs[0x9a] = get_byte (get_shrd (mt->adcclkp[0], 0x18));
5113	  Regs[0x9b] &= 0xf0;
5114	  Regs[0x9b] |= ((get_byte (get_shrd (mt->adcclkp[0], 0x20))) & 0x0f);
5115
5116	  Regs[0xc1] = get_byte (mt->adcclkp[1]);
5117	  Regs[0xc2] = get_byte (get_shrd (mt->adcclkp[1], 0x08));
5118	  Regs[0xc3] = get_byte (get_shrd (mt->adcclkp[1], 0x10));
5119	  Regs[0xc4] = get_byte (get_shrd (mt->adcclkp[1], 0x18));
5120	  Regs[0xc5] &= 0xe0;
5121	  Regs[0xc5] |= ((get_byte (get_shrd (mt->adcclkp[1], 0x20))) & 0x0f);
5122
5123	  /* bit(4) = bit(0) */
5124	  Regs[0xc5] |= ((mt->adcclkp2e & 1) << 4);
5125
5126	  Timing_SetLinearImageSensorClock (&Regs[0x48], &mt->cph[0]);
5127	  Timing_SetLinearImageSensorClock (&Regs[0x52], &mt->cph[1]);
5128	  Timing_SetLinearImageSensorClock (&Regs[0x5c], &mt->cph[2]);
5129	  Timing_SetLinearImageSensorClock (&Regs[0x66], &mt->cph[3]);
5130	  Timing_SetLinearImageSensorClock (&Regs[0x70], &mt->cph[4]);
5131	  Timing_SetLinearImageSensorClock (&Regs[0x7a], &mt->cph[5]);
5132	}
5133    }
5134}
5135
5136static SANE_Int
5137Motor_GetFromResolution (SANE_Int resolution)
5138{
5139  SANE_Int ret;
5140
5141  ret = 3;
5142  if (RTS_Debug->usbtype != USB11)
5143    {
5144      if (scan.scantype != ST_NORMAL)
5145	{
5146	  /* scantype is ST_NEG or ST_TA */
5147	  if (resolution >= 600)
5148	    ret = 0;
5149	}
5150      else if (resolution >= 1200)
5151	ret = 0;
5152    }
5153  else if (resolution >= 600)
5154    ret = 0;
5155
5156  DBG (DBG_FNC, "> Motor_GetFromResolution(resolution=%i): %i\n", resolution,
5157       ret);
5158
5159  return ret;
5160}
5161
5162static SANE_Int
5163SetMultiExposure (struct st_device *dev, SANE_Byte * Regs)
5164{
5165  SANE_Int iValue, myctpc;
5166
5167  DBG (DBG_FNC, "> SetMultiExposure:\n");
5168
5169  /* set motor has no curves */
5170  data_bitset (&Regs[0xdf], 0x10, 0);	   /*---0----*/
5171
5172  /* select case systemclock */
5173  switch (Regs[0x00] & 0x0f)
5174    {
5175    case 0x00:
5176      iValue = 0x00895440;
5177      break;			/*  3 x 0x2DC6C0 */
5178    case 0x08:
5179    case 0x01:
5180      iValue = 0x00b71b00;
5181      break;			/*  4 x 0x2DC6C0 */
5182    case 0x02:
5183      iValue = 0x0112a880;
5184      break;			/*  6 x 0x2DC6C0 */
5185    case 0x0a:
5186    case 0x03:
5187      iValue = 0x016e3600;
5188      break;			/*  8 x 0x2DC6C0 */
5189    case 0x04:
5190      iValue = 0x02255100;
5191      break;			/* 12 x 0x2DC6C0 */
5192    case 0x0c:
5193      iValue = 0x02dc6c00;
5194      break;			/* 16 x 0x2DC6C0 */
5195    case 0x05:
5196      iValue = 0x044aa200;
5197      break;			/* 24 x 0x2DC6C0 */
5198    case 0x0d:
5199      iValue = 0x05b8d800;
5200      break;			/* 32 x 0x2DC6C0 */
5201
5202    case 0x09:
5203      iValue = 0x00f42400;
5204      break;
5205    case 0x0b:
5206      iValue = 0x01e84800;
5207      break;			/* = case 9 * 2 */
5208    default:
5209      iValue = 0x0478f7f8;
5210      break;
5211    }
5212
5213  /* divide by timing.cnpp */
5214  iValue /= ((Regs[0x96] & 0x3f) + 1);
5215  iValue /= dev->motorcfg->basespeedpps;
5216
5217  /* get line exposure time */
5218  myctpc = data_lsb_get (&Regs[0x30], 3) + 1;
5219
5220  DBG (DBG_FNC, "CTPC -- SetMultiExposure -- 1 =%i\n", myctpc);
5221
5222  /* if last step of accurve.normalscan table is lower than iValue ... */
5223  if (data_lsb_get (&Regs[0xe1], 3) < iValue)
5224    {
5225      SANE_Int traget;
5226      SANE_Int step_size = _B0 (Regs[0xe0]) + 1;
5227
5228      /* set exposure time [RED] if zero */
5229      if (data_lsb_get (&Regs[0x36], 3) == 0)
5230	data_lsb_set (&Regs[0x36], myctpc - 1, 3);
5231
5232      /* set exposure time [GREEN] if zero */
5233      if (data_lsb_get (&Regs[0x3c], 3) == 0)
5234	data_lsb_set (&Regs[0x3c], myctpc - 1, 3);
5235
5236      /* set exposure time [BLUE] if zero */
5237      if (data_lsb_get (&Regs[0x42], 3) == 0)
5238	data_lsb_set (&Regs[0x42], myctpc - 1, 3);
5239
5240      iValue = (iValue + 1) * step_size;
5241
5242      /* update line exposure time */
5243      traget = (((myctpc + iValue - 1) / myctpc) * myctpc);
5244      data_lsb_set (&Regs[0x30], traget - 1, 3);
5245
5246      traget = (traget / step_size) - 1;
5247      data_lsb_set (&Regs[0x00e1], traget, 3);
5248    }
5249
5250  /* 8300 */
5251  return OK;
5252}
5253
5254static SANE_Int
5255data_lsb_get (SANE_Byte * address, SANE_Int size)
5256{
5257  SANE_Int ret = 0;
5258  if ((address != NULL) && (size > 0) && (size < 5))
5259    {
5260      SANE_Int a;
5261      SANE_Byte b;
5262      size--;
5263      for (a = size; a >= 0; a--)
5264	{
5265	  b = address[a];
5266	  ret = (ret << 8) + b;
5267	}
5268    }
5269  return ret;
5270}
5271
5272static SANE_Byte
5273data_bitget (SANE_Byte * address, SANE_Int mask)
5274{
5275  SANE_Int desp = 0;
5276
5277  if (mask & 1);
5278  else if (mask & 2)
5279    desp = 1;
5280  else if (mask & 4)
5281    desp = 2;
5282  else if (mask & 8)
5283    desp = 3;
5284  else if (mask & 16)
5285    desp = 4;
5286  else if (mask & 32)
5287    desp = 5;
5288  else if (mask & 64)
5289    desp = 6;
5290  else if (mask & 128)
5291    desp = 7;
5292
5293  return (*address & mask) >> desp;
5294}
5295
5296static void
5297data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data)
5298{
5299  /* This function fills mask bits of just a byte with bits given in data */
5300  if (mask & 1);
5301  else if (mask & 2)
5302    data <<= 1;
5303  else if (mask & 4)
5304    data <<= 2;
5305  else if (mask & 8)
5306    data <<= 3;
5307  else if (mask & 16)
5308    data <<= 4;
5309  else if (mask & 32)
5310    data <<= 5;
5311  else if (mask & 64)
5312    data <<= 6;
5313  else if (mask & 128)
5314    data <<= 7;
5315
5316  *address = (*address & (0xff - mask)) | (data & mask);
5317}
5318
5319static void
5320data_wide_bitset (SANE_Byte * address, SANE_Int mask, SANE_Int data)
5321{
5322  /* Setting bytes bit per bit
5323     mask is 4 bytes size
5324     Example:
5325     data  = 0111010111
5326     mask  = 00000000 11111111 11000000 00000000
5327     rst   = 00000000 01110101 11000000 00000000 */
5328
5329  SANE_Int mymask, started = FALSE;
5330
5331  if ((address != NULL) && (mask != 0))
5332    {
5333      while (mask != 0)
5334	{
5335	  mymask = _B0 (mask);
5336
5337	  if (started == FALSE)
5338	    {
5339	      if (mymask != 0)
5340		{
5341		  SANE_Int a, myvalue;
5342
5343		  for (a = 0; a < 8; a++)
5344		    if ((mymask & (1 << a)) != 0)
5345		      break;
5346
5347		  myvalue = _B0 (data << a);
5348		  myvalue >>= a;
5349		  data_bitset (address, mymask, myvalue);
5350		  data >>= (8 - a);
5351		  started = TRUE;
5352		}
5353	    }
5354	  else
5355	    {
5356	      data_bitset (address, mymask, _B0 (data));
5357	      data >>= 8;
5358	    }
5359
5360	  address++;
5361	  mask >>= 8;
5362	}
5363    }
5364}
5365
5366
5367static void
5368data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size)
5369{
5370  if ((address != NULL) && (size > 0) && (size < 5))
5371    {
5372      SANE_Int a;
5373      for (a = 0; a < size; a++)
5374	{
5375	  address[a] = _B0 (data);
5376	  data >>= 8;
5377	}
5378    }
5379}
5380
5381static void
5382data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size)
5383{
5384  if ((address != NULL) && (size > 0) && (size < 5))
5385    {
5386      SANE_Int a;
5387
5388      for (a = size - 1; a >= 0; a--)
5389	{
5390	  address[a] = _B0 (data);
5391	  data >>= 8;
5392	}
5393    }
5394}
5395
5396static SANE_Int
5397data_swap_endianess (SANE_Int address, SANE_Int size)
5398{
5399  SANE_Int rst = 0;
5400
5401  if ((size > 0) && (size < 5))
5402    {
5403      SANE_Int a;
5404
5405      for (a = 0; a < size; a++)
5406	{
5407	  rst = (rst << 8) | _B0 (address);
5408	  address >>= 8;
5409	}
5410    }
5411
5412  return rst;
5413}
5414
5415static void
5416Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs,
5417		  SANE_Int resolution, SANE_Byte gainmode)
5418{
5419  DBG (DBG_FNC, "> Lamp_SetGainMode(*Regs, resolution=%i, gainmode=%i):\n",
5420       resolution, gainmode);
5421
5422  if (dev->chipset->model == RTS8822L_02A)
5423    {
5424      /* hp4370 */
5425      SANE_Int data1, data2;
5426
5427      data1 = data_lsb_get (&Regs[0x154], 2) & 0xfe7f;
5428      data2 = data_lsb_get (&Regs[0x156], 2);
5429
5430      switch (resolution)
5431	{
5432	case 4800:
5433	  data2 |= 0x40;
5434	  data1 &= 0xffbf;
5435	  break;
5436	case 100:
5437	case 150:
5438	case 200:
5439	case 300:
5440	case 600:
5441	case 1200:
5442	case 2400:
5443	  data1 |= 0x40;
5444	  data2 &= 0xffbf;
5445	  break;
5446	}
5447
5448      data_lsb_set (&Regs[0x154], data1, 2);
5449      data_lsb_set (&Regs[0x156], data2, 2);
5450    }
5451  else
5452    {
5453      /* hp3970 hp4070 ua4900 */
5454      SANE_Int data;
5455
5456      data = data_lsb_get (&Regs[0x154], 2) & 0xfe7f;
5457      data = (gainmode == FALSE) ? data | 0x0040 : data & 0xffbf;
5458
5459      switch (resolution)
5460	{
5461	case 100:
5462	case 200:
5463	case 300:
5464	case 600:
5465	  data |= 0x0100;
5466	  break;
5467	case 2400:
5468	  data |= 0x0180;
5469	  break;
5470	case 1200:
5471	  if (dev->sensorcfg->type == CIS_SENSOR)
5472	    data |= 0x80;
5473	  else if (dev->sensorcfg->type == CCD_SENSOR)
5474	    data |= 0x0180;
5475	  break;
5476	}
5477
5478      data_lsb_set (&Regs[0x0154], data, 2);
5479    }
5480}
5481
5482static SANE_Int
5483RTS_Scanner_StartScan (struct st_device *dev)
5484{
5485  SANE_Int rst = ERROR;		/* default */
5486  SANE_Int data;
5487
5488  DBG (DBG_FNC, "+ RTS_Scanner_StartScan():\n");
5489
5490  v14b4 = 1;			/* TEMPORAL */
5491  data = 0;
5492  Lamp_PWM_DutyCycle_Get (dev, &data);
5493  data = _B0 (data);
5494
5495  DBG (DBG_FNC, "->   Pwm used = %i\n", data);
5496
5497  /*
5498     windows driver saves pwm used, in file usbfile
5499     Section [SCAN_PARAM], field PwmUsed
5500   */
5501
5502  dev->status->cancel = FALSE;
5503
5504  if (Scan_Start (dev) == OK)
5505    {
5506      SANE_Int transferred;
5507
5508      rst = OK;
5509
5510      if (dev->scanning->imagebuffer != NULL)
5511	{
5512	  free (dev->scanning->imagebuffer);
5513	  dev->scanning->imagebuffer = NULL;
5514	}
5515
5516      SetLock (dev->usb_handle, NULL, (scan2.depth == 16) ? FALSE : TRUE);
5517
5518      /* Reservamos los buffers necesarios para leer la imagen */
5519      Reading_CreateBuffers (dev);
5520
5521      if (dev->Resize->type != RSZ_NONE)
5522	Resize_Start (dev, &transferred);	/* 6729 */
5523
5524      RTS_ScanCounter_Inc (dev);
5525    }
5526
5527  DBG (DBG_FNC, "- RTS_Scanner_StartScan: %i\n", rst);
5528
5529  return rst;
5530}
5531
5532static void
5533Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2,
5534	      SANE_Byte * buffer, SANE_Int channels_count)
5535{
5536  /*
5537     pPointer1 = FAB8
5538     pPointer2 = FABC
5539     buffer    = FAC0
5540     channels_count = FAC4
5541   */
5542
5543  SANE_Int value;
5544  SANE_Int channel_size;
5545
5546  DBG (DBG_FNC,
5547       "> Triplet_Gray(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n",
5548       channels_count);
5549
5550  channel_size = (scan2.depth > 8) ? 2 : 1;
5551  channels_count = channels_count / 2;
5552
5553  while (channels_count > 0)
5554    {
5555      value = data_lsb_get (pPointer1, channel_size);
5556      data_lsb_set (buffer, value, channel_size);
5557
5558      value = data_lsb_get (pPointer2, channel_size);
5559      data_lsb_set (buffer + channel_size, value, channel_size);
5560
5561      pPointer1 += 2 * channel_size;
5562      pPointer2 += 2 * channel_size;
5563      buffer += 2 * channel_size;
5564
5565      channels_count--;
5566    }
5567}
5568
5569static void
5570Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2,
5571		 SANE_Byte * buffer, SANE_Int channels_count)
5572{
5573  /* Composing colour in lineart mode */
5574
5575  SANE_Int dots_count = 0;
5576  SANE_Int channel;
5577  SANE_Byte mask;
5578  SANE_Byte value;
5579  SANE_Int C;
5580
5581  DBG (DBG_FNC,
5582       "> Triplet_Lineart(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n",
5583       channels_count);
5584
5585  if (channels_count > 0)
5586    {
5587      dots_count = (channels_count + 1) / 2;
5588      while (dots_count > 0)
5589	{
5590	  mask = 0x80;
5591	  channel = 2;
5592	  do
5593	    {
5594	      value = 0;
5595	      for (C = 4; C > 0; C--)
5596		{
5597		  value =
5598		    (value << 2) +
5599		    (((*pPointer2 & mask) << 1) | (*pPointer1 & mask));
5600		  mask = mask >> 1;
5601		}
5602	      *buffer = value;
5603	      buffer++;
5604	      channel--;
5605	    }
5606	  while (channel > 0);
5607	  pPointer2 += 2;
5608	  pPointer1 += 2;
5609	  dots_count--;
5610	}
5611    }
5612}
5613
5614static SANE_Int
5615Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer,
5616		   SANE_Int buffer_size, SANE_Int * transferred)
5617{
5618  /*
5619     buffer : fadc
5620     buffer_size : fae0
5621   */
5622
5623  SANE_Int lines_count = 0;	/* ebp */
5624  SANE_Int channels_count = 0;	/* fadc pisa buffer */
5625  SANE_Int rst = ERROR;
5626  struct st_scanning *scn;
5627
5628  DBG (DBG_FNC,
5629       "+ Arrange_NonColour(*buffer, buffer_size=%i, *transferred):\n",
5630       buffer_size);
5631
5632  /* this is just to make code more legible */
5633  scn = dev->scanning;
5634
5635  if (scn->imagebuffer == NULL)
5636    {
5637      if ((scn->arrange_hres == TRUE) || (scan2.colormode == CM_LINEART))
5638	{
5639	  scn->bfsize = (scn->arrange_sensor_evenodd_dist + 1) * line_size;
5640	  scn->imagebuffer =
5641	    (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte));
5642	  if (scn->imagebuffer != NULL)
5643	    {
5644	      if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred)
5645		  == OK)
5646		{
5647		  scn->channel_size = (scan2.depth == 8) ? 1 : 2;
5648		  scn->desp1[CL_RED] = 0;
5649		  scn->desp2[CL_RED] =
5650		    scn->channel_size +
5651		    (scn->arrange_sensor_evenodd_dist * line_size);
5652		  scn->pColour2[CL_RED] =
5653		    scn->imagebuffer + scn->desp2[CL_RED];
5654		  scn->pColour1[CL_RED] =
5655		    scn->imagebuffer + scn->desp1[CL_RED];
5656		  rst = OK;
5657		}
5658	    }
5659	}
5660    }
5661  else
5662    rst = OK;
5663
5664  /* b0f4 */
5665  if (rst == OK)
5666    {
5667      scn->imagepointer = scn->imagebuffer;
5668      lines_count = buffer_size / line_size;
5669      channels_count = line_size / scn->channel_size;
5670      while (lines_count > 0)
5671	{
5672	  if (scan2.colormode == CM_LINEART)
5673	    Triplet_Lineart (scn->pColour1[CL_RED], scn->pColour2[CL_RED],
5674			     buffer, channels_count);
5675	  else
5676	    Triplet_Gray (scn->pColour1[CL_RED], scn->pColour2[CL_RED],
5677			  buffer, channels_count);
5678
5679	  buffer += line_size;
5680	  scn->arrange_size -= bytesperline;
5681
5682	  lines_count--;
5683	  if (lines_count == 0)
5684	    {
5685	      if ((scn->arrange_size | v15bc) == 0)
5686		break;
5687	    }
5688
5689	  rst = Read_Block (dev, line_size, scn->imagepointer, transferred);
5690	  if (rst != OK)
5691	    break;
5692
5693	  if (scn->arrange_hres == TRUE)
5694	    {
5695	      scn->desp2[CL_RED] =
5696		(line_size + scn->desp2[CL_RED]) % scn->bfsize;
5697	      scn->desp1[CL_RED] =
5698		(line_size + scn->desp1[CL_RED]) % scn->bfsize;
5699
5700	      scn->pColour2[CL_RED] = scn->imagebuffer + scn->desp2[CL_RED];
5701	      scn->pColour1[CL_RED] = scn->imagebuffer + scn->desp1[CL_RED];
5702	    }
5703
5704	  /* b21d */
5705	  scn->imagepointer += line_size;
5706	  if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize))
5707	    scn->imagepointer = scn->imagebuffer;
5708	}
5709    }
5710
5711  /* 2246 */
5712
5713  DBG (DBG_FNC, "- Arrange_NonColour(*transferred=%i): %i\n", *transferred,
5714       rst);
5715
5716  return rst;
5717}
5718
5719static SANE_Int
5720Resize_Decrease (SANE_Byte * to_buffer, SANE_Int to_resolution,
5721		 SANE_Int to_width, SANE_Byte * from_buffer,
5722		 SANE_Int from_resolution, SANE_Int from_width,
5723		 SANE_Int myresize_mode)
5724{
5725  /*
5726     to_buffer = FAC8 = 0x236200
5727     to_resolution      = FACC = 0x4b
5728     to_width    = FAD0 = 0x352
5729     from_buffer = FAD4 = 0x235460
5730     from_resolution      = FAD8 = 0x64
5731     from_width    = FADC = 0x46d
5732     myresize_mode   = FAE0 = 1
5733   */
5734
5735  SANE_Int rst = ERROR;
5736  SANE_Int channels = 0;	/* fac8 */
5737  SANE_Int depth = 0;		/* fae0 */
5738  SANE_Int color[3] = { 0, 0, 0 };	/* fab8 | fabc | fac0 */
5739  SANE_Int to_pos = 0;		/* fad4 */
5740  SANE_Int rescont = 0;
5741  SANE_Int from_pos = 0;	/* fab4 */
5742  SANE_Int C;
5743  SANE_Int smres = 0;		/* fab0 */
5744  SANE_Int value;
5745  SANE_Int channel_size;
5746
5747  to_resolution = to_resolution & 0xffff;
5748  from_resolution = from_resolution & 0xffff;
5749
5750  DBG (DBG_FNC,
5751       "+ Resize_Decrease(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n",
5752       to_resolution, to_width, from_resolution, from_width, myresize_mode);
5753
5754  if (myresize_mode != RSZ_LINEART)
5755    {
5756      switch (myresize_mode)
5757	{
5758	case RSZ_GRAYL:
5759	  channels = 1;
5760	  depth = 8;
5761	  break;
5762	case RSZ_COLOURL:
5763	  channels = 3;
5764	  depth = 8;
5765	  break;
5766	case RSZ_COLOURH:
5767	  channels = 3;
5768	  depth = 16;
5769	  break;
5770	case RSZ_GRAYH:
5771	  channels = 1;
5772	  depth = 16;
5773	  break;
5774	}
5775
5776      channel_size = (depth > 8) ? 2 : 1;
5777      to_pos = 0;
5778      rescont = 0;
5779
5780      while (to_pos < to_width)
5781	{
5782	  from_pos++;
5783	  if (from_pos > from_width)
5784	    from_buffer -= (((depth + 7) / 8) * channels);
5785
5786	  rescont += to_resolution;
5787	  if (rescont < from_resolution)
5788	    {
5789	      /* Adds 3 color channel values */
5790	      for (C = 0; C < channels; C++)
5791		{
5792		  color[C] +=
5793		    data_lsb_get (from_buffer, channel_size) * to_resolution;
5794		  from_buffer += channel_size;
5795		}
5796	    }
5797	  else
5798	    {
5799	      /* fc3c */
5800	      to_pos++;
5801	      smres = to_resolution - (rescont - from_resolution);
5802	      for (C = 0; C < channels; C++)
5803		{
5804		  value =
5805		    ((data_lsb_get (from_buffer, channel_size) * smres) +
5806		     color[C]) / from_resolution;
5807		  data_lsb_set (to_buffer, value, channel_size);
5808		  color[C] =
5809		    data_lsb_get (from_buffer,
5810				  channel_size) * (rescont - from_resolution);
5811
5812		  to_buffer += channel_size;
5813		  from_buffer += channel_size;
5814		}
5815	      rescont -= from_resolution;
5816	    }
5817	}
5818
5819      rst = OK;
5820    }
5821  else
5822    {
5823      /* fd60 */
5824      SANE_Int bit, pos, desp, rescont2;
5825
5826      *to_buffer = 0;
5827      bit = 0;
5828      pos = 0;
5829      desp = 0;
5830      rescont = 0;
5831      rescont2 = 0;
5832      if (to_width > 0)
5833	{
5834	  do
5835	    {
5836	      if (bit == 8)
5837		{
5838		  /* fda6 */
5839		  bit = 0;
5840		  to_buffer++;
5841		  *to_buffer = 0;
5842		}
5843
5844	      rescont += to_resolution;
5845	      if (rescont < from_resolution)
5846		{
5847		  if ((*from_buffer & (0x80 >> desp)) != 0)
5848		    rescont2 += to_resolution;
5849		}
5850	      else
5851		{
5852		  /*fdd5 */
5853		  pos++;
5854		  rescont -= from_resolution;
5855		  if ((*from_buffer & (0x80 >> desp)) != 0)
5856		    /*fdee */
5857		    rescont2 += (to_resolution - rescont);
5858		  if (rescont2 > (to_resolution / 2))
5859		    /* fe00 */
5860		    *to_buffer = _B0 (*to_buffer | (0x80 >> bit));
5861		  rescont2 =
5862		    ((*from_buffer & (0x80 >> desp)) != 0) ? rescont : 0;
5863		  bit++;
5864		}
5865
5866	      /* fe2f */
5867	      desp++;
5868	      if (desp == 8)
5869		{
5870		  desp = 0;
5871		  from_buffer++;
5872		}
5873	    }
5874	  while (pos < to_width);
5875	}
5876      else
5877	rst = OK;
5878    }
5879
5880  DBG (DBG_FNC, "- Resize_Decrease: %i\n", rst);
5881
5882  return rst;
5883}
5884
5885static SANE_Int
5886Resize_Increase (SANE_Byte * to_buffer, SANE_Int to_resolution,
5887		 SANE_Int to_width, SANE_Byte * from_buffer,
5888		 SANE_Int from_resolution, SANE_Int from_width,
5889		 SANE_Int myresize_mode)
5890{
5891  /*
5892
5893     to_buffer       = FAC8 = 0x2353f0
5894     to_resolution   = FACC = 0x4b
5895     to_width        = FAD0 = 0x352
5896     from_buffer     = FAD4 = 0x234650
5897     from_resolution = FAD8 = 0x64
5898     from_width      = FADC = 0x46d
5899     myresize_mode   = FAE0 = 1
5900   */
5901
5902  SANE_Int rst = ERROR;
5903  SANE_Int desp;		/* fac0 */
5904  SANE_Byte *myp2;		/* faac */
5905  SANE_Int mywidth;		/* fab4 fab8 */
5906  SANE_Int mychannels;		/* fabc */
5907  SANE_Int channels = 0;	/* faa4 */
5908  SANE_Int depth = 0;		/* faa8 */
5909  SANE_Int pos = 0;		/* fae0 */
5910  SANE_Int rescount;
5911  SANE_Int val6 = 0;
5912  SANE_Int val7 = 0;
5913  SANE_Int value;
5914  /**/
5915    DBG (DBG_FNC,
5916	 "+ Resize_Increase(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n",
5917	 to_resolution, to_width, from_resolution, from_width, myresize_mode);
5918
5919  if (myresize_mode != RSZ_LINEART)
5920    {
5921      switch (myresize_mode)
5922	{
5923	case RSZ_GRAYL:
5924	  channels = 1;
5925	  depth = 8;
5926	  break;
5927	case RSZ_COLOURL:
5928	  channels = 3;
5929	  depth = 8;
5930	  break;
5931	case RSZ_COLOURH:
5932	  channels = 3;
5933	  depth = 16;
5934	  break;
5935	case RSZ_GRAYH:
5936	  channels = 1;
5937	  depth = 16;
5938	  break;
5939	}
5940
5941      if (channels > 0)
5942	{
5943	  SANE_Byte channel_size;
5944	  SANE_Byte *p_dst;	/* fac8 */
5945	  SANE_Byte *p_src;	/* fad4 */
5946
5947	  desp = to_buffer - from_buffer;
5948	  myp2 = from_buffer;
5949	  channel_size = (depth == 8) ? 1 : 2;
5950
5951	  for (mychannels = 0; mychannels < channels; mychannels++)
5952	    {
5953	      pos = 0;
5954	      rescount = (from_resolution / 2) + to_resolution;
5955
5956	      p_src = myp2;
5957	      p_dst = myp2 + desp;
5958
5959	      /* f938 */
5960	      val7 = data_lsb_get (p_src, channel_size);
5961
5962	      if (to_width > 0)
5963		{
5964		  for (mywidth = 0; mywidth < to_width; mywidth++)
5965		    {
5966		      if (rescount >= to_resolution)
5967			{
5968			  rescount -= to_resolution;
5969			  val6 = val7;
5970			  pos++;
5971			  if (pos < from_width)
5972			    {
5973			      p_src += (channels * channel_size);
5974			      val7 = data_lsb_get (p_src, channel_size);
5975			    }
5976			}
5977
5978		      /*f9a5 */
5979		      data_lsb_set (p_dst,
5980				    ((((to_resolution - rescount) * val6) +
5981				      (val7 * rescount)) / to_resolution),
5982				    channel_size);
5983		      rescount += from_resolution;
5984		      p_dst += (channels * channel_size);
5985		    }
5986		}
5987
5988	      myp2 += channel_size;
5989	    }
5990
5991	  rst = OK;
5992	}
5993      else
5994	rst = OK;
5995    }
5996  else
5997    {
5998      /* RSZ_LINEART mode */
5999      /* fa02 */
6000      /*
6001         to_buffer = FAC8 = 0x2353f0
6002         to_resolution      = FACC = 0x4b
6003         to_width    = FAD0 = 0x352
6004         from_buffer = FAD4 = 0x234650
6005         from_resolution      = FAD8 = 0x64
6006         from_width    = FADC = 0x46d
6007         myresize_mode   = FAE0 = 1
6008       */
6009      SANE_Int myres2;		/* fac8 */
6010      SANE_Int sres;
6011      SANE_Int lfae0;
6012      SANE_Int lfad8;
6013      SANE_Int myres;
6014      SANE_Int cont = 1;
6015      SANE_Int someval;
6016      SANE_Int bit;		/*lfaa8 */
6017
6018      myres2 = from_resolution;
6019      sres = (myres2 / 2) + to_resolution;
6020      value = _B0 (*from_buffer);
6021      bit = 0;
6022      lfae0 = 0;
6023      lfad8 = value >> 7;
6024      someval = lfad8;
6025      *to_buffer = 0;
6026
6027      if (to_width > 0)
6028	{
6029	  myres = to_resolution;
6030	  to_resolution = myres / 2;
6031	  do
6032	    {
6033	      if (sres >= myres)
6034		{
6035		  sres -= myres;
6036		  lfae0++;
6037		  cont++;
6038		  lfad8 = someval;
6039		  if (lfae0 < from_width)
6040		    {
6041		      if (cont == 8)
6042			{
6043			  cont = 0;
6044			  from_buffer++;
6045			}
6046		      bit = (((0x80 >> cont) & *from_buffer) != 0) ? 1 : 0;
6047		    }
6048		}
6049	      /*faa6 */
6050	      if ((((myres - sres) * lfad8) + (bit * sres)) > to_resolution)
6051		*to_buffer |= (0x80 >> bit);
6052
6053	      bit++;
6054	      if (bit == 8)
6055		{
6056		  bit = 0;
6057		  to_buffer++;
6058		  *to_buffer = 0;
6059		}
6060	      to_width--;
6061	      sres += myres2;
6062	    }
6063	  while (to_width > 0);
6064	  rst = OK;
6065	}
6066    }
6067
6068  DBG (DBG_FNC, "- Resize_Increase: %i\n", rst);
6069
6070  return rst;
6071}
6072
6073static SANE_Int
6074Resize_Start (struct st_device *dev, SANE_Int * transferred)
6075{
6076  SANE_Int rst = ERROR;
6077  struct st_resize *rz = dev->Resize;
6078
6079  DBG (DBG_FNC, "+ Resize_Start(*transferred):\n");
6080
6081  if (Resize_CreateBuffers
6082      (dev, line_size, rz->bytesperline, rz->bytesperline) == ERROR)
6083    return ERROR;
6084
6085  if (arrangeline2 == FIX_BY_SOFT)
6086    {
6087      /* fee0 */
6088      if (scan2.colormode == CM_COLOR)
6089	rst = Arrange_Colour (dev, rz->v3624, line_size, transferred);
6090      else
6091	rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred);
6092    }
6093  else
6094    rst = Read_Block (dev, line_size, rz->v3624, transferred);	/* ff03 */
6095
6096  /* Redimensionado */
6097  switch (rz->type)
6098    {
6099    case RSZ_DECREASE:
6100      /* ff1b */
6101      Resize_Decrease (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624,
6102		       scan2.resolution_x, rz->fromwidth, rz->mode);
6103      break;
6104    case RSZ_INCREASE:
6105      /* ff69 */
6106      rz->rescount = 0;
6107      Resize_Increase (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624,
6108		       scan2.resolution_x, rz->fromwidth, rz->mode);
6109      if (arrangeline2 == FIX_BY_SOFT)
6110	{
6111	  /* ffb1 */
6112	  if (scan2.colormode == CM_COLOR)
6113	    rst = Arrange_Colour (dev, rz->v3624, line_size, transferred);
6114	  else
6115	    rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred);
6116	}
6117      else
6118	rst = Read_Block (dev, line_size, rz->v3624, transferred);	/* ffe0 */
6119
6120      /* fff2 */
6121      Resize_Increase (rz->v362c, rz->resolution_x, rz->towidth, rz->v3624,
6122		       scan2.resolution_x, rz->fromwidth, rz->mode);
6123      break;
6124    }
6125
6126  /* 002a */
6127
6128  DBG (DBG_FNC, "- Resize_Start(*transferred=%i): %i\n", *transferred, rst);
6129
6130  return rst;
6131}
6132
6133static SANE_Int
6134Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, SANE_Int size2,
6135		      SANE_Int size3)
6136{
6137  SANE_Int rst = ERROR;
6138  struct st_resize *rz = dev->Resize;
6139
6140  rz->v3624 = (SANE_Byte *) malloc ((size1 + 0x40) * sizeof (SANE_Byte));
6141  rz->v3628 = (SANE_Byte *) malloc ((size2 + 0x40) * sizeof (SANE_Byte));
6142  rz->v362c = (SANE_Byte *) malloc ((size3 + 0x40) * sizeof (SANE_Byte));
6143
6144  if ((rz->v3624 == NULL) || (rz->v3628 == NULL) || (rz->v362c == NULL))
6145    Resize_DestroyBuffers (dev);
6146  else
6147    rst = OK;
6148
6149  DBG (DBG_FNC, "> Resize_CreateBuffers(size1=%i, size2=%i, size3=%i): %i\n",
6150       size1, size2, size3, rst);
6151
6152  return rst;
6153}
6154
6155static SANE_Int
6156Resize_DestroyBuffers (struct st_device *dev)
6157{
6158  struct st_resize *rz = dev->Resize;
6159
6160  if (rz->v3624 != NULL)
6161    free (rz->v3624);
6162
6163  if (rz->v3628 != NULL)
6164    free (rz->v3628);
6165
6166  if (rz->v362c != NULL)
6167    free (rz->v362c);
6168
6169  rz->v3624 = NULL;
6170  rz->v3628 = NULL;
6171  rz->v362c = NULL;
6172
6173  return OK;
6174}
6175
6176static SANE_Int
6177Reading_DestroyBuffers (struct st_device *dev)
6178{
6179  DBG (DBG_FNC, "> Reading_DestroyBuffers():\n");
6180
6181  if (dev->Reading->DMABuffer != NULL)
6182    free (dev->Reading->DMABuffer);
6183
6184  if (dev->scanning->imagebuffer != NULL)
6185    {
6186      free (dev->scanning->imagebuffer);
6187      dev->scanning->imagebuffer = NULL;
6188    }
6189
6190  memset (dev->Reading, 0, sizeof (struct st_readimage));
6191
6192  return OK;
6193}
6194
6195static SANE_Int
6196Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs,
6197		  SANE_Byte * gammatable, SANE_Int size)
6198{
6199  SANE_Int rst = ERROR;
6200
6201  DBG (DBG_FNC, "+ Gamma_SendTables(*Regs, *gammatable, size=%i):\n", size);
6202
6203  if ((gammatable != NULL) && (size > 0))
6204    {
6205      SANE_Int transferred;
6206      SANE_Int first_table;
6207      SANE_Int cont = 0;
6208      SANE_Int retry = TRUE;
6209      SANE_Byte *mybuffer;
6210
6211      /* lock */
6212      SetLock (dev->usb_handle, Regs, TRUE);
6213
6214      first_table = (data_lsb_get (&Regs[0x1b4], 2) & 0x3fff) >> 4;
6215
6216      mybuffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * size);
6217      if (mybuffer != NULL)
6218	{
6219	  /* Try to send buffer during 10 seconds */
6220	  long tick = GetTickCount () + 10000;
6221	  while ((retry == TRUE) && (tick > GetTickCount ()))
6222	    {
6223	      retry = FALSE;
6224
6225	      /* Operation type 0x14 */
6226	      if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == OK)
6227		{
6228		  /* Send size to write */
6229		  if (RTS_DMA_Enable_Write (dev, 0x0000, size, first_table) ==
6230		      OK)
6231		    {
6232		      /* Send data */
6233		      if (Bulk_Operation
6234			  (dev, BLK_WRITE, size, gammatable,
6235			   &transferred) == OK)
6236			{
6237			  /* Send size to read */
6238			  if (RTS_DMA_Enable_Read
6239			      (dev, 0x0000, size, first_table) == OK)
6240			    {
6241			      /* Retrieve data */
6242			      if (Bulk_Operation
6243				  (dev, BLK_READ, size, mybuffer,
6244				   &transferred) == OK)
6245				{
6246				  /* Check data */
6247				  while ((cont < size) && (retry == FALSE))
6248				    {
6249				      if (mybuffer[cont] != gammatable[cont])
6250					retry = TRUE;
6251				      cont++;
6252				    }
6253
6254				  if (retry == FALSE)
6255				    rst = OK;
6256				}
6257			    }
6258			}
6259		    }
6260		}
6261	    }
6262
6263	  free (mybuffer);
6264	}
6265
6266      /* unlock */
6267      SetLock (dev->usb_handle, Regs, FALSE);
6268    }
6269
6270  DBG (DBG_FNC, "- Gamma_SendTables: %i\n", rst);
6271
6272  return rst;
6273}
6274
6275static SANE_Int
6276Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer)
6277{
6278  SANE_Int rst = ERROR;
6279
6280  DBG (DBG_FNC, "+ Gamma_GetTables(SANE_Byte *Gamma_buffer):\n");
6281
6282  if (Gamma_buffer == NULL)
6283    return ERROR;
6284
6285  /* Operation type 0x14 */
6286  if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == 0x00)
6287    {
6288      SANE_Int size = 768;
6289
6290      if (RTS_DMA_Enable_Read (dev, 0x0000, size, 0) == OK)
6291	{
6292	  SANE_Int transferred = 0;
6293	  usleep (1000 * 500);
6294
6295	  /* Read buffer */
6296	  rst =
6297	    Bulk_Operation (dev, BLK_READ, size, Gamma_buffer, &transferred);
6298	}
6299    }
6300
6301  DBG (DBG_FNC, "- Gamma_GetTables: %i\n", rst);
6302
6303  return rst;
6304}
6305
6306static void
6307Gamma_FreeTables ()
6308{
6309  SANE_Int c;
6310
6311  DBG (DBG_FNC, "> Gamma_FreeTables()\n");
6312
6313  for (c = 0; c < 3; c++)
6314    {
6315      if (hp_gamma->table[c] != NULL)
6316	{
6317	  free (hp_gamma->table[c]);
6318	  hp_gamma->table[c] = NULL;
6319	}
6320    }
6321  use_gamma_tables = FALSE;
6322}
6323
6324static void
6325RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait)
6326{
6327  SANE_Byte data;
6328
6329  DBG (DBG_FNC, "+ RTS_Scanner_StopScan():\n");
6330
6331  data = 0;
6332
6333  Reading_DestroyBuffers (dev);
6334  Resize_DestroyBuffers (dev);
6335
6336  RTS_DMA_Reset (dev);
6337
6338  data_bitset (&dev->init_regs[0x60b], 0x10, 0);
6339  data_bitset (&dev->init_regs[0x60a], 0x40, 0);
6340
6341  if (Write_Buffer (dev->usb_handle, 0xee0a, &dev->init_regs[0x60a], 2) == OK)
6342    Motor_Change (dev, dev->init_regs, 3);
6343
6344  usleep (1000 * 200);
6345
6346  if (wait == FALSE)
6347    {
6348      Read_Byte (dev->usb_handle, 0xe801, &data);
6349      if ((data & 0x02) == 0)
6350	{
6351	  if (Head_IsAtHome (dev, dev->init_regs) == FALSE)
6352	    {
6353	      /* clear execution bit */
6354	      data_bitset (&dev->init_regs[0x00], 0x80, 0);
6355
6356	      Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]);
6357	      Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
6358	    }
6359	}
6360    }
6361  else
6362    {
6363      /*66a1 */
6364      /* clear execution bit */
6365      data_bitset (&dev->init_regs[0x00], 0x80, 0);
6366
6367      Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]);
6368      if (Head_IsAtHome (dev, dev->init_regs) == FALSE)
6369	Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
6370    }
6371
6372  /*66e0 */
6373  RTS_Enable_CCD (dev, dev->init_regs, 0);
6374
6375  Lamp_Status_Timer_Set (dev, 13);
6376
6377  DBG (DBG_FNC, "- RTS_Scanner_StopScan()\n");
6378}
6379
6380static SANE_Int
6381Reading_CreateBuffers (struct st_device *dev)
6382{
6383  SANE_Byte data;
6384  SANE_Int mybytesperline;
6385  SANE_Int mybuffersize, a, b;
6386
6387  DBG (DBG_FNC, "+ Reading_CreateBuffers():\n");
6388
6389  data = 0;
6390
6391  /* Gets BinarythresholdH */
6392  if (Read_Byte (dev->usb_handle, 0xe9a1, &data) == OK)
6393    binarythresholdh = data;
6394
6395  mybytesperline =
6396    (scan2.depth == 12) ? (bytesperline * 3) / 4 : bytesperline;
6397
6398  dev->Reading->Max_Size = 0xfc00;
6399  dev->Reading->DMAAmount = 0;
6400
6401  a = (RTS_Debug->dmabuffersize / 63);
6402  b = (((RTS_Debug->dmabuffersize - a) / 2) + a) >> 0x0f;
6403  mybuffersize = ((b << 6) - b) << 10;
6404  if (mybuffersize < 0x1f800)
6405    mybuffersize = 0x1f800;
6406
6407  dev->Reading->DMABufferSize = mybuffersize;	/*3FFC00 4193280 */
6408
6409  do
6410    {
6411      dev->Reading->DMABuffer =
6412	(SANE_Byte *) malloc (dev->Reading->DMABufferSize *
6413			      sizeof (SANE_Byte));
6414      if (dev->Reading->DMABuffer != NULL)
6415	break;
6416      dev->Reading->DMABufferSize -= dev->Reading->Max_Size;
6417    }
6418  while (dev->Reading->DMABufferSize >= dev->Reading->Max_Size);
6419
6420  /* 6003 */
6421  dev->Reading->Starting = TRUE;
6422
6423  dev->Reading->Size4Lines = (mybytesperline > dev->Reading->Max_Size) ?
6424    mybytesperline : (dev->Reading->Max_Size / mybytesperline) *
6425    mybytesperline;
6426
6427  dev->Reading->ImageSize = imagesize;
6428  read_v15b4 = v15b4;
6429
6430  DBG (DBG_FNC, "- Reading_CreateBuffers():\n");
6431
6432  return OK;
6433}
6434
6435static SANE_Int
6436RTS_ScanCounter_Inc (struct st_device *dev)
6437{
6438  /* Keep a count of the number of scans done by this scanner */
6439
6440  SANE_Int idata;
6441
6442  DBG (DBG_FNC, "+ RTS_ScanCounter_Inc():\n");
6443
6444  /* check if chipset supports accessing eeprom */
6445  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
6446    {
6447      SANE_Byte cdata = 0;
6448      SANE_Byte somebuffer[26];
6449
6450      switch (dev->chipset->model)
6451	{
6452	case RTS8822L_02A:
6453	case RTS8822BL_03A:
6454	  /* value is 4 bytes size starting from address 0x21 in msb format */
6455	  if (RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata) == OK)
6456	    {
6457	      idata = data_swap_endianess (idata, 4) + 1;
6458	      idata = data_swap_endianess (idata, 4);
6459	      RTS_EEPROM_WriteInteger (dev->usb_handle, 0x21, idata);
6460	    }
6461	  break;
6462	default:
6463	  /* value is 4 bytes size starting from address 0x21 in lsb format */
6464	  memset (&somebuffer, 0, sizeof (somebuffer));
6465	  somebuffer[4] = 0x0c;
6466
6467	  RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata);
6468	  data_lsb_set (&somebuffer[0], idata + 1, 4);
6469
6470	  RTS_EEPROM_ReadByte (dev->usb_handle, 0x003a, &cdata);
6471	  somebuffer[25] = cdata;
6472	  RTS_EEPROM_WriteBuffer (dev->usb_handle, 0x21, somebuffer, 0x1a);
6473	  break;
6474	}
6475    }
6476
6477  DBG (DBG_FNC, "- RTS_ScanCounter_Inc()\n");
6478
6479  return OK;
6480}
6481
6482static SANE_Int
6483RTS_ScanCounter_Get (struct st_device *dev)
6484{
6485  /* Returns the number of scans done by this scanner */
6486
6487  SANE_Int idata = 0;
6488
6489  DBG (DBG_FNC, "+ RTS_ScanCounter_Get():\n");
6490
6491  /* check if chipset supports accessing eeprom */
6492  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
6493    {
6494      RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata);
6495
6496      switch (dev->chipset->model)
6497	{
6498	case RTS8822L_02A:
6499	case RTS8822BL_03A:
6500	  /* value is 4 bytes size starting from address 0x21 in msb format */
6501	  idata = data_swap_endianess (idata, 4);
6502	  break;
6503	default:		/* RTS8822L_01H */
6504	  /* value is 4 bytes size starting from address 0x21 in lsb format */
6505	  idata &= 0xffffffff;
6506	  break;
6507	}
6508    }
6509
6510  DBG (DBG_FNC, "- RTS_ScanCounter_Get(): %i\n", idata);
6511
6512  return idata;
6513}
6514
6515static SANE_Int
6516Read_Image (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer,
6517	    SANE_Int * transferred)
6518{
6519  SANE_Int rst;
6520  SANE_Byte mycolormode;
6521
6522  DBG (DBG_FNC, "+ Read_Image(buffer_size=%i, *buffer, *transferred):\n",
6523       buffer_size);
6524
6525  *transferred = 0;
6526  mycolormode = scan2.colormode;
6527  rst = ERROR;
6528  if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3))
6529    mycolormode = 3;
6530
6531  if (dev->Resize->type == RSZ_NONE)
6532    {
6533      if (arrangeline == FIX_BY_SOFT)
6534	{
6535	  switch (mycolormode)
6536	    {
6537	    case CM_COLOR:
6538	      rst = Arrange_Colour (dev, buffer, buffer_size, transferred);
6539	      break;
6540	    case 3:
6541	      rst = Arrange_Compose (dev, buffer, buffer_size, transferred);
6542	      break;
6543	    default:
6544	      rst = Arrange_NonColour (dev, buffer, buffer_size, transferred);
6545	      break;
6546	    }
6547	}
6548      else
6549	rst = Read_Block (dev, buffer_size, buffer, transferred);	/*00fe */
6550    }
6551  else
6552    rst = Read_ResizeBlock (dev, buffer, buffer_size, transferred);	/*010d */
6553
6554  DBG (DBG_FNC, "- Read_Image(*transferred=%i): %i\n", *transferred, rst);
6555
6556  return rst;
6557}
6558
6559static SANE_Int
6560Arrange_Compose (struct st_device *dev, SANE_Byte * buffer,
6561		 SANE_Int buffer_size, SANE_Int * transferred)
6562{
6563  /*
6564     fnb250
6565
6566     0600FA7C   05E10048 buffer
6567     0600FA80   0000F906 buffer_size
6568   */
6569  SANE_Byte *mybuffer = buffer;	/* fa7c */
6570  SANE_Int mydistance;		/*ebp */
6571  SANE_Int mydots;		/*fa74 */
6572  SANE_Int channel_size;
6573  SANE_Int c;
6574  struct st_scanning *scn;
6575
6576  /*mywidth = fa70 */
6577
6578  DBG (DBG_FNC, "+ Arrange_Compose(*buffer, buffer_size=%i, *transferred):\n",
6579       buffer_size);
6580
6581  channel_size = (scan2.depth == 8) ? 1 : 2;
6582
6583  /* this is just to make code more legible */
6584  scn = dev->scanning;
6585
6586  if (scn->imagebuffer == NULL)
6587    {
6588      if (dev->sensorcfg->type == CCD_SENSOR)
6589	mydistance =
6590	  (dev->sensorcfg->line_distance * scan2.resolution_y) /
6591	  dev->sensorcfg->resolution;
6592      else
6593	mydistance = 0;
6594
6595      if (mydistance != 0)
6596	{
6597	  scn->bfsize =
6598	    (scn->arrange_hres ==
6599	     TRUE) ? scn->arrange_sensor_evenodd_dist : 0;
6600	  scn->bfsize = line_size * (scn->bfsize + (mydistance * 2) + 1);
6601	}
6602      else
6603	scn->bfsize = line_size * 2;
6604
6605      /*b2f0 */
6606      scn->imagebuffer =
6607	(SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte));
6608      if (scn->imagebuffer == NULL)
6609	return ERROR;
6610
6611      scn->imagepointer = scn->imagebuffer;
6612      if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) ==
6613	  ERROR)
6614	return ERROR;
6615
6616      /* Calculate channel displacements */
6617      scn->arrange_orderchannel = FALSE;
6618      for (c = CL_RED; c <= CL_BLUE; c++)
6619	{
6620	  if (mydistance == 0)
6621	    {
6622	      /*b34e */
6623	      if (scn->arrange_hres == FALSE)
6624		{
6625		  if ((((dev->sensorcfg->line_distance * scan2.resolution_y) *
6626			2) / dev->sensorcfg->resolution) == 1)
6627		    scn->arrange_orderchannel = TRUE;
6628
6629		  if (scn->arrange_orderchannel == TRUE)
6630		    scn->desp[c] =
6631		      ((dev->sensorcfg->rgb_order[c] / 2) * line_size) +
6632		      (channel_size * c);
6633		  else
6634		    scn->desp[c] = channel_size * c;
6635		}
6636	    }
6637	  else
6638	    {
6639	      /*b3e3 */
6640	      scn->desp[c] =
6641		(dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) +
6642		(channel_size * c);
6643
6644	      if (scn->arrange_hres == TRUE)
6645		{
6646		  /*b43b */
6647		  scn->desp1[c] = scn->desp[c];
6648		  scn->desp2[c] =
6649		    ((channel_size * 3) + scn->desp1[c]) +
6650		    (scn->arrange_sensor_evenodd_dist * line_size);
6651		};
6652	    }
6653	}
6654
6655      for (c = CL_RED; c <= CL_BLUE; c++)
6656	{
6657	  if (scn->arrange_hres == TRUE)
6658	    {
6659	      scn->pColour2[c] = scn->imagebuffer + scn->desp2[c];
6660	      scn->pColour1[c] = scn->imagebuffer + scn->desp1[c];
6661	    }
6662	  else
6663	    scn->pColour[c] = scn->imagebuffer + scn->desp[c];
6664	}
6665    }
6666
6667  /*b545 */
6668  buffer_size /= line_size;
6669  mydots = line_size / (channel_size * 3);
6670
6671  while (buffer_size > 0)
6672    {
6673      if (scn->arrange_orderchannel == FALSE)
6674	{
6675	  /*b5aa */
6676	  if (scn->arrange_hres == TRUE)
6677	    Triplet_Compose_HRes (scn->pColour1[CL_RED],
6678				  scn->pColour1[CL_GREEN],
6679				  scn->pColour1[CL_BLUE],
6680				  scn->pColour2[CL_RED],
6681				  scn->pColour2[CL_GREEN],
6682				  scn->pColour2[CL_BLUE], mybuffer, mydots);
6683	  else
6684	    Triplet_Compose_LRes (scn->pColour[CL_RED],
6685				  scn->pColour[CL_GREEN],
6686				  scn->pColour[CL_BLUE], mybuffer, mydots);
6687	}
6688      else
6689	Triplet_Compose_Order (dev, scn->pColour[CL_RED],
6690			       scn->pColour[CL_GREEN], scn->pColour[CL_BLUE],
6691			       mybuffer, mydots);
6692
6693      /*b5f8 */
6694      mybuffer += line_size;
6695      scn->arrange_size -= bytesperline;
6696      if (scn->arrange_size < 0)
6697	v15bc--;
6698
6699      buffer_size--;
6700      if (buffer_size == 0)
6701	{
6702	  if ((scn->arrange_size | v15bc) == 0)
6703	    return OK;
6704	}
6705
6706      /*b63f */
6707      if (Read_Block (dev, line_size, scn->imagepointer, transferred) ==
6708	  ERROR)
6709	return ERROR;
6710
6711      for (c = CL_RED; c <= CL_BLUE; c++)
6712	{
6713	  if (scn->arrange_hres == TRUE)
6714	    {
6715	      /*b663 */
6716	      scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize;
6717	      scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize;
6718
6719	      scn->pColour2[c] = scn->imagebuffer + scn->desp2[c];
6720	      scn->pColour1[c] = scn->imagebuffer + scn->desp1[c];
6721	    }
6722	  else
6723	    {
6724	      /*b74a */
6725	      scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize;
6726	      scn->pColour[c] = scn->imagebuffer + scn->desp[c];
6727	    }
6728	}
6729
6730      /*b7be */
6731      scn->imagepointer += line_size;
6732      if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize))
6733	scn->imagepointer = scn->imagebuffer;
6734    }
6735
6736  return OK;
6737}
6738
6739static void
6740Triplet_Compose_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1,
6741		      SANE_Byte * pBlue1, SANE_Byte * pRed2,
6742		      SANE_Byte * pGreen2, SANE_Byte * pBlue2,
6743		      SANE_Byte * buffer, SANE_Int Width)
6744{
6745  SANE_Int Value;
6746  SANE_Int Channel_size;
6747  SANE_Int max_value;
6748
6749  DBG (DBG_FNC,
6750       "> Triplet_Compose_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2 *pGreen2, *pBlue2, *buffer, Width=%i):\n",
6751       Width);
6752
6753  Width /= 2;
6754  Channel_size = (scan2.depth > 8) ? 2 : 1;
6755  max_value = (1 << scan2.depth) - 1;
6756
6757  while (Width > 0)
6758    {
6759      Value =
6760	data_lsb_get (pRed1, Channel_size) + data_lsb_get (pGreen1,
6761							   Channel_size) +
6762	data_lsb_get (pBlue1, Channel_size);
6763
6764      Value = min (Value, max_value);
6765
6766      if (v1600 != NULL)
6767	{
6768	  if (scan2.depth > 8)
6769	    Value = *(v1600 + (Value >> 8)) | _B0 (Value);
6770	  else
6771	    Value = *(v1600 + Value);
6772	}
6773
6774      data_lsb_set (buffer, Value, Channel_size);
6775      buffer += Channel_size;
6776
6777      Value =
6778	data_lsb_get (pRed2, Channel_size) + data_lsb_get (pGreen2,
6779							   Channel_size) +
6780	data_lsb_get (pBlue2, Channel_size);
6781
6782      Value = min (Value, max_value);
6783
6784      if (v1600 != NULL)
6785	{
6786	  if (scan2.depth > 8)
6787	    Value = *(v1600 + (Value >> 8)) | _B0 (Value);
6788	  else
6789	    Value = *(v1600 + Value);
6790	}
6791
6792      data_lsb_set (buffer, Value, Channel_size);
6793      buffer += Channel_size;
6794
6795      pRed1 += 6 * Channel_size;
6796      pGreen1 += 6 * Channel_size;
6797      pBlue1 += 6 * Channel_size;
6798
6799      pRed2 += 6 * Channel_size;
6800      pGreen2 += 6 * Channel_size;
6801      pBlue2 += 6 * Channel_size;
6802
6803      Width--;
6804    }
6805}
6806
6807static void
6808Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed,
6809		       SANE_Byte * pGreen, SANE_Byte * pBlue,
6810		       SANE_Byte * buffer, SANE_Int dots)
6811{
6812  SANE_Int Value;
6813
6814  DBG (DBG_FNC,
6815       "> Triplet_Compose_Order(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n",
6816       dots);
6817
6818  if (scan2.depth > 8)
6819    {
6820      /* c0fe */
6821      dots = dots / 2;
6822      while (dots > 0)
6823	{
6824	  Value =
6825	    min (data_lsb_get (pRed, 2) + data_lsb_get (pGreen, 2) +
6826		 data_lsb_get (pBlue, 2), 0xffff);
6827
6828	  if (v1600 != NULL)
6829	    Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value);
6830
6831	  data_lsb_set (buffer, Value, 2);
6832
6833	  buffer += 2;
6834	  pRed += 6;
6835	  pGreen += 6;
6836	  pBlue += 6;
6837	  dots--;
6838	}
6839    }
6840  else
6841    {
6842      SANE_Byte *myp1, *myp2, *myp3;
6843
6844      if (dev->sensorcfg->rgb_order[CL_RED] == 1)
6845	{
6846	  myp1 = pRed;
6847	  myp2 = pGreen;
6848	  myp3 = pBlue;
6849	}
6850      else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1)
6851	{
6852	  myp1 = pGreen;
6853	  myp2 = pRed;
6854	  myp3 = pBlue;
6855	}
6856      else
6857	{
6858	  myp1 = pBlue;
6859	  myp2 = pRed;
6860	  myp3 = pGreen;
6861	}
6862
6863      while (dots > 0)
6864	{
6865	  Value =
6866	    min (((*myp1 + *(line_size + myp1)) / 2) + *myp2 + *myp3, 0xff);
6867
6868	  *buffer = (v1600 == NULL) ? _B0 (Value) : *(v1600 + Value);
6869
6870	  buffer++;
6871	  myp1 += 3;
6872	  myp2 += 3;
6873	  myp3 += 3;
6874	  dots--;
6875	}
6876    }
6877}
6878
6879static void
6880Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue,
6881		      SANE_Byte * buffer, SANE_Int dots)
6882{
6883  SANE_Int Value;
6884  SANE_Int Channel_size;
6885  SANE_Int max_value;
6886
6887  DBG (DBG_FNC,
6888       "> Triplet_Compose_LRes(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n",
6889       dots);
6890
6891  Channel_size = (scan2.depth > 8) ? 2 : 1;
6892  max_value = (1 << scan2.depth) - 1;
6893
6894  /*bf59 */
6895  while (dots > 0)
6896    {
6897      Value =
6898	data_lsb_get (pRed, Channel_size) + data_lsb_get (pGreen,
6899							  Channel_size) +
6900	data_lsb_get (pBlue, Channel_size);
6901
6902      Value = min (Value, max_value);
6903
6904      if (v1600 != NULL)
6905	{
6906	  if (scan2.depth > 8)
6907	    Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value);
6908	  else
6909	    Value = _B0 (*(v1600 + Value));
6910	}
6911
6912      data_lsb_set (buffer, Value, Channel_size);
6913
6914      buffer += Channel_size;
6915      pRed += Channel_size * 3;
6916      pGreen += Channel_size * 3;
6917      pBlue += Channel_size * 3;
6918      dots--;
6919    }
6920}
6921
6922static void
6923Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed,
6924		      SANE_Byte * pGreen, SANE_Byte * pBlue,
6925		      SANE_Byte * buffer, SANE_Int Width)
6926{
6927  SANE_Int Value;
6928
6929  DBG (DBG_FNC,
6930       "> Triplet_Colour_Order(*pRed, *pGreen, *pBlue, *buffer, Width=%i):\n",
6931       Width);
6932
6933  if (scan2.depth > 8)
6934    {
6935      Width = Width / 2;
6936      while (Width > 0)
6937	{
6938	  Value = data_lsb_get (pRed, 2);
6939	  data_lsb_set (buffer, Value, 2);
6940
6941	  Value = data_lsb_get (pGreen, 2);
6942	  data_lsb_set (buffer + 2, Value, 2);
6943
6944	  Value = data_lsb_get (pBlue, 2);
6945	  data_lsb_set (buffer + 4, Value, 2);
6946
6947	  pRed += 6;
6948	  pGreen += 6;
6949	  pBlue += 6;
6950	  buffer += 6;
6951	  Width--;
6952	}
6953    }
6954  else
6955    {
6956      SANE_Int Colour;
6957
6958      if (dev->sensorcfg->rgb_order[CL_RED] == 1)
6959	Colour = CL_RED;
6960      else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1)
6961	Colour = CL_GREEN;
6962      else
6963	Colour = CL_BLUE;
6964
6965      while (Width > 0)
6966	{
6967	  switch (Colour)
6968	    {
6969	    case CL_RED:
6970	      *buffer = (*pRed + *(pRed + line_size)) / 2;
6971	      *(buffer + 1) = *pGreen;
6972	      *(buffer + 2) = *pBlue;
6973	      break;
6974	    case CL_GREEN:
6975	      *buffer = *pRed;
6976	      *(buffer + 1) = ((*pGreen + *(pGreen + line_size)) / 2);
6977	      *(buffer + 2) = *pBlue;
6978	      break;
6979	    case CL_BLUE:
6980	      *buffer = *pRed;
6981	      *(buffer + 1) = *pGreen;
6982	      *(buffer + 2) = ((*pBlue + *(pBlue + line_size)) / 2);
6983	      break;
6984	    }
6985
6986	  pRed += 3;
6987	  pGreen += 3;
6988	  pBlue += 3;
6989	  buffer += 3;
6990
6991	  Width--;
6992	}
6993    }
6994}
6995
6996static void
6997Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1,
6998		     SANE_Byte * pBlue1, SANE_Byte * pRed2,
6999		     SANE_Byte * pGreen2, SANE_Byte * pBlue2,
7000		     SANE_Byte * buffer, SANE_Int Width)
7001{
7002  SANE_Int Value;
7003  SANE_Int channel_size;
7004  SANE_Int c;
7005  SANE_Byte *pPointers[6];
7006
7007  pPointers[0] = pRed1;
7008  pPointers[1] = pGreen1;
7009  pPointers[2] = pBlue1;
7010
7011  pPointers[3] = pRed2;
7012  pPointers[4] = pGreen2;
7013  pPointers[5] = pBlue2;
7014
7015  DBG (DBG_FNC,
7016       "> Triplet_Colour_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2, *pGreen2, *pBlue2, *buffer, Width=%i):\n",
7017       Width);
7018
7019  channel_size = (scan2.depth > 8) ? 2 : 1;
7020
7021  Width = Width / 2;
7022  while (Width > 0)
7023    {
7024      for (c = 0; c < 6; c++)
7025	{
7026	  Value = data_lsb_get (pPointers[c], channel_size);
7027	  data_lsb_set (buffer, Value, channel_size);
7028
7029	  pPointers[c] += (6 * channel_size);
7030	  buffer += (channel_size);
7031	}
7032      Width--;
7033    }
7034}
7035
7036static void
7037Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer,
7038		     SANE_Byte * pChannel1, SANE_Byte * pChannel2,
7039		     SANE_Byte * pChannel3)
7040{
7041  /*
7042     05F0FA4C   04EBAE4A  /CALL to Assumed StdFunc6 from hpgt3970.04EBAE45
7043     05F0FA50   00234FF8  |Arg1 = 00234FF8 pChannel3
7044     05F0FA54   002359EF  |Arg2 = 002359EF pChannel2
7045     05F0FA58   002363E6  |Arg3 = 002363E6 pChannel1
7046     05F0FA5C   05D10048  |Arg4 = 05D10048 Buffer
7047     05F0FA60   00000352  |Arg5 = 00000352 Width
7048   */
7049
7050  /* Esta funcion une los tres canales de color en un triplete
7051     Inicialmente cada color está separado en 3 buffers apuntados
7052     por pChannel1 ,2 y 3
7053   */
7054  SANE_Int Value;
7055  SANE_Int channel_size;
7056  SANE_Int c;
7057  SANE_Byte *pChannels[3];
7058
7059  pChannels[0] = pChannel3;
7060  pChannels[1] = pChannel2;
7061  pChannels[2] = pChannel1;
7062
7063  DBG (DBG_FNC, "> Triplet_Colour_LRes(Width=%i, *Buffer2, *p1, *p2, *p3):\n",
7064       Width);
7065
7066  channel_size = (scan2.depth > 8) ? 2 : 1;
7067  while (Width > 0)
7068    {
7069      /* ba74 */
7070      for (c = 0; c < 3; c++)
7071	{
7072	  Value = data_lsb_get (pChannels[c], channel_size);
7073	  data_lsb_set (Buffer, Value, channel_size);
7074
7075	  pChannels[c] += channel_size;
7076	  Buffer += channel_size;
7077	}
7078      Width--;
7079    }
7080}
7081
7082static SANE_Int
7083Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer,
7084		  SANE_Int buffer_size, SANE_Int * transferred)
7085{
7086  /*The Beach
7087     buffer      = FA7C   05E30048
7088     buffer_size = FA80   0000F906
7089   */
7090
7091  SANE_Int rst = ERROR;		/* fa68 */
7092  SANE_Int lfa54;
7093  SANE_Int lfa58;
7094  SANE_Byte *pP1;		/* fa5c */
7095  SANE_Byte *pP2;		/* fa60 */
7096  SANE_Int bOk;
7097  struct st_resize *rz = dev->Resize;
7098
7099  /* fa74 = Resize->resolution_y */
7100  /* fa70 = Resize->resolution_x */
7101  /* fa64 = scan2.resolution_y  */
7102  /* fa6c = scan2.resolution_x  */
7103
7104  DBG (DBG_FNC,
7105       "+ Read_ResizeBlock(*buffer, buffer_size=%i, *transferred):\n",
7106       buffer_size);
7107
7108  if (rz->type == RSZ_DECREASE)
7109    {
7110      lfa58 = 0;
7111      do
7112	{
7113	  bOk = 1;
7114	  if (arrangeline2 == FIX_BY_SOFT)
7115	    {
7116	      if (scan2.colormode == CM_COLOR)
7117		rst = Arrange_Colour (dev, rz->v3624, line_size, transferred);
7118	      else
7119		rst =
7120		  Arrange_NonColour (dev, rz->v3624, line_size, transferred);
7121	    }
7122	  else
7123	    rst = Read_Block (dev, line_size, rz->v3624, transferred);
7124
7125	  /*f2df */
7126	  Resize_Decrease (rz->v362c, rz->resolution_x, rz->towidth,
7127			   rz->v3624, scan2.resolution_x, rz->fromwidth,
7128			   rz->mode);
7129	  rz->rescount += rz->resolution_y;
7130
7131	  if (rz->rescount > scan2.resolution_y)
7132	    {
7133	      /*f331 */
7134	      rz->rescount -= scan2.resolution_y;
7135	      if (scan2.depth == 8)
7136		{
7137		  /* f345 */
7138		  pP1 = rz->v3628;
7139		  pP2 = rz->v362c;
7140		  if (rz->mode == RSZ_LINEART)
7141		    {
7142		      /* f36b */
7143		      SANE_Int bit = 0;
7144		      SANE_Byte *pP3 = rz->v362c;
7145		      SANE_Int value;
7146
7147		      *buffer = 0;
7148		      lfa54 = 0;
7149		      while (lfa54 < rz->towidth)
7150			{
7151			  if (bit == 8)
7152			    {
7153			      buffer++;
7154			      *buffer = 0;
7155			      pP1++;
7156			      bit = 0;
7157			      pP3++;
7158			    }
7159
7160			  value =
7161			    ((*pP1 & (0x80 >> bit)) != 0) ? rz->rescount : 0;
7162
7163			  if ((*pP3 & (0x80 >> bit)) != 0)
7164			    value += (scan2.resolution_y - rz->rescount);
7165
7166			  if (value > rz->resolution_y)
7167			    *buffer |= (0x80 >> bit);
7168
7169			  bit++;
7170			  lfa54++;
7171			}
7172		    }
7173		  else
7174		    {
7175		      /* f414 */
7176		      lfa54 = 0;
7177		      while (lfa54 < rz->bytesperline)
7178			{
7179			  *buffer =
7180			    _B0 ((((scan2.resolution_y -
7181				    rz->rescount) * *pP2) +
7182				  (*pP1 * rz->rescount)) /
7183				 scan2.resolution_y);
7184			  pP1++;
7185			  pP2++;
7186			  buffer++;
7187			  lfa54++;
7188			}
7189		    }
7190		}
7191	      else
7192		{
7193		  /* f47d */
7194		  lfa54 = 0;
7195		  pP1 = rz->v3628;
7196		  pP2 = rz->v362c;
7197
7198		  if ((rz->bytesperline & 0xfffffffe) > 0)
7199		    {
7200		      SANE_Int value;
7201		      do
7202			{
7203			  value =
7204			    (((scan2.resolution_y -
7205			       rz->rescount) * data_lsb_get (pP2,
7206							     2)) +
7207			     (data_lsb_get (pP1, 2) * rz->rescount)) /
7208			    scan2.resolution_y;
7209			  data_lsb_set (buffer, value, 2);
7210
7211			  buffer += 2;
7212			  pP1 += 2;
7213			  pP2 += 2;
7214			  lfa54++;
7215			}
7216		      while (lfa54 < (rz->bytesperline / 2));
7217		    }
7218		}
7219	    }
7220	  else
7221	    bOk = 0;
7222	  /* f4fd f502 */
7223	  pP1 = rz->v3628;
7224	  /* swap pointers */
7225	  rz->v3628 = rz->v362c;
7226	  rz->v362c = pP1;
7227	}
7228      while (bOk == 0);
7229    }
7230  else
7231    {
7232      /*f530 */
7233      SANE_Int lfa68;
7234      SANE_Int transferred;
7235      SANE_Int channel_size;
7236
7237      rz->rescount += scan2.resolution_y;
7238      lfa58 = 0;
7239      if (rz->rescount > rz->resolution_y)
7240	{
7241	  lfa68 = 1;
7242	  rz->rescount -= rz->resolution_y;
7243	}
7244      else
7245	lfa68 = 0;
7246
7247      pP1 = rz->v3628;
7248      pP2 = rz->v362c;
7249
7250      if (rz->mode == RSZ_LINEART)
7251	{
7252	  /*f592 */
7253	  *buffer = 0;
7254
7255	  if (rz->towidth > 0)
7256	    {
7257	      SANE_Int mask, mres;
7258	      /* lfa60 = rz->resolution_y     */
7259	      /* lfa7c = rz->resolution_y / 2 */
7260
7261	      for (lfa54 = 0; lfa54 < rz->towidth; lfa54++)
7262		{
7263		  mask = 0x80 >> lfa58;
7264
7265		  mres = ((mask & *pP1) != 0) ? rz->rescount : 0;
7266
7267		  if ((mask & *pP2) != 0)
7268		    mres += (rz->resolution_y - rz->rescount);
7269
7270		  if (mres > (rz->resolution_y / 2))
7271		    *buffer = *buffer | mask;
7272
7273		  lfa58++;
7274		  if (lfa58 == 8)
7275		    {
7276		      lfa58 = 0;
7277		      buffer++;
7278		      pP1++;
7279		      pP2++;
7280		      *buffer = 0;
7281		    }
7282		}
7283	    }
7284	}
7285      else
7286	{
7287	  /*f633 */
7288	  channel_size = (scan2.depth > 8) ? 2 : 1;
7289
7290	  if (rz->rescount < scan2.resolution_y)
7291	    {
7292	      if (rz->bytesperline != 0)
7293		{
7294		  SANE_Int value;
7295
7296		  for (lfa54 = 0; lfa54 < rz->bytesperline; lfa54++)
7297		    {
7298		      value =
7299			(((scan2.resolution_y -
7300			   rz->rescount) * data_lsb_get (pP2,
7301							 channel_size)) +
7302			 (rz->rescount * data_lsb_get (pP1, channel_size))) /
7303			scan2.resolution_y;
7304		      data_lsb_set (buffer, value, channel_size);
7305
7306		      pP1 += channel_size;
7307		      pP2 += channel_size;
7308		      buffer += channel_size;
7309		    }
7310		}
7311	    }
7312	  else
7313	    memcpy (buffer, rz->v3628, rz->bytesperline);	/*f6a8 */
7314	}
7315
7316      /*f736 */
7317      if (lfa68 != 0)
7318	{
7319	  SANE_Byte *temp;
7320
7321	  if (arrangeline2 == FIX_BY_SOFT)
7322	    {
7323	      /*f74b */
7324	      if (scan2.colormode == CM_COLOR)
7325		rst =
7326		  Arrange_Colour (dev, rz->v3624, line_size, &transferred);
7327	      else
7328		rst =
7329		  Arrange_NonColour (dev, rz->v3624, line_size, &transferred);
7330	    }
7331	  else
7332	    rst = Read_Block (dev, line_size, rz->v3624, &transferred);	/*f77a */
7333
7334	  /*f78c */
7335	  /* swap buffers */
7336	  temp = rz->v3628;
7337	  rz->v3628 = rz->v362c;
7338	  rz->v362c = temp;
7339
7340	  Resize_Increase (temp, rz->resolution_x, rz->towidth, rz->v3624,
7341			   scan2.resolution_x, rz->fromwidth, rz->mode);
7342	}
7343      else
7344	rst = OK;
7345    }
7346
7347  DBG (DBG_FNC, "- Read_ResizeBlock(*transferred=%i): %i\n", *transferred,
7348       rst);
7349
7350  return rst;
7351}
7352
7353static void
7354Split_into_12bit_channels (SANE_Byte * destino, SANE_Byte * fuente,
7355			   SANE_Int size)
7356{
7357  /*
7358     Each letter represents a bit
7359     abcdefgh 12345678 lmnopqrs << before splitting
7360     [efgh1234 0000abcd] [lmnopqrs 00005678]  << after splitting, in memory
7361     [0000abcd efgh1234] [00005678 lmnopqrs]  << resulting channels
7362   */
7363
7364  DBG (DBG_FNC, "> Split_into_12bit_channels(*destino, *fuente, size=%i\n",
7365       size);
7366
7367  if ((destino != NULL) && (fuente != NULL))
7368    {
7369      if ((size - (size & 0x03)) != 0)
7370	{
7371	  SANE_Int C;
7372
7373	  C = (size - (size & 0x03) + 3) / 4;
7374	  do
7375	    {
7376	      *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4));
7377	      *(destino + 1) = _B0 (*fuente >> 4);
7378	      *(destino + 2) = _B0 (*(fuente + 2));
7379	      *(destino + 3) = *(fuente + 1) & 0x0f;
7380	      destino += 4;
7381	      fuente += 3;
7382	      C--;
7383	    }
7384	  while (C > 0);
7385	}
7386
7387       /**/ if ((size & 0x03) != 0)
7388	{
7389	  *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4));
7390	  *(destino + 1) = _B0 (*fuente >> 4);
7391	}
7392    }
7393}
7394
7395static SANE_Int
7396Read_NonColor_Block (struct st_device *dev, SANE_Byte * buffer,
7397		     SANE_Int buffer_size, SANE_Byte ColorMode,
7398		     SANE_Int * transferred)
7399{
7400  /* FA50   05DA0048 buffer
7401     FA54   0000F906 buffer_size
7402     FA58   00       ColorMode
7403   */
7404
7405  SANE_Int rst = OK;
7406  SANE_Int lfa38 = 0;
7407  SANE_Byte *gamma = v1600;
7408  SANE_Int block_bytes_per_line;
7409  SANE_Int mysize;
7410  SANE_Byte *mybuffer;
7411
7412  DBG (DBG_FNC,
7413       "+ Read_NonColor_Block(*buffer, buffer_size=%i, ColorMode=%s):\n",
7414       buffer_size, dbg_colour (ColorMode));
7415
7416  if (ColorMode != CM_GRAY)
7417    {
7418      /* Lineart mode */
7419      if ((lineart_width & 7) != 0)
7420	lfa38 = 8 - (lineart_width & 7);
7421      block_bytes_per_line = (lineart_width + 7) / 8;
7422    }
7423  else
7424    block_bytes_per_line = line_size;
7425  /*61b2 */
7426
7427  mysize = (buffer_size / block_bytes_per_line) * bytesperline;
7428  mybuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte));	/*fa40 */
7429
7430  if (mybuffer != NULL)
7431    {
7432      SANE_Int LinesCount;
7433      SANE_Int mysize4lines;
7434      SANE_Byte *pBuffer = buffer;
7435      SANE_Byte *pImage = NULL;	/* fa30 */
7436      SANE_Int puntero;
7437      SANE_Int value;
7438
7439      do
7440	{
7441	  mysize4lines =
7442	    (mysize <=
7443	     dev->Reading->Size4Lines) ? mysize : dev->Reading->Size4Lines;
7444	  LinesCount = mysize4lines / bytesperline;
7445
7446	  if (ColorMode == CM_GRAY)
7447	    {
7448	      if (scan2.depth == 12)
7449		{
7450		  /* 633b */
7451		  /*GRAY Bit mode 12 */
7452		  rst =
7453		    Scan_Read_BufferA (dev, (mysize4lines * 3) / 4, 0,
7454				       mybuffer, transferred);
7455		  if (rst == OK)
7456		    {
7457		      pImage = mybuffer;
7458		      pBuffer += LinesCount * block_bytes_per_line;
7459		      while (LinesCount > 0)
7460			{
7461			  Split_into_12bit_channels (mybuffer, pImage,
7462						     line_size);
7463			  pImage += (bytesperline * 3) / 4;
7464			  LinesCount--;
7465			}
7466		    }
7467		  else
7468		    break;
7469		}
7470	      else
7471		{
7472		  /* grayscale 8 and 16 bits */
7473
7474		  SANE_Int channel_size;
7475
7476		  rst =
7477		    Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer,
7478				       transferred);
7479
7480		  if (rst == OK)
7481		    {
7482		      channel_size = (scan2.depth > 8) ? 2 : 1;
7483
7484		      pImage = mybuffer;
7485
7486		      /* No gamma tables */
7487		      while (LinesCount > 0)
7488			{
7489			  if (line_size > 0)
7490			    {
7491			      puntero = 0;
7492			      do
7493				{
7494				  value =
7495				    data_lsb_get (pImage + puntero,
7496						  channel_size);
7497
7498				  if (gamma != NULL)
7499				    value +=
7500				      *gamma << (8 * (channel_size - 1));
7501
7502				  data_lsb_set (pBuffer, value, channel_size);
7503
7504				  pBuffer += channel_size;
7505				  puntero += channel_size;
7506				}
7507			      while (puntero < line_size);
7508			    }
7509			  pImage += bytesperline;
7510			  LinesCount--;
7511			}
7512		    }
7513		  else
7514		    break;
7515		}
7516	    }
7517	  else
7518	    {
7519	      /*6429 */
7520	      /* LINEART */
7521	      SANE_Int desp;
7522	      rst =
7523		Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer,
7524				   transferred);
7525	      if (rst == OK)
7526		{
7527		  pImage = mybuffer;
7528		  while (LinesCount > 0)
7529		    {
7530		      if (lineart_width > 0)
7531			{
7532			  desp = 0;
7533			  do
7534			    {
7535			      if ((desp % 7) == 0)
7536				*pBuffer = 0;
7537
7538			      /* making a byte bit per bit */
7539			      *pBuffer = *pBuffer << 1;
7540
7541			      /* bit 1 if data is under thresholdh value */
7542			      if (*(pImage + desp) >= binarythresholdh)	/* binarythresholdh = 0x0c */
7543				*pBuffer = *pBuffer | 1;
7544
7545			      desp++;
7546			      if ((desp % 7) == 0)
7547				pBuffer++;
7548
7549			    }
7550			  while (desp < lineart_width);
7551			}
7552
7553		      if (lfa38 != 0)
7554			{
7555			  *pBuffer = (*pBuffer << lfa38);
7556			  pBuffer++;
7557			}
7558		      /* 64b0 */
7559		      pImage += bytesperline;
7560		      LinesCount--;
7561		    }
7562		}
7563	      else
7564		break;
7565	    }
7566	  /* 64c0 */
7567	  mysize -= mysize4lines;
7568	}
7569      while ((mysize > 0) && (dev->status->cancel == FALSE));
7570
7571      free (mybuffer);
7572    }
7573  else
7574    rst = ERROR;
7575
7576  DBG (DBG_FNC, "- Read_NonColor_Block(*transferred=%i): %i\n", *transferred,
7577       rst);
7578
7579  return rst;
7580}
7581
7582static SANE_Int
7583Read_Block (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer,
7584	    SANE_Int * transferred)
7585{
7586  /*
7587     SANE_Int buffer_size          fa80
7588     SANE_Byte *buffer    fa7c
7589   */
7590/*
7591scan2:
759204F0155C  01 08 00 02 03 00 58 02  ..X
759304F01564  58 02 58 02 C5 00 00 00  XXÅ...
759404F0156C  B4 07 00 00 8B 01 00 00  ´....
759504F01574  10 06 00 00 EC 13 00 00  ..ì..
759604F0157C  B2 07 00 00 B4 07 00 00  ²..´..
759704F01584  CF 08 00 00              Ï..
7598
7599arrangeline2 = 1
7600*/
7601  SANE_Int rst, LinesCount;
7602  SANE_Int mysize;
7603  SANE_Byte *readbuffer = NULL;
7604  SANE_Byte *pImage = NULL;
7605
7606  DBG (DBG_FNC, "+ Read_Block(buffer_size=%i, *buffer):\n", buffer_size);
7607
7608  rst = ERROR;
7609  *transferred = 0;
7610
7611  if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3)
7612      && (arrangeline2 != FIX_BY_SOFT))
7613    {
7614      /*6510 */
7615      return Read_NonColor_Block (dev, buffer, buffer_size, scan2.colormode,
7616				  transferred);
7617    }
7618
7619  /*6544 */
7620  mysize = (buffer_size / line_size) * bytesperline;
7621  readbuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte));
7622  pImage = buffer;
7623
7624  if (readbuffer != NULL)
7625    {
7626      do
7627	{
7628	  buffer_size =
7629	    (dev->Reading->Size4Lines <
7630	     mysize) ? dev->Reading->Size4Lines : mysize;
7631	  LinesCount = buffer_size / bytesperline;
7632
7633	  if (scan2.depth == 12)
7634	    {
7635	      rst =
7636		Scan_Read_BufferA (dev, buffer_size, 0, readbuffer,
7637				   transferred);
7638	      if (rst == OK)
7639		{
7640		  if (LinesCount > 0)
7641		    {
7642		      SANE_Byte *destino, *fuente;
7643		      destino = buffer;
7644		      fuente = readbuffer;
7645		      do
7646			{
7647			  Split_into_12bit_channels (destino, fuente,
7648						     line_size);
7649			  destino += line_size;
7650			  fuente += (bytesperline * 3) / 4;
7651			  LinesCount--;
7652			}
7653		      while (LinesCount > 0);
7654		    }
7655		}
7656	      else
7657		break;
7658	    }
7659	  else
7660	    {
7661	      /*65d9 */
7662	      rst =
7663		Scan_Read_BufferA (dev, buffer_size, 0, readbuffer,
7664				   transferred);
7665	      if (rst == OK)
7666		{
7667		  memcpy (pImage, readbuffer, *transferred);
7668
7669		  /* apply white shading correction */
7670		  if ((RTS_Debug->wshading == TRUE)
7671		      && (scan2.scantype == ST_NORMAL))
7672		    WShading_Emulate (pImage, &wshading->ptr, *transferred,
7673				      scan2.depth);
7674
7675		  pImage += *transferred;
7676		}
7677	      else
7678		break;
7679	    }
7680	  /*6629 */
7681	  mysize -= buffer_size;
7682	}
7683      while ((mysize > 0) && (dev->status->cancel == FALSE));
7684
7685      free (readbuffer);
7686    }
7687
7688  DBG (DBG_FNC, "- Read_Block(*transferred=%i): %i\n", *transferred, rst);
7689
7690  return rst;
7691}
7692
7693static SANE_Int
7694Scan_Read_BufferA (struct st_device *dev, SANE_Int buffer_size, SANE_Int arg2,
7695		   SANE_Byte * pBuffer, SANE_Int * bytes_transferred)
7696{
7697  SANE_Int rst = OK;
7698  SANE_Byte *ptBuffer = NULL;
7699  SANE_Byte *ptImg = NULL;
7700  struct st_readimage *rd = dev->Reading;
7701
7702  DBG (DBG_FNC,
7703       "+ Scan_Read_BufferA(buffer_size=%i, arg2, *pBuffer, *bytes_transferred):\n",
7704       buffer_size);
7705
7706  (void) arg2;			/* silence gcc */
7707  *bytes_transferred = 0;
7708
7709  if (pBuffer != NULL)
7710    {
7711      ptBuffer = pBuffer;
7712
7713      while ((buffer_size > 0) && (rst == OK)
7714	     && (dev->status->cancel == FALSE))
7715	{
7716	  /* Check if we've already started */
7717	  if (rd->Starting == TRUE)
7718	    {
7719	      /* Get channels per dot and channel's size in bytes */
7720	      SANE_Byte data;
7721
7722	      rd->Channels_per_dot = 1;
7723	      if (Read_Byte (dev->usb_handle, 0xe812, &data) == OK)
7724		{
7725		  data = data >> 6;
7726		  if (data != 0)
7727		    rd->Channels_per_dot = data;
7728		}
7729
7730	      rd->Channel_size = 1;
7731	      if (Read_Byte (dev->usb_handle, 0xee0b, &data) == OK)
7732		if (((data & 0x40) != 0) && ((data & 0x08) == 0))
7733		  rd->Channel_size = 2;
7734
7735	      rd->RDStart = rd->DMABuffer;
7736	      rd->RDSize = 0;
7737	      rd->DMAAmount = 0;
7738	      rd->Starting = FALSE;
7739	    }
7740
7741	  /* Is there any data to read from scanner? */
7742	  if ((rd->ImageSize > 0) && (rd->RDSize == 0))
7743	    {
7744	      /* Try to read from scanner all possible data to fill DMABuffer */
7745	      if (rd->RDSize < rd->DMABufferSize)
7746		{
7747		  SANE_Int iAmount, dofree;
7748
7749		  /* Check if we have already notify buffer size */
7750		  if (rd->DMAAmount <= 0)
7751		    {
7752		      /* Initially I suppose that I can read all image */
7753		      iAmount = min (rd->ImageSize, rd->Max_Size);
7754		      rd->DMAAmount =
7755			((RTS_Debug->dmasetlength * 2) / iAmount) * iAmount;
7756		      rd->DMAAmount = min (rd->DMAAmount, rd->ImageSize);
7757		      Reading_BufferSize_Notify (dev, 0, rd->DMAAmount);
7758		      iAmount = min (iAmount, rd->DMABufferSize - rd->RDSize);
7759		    }
7760		  else
7761		    {
7762		      iAmount = min (rd->DMAAmount, rd->ImageSize);
7763		      iAmount = min (iAmount, rd->Max_Size);
7764		    }
7765
7766		  /* Allocate buffer to read image if it's necessary */
7767		  if ((rd->RDSize == 0) && (iAmount <= buffer_size))
7768		    {
7769		      ptImg = ptBuffer;
7770		      dofree = FALSE;
7771		    }
7772		  else
7773		    {
7774		      ptImg =
7775			(SANE_Byte *) malloc (iAmount * sizeof (SANE_Byte));
7776		      dofree = TRUE;
7777		    }
7778
7779		  if (ptImg != NULL)
7780		    {
7781		      /* We must wait for scanner to get data */
7782		      SANE_Int opStatus, sc;
7783
7784		      sc = (iAmount < rd->Max_Size) ? TRUE : FALSE;
7785		      opStatus = Reading_Wait (dev, rd->Channels_per_dot,
7786					       rd->Channel_size,
7787					       iAmount,
7788					       &rd->Bytes_Available, 60, sc);
7789
7790		      /* If something fails, perhaps we can read some bytes... */
7791		      if (opStatus != OK)
7792			{
7793			  if (rd->Bytes_Available > 0)
7794			    iAmount = rd->Bytes_Available;
7795			  else
7796			    rst = ERROR;
7797			}
7798
7799		      if (rst == OK)
7800			{
7801			  /* Try to read from scanner */
7802			  SANE_Int transferred = 0;
7803			  opStatus =
7804			    Bulk_Operation (dev, BLK_READ, iAmount, ptImg,
7805					    &transferred);
7806
7807			  DBG (DBG_FNC,
7808			       "> Scan_Read_BufferA: Bulk read %i bytes\n",
7809			       transferred);
7810
7811			  /*if something fails may be we can read some bytes */
7812			  iAmount = (SANE_Int) transferred;
7813			  if (iAmount != 0)
7814			    {
7815			      /* Lets copy data into DMABuffer if it's necessary */
7816			      if (ptImg != ptBuffer)
7817				{
7818				  SANE_Byte *ptDMABuffer;
7819
7820				  ptDMABuffer = rd->RDStart + rd->RDSize;
7821				  if ((ptDMABuffer - rd->DMABuffer) >=
7822				      rd->DMABufferSize)
7823				    ptDMABuffer -= rd->DMABufferSize;
7824
7825				  if ((ptDMABuffer + iAmount) >=
7826				      (rd->DMABuffer + rd->DMABufferSize))
7827				    {
7828				      SANE_Int rest =
7829					iAmount - (rd->DMABufferSize -
7830						   (ptDMABuffer -
7831						    rd->DMABuffer));
7832				      memcpy (ptDMABuffer, ptImg,
7833					      iAmount - rest);
7834				      memcpy (rd->DMABuffer,
7835					      ptImg + (iAmount - rest), rest);
7836				    }
7837				  else
7838				    memcpy (ptDMABuffer, ptImg, iAmount);
7839				  rd->RDSize += iAmount;
7840				}
7841			      else
7842				{
7843				  *bytes_transferred += iAmount;
7844				  buffer_size -= iAmount;
7845				}
7846
7847			      rd->DMAAmount -= iAmount;
7848			      rd->ImageSize -= iAmount;
7849			    }
7850			  else
7851			    rst = ERROR;
7852			}
7853
7854		      /* Lets free buffer */
7855		      if (dofree == TRUE)
7856			{
7857			  free (ptImg);
7858			  ptImg = NULL;
7859			}
7860		    }
7861		  else
7862		    rst = ERROR;
7863		}
7864	    }
7865
7866	  /* is there any data read from scanner? */
7867	  if (rd->RDSize > 0)
7868	    {
7869	      /* Add to the given buffer as many bytes as possible */
7870	      SANE_Int iAmount;
7871
7872	      iAmount = min (buffer_size, rd->RDSize);
7873	      if ((rd->RDStart + iAmount) >=
7874		  (rd->DMABuffer + rd->DMABufferSize))
7875		{
7876		  SANE_Int rest =
7877		    rd->DMABufferSize - (rd->RDStart - rd->DMABuffer);
7878		  memcpy (ptBuffer, rd->RDStart, rest);
7879		  memcpy (ptBuffer + rest, rd->DMABuffer, iAmount - rest);
7880		  rd->RDStart = rd->DMABuffer + (iAmount - rest);
7881		}
7882	      else
7883		{
7884		  memcpy (ptBuffer, rd->RDStart, iAmount);
7885		  rd->RDStart += iAmount;
7886		}
7887
7888	      ptBuffer += iAmount;
7889	      rd->RDSize -= iAmount;
7890	      buffer_size -= iAmount;
7891	      *bytes_transferred += iAmount;
7892
7893	      /* if there isn't any data in DMABuffer we can point RDStart
7894	         to the beginning of DMABuffer */
7895	      if (rd->RDSize == 0)
7896		rd->RDStart = rd->DMABuffer;
7897	    }
7898
7899	  /* in case of all data is read we return OK with bytes_transferred = 0 */
7900	  if ((*bytes_transferred == 0)
7901	      || ((rd->RDSize == 0) && (rd->ImageSize == 0)))
7902	    break;
7903	}
7904
7905      if (rst == ERROR)
7906	RTS_DMA_Cancel (dev);
7907    }
7908
7909  DBG (DBG_FNC, "->   *bytes_transferred=%i\n", *bytes_transferred);
7910  DBG (DBG_FNC, "->   Reading->ImageSize=%i\n", rd->ImageSize);
7911  DBG (DBG_FNC, "->   Reading->DMAAmount=%i\n", rd->DMAAmount);
7912  DBG (DBG_FNC, "->   Reading->RDSize   =%i\n", rd->RDSize);
7913
7914  DBG (DBG_FNC, "- Scan_Read_BufferA: %i\n", rst);
7915
7916  return rst;
7917}
7918
7919static SANE_Int
7920Reading_BufferSize_Get (struct st_device *dev, SANE_Byte channels_per_dot,
7921			SANE_Int channel_size)
7922{
7923  /* returns the amount of bytes in scanner's buffer ready to be read */
7924
7925  SANE_Int rst;
7926
7927  DBG (DBG_FNC,
7928       "+ Reading_BufferSize_Get(channels_per_dot=%i, channel_size=%i):\n",
7929       channels_per_dot, channel_size);
7930
7931  rst = 0;
7932
7933  if (channel_size > 0)
7934    {
7935      SANE_Int myAmount;
7936
7937      if (channels_per_dot < 1)
7938	{
7939	  /* read channels per dot from registers */
7940	  if (Read_Byte (dev->usb_handle, 0xe812, &channels_per_dot) == OK)
7941	    channels_per_dot = _B0 (channels_per_dot >> 6);
7942
7943	  if (channels_per_dot == 0)
7944	    channels_per_dot++;
7945	}
7946
7947      if (Read_Integer (dev->usb_handle, 0xef16, &myAmount) == OK)
7948	rst = ((channels_per_dot * 32) / channel_size) * myAmount;
7949    }
7950
7951  DBG (DBG_FNC, "- Reading_BufferSize_Get: %i bytes\n", rst);
7952
7953  return rst;
7954}
7955
7956static SANE_Int
7957Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, SANE_Int lamp,
7958	     SANE_Int resolution)
7959{
7960  SANE_Int rst = OK;
7961
7962  DBG (DBG_FNC, "+ Lamp_Warmup(*Regs, lamp=%i, resolution=%i)\n", lamp,
7963       resolution);
7964
7965  if (Regs != NULL)
7966    {
7967      SANE_Byte flb_lamp, tma_lamp;
7968      SANE_Int overdrivetime;
7969
7970      Lamp_Status_Get (dev, &flb_lamp, &tma_lamp);
7971
7972      /* ensure that selected lamp is switched on */
7973      if (lamp == FLB_LAMP)
7974	{
7975	  overdrivetime = RTS_Debug->overdrive_flb;
7976
7977	  if (flb_lamp == 0)
7978	    {
7979	      /* FLB-Lamp is turned off, lets turn on */
7980	      Lamp_Status_Set (dev, Regs, TRUE, FLB_LAMP);
7981	      waitforpwm = TRUE;
7982	    }
7983	}
7984      else
7985	{
7986	  /* is tma device attached to scanner ? */
7987	  if (RTS_isTmaAttached (dev) == TRUE)
7988	    {
7989	      overdrivetime = RTS_Debug->overdrive_ta;
7990
7991	      if (tma_lamp == 0)
7992		{
7993		  /* tma lamp is turned off */
7994		  Lamp_Status_Set (dev, Regs, FALSE, TMA_LAMP);
7995		  waitforpwm = TRUE;
7996		}
7997	    }
7998	  else
7999	    rst = ERROR;
8000	}
8001
8002      /* perform warmup process */
8003      if (rst == OK)
8004	{
8005	  Lamp_PWM_Setup (dev, lamp);
8006
8007	  if (waitforpwm == TRUE)
8008	    {
8009	      /*Lamp_PWM_DutyCycle_Set(dev, (lamp == TMA_LAMP)? 0x0e : 0x00); */
8010
8011	      if (RTS_Debug->warmup == TRUE)
8012		{
8013		  long ticks = GetTickCount () + overdrivetime;
8014
8015		  DBG (DBG_VRB, "- Lamp Warmup process. Please wait...\n");
8016
8017		  dev->status->warmup = TRUE;
8018
8019		  while (GetTickCount () <= ticks)
8020		    usleep (1000 * 200);
8021
8022		  Lamp_PWM_CheckStable (dev, resolution, lamp);
8023
8024		}
8025	      else
8026		DBG (DBG_VRB, "- Lamp Warmup process disabled.\n");
8027	    }
8028
8029	  /*Lamp_PWM_Setup(dev, lamp);
8030
8031	     if (waitforpwm == TRUE)
8032	     {
8033	     if (RTS_Debug->warmup == TRUE)
8034	     Lamp_PWM_CheckStable(dev, resolution, lamp);
8035
8036	     waitforpwm = FALSE;
8037	     } */
8038	}
8039
8040    }
8041  else
8042    rst = ERROR;
8043
8044  dev->status->warmup = FALSE;
8045
8046  DBG (DBG_FNC, "- Lamp_Warmup: %i\n", rst);
8047
8048  return rst;
8049}
8050
8051static SANE_Int
8052Scan_Start (struct st_device *dev)
8053{
8054  SANE_Int rst;
8055
8056  DBG (DBG_FNC, "+ Scan_Start:\n");
8057
8058  rst = ERROR;
8059  if (RTS_Enable_CCD (dev, dev->init_regs, 0x0f) == OK)
8060    {
8061      SANE_Byte Regs[RT_BUFFER_LEN], mlock;
8062      SANE_Int ypos, xpos, runb1;
8063      struct st_scanparams scancfg;
8064      struct st_hwdconfig hwdcfg;
8065      struct st_calibration myCalib;
8066      long tick;
8067
8068      memcpy (&Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
8069      memcpy (&scancfg, &scan, sizeof (struct st_scanparams));
8070
8071      dbg_ScanParams (&scancfg);
8072
8073      /* reserva buffer 6 dwords en fa84-fa9f */
8074      memset (&hwdcfg, 0, sizeof (struct st_hwdconfig));
8075
8076      /* wait till lamp is at home (should use timeout
8077         windows driver doesn't use it)
8078       */
8079      tick = GetTickCount () + 10000;
8080      while ((Head_IsAtHome (dev, Regs) == FALSE)
8081	     && (tick > GetTickCount ()));
8082
8083      if (v14b4 != 0)
8084	{
8085	  SANE_Int lfaa0 = 0;
8086
8087	  if (GainOffset_Counter_Inc (dev, &lfaa0) != OK)
8088	    return 0x02;
8089	}
8090
8091      tick = GetTickCount ();
8092
8093      /* set margin references */
8094      Refs_Set (dev, Regs, &scancfg);
8095
8096      /* locate head to right position */
8097      Load_StripCoords (scantype, &ypos, &xpos);
8098      if (ypos != 0)
8099	Head_Relocate (dev, dev->motorcfg->parkhomemotormove, MTR_FORWARD,
8100		       ypos);
8101
8102      /* perform lamp warmup */
8103      if (Lamp_Warmup
8104	  (dev, Regs, (scancfg.scantype == ST_NORMAL) ? FLB_LAMP : TMA_LAMP,
8105	   scan.resolution_x) == ERROR)
8106	return ERROR;
8107
8108      /* Calibration process */
8109
8110      /*592c */
8111      if (Calib_CreateBuffers (dev, &myCalib, v14b4) != OK)
8112	return ERROR;
8113
8114      /*5947 */
8115
8116/*
8117if (Calib_BlackShading_jkd(dev, Regs, &myCalib, &scancfg) == OK)
8118	Head_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove);
8119*/
8120
8121/*
8122if (Calib_test(dev, Regs, &myCalib, &scancfg) == OK )
8123	Head_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove);
8124*/
8125
8126/* Calibrate White shading correction */
8127      if ((RTS_Debug->wshading == TRUE) && (scan.scantype == ST_NORMAL))
8128	if (WShading_Calibrate (dev, Regs, &myCalib, &scancfg) == OK)
8129	  Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
8130
8131      hwdcfg.calibrate = RTS_Debug->calibrate;
8132
8133      if (RTS_Debug->calibrate != 0)
8134	{
8135	  /* Let's calibrate */
8136	  if ((scancfg.colormode != CM_COLOR) && (scancfg.channel == 3))
8137	    scancfg.colormode = CM_COLOR;
8138
8139	  hwdcfg.arrangeline = 0;
8140
8141	  if (scan.scantype == ST_NORMAL)
8142	    {
8143	      /* Calibration for reflective type */
8144
8145	      /*59e3 */
8146	      memcpy (&Regs, dev->init_regs,
8147		      RT_BUFFER_LEN * sizeof (SANE_Byte));
8148
8149	      if (Calibration (dev, Regs, &scancfg, &myCalib, 0) != OK)
8150		{
8151		  if (v14b4 == 0)
8152		    Calib_FreeBuffers (&myCalib);
8153		  return ERROR;
8154		}
8155	    }
8156	  else
8157	    {
8158	      /*59ed */
8159	      /* Calibration for negative/slide type */
8160
8161	    }
8162
8163	  /*5af1 */
8164	  if (RTS_Debug->ScanWhiteBoard != FALSE)
8165	    {
8166	      Head_ParkHome (dev, TRUE, dev->motorcfg->basespeedmotormove);
8167	      scan.ler = 1;
8168	    }
8169
8170	  scancfg.colormode = scan.colormode;
8171	}
8172      else
8173	{
8174	  /*5b1e */
8175	  /*Don't calibrate */
8176	  if (scan.scantype == ST_NORMAL)
8177	    {
8178	      Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP);
8179	    }
8180	  else
8181	    {
8182	      if ((scan.scantype == ST_TA) || (scan.scantype == ST_NEG))
8183		{
8184		  /*SANE_Int ta_y_start; */
8185		  Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP);
8186		  /*ta_y_start =
8187		     get_value(SCAN_PARAM, TA_Y_START, 0x2508, usbfile);
8188		     ta_y_start += (((((scan.coord.top * 3) * 5) * 5) * 32) / scancfg.resolution_x);
8189		     if (ta_y_start >= 500)
8190		     {
8191		     Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, ta_y_start);
8192		     scancfg.coord.top = 1;
8193		     scan.ler = 1;
8194		     } else
8195		     {
8196		     / *5ba9* /
8197		     if (ta_y_start > 0)
8198		     {
8199		     Head_Relocate(dev, dev->motorcfg->basespeedmotormove, MTR_FORWARD, ta_y_start);
8200		     scancfg.coord.top = 1;
8201		     scan.ler = 1;
8202		     }
8203		     } */
8204		}
8205	    }
8206	}
8207
8208      /*5bd0 */
8209      usleep (1000 * 200);
8210
8211      hwdcfg.scantype = scan.scantype;
8212      hwdcfg.motor_direction = MTR_FORWARD;
8213
8214      /* Set Origin */
8215      if ((scan.scantype >= ST_NORMAL) || (scan.scantype <= ST_NEG))
8216	{
8217	  scancfg.coord.left += scan.ser;
8218	  scancfg.coord.top += scan.ler;
8219	}
8220
8221      hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance;
8222      hwdcfg.highresolution = (scancfg.resolution_x <= 1200) ? FALSE : TRUE;
8223
8224      /*5c55 */
8225      /*
8226         if (RTS_Debug->calibrate == FALSE)
8227         {
8228         SANE_Int mytop = (((scancfg.coord.top * 5) * 5) * 16) / scancfg.resolution_y;
8229         if ((scancfg.resolution_y <= 150)&&(mytop < 300))
8230         {
8231         scancfg.coord.top = scancfg.resolution_y / 4;
8232         } else
8233         {
8234         if (mytop < 100)
8235         scancfg.coord.top = scancfg.resolution_y / 12;
8236         }
8237         }
8238       */
8239
8240      /*5cd9 */
8241      if (compression != FALSE)
8242	hwdcfg.compression = TRUE;
8243
8244      /* setting arrangeline option */
8245      hwdcfg.arrangeline = arrangeline;
8246      if (scancfg.resolution_x == 2400)
8247	{
8248	  /* 5cfa */
8249	  if (scancfg.colormode != CM_COLOR)
8250	    {
8251	      if ((scancfg.colormode == CM_GRAY) && (scancfg.channel == 3))
8252		hwdcfg.arrangeline = FIX_BY_SOFT;
8253	    }
8254	  else
8255	    hwdcfg.arrangeline = FIX_BY_SOFT;
8256	}
8257
8258      /*5d12 */
8259      if (dev->sensorcfg->type == CCD_SENSOR)
8260	{
8261	  /*5d3a */
8262	  scancfg.coord.left += 24;
8263	  switch (scancfg.resolution_x)
8264	    {
8265	    case 1200:
8266	      scancfg.coord.left -= 63;
8267	      break;
8268	    case 2400:
8269	      scancfg.coord.left -= 127;
8270	      break;
8271	    }
8272	}
8273      else
8274	{
8275	  /*5d5a */
8276	  /* CIS sensor */
8277	  /*5d6d */
8278	  scancfg.coord.left += 50;
8279	  switch (scancfg.resolution_x)
8280	    {
8281	    case 1200:
8282	      scancfg.coord.left -= 63;
8283	      break;
8284	    case 2400:
8285	      scancfg.coord.left -= 127;
8286	      break;
8287	    }
8288	}
8289
8290      /* 5d92 */
8291      DBG (DBG_FNC, " ->Scan_Start xStart=%i, xExtent=%i\n",
8292	   scancfg.coord.left, scancfg.coord.width);
8293
8294      runb1 = 1;
8295      if (scan.scantype == ST_NORMAL)
8296	{
8297	  /*5db7 */
8298	  if ((scancfg.resolution_x == 1200)
8299	      || (scancfg.resolution_x == 2400))
8300	    {
8301	      /*5e41 */
8302	      if ((scancfg.resolution_y / 10) > scancfg.coord.top)
8303		runb1 = 0;
8304	    }
8305	  else
8306	    {
8307	      if ((scancfg.resolution_x == 600)
8308		  && (RTS_Debug->usbtype == USB11)
8309		  && (scancfg.colormode == CM_COLOR))
8310		{
8311		  /*5ded */
8312		  if ((scancfg.resolution_y / 10) > scancfg.coord.top)
8313		    runb1 = 0;
8314		}
8315	      else
8316		{
8317		  if ((scancfg.resolution_x == 600)
8318		      || (scancfg.resolution_x == 300))
8319		    {
8320		      /*5e11 */
8321		      if (scancfg.resolution_y > scancfg.coord.top)
8322			runb1 = 0;
8323		    }
8324		  else
8325		    runb1 = 0;
8326		}
8327	    }
8328	}
8329      else
8330	{
8331	  /*5e7c *//* entra aquí */
8332	  if ((scancfg.resolution_y / 10) > scancfg.coord.top)
8333	    runb1 = 0;
8334	}
8335      /*5eb1 */
8336      if (runb1 == 1)		/*entra */
8337	{
8338	  SANE_Int val1 = scancfg.coord.top - (scancfg.resolution_y / 10);
8339	  scancfg.coord.top -= val1;
8340	  Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, (dev->motorcfg->resolution / scancfg.resolution_y) * val1);	/*x168 */
8341	}
8342
8343      /*5efe */
8344      if (RTS_Debug->calibrate != FALSE)
8345	{
8346	  if (use_gamma_tables != FALSE)
8347	    {
8348	      hwdcfg.use_gamma_tables = TRUE;
8349	      hp_gamma->depth = 0;
8350	    }
8351
8352	  /*5f24 */
8353	  hwdcfg.white_shading = TRUE;
8354	  hwdcfg.black_shading = TRUE;
8355	  hwdcfg.unk3 = 0;
8356	  RTS_Setup (dev, Regs, &scancfg, &hwdcfg, &calibdata->gain_offset);
8357
8358	  myCalib.shading_type = 0;
8359	  myCalib.shadinglength =
8360	    min (myCalib.shadinglength, scan.shadinglength);
8361
8362	  if (scancfg.colormode != CM_COLOR)
8363	    {
8364	      if ((scancfg.channel > 0) && (scancfg.channel < 3))
8365		myCalib.WRef[0] = myCalib.WRef[scancfg.channel];
8366	    }
8367
8368	  RTS_WriteRegs (dev->usb_handle, Regs);
8369
8370	  /* apply gamma if required */
8371	  Gamma_Apply (dev, Regs, &scancfg, &hwdcfg, hp_gamma);
8372
8373	  Shading_apply (dev, Regs, &scancfg, &myCalib);
8374
8375	  /* Save to file? */
8376	  if (RTS_Debug->DumpShadingData != FALSE)
8377	    dump_shading (&myCalib);	/*5ff9 */
8378	}
8379      else
8380	RTS_Setup (dev, Regs, &scancfg, &hwdcfg, default_gain_offset);
8381
8382      /*602a */
8383      RTS_Debug->calibrate = hwdcfg.calibrate;
8384      binarythresholdh = bw_threshold;
8385      binarythresholdl = bw_threshold;
8386      DBG (DBG_FNC, ">  bw threshold -- hi=%i, lo=%i\n", binarythresholdh,
8387	   binarythresholdl);
8388
8389      /* set threshold high */
8390      data_lsb_set (&Regs[0x1a0], binarythresholdh, 2);
8391
8392      /* set threshold low */
8393      data_lsb_set (&Regs[0x19e], binarythresholdl, 2);
8394
8395      /* if has motorcurves... */
8396      if ((Regs[0xdf] & 0x10) != 0)
8397	data_bitset (&Regs[0x01], 0x02, 1);
8398
8399      /* Set MLOCK */
8400      mlock = get_value (SCAN_PARAM, MLOCK, 0, usbfile) & 1;
8401      data_bitset (&Regs[0x00], 0x10, mlock);	       /*---x----*/
8402
8403      if (dev->motorcfg->changemotorcurrent != FALSE)
8404	Motor_Change (dev, Regs,
8405		      Motor_GetFromResolution (scancfg.resolution_x));
8406
8407      /* set gain control mode */
8408      Lamp_SetGainMode (dev, Regs, scancfg.resolution_x,
8409			Lamp_GetGainMode (dev, scancfg.resolution_x,
8410					  scan.scantype));
8411
8412      RTS_WaitScanEnd (dev, 15000);
8413      if (v14b4 == 0)
8414	Calib_FreeBuffers (&myCalib);
8415
8416      /* release motor */
8417      Motor_Release (dev);
8418
8419
8420#ifdef developing
8421/*	prueba(Regs);
8422	dbg_registers(Regs);*/
8423      /*WShading_Calibrate(dev, Regs, &myCalib, &scancfg); */
8424      /*shadingtest1(dev, Regs, &myCalib); */
8425#endif
8426
8427      if (RTS_Warm_Reset (dev) == OK)
8428	{
8429	  RTS_WriteRegs (dev->usb_handle, Regs);
8430	  usleep (1000 * 500);
8431
8432	  if (RTS_Execute (dev) == OK)
8433	    {
8434	      Lamp_Status_Timer_Set (dev, 0);
8435
8436	      /* Let scanner some time to store some data */
8437	      if ((dev->chipset->model == RTS8822L_02A)
8438		  && (scancfg.resolution_x > 2400))
8439		usleep (1000 * 5000);
8440
8441	      rst = OK;
8442	    }
8443	}
8444    }
8445
8446  DBG (DBG_FNC, "- Scan_Start: %i\n", rst);
8447
8448  return rst;
8449}
8450
8451static SANE_Int
8452RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs,
8453		 struct st_scanparams *scancfg, SANE_Int somevalue)
8454{
8455  SANE_Int rst = ERROR;		/* default */
8456
8457  DBG (DBG_FNC, "+ RTS_Setup_Motor(*Regs, *scancfg, somevalue=%i):\n",
8458       somevalue);
8459  dbg_ScanParams (scancfg);
8460
8461  if ((Regs != NULL) && (scancfg != NULL))
8462    {
8463      SANE_Int colormode, mymode;
8464
8465      colormode = ((scancfg->colormode != CM_COLOR)
8466		   && (scancfg->channel == 3)) ? 3 : scancfg->colormode;
8467      mymode =
8468	RTS_GetScanmode (dev, scantype, colormode, scancfg->resolution_x);
8469
8470      if (mymode != -1)
8471	{
8472	  SANE_Int mbs[2] = { 0 };	/* motor back steps */
8473	  SANE_Int step_size, step_type, dummyline, myvalue, lf02c;
8474	  struct st_scanmode *sm;
8475
8476	  sm = dev->scanmodes[mymode];
8477
8478	  /* set motor step type */
8479	  data_bitset (&Regs[0xd9], 0x70, sm->scanmotorsteptype);	       /*-xxx----*/
8480
8481	  /* set motor direction (polarity) */
8482	  data_bitset (&Regs[0xd9], 0x80, somevalue >> 3);	/*e------- */
8483
8484	  /* next value doesn't seem to have any effect */
8485	  data_bitset (&Regs[0xd9], 0x0f, somevalue);			       /*----efgh*/
8486
8487	  /* 0 enable/1 disable motor */
8488	  data_bitset (&Regs[0xdd], 0x80, somevalue >> 4);	/*d------- */
8489
8490	  /* next value doesn't seem to have any effect */
8491	  data_bitset (&Regs[0xdd], 0x40, somevalue >> 4);		       /*-d------*/
8492
8493	  switch (sm->scanmotorsteptype)
8494	    {
8495	    case STT_OCT:
8496	      step_type = 8;
8497	      break;
8498	    case STT_QUART:
8499	      step_type = 4;
8500	      break;
8501	    case STT_HALF:
8502	      step_type = 2;
8503	      break;
8504	    default:
8505	      step_type = 1;
8506	      break;		/* STT_FULL */
8507	    }
8508
8509	  /* set dummy lines */
8510	  dummyline = sm->dummyline;
8511	  if (dummyline == 0)
8512	    dummyline++;
8513
8514	  data_bitset (&Regs[0xd6], 0xf0, dummyline);	/*xxxx---- */
8515
8516	  /* Set if motor has curves */
8517	  data_bitset (&Regs[0xdf], 0x10, ((sm->motorcurve != -1) ? 1 : 0));		 /*---x----*/
8518
8519	  /* set last step of deccurve.scanbufferfull table to 16 */
8520	  data_lsb_set (&Regs[0xea], 0x10, 3);
8521
8522	  /* set last step of deccurve.normalscan table to 16 */
8523	  data_lsb_set (&Regs[0xed], 0x10, 3);
8524
8525	  /* set last step of deccurve.smearing table to 16 */
8526	  data_lsb_set (&Regs[0xf0], 0x10, 3);
8527
8528	  /* set last step of deccurve.parkhome table to 16 */
8529	  data_lsb_set (&Regs[0xf3], 0x10, 3);
8530
8531	  /* set step size */
8532	  step_size =
8533	    _B0 ((dev->motorcfg->resolution * step_type) /
8534		 (dummyline * scancfg->resolution_y));
8535	  data_lsb_set (&Regs[0xe0], step_size - 1, 1);
8536
8537	  /* set line exposure time */
8538	  myvalue = data_lsb_get (&Regs[0x30], 3);
8539	  myvalue += ((myvalue + 1) % step_size);
8540	  data_lsb_set (&Regs[0x30], myvalue, 3);
8541
8542	  /* set last step of accurve.normalscan table */
8543	  myvalue = ((myvalue + 1) / step_size) - 1;
8544	  data_lsb_set (&Regs[0xe1], myvalue, 3);
8545
8546	  /* 42b30eb */
8547	  lf02c = 0;
8548	  if (sm->motorcurve != -1)
8549	    {
8550	      if (sm->motorcurve < dev->mtrsetting_count)
8551		{
8552		  struct st_motorcurve *ms = dev->mtrsetting[sm->motorcurve];
8553		  ms->motorbackstep = sm->motorbackstep;
8554		}
8555
8556	      DBG (DBG_FNC, " -> Setting up step motor using motorcurve %i\n",
8557		   sm->motorcurve);
8558	      lf02c = Motor_Setup_Steps (dev, Regs, sm->motorcurve);
8559
8560	      /* set motor back steps */
8561	      mbs[1] = sm->motorbackstep;
8562	      if (mbs[1] >= (smeardeccurvecount + smearacccurvecount))
8563		mbs[0] =
8564		  mbs[1] - (smeardeccurvecount + smearacccurvecount) + 2;
8565	      else
8566		mbs[0] = 0;
8567
8568	      if (mbs[1] >= (deccurvecount + acccurvecount))
8569		mbs[1] -= (deccurvecount + acccurvecount) + 2;
8570	      else
8571		mbs[1] = 0;
8572	    }
8573	  else
8574	    {
8575	      /* this scanner hasn't got any motorcurve */
8576
8577	      /* set last step of accurve.smearing table (same as accurve.normalscan) */
8578	      data_lsb_set (&Regs[0xe4], myvalue, 3);
8579
8580	      /* set last step of accurve.parkhome table (same as accurve.normalscan) */
8581	      data_lsb_set (&Regs[0xe7], myvalue, 3);
8582
8583	      /* both motorbacksteps are equal */
8584	      mbs[0] = sm->motorbackstep;
8585	      mbs[1] = sm->motorbackstep;
8586	    }
8587
8588	  /* show msi and motorbacksteps */
8589	  DBG (DBG_FNC, " -> msi            = %i\n", sm->msi);
8590	  DBG (DBG_FNC, " -> motorbackstep1 = %i\n", mbs[0]);
8591	  DBG (DBG_FNC, " -> motorbackstep2 = %i\n", mbs[1]);
8592
8593	  /* set msi */
8594	  data_bitset (&Regs[0xda], 0xff, _B0 (sm->msi));	/*xxxxxxxx */
8595	  data_bitset (&Regs[0xdd], 0x03, _B1 (sm->msi));	      /*------xx*/
8596
8597	  /* set motorbackstep (a) */
8598	  data_bitset (&Regs[0xdb], 0xff, _B0 (mbs[0]));	/*xxxxxxxx */
8599	  data_bitset (&Regs[0xdd], 0x0c, _B1 (mbs[0]));	      /*----xx--*/
8600
8601	  /* set motorbackstep (b) */
8602	  data_bitset (&Regs[0xdc], 0xff, _B0 (mbs[1]));	/*xxxxxxxx */
8603	  data_bitset (&Regs[0xdd], 0x30, _B1 (mbs[1]));	      /*--xx----*/
8604
8605	  /* 328b */
8606
8607	  /* get dummy lines count */
8608	  dummyline = data_bitget (&Regs[0xd6], 0xf0);
8609
8610	  myvalue = scancfg->coord.top * (dummyline * step_size);
8611
8612	  if (lf02c >= myvalue)
8613	    scancfg->coord.top = 1;
8614	  else
8615	    scancfg->coord.top -= (lf02c / (dummyline * step_size)) - 1;
8616
8617	  rst = lf02c;		/* Result from Motor_Setup_Steps */
8618	}
8619    }
8620
8621  DBG (DBG_FNC, "- RTS_Setup_Motor: %i\n", rst);
8622
8623  return rst;
8624}
8625
8626static void
8627RTS_Setup_Exposure_Times (SANE_Byte * Regs, struct st_scanparams *scancfg,
8628			  struct st_scanmode *sm)
8629{
8630  DBG (DBG_FNC, "> RTS_Setup_Exposure_Times\n");
8631
8632  if ((sm != NULL) && (Regs != NULL) && (scancfg != NULL))
8633    {
8634      SANE_Int myexpt[3], linexpt, a;
8635
8636      /* calculate line exposure time */
8637      linexpt = sm->ctpc + 1;
8638      if (RTS_Debug->usbtype == USB11)
8639	linexpt *= sm->multiexposureforfullspeed;
8640
8641      if (scancfg->depth > 8)
8642	linexpt *= sm->multiexposurefor16bitmode;
8643
8644      linexpt--;
8645
8646      /* generate exposure times for each channel color */
8647      for (a = CL_RED; a <= CL_BLUE; a++)
8648	{
8649	  if ((linexpt > sm->mexpt[a]) && (sm->expt[a] == 0))
8650	    sm->expt[a] = sm->mexpt[a];
8651
8652	  myexpt[a] = (sm->expt[a] == 0) ? sm->mexpt[a] : sm->expt[a];
8653	}
8654
8655      /* save exposure times */
8656      DBG (DBG_FNC, "-> Exposure times : %04x, %04x, %04x\n", sm->expt[0],
8657	   sm->expt[1], sm->expt[2]);
8658      data_lsb_set (&Regs[0x36], sm->expt[CL_RED], 3);
8659      data_lsb_set (&Regs[0x3c], sm->expt[CL_GREEN], 3);
8660      data_lsb_set (&Regs[0x42], sm->expt[CL_BLUE], 3);
8661
8662      /* save maximum exposure times */
8663      DBG (DBG_FNC, "-> Maximum exposure times: %04x, %04x, %04x\n",
8664	   sm->mexpt[0], sm->mexpt[1], sm->mexpt[2]);
8665      data_lsb_set (&Regs[0x33], sm->mexpt[CL_RED], 3);
8666      data_lsb_set (&Regs[0x39], sm->mexpt[CL_GREEN], 3);
8667      data_lsb_set (&Regs[0x3f], sm->mexpt[CL_BLUE], 3);
8668
8669      /* save line exposure time */
8670      data_lsb_set (&Regs[0x30], linexpt, 3);
8671
8672      /* scancfg->expt = lowest value */
8673      scancfg->expt = min (min (myexpt[1], myexpt[2]), myexpt[0]);
8674    }
8675}
8676
8677static SANE_Int
8678RTS_Setup_Line_Distances (struct st_device *dev, SANE_Byte * Regs,
8679			  struct st_scanparams *scancfg,
8680			  struct st_hwdconfig *hwdcfg, SANE_Int mycolormode,
8681			  SANE_Int arrangeline)
8682{
8683  SANE_Int iLineDistance = 0;
8684
8685  if (arrangeline == FIX_BY_HARD)
8686    {
8687      /* we don't need to arrange retrieved line */
8688      SANE_Int mylinedistance, myevenodddist;
8689
8690      mylinedistance =
8691	(dev->sensorcfg->line_distance * scancfg->resolution_y) /
8692	dev->sensorcfg->resolution;
8693
8694      if (hwdcfg->highresolution == TRUE)
8695	myevenodddist =
8696	  (hwdcfg->sensorevenodddistance * scancfg->resolution_y) /
8697	  dev->sensorcfg->resolution;
8698      else
8699	myevenodddist = 0;
8700
8701      data_bitset (&Regs[0x149], 0x3f, myevenodddist);
8702      data_bitset (&Regs[0x14a], 0x3f, mylinedistance);
8703      data_bitset (&Regs[0x14b], 0x3f, mylinedistance + myevenodddist);
8704      data_bitset (&Regs[0x14c], 0x3f, mylinedistance * 2);
8705      data_bitset (&Regs[0x14d], 0x3f, (mylinedistance * 2) + myevenodddist);
8706    }
8707  else
8708    {
8709      /* arrange retrieved line */
8710      data_bitset (&Regs[0x149], 0x3f, 0);
8711      data_bitset (&Regs[0x14a], 0x3f, 0);
8712      data_bitset (&Regs[0x14b], 0x3f, 0);
8713      data_bitset (&Regs[0x14c], 0x3f, 0);
8714      data_bitset (&Regs[0x14d], 0x3f, 0);
8715
8716      if (arrangeline == FIX_BY_SOFT)
8717	{
8718	  if (hwdcfg->highresolution == FALSE)
8719	    {
8720	      if (mycolormode == CM_COLOR)
8721		{
8722		  iLineDistance =
8723		    (dev->sensorcfg->line_distance * scan2.resolution_y) * 2;
8724		  iLineDistance =
8725		    (iLineDistance / dev->sensorcfg->resolution) + 1;
8726		  if (iLineDistance < 2)
8727		    iLineDistance = 2;
8728		}
8729	    }
8730	  else
8731	    {
8732	      /* bcc */
8733	      if (mycolormode == CM_COLOR)
8734		iLineDistance =
8735		  ((dev->sensorcfg->line_distance * 2) +
8736		   hwdcfg->sensorevenodddistance) * scan2.resolution_y;
8737	      else
8738		iLineDistance =
8739		  dev->sensorcfg->line_distance * scan2.resolution_y;
8740
8741	      iLineDistance =
8742		(iLineDistance / dev->sensorcfg->resolution) + 1;
8743	      if (iLineDistance < 2)
8744		iLineDistance = 2;
8745	    }
8746
8747	  /* c25 */
8748	  iLineDistance &= 0xffff;
8749	  v15b4 = (iLineDistance > 0) ? 1 : 0;
8750	  imagesize += iLineDistance * bytesperline;
8751	}
8752    }
8753
8754  DBG (DBG_FNC,
8755       "> RTS_Setup_Line_Distances(*Regs, *scancfg, *hwdcfg, mycolormode=%i, arrangeline=%i): %i\n",
8756       mycolormode, arrangeline, iLineDistance);
8757
8758  return iLineDistance;
8759}
8760
8761static SANE_Int
8762RTS_Setup_Depth (SANE_Byte * Regs, struct st_scanparams *scancfg,
8763		 SANE_Int mycolormode)
8764{
8765  /* channels_per_line = channels_per_dot * scan.width
8766     bytes_per_line = channels_per_line * bits_per_channel
8767   */
8768
8769  SANE_Int bytes_per_line = 0;
8770
8771  if ((scancfg != NULL) && (Regs != NULL))
8772    {
8773      SANE_Int channels_per_line =
8774	data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width;
8775
8776      bytes_per_line = channels_per_line;
8777
8778      /* set bits per channel in shading correction's register (0x1cf) */
8779      if (mycolormode == CM_LINEART)
8780	{
8781	  /* lineart mode */
8782	  bytes_per_line = (bytes_per_line + 7) / 8;
8783	  data_bitset (&Regs[0x1cf], 0x30, 3);		    /*--11----*/
8784	}
8785      else
8786	{
8787	  /*f0c */
8788	  switch (scancfg->depth)
8789	    {
8790	    case 16:
8791	      /* 16 bits per channel */
8792	      bytes_per_line *= 2;
8793	      data_bitset (&Regs[0x1cf], 0x30, 2);			    /*--10----*/
8794	      break;
8795	    case 12:
8796	      /* 12 bits per channel */
8797	      bytes_per_line *= 2;
8798	      data_bitset (&Regs[0x1cf], 0x30, 1);			    /*--01----*/
8799	      break;
8800	    default:
8801	      /* 8 bits per channel */
8802	      data_bitset (&Regs[0x1cf], 0x30, 0);			    /*--00----*/
8803	      break;
8804	    }
8805	}
8806    }
8807
8808  return bytes_per_line;
8809}
8810
8811static void
8812RTS_Setup_Shading (SANE_Byte * Regs, struct st_scanparams *scancfg,
8813		   struct st_hwdconfig *hwdcfg, SANE_Int bytes_per_line)
8814{
8815  DBG (DBG_FNC,
8816       "> RTS_Setup_Shading(*Regs, *scancfg, *hwdcfg, bytes_per_line=%i)\n",
8817       bytes_per_line);
8818
8819  if ((Regs != NULL) && (hwdcfg != NULL))
8820    {
8821      SANE_Int dots_count, myvalue, myvalue2, mem_available, resolution_ratio,
8822	sensor_line_distance;
8823      SANE_Int channels, table_size;
8824
8825      resolution_ratio = Regs[0x0c0] & 0x1f;
8826
8827      /* 50de */
8828      data_bitset (&Regs[0x1bf], 0x18, hwdcfg->unk3);	       /*---xx---*/
8829
8830      /* Enable black shading correction ? */
8831      data_bitset (&Regs[0x1cf], 0x08, hwdcfg->black_shading);		/*----x---*/
8832
8833      /* Enable white shading correction ? */
8834      data_bitset (&Regs[0x1cf], 0x04, hwdcfg->white_shading);		/*-----x--*/
8835
8836      if ((hwdcfg->white_shading != FALSE) && (hwdcfg->black_shading != FALSE)
8837	  && (hwdcfg->unk3 != 0))
8838	data_bitset (&Regs[0x1cf], 0x04, 0);		    /*-----x--*/
8839
8840      table_size = 0;
8841
8842      /* if hwdcfg->black_shading */
8843      if ((Regs[0x1cf] & 8) != 0)
8844	table_size = (resolution_ratio * scancfg->coord.width) * 2;	/* black shading buffer size? */
8845
8846      /* if hwdcfg->white_shading */
8847      if ((Regs[0x1cf] & 4) != 0)
8848	table_size += (resolution_ratio * scancfg->coord.width) * 2;	/* white shading buffer size? */
8849
8850      /* Regs 0x1ba, 0x1bb, 0x1bd, 0x1c0 seem to be 4 pointers
8851         to some buffer related to shading correction */
8852
8853      Regs[0x1ba] = 0x00;
8854      table_size = (table_size + v160c_block_size - 1) / v160c_block_size;
8855      table_size = ((table_size + 15) / 16) + 16;
8856
8857      Regs[0x1bf] &= 0xfe;
8858      Regs[0x1bb] = _B0 (table_size);
8859      Regs[0x1bc] = _B1 (table_size);
8860      Regs[0x1bf] |= _B2 (table_size) & 1;	    /*-------x*/
8861
8862      Regs[0x1bf] &= 0xf9;
8863      Regs[0x1bd] = _B0 (table_size * 2);
8864      Regs[0x1be] = _B1 (table_size * 2);
8865      Regs[0x1bf] |= (_B2 (table_size * 2) & 3) << 1;	       /*-----xx-*/
8866
8867      data_wide_bitset (&Regs[0x1c0], 0xfffff, table_size * 3);
8868
8869      mem_available = mem_total - ((table_size * 3) * 16);
8870      sensor_line_distance = Regs[0x14a] & 0x3f;
8871
8872      /* select case channels_per_dot */
8873      channels = data_lsb_get (&Regs[0x12], 1) >> 6;
8874
8875      switch (channels)
8876	{
8877	case 3:		/* 3 channels per dot */
8878	  /* 528d */
8879	  dots_count = bytes_per_line / 3;	/* 882 */
8880	  myvalue =
8881	    (((sensor_line_distance + 1) * dots_count) + v160c_block_size -
8882	     1) / v160c_block_size;
8883	  myvalue2 = myvalue;
8884	  mem_available = (mem_available - (myvalue * 3) + 2) / 3;
8885
8886	  myvalue += (table_size * 3) * 8;
8887	  myvalue = ((myvalue * 2) + mem_available);
8888
8889	  data_bitset (&Regs[0x1c2], 0xf0, _B2 ((myvalue / 16) + 1));	/* 4 higher bits   xxxx---- */
8890	  data_wide_bitset (&Regs[0x1c3], 0xffff, (myvalue / 16) + 1);	/* 16 lower bits */
8891
8892	  myvalue = myvalue + myvalue2 + mem_available;
8893	  data_wide_bitset (&Regs[0x1c5], 0xfffff, (myvalue / 16) + 1);
8894	  break;
8895	case 2:		/* 2 channels per dot */
8896	  dots_count = bytes_per_line / 2;
8897	  myvalue =
8898	    (((sensor_line_distance + 1) * dots_count) + v160c_block_size -
8899	     1) / v160c_block_size;
8900	  mem_available = ((mem_available - myvalue) + 1) / 2;
8901	  myvalue += (((table_size * 3) + mem_available) / 16) + 1;
8902
8903	  data_bitset (&Regs[0x1c2], 0xf0, _B2 (myvalue));	/* 4 higher bits   xxxx---- */
8904	  data_wide_bitset (&Regs[0x1c3], 0xffff, myvalue);	/* 16 lower bits */
8905	  break;
8906	default:
8907	  dots_count = bytes_per_line;
8908	  break;
8909	}
8910
8911      Regs[0x01c7] &= 0x0f;
8912      Regs[0x01c8] = _B0 ((mem_total - 1) / 16);
8913      Regs[0x01c9] = _B1 ((mem_total - 1) / 16);
8914      Regs[0x01c7] |= (_B2 ((mem_total - 1) / 16) & 0x0f) << 4;
8915
8916      mem_available -= (dots_count + v160c_block_size - 1) / v160c_block_size;
8917      mem_available /= 16;
8918      Regs[0x0712] &= 0x0f;
8919      Regs[0x0710] = _B0 (mem_available);
8920      Regs[0x0711] = _B1 (mem_available);
8921      Regs[0x0712] |= _B0 (_B2 (mem_available) << 4);	/*xxxx---- */
8922
8923      Regs[0x0713] = 0x00;
8924      Regs[0x0714] = 0x10;
8925      Regs[0x0715] &= 0xf0;
8926    }
8927}
8928
8929static void
8930RTS_Setup_Arrangeline (struct st_device *dev, struct st_hwdconfig *hwdcfg,
8931		       SANE_Int colormode)
8932{
8933  dev->scanning->arrange_compression =
8934    (colormode == CM_LINEART) ? FALSE : hwdcfg->compression;
8935
8936  if ((colormode == CM_LINEART)
8937      || ((colormode == CM_GRAY) && (hwdcfg->highresolution == FALSE)))
8938    arrangeline2 = 0;
8939  else
8940    arrangeline2 = hwdcfg->arrangeline;
8941
8942  dev->scanning->arrange_hres = hwdcfg->highresolution;
8943  dev->scanning->arrange_sensor_evenodd_dist =
8944    (hwdcfg->highresolution == FALSE) ? 0 : hwdcfg->sensorevenodddistance;
8945}
8946
8947static void
8948RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs,
8949		    struct st_scanparams *scancfg, SANE_Int mycolormode)
8950{
8951  DBG (DBG_FNC, "> RTS_Setup_Channels(colormode=%i)\n", mycolormode);
8952
8953  if ((scancfg != NULL) && (Regs != NULL))
8954    {
8955      if ((mycolormode != CM_COLOR) && (mycolormode != 3))
8956	{
8957	  /* CM_GRAY || CM_LINEART */
8958	  if (scancfg->samplerate == LINE_RATE)
8959	    {
8960	      /* Setting channels_per_dot to 1 */
8961	      data_bitset (&Regs[0x12], 0xc0, 1);	/*01------ */
8962
8963	      /* setting one rgb_channel_order */
8964	      data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[scancfg->channel]);		     /*------xx*/
8965
8966	      /* set sensor_channel_color_order */
8967	      data_bitset (&Regs[0x60a], 0x3f, 6);		    /*--xxxxxx*/
8968
8969	      /* set samplerate */
8970	      data_bitset (&Regs[0x1cf], 0x40, PIXEL_RATE);		     /*-x------*/
8971
8972	      /* set unknown data */
8973	      data_bitset (&Regs[0x1cf], 0x80, 1);	/*x------- */
8974
8975	      if (scancfg->channel == dev->sensorcfg->rgb_order[1])
8976		{
8977		  /* mexpts[CL_RED] = mexpts[CL_GREEN] */
8978		  data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x39], 3),
8979				3);
8980
8981		  /* expts[CL_RED] = expts[CL_GREEN] */
8982		  data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x3c], 3),
8983				3);
8984		}
8985	      else if (scancfg->channel == dev->sensorcfg->rgb_order[2])
8986		{
8987		  /* mexpts[CL_RED] = mexpts[CL_BLUE] */
8988		  data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x3f], 3),
8989				3);
8990
8991		  /* expts[CL_RED] = expts[CL_BLUE] */
8992		  data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x42], 3),
8993				3);
8994		}
8995	    }
8996	  else
8997	    {
8998	      /* e01 */
8999	      /* setting channels_per_dot to 2 */
9000	      data_bitset (&Regs[0x12], 0xc0, 2);
9001
9002	      /* set two channel color order */
9003	      data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->channel_gray[0]);			 /*------xx*/
9004	      data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->channel_gray[1]);			 /*----xx--*/
9005
9006	      /* set samplerate */
9007	      data_bitset (&Regs[0x1cf], 0x40, LINE_RATE);
9008
9009	      /* set unknown data */
9010	      data_bitset (&Regs[0x1cf], 0x80, 1);
9011	    }
9012	}
9013      else
9014	{
9015	  /* CM_COLOR || 3 */
9016	  /* e42 */
9017
9018	  /* setting channels_per_dot to 3 */
9019	  data_bitset (&Regs[0x12], 0xc0, 3);
9020
9021	  /* setting samplerate */
9022	  data_bitset (&Regs[0x1cf], 0x40, scancfg->samplerate);
9023
9024	  /* set unknown data */
9025	  data_bitset (&Regs[0x1cf], 0x80, 0);
9026
9027	  /* set sensor chanel_color_order */
9028	  data_bitset (&Regs[0x60a], 0x03, dev->sensorcfg->channel_color[2]);		   /*------xx*/
9029	  data_bitset (&Regs[0x60a], 0x0c, dev->sensorcfg->channel_color[1]);		   /*----xx--*/
9030	  data_bitset (&Regs[0x60a], 0x30, dev->sensorcfg->channel_color[0]);		   /*--xx----*/
9031
9032	  /* set rgb_channel_order */
9033	  data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[0]);	      /*------xx*/
9034	  data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->rgb_order[1]);	      /*----xx--*/
9035	  data_bitset (&Regs[0x12], 0x30, dev->sensorcfg->rgb_order[2]);	      /*--xx----*/
9036	}
9037    }
9038}
9039
9040static SANE_Int
9041RTS_Setup (struct st_device *dev, SANE_Byte * Regs,
9042	   struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg,
9043	   struct st_gain_offset *gain_offset)
9044{
9045  SANE_Int rst = ERROR;		/* default */
9046  SANE_Int lSMode;
9047  SANE_Byte mycolormode;
9048
9049  DBG (DBG_FNC, "+ RTS_Setup:\n");
9050  dbg_ScanParams (scancfg);
9051  dbg_hwdcfg (hwdcfg);
9052
9053  mycolormode = scancfg->colormode;
9054  if (scancfg->colormode != CM_COLOR)
9055    {
9056      if (scancfg->colormode == CM_LINEART)
9057	scancfg->depth = 8;
9058
9059      if (scancfg->channel == 3)
9060	{
9061	  if (scancfg->colormode == CM_GRAY)
9062	    mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR;
9063	  else
9064	    mycolormode = 3;
9065	}
9066    }
9067
9068  /* 42b47d6 */
9069  memcpy (&scan2, scancfg, sizeof (struct st_scanparams));
9070
9071  scantype = hwdcfg->scantype;
9072  lSMode =
9073    RTS_GetScanmode (dev, scantype, mycolormode, scancfg->resolution_x);
9074  if (lSMode >= 0)
9075    {
9076      struct st_scanmode *sm = dev->scanmodes[lSMode];
9077
9078      if (sm != NULL)
9079	{
9080	  SANE_Int dummyline, iLineDistance, resolution_ratio, bytes_per_line;
9081	  struct st_coords rts_coords;
9082
9083	  iLineDistance = 0;
9084
9085	  scancfg->timing = sm->timing;
9086	  scancfg->sensorresolution =
9087	    dev->timings[scancfg->timing]->sensorresolution;
9088	  scancfg->shadinglength =
9089	    (((scancfg->sensorresolution * 17) / 2) + 3) & 0xfffffffc;
9090	  scancfg->samplerate = sm->samplerate;
9091
9092	  hwdcfg->motorplus = sm->motorplus;
9093
9094	  /* set systemclock */
9095	  data_bitset (&Regs[0x00], 0x0f, sm->systemclock);
9096
9097	  /* setting exposure times */
9098	  RTS_Setup_Exposure_Times (Regs, scancfg, sm);
9099
9100	  /* setting arranges */
9101	  RTS_Setup_Arrangeline (dev, hwdcfg, mycolormode);
9102
9103	  /* set up line distances */
9104	  iLineDistance =
9105	    RTS_Setup_Line_Distances (dev, Regs, scancfg, hwdcfg, mycolormode,
9106				      arrangeline);
9107
9108	  /* 4c67 */
9109
9110	  /* setup channel colors */
9111	  RTS_Setup_Channels (dev, Regs, scancfg, mycolormode);
9112
9113	  /* setup depth */
9114	  bytes_per_line = RTS_Setup_Depth (Regs, scancfg, mycolormode);
9115
9116	  /* f61 */
9117
9118	  /* Set resolution ratio */
9119	  resolution_ratio =
9120	    (scancfg->sensorresolution / scancfg->resolution_x) & 0x1f;
9121	  data_bitset (&Regs[0xc0], 0x1f, resolution_ratio);
9122
9123	  /* set sensor timing values */
9124	  RTS_Setup_SensorTiming (dev, scancfg->timing, Regs);
9125
9126	  data_bitset (&Regs[0xd8], 0x40, ((scantype == ST_NORMAL) ? 0 : 1));		  /*-x------*/
9127
9128	  /* Use static head ? */
9129	  data_bitset (&Regs[0xd8], 0x80, ((hwdcfg->static_head == FALSE) ? 1 : 0));	/*x------- */
9130
9131	  /* Setting up gamma */
9132	  RTS_Setup_Gamma (Regs, hwdcfg);
9133
9134	  /* setup shading correction */
9135	  RTS_Setup_Shading (Regs, scancfg, hwdcfg, bytes_per_line);
9136
9137	  /* setup stepper motor */
9138	  hwdcfg->startpos =
9139	    RTS_Setup_Motor (dev, Regs, scancfg,
9140			     hwdcfg->motor_direction | MTR_ENABLED);
9141
9142	  /* set coordinates */
9143	  dummyline = data_bitget (&Regs[0xd6], 0xf0);
9144
9145	  if (scancfg->coord.left == 0)
9146	    scancfg->coord.left++;
9147	  if (scancfg->coord.top == 0)
9148	    scancfg->coord.top++;
9149
9150	  rts_coords.left = scancfg->coord.left * resolution_ratio;
9151	  rts_coords.width = scancfg->coord.width * resolution_ratio;
9152	  rts_coords.top = scancfg->coord.top * dummyline;
9153	  rts_coords.height =
9154	    ((Regs[0x14d] & 0x3f) + scancfg->coord.height +
9155	     iLineDistance) * dummyline;
9156
9157	  if ((rts_coords.left & 1) == 0)
9158	    rts_coords.left++;
9159
9160	  RTS_Setup_Coords (Regs, rts_coords.left, rts_coords.top,
9161			    rts_coords.width, rts_coords.height);
9162
9163	  data_bitset (&Regs[0x01], 0x06, 0);		   /*-----xx-*/
9164
9165	  /* dummy_scan? */
9166	  data_bitset (&Regs[0x01], 0x10, hwdcfg->dummy_scan);		    /*---x----*/
9167
9168	  data_bitset (&Regs[0x163], 0xc0, 1);	/*xx------ */
9169
9170	  if (dev->scanning->arrange_compression != FALSE)
9171	    {
9172	      Regs[0x60b] &= 0x8f;
9173	      data_bitset (&Regs[0x60b], 0x10, 1);			 /*-001----*/
9174	    }
9175	  else
9176	    data_bitset (&Regs[0x60b], 0x7f, 0);		   /*-0000000*/
9177
9178	  if (mycolormode == 3)
9179	    {
9180	      SANE_Int channels_per_line;
9181
9182	      /* Set channels_per_line = channels_per_dot * scan_width */
9183	      channels_per_line =
9184		data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width;
9185	      data_wide_bitset (&Regs[0x060c], 0x3ffff, channels_per_line);
9186
9187	      /* Sets 16 bits per channel */
9188	      data_bitset (&Regs[0x1cf], 0x30, 2);		    /*--10----*/
9189
9190	      Regs[0x60b] |= 0x40;
9191	      if (v1619 == 0x21)
9192		{
9193		  dev->scanning->arrange_compression = FALSE;
9194		  data_bitset (&Regs[0x60b], 0x10, 0);			    /*---0----*/
9195		}
9196
9197	      switch (scancfg->depth)
9198		{
9199		case 8:
9200		case 16:
9201		  Regs[0x060b] &= 0xf3;
9202		  break;
9203		case 12:
9204		  Regs[0x060b] = (Regs[0x060b] & 0xfb) | 0x08;
9205		  break;
9206		}
9207
9208	      if (scancfg->colormode == CM_LINEART)
9209		data_bitset (&Regs[0x60b], 0x0c, 0);
9210
9211	      /* disable gamma correction ¿? */
9212	      data_bitset (&Regs[0x1d0], 0x40, 0);
9213	    }
9214
9215	  /* 5683 */
9216	  /* Set calibration table */
9217	  RTS_Setup_GainOffset (Regs, gain_offset);
9218
9219	  rst = OK;
9220	}
9221    }
9222
9223  DBG (DBG_FNC, "- RTS_Setup: %i\n", rst);
9224
9225  return rst;
9226}
9227
9228static void
9229RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop,
9230		  SANE_Int width, SANE_Int height)
9231{
9232  DBG (DBG_FNC,
9233       "> RTS_Setup_Coords(*Regs, iLeft=%i, iTop=%i, width=%i, height=%i)\n",
9234       iLeft, iTop, width, height);
9235
9236  if (Regs != NULL)
9237    {
9238      /* Set Left coord */
9239      data_lsb_set (&Regs[0xb0], iLeft, 2);
9240
9241      /* Set Right coord */
9242      data_lsb_set (&Regs[0xb2], iLeft + width, 2);
9243
9244      /* Set Top coord */
9245      data_lsb_set (&Regs[0xd0], iTop, 2);
9246      data_bitset (&Regs[0xd4], 0x0f, _B2 (iTop));
9247
9248      /* Set Down coord */
9249      data_lsb_set (&Regs[0xd2], iTop + height, 2);
9250      data_bitset (&Regs[0xd4], 0xf0, _B2 (iTop + height));
9251    }
9252}
9253
9254static void
9255RTS_Setup_GainOffset (SANE_Byte * Regs, struct st_gain_offset *gain_offset)
9256{
9257  SANE_Byte fake[] =
9258    { 0x19, 0x15, 0x19, 0x64, 0x64, 0x64, 0x74, 0xc0, 0x74, 0xc0, 0x6d,
9259    0xc0, 0x6d, 0xc0, 0x5f, 0xc0, 0x5f, 0xc0
9260  };
9261
9262  DBG (DBG_FNC, "> RTS_Setup_GainOffset(*Regs, *gain_offset)\n");
9263  dbg_calibtable (gain_offset);
9264
9265  if ((Regs != NULL) && (gain_offset != NULL))
9266    {
9267      if (RTS_Debug->calibrate == FALSE)
9268	{
9269	  data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]);		    /*------xx*/
9270	  data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]);		    /*----xx--*/
9271	  data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]);		    /*--xx----*/
9272
9273	  memcpy (&Regs[0x14], &fake, 18);
9274	}
9275      else
9276	{
9277	  SANE_Int a;
9278
9279	  for (a = CL_RED; a <= CL_BLUE; a++)
9280	    {
9281	      /* Offsets */
9282	      Regs[0x1a + (a * 4)] = _B0 (gain_offset->edcg1[a]);
9283	      Regs[0x1b + (a * 4)] =
9284		((gain_offset->edcg1[a] >> 1) & 0x80) | (gain_offset->
9285							 edcg2[a] & 0x7f);
9286	      Regs[0x1c + (a * 4)] = _B0 (gain_offset->odcg1[a]);
9287	      Regs[0x1d + (a * 4)] =
9288		((gain_offset->odcg1[a] >> 1) & 0x80) | (gain_offset->
9289							 odcg2[a] & 0x7f);
9290
9291	      /* Variable Gain Amplifier */
9292	      data_bitset (&Regs[0x14 + a], 0x1f, gain_offset->vgag1[a]);
9293	      data_bitset (&Regs[0x17 + a], 0x1f, gain_offset->vgag2[a]);
9294	    }
9295
9296	  data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]);		    /*------xx*/
9297	  data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]);		    /*----xx--*/
9298	  data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]);		    /*--xx----*/
9299	}
9300    }
9301}
9302
9303static void
9304Calibrate_Free (struct st_cal2 *calbuffers)
9305{
9306  DBG (DBG_FNC, "> Calibrate_Free(*calbuffers)\n");
9307
9308  if (calbuffers != NULL)
9309    {
9310      SANE_Int c;
9311
9312      if (calbuffers->table2 != NULL)
9313	{
9314	  free (calbuffers->table2);
9315	  calbuffers->table2 = NULL;
9316	}
9317
9318      for (c = 0; c < 4; c++)
9319	{
9320	  if (calbuffers->tables[c] != NULL)
9321	    {
9322	      free (calbuffers->tables[c]);
9323	      calbuffers->tables[c] = NULL;
9324	    }
9325	}
9326
9327      calbuffers->shadinglength1 = 0;
9328      calbuffers->tables_size = 0;
9329      calbuffers->shadinglength3 = 0;
9330    }
9331}
9332
9333static SANE_Int
9334Calibrate_Malloc (struct st_cal2 *calbuffers, SANE_Byte * Regs,
9335		  struct st_calibration *myCalib, SANE_Int somelength)
9336{
9337  SANE_Int myshadinglength, pos;
9338  SANE_Int rst;
9339
9340  if ((calbuffers != NULL) && (Regs != NULL) && (myCalib != NULL))
9341    {
9342      if ((Regs[0x1bf] & 0x18) == 0)
9343	{
9344	  if ((((Regs[0x1cf] >> 1) & Regs[0x1cf]) & 0x04) != 0)
9345	    calbuffers->table_count = 2;
9346	  else
9347	    calbuffers->table_count = 4;
9348	}
9349      else
9350	calbuffers->table_count = 4;
9351
9352      /*365d */
9353      myshadinglength = myCalib->shadinglength * 2;
9354      calbuffers->shadinglength1 = min (myshadinglength, somelength);
9355
9356      if ((myshadinglength % somelength) != 0)
9357	calbuffers->tables_size =
9358	  (myshadinglength >= somelength) ? somelength * 2 : somelength;
9359      else
9360	calbuffers->tables_size = somelength;
9361
9362      if (myshadinglength >= somelength)
9363	{
9364	  calbuffers->shadinglength1 =
9365	    (myshadinglength % calbuffers->shadinglength1) +
9366	    calbuffers->shadinglength1;
9367	  calbuffers->shadinglength3 =
9368	    ((myCalib->shadinglength * 2) / somelength) - 1;
9369	}
9370      else
9371	calbuffers->shadinglength3 = 0;
9372
9373      calbuffers->shadinglength3 =
9374	(somelength / 16) * calbuffers->shadinglength3;
9375
9376      rst = OK;
9377      for (pos = 0; pos < calbuffers->table_count; pos++)
9378	{
9379	  calbuffers->tables[pos] =
9380	    (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT));
9381	  if (calbuffers->tables[pos] == NULL)
9382	    {
9383	      rst = ERROR;
9384	      break;
9385	    }
9386	}
9387
9388      if (rst == OK)
9389	{
9390	  calbuffers->table2 =
9391	    (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT));
9392	  if (calbuffers->table2 == NULL)
9393	    rst = ERROR;
9394	}
9395
9396      if (rst != OK)
9397	Calibrate_Free (calbuffers);
9398    }
9399  else
9400    rst = ERROR;
9401
9402  DBG (DBG_FNC,
9403       "> Calibrate_Malloc(*calbuffers, *Regs, *myCalib, somelength=%i): %i\n",
9404       somelength, rst);
9405
9406  return rst;
9407}
9408
9409static SANE_Int
9410fn3560 (USHORT * table, struct st_cal2 *calbuffers, SANE_Int * tablepos)
9411{
9412  /*05FEF974   001F99B0  |table = 001F99B0
9413     05FEF978   05FEFA08  |calbuffers->tables[0] = 05FEFA08
9414     05FEF97C   000000A0  |calbuffers->shadinglength3 = 000000A0
9415     05FEF980   00000348  |calbuffers->shadinglength1 = 00000348
9416     05FEF984   04F01502  |calbuffers->table_count = 04F01502
9417     05FEF988   05FEF998  \Arg6 = 05FEF998
9418   */
9419
9420  if (table != NULL)
9421    {
9422      SANE_Int pos[4] = { 0, 0, 0, 0 };	/*f960 f964 f968 f96c */
9423      SANE_Int usetable = 0;
9424      SANE_Int a;
9425
9426      SANE_Int mylength3 = calbuffers->shadinglength1;	/*f97c */
9427      SANE_Byte *pPointer =
9428	(SANE_Byte *) (table + (calbuffers->shadinglength3 * 16));
9429
9430      DBG (DBG_FNC, "> fn3560(*table, *calbuffers, *tablepos)\n");
9431
9432      if (mylength3 > 0)
9433	{
9434	  do
9435	    {
9436	      if (calbuffers->tables[usetable] != NULL)
9437		{
9438		  if (mylength3 <= 16)
9439		    {
9440		      if (mylength3 > 0)
9441			{
9442			  do
9443			    {
9444			      *(calbuffers->tables[usetable] +
9445				pos[usetable]) = _B0 (*pPointer);
9446			      pPointer++;
9447			      pos[usetable]++;
9448			      mylength3--;
9449			    }
9450			  while (mylength3 > 0);
9451			}
9452		      break;
9453		    }
9454
9455		  for (a = 0; a < 16; a++)
9456		    {
9457		      *(calbuffers->tables[usetable] + pos[usetable]) =
9458			_B0 (*pPointer);
9459		      pPointer++;
9460		      pos[usetable]++;
9461		    }
9462		}
9463
9464	      mylength3 -= 16;
9465	      usetable++;
9466	      if (usetable == calbuffers->table_count)
9467		usetable = 0;
9468	    }
9469	  while (mylength3 > 0);
9470	}
9471
9472      /*35f8 */
9473      if (calbuffers->table_count > 0)
9474	{
9475	  /* Return position of each table */
9476	  memcpy (tablepos, pos, sizeof (SANE_Int) * 4);
9477	}
9478    }
9479
9480  return OK;
9481}
9482
9483static SANE_Int
9484Calib_WriteTable (struct st_device *dev, SANE_Byte * table, SANE_Int size,
9485		  SANE_Int data)
9486{
9487  SANE_Int rst = ERROR;
9488
9489  DBG (DBG_FNC, "+ Calib_WriteTable(*table, size=%i):\n", size);
9490
9491  if ((table != NULL) && (size > 0))
9492    {
9493      SANE_Int transferred;
9494
9495      if (RTS_DMA_Reset (dev) == OK)
9496	{
9497	  /* Send size to write */
9498	  if (RTS_DMA_Enable_Write (dev, 0x0004, size, data) == OK)
9499	    /* Send data */
9500	    rst = Bulk_Operation (dev, BLK_WRITE, size, table, &transferred);
9501	}
9502    }
9503
9504  DBG (DBG_FNC, "- Calib_WriteTable: %i\n", rst);
9505
9506  return rst;
9507}
9508
9509static SANE_Int
9510Calib_ReadTable (struct st_device *dev, SANE_Byte * table, SANE_Int size,
9511		 SANE_Int data)
9512{
9513  SANE_Int rst = ERROR;
9514
9515  DBG (DBG_FNC, "+ Calib_ReadTable(*table, size=%i):\n", size);
9516
9517  if ((table != NULL) && (size > 0))
9518    {
9519      SANE_Int transferred;
9520
9521      if (RTS_DMA_Reset (dev) == OK)
9522	{
9523	  /* Send size to read */
9524	  if (RTS_DMA_Enable_Read (dev, 0x0004, size, data) == OK)
9525	    /* Retrieve data */
9526	    rst = Bulk_Operation (dev, BLK_READ, size, table, &transferred);
9527	}
9528    }
9529
9530  DBG (DBG_FNC, "- Calib_ReadTable: %i\n", rst);
9531
9532  return rst;
9533}
9534
9535static SANE_Int
9536fn3330 (struct st_device *dev, SANE_Byte * Regs, struct st_cal2 *calbuffers,
9537	SANE_Int sensorchannelcolor, SANE_Int * tablepos, SANE_Int data)
9538{
9539  /*05EEF968   04F0F7F8  |Regs = 04F0F7F8
9540     05EEF96C   02DEC838  |calbuffers->table2 = 02DEC838
9541     05EEF970   05EEFA08  |calbuffers->tables[] = 05EEFA08
9542     05EEF974   00000000  |sensorchannelcolor = 00000000
9543     05EEF978   000000A0  |calbuffers->shadinglength3 = 000000A0
9544     05EEF97C   00000400  |calbuffers->tables_size = 00000400
9545     05EEF980   05EEF998  |&pos = 05EEF998
9546     05EEF984   00221502  |calbuffers->table_count = 00221502
9547     05EEF988   00000000  \data = 00000000
9548   */
9549
9550  SANE_Int table_count = calbuffers->table_count;	/*f960 */
9551  SANE_Int schcolor = _B0 (sensorchannelcolor);
9552  SANE_Int a = 0;
9553  SANE_Int tablelength = calbuffers->shadinglength3 / table_count;	/*f954 */
9554  SANE_Int val_color = 0;	/*f974 */
9555  SANE_Int val_lineart = 0;	/*f978 */
9556  SANE_Int val_gray = 0;	/*ebx */
9557  SANE_Int value4 = 0;		/*ebp */
9558  SANE_Int size;
9559  SANE_Int rst = OK;
9560
9561  DBG (DBG_FNC,
9562       "+ fn3330(*Regs, *calbuffers, sensorchannelcolor=%i, *tablepos, data=%i):\n",
9563       sensorchannelcolor, data);
9564
9565  if (calbuffers->table_count > 0)
9566    {
9567      do
9568	{
9569	  if (calbuffers->table_count == 2)
9570	    {
9571	      /*338c */
9572	      if (a != 0)
9573		{
9574		  /*3394 */
9575		  if (_B0 (data) == 0)
9576		    {
9577		      val_color = 0x100000;
9578		      val_lineart = 0x100000;
9579		      val_gray = 0x200000;
9580		    }
9581		  else
9582		    {
9583		      /*343a */
9584		      val_color = 0x300000;
9585		      val_lineart = 0x300000;
9586		      val_gray = 0;
9587		    }
9588		}
9589	      else
9590		{
9591		  /*33be */
9592		  if (_B0 (data) == 0)
9593		    {
9594		      val_color = 0;
9595		      val_lineart = 0;
9596		      val_gray = 0x300000;
9597		    }
9598		  else
9599		    {
9600		      /*342a */
9601		      val_color = 0x200000;
9602		      val_lineart = 0x200000;
9603		      val_gray = 0x100000;
9604		    }
9605		}
9606	    }
9607	  else
9608	    {
9609	      /*33d5 */
9610	      switch (a)
9611		{
9612		case 0:
9613		  val_color = 0;
9614		  val_lineart = 0;
9615		  val_gray = 0x300000;
9616		  break;
9617		case 1:
9618		  val_color = 0x200000;
9619		  val_lineart = 0x200000;
9620		  val_gray = 0x100000;
9621		  break;
9622		case 2:
9623		  val_color = 0x100000;
9624		  val_lineart = 0x100000;
9625		  val_gray = 0x200000;
9626		  break;
9627		case 3:
9628		  val_color = 0x300000;
9629		  val_lineart = 0x300000;
9630		  val_gray = 0;
9631		  break;
9632		}
9633	    }
9634
9635	  /*3449 */
9636	  switch (schcolor)
9637	    {
9638	    case CM_LINEART:
9639	      size =
9640		(((Regs[0x1bf] >> 1) & 3) << 0x10) | (Regs[0x1be] << 0x08) |
9641		Regs[0x1bd];
9642	      value4 = (tablelength + size) | val_lineart;
9643	      break;
9644	    case CM_GRAY:
9645	      size =
9646		((Regs[0x1bf] & 1) << 0x10) | (Regs[0x1bc] << 0x08) |
9647		Regs[0x1bb];
9648	      value4 = (tablelength + size) | val_gray;
9649	      break;
9650	    default:
9651	      size = _B0 (Regs[0x1ba]);
9652	      value4 = (tablelength + size) | val_color;
9653	      break;
9654	    }
9655
9656	  if (Calib_ReadTable
9657	      (dev, (SANE_Byte *) calbuffers->table2, calbuffers->tables_size,
9658	       value4) != OK)
9659	    {
9660	      rst = ERROR;
9661	      break;
9662	    }
9663
9664	  memcpy (calbuffers->tables[a], calbuffers->table2, tablepos[a]);
9665
9666	  if (tablepos[a + 1] == 0)
9667	    break;
9668
9669	  a++;
9670	}
9671      while (a < calbuffers->table_count);
9672    }
9673
9674  DBG (DBG_FNC, "- fn3330: %i\n", rst);
9675
9676  return rst;
9677}
9678
9679static SANE_Int
9680fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, SANE_Byte * Regs,
9681	USHORT * table, SANE_Int sensorchannelcolor, SANE_Int data)
9682{
9683  /*05FEF9AC   |calbuffers         = 05FEF9F8
9684     05FEF9B0   |Regs               = 04EFF7F8
9685     05FEF9B4   |table              = 001F99B0
9686     05FEF9B8   |sensorchannelcolor = 00000000
9687     05FEF9BC   |data               = 00000000
9688   */
9689
9690  SANE_Int pos[4] = { 0, 0, 0, 0 };	/*f998 f99c f9a0 f9a4 */
9691  SANE_Int rst;
9692
9693  DBG (DBG_FNC,
9694       "+ fn3730(*calbuffers, *Regs, *table, sensorchannelcolor=%i, data=%i):\n",
9695       sensorchannelcolor, data);
9696
9697  fn3560 (table, calbuffers, pos);
9698  rst = fn3330 (dev, Regs, calbuffers, sensorchannelcolor, pos, data);
9699
9700  DBG (DBG_FNC, "- fn3730: %i\n", rst);
9701
9702  return rst;
9703}
9704
9705static SANE_Int
9706Shading_white_apply (struct st_device *dev, SANE_Byte * Regs,
9707		     SANE_Int channels, struct st_calibration *myCalib,
9708		     struct st_cal2 *calbuffers)
9709{
9710  SANE_Int rst = OK;
9711
9712  DBG (DBG_FNC, "+ Shading_white_apply(channels=%i)\n", channels);
9713
9714  /*3e7f */
9715  Calibrate_Malloc (calbuffers, Regs, myCalib,
9716		    (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40);
9717
9718  if (channels > 0)
9719    {
9720      /*int a; */
9721      SANE_Int chnl;
9722      SANE_Int pos;		/*fa2c */
9723      SANE_Int transferred;
9724
9725      rst = ERROR;
9726
9727      for (chnl = 0; chnl < channels; chnl++)
9728	{
9729	  /*for (a = 0; a < myCalib->shadinglength; a++)
9730	     myCalib->black_shading[chnl][a] = 0x2000; */
9731	  /* 11 tries */
9732	  for (pos = 0; pos <= 10; pos++)
9733	    {
9734	      /* Send size to write */
9735	      if (RTS_DMA_Enable_Write
9736		  (dev, dev->sensorcfg->channel_color[chnl] | 0x14,
9737		   myCalib->shadinglength, 0) == OK)
9738		/* Send data */
9739		Bulk_Operation (dev, BLK_WRITE,
9740				myCalib->shadinglength * sizeof (USHORT),
9741				(SANE_Byte *) & myCalib->
9742				white_shading[chnl][myCalib->first_position -
9743						    1], &transferred);
9744
9745	      /*3df7 */
9746	      if (fn3730
9747		  (dev, calbuffers, Regs,
9748		   &myCalib->white_shading[chnl][myCalib->first_position - 1],
9749		   dev->sensorcfg->channel_color[chnl], 1) == OK)
9750		{
9751		  rst = OK;
9752		  break;
9753		}
9754
9755	      RTS_DMA_Cancel (dev);
9756	    }
9757	}
9758    }
9759
9760  Calibrate_Free (calbuffers);
9761
9762  DBG (DBG_FNC, "- Shading_white_apply: %i\n", rst);
9763
9764  return OK;
9765}
9766
9767static SANE_Int
9768Shading_black_apply (struct st_device *dev, SANE_Byte * Regs,
9769		     SANE_Int channels, struct st_calibration *myCalib,
9770		     struct st_cal2 *calbuffers)
9771{
9772  SANE_Int rst = OK;
9773
9774  DBG (DBG_FNC, "+ Shading_black_apply(channels=%i)\n", channels);
9775
9776  /* 3d79 */
9777  Calibrate_Malloc (calbuffers, Regs, myCalib,
9778		    (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40);
9779
9780  if (channels > 0)
9781    {
9782      /*int a; */
9783      SANE_Int chnl;
9784      SANE_Int pos;		/*fa2c */
9785      SANE_Int transferred;
9786
9787      rst = ERROR;
9788
9789      for (chnl = 0; chnl < channels; chnl++)
9790	{
9791	  /* 11 tries */
9792	  /*for (a = 0; a < myCalib->shadinglength; a++)
9793	     myCalib->black_shading[chnl][a] = 0x2000; */
9794
9795	  for (pos = 0; pos <= 10; pos++)
9796	    {
9797	      /* Send size to write */
9798	      if (RTS_DMA_Enable_Write
9799		  (dev, dev->sensorcfg->channel_color[chnl] | 0x10,
9800		   myCalib->shadinglength, 0) == OK)
9801		/* Send data */
9802		Bulk_Operation (dev, BLK_WRITE,
9803				myCalib->shadinglength * sizeof (USHORT),
9804				(SANE_Byte *) & myCalib->
9805				black_shading[chnl][myCalib->first_position -
9806						    1], &transferred);
9807
9808	      /*3df7 */
9809	      if (fn3730
9810		  (dev, calbuffers, Regs,
9811		   &myCalib->black_shading[chnl][myCalib->first_position - 1],
9812		   dev->sensorcfg->channel_color[chnl], 0) == OK)
9813		{
9814		  rst = OK;
9815		  break;
9816		}
9817
9818	      RTS_DMA_Cancel (dev);
9819	    }
9820	}
9821    }
9822
9823  /*3e62 */
9824  Calibrate_Free (calbuffers);
9825
9826  DBG (DBG_FNC, "- Shading_black_apply: %i\n", rst);
9827
9828  return OK;
9829}
9830
9831static SANE_Int
9832Shading_apply (struct st_device *dev, SANE_Byte * Regs,
9833	       struct st_scanparams *myvar, struct st_calibration *myCalib)
9834{
9835  /*
9836     Regs f1bc
9837     myvar     f020
9838     hwdcfg  e838
9839     arg4      e81c
9840     myCalib   e820
9841   */
9842
9843  SANE_Int rst;			/* lf9e0 */
9844  SANE_Int myfact;		/* e820 */
9845  SANE_Int shadata;
9846  SANE_Byte channels;		/* f9d4 */
9847  SANE_Int myShadingBase;	/* e818 */
9848
9849  char lf9d1;
9850  char lf9d0;
9851
9852  DBG (DBG_FNC, "+ Shading_apply(*Regs, *myvar, *mygamma, *myCalib):\n");
9853  dbg_ScanParams (myvar);
9854
9855  lf9d0 = (Regs[0x60b] >> 6) & 1;
9856  lf9d1 = (Regs[0x60b] >> 4) & 1;
9857  Regs[0x060b] &= 0xaf;
9858  rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]);
9859  if (rst == OK)
9860    {
9861      SANE_Byte colormode = myvar->colormode;	/*fa24 */
9862      SANE_Int le7cc, le7d8;
9863      struct st_cal2 calbuffers;	/* f9f8 */
9864
9865      if (colormode != CM_COLOR)
9866	{
9867	  if (myvar->channel != 3)
9868	    {
9869	      if (colormode != 3)
9870		channels = (myvar->samplerate == PIXEL_RATE) ? 2 : 1;
9871	      else
9872		channels = 3;
9873	    }
9874	  else
9875	    {
9876	      colormode = 3;
9877	      channels = 3;
9878	    }
9879	}
9880      else
9881	channels = 3;
9882
9883      /*
9884         White shading formula :    2000H x Target / (Wn-Dn) = White Gain data ----- for 8 times system
9885         White shading formula :    4000H x Target / (Wn-Dn) = White Gain data ----- for 4 times system
9886         For example : Target = 3FFFH   Wn = 2FFFH     Dn = 0040H  and 8 times system operation
9887         then   White Gain = 2000H x 3FFFH / (2FFFH-0040H) = 2AE4H (1.34033 times)
9888       */
9889      /* 3aad */
9890      if (colormode == 3)
9891	{
9892	  /*
9893	     SANE_Int pos;
9894	     SANE_Int colour;
9895
9896	     myShadingBase = shadingbase;
9897
9898	     for (colour = 0; colour < channels; colour++)
9899	     {
9900	     if (myCalib->white_shading[colour] != NULL)
9901	     {
9902	     myfact = shadingfact[colour];
9903	     if (myCalib->shadinglength > 0)
9904	     {
9905	     for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++)
9906	     myCalib->white_shading[colour][pos] = (myCalib->white_shading[colour][pos] * myfact) / myShadingBase;
9907	     }
9908	     } else break;
9909	     }
9910	   */
9911	}
9912
9913      /* 3b3b */
9914      if (myCalib->shading_enabled != FALSE)
9915	{
9916	  /* 3b46 */
9917	  SANE_Int colour, pos;
9918	  le7cc = shadingbase;
9919	  le7d8 = shadingbase;
9920
9921	  DBG (DBG_FNC, "-> Shading type: %i\n", myCalib->shading_type);
9922
9923	  for (colour = 0; colour < channels; colour++)
9924	    {
9925	      if (colormode == 3)
9926		le7cc = shadingfact[colour];
9927
9928	      myShadingBase = ((Regs[0x1cf] & 2) != 0) ? 0x2000 : 0x4000;
9929
9930	      myfact = myCalib->WRef[colour] * myShadingBase;
9931
9932	      if (myCalib->shading_type == 2)
9933		{
9934		  /*3bd8 */
9935		  if ((myCalib->black_shading[colour] != NULL)
9936		      && (myCalib->white_shading[colour] != NULL))
9937		    {
9938		      for (pos = myCalib->first_position - 1;
9939			   pos < myCalib->shadinglength; pos++)
9940			{
9941			  if (myCalib->white_shading[colour][pos] == 0)
9942			    shadata = myShadingBase;
9943			  else
9944			    shadata =
9945			      myfact / myCalib->white_shading[colour][pos];
9946
9947			  shadata = min ((shadata * le7cc) / le7d8, 0xff00);
9948			  myCalib->black_shading[colour][pos] &= 0xff;
9949			  myCalib->black_shading[colour][pos] |=
9950			    shadata & 0xff00;
9951			}
9952		    }
9953		  else
9954		    break;
9955		}
9956	      else
9957		{
9958		  /*3c63 */
9959		  if (myCalib->shading_type == 3)
9960		    {
9961		      /*3c68 */
9962		      if (myCalib->black_shading[colour] != NULL)
9963			{
9964			  for (pos = myCalib->first_position - 1;
9965			       pos < myCalib->shadinglength; pos++)
9966			    {
9967			      if (myCalib->black_shading[colour][pos] == 0)
9968				shadata = myShadingBase;
9969			      else
9970				shadata =
9971				  myfact /
9972				  myCalib->black_shading[colour][pos];
9973
9974			      shadata =
9975				min ((shadata * le7cc) / le7d8, 0xffc0);
9976			      myCalib->black_shading[colour][pos] &= 0x3f;
9977			      myCalib->black_shading[colour][pos] |=
9978				shadata & 0xffc0;
9979			    }
9980			}
9981		      else
9982			break;
9983		    }
9984		  else
9985		    {
9986		      /*3ce3 */
9987		      if (myCalib->white_shading[colour] != NULL)
9988			{
9989			  for (pos = 0; pos < myCalib->shadinglength; pos++)
9990			    {
9991			      if (myCalib->white_shading[colour][pos] == 0)
9992				shadata = myShadingBase;
9993			      else
9994				shadata =
9995				  myfact /
9996				  myCalib->white_shading[colour][pos];
9997
9998			      shadata =
9999				min ((shadata * le7cc) / le7d8, 0xffff);
10000			      myCalib->white_shading[colour][pos] = shadata;
10001			    }
10002			}
10003		      else
10004			break;
10005		    }
10006		}
10007	    }
10008	}
10009
10010      /*3d4c */
10011      memset (&calbuffers, 0, sizeof (struct st_cal2));
10012
10013      /* If black shading correction is enabled ... */
10014      if ((Regs[0x1cf] & 8) != 0)
10015	Shading_black_apply (dev, Regs, channels, myCalib, &calbuffers);
10016
10017      /*3e6e */
10018
10019      /* If white shading correction is enabled ... */
10020      if ((Regs[0x1cf] & 4) != 0)
10021	Shading_white_apply (dev, Regs, channels, myCalib, &calbuffers);
10022
10023      /* 3f74 */
10024      if (rst == 0)
10025	{
10026	  data_bitset (&Regs[0x60b], 0x40, lf9d0);		/*-x------*/
10027	  data_bitset (&Regs[0x60b], 0x10, lf9d1);		/*---x----*/
10028
10029	  rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]);
10030	}
10031    }
10032  /*3fb5 */
10033
10034  DBG (DBG_FNC, "- Shading_apply: %i\n", rst);
10035
10036  return rst;
10037}
10038
10039static SANE_Int
10040Bulk_Operation (struct st_device *dev, SANE_Byte op, SANE_Int buffer_size,
10041		SANE_Byte * buffer, SANE_Int * transferred)
10042{
10043  SANE_Int iTransferSize, iBytesToTransfer, iPos, rst, iBytesTransfered;
10044
10045  DBG (DBG_FNC, "+ Bulk_Operation(op=%s, buffer_size=%i, buffer):\n",
10046       ((op & 0x01) != 0) ? "READ" : "WRITE", buffer_size);
10047
10048  iBytesToTransfer = buffer_size;
10049  iPos = 0;
10050  rst = OK;
10051  iBytesTransfered = 0;
10052
10053  if (transferred != NULL)
10054    *transferred = 0;
10055
10056  iTransferSize = min (buffer_size, RTS_Debug->dmatransfersize);
10057
10058  if (op != 0)
10059    {
10060      /* Lectura */
10061      do
10062	{
10063	  iTransferSize = min (iTransferSize, iBytesToTransfer);
10064
10065	  iBytesTransfered =
10066	    Read_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize);
10067	  if (iBytesTransfered < 0)
10068	    {
10069	      rst = ERROR;
10070	      break;
10071	    }
10072	  else
10073	    {
10074	      if (transferred != NULL)
10075		*transferred += iBytesTransfered;
10076	    }
10077	  iPos += iTransferSize;
10078	  iBytesToTransfer -= iTransferSize;
10079	}
10080      while (iBytesToTransfer > 0);
10081    }
10082  else
10083    {
10084      /* Escritura */
10085      do
10086	{
10087	  iTransferSize = min (iTransferSize, iBytesToTransfer);
10088
10089	  if (Write_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize) !=
10090	      OK)
10091	    {
10092	      rst = ERROR;
10093	      break;
10094	    }
10095	  else
10096	    {
10097	      if (transferred != NULL)
10098		*transferred += iTransferSize;
10099	    }
10100	  iPos += iTransferSize;
10101	  iBytesToTransfer -= iTransferSize;
10102	}
10103      while (iBytesToTransfer > 0);
10104    }
10105
10106  DBG (DBG_FNC, "- Bulk_Operation: %i\n", rst);
10107
10108  return rst;
10109}
10110
10111static SANE_Int
10112Reading_BufferSize_Notify (struct st_device *dev, SANE_Int data,
10113			   SANE_Int size)
10114{
10115  SANE_Int rst;
10116
10117  DBG (DBG_FNC, "+ Reading_BufferSize_Notify(data=%i, size=%i):\n", data,
10118       size);
10119
10120  rst = RTS_DMA_Enable_Read (dev, 0x0008, size, data);
10121
10122  DBG (DBG_FNC, "- Reading_BufferSize_Notify: %i\n", rst);
10123
10124  return rst;
10125}
10126
10127static SANE_Int
10128Reading_Wait (struct st_device *dev, SANE_Byte Channels_per_dot,
10129	      SANE_Byte Channel_size, SANE_Int size, SANE_Int * last_amount,
10130	      SANE_Int seconds, SANE_Byte op)
10131{
10132  SANE_Int rst;
10133  SANE_Byte cTimeout, executing;
10134  SANE_Int lastAmount, myAmount;
10135  long tick;
10136
10137  DBG (DBG_FNC,
10138       "+ Reading_Wait(Channels_per_dot=%i, Channel_size=%i, size=%i, *last_amount, seconds=%i, op=%i):\n",
10139       Channels_per_dot, Channel_size, size, seconds, op);
10140
10141  rst = OK;
10142  cTimeout = FALSE;
10143  lastAmount = 0;
10144
10145  myAmount = Reading_BufferSize_Get (dev, Channels_per_dot, Channel_size);
10146  if (myAmount < size)
10147    {
10148      /* Wait until scanner fills its buffer */
10149      if (seconds == 0)
10150	seconds = 10;
10151      tick = GetTickCount () + (seconds * 1000);
10152
10153      while (cTimeout == FALSE)
10154	{
10155	  myAmount =
10156	    Reading_BufferSize_Get (dev, Channels_per_dot, Channel_size);
10157
10158	  /* check special case */
10159	  if (op == TRUE)
10160	    {
10161	      if (((myAmount + 0x450) > size)
10162		  || (RTS_IsExecuting (dev, &executing) == FALSE))
10163		break;
10164	    }
10165
10166	  if (myAmount < size)
10167	    {
10168	      /* Check timeout */
10169	      if (myAmount == lastAmount)
10170		{
10171		  /* we are in timeout? */
10172		  if (tick < GetTickCount ())
10173		    {
10174		      /* TIMEOUT */
10175		      rst = ERROR;
10176		      cTimeout = TRUE;
10177		    }
10178		  else
10179		    usleep (100 * 1000);
10180		}
10181	      else
10182		{
10183		  /* Amount increased, update tick */
10184		  lastAmount = myAmount;
10185		  tick = GetTickCount () + (seconds * 1000);
10186		}
10187	    }
10188	  else
10189	    {
10190	      lastAmount = myAmount;
10191	      break;		/* buffer full */
10192	    }
10193	}
10194    }
10195
10196  if (last_amount != NULL)
10197    *last_amount = myAmount;
10198
10199  DBG (DBG_FNC, "- Reading_Wait: %i , last_amount=%i\n", rst, myAmount);
10200
10201  return rst;
10202}
10203
10204static SANE_Int
10205RTS_GetImage_GetBuffer (struct st_device *dev, double dSize,
10206			char unsigned *buffer, double *transferred)
10207{
10208  SANE_Int rst = ERROR;
10209  SANE_Int itransferred;
10210  double dtransferred = 0;
10211
10212  DBG (DBG_FNC, "+ RTS_GetImage_GetBuffer(dSize=%f, buffer, transferred):\n",
10213       dSize);
10214
10215  rst = OK;
10216  dSize /= 2;
10217
10218  if (dSize > 0)
10219    {
10220      SANE_Int myLength;
10221      SANE_Int iPos = 0;
10222
10223      do
10224	{
10225	  itransferred = 0;
10226	  myLength =
10227	    (dSize <=
10228	     RTS_Debug->dmasetlength) ? dSize : RTS_Debug->dmasetlength;
10229
10230	  if (myLength > 0x1ffe0)
10231	    myLength = 0x1ffe0;
10232
10233	  rst = ERROR;
10234	  if (Reading_Wait (dev, 0, 1, myLength * 2, NULL, 5, FALSE) == OK)
10235	    {
10236	      if (Reading_BufferSize_Notify (dev, 0, myLength * 2) == OK)
10237		rst =
10238		  Bulk_Operation (dev, BLK_READ, myLength * 2, &buffer[iPos],
10239				  &itransferred);
10240	    }
10241
10242	  if (rst != OK)
10243	    break;
10244
10245	  iPos += itransferred;
10246	  dSize -= itransferred;
10247	  dtransferred += itransferred * 2;
10248	}
10249      while (dSize > 0);
10250    }
10251
10252  /* Return bytes transferred */
10253  if (transferred != NULL)
10254    *transferred = dtransferred;
10255
10256  if (rst != OK)
10257    RTS_DMA_Cancel (dev);
10258
10259  DBG (DBG_FNC, "- RTS_GetImage_GetBuffer: %i\n", rst);
10260
10261  return rst;
10262}
10263
10264static SANE_Int
10265RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer,
10266		   struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg)
10267{
10268  /*buffer   f80c = esp+14
10269     scancfg    f850 = esp+18
10270     hwdcfg faac = */
10271
10272  SANE_Int rst = ERROR;
10273
10274  DBG (DBG_FNC, "+ RTS_GetImage_Read(buffer, scancfg, hwdcfg):\n");
10275
10276  if (buffer != NULL)
10277    {
10278      double dSize = scancfg->bytesperline * scancfg->coord.height;
10279      SANE_Byte exfn;
10280
10281      if (scancfg->depth == 12)
10282	dSize = (dSize * 3) / 4;
10283
10284      /*3ff6 */
10285      exfn = 1;
10286      if (hwdcfg != NULL)
10287	if (hwdcfg->compression != FALSE)
10288	  exfn = 0;
10289
10290      if (exfn != 0)
10291	{
10292	  double transferred;
10293	  rst = RTS_GetImage_GetBuffer (dev, dSize, buffer, &transferred);
10294	}
10295
10296      if (rst == OK)
10297	RTS_WaitScanEnd (dev, 1500);
10298    }
10299
10300  DBG (DBG_FNC, "- RTS_GetImage_Read: %i\n", rst);
10301
10302  return rst;
10303}
10304
10305static SANE_Int
10306RTS_GetImage (struct st_device *dev, SANE_Byte * Regs,
10307	      struct st_scanparams *scancfg,
10308	      struct st_gain_offset *gain_offset, SANE_Byte * buffer,
10309	      struct st_calibration *myCalib, SANE_Int options,
10310	      SANE_Int gaincontrol)
10311{
10312  /* 42b8e10 */
10313
10314  SANE_Int rst = ERROR;		/* default */
10315
10316  DBG (DBG_FNC,
10317       "+ RTS_GetImage(*Regs, *scancfg, *gain_offset, *buffer, myCalib, options=0x%08x, gaincontrol=%i):\n",
10318       options, gaincontrol);
10319  dbg_ScanParams (scancfg);
10320
10321  /* validate arguments */
10322  if ((Regs != NULL) && (scancfg != NULL))
10323    {
10324      if ((scancfg->coord.width != 0) && (scancfg->coord.height != 0))
10325	{
10326	  struct st_scanparams *myscancfg;
10327
10328	  /* let's make a copy of scan config */
10329	  myscancfg =
10330	    (struct st_scanparams *) malloc (sizeof (struct st_scanparams));
10331	  if (myscancfg != NULL)
10332	    {
10333	      struct st_hwdconfig *hwdcfg;
10334
10335	      memcpy (myscancfg, scancfg, sizeof (struct st_scanparams));
10336
10337	      /* Allocate space for low level config */
10338	      hwdcfg =
10339		(struct st_hwdconfig *) malloc (sizeof (struct st_hwdconfig));
10340	      if (hwdcfg != NULL)
10341		{
10342		  memset (hwdcfg, 0, sizeof (struct st_hwdconfig));
10343
10344		  if (((options & 2) != 0) || ((_B1 (options) & 1) != 0))
10345		    {
10346		      /* switch off lamp */
10347		      data_bitset (&Regs[0x146], 0x40, 0);
10348
10349		      Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]);
10350		      usleep (1000 * ((v14b4 == 0) ? 500 : 300));
10351		    }
10352
10353		  hwdcfg->scantype = scan.scantype;
10354		  hwdcfg->use_gamma_tables =
10355		    ((options & OP_USE_GAMMA) != 0) ? 1 : 0;
10356		  hwdcfg->white_shading =
10357		    ((options & OP_WHITE_SHAD) != 0) ? 1 : 0;
10358		  hwdcfg->black_shading =
10359		    ((options & OP_BLACK_SHAD) != 0) ? 1 : 0;
10360		  hwdcfg->motor_direction =
10361		    ((options & OP_BACKWARD) !=
10362		     0) ? MTR_BACKWARD : MTR_FORWARD;
10363		  hwdcfg->compression =
10364		    ((options & OP_COMPRESSION) != 0) ? 1 : 0;
10365		  hwdcfg->static_head =
10366		    ((options & OP_STATIC_HEAD) != 0) ? 1 : 0;
10367		  hwdcfg->dummy_scan = (buffer == NULL) ? TRUE : FALSE;
10368		  hwdcfg->arrangeline = 0;
10369		  hwdcfg->highresolution =
10370		    (myscancfg->resolution_x > 1200) ? TRUE : FALSE;
10371		  hwdcfg->unk3 = 0;
10372
10373		  /* Set Left coord */
10374		  myscancfg->coord.left +=
10375		    ((dev->sensorcfg->type == CCD_SENSOR) ? 24 : 50);
10376
10377		  switch (myscancfg->resolution_x)
10378		    {
10379		    case 1200:
10380		      myscancfg->coord.left -= 63;
10381		      break;
10382		    case 2400:
10383		      myscancfg->coord.left -= 126;
10384		      break;
10385		    }
10386
10387		  if (myscancfg->coord.left < 0)
10388		    myscancfg->coord.left = 0;
10389
10390		  RTS_Setup (dev, Regs, myscancfg, hwdcfg, gain_offset);
10391
10392		  /* Setting exposure time */
10393		  switch (scan.scantype)
10394		    {
10395		    case ST_NORMAL:
10396		      if (scan.resolution_x == 100)
10397			{
10398			  SANE_Int iValue;
10399			  SANE_Byte *myRegs;
10400
10401			  myRegs =
10402			    (SANE_Byte *) malloc (RT_BUFFER_LEN *
10403						  sizeof (SANE_Byte));
10404			  if (myRegs != NULL)
10405			    {
10406			      memset (myRegs, 0,
10407				     RT_BUFFER_LEN * sizeof (SANE_Byte));
10408			      RTS_Setup (dev, myRegs, &scan, hwdcfg,
10409					 gain_offset);
10410
10411			      iValue = data_lsb_get (&myRegs[0x30], 3);
10412			      data_lsb_set (&Regs[0x30], iValue, 3);
10413
10414			      /*Copy myregisters mexpts to Regs mexpts */
10415			      iValue = data_lsb_get (&myRegs[0x33], 3);
10416			      data_lsb_set (&Regs[0x33], iValue, 3);
10417
10418			      iValue = data_lsb_get (&myRegs[0x39], 3);
10419			      data_lsb_set (&Regs[0x39], iValue, 3);
10420
10421			      iValue = data_lsb_get (&myRegs[0x3f], 3);
10422			      data_lsb_set (&Regs[0x3f], iValue, 3);
10423
10424			      free (myRegs);
10425			    }
10426			}
10427		      break;
10428		    case ST_NEG:
10429		      {
10430			SANE_Int myvalue;
10431
10432			/* Setting exposure times for Negative scans */
10433			data_lsb_set (&Regs[0x30], myscancfg->expt, 3);
10434			data_lsb_set (&Regs[0x33], myscancfg->expt, 3);
10435			data_lsb_set (&Regs[0x39], myscancfg->expt, 3);
10436			data_lsb_set (&Regs[0x3f], myscancfg->expt, 3);
10437
10438			data_lsb_set (&Regs[0x36], 0, 3);
10439			data_lsb_set (&Regs[0x3c], 0, 3);
10440			data_lsb_set (&Regs[0x42], 0, 3);
10441
10442			myvalue =
10443			  ((myscancfg->expt +
10444			    1) / (data_lsb_get (&Regs[0xe0], 1) + 1)) - 1;
10445			data_lsb_set (&Regs[0xe1], myvalue, 3);
10446		      }
10447		      break;
10448		    }
10449
10450		  /* 91a0 */
10451		  if (myscancfg->resolution_y > 600)
10452		    {
10453		      options |= 0x20000000;
10454		      if (options != 0)	/* Always true ... */
10455			SetMultiExposure (dev, Regs);
10456		      else
10457			myscancfg->coord.top += hwdcfg->startpos;
10458		    }
10459		  else
10460		    SetMultiExposure (dev, Regs);
10461
10462		  /* 91e2 */
10463		  RTS_WriteRegs (dev->usb_handle, Regs);
10464		  if (myCalib != NULL)
10465		    Shading_apply (dev, Regs, myscancfg, myCalib);
10466
10467		  if (dev->motorcfg->changemotorcurrent != FALSE)
10468		    Motor_Change (dev, Regs,
10469				  Motor_GetFromResolution (myscancfg->
10470							   resolution_x));
10471
10472		  /* mlock = 0 */
10473		  data_bitset (&Regs[0x00], 0x10, 0);
10474
10475		  data_wide_bitset (&Regs[0xde], 0xfff, 0);
10476
10477		  /* release motor */
10478		  Motor_Release (dev);
10479
10480		  if (RTS_Warm_Reset (dev) == OK)
10481		    {
10482		      rst = OK;
10483
10484		      SetLock (dev->usb_handle, Regs,
10485			       (myscancfg->depth == 16) ? FALSE : TRUE);
10486
10487		      /* set gain control */
10488		      Lamp_SetGainMode (dev, Regs, myscancfg->resolution_x,
10489					gaincontrol);
10490
10491		      /* send registers to scanner */
10492		      if (RTS_WriteRegs (dev->usb_handle, Regs) == OK)
10493			{
10494			  /* execute! */
10495			  if (RTS_Execute (dev) == OK)
10496			    RTS_GetImage_Read (dev, buffer, myscancfg, hwdcfg);	/*92e7 */
10497			}
10498
10499		      /*92fc */
10500		      SetLock (dev->usb_handle, Regs, FALSE);
10501
10502		      if ((options & 0x200) != 0)
10503			{
10504			  /* switch on lamp */
10505			  data_bitset (&Regs[0x146], 0x40, 1);
10506
10507			  Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]);
10508			  /* Wait 3 seconds */
10509			  usleep (1000 * 3000);
10510			}
10511
10512		      /*9351 */
10513		      if (dev->motorcfg->changemotorcurrent == TRUE)
10514			Motor_Change (dev, dev->init_regs, 3);
10515		    }
10516
10517		  /* free low level configuration */
10518		  free (hwdcfg);
10519		}
10520
10521	      /* free scanning configuration */
10522	      free (myscancfg);
10523	    }
10524	}
10525    }
10526
10527  DBG (DBG_FNC, "- RTS_GetImage: %i\n", rst);
10528
10529  return rst;
10530}
10531
10532static SANE_Int
10533Refs_Detect (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution_x,
10534	     SANE_Int resolution_y, SANE_Int * x, SANE_Int * y)
10535{
10536  SANE_Int rst = ERROR;		/* default */
10537
10538  DBG (DBG_FNC, "+ Refs_Detect(*Regs, resolution_x=%i, resolution_y=%i):\n",
10539       resolution_x, resolution_y);
10540
10541  if ((x != NULL) && (y != NULL))
10542    {
10543      SANE_Byte *image;
10544      struct st_scanparams scancfg;
10545
10546      *x = *y = 0;		/* default */
10547
10548      /* set configuration to scan a little area at the top-left corner */
10549      memset (&scancfg, 0, sizeof (struct st_scanparams));
10550      scancfg.depth = 8;
10551      scancfg.colormode = CM_GRAY;
10552      scancfg.channel = CL_RED;
10553      scancfg.resolution_x = resolution_x;
10554      scancfg.resolution_y = resolution_y;
10555      scancfg.coord.left = 4;
10556      scancfg.coord.width = (resolution_x * 3) / 10;
10557      scancfg.coord.top = 1;
10558      scancfg.coord.height = (resolution_y * 4) / 10;
10559      scancfg.shadinglength = (resolution_x * 17) / 2;
10560      scancfg.bytesperline = scancfg.coord.width;
10561
10562      /* allocate space to store image */
10563      image =
10564	(SANE_Byte *) malloc ((scancfg.coord.height * scancfg.coord.width) *
10565			      sizeof (SANE_Byte));
10566      if (image != NULL)
10567	{
10568	  struct st_gain_offset gain_offset;
10569	  SANE_Int gaincontrol, pwmlamplevel_backup, C;
10570
10571	  gaincontrol = 0;
10572	  if (RTS_Debug->use_fixed_pwm == FALSE)
10573	    {
10574	      /* 3877 */
10575	      gaincontrol = Lamp_GetGainMode (dev, resolution_x, ST_NORMAL);	/* scan.scantype */
10576	      pwmlamplevel = 0;
10577	      Lamp_PWM_use (dev, 1);
10578	      Lamp_PWM_DutyCycle_Set (dev, (gaincontrol == 0) ? 0x12 : 0x26);
10579
10580	      /* Enciende flb lamp */
10581	      Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP);
10582	      usleep (1000 * 2000);
10583	    }
10584
10585	  /* 38d6 */
10586	  pwmlamplevel_backup = pwmlamplevel;
10587	  pwmlamplevel = 0;
10588	  Lamp_PWM_use (dev, 1);
10589
10590	  memset (&gain_offset, 0, sizeof (struct st_gain_offset));
10591	  for (C = CL_RED; C <= CL_BLUE; C++)
10592	    {
10593	      gain_offset.pag[C] = 3;
10594	      gain_offset.vgag1[C] = 4;
10595	      gain_offset.vgag2[C] = 4;
10596	    }
10597
10598	  /* perform lamp warmup */
10599	  Lamp_Warmup (dev, Regs, FLB_LAMP, resolution_x);
10600
10601	  /* retrieve image from scanner */
10602	  if (RTS_GetImage
10603	      (dev, Regs, &scancfg, &gain_offset, image, 0, 0x20000000,
10604	       gaincontrol) == OK)
10605	    {
10606	      SANE_Int ser1, ler1;
10607
10608	      /* same image to disk if required by user */
10609	      if (RTS_Debug->SaveCalibFile != FALSE)
10610		{
10611		  dbg_tiff_save ("pre-autoref.tiff",
10612				 scancfg.coord.width,
10613				 scancfg.coord.height,
10614				 scancfg.depth,
10615				 CM_GRAY,
10616				 scancfg.resolution_x,
10617				 scancfg.resolution_y,
10618				 image,
10619				 scancfg.coord.height * scancfg.coord.width);
10620		}
10621
10622	      /* calculate reference position */
10623	      if (Refs_Analyze_Pattern (&scancfg, image, &ler1, 1, &ser1, 0)
10624		  == OK)
10625		{
10626		  *y = scancfg.coord.top + ler1;
10627		  *x = scancfg.coord.left + ser1;
10628
10629		  rst = OK;
10630		}
10631	    }
10632
10633	  free (image);
10634
10635	  pwmlamplevel = pwmlamplevel_backup;
10636	}
10637
10638      DBG (DBG_FNC, " -> Detected refs: x=%i , y=%i\n", *x, *y);
10639    }
10640
10641  DBG (DBG_FNC, "- Refs_Detect: %i\n", rst);
10642
10643  return rst;
10644}
10645
10646static SANE_Int
10647Refs_Set (struct st_device *dev, SANE_Byte * Regs,
10648	  struct st_scanparams *scancfg)
10649{
10650  SANE_Int rst;
10651  SANE_Int y, x;
10652  struct st_autoref refcfg;
10653
10654  DBG (DBG_FNC, "+ Refs_Set(*Regs, *scancfg):\n");
10655  dbg_ScanParams (scancfg);
10656
10657  rst = OK;
10658
10659  /* get fixed references for given resolution */
10660  cfg_vrefs_get (dev->sensorcfg->type, scancfg->resolution_x, &scan.ler,
10661		 &scan.ser);
10662  scan.leftleading = scan.ser;
10663  scan.startpos = scan.ler;
10664
10665  /* get auto reference configuration */
10666  cfg_autoref_get (&refcfg);
10667
10668  if (refcfg.type != REF_NONE)
10669    {
10670      /* if reference counter is == 0 perform auto detection */
10671      if (Refs_Counter_Load (dev) == 0)
10672	{
10673	  DBG (DBG_FNC,
10674	       " -> Refs_Set - Autodetection mandatory (counter == 0)\n");
10675
10676	  refcfg.type = REF_AUTODETECT;
10677	}
10678
10679      switch (refcfg.type)
10680	{
10681	case REF_AUTODETECT:
10682	  /* try to autodetect references scanning a little area */
10683	  if (Refs_Detect
10684	      (dev, Regs, refcfg.resolution, refcfg.resolution, &x, &y) == OK)
10685	    Refs_Save (dev, x, y);
10686	  else
10687	    rst = ERROR;
10688
10689	  Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
10690	  break;
10691
10692	case REF_TAKEFROMSCANNER:
10693	  /* Try to get values from scanner */
10694	  if (Refs_Load (dev, &x, &y) == ERROR)
10695	    {
10696	      if (Refs_Detect
10697		  (dev, Regs, refcfg.resolution, refcfg.resolution, &x,
10698		   &y) == OK)
10699		Refs_Save (dev, x, y);
10700	      else
10701		rst = ERROR;
10702
10703	      Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
10704	    }
10705	  break;
10706	}
10707
10708      if (rst == OK)
10709	{
10710	  /* values are based on resolution given by refcfg.resolution.
10711
10712	     offset_x and y are based on 2400 dpi so convert values to that dpi
10713	     before adding offsets and then return to resolution given by user */
10714
10715	  x *= (2400 / refcfg.resolution);
10716	  y *= (2400 / refcfg.resolution);
10717
10718	  scan.leftleading = x;
10719	  scan.startpos = y;
10720	  scan.ser = ((x + refcfg.offset_x) * scancfg->resolution_x) / 2400;
10721	  scan.ler = ((y + refcfg.offset_y) * scancfg->resolution_y) / 2400;
10722
10723	  DBG (DBG_FNC,
10724	       " -> After SEROffset and LEROffset, xoffset = %i, yoffset =%i\n",
10725	       scan.ser, scan.ler);
10726	}
10727
10728      /* increase refs counter */
10729      Refs_Counter_Inc (dev);
10730    }
10731
10732  DBG (DBG_FNC, "- Refs_Set: %i\n", rst);
10733
10734  return rst;
10735}
10736
10737static SANE_Int
10738Lamp_Status_Set (struct st_device *dev, SANE_Byte * Regs, SANE_Int turn_on,
10739		 SANE_Int lamp)
10740{
10741  SANE_Int rst = ERROR;		/* default */
10742  SANE_Byte freevar = FALSE;
10743
10744  DBG (DBG_FNC, "+ Lamp_Status_Set(*Regs, turn_on=%i->%s, lamp=%s)\n",
10745       turn_on,
10746       ((((lamp - 1) | turn_on) & 1) == 1) ? "Yes" : "No",
10747       (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP");
10748
10749  if (Regs == NULL)
10750    {
10751      Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
10752
10753      if (Regs != NULL)
10754	freevar = TRUE;
10755    }
10756
10757  if (Regs != NULL)
10758    {
10759      RTS_ReadRegs (dev->usb_handle, Regs);
10760
10761      /* next op depends on chipset */
10762      switch (dev->chipset->model)
10763	{
10764	case RTS8822BL_03A:
10765	  /* register 0xe946 has 2 bits and each one refers one lamp
10766	     0x40: FLB_LAMP | 0x20 : TMA_LAMP
10767	     if both were enabled both lamps would be switched on */
10768	  data_bitset (&Regs[0x146], 0x20, ((lamp == TMA_LAMP) && (turn_on == TRUE)) ? 1 : 0);	/* TMA */
10769	  data_bitset (&Regs[0x146], 0x40, ((lamp == FLB_LAMP) && (turn_on == TRUE)) ? 1 : 0);	/* FLB */
10770
10771	  data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0);
10772	  break;
10773	default:
10774	  /* the other chipsets only use one bit to indicate when a lamp is
10775	     switched on or not being bit 0x10 in 0xe955 who decides which lamp
10776	     is affected */
10777	  /* switch on lamp? yes if TMA_LAMP, else whatever turn_on says */
10778	  data_bitset (&Regs[0x146], 0x40, ((lamp - 1) | turn_on));
10779	  /* what lamp must be switched on? */
10780	  if ((Regs[0x146] & 0x40) != 0)
10781	    data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0);
10782	  break;
10783	}
10784
10785      /*42b8cd1 */
10786      /* switch on/off lamp */
10787      /*dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0xbf) | (Regs[0x146] & 0x40); */
10788      dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0x9f) | (Regs[0x146] & 0x60);		/*-xx-----*/
10789
10790      /* Which lamp */
10791      dev->init_regs[0x0155] = Regs[0x0155];
10792      Write_Byte (dev->usb_handle, 0xe946, Regs[0x0146]);
10793      usleep (1000 * 200);
10794      Write_Buffer (dev->usb_handle, 0xe954, &Regs[0x0154], 2);
10795    }
10796
10797  if (freevar != FALSE)
10798    {
10799      free (Regs);
10800      Regs = NULL;
10801    }
10802
10803  DBG (DBG_FNC, "- Lamp_Status_Set: %i\n", rst);
10804
10805  return rst;
10806}
10807
10808static SANE_Int
10809Get_PAG_Value (SANE_Byte scantype, SANE_Byte color)
10810{
10811  SANE_Int rst, iType, iColor;
10812
10813  switch (scantype)
10814    {
10815    case ST_NEG:
10816      iType = CALIBNEGATIVEFILM;
10817      break;
10818    case ST_TA:
10819      iType = CALIBTRANSPARENT;
10820      break;
10821    case ST_NORMAL:
10822      iType = CALIBREFLECTIVE;
10823      break;
10824    default:
10825      iType = CALIBREFLECTIVE;
10826      break;
10827    }
10828
10829  switch (color)
10830    {
10831    case CL_BLUE:
10832      iColor = PAGB;
10833      break;
10834    case CL_GREEN:
10835      iColor = PAGG;
10836      break;
10837    case CL_RED:
10838      iColor = PAGR;
10839      break;
10840    default:
10841      iColor = PAGR;
10842      break;
10843    }
10844
10845  rst = get_value (iType, iColor, 1, FITCALIBRATE);
10846
10847  DBG (DBG_FNC, "> Get_PAG_Value(scantype=%s, color=%i): %i\n",
10848       dbg_scantype (scantype), color, rst);
10849
10850  return rst;
10851}
10852
10853static SANE_Byte
10854Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution,
10855		  SANE_Byte scantype)
10856{
10857  SANE_Byte ret;
10858  SANE_Int mygain, iValue;
10859
10860  switch (scantype)
10861    {
10862    case ST_TA:
10863      ret = 0;
10864      iValue = DPIGAINCONTROL_TA600;
10865      break;
10866    case ST_NEG:
10867      ret = 1;
10868      iValue = DPIGAINCONTROL_NEG600;
10869      break;
10870    default:			/* Reflective */
10871      ret = 1;
10872      iValue = DPIGAINCONTROL600;
10873      break;
10874    }
10875
10876  mygain = get_value (SCAN_PARAM, iValue, ret, usbfile);
10877  ret = 0;
10878
10879/*
10880
10881*/
10882  if (scantype == ST_NORMAL)
10883    {
10884      if (dev->chipset->model == RTS8822L_02A)
10885	{
10886	  switch (resolution)
10887	    {
10888	    case 100:
10889	    case 150:
10890	    case 300:
10891	    case 600:
10892	    case 1200:
10893	    case 2400:
10894	    case 4800:
10895	      ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0;
10896	      break;
10897	    }
10898	}
10899      else
10900	{
10901	  switch (resolution)
10902	    {
10903	    case 100:
10904	    case 200:
10905	    case 300:
10906	    case 600:
10907	      if (RTS_Debug->usbtype != USB11)
10908		ret = (mygain != 0) ? 1 : 0;
10909	      else
10910		ret = (resolution == 100) ? 1 : 0;
10911	      break;
10912	    case 1200:
10913	    case 2400:
10914	      ret = 0;
10915	      break;
10916	    }
10917	}
10918    }
10919  else if (scantype == ST_TA)
10920    {
10921      switch (resolution)
10922	{
10923	  /*hp3970 */
10924	case 100:
10925	case 200:
10926	  /*common */
10927	case 300:
10928	case 600:
10929	case 1200:
10930	case 2400:
10931	  /*hp4370 */
10932	case 150:
10933	case 4800:
10934	  ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0;
10935	  break;
10936	}
10937    }
10938  else
10939    {
10940      /* ST_NEG */
10941      switch (resolution)
10942	{
10943	case 100:
10944	case 200:
10945	case 300:
10946	case 600:
10947	  ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0;
10948	  break;
10949	case 1200:
10950	case 2400:
10951	case 4800:		/*hp4370 */
10952	  ret = 0;
10953	  break;
10954	}
10955    }
10956
10957  DBG (DBG_FNC, "> Lamp_GetGainMode(resolution=%i, scantype=%s): %i\n",
10958       resolution, dbg_scantype (scantype), ret);
10959
10960  return ret;
10961}
10962
10963static SANE_Int
10964GetOneLineInfo (struct st_device *dev, SANE_Int resolution,
10965		SANE_Int * maximus, SANE_Int * minimus, double *average)
10966{
10967  SANE_Int rst = ERROR;
10968
10969  DBG (DBG_FNC,
10970       "+ GetOneLineInfo(resolution=%i, *maximus, *minimus, *average):\n",
10971       resolution);
10972
10973  /* Check parameters */
10974  if ((maximus != NULL) && (minimus != NULL) && (average != NULL))
10975    {
10976      SANE_Byte *Regs, *image;
10977      SANE_Int a, gainmode;
10978      struct st_gain_offset gain_offset;
10979      struct st_scanparams scancfg;
10980
10981      Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
10982      if (Regs != NULL)
10983	{
10984	  /* Copy scanner registers */
10985	  memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
10986
10987	  /* Setting some registers */
10988	  for (a = 0x192; a <= 0x19d; a++)
10989	    Regs[a] = 0;
10990
10991	  /* Create calibration table */
10992	  for (a = CL_RED; a <= CL_BLUE; a++)
10993	    {
10994	      gain_offset.edcg1[a] = 256;
10995	      gain_offset.edcg2[a] = 0;
10996	      gain_offset.odcg1[a] = 256;
10997	      gain_offset.odcg2[a] = 0;
10998	      gain_offset.vgag1[a] = 4;
10999	      gain_offset.vgag2[a] = 4;
11000	      gain_offset.pag[a] = Get_PAG_Value (scan.scantype, a);
11001	    }
11002
11003	  RTS_GetScanmode (dev, scantype, 0, resolution);
11004
11005	  /* Setting scanning params */
11006	  memset (&scancfg, 0, sizeof (struct st_scanparams));
11007	  scancfg.colormode = CM_COLOR;
11008	  scancfg.resolution_x = resolution;
11009	  scancfg.resolution_y = resolution;
11010	  scancfg.coord.left = 100;
11011	  scancfg.coord.width = (resolution * 8.5) - 100;
11012	  scancfg.coord.top = 1;
11013	  scancfg.coord.height = 1;
11014	  scancfg.depth = 8;
11015	  scancfg.shadinglength = resolution * 8.5;
11016	  scancfg.v157c = scancfg.coord.width * 3;
11017	  scancfg.bytesperline = scancfg.v157c;
11018
11019	  /* Reserve buffer for line */
11020	  image =
11021	    (SANE_Byte *) malloc (((scancfg.coord.width * 0x21) * 3) *
11022				  sizeof (SANE_Byte));
11023	  if (image != NULL)
11024	    {
11025	      gainmode =
11026		Lamp_GetGainMode (dev, resolution & 0xffff, scan.scantype);
11027	      if (RTS_GetImage
11028		  (dev, Regs, &scancfg, &gain_offset, image, 0,
11029		   OP_STATIC_HEAD, gainmode) != ERROR)
11030		{
11031		  /* Read all image to take max min and average colours */
11032		  SANE_Byte *pointer1 = image;
11033		  SANE_Byte *pointer2;
11034		  SANE_Byte *pointer3;
11035		  SANE_Int cmin[3];	/* min values */
11036		  SANE_Int cmax[3];	/* max values */
11037		  double cave[3];	/* average values */
11038		  SANE_Int mysize;
11039
11040		  if (scancfg.colormode != CM_GRAY)
11041		    {
11042		      pointer2 = image;
11043		      pointer3 = image;
11044		    }
11045		  else
11046		    {
11047		      pointer2 = image + 1;
11048		      pointer3 = image + 2;
11049		    }
11050
11051		  for (a = CL_RED; a <= CL_BLUE; a++)
11052		    {
11053		      cmin[a] = 255;
11054		      cmax[a] = 0;
11055		      cave[a] = 0;
11056		    }
11057
11058		  if (scancfg.coord.height > 0)
11059		    {
11060		      SANE_Int y, x;
11061		      SANE_Byte *mypointer;
11062		      SANE_Byte color;
11063		      SANE_Int desp[3];
11064
11065		      desp[CL_RED] = pointer1 - pointer3;
11066		      desp[CL_GREEN] = pointer2 - pointer3;
11067		      desp[CL_BLUE] = 0;
11068
11069		      for (y = 0; y < scancfg.coord.height; y++)
11070			{
11071			  if (scancfg.coord.width > 0)
11072			    {
11073			      mypointer = pointer3;
11074
11075			      for (x = 0; x < scancfg.coord.width; x++)
11076				{
11077				  for (a = CL_RED; a <= CL_BLUE; a++)
11078				    {
11079				      /* Take colour values */
11080				      color = *(mypointer + desp[a]);
11081
11082				      /* Take max values for each color */
11083				      cmax[a] = max (cmax[a], color);
11084
11085				      /* Take min values for each color */
11086				      cmin[a] = min (cmin[a], color);
11087
11088				      /* Average */
11089				      cave[a] += color;
11090				    }
11091
11092				  mypointer += 3;
11093				}
11094			    }
11095
11096			  /* point to the pixel that is below */
11097			  pointer1 += scancfg.coord.width * 3;
11098			  pointer2 += scancfg.coord.width * 3;
11099			  pointer3 += scancfg.coord.width * 3;
11100			}
11101		    }
11102
11103		  mysize = scancfg.coord.height * scancfg.coord.width;
11104		  if (mysize < 1)
11105		    mysize = 1;
11106
11107		  for (a = CL_RED; a <= CL_BLUE; a++)
11108		    {
11109		      maximus[a] = cmax[a];
11110		      minimus[a] = cmin[a];
11111		      average[a] = cave[a] / mysize;
11112		    }
11113
11114		  DBG (DBG_FNC, " -> GetOneLineInfo: max r=%3i g=%3i b=%3i\n",
11115		       maximus[CL_RED], maximus[CL_GREEN], maximus[CL_BLUE]);
11116		  DBG (DBG_FNC, " ->                 min r=%3i g=%3i b=%3i\n",
11117		       minimus[CL_RED], minimus[CL_GREEN], minimus[CL_BLUE]);
11118		  DBG (DBG_FNC,
11119		       " ->                 avg r=%3.0f g=%3.0f b=%3.0f\n",
11120		       average[CL_RED], average[CL_GREEN], average[CL_BLUE]);
11121
11122		  rst = OK;
11123		}
11124
11125	      free (image);
11126	    }
11127
11128	  free (Regs);
11129	}
11130    }
11131
11132  DBG (DBG_FNC, "- GetOneLineInfo: %i\n", rst);
11133
11134  return OK;
11135}
11136
11137static SANE_Int
11138Lamp_PWM_CheckStable (struct st_device *dev, SANE_Int resolution,
11139		      SANE_Int lamp)
11140{
11141  struct st_checkstable check;
11142  SANE_Int rst;
11143
11144  DBG (DBG_FNC, "+ Lamp_PWM_CheckStable(resolution=%i, lamp=%i):\n",
11145       resolution, lamp);
11146
11147  rst = cfg_checkstable_get (lamp, &check);
11148
11149  if (rst == OK)
11150    {
11151      SANE_Int maximus[3] = { 0 };
11152      SANE_Int minimus[3] = { 0 };
11153      double average[3] = { 0 };
11154      SANE_Int maxbigger;
11155      SANE_Int last_colour = 0;
11156
11157      double diff = check.diff * 0.01;
11158      long tottime = GetTickCount () + check.tottime;
11159
11160      while (GetTickCount () <= tottime)
11161	{
11162	  rst = GetOneLineInfo (dev, resolution, maximus, minimus, average);
11163	  if (rst == OK)
11164	    {
11165	      /* Takes maximal colour value */
11166	      maxbigger =
11167		max (maximus[CL_GREEN],
11168		     max (maximus[CL_BLUE], maximus[CL_RED]));
11169
11170	      /*breaks when colour intensity increases 'diff' or lower */
11171	      if (abs (maxbigger - last_colour) < diff)
11172		{
11173		  DBG (DBG_FNC, " -> PWM is ready\n");
11174		  break;
11175		}
11176
11177	      last_colour = maxbigger;
11178	    }
11179
11180	  usleep (1000 * check.interval);
11181	}
11182
11183    }
11184
11185  DBG (DBG_FNC, "- Lamp_PWM_CheckStable: %i\n", rst);
11186
11187  return OK;
11188}
11189
11190static SANE_Byte
11191Refs_Counter_Load (struct st_device *dev)
11192{
11193  SANE_Byte data = 15;
11194
11195  DBG (DBG_FNC, "+ Refs_Counter_Load:\n");
11196
11197  /* check if chipset supports accessing eeprom */
11198  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
11199    if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x78, &data) != OK)
11200      data = 15;
11201
11202  DBG (DBG_FNC, "- Refs_Counter_Load: %i\n", _B0 (data));
11203
11204  return data;
11205}
11206
11207static SANE_Int
11208Refs_Counter_Save (struct st_device *dev, SANE_Byte data)
11209{
11210  SANE_Int rst = OK;
11211
11212  DBG (DBG_FNC, "+ Refs_Counter_Save(data=%i):\n", data);
11213
11214  /* check if chipset supports accessing eeprom */
11215  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
11216    {
11217      if (data > 15)
11218	data = 15;
11219
11220      rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x78, data);
11221    }
11222
11223  DBG (DBG_FNC, "- Refs_Counter_Save: %i\n", rst);
11224
11225  return rst;
11226}
11227
11228static SANE_Int
11229Refs_Counter_Inc (struct st_device *dev)
11230{
11231  SANE_Byte data;
11232
11233  DBG (DBG_FNC, "+ Refs_Counter_Inc:\n");
11234
11235  data = Refs_Counter_Load (dev) + 1;
11236
11237  if (data >= 15)
11238    data = 0;
11239
11240  Refs_Counter_Save (dev, data);
11241
11242  DBG (DBG_FNC, "- Refs_Counter_Inc() : Count=%i\n", data);
11243
11244  return OK;
11245}
11246
11247static SANE_Int
11248Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, SANE_Int * xpos)
11249{
11250  SANE_Int iType;
11251
11252  switch (scantype)
11253    {
11254    case 3:
11255      iType = CALIBNEGATIVEFILM;
11256      break;
11257    case 2:
11258      iType = CALIBTRANSPARENT;
11259      break;
11260    default:
11261      iType = CALIBREFLECTIVE;
11262      break;
11263    }
11264
11265  *xpos = get_value (iType, WSTRIPXPOS, 0, FITCALIBRATE);
11266  *ypos = get_value (iType, WSTRIPYPOS, 0, FITCALIBRATE);
11267
11268  DBG (DBG_FNC, "> Load_StripCoords(scantype=%s): ypos=%i, xpos=%i\n",
11269       dbg_scantype (scantype), *ypos, *xpos);
11270
11271  return OK;
11272}
11273
11274static SANE_Int
11275Head_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction,
11276	       SANE_Int ypos)
11277{
11278  SANE_Int rst;
11279  SANE_Byte *Regs;
11280
11281  DBG (DBG_FNC, "+ Head_Relocate(speed=%i, direction=%i, ypos=%i):\n", speed,
11282       direction, ypos);
11283
11284  rst = ERROR;
11285
11286  Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
11287  if (Regs != NULL)
11288    {
11289      struct st_motormove mymotor;
11290      struct st_motorpos mtrpos;
11291
11292      memset (&mymotor, 0, sizeof (struct st_motormove));
11293      memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
11294
11295      if (speed < dev->motormove_count)
11296	memcpy (&mymotor, dev->motormove[speed],
11297		sizeof (struct st_motormove));
11298
11299      /*83fe */
11300      mtrpos.coord_y = ypos;
11301      mtrpos.options =
11302	MTR_ENABLED | ((direction == MTR_BACKWARD) ? MTR_BACKWARD :
11303		       MTR_FORWARD);
11304      mtrpos.v12e448 = 0;
11305      mtrpos.v12e44c = 1;
11306
11307      Motor_Move (dev, Regs, &mymotor, &mtrpos);
11308
11309      /* waits 15 seconds */
11310      RTS_WaitScanEnd (dev, 15000);
11311
11312      free (Regs);
11313      rst = OK;
11314    }
11315
11316  DBG (DBG_FNC, "- Head_Relocate: %i\n", rst);
11317
11318  return rst;
11319}
11320
11321static SANE_Int
11322Calib_CreateFixedBuffers ()
11323{
11324  SANE_Byte channel;
11325  SANE_Int ret;
11326
11327  DBG (DBG_FNC, "> Calib_CreateFixedBuffers()\n");
11328
11329  ret = OK;
11330  channel = 0;
11331
11332  while ((channel < 3) && (ret == OK))
11333    {
11334      /* First table */
11335      if (fixed_black_shading[channel] == NULL)
11336	fixed_black_shading[channel] =
11337	  (USHORT *) malloc (0x7f8 * sizeof (USHORT));
11338
11339      if (fixed_black_shading[channel] != NULL)
11340	memset (fixed_black_shading[channel], 0, 0x7f8 * sizeof (USHORT));
11341      else
11342	ret = ERROR;
11343
11344      /* Second table */
11345      if (fixed_white_shading[channel] == NULL)
11346	fixed_white_shading[channel] =
11347	  (USHORT *) malloc (0x7f8 * sizeof (USHORT));
11348
11349      if (fixed_white_shading[channel] != NULL)
11350	memset (fixed_white_shading[channel], 0, 0x7f8 * sizeof (USHORT));
11351      else
11352	ret = ERROR;
11353
11354      channel++;
11355    }
11356
11357  return ret;
11358}
11359
11360static SANE_Int
11361Calib_CreateBuffers (struct st_device *dev, struct st_calibration *buffer,
11362		     SANE_Int my14b4)
11363{
11364  SANE_Int ebp, ret, channel;
11365
11366  ret = ERROR;
11367  (void) dev;
11368
11369  buffer->shadinglength = scan.coord.width;
11370  ebp = 0x14;
11371
11372  if (my14b4 != 0)
11373    {
11374      /* 673d */
11375      if (Calib_CreateFixedBuffers () == OK)
11376	{
11377	  for (channel = 0; channel < 3; channel++)
11378	    {
11379	      buffer->white_shading[channel] = fixed_white_shading[channel];
11380	      buffer->black_shading[channel] = fixed_black_shading[channel];
11381	    }
11382	  ret = OK;
11383	}
11384    }
11385  else
11386    {
11387      /* 677f */
11388      SANE_Int pos;
11389      channel = 0;
11390      while ((channel < 3) && (ret == OK))
11391	{
11392	  buffer->black_shading[channel] =
11393	    (USHORT *) malloc (ebp +
11394			       (buffer->shadinglength * sizeof (USHORT)));
11395	  buffer->white_shading[channel] =
11396	    (USHORT *) malloc (ebp +
11397			       (buffer->shadinglength * sizeof (USHORT)));
11398	  if ((buffer->black_shading[channel] != NULL)
11399	      && (buffer->white_shading[channel] != NULL))
11400	    {
11401	      for (pos = 0; pos < buffer->shadinglength; pos++)
11402		{
11403		  buffer->black_shading[channel][pos] = 0x00;
11404		  buffer->white_shading[channel][pos] = 0x4000;
11405		}
11406	      ret = OK;
11407	    }
11408	  else
11409	    Calib_FreeBuffers (buffer);
11410
11411	  channel++;
11412	}
11413    }
11414
11415  DBG (DBG_FNC, "> Calib_CreateBuffers: *buffer, my14b4=%i): %i\n", my14b4,
11416       ret);
11417
11418  return ret;
11419}
11420
11421static void
11422Calib_FreeBuffers (struct st_calibration *caltables)
11423{
11424  DBG (DBG_FNC, "> Calib_FreeBuffers(*caltables)\n");
11425
11426  if (caltables != NULL)
11427    {
11428      SANE_Int channel;
11429
11430      for (channel = 0; channel < 3; channel++)
11431	{
11432	  if (caltables->black_shading[channel] != NULL)
11433	    {
11434	      free (caltables->black_shading[channel]);
11435	      caltables->black_shading[channel] = NULL;
11436	    }
11437
11438	  if (caltables->white_shading[channel] != NULL)
11439	    {
11440	      free (caltables->white_shading[channel]);
11441	      caltables->white_shading[channel] = NULL;
11442	    }
11443	}
11444    }
11445}
11446
11447static SANE_Int
11448Calib_LoadConfig (struct st_device *dev,
11449		  struct st_calibration_config *calibcfg, SANE_Int scantype,
11450		  SANE_Int resolution, SANE_Int bitmode)
11451{
11452  SANE_Int section, a;
11453  struct st_autoref refcfg;
11454
11455  DBG (DBG_FNC,
11456       "> Calib_LoadConfig(*calibcfg, scantype=%s, resolution=%i, bitmode=%i)\n",
11457       dbg_scantype (scantype), resolution, bitmode);
11458
11459  switch (scantype)
11460    {
11461    case ST_NEG:
11462      section = CALIBNEGATIVEFILM;
11463      break;
11464    case ST_TA:
11465      section = CALIBTRANSPARENT;
11466      break;
11467    default:
11468      section = CALIBREFLECTIVE;
11469      break;
11470    }
11471
11472  calibcfg->WStripXPos = get_value (section, WSTRIPXPOS, 0, FITCALIBRATE);
11473  calibcfg->WStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE);
11474  calibcfg->BStripXPos = get_value (section, BSTRIPXPOS, 0, FITCALIBRATE);
11475  calibcfg->BStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE);
11476
11477  /* get calibration wrefs */
11478  cfg_wrefs_get (dev->sensorcfg->type, bitmode, resolution, scantype,
11479		 &calibcfg->WRef[CL_RED], &calibcfg->WRef[CL_GREEN],
11480		 &calibcfg->WRef[CL_BLUE]);
11481
11482  /* 4913 */
11483
11484  for (a = CL_RED; a <= CL_BLUE; a++)
11485    {
11486      WRef[a] = _B0 (calibcfg->WRef[a]);
11487
11488      calibcfg->BRef[a] = get_value (section, BREFR + a, 10, FITCALIBRATE);
11489      calibcfg->OffsetEven1[a] =
11490	get_value (section, OFFSETEVEN1R + a, 256, FITCALIBRATE);
11491      calibcfg->OffsetEven2[a] =
11492	get_value (section, OFFSETEVEN2R + a, 0, FITCALIBRATE);
11493      calibcfg->OffsetOdd1[a] =
11494	get_value (section, OFFSETODD1R + a, 256, FITCALIBRATE);
11495      calibcfg->OffsetOdd2[a] =
11496	get_value (section, OFFSETODD2R + a, 0, FITCALIBRATE);
11497    }
11498
11499  calibcfg->RefBitDepth =
11500    _B0 (get_value (section, REFBITDEPTH, 8, FITCALIBRATE));
11501  calibcfg->CalibOffset10n =
11502    _B0 (get_value (section, CALIBOFFSET10N, 3, FITCALIBRATE));
11503  calibcfg->CalibOffset20n =
11504    _B0 (get_value (section, CALIBOFFSET20N, 0, FITCALIBRATE));
11505  calibcfg->OffsetHeight =
11506    get_value (section, OFFSETHEIGHT, 10, FITCALIBRATE);
11507
11508  /* 4ae9 */
11509
11510  /* get left coordinate and length to calibrate offset */
11511  cfg_offset_get (dev->sensorcfg->type, resolution, scantype,
11512		  &calibcfg->OffsetPixelStart, &calibcfg->OffsetNPixel);
11513
11514  /*4c49 */
11515  calibcfg->OffsetNSigma = get_value (section, OFFSETNSIGMA, 2, FITCALIBRATE);
11516  calibcfg->OffsetTargetMax =
11517    get_value (section, OFFSETTARGETMAX, 0x32, FITCALIBRATE) * 0.01;
11518  calibcfg->OffsetTargetMin =
11519    get_value (section, OFFSETTARGETMIN, 2, FITCALIBRATE) * 0.01;
11520  calibcfg->OffsetBoundaryRatio1 =
11521    get_value (section, OFFSETBOUNDARYRATIO1, 0x64, FITCALIBRATE) * 0.01;
11522  calibcfg->OffsetBoundaryRatio2 =
11523    get_value (section, OFFSETBOUNDARYRATIO2, 0x64, FITCALIBRATE) * 0.01;
11524
11525  calibcfg->OffsetAvgRatio1 =
11526    get_value (section, OFFSETAVGRATIO1, 0x64, FITCALIBRATE) * 0.01;
11527  calibcfg->OffsetAvgRatio2 =
11528    get_value (section, OFFSETAVGRATIO2, 0x64, FITCALIBRATE) * 0.01;
11529  calibcfg->AdcOffQuickWay =
11530    get_value (section, ADCOFFQUICKWAY, 1, FITCALIBRATE);
11531  calibcfg->AdcOffPredictStart =
11532    get_value (section, ADCOFFPREDICTSTART, 0xc8, FITCALIBRATE);
11533  calibcfg->AdcOffPredictEnd =
11534    get_value (section, ADCOFFPREDICTEND, 0x1f4, FITCALIBRATE);
11535  calibcfg->AdcOffEvenOdd =
11536    get_value (section, ADCOFFEVENODD, 1, FITCALIBRATE);
11537  calibcfg->OffsetTuneStep1 =
11538    _B0 (get_value (section, OFFSETTUNESTEP1, 1, FITCALIBRATE));
11539  calibcfg->OffsetTuneStep2 =
11540    _B0 (get_value (section, OFFSETTUNESTEP2, 1, FITCALIBRATE));
11541  calibcfg->CalibGain10n = get_value (section, CALIBGAIN10N, 1, FITCALIBRATE);
11542  calibcfg->CalibGain20n = get_value (section, CALIBGAIN20N, 0, FITCALIBRATE);
11543  calibcfg->CalibPAGOn = get_value (section, CALIBPAGON, 0, FITCALIBRATE);
11544
11545  for (a = CL_RED; a <= CL_BLUE; a++)
11546    {
11547      calibcfg->OffsetAvgTarget[a] =
11548	_B0 (get_value (section, OFFSETAVGTARGETR + a, 0x0d, FITCALIBRATE));
11549      calibcfg->PAG[a] = get_value (section, PAGR + a, 3, FITCALIBRATE);
11550      calibcfg->Gain1[a] = get_value (section, GAIN1R + a, 4, FITCALIBRATE);
11551      calibcfg->Gain2[a] = get_value (section, GAIN2R + a, 4, FITCALIBRATE);
11552      calibcfg->WShadingPreDiff[a] =
11553	get_value (section, WSHADINGPREDIFFR + a, -1, FITCALIBRATE);
11554      calibcfg->BShadingPreDiff[a] =
11555	get_value (section, BSHADINGPREDIFFR + a, 2, FITCALIBRATE);
11556    }
11557
11558  calibcfg->GainHeight = get_value (section, GAINHEIGHT, 0x1e, FITCALIBRATE);
11559  calibcfg->GainTargetFactor =
11560    get_value (section, GAINTARGETFACTOR, 0x5a, FITCALIBRATE) * 0.01;
11561  calibcfg->TotShading = get_value (section, TOTSHADING, 0, FITCALIBRATE);
11562
11563  /* White shading */
11564  calibcfg->WShadingOn = get_value (section, WSHADINGON, 3, FITCALIBRATE);
11565  calibcfg->WShadingHeight =
11566    get_value (section, WSHADINGHEIGHT, 0x18, FITCALIBRATE);
11567
11568  /* Black shading */
11569  calibcfg->BShadingOn = get_value (section, BSHADINGON, 2, FITCALIBRATE);
11570  calibcfg->BShadingHeight =
11571    get_value (section, BSHADINGHEIGHT, 0x1e, FITCALIBRATE);
11572
11573  calibcfg->BShadingDefCutOff =
11574    get_value (section, BSHADINGDEFCUTOFF, 0, FITCALIBRATE);
11575
11576  refcfg.extern_boundary = 0;
11577  cfg_autoref_get (&refcfg);
11578  calibcfg->ExternBoundary = refcfg.extern_boundary * 0.01;
11579
11580  calibcfg->EffectivePixel =
11581    cfg_effectivepixel_get (dev->sensorcfg->type, resolution);
11582
11583  return OK;
11584}
11585
11586static SANE_Int
11587Calib_AdcGain (struct st_device *dev, struct st_calibration_config *calibcfg,
11588	       SANE_Int arg2, SANE_Int gaincontrol)
11589{
11590  /*
11591     0606F8E0   04F60738  |Arg1 = 04F60738
11592     0606F8E4   0606F90C  |Arg2 = 0606F90C calibcfg
11593     0606F8E8   00000001  |Arg3 = 00000001 arg2
11594     0606F8EC   00000001  \Arg4 = 00000001 gaincontrol
11595   */
11596
11597  SANE_Int rst = ERROR;
11598  SANE_Byte *myRegs;		/*f1c0 */
11599
11600  DBG (DBG_FNC, "+ Calib_AdcGain(*calibcfg, arg2=%i, gaincontrol=%i)\n", arg2,
11601       gaincontrol);
11602
11603  myRegs = (SANE_Byte *) malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN);
11604  if (myRegs != NULL)
11605    {
11606      struct st_scanparams *scancfg;	/*f17c */
11607      SANE_Int bytes_per_line, bytes_to_next_colour, bytes_per_pixel;
11608
11609      /* get register values to perform adc gain calibration */
11610      memcpy (myRegs, &calibdata->Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN);
11611
11612      scancfg =
11613	(struct st_scanparams *) malloc (sizeof (struct st_scanparams));
11614      if (scancfg != NULL)
11615	{
11616	  SANE_Byte *image, *pgain, *pcalgain;
11617
11618	  /* get proper scan configuration */
11619	  memcpy (scancfg, &calibdata->scancfg,
11620		  sizeof (struct st_scanparams));
11621
11622	  /* set gain control type */
11623	  Lamp_SetGainMode (dev, myRegs, scancfg->resolution_x, gaincontrol);
11624
11625	  /* 8-bit depth */
11626	  scancfg->depth = 8;
11627
11628	  /* set coordinates */
11629	  if ((scan.scantype > 0) && (scan.scantype < 4))
11630	    scancfg->coord.left += scan.ser;
11631
11632	  if ((scancfg->coord.width & 1) == 0)
11633	    scancfg->coord.width++;
11634
11635	  scancfg->coord.top = 1;
11636	  scancfg->coord.height = calibcfg->OffsetHeight;
11637
11638	  /* three more values to read image data after getting image from scanner */
11639	  switch (scancfg->colormode)
11640	    {
11641	    case CM_GRAY:
11642	    case CM_LINEART:
11643	      bytes_to_next_colour = 0;
11644	      bytes_per_pixel = 1;
11645	      bytes_per_line = scancfg->coord.width;
11646	      break;
11647	    default:		/* CM_COLOR */
11648	      /* c027 */
11649	      bytes_to_next_colour = 1;
11650	      bytes_per_line = scancfg->coord.width * 3;
11651	      if (scancfg->samplerate == LINE_RATE)
11652		{
11653		  bytes_to_next_colour = scancfg->coord.width;
11654		  bytes_per_pixel = 1;
11655		}
11656	      else
11657		bytes_per_pixel = 3;
11658	      break;
11659	    }
11660
11661	  /*7fc7 */
11662	  scancfg->v157c = bytes_per_line;
11663	  scancfg->bytesperline = bytes_per_line;
11664
11665	  /* select type of gain parameters to set */
11666	  if (arg2 != 0)
11667	    {
11668	      pgain = calibdata->gain_offset.vgag1;
11669	      pcalgain = calibcfg->Gain1;
11670	    }
11671	  else
11672	    {
11673	      /*7ff2 */
11674	      pgain = calibdata->gain_offset.vgag2;
11675	      pcalgain = calibcfg->Gain2;
11676	    }
11677
11678	  /*8002 */
11679	  /* Allocate space for image  | size = 132912 */
11680	  image =
11681	    (SANE_Byte *) malloc (sizeof (SANE_Byte) *
11682				  ((scancfg->coord.height +
11683				    16) * bytes_per_line));
11684	  if (image != NULL)
11685	    {
11686	      /* Lets read image */
11687	      if (RTS_GetImage
11688		  (dev, myRegs, scancfg, &calibdata->gain_offset, image, NULL,
11689		   OP_STATIC_HEAD, gaincontrol) == OK)
11690		{
11691		  SANE_Int a;
11692		  SANE_Int vmin[3], vmax[3];
11693		  double dval[3] = { 0.0 };	/*f1a8 f1b0 f1b8 */
11694		  SANE_Byte *pimage = image;
11695
11696		  /* initialize values */
11697		  for (a = CL_RED; a <= CL_BLUE; a++)
11698		    {
11699		      calibcfg->unk1[a] = 0;
11700		      calibcfg->unk2[a] = 0xff;
11701
11702		      vmin[a] = 0xff;
11703		      vmax[a] = 0;
11704		    }
11705
11706		  /* process image data */
11707		  if (scancfg->coord.width > 0)
11708		    {
11709		      /*8104 */
11710		      SANE_Int pos, myheight /*f164 */ ;
11711		      SANE_Int chn_sum[3];
11712
11713		      for (pos = scancfg->coord.width; pos > 0; pos--)
11714			{
11715			  chn_sum[CL_RED] = chn_sum[CL_GREEN] =
11716			    chn_sum[CL_BLUE] = 0;
11717
11718			  if (scancfg->coord.height > 0)
11719			    for (myheight = 0;
11720				 myheight < scancfg->coord.height; myheight++)
11721			      for (a = CL_RED; a <= CL_BLUE; a++)
11722				chn_sum[a] +=
11723				  *(pimage + (bytes_per_line * myheight) +
11724				    (bytes_to_next_colour * a));
11725
11726			  /*816e */
11727			  for (a = CL_RED; a <= CL_BLUE; a++)
11728			    {
11729			      vmin[a] =
11730				min (vmin[a],
11731				     chn_sum[a] / scancfg->coord.height);
11732			      vmax[a] =
11733				max (vmax[a],
11734				     chn_sum[a] / scancfg->coord.height);
11735
11736			      calibcfg->unk1[a] =
11737				max (calibcfg->unk1[a], vmax[a]);
11738			      calibcfg->unk2[a] =
11739				min (calibcfg->unk1[a], vmin[a]);
11740
11741			      dval[a] += vmax[a] & 0xffff;
11742			    }
11743
11744			  pimage += bytes_per_pixel;
11745			}
11746		    }
11747
11748		  /*82b0 */
11749		  dval[CL_RED] /= scancfg->coord.width;
11750		  dval[CL_GREEN] /= scancfg->coord.width;
11751		  dval[CL_BLUE] /= scancfg->coord.width;
11752
11753		  DBG (DBG_FNC, " -> adcgain (av/l): r=%f, g=%f, b=%f\n",
11754		       dval[CL_RED], dval[CL_GREEN], dval[CL_BLUE]);
11755		  DBG (DBG_FNC, " ->         (max ): R=%i, G=%i, B=%i\n",
11756		       calibcfg->unk1[CL_RED], calibcfg->unk1[CL_GREEN],
11757		       calibcfg->unk1[CL_BLUE]);
11758		  DBG (DBG_FNC, " ->         (min ): r=%i, g=%i, b=%i\n",
11759		       calibcfg->unk2[CL_RED], calibcfg->unk2[CL_GREEN],
11760		       calibcfg->unk2[CL_BLUE]);
11761
11762		  if (scancfg->colormode == CM_COLOR)
11763		    {
11764		      /*8353 */
11765		      double dvalue;
11766		      SANE_Int ival;
11767
11768		      for (a = CL_RED; a <= CL_BLUE; a++)
11769			{
11770			  dvalue =
11771			    ((((calibcfg->WRef[a] * (1 << scancfg->depth)) *
11772			       calibcfg->GainTargetFactor) * 0.00390625) /
11773			     dval[a]) * ((44 - pgain[a]) / 40);
11774			  if (dvalue > 0.9090909090909091)
11775			    {
11776			      /*83d7 */
11777			      dvalue = min (44 - (40 / dvalue), 31);
11778			      ival = dvalue;
11779			      pgain[a] = _B0 (ival);
11780			      pcalgain[a] = _B0 (ival);
11781			    }
11782			  else
11783			    {
11784			      pgain[a] = 0;
11785			      pcalgain[a] = 0;
11786			    }
11787			}
11788		    }
11789		  else
11790		    {
11791		      /*843c */
11792		      /*falta codigo */
11793		      double dvalue;
11794		      SANE_Int ival;
11795
11796		      dvalue =
11797			((44 -
11798			  pgain[CL_RED]) / 40) * ((((1 << scancfg->depth) *
11799						    calibcfg->WRef[scancfg->
11800								   channel]) *
11801						   0.9) * 0.00390625) /
11802			17.08509389671362;
11803
11804		      for (a = CL_RED; a <= CL_BLUE; a++)
11805			{
11806			  if (dvalue > 0.9090909090909091)
11807			    {
11808			      dvalue = min (44 - (40 / dvalue), 31);
11809			      ival = dvalue;
11810			      pgain[a] = _B0 (ival);
11811			      pcalgain[a] = _B0 (ival);
11812			    }
11813			  else
11814			    {
11815			      /*84e3 */
11816			      pgain[a] = 0;
11817			      pcalgain[a] = 0;
11818			    }
11819			}
11820		    }
11821
11822		  /*84fa */
11823		  /* Save buffer */
11824		  if (RTS_Debug->SaveCalibFile != FALSE)
11825		    {
11826		      dbg_tiff_save ("adcgain.tiff",
11827				     scancfg->coord.width,
11828				     scancfg->coord.height,
11829				     scancfg->depth,
11830				     CM_COLOR,
11831				     scancfg->resolution_x,
11832				     scancfg->resolution_y,
11833				     image,
11834				     (scancfg->coord.height +
11835				      16) * bytes_per_line);
11836		    }
11837
11838		  /* check if peak values are above offset average target + 5 */
11839		  for (a = CL_RED; a <= CL_BLUE; a++)
11840		    if (calibcfg->unk1[a] >= calibcfg->OffsetAvgTarget[a] + 5)
11841		      {
11842			rst = OK;
11843			break;
11844		      }
11845		}
11846
11847	      free (image);
11848	    }
11849
11850	  free (scancfg);
11851	}
11852
11853      free (myRegs);
11854    }
11855
11856  /* v14b8 = (rst == OK)? 0: 1; */
11857
11858  /* show */
11859  dbg_calibtable (&calibdata->gain_offset);
11860
11861  DBG (DBG_FNC, "- Calib_AdcGain: %i\n", rst);
11862
11863  return rst;
11864}
11865
11866static SANE_Int
11867GainOffset_Save (struct st_device *dev, SANE_Int * offset, SANE_Byte * gain)
11868{
11869  SANE_Int rst = OK;
11870
11871  DBG (DBG_FNC, "+ GainOffset_Save(*offset, *gain):\n");
11872
11873  /* check if chipset supports accessing eeprom */
11874  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
11875    {
11876      if ((offset != NULL) && (gain != NULL))
11877	{
11878	  SANE_Int a, crc, value;
11879
11880	  crc = 0x5B;
11881	  for (a = CL_RED; a <= CL_BLUE; a++)
11882	    {
11883	      value = (*gain << 9) | *offset;
11884	      crc = _B0 (abs (crc - _B0 (value)));
11885	      rst =
11886		RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (a * 2), value);
11887	    }
11888
11889	  if (rst == OK)
11890	    rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, crc);
11891	}
11892      else
11893	rst = ERROR;
11894    }
11895
11896  DBG (DBG_FNC, "- GainOffset_Save: %i\n", rst);
11897
11898  return rst;
11899}
11900
11901static SANE_Int
11902Calib_PAGain (struct st_device *dev, struct st_calibration_config *calibcfg,
11903	      SANE_Int gainmode)
11904{
11905  SANE_Byte *Regs;
11906  struct st_scanparams *scancfg;
11907  SANE_Int channel_size;
11908  SANE_Int bytes_to_next_colour = 0;
11909  SANE_Int bytes_per_pixel = 0;
11910  SANE_Int length = 0;
11911  SANE_Byte *image;
11912  double rst;
11913  SANE_Int ret = ERROR;
11914
11915  DBG (DBG_FNC, "+ Calib_PAGain(*calibcfg, gainmode=%i)\n", gainmode);
11916
11917  Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
11918  if (Regs != NULL)
11919    {
11920      scancfg =
11921	(struct st_scanparams *) malloc (sizeof (struct st_scanparams));
11922      if (scancfg != NULL)
11923	{
11924	  memcpy (Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
11925	  memcpy (scancfg, &calibdata->scancfg,
11926		  sizeof (struct st_scanparams));
11927
11928	  if (scan.scantype == ST_NORMAL)
11929	    {
11930	      /* bfa5 */
11931	      scancfg->coord.left = scan.ser;
11932	      scancfg->coord.width = (scancfg->sensorresolution * 17) / 2;
11933	    }
11934	  else
11935	    {
11936	      scancfg->coord.left = scan.ser + v0750;
11937	      scancfg->coord.width = (scancfg->sensorresolution * 3) / 2;
11938	    }
11939
11940	  /* bfca */
11941	  if ((scancfg->coord.width & 1) == 1)
11942	    scancfg->coord.width++;
11943
11944	  scancfg->coord.top = 1;
11945	  scancfg->coord.height = calibcfg->OffsetHeight;
11946
11947	  channel_size = (scancfg->depth > 8) ? 2 : 1;
11948
11949	  switch (scancfg->colormode)
11950	    {
11951	    case CM_GRAY:
11952	    case CM_LINEART:
11953	      bytes_to_next_colour = 0;
11954	      bytes_per_pixel = 1;
11955	      length = channel_size * scancfg->coord.width;
11956	      break;
11957	    default:		/* CM_COLOR */
11958	      /* c027 */
11959	      bytes_to_next_colour = 1;
11960	      length = (channel_size * scancfg->coord.width) * 3;
11961	      if (scancfg->samplerate == LINE_RATE)
11962		{
11963		  bytes_to_next_colour = scancfg->coord.width;
11964		  bytes_per_pixel = 1;
11965		}
11966	      else
11967		bytes_per_pixel = 3;
11968	      break;
11969	    }
11970
11971	  /* c070 */
11972	  scancfg->v157c = length;
11973
11974	  image =
11975	    (SANE_Byte *) malloc ((scancfg->coord.height * length) *
11976				  sizeof (SANE_Byte));
11977	  if (image != NULL)
11978	    {
11979	      ret =
11980		RTS_GetImage (dev, Regs, scancfg, &calibdata->gain_offset,
11981			      image, 0, OP_STATIC_HEAD, gainmode);
11982	      if (ret == OK)
11983		{
11984		  /* 429c105 */
11985		  SANE_Int a;
11986		  SANE_Byte *ptr[3];
11987		  SANE_Int vmin[3] = { 255, 255, 255 };	/* f16c|f16e|f170 */
11988		  SANE_Int vmax[3] = { 0, 0, 0 };	/* f164|f166|f168 */
11989		  SANE_Int total[3];
11990
11991		  ptr[CL_RED] = image;
11992		  ptr[CL_GREEN] = image + bytes_to_next_colour;
11993		  ptr[CL_BLUE] = image + (bytes_to_next_colour * 2);
11994
11995		  if (scancfg->coord.width > 0)
11996		    {
11997		      SANE_Int pos, b;
11998
11999		      for (pos = 0; pos < scancfg->coord.width; pos++)
12000			{
12001			  total[CL_BLUE] = 0;
12002			  total[CL_GREEN] = 0;
12003			  total[CL_RED] = 0;
12004
12005			  for (a = 0; a < scancfg->coord.height; a++)
12006			    {
12007			      for (b = CL_RED; b <= CL_BLUE; b++)
12008				total[b] +=
12009				  *(ptr[b] +
12010				    ((scancfg->coord.height - a) * length));
12011			    }
12012
12013			  /* c1a5 */
12014			  for (a = CL_RED; a <= CL_BLUE; a++)
12015			    {
12016			      total[a] /= scancfg->coord.height;
12017			      vmin[a] = min (vmin[a], total[a]);
12018			      vmax[a] = max (vmax[a], total[a]);
12019
12020			      ptr[a] += bytes_per_pixel;
12021			    }
12022			}
12023		    }
12024
12025		  /* 429c234 */
12026		  for (a = CL_RED; a <= CL_BLUE; a++)
12027		    {
12028		      rst =
12029			(calibcfg->WRef[a] * calibcfg->GainTargetFactor) /
12030			vmax[a];
12031		      if (rst <= 1.5)
12032			{
12033			  if (rst <= 1.286)
12034			    {
12035			      if (rst <= 1.125)
12036				calibdata->gain_offset.pag[a] = 0;
12037			      else
12038				calibdata->gain_offset.pag[a] = 1;
12039			    }
12040			  else
12041			    calibdata->gain_offset.pag[a] = 2;
12042			}
12043		      else
12044			calibdata->gain_offset.pag[a] = 3;
12045		    }
12046		}
12047	      free (image);
12048	    }
12049	  free (scancfg);
12050	}
12051      free (Regs);
12052    }
12053
12054  DBG (DBG_FNC, "- Calib_PAGain: %i\n", ret);
12055
12056  return ret;
12057}
12058
12059static SANE_Int
12060Chipset_ID (struct st_device *dev)
12061{
12062  SANE_Int ret;
12063
12064  if (Read_Word (dev->usb_handle, 0xfe3c, &ret) == OK)
12065    ret = _B0 (ret);
12066  else
12067    ret = 0;
12068
12069  DBG (DBG_FNC, "> Chipset_ID(): %i\n", ret);
12070
12071  return ret;
12072}
12073
12074static SANE_Int
12075Chipset_Name (struct st_device *dev, char *name, SANE_Int size)
12076{
12077  SANE_Int rst = ERROR;
12078
12079  if (name != NULL)
12080    {
12081      strncpy (name, dev->chipset->name, size);
12082      rst = OK;
12083    }
12084
12085  return rst;
12086}
12087
12088static SANE_Int
12089Refs_Load (struct st_device *dev, SANE_Int * x, SANE_Int * y)
12090{
12091  SANE_Int ret = OK;
12092
12093  DBG (DBG_FNC, "+ Refs_Load:\n");
12094
12095  *y = *x = 0;
12096
12097  /* check if chipset supports accessing eeprom */
12098  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
12099    {
12100      SANE_Int data;
12101
12102      ret = ERROR;
12103
12104      if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6a, &data) == OK)
12105	{
12106	  *x = data;
12107	  if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6c, &data) == OK)
12108	    {
12109	      *y = data;
12110	      if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6e, &data) == OK)
12111		{
12112		  if ((_B0 (*y + *x + data)) == 0x5a)
12113		    ret = OK;
12114		}
12115	    }
12116	}
12117    }
12118
12119  DBG (DBG_FNC, "- Refs_Load(y=%i, x=%i) : %i\n", *y, *x, ret);
12120
12121  return ret;
12122}
12123
12124static SANE_Int
12125Refs_Save (struct st_device *dev, SANE_Int left_leading, SANE_Int start_pos)
12126{
12127  SANE_Int ret = OK;
12128
12129  DBG (DBG_FNC, "+ Refs_Save(left_leading=%i, start_pos=%i)\n", left_leading,
12130       start_pos);
12131
12132  /* check if chipset supports accessing eeprom */
12133  if ((dev->chipset->capabilities & CAP_EEPROM) != 0)
12134    {
12135      ret = ERROR;
12136
12137      if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6a, left_leading) == OK)
12138	{
12139	  if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6c, start_pos) == OK)
12140	    {
12141	      SANE_Byte data = _B0 (0x5a - (start_pos + left_leading));
12142	      ret = RTS_EEPROM_WriteByte (dev->usb_handle, 0x6e, data);
12143	    }
12144	}
12145    }
12146
12147  DBG (DBG_FNC, "- Refs_Save: %i\n", ret);
12148
12149  return ret;
12150}
12151
12152static SANE_Int
12153Calib_AdcOffsetRT (struct st_device *dev,
12154		   struct st_calibration_config *calibcfg, SANE_Int value)
12155{
12156/*
1215705EFF8E4   04F10738  |Arg1 = 04F10738
1215805EFF8E8   05EFF90C  |Arg2 = 05EFF90C calibcfg
1215905EFF8EC   00000001  \Arg3 = 00000001 value
12160*/
12161  SANE_Byte Regs[RT_BUFFER_LEN];	/*f1c4 */
12162  SANE_Int channels_per_dot;	/*f108 */
12163  struct st_scanparams scancfg;	/*f18c */
12164  SANE_Int *pedcg;		/*f114 */
12165  SANE_Int *podcg;		/*f118 */
12166  SANE_Int *poffseteven;	/*f130 */
12167  SANE_Int *poffsetodd;		/*f128 */
12168  SANE_Int channel;
12169  SANE_Int avgtarget[3];	/*f1b8 f1bc f1c0 */
12170  SANE_Byte *scanbuffer;	/*f0f8 */
12171  SANE_Int scan_options;	/*f12c */
12172  SANE_Int highresolution;	/*f144 */
12173  double dbValues[3] = { 0, 0, 0 };	/*f148 f14c f150 */
12174  SANE_Int do_loop;		/*f0ec */
12175  SANE_Int gainmode;
12176  SANE_Byte *ptr;		/*f0f4 */
12177  SANE_Byte *mvgag;		/*f0e4 *//*f10c */
12178  USHORT wvalues[9];		/*0856 0858 085a 085c 085e 0860 0862 0864 0866 */
12179  SANE_Int imgcount = 0;
12180  /* myoffsetnpixel = f120 */
12181  /* desp f0e8 & f140 */
12182
12183  DBG (DBG_FNC, "+ Calib_AdcOffsetRT(*calibcfg, value=%i)\n", value);
12184
12185  memcpy (&Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
12186  memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams));
12187
12188  channels_per_dot = (calibdata->scancfg.colormode == CM_COLOR) ? 3 : 1;
12189
12190  if (value != 0)
12191    {
12192      pedcg = &calibdata->gain_offset.edcg1[CL_RED];
12193      podcg = &calibdata->gain_offset.odcg1[CL_RED];
12194      poffseteven = &calibcfg->OffsetEven1[CL_RED];
12195      poffsetodd = &calibcfg->OffsetOdd1[CL_RED];
12196    }
12197  else
12198    {
12199      /*c37c */
12200      pedcg = &calibdata->gain_offset.edcg2[CL_RED];
12201      podcg = &calibdata->gain_offset.odcg2[CL_RED];
12202      poffseteven = &calibcfg->OffsetEven2[CL_RED];
12203      poffsetodd = &calibcfg->OffsetOdd2[CL_RED];
12204    }
12205
12206  /*c3a4 */
12207  scancfg.coord.left = calibcfg->OffsetPixelStart;
12208
12209  if (channels_per_dot > 0)
12210    {
12211      for (channel = 0; channel < channels_per_dot; channel++)
12212	{
12213	  avgtarget[channel] = calibcfg->OffsetAvgTarget[channel] << 8;
12214	  if (avgtarget[channel] == 0)
12215	    avgtarget[channel] = 0x80;
12216	}
12217    }
12218
12219  /* set image coordinates to scan */
12220  scancfg.coord.width = calibcfg->OffsetNPixel;
12221  if ((scancfg.coord.width & 1) == 0)
12222    scancfg.coord.width++;
12223
12224  scancfg.bytesperline = channels_per_dot * scancfg.coord.width;
12225  scancfg.coord.top = 1;
12226  scancfg.coord.height = calibcfg->OffsetHeight;
12227  scancfg.depth = 8;
12228
12229  /* allocate memory to store image */
12230  scanbuffer =
12231    (SANE_Byte *) malloc ((scancfg.bytesperline * calibcfg->OffsetHeight) *
12232			  sizeof (SANE_Byte));
12233  if (scanbuffer == NULL)
12234    return ERROR;
12235
12236  /*42ac477 */
12237  scan_options = (linedarlampoff == 1) ? 1 : 0x101;
12238  highresolution = (scancfg.sensorresolution >= 1200) ? TRUE : FALSE;
12239
12240  do
12241    {
12242      if (channels_per_dot > 0)
12243	{
12244	  for (channel = 0; channel < channels_per_dot; channel++)
12245	    dbValues[channel] =
12246	      (40 / (44 - calibdata->gain_offset.vgag2[channel])) * (40 /
12247								     (44 -
12248								      calibdata->
12249								      gain_offset.
12250								      vgag1
12251								      [channel]));
12252	}
12253
12254      /*429c50f */
12255      /* Get Image */
12256      gainmode = Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype);
12257      if (RTS_GetImage
12258	  (dev, Regs, &scancfg, &calibdata->gain_offset, scanbuffer, 0,
12259	   scan_options, gainmode) != OK)
12260	{
12261	  free (scanbuffer);
12262	  return ERROR;
12263	}
12264
12265      /*429c55f */
12266      /* Save retrieved image */
12267      if (RTS_Debug->SaveCalibFile != FALSE)
12268	{
12269	  char fname[30];
12270
12271	  imgcount++;
12272	  if (snprintf (fname, 30, "adcoffset_rt%i.tiff", imgcount) > 0)
12273	    dbg_tiff_save (fname,
12274			   scancfg.coord.width,
12275			   scancfg.coord.height,
12276			   scancfg.depth,
12277			   CM_COLOR,
12278			   scancfg.resolution_x,
12279			   scancfg.resolution_y,
12280			   scanbuffer,
12281			   scancfg.bytesperline * calibcfg->OffsetHeight);
12282	}
12283
12284      /*429c5a5 */
12285      do_loop = FALSE;
12286
12287      if (highresolution == TRUE)
12288	{
12289	  /* f0fc = f0e4 = channel */
12290	  SANE_Int lf104;
12291	  SANE_Int *mydcg;	/*f0f4 */
12292	  USHORT *mywvalue;	/*ebp */
12293
12294	  SANE_Byte is_ready[6];	/*f174 f178 f17c f180 f184 f18c */
12295	  SANE_Byte *ptr_ready;	/*f11c */
12296	  SANE_Int colour;
12297
12298	  for (channel = 0; channel < 6; channel++)
12299	    is_ready[channel] = FALSE;
12300
12301	  if (channels_per_dot <= 0)
12302	    break;
12303
12304	  ptr = scanbuffer;
12305	  mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1;
12306
12307	  for (channel = 0; channel < channels_per_dot; channel++)
12308	    {
12309	      for (lf104 = 0; lf104 < 2; lf104++)
12310		{
12311		  if (lf104 == 0)
12312		    {
12313		      mywvalue = &wvalues[channel];
12314		      mydcg = pedcg;
12315		      ptr_ready = &is_ready[0];
12316		    }
12317		  else
12318		    {
12319		      /*1645 */
12320		      mywvalue = &wvalues[3];
12321		      mydcg = podcg;
12322		      ptr_ready = &is_ready[3];
12323		    }
12324
12325		  /*1658 */
12326		  if (ptr_ready[channel] == FALSE)
12327		    {
12328		      colour = 0;
12329		      if (lf104 < calibcfg->OffsetNPixel)
12330			{
12331			  SANE_Int dot;
12332
12333			  for (dot = 0;
12334			       dot < (calibcfg->OffsetNPixel - lf104 + 1) / 2;
12335			       dot++)
12336			    colour +=
12337			      scanbuffer[mvgag[(lf104 * channels_per_dot)] +
12338					 (dot * (channels_per_dot * 2))];
12339			}
12340
12341		      /*c6b2 */
12342		      colour = colour << 8;
12343		      if (colour == 0)
12344			{
12345			  /*c6b9 */
12346			  if (mydcg[channel] != 0x1ff)
12347			    {
12348			      /*c6d5 */
12349			      mydcg[channel] = 0x1ff;
12350			      do_loop = TRUE;
12351			    }
12352			  else
12353			    ptr_ready[channel] = TRUE;
12354			}
12355		      else
12356			{
12357			  SANE_Int myesi;
12358			  SANE_Int d;
12359
12360			  /*c6e8 */
12361			  if (*mywvalue == 0)
12362			    mywvalue += 2;
12363
12364			  colour /= (calibcfg->OffsetNPixel / 2);
12365			  if (colour >= avgtarget[channel])
12366			    {
12367			      colour -= avgtarget[channel];
12368			      myesi = 0;
12369			    }
12370			  else
12371			    {
12372			      colour = avgtarget[channel] - colour;
12373			      myesi = 1;
12374			    }
12375
12376			  d = mydcg[channel];
12377			  if (d < 0x100)
12378			    d = 0xff - d;
12379
12380			  if (myesi != 0)
12381			    {
12382			      /*c76e */
12383			      if ((d + colour) > 0x1ff)
12384				{
12385				  if (*mvgag > 0)
12386				    {
12387				      *mvgag = *mvgag - 1;
12388				      do_loop = TRUE;
12389				    }
12390				  else
12391				    ptr_ready[channel] = TRUE;	/*c7a0 */
12392				}
12393			      else
12394				d += colour;
12395			    }
12396			  else
12397			    {
12398			      /*c7ad */
12399			      if (colour > d)
12400				{
12401				  if (*mvgag > 0)
12402				    {
12403				      *mvgag = *mvgag - 1;
12404				      do_loop = TRUE;
12405				    }
12406				  else
12407				    ptr_ready[channel] = TRUE;
12408				}
12409			      else
12410				d -= colour;
12411			    }
12412
12413			  /*c7dd */
12414			  mydcg[channel] = (d < 0x100) ? 0x100 - d : d;
12415			}
12416
12417		      dbg_calibtable (&calibdata->gain_offset);
12418		    }
12419		}
12420
12421	      /*c804 */
12422	      mvgag++;
12423	    }
12424	}
12425      else
12426	{
12427	  /* Low resolution */
12428
12429	  SANE_Byte is_ready[3];
12430	  SANE_Int colour;
12431
12432	  /*429c845 */
12433	  for (channel = 0; channel < channels_per_dot; channel++)
12434	    is_ready[channel] = FALSE;
12435
12436	  if (channels_per_dot <= 0)
12437	    break;
12438
12439	  ptr = scanbuffer;
12440	  mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1;
12441
12442	  for (channel = 0; channel < channels_per_dot; channel++)
12443	    {
12444	      if (is_ready[channel] == FALSE)
12445		{
12446		  colour = 0;
12447		  if (calibcfg->OffsetNPixel > 0)
12448		    {
12449		      SANE_Int dot;
12450
12451		      /* Take one channel colour values from offsetnpixel pixels */
12452		      for (dot = 0; dot < calibcfg->OffsetNPixel; dot++)
12453			colour += *(ptr + (dot * channels_per_dot));
12454		    }
12455
12456		  colour <<= 8;
12457		  if (colour == 0)
12458		    {
12459		      if (pedcg[channel] != 0x1ff)
12460			{
12461			  do_loop = TRUE;
12462			  podcg[channel] = 0x1ff;
12463			  pedcg[channel] = 0x1ff;
12464			}
12465		      else
12466			is_ready[channel] = TRUE;
12467		    }
12468		  else
12469		    {
12470		      /*c8f7 */
12471		      SANE_Int myesi;
12472		      SANE_Int op1, op2, op3;
12473
12474		      /* Get colour average */
12475		      colour /= calibcfg->OffsetNPixel;
12476
12477		      /* get absolute difference with avgtarget */
12478		      myesi = (colour > avgtarget[channel]) ? 0 : 1;
12479		      colour = abs (avgtarget[channel] - colour);
12480
12481		      if (scancfg.resolution_x > 600)
12482			{
12483			  /*c923 */
12484			  if (wvalues[channel + 3] == 0)
12485			    wvalues[channel + 3]++;
12486
12487			  if (wvalues[channel] == 0)
12488			    wvalues[channel]++;
12489
12490			  op3 = max (wvalues[channel], wvalues[channel + 3]);
12491			}
12492		      else
12493			{
12494			  if (wvalues[channel + 6] == 0)
12495			    wvalues[channel + 6]++;
12496
12497			  op3 = wvalues[channel + 6];
12498			}
12499
12500		      /*c9d3 */
12501		      op1 = (SANE_Int) (colour / (dbValues[channel] * op3));
12502		      op2 =
12503			(pedcg[channel] <
12504			 0x100) ? pedcg[channel] - 0xff : pedcg[channel];
12505
12506		      if (myesi != 0)
12507			{
12508			  /*c9f5 */
12509			  if (((op2 + op1) & 0xffff) > 0x1ff)
12510			    {
12511			      if (*mvgag != 0)
12512				{
12513				  do_loop = TRUE;
12514				  *mvgag = *mvgag - 1;
12515				}
12516			      else
12517				is_ready[channel] = TRUE;
12518			    }
12519			  else
12520			    op2 += op1;
12521			}
12522		      else
12523			{
12524			  /*ca31 */
12525			  if (op1 > op2)
12526			    {
12527			      if (*mvgag > 0)
12528				{
12529				  do_loop = TRUE;
12530				  *mvgag = *mvgag - 1;
12531				}
12532			      else
12533				is_ready[channel] = TRUE;
12534			    }
12535			  else
12536			    op2 -= op1;
12537			}
12538
12539		      /*ca54 */
12540		      if (op2 < 0x100)
12541			op2 = 0x100 - op2;
12542
12543		      pedcg[channel] = op2;
12544		      podcg[channel] = op2;
12545		    }
12546		}
12547	      /*ca6f */
12548	      ptr++;
12549	      mvgag++;
12550	      dbg_calibtable (&calibdata->gain_offset);
12551	    }
12552	}
12553    }
12554  while (do_loop != FALSE);
12555
12556  /*429cad1 */
12557  for (channel = 0; channel < 3; channel++)
12558    {
12559      poffseteven[channel] =
12560	(pedcg[channel] < 0x100) ? 0xff - pedcg[channel] : pedcg[channel];
12561      poffsetodd[channel] =
12562	(podcg[channel] < 0x100) ? 0xff - podcg[channel] : podcg[channel];
12563    }
12564
12565  free (scanbuffer);
12566
12567  return OK;
12568}
12569
12570static void
12571Calib_LoadCut (struct st_device *dev, struct st_scanparams *scancfg,
12572	       SANE_Int scantype, struct st_calibration_config *calibcfg)
12573{
12574  double mylong;		/*ee78 */
12575  double mylong2;
12576  /**/ SANE_Int channel[3];
12577  SANE_Int a;
12578
12579  cfg_shading_cut_get (dev->sensorcfg->type, scancfg->depth,
12580		       scancfg->resolution_x, scantype, &channel[0],
12581		       &channel[1], &channel[2]);
12582
12583  mylong = 1 << scancfg->depth;
12584
12585  for (a = CL_RED; a <= CL_BLUE; a++)
12586    {
12587      mylong2 = channel[a];
12588      calibcfg->ShadingCut[a] = (mylong * mylong2) * 0.000390625;
12589    }
12590}
12591
12592static SANE_Int
12593Calib_BWShading (struct st_calibration_config *calibcfg,
12594		 struct st_calibration *myCalib, SANE_Int gainmode)
12595{
12596  /*
12597     0603F8E4   0603F90C  |Arg1 = 0603F90C calibcfg
12598     0603F8E8   0603FAAC  |Arg2 = 0603FAAC myCalib
12599     0603F8EC   00000001  \Arg3 = 00000001 gainmode
12600   */
12601
12602  /*falta codigo */
12603
12604  /*silence gcc */
12605  (void) calibcfg;
12606  (void) myCalib;
12607  (void) gainmode;
12608
12609  return OK;
12610}
12611
12612static SANE_Int
12613Calib_WhiteShading_3 (struct st_device *dev,
12614		      struct st_calibration_config *calibcfg,
12615		      struct st_calibration *myCalib, SANE_Int gainmode)
12616{
12617/*
1261805EDF8E0   04F00738  |Arg1 = 04F00738
1261905EDF8E4   05EDF90C  |Arg2 = 05EDF90C calibcfg
1262005EDF8E8   05EDFAAC  |Arg3 = 05EDFAAC myCalib
1262105EDF8EC   00000001  \Arg4 = 00000001 gainmode
12622*/
12623  SANE_Byte *myRegs;		/*f1bc */
12624  struct st_scanparams scancfg;	/*f170 */
12625  SANE_Int myWidth;		/*f14c */
12626  SANE_Int lf168, bytes_per_pixel;
12627  SANE_Int bytes_per_line;
12628  /**/ SANE_Int a;
12629  double lf1a4[3];
12630  SANE_Int otherheight;		/*f150 */
12631  SANE_Int otherheight2;
12632  SANE_Int lf12c;
12633  SANE_Int lf130;
12634  double *buffer1;		/*f138 */
12635  double *buffer2;		/*f144 */
12636  SANE_Byte *scanbuffer;	/*f164 */
12637  SANE_Byte *ptr;		/*f148 */
12638  SANE_Int position;		/*f140 */
12639  SANE_Int lf13c, myHeight;
12640  SANE_Int myESI, myEDI;
12641  SANE_Int channel;		/*f134 */
12642  double myst;
12643  double sumatorio;
12644  SANE_Int rst;
12645
12646  DBG (DBG_FNC, "> Calib_WhiteShading3(*calibcfg, *myCalib, gainmode=%i)\n",
12647       gainmode);
12648
12649  myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
12650  memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
12651  memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams));
12652
12653  Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode);
12654
12655  rst = OK;
12656  scancfg.resolution_y = 200;
12657  switch (scan.scantype)
12658    {
12659    case ST_NORMAL:
12660      /*a184 */
12661      scancfg.coord.left += scan.ser;
12662      scancfg.coord.width &= 0xffff;
12663      break;
12664    case ST_TA:
12665    case ST_NEG:
12666      scancfg.coord.left += scan.ser;
12667      break;
12668    }
12669
12670  /*a11b */
12671  if ((scancfg.coord.width & 1) != 0)
12672    scancfg.coord.width++;
12673
12674  scancfg.coord.top = 1;
12675  scancfg.coord.height = calibcfg->WShadingHeight;
12676
12677  switch (scancfg.colormode)
12678    {
12679    case CM_GRAY:
12680    case CM_LINEART:
12681      myWidth = scancfg.coord.width;
12682      lf168 = 0;
12683      bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth;
12684      bytes_per_pixel = 1;
12685      break;
12686    default:			/* CM_COLOR */
12687      myWidth = scancfg.coord.width * 3;
12688      bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth;
12689      lf168 = (scancfg.samplerate == LINE_RATE) ? scancfg.coord.width : 1;
12690      bytes_per_pixel = (scancfg.samplerate == PIXEL_RATE) ? 3 : 1;
12691      break;
12692    }
12693
12694  /*a1e8 */
12695  scancfg.v157c = bytes_per_line;
12696  scancfg.bytesperline = bytes_per_line;
12697
12698  for (a = 0; a < 3; a++)
12699    lf1a4[a] = (calibcfg->WRef[a] * (1 << scancfg.depth)) >> 8;
12700
12701  /* debug this code because if it's correct, lf130 and lf12c are always 2 */
12702  otherheight = calibcfg->WShadingHeight - 3;
12703  otherheight -= (otherheight - 4);
12704  otherheight2 = otherheight / 2;
12705  otherheight -= otherheight2;
12706  lf130 = otherheight2;
12707  lf12c = otherheight;
12708
12709  buffer1 = (double *) malloc (otherheight * sizeof (double));
12710  if (buffer1 == NULL)
12711    return ERROR;
12712
12713  buffer2 = (double *) malloc (otherheight * sizeof (double));
12714  if (buffer2 == NULL)
12715    {
12716      free (buffer1);
12717      return ERROR;
12718    }
12719
12720  scanbuffer =
12721    (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) *
12722			  sizeof (SANE_Byte));
12723  if (scanbuffer == NULL)
12724    {
12725      free (buffer1);
12726      free (buffer2);
12727      return ERROR;
12728    }
12729
12730  /* Scan image */
12731  myCalib->shading_enabled = FALSE;
12732  rst =
12733    RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, scanbuffer,
12734		  myCalib, 0x20000080, gainmode);
12735
12736  for (a = 0; a < 3; a++)
12737    myCalib->WRef[a] *= ((1 << scancfg.depth) >> 8);
12738
12739  if (rst == ERROR)
12740    {
12741      free (buffer1);
12742      free (buffer2);
12743      free (scanbuffer);
12744      return ERROR;
12745    }
12746
12747  if (scancfg.depth > 8)
12748    {
12749      /*a6d9 */
12750      position = 0;
12751      sumatorio = 0;
12752      if (myWidth > 0)
12753	{
12754	  do
12755	    {
12756	      switch (scancfg.colormode)
12757		{
12758		case CM_GRAY:
12759		case CM_LINEART:
12760		  channel = 0;
12761		  lf13c = position;
12762		  break;
12763		default:	/*CM_COLOR */
12764		  if (scancfg.samplerate == PIXEL_RATE)
12765		    {
12766		      /* pixel rate */
12767		      channel = position % bytes_per_pixel;
12768		      lf13c = position / bytes_per_pixel;
12769		    }
12770		  else
12771		    {
12772		      /* line rate */
12773		      channel = position / lf168;
12774		      lf13c = position % lf168;
12775		    }
12776		  break;
12777		}
12778
12779	      /*a743 */
12780	      if (lf130 > 0)
12781		memset (buffer1, 0, lf130 * sizeof (double));
12782
12783	      /*a761 */
12784	      if (lf12c > 0)
12785		{
12786		  for (a = 0; a < lf12c; a++)
12787		    buffer2[a] = (1 << scancfg.depth) - 1.0;
12788		}
12789
12790	      /*a78f */
12791	      myESI = 0;
12792	      myEDI = 0;
12793	      ptr = scanbuffer + (position * 2);
12794	      myHeight = 0;
12795
12796	      if (otherheight > 0)
12797		{
12798		  do
12799		    {
12800		      myst = 0;
12801		      for (a = 0; a < 4; a++)
12802			myst += data_lsb_get (ptr + (a * (myWidth * 2)), 2);
12803
12804		      myEDI = 0;
12805		      myst = myst * 0.25;
12806		      if (myHeight < (otherheight - 4))
12807			{
12808			  if (myst < buffer2[myESI])
12809			    {
12810			      buffer2[myESI] = myst;
12811			      if (lf12c > 0)
12812				{
12813				  for (a = 0; a < lf12c; a++)
12814				    if (buffer2[myESI] < buffer2[a])
12815				      myESI = a;
12816				}
12817			    }
12818
12819			  /*a820 */
12820			  if (myst >= buffer1[myEDI])
12821			    {
12822			      buffer1[myEDI] = myst;
12823			      if (lf130 > 0)
12824				{
12825				  for (a = 0; a < lf130; a++)
12826				    if (buffer1[myEDI] >= buffer1[a])
12827				      myEDI = a;
12828				}
12829			    }
12830			  sumatorio += myst;
12831			}
12832		      else
12833			{
12834			  /*a853 */
12835			  if (myHeight == (otherheight - 4))
12836			    {
12837			      if (lf12c > 0)
12838				{
12839				  for (a = 0; a < lf12c; a++)
12840				    if (buffer2[myESI] >= buffer2[a])
12841				      myESI = a;
12842				}
12843
12844			      if (lf130 > 0)
12845				{
12846				  for (a = 0; a < lf130; a++)
12847				    if (buffer1[myEDI] < buffer1[a])
12848				      myEDI = a;
12849				}
12850			    }
12851
12852			  /*a895 */
12853			  if (myst >= buffer2[myESI])
12854			    {
12855			      /*a89c */
12856			      sumatorio -= buffer2[myESI];
12857			      sumatorio += myst;
12858			      buffer2[myESI] = myst;
12859			      if (lf12c > 0)
12860				{
12861				  for (a = 0; a < lf12c; a++)
12862				    if (buffer2[myESI] >= buffer2[a])
12863				      myESI = a;
12864				}
12865			    }
12866			  else
12867			    {
12868			      if (myst < buffer1[myEDI])
12869				{
12870				  sumatorio -= buffer1[myEDI];
12871				  sumatorio += myst;
12872				  buffer1[myEDI] = myst;
12873
12874				  if (lf130 > 0)
12875				    {
12876				      for (a = 0; a < lf130; a++)
12877					if (buffer1[myEDI] < buffer1[a])
12878					  myEDI = a;
12879				    }
12880				}
12881			    }
12882			}
12883
12884		      /*a901 */
12885		      ptr += (myWidth * 2);
12886		      myHeight++;
12887		    }
12888		  while (myHeight < otherheight);
12889		}
12890
12891	      /*a924 */
12892	      scancfg.ser = 0;
12893	      scancfg.startpos = otherheight - 4;
12894
12895	      sumatorio = sumatorio / scancfg.startpos;
12896	      if (myCalib->shading_enabled != FALSE)
12897		{
12898		  /*a94a */
12899		  myCalib->white_shading[channel][lf13c] =
12900		    (unsigned short) sumatorio;
12901		}
12902	      else
12903		{
12904		  /*a967 */
12905		  if ((scancfg.colormode != CM_GRAY)
12906		      && (scancfg.colormode != CM_LINEART))
12907		    sumatorio /= lf1a4[channel];
12908		  else
12909		    sumatorio /= lf1a4[scancfg.channel];
12910
12911		  sumatorio = min (sumatorio * 0x4000, 65535);
12912
12913		  if (myRegs[0x1bf] != 0x18)
12914		    myCalib->black_shading[channel][lf13c] |=
12915		      (0x140 -
12916		       ((((myRegs[0x1bf] >> 3) & 3) *
12917			 3) << 6)) & ((int) sumatorio);
12918		  else
12919		    myCalib->white_shading[channel][lf13c] =
12920		      (unsigned short) sumatorio;
12921		}
12922
12923	      /*a9fd */
12924	      position++;
12925	    }
12926	  while (position < myWidth);
12927	}
12928    }
12929  else
12930    {
12931      /*a6d9 */
12932      position = 0;
12933      sumatorio = 0;
12934      if (myWidth > 0)
12935	{
12936	  do
12937	    {
12938	      switch (scancfg.colormode)
12939		{
12940		case CM_GRAY:
12941		case CM_LINEART:
12942		  channel = 0;
12943		  lf13c = position;
12944		  break;
12945		default:	/*CM_COLOR */
12946		  if (scancfg.samplerate == PIXEL_RATE)
12947		    {
12948		      channel = position % bytes_per_pixel;
12949		      lf13c = position / bytes_per_pixel;
12950		    }
12951		  else
12952		    {
12953		      channel = position / lf168;
12954		      lf13c = position % lf168;
12955		    }
12956		  break;
12957		}
12958
12959	      /*a743 */
12960	      if (lf130 > 0)
12961		memset (buffer1, 0, lf130 * sizeof (double));
12962
12963	      /*a761 */
12964	      if (lf12c > 0)
12965		{
12966		  for (a = 0; a < lf12c; a++)
12967		    buffer2[a] = (1 << scancfg.depth) - 1.0;
12968		}
12969
12970	      /*a78f */
12971	      myESI = 0;
12972	      myEDI = 0;
12973	      ptr = scanbuffer + position;
12974	      myHeight = 0;
12975
12976	      if (otherheight > 0)
12977		{
12978		  do
12979		    {
12980		      myst = 0;
12981		      for (a = 0; a < 4; a++)
12982			myst += *(ptr + (a * myWidth));
12983
12984		      myEDI = 0;
12985		      myst *= 0.25;
12986		      if (myHeight < (otherheight - 4))
12987			{
12988			  if (myst < buffer2[myESI])
12989			    {
12990			      buffer2[myESI] = myst;
12991			      if (lf12c > 0)
12992				{
12993				  for (a = 0; a < lf12c; a++)
12994				    if (buffer2[myESI] < buffer2[a])
12995				      myESI = a;
12996				}
12997			    }
12998			  /*a820 */
12999			  if (myst >= buffer1[myEDI])
13000			    {
13001			      buffer1[myEDI] = myst;
13002			      if (lf130 > 0)
13003				{
13004				  for (a = 0; a < lf130; a++)
13005				    if (buffer1[myEDI] >= buffer1[a])
13006				      myEDI = a;
13007				}
13008			    }
13009			  sumatorio += myst;
13010			}
13011		      else
13012			{
13013			  /*a853 */
13014			  if (myHeight == (otherheight - 4))
13015			    {
13016			      if (lf12c > 0)
13017				{
13018				  for (a = 0; a < lf12c; a++)
13019				    if (buffer2[myESI] >= buffer2[a])
13020				      myESI = a;
13021				}
13022
13023			      if (lf130 > 0)
13024				{
13025				  for (a = 0; a < lf130; a++)
13026				    if (buffer1[myEDI] < buffer1[a])
13027				      myEDI = a;
13028				}
13029			    }
13030
13031			  /*a895 */
13032			  if (myst >= buffer2[myESI])
13033			    {
13034			      /*a89c */
13035			      sumatorio -= buffer2[myESI];
13036			      sumatorio += myst;
13037			      buffer2[myESI] = myst;
13038			      if (lf12c > 0)
13039				{
13040				  for (a = 0; a < lf12c; a++)
13041				    if (buffer2[myESI] >= buffer2[a])
13042				      myESI = a;
13043				}
13044			    }
13045			  else
13046			    {
13047			      if (myst < buffer1[myEDI])
13048				{
13049				  sumatorio -= buffer1[myEDI];
13050				  sumatorio += myst;
13051				  buffer1[myEDI] = myst;
13052
13053				  if (lf130 > 0)
13054				    {
13055				      for (a = 0; a < lf130; a++)
13056					if (buffer1[myEDI] < buffer1[a])
13057					  myEDI = a;
13058				    }
13059				}
13060			    }
13061			}
13062		      /*a901 */
13063		      ptr += myWidth;
13064		      myHeight++;
13065		    }
13066		  while (myHeight < otherheight);
13067		}
13068	      /*a924 */
13069	      scancfg.ser = 0;
13070	      scancfg.startpos = otherheight - 4;
13071
13072	      sumatorio /= scancfg.startpos;
13073	      if (myCalib->shading_enabled != FALSE)
13074		{
13075		  /*a94a */
13076		  myCalib->white_shading[channel][lf13c] =
13077		    (unsigned short) sumatorio;
13078		}
13079	      else
13080		{
13081		  /*a967 */
13082		  if ((scancfg.colormode != CM_GRAY)
13083		      && (scancfg.colormode != CM_LINEART))
13084		    sumatorio /= lf1a4[channel];
13085		  else
13086		    sumatorio /= lf1a4[scancfg.channel];
13087
13088		  sumatorio = min (sumatorio * 0x4000, 65535);
13089
13090		  if (myRegs[0x1bf] != 0x18)
13091		    myCalib->black_shading[channel][lf13c] |=
13092		      (0x140 -
13093		       ((((myRegs[0x1bf] >> 3) & 0x03) *
13094			 3) << 6)) & ((int) sumatorio);
13095		  else
13096		    myCalib->white_shading[channel][lf13c] =
13097		      (unsigned short) sumatorio;
13098		}
13099	      /*a9fd */
13100	      position++;
13101	    }
13102	  while (position < myWidth);
13103	}
13104    }
13105
13106  /*aa12 */
13107  if (RTS_Debug->SaveCalibFile != FALSE)
13108    {
13109      dbg_tiff_save ("whiteshading3.tiff",
13110		     scancfg.coord.width,
13111		     scancfg.coord.height,
13112		     scancfg.depth,
13113		     CM_COLOR,
13114		     scancfg.resolution_x,
13115		     scancfg.resolution_y,
13116		     scanbuffer,
13117		     (scancfg.coord.height + 16) * bytes_per_line);
13118    }
13119
13120  free (buffer1);
13121  free (buffer2);
13122  free (scanbuffer);
13123
13124  return OK;
13125}
13126
13127static SANE_Int
13128Calib_BlackShading (struct st_device *dev,
13129		    struct st_calibration_config *calibcfg,
13130		    struct st_calibration *myCalib, SANE_Int gainmode)
13131{
13132  /*
13133     gainmode  f8ec
13134     myCalib   f8e8
13135     calibcfg f8e4
13136   */
13137  SANE_Byte *myRegs;		/*f1bc */
13138  struct st_scanparams scancfg;	/*f020 */
13139  double shadingprediff[6];	/*f08c f094 f09c f0a4 f0ac f0b4 */
13140  double mylong;		/*f018 */
13141  double maxvalue;		/*eff8 */
13142  double sumatorio = 0.0;
13143  double myst;
13144  SANE_Int rst;
13145  SANE_Int a;
13146  SANE_Int mheight;		/*efe0 */
13147  SANE_Int current_line;	/*efe4 */
13148  SANE_Int bytes_per_line;	/*efd8 */
13149  SANE_Int position;		/*lefcc */
13150  SANE_Int leff0, lf010, lefd0;
13151  SANE_Byte *buffer;		/*efd4 */
13152  SANE_Byte buff2[256];		/*F0BC */
13153  SANE_Int buff3[0x8000];
13154  SANE_Byte *ptr;		/*f008 */
13155  SANE_Int my14b4;		/*f008 pisa ptr */
13156  SANE_Int biggest;		/*bx */
13157  SANE_Int lowest;		/*dx */
13158  SANE_Int lefdc;
13159  SANE_Int channel;
13160  SANE_Int smvalues[3];		/*f04c f04e f050 */
13161  double dbvalue[6];		/*lf05c lf060, lf064 lf068, lf06c lf070,
13162				   lf074 lf078, lf07c lf080, lf084 lf088 */
13163
13164  DBG (DBG_FNC, "> Calib_BlackShading(*calibcfg, *myCalib, gainmode=%i)\n",
13165       gainmode);
13166
13167  rst = OK;
13168  myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
13169  memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
13170  memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams));
13171
13172  Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode);
13173
13174  for (a = CL_RED; a <= CL_BLUE; a++)
13175    shadingprediff[a + 3] = calibcfg->BShadingPreDiff[a];
13176
13177  if ((scan.scantype >= ST_NORMAL) && (scan.scantype <= ST_NEG))
13178    scancfg.coord.left += scan.ser;
13179
13180  if ((scancfg.coord.width & 1) != 0)
13181    scancfg.coord.width++;
13182
13183  scancfg.coord.top = 1;
13184  scancfg.depth = 8;
13185  scancfg.coord.height = calibcfg->BShadingHeight;
13186
13187  if (scancfg.colormode != CM_COLOR)
13188    {
13189      bytes_per_line = scancfg.coord.width;
13190      leff0 = 0;
13191      lf010 = 1;
13192    }
13193  else
13194    {
13195      /*876c */
13196      bytes_per_line = scancfg.coord.width * 3;
13197      if (scancfg.samplerate == LINE_RATE)
13198	{
13199	  leff0 = scancfg.coord.width;
13200	  lf010 = 1;
13201	}
13202      else
13203	{
13204	  leff0 = 1;
13205	  lf010 = 3;
13206	}
13207    }
13208
13209  scancfg.v157c = bytes_per_line;
13210  scancfg.bytesperline = bytes_per_line;
13211
13212  mylong = 1 << (16 - scancfg.depth);
13213  if ((myRegs[0x1bf] & 0x18) != 0)
13214    mylong /= 1 << (((myRegs[0x1bf] >> 5) & 3) + 4);
13215
13216  lefd0 =
13217    ((((myRegs[0x1bf] >> 3) & 2) << 8) -
13218     ((((myRegs[0x1bf] >> 3) & 1) * 3) << 6)) - 1;
13219
13220  if (scancfg.depth >= 8)
13221    maxvalue = ((1 << (scancfg.depth - 8)) << 8) - 1;
13222  else
13223    maxvalue = (256 / (1 << (8 - scancfg.depth))) - 1;
13224
13225  Calib_LoadCut (dev, &scancfg, scan.scantype, calibcfg);
13226  for (a = CL_RED; a <= CL_BLUE; a++)
13227    shadingprediff[a] = calibcfg->ShadingCut[a];
13228
13229  if (calibcfg->BShadingOn == -1)
13230    {
13231      SANE_Int b, d;
13232      double e;
13233
13234      for (a = CL_RED; a <= CL_BLUE; a++)
13235	{
13236	  myst = max (shadingprediff[a], 0);
13237	  myst = (maxvalue >= myst) ? shadingprediff[a] : maxvalue;
13238	  shadingprediff[a] = max (myst, 0);
13239	}
13240
13241      b = 0;
13242
13243      while (b < bytes_per_line)
13244	{
13245	  if (scancfg.colormode != CM_COLOR)
13246	    {
13247	      channel = 0;
13248	      d = b;
13249	    }
13250	  else
13251	    {
13252	      if (scancfg.samplerate == PIXEL_RATE)
13253		{
13254		  channel = (b % lf010) & 0xffff;
13255		  d = (b / lf010) & 0xffff;
13256		}
13257	      else
13258		{
13259		  channel = (b / leff0) & 0xffff;
13260		  d = (b % leff0) & 0xffff;
13261		}
13262	    }
13263	  /*89d0 */
13264	  e = min (lefd0, mylong * shadingprediff[channel]);
13265	  myCalib->black_shading[channel][d] |= (unsigned short) e & 0xffff;
13266	  b++;
13267	}
13268
13269      return OK;
13270    }
13271
13272  /* Allocate buffer to read image */
13273  mheight = scancfg.coord.height;
13274  buffer =
13275    (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) *
13276			  sizeof (SANE_Byte));
13277  if (buffer == NULL)
13278    return ERROR;
13279
13280  /* Turn off lamp */
13281  Lamp_Status_Set (dev, NULL, FALSE, FLB_LAMP);
13282  usleep (200 * 1000);
13283
13284  /* Scan image */
13285  myCalib->shading_enabled = FALSE;
13286  rst =
13287    RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, buffer,
13288		  myCalib, 0x101, gainmode);
13289  if (rst == ERROR)
13290    {
13291      /*8ac2 */
13292      free (buffer);
13293      memcpy (&calibdata->Regs, myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte));
13294      free (myRegs);
13295      return ERROR;
13296    }
13297
13298  /* myRegs isn't going to be used anymore */
13299  free (myRegs);
13300  myRegs = NULL;
13301
13302  /* Turn on lamp again */
13303  if (scan.scantype != ST_NORMAL)
13304    {
13305      Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP);
13306      usleep (1000 * 1000);
13307    }
13308  else
13309    Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP);
13310
13311  /* Save buffer */
13312  if (RTS_Debug->SaveCalibFile != FALSE)
13313    {
13314      dbg_tiff_save ("blackshading.tiff",
13315		     scancfg.coord.width,
13316		     scancfg.coord.height,
13317		     scancfg.depth,
13318		     CM_COLOR,
13319		     scancfg.resolution_x,
13320		     scancfg.resolution_y,
13321		     buffer, (scancfg.coord.height + 16) * bytes_per_line);
13322    }
13323
13324  if (scancfg.depth > 8)
13325    {
13326      /*8bb2 */
13327      memset (&dbvalue, 0, 6 * sizeof (double));
13328      position = 0;
13329
13330      if (bytes_per_line > 0)
13331	{
13332	  do
13333	    {
13334	      memset (&buff3, 0, 0x8000 * sizeof (SANE_Int));
13335	      sumatorio = 0;
13336	      ptr = buffer + position;
13337	      current_line = 0;
13338	      biggest = 0;
13339	      lowest = (int) maxvalue;
13340	      /* Toma los valores de una columna */
13341	      if (mheight > 0)
13342		{
13343		  SANE_Int value;
13344		  do
13345		    {
13346		      value = data_lsb_get (ptr, 2);
13347		      biggest = max (biggest, value);
13348		      if (current_line < mheight)
13349			{
13350			  sumatorio += value;
13351			  lowest = min (lowest, value);
13352			  biggest = max (biggest, value);
13353
13354			  buff3[value]++;
13355			}
13356		      else
13357			{
13358			  /*8cab */
13359			  if (value > lowest)
13360			    {
13361			      buff3[lowest]--;
13362			      buff3[value]++;
13363			      sumatorio += value;
13364			      sumatorio -= lowest;
13365
13366			      if (buff3[lowest] != 0)
13367				{
13368				  do
13369				    {
13370				      lowest++;
13371				    }
13372				  while (buff3[lowest] == 0);
13373				}
13374			    }
13375			}
13376		      /*8d0b */
13377		      ptr += (bytes_per_line * 2);
13378		      current_line++;
13379		    }
13380		  while (current_line < mheight);
13381		}
13382	      /*8d27 */
13383	      sumatorio /= mheight;
13384
13385	      if (scancfg.colormode != CM_COLOR)
13386		{
13387		  channel = 0;
13388		  lefdc = position;
13389		}
13390	      else
13391		{
13392		  /*8d5f */
13393		  if (scancfg.samplerate == PIXEL_RATE)
13394		    {
13395		      channel = position % lf010;
13396		      lefdc = (position / lf010) & 0xffff;
13397		    }
13398		  else
13399		    {
13400		      channel = position / leff0;
13401		      lefdc = position % leff0;
13402		    }
13403		}
13404
13405	      dbvalue[channel] += sumatorio;
13406	      if ((scancfg.colormode == CM_GRAY)
13407		  || (scancfg.colormode == CM_LINEART))
13408		sumatorio += shadingprediff[scancfg.channel];
13409	      else
13410		sumatorio += shadingprediff[channel];
13411
13412	      myst = min (max (0, sumatorio), maxvalue);
13413
13414	      dbvalue[channel + 3] = myst;
13415
13416	      if ((calibcfg->BShadingOn == 1) || (calibcfg->BShadingOn == 2))
13417		{
13418		  if (calibcfg->BShadingOn == 2)
13419		    {
13420		      myst -=
13421			calibcfg->BRef[channel] * (1 << (scancfg.depth - 8));
13422		      myst = max (myst, 0);
13423		    }
13424		  /*8e6d */
13425		  myst *= mylong;
13426		  myCalib->black_shading[channel][lefdc] = min (myst, lefd0);
13427		}
13428
13429	      position++;
13430	    }
13431	  while (position < bytes_per_line);
13432	}
13433    }
13434  else
13435    {
13436      /*8eb6 */
13437      memset (&dbvalue, 0, 6 * sizeof (double));
13438      position = 0;
13439
13440      if (bytes_per_line > 0)
13441	{
13442	  do
13443	    {
13444	      memset (&buff2, 0, 256 * sizeof (SANE_Byte));
13445	      sumatorio = 0;
13446	      /* ptr points to the next position of the first line */
13447	      ptr = buffer + position;
13448	      biggest = 0;
13449	      lowest = (int) maxvalue;
13450	      current_line = 0;
13451	      /* Toma los valores de una columna */
13452	      if (mheight > 0)
13453		{
13454		  my14b4 = v14b4;
13455		  do
13456		    {
13457		      biggest = max (biggest, *ptr);
13458
13459		      if (my14b4 == 0)
13460			{
13461			  /*8fd7 */
13462			  if (current_line < mheight)
13463			    {
13464			      sumatorio += *ptr;
13465
13466			      lowest = min (lowest, *ptr);
13467			      biggest = max (biggest, *ptr);
13468
13469			      buff2[*ptr]++;
13470			    }
13471			  else
13472			    {
13473			      /*9011 */
13474			      if (*ptr > lowest)
13475				{
13476				  buff2[lowest]--;
13477				  buff2[*ptr]++;
13478				  sumatorio += *ptr;
13479				  sumatorio -= lowest;
13480
13481				  if (buff2[lowest] != 0)
13482				    {
13483				      do
13484					{
13485					  lowest++;
13486					}
13487				      while (buff2[lowest] == 0);
13488				    }
13489				}
13490			    }
13491			}
13492		      else
13493			sumatorio += *ptr;
13494		      /*9067 */
13495		      /* Point to the next pixel under current line */
13496		      ptr += bytes_per_line;
13497		      current_line++;
13498		    }
13499		  while (current_line < mheight);
13500		}
13501
13502	      /*908a */
13503	      /* Calculates average of each column */
13504	      sumatorio = sumatorio / mheight;
13505
13506	      if (scancfg.colormode != CM_COLOR)
13507		{
13508		  channel = 0;
13509		  lefdc = position;
13510		}
13511	      else
13512		{
13513		  /*90c5 */
13514		  if (scancfg.samplerate == PIXEL_RATE)
13515		    {
13516		      channel = position % lf010;
13517		      lefdc = (position / lf010) & 0xffff;
13518		    }
13519		  else
13520		    {
13521		      /*90fb */
13522		      channel = position / leff0;
13523		      lefdc = position % leff0;
13524		    }
13525		}
13526
13527	      /*911f */
13528	      dbvalue[channel] += sumatorio;
13529	      if ((scancfg.colormode == CM_GRAY)
13530		  || (scancfg.colormode == CM_LINEART))
13531		sumatorio += shadingprediff[scancfg.channel];
13532	      else
13533		sumatorio += shadingprediff[channel];
13534
13535	      /*9151 */
13536	      myst = min (max (0, sumatorio), maxvalue);
13537
13538	      /*9198 */
13539	      if (position >= 3)
13540		{
13541		  double myst2;
13542
13543		  myst -= dbvalue[channel + 3];
13544		  myst2 = myst;
13545		  myst = min (myst, shadingprediff[channel + 3]);
13546
13547		  my14b4 = -shadingprediff[channel + 3];
13548		  if (myst >= my14b4)
13549		    myst = min (myst2, shadingprediff[channel + 3]);
13550		  else
13551		    myst = my14b4;
13552
13553		  myst += dbvalue[channel + 3];
13554		}
13555
13556	      /*9203 */
13557	      dbvalue[channel + 3] = myst;
13558
13559	      switch (calibcfg->BShadingOn)
13560		{
13561		case 1:
13562		  myCalib->black_shading[channel][lefdc] |=
13563		    (unsigned short) (((int) myst & 0xff) << 8) & 0xffff;
13564		  break;
13565		case 2:
13566		  /*9268 */
13567		  my14b4 =
13568		    calibcfg->BRef[channel] / (1 << (8 - scancfg.depth));
13569		  myst -= my14b4;
13570		  myst = max (myst, 0);
13571		  myst *= mylong;
13572		  myCalib->black_shading[channel][lefdc] = min (myst, lefd0);
13573		  break;
13574		}
13575
13576	      /*92d8 */
13577	      position++;
13578	    }
13579	  while (position < bytes_per_line);
13580	}
13581    }
13582
13583  /*9306 */
13584  if (calibcfg->BShadingOn == -2)
13585    {
13586      for (a = 0; a < 3; a++)
13587	{
13588	  dbvalue[a] =
13589	    (dbvalue[a] / scancfg.coord.width) + calibcfg->ShadingCut[a];
13590	  if (dbvalue[a] < 0)
13591	    dbvalue[a] = 0;
13592	  smvalues[a] = min ((int) (dbvalue[a] + 0.5) & 0xffff, maxvalue);
13593	}
13594
13595      if (scancfg.coord.width > 0)
13596	{
13597	  SANE_Int b, c;
13598
13599	  for (c = 0; c < scancfg.coord.width; c++)
13600	    for (b = 0; b < 3; b++)
13601	      myCalib->black_shading[b][c] |=
13602		(unsigned short) min (smvalues[b] * mylong, lefd0);
13603	}
13604    }
13605  /*9425 */
13606  free (buffer);
13607
13608  return OK;
13609}
13610
13611static SANE_Int
13612Calibration (struct st_device *dev, SANE_Byte * Regs,
13613	     struct st_scanparams *scancfg, struct st_calibration *myCalib,
13614	     SANE_Int value)
13615{
13616  /*//SANE_Int Calibration([fa20]char *Regs, [fa24]struct st_scanparams *scancfg, [fa28]struct st_calibration myCalib, [fa2c]SANE_Int value)
13617   */
13618
13619  struct st_calibration_config calibcfg;	/* f90c */
13620  SANE_Int a;
13621  SANE_Byte gainmode;
13622  SANE_Int lf900;
13623
13624  DBG (DBG_FNC, "> Calibration\n");
13625  dbg_ScanParams (scancfg);
13626
13627  (void) value;			/*silence gcc */
13628
13629  memcpy (&calibdata->Regs, Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN);
13630
13631  /*4213be8 */
13632  memset (&calibcfg, 0x30, sizeof (struct st_calibration_config));
13633  Calib_LoadConfig (dev, &calibcfg, scan.scantype, scancfg->resolution_x,
13634		    scancfg->depth);
13635
13636  memset (&calibdata->gain_offset, 0, sizeof (struct st_gain_offset));	/*[42b3654] */
13637  for (a = CL_RED; a <= CL_BLUE; a++)
13638    {
13639      myCalib->WRef[a] = calibcfg.WRef[a];
13640
13641      calibdata->gain_offset.edcg1[a] = 256;
13642      calibdata->gain_offset.odcg1[a] = 256;
13643      calibdata->gain_offset.vgag1[a] = 4;
13644      calibdata->gain_offset.vgag2[a] = 4;
13645
13646      /*3654|3656|3658
13647         365a|365c|365e
13648         3660|3662|3664
13649         3666|3668|366a
13650         366c|366d|366e
13651         366f|3670|3671
13652         3672|3673|3674 */
13653    }
13654
13655  memcpy (&calibdata->scancfg, scancfg, sizeof (struct st_scanparams));
13656  gainmode = Lamp_GetGainMode (dev, scancfg->resolution_x, scan.scantype);	/* [lf904] = 1 */
13657
13658  /* 3cf3 */
13659  myCalib->first_position = 1;
13660  myCalib->shading_type = 0;
13661  if (calibdata->scancfg.colormode == CM_LINEART)
13662    {
13663      calibdata->scancfg.colormode = CM_GRAY;
13664      calibcfg.GainTargetFactor = 1.3;
13665    }
13666
13667  lf900 = OK;
13668  if (calibcfg.CalibPAGOn != 0)
13669    {
13670      if (Calib_PAGain (dev, &calibcfg, gainmode) != 0)
13671	lf900 = ERROR;
13672    /*ERROR*/}
13673  else
13674    {
13675      /*3da7 */
13676      if ((calibdata->scancfg.colormode != CM_GRAY)
13677	  && (calibdata->scancfg.colormode != CM_LINEART))
13678	{
13679	  for (a = CL_RED; a <= CL_BLUE; a++)
13680	    calibdata->gain_offset.pag[a] = calibcfg.PAG[a];
13681	}
13682      else
13683	{
13684	  /* 3dd3 */
13685	  /* Default PAGain */
13686	  if (calibdata->scancfg.channel > 2)
13687	    calibdata->scancfg.channel = 0;
13688
13689	  for (a = CL_RED; a <= CL_BLUE; a++)
13690	    calibdata->gain_offset.pag[a] =
13691	      calibcfg.PAG[calibdata->scancfg.channel];
13692	}
13693    }
13694
13695  /* 3e01 */
13696  if (calibcfg.CalibOffset10n != 0)	  /*==2*/
13697    {
13698      /*v14b4=1  offset[CL_RED]=0x174  offset[CL_GREEN]=0x16d  offset[CL_BLUE]=0x160 */
13699      if ((v14b4 != 0) && (offset[CL_RED] != 0) && (offset[CL_GREEN] != 0)
13700	  && (offset[CL_BLUE] != 0))
13701	{
13702	  for (a = CL_RED; a <= CL_BLUE; a++)
13703	    {
13704	      calibdata->gain_offset.edcg1[a] = offset[a];
13705	      calibdata->gain_offset.odcg1[a] = offset[a];
13706	    }
13707	}
13708      else
13709	{
13710	  /* 3e84 */
13711	  if ((calibcfg.CalibOffset10n > 0) && (calibcfg.CalibOffset10n < 4))
13712	    {
13713	      /*if (calibcfg.CalibOffset10n != 0) */
13714	      if (calibcfg.CalibOffset10n == 3)
13715		{
13716		  lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 1);
13717		}
13718	      else
13719		{
13720		  /* 3eb2 */
13721		  /*falta codigo */
13722		}
13723	    }
13724	}
13725    }
13726  else
13727    {
13728      /* 3faf */
13729      for (a = CL_RED; a <= CL_BLUE; a++)
13730	{
13731	  calibdata->gain_offset.edcg1[a] =
13732	    abs (calibcfg.OffsetEven1[a] - 0x100);
13733	  calibdata->gain_offset.odcg1[a] =
13734	    abs (calibcfg.OffsetOdd1[a] - 0x100);
13735	}
13736    }
13737
13738  /* 3f13 3f0b */
13739  if ((gainmode != 0) && (calibcfg.CalibGain10n != 0))
13740    {
13741      /*gain[CL_RED]=0x17 gain[CL_GREEN]=0x12 gain[CL_BLUE]=0x17 */
13742      if ((v14b4 != 0) && (gain[CL_RED] != 0) && (gain[CL_GREEN] != 0)
13743	  && (gain[CL_BLUE] != 0))
13744	{
13745	  for (a = CL_RED; a <= CL_BLUE; a++)
13746	    calibdata->gain_offset.vgag1[a] = gain[a];
13747	}
13748      else
13749	{
13750	  /*4025 */
13751	  lf900 = Calib_AdcGain (dev, &calibcfg, 1, gainmode);
13752
13753	  if ((v14b4 != 0) && (lf900 == OK))
13754	    GainOffset_Save (dev, &calibdata->gain_offset.edcg1[0],
13755			     &calibdata->gain_offset.vgag1[0]);
13756	}
13757    }
13758  else
13759    {
13760      /*4089 */
13761      for (a = CL_RED; a <= CL_BLUE; a++)
13762	calibdata->gain_offset.vgag1[a] = calibcfg.Gain1[a];
13763    }
13764
13765  /*40a5 */
13766  if ((gainmode != 0) && (calibcfg.CalibOffset20n != 0))
13767    {
13768      switch (calibcfg.CalibOffset20n)
13769	{
13770	case 3:
13771	  lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 2);
13772	  break;
13773	}
13774      /*4140 */
13775      /*falta codigo */
13776    }
13777  else
13778    {
13779      /*4162 */
13780      for (a = CL_RED; a <= CL_BLUE; a++)
13781	{
13782	  calibdata->gain_offset.edcg2[a] =
13783	    abs (calibcfg.OffsetEven2[a] - 0x40);
13784	  calibdata->gain_offset.odcg2[a] =
13785	    abs (calibcfg.OffsetOdd2[a] - 0x40);
13786	}
13787    }
13788
13789  /*41d6 */
13790  if ((gainmode != 0) && (calibcfg.CalibGain20n != 0))
13791    {
13792      lf900 = Calib_AdcGain (dev, &calibcfg, 0, gainmode);
13793    }
13794  else
13795    {
13796      /*423c */
13797      for (a = CL_RED; a <= CL_BLUE; a++)
13798	calibdata->gain_offset.vgag2[a] = calibcfg.Gain2[a];
13799    }
13800
13801  /*4258 */
13802  if (calibcfg.TotShading != 0)
13803    {
13804      lf900 = Calib_BWShading (&calibcfg, myCalib, gainmode);
13805      /*falta codigo */
13806    }
13807  else
13808    {
13809      /*428f */
13810      if (gainmode != 0)
13811	{
13812	  if (calibcfg.BShadingOn != 0)
13813	    lf900 = Calib_BlackShading (dev, &calibcfg, myCalib, gainmode);
13814
13815	  /*42fd */
13816	  if ((lf900 != ERROR) && (calibcfg.WShadingOn != 0))
13817	    {
13818	      switch (calibcfg.WShadingOn)
13819		{
13820		default:
13821		  break;
13822		case 3:
13823		  lf900 =
13824		    Calib_WhiteShading_3 (dev, &calibcfg, myCalib, gainmode);
13825		  break;
13826		case 2:
13827		  break;
13828		}
13829	    }
13830	  else
13831	    myCalib->shading_enabled = FALSE;
13832	}
13833      else
13834	myCalib->shading_enabled = FALSE;
13835    }
13836
13837  /*43ca */
13838  memcpy (&myCalib->gain_offset, &calibdata->gain_offset,
13839	  sizeof (struct st_gain_offset));
13840  memcpy (&mitabla2, &calibdata->gain_offset, sizeof (struct st_gain_offset));
13841
13842  /*4424 */
13843  /* Park home after calibration */
13844  if (get_value (SCANINFO, PARKHOMEAFTERCALIB, TRUE, FITCALIBRATE) == FALSE)
13845    scan.ler -= calibcfg.WShadingHeight;
13846  else
13847    Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
13848
13849  return OK;
13850}
13851
13852/*static void show_diff(struct st_device *dev, SANE_Byte *original)
13853{
13854	SANE_Byte *buffer = (SANE_Byte *)malloc(RT_BUFFER_LEN * sizeof(SANE_Byte));
13855	SANE_Int a;
13856
13857	if ((buffer == NULL)||(original == NULL))
13858		return;
13859
13860	if (RTS_ReadRegs(dev->usb_handle, buffer) != OK)
13861	{
13862		free(buffer);
13863		return;
13864	}
13865
13866	for (a = 0; a < RT_BUFFER_LEN; a++)
13867	{
13868		if ((original[a] & 0xff) != (buffer[a] & 0xff))
13869		{
13870			printf("%5i: %i -> %i\n", a, original[a] & 0xff, buffer[a] & 0xff);
13871			original[a] = buffer[a] & 0xff;
13872		}
13873	}
13874
13875	free(buffer);
13876} */
13877
13878static SANE_Int
13879Load_Constrains (struct st_device *dev)
13880{
13881  SANE_Int rst = ERROR;
13882
13883  if (dev->constrains != NULL)
13884    Free_Constrains (dev);
13885
13886  DBG (DBG_FNC, "> Load_Constrains\n");
13887
13888  dev->constrains =
13889    (struct st_constrains *) malloc (sizeof (struct st_constrains));
13890  if (dev->constrains != NULL)
13891    {
13892      cfg_constrains_get (dev->constrains);
13893      rst = OK;
13894    }
13895
13896  return rst;
13897}
13898
13899static SANE_Int
13900Constrains_Check (struct st_device *dev, SANE_Int Resolution,
13901		  SANE_Int scantype, struct st_coords *mycoords)
13902{
13903  /*
13904     Constrains:
13905     100 dpi   850 x  1170   | 164 x 327
13906     300 dpi  2550 x  3510
13907     600 dpi  5100 x  7020
13908     1200 dpi 10200 x 14040
13909   */
13910
13911  SANE_Int rst = ERROR;
13912
13913  if (dev->constrains != NULL)
13914    {
13915      struct st_coords coords;
13916      struct st_coords *mc;
13917
13918      if ((scantype < ST_NORMAL) || (scantype > ST_NEG))
13919	scantype = ST_NORMAL;
13920
13921      switch (scantype)
13922	{
13923	case ST_TA:
13924	  mc = &dev->constrains->slide;
13925	  break;
13926	case ST_NEG:
13927	  mc = &dev->constrains->negative;
13928	  break;
13929	default:
13930	  mc = &dev->constrains->reflective;
13931	  break;
13932	}
13933
13934      coords.left = MM_TO_PIXEL (mc->left, Resolution);
13935      coords.width = MM_TO_PIXEL (mc->width, Resolution);
13936      coords.top = MM_TO_PIXEL (mc->top, Resolution);
13937      coords.height = MM_TO_PIXEL (mc->height, Resolution);
13938
13939      /* Check left and top */
13940      if (mycoords->left < 0)
13941	mycoords->left = 0;
13942
13943      mycoords->left += coords.left;
13944
13945      if (mycoords->top < 0)
13946	mycoords->top = 0;
13947
13948      mycoords->top += coords.top;
13949
13950      /* Check width and height */
13951      if ((mycoords->width < 0) || (mycoords->width > coords.width))
13952	mycoords->width = coords.width;
13953
13954      if ((mycoords->height < 0) || (mycoords->height > coords.height))
13955	mycoords->height = coords.height;
13956
13957      rst = OK;
13958    }
13959
13960  DBG (DBG_FNC,
13961       "> Constrains_Check: Source=%s, Res=%i, LW=(%i,%i), TH=(%i,%i): %i\n",
13962       dbg_scantype (scantype), Resolution, mycoords->left, mycoords->width,
13963       mycoords->top, mycoords->height, rst);
13964
13965  return rst;
13966}
13967
13968static struct st_coords *
13969Constrains_Get (struct st_device *dev, SANE_Byte scantype)
13970{
13971  static struct st_coords *rst = NULL;
13972
13973  if (dev->constrains != NULL)
13974    {
13975      switch (scantype)
13976	{
13977	case ST_TA:
13978	  rst = &dev->constrains->slide;
13979	  break;
13980	case ST_NEG:
13981	  rst = &dev->constrains->negative;
13982	  break;
13983	default:
13984	  rst = &dev->constrains->reflective;
13985	  break;
13986	}
13987    }
13988
13989  return rst;
13990}
13991
13992static void
13993Free_Constrains (struct st_device *dev)
13994{
13995  DBG (DBG_FNC, "> Free_Constrains\n");
13996
13997  if (dev->constrains != NULL)
13998    {
13999      free (dev->constrains);
14000      dev->constrains = NULL;
14001    }
14002}
14003
14004static void
14005RTS_DebugInit ()
14006{
14007  /* Default values */
14008  RTS_Debug->dev_model = HP3970;
14009
14010  RTS_Debug->DumpShadingData = FALSE;
14011  RTS_Debug->SaveCalibFile = FALSE;
14012  RTS_Debug->ScanWhiteBoard = FALSE;
14013  RTS_Debug->EnableGamma = TRUE;
14014  RTS_Debug->use_fixed_pwm = TRUE;
14015  RTS_Debug->dmatransfersize = 0x80000;
14016  RTS_Debug->dmasetlength = 0x7c0000;
14017  RTS_Debug->dmabuffersize = 0x400000;
14018  RTS_Debug->usbtype = -1;
14019
14020  /* Lamp settings */
14021  RTS_Debug->overdrive_flb = 10000;	/* msecs */
14022  RTS_Debug->overdrive_ta = 10000;	/* msecs */
14023
14024  RTS_Debug->warmup = TRUE;
14025
14026  /* Calibration settings */
14027  RTS_Debug->calibrate = FALSE;
14028  RTS_Debug->wshading = TRUE;
14029}
14030
14031static void
14032RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *hwdcfg)
14033{
14034  DBG (DBG_FNC, "> RTS_Setup_Gamma(*Regs, *hwdcfg)\n");
14035
14036  if ((hwdcfg != NULL) && (Regs != NULL))
14037    {
14038      if (hwdcfg->use_gamma_tables != FALSE)
14039	{
14040	  SANE_Int table_size;
14041
14042	  /* set set table size */
14043	  data_bitset (&Regs[0x1d0], 0x0f, hwdcfg->gamma_tablesize);
14044
14045	  /* enable gamma correction */
14046	  data_bitset (&Regs[0x1d0], 0x40, 1);
14047
14048
14049	  switch (Regs[0x1d0] & 0x0c)
14050	    {
14051	    case 0:
14052	      table_size = (Regs[0x1d0] & 1) | 0x0100;
14053	      break;
14054	    case 4:
14055	      table_size = (Regs[0x1d0] & 1) | 0x0400;
14056	      break;
14057	    case 8:
14058	      table_size = (Regs[0x1d0] & 1) | 0x1000;
14059	      break;
14060	    default:
14061	      table_size = hwdcfg->startpos & 0xffff;
14062	      break;
14063	    }
14064
14065	  /* 5073 */
14066	  /* points to red gamma table */
14067	  data_wide_bitset (&Regs[0x1b4], 0x3fff, 0);
14068
14069	  /* points to green gamma table */
14070	  data_wide_bitset (&Regs[0x1b6], 0x3fff, table_size);
14071
14072	  /* points to blue gamma table */
14073	  data_wide_bitset (&Regs[0x1b8], 0x3fff, table_size * 2);
14074
14075	  v15f8 = (((table_size * 3) + 15) / 16) & 0xffff;
14076	}
14077      else
14078	{
14079	  /* disable gamma correction */
14080	  data_bitset (&Regs[0x1d0], 0x40, 0);
14081	  v15f8 = 0;
14082	}
14083    }
14084}
14085
14086static SANE_Int
14087RTS_USBType (struct st_device *dev)
14088{
14089  /* Gets USB type of this scanner */
14090
14091  SANE_Int rst = ERROR;
14092  SANE_Byte data;
14093
14094  DBG (DBG_FNC, "+ RTS_USBType\n");
14095
14096  if (Read_Byte (dev->usb_handle, 0xfe11, &data) == OK)
14097    rst = (data & 1);
14098
14099  DBG (DBG_FNC, "- RTS_USBType(void): %s\n",
14100       (rst == USB11) ? "USB1.1" : "USB2.0");
14101
14102  return rst;
14103}
14104
14105static SANE_Int
14106Init_Vars (void)
14107{
14108  SANE_Int rst = OK;
14109
14110  hp_gamma = malloc (sizeof (struct st_gammatables));
14111  if (hp_gamma != NULL)
14112    memset (hp_gamma, 0, sizeof (struct st_gammatables));
14113  else
14114    rst = ERROR;
14115
14116  if (rst == OK)
14117    {
14118      RTS_Debug = malloc (sizeof (struct st_debug_opts));
14119      if (RTS_Debug != NULL)
14120	memset (RTS_Debug, 0, sizeof (struct st_debug_opts));
14121      else
14122	rst = ERROR;
14123    }
14124
14125  if (rst == OK)
14126    {
14127      default_gain_offset = malloc (sizeof (struct st_gain_offset));
14128      if (default_gain_offset != NULL)
14129	memset (default_gain_offset, 0, sizeof (struct st_gain_offset));
14130      else
14131	rst = ERROR;
14132    }
14133
14134  if (rst == OK)
14135    {
14136      calibdata = malloc (sizeof (struct st_calibration_data));
14137      if (calibdata != NULL)
14138	memset (calibdata, 0, sizeof (struct st_calibration_data));
14139      else
14140	rst = ERROR;
14141    }
14142
14143  if (rst == OK)
14144    {
14145      wshading = malloc (sizeof (struct st_shading));
14146      if (wshading != NULL)
14147	memset (wshading, 0, sizeof (struct st_shading));
14148      else
14149	rst = ERROR;
14150    }
14151
14152  waitforpwm = TRUE;
14153
14154  use_gamma_tables = TRUE;
14155
14156  if (rst == OK)
14157    RTS_DebugInit ();
14158  else
14159    Free_Vars ();
14160
14161  return rst;
14162}
14163
14164static void
14165Free_Vars (void)
14166{
14167  if (RTS_Debug != NULL)
14168    {
14169      free (RTS_Debug);
14170      RTS_Debug = NULL;
14171    }
14172
14173  if (hp_gamma != NULL)
14174    {
14175      free (hp_gamma);
14176      hp_gamma = NULL;
14177    }
14178
14179  if (calibdata != NULL)
14180    {
14181      free (calibdata);
14182      calibdata = NULL;
14183    }
14184
14185  if (wshading != NULL)
14186    {
14187      if (wshading->rates != NULL)
14188	free (wshading->rates);
14189
14190      free (wshading);
14191      wshading = NULL;
14192    }
14193
14194  if (default_gain_offset != NULL)
14195    {
14196      free (default_gain_offset);
14197      default_gain_offset = NULL;
14198    }
14199
14200}
14201
14202static SANE_Int
14203Chipset_Reset (struct st_device *dev)
14204{
14205  SANE_Int rst;
14206
14207  DBG (DBG_FNC, "+ Chipset_Reset:\n");
14208
14209  /* I've found two ways to reset chipset. Next one will stay commented
14210     rst = ERROR;
14211     if (Read_Byte(dev->usb_handle, 0xe800, &data) == OK)
14212     {
14213     data |= 0x20;
14214     if (Write_Byte(dev->usb_handle, 0xe800, data) == OK)
14215     {
14216     data &= 0xdf;
14217     rst = Write_Byte(dev->usb_handle, 0xe800, data);
14218     }
14219     }
14220   */
14221
14222  rst = IWrite_Buffer (dev->usb_handle, 0x0000, NULL, 0, 0x0801);
14223
14224  DBG (DBG_FNC, "- Chipset_Reset: %i\n", rst);
14225
14226  return rst;
14227}
14228
14229static SANE_Int
14230RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int size,
14231		     SANE_Int options)
14232{
14233  SANE_Int rst = ERROR;
14234  SANE_Byte buffer[6];
14235
14236  DBG (DBG_FNC,
14237       "+ RTS_DMA_Enable_Read(dmacs=0x%04x, size=%i, options=0x%06x)\n",
14238       dmacs, size, options);
14239
14240  data_msb_set (&buffer[0], options, 3);
14241
14242  /* buffer size divided by 2 (words count) */
14243  data_lsb_set (&buffer[3], size / 2, 3);
14244
14245  rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0400);
14246
14247  DBG (DBG_FNC, "- RTS_DMA_Enable_Read: %i\n", rst);
14248
14249  return rst;
14250}
14251
14252static SANE_Int
14253RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int size,
14254		      SANE_Int options)
14255{
14256  SANE_Int rst = ERROR;
14257  SANE_Byte buffer[6];
14258
14259  DBG (DBG_FNC,
14260       "+ RTS_DMA_Enable_Write(dmacs=0x%04x, size=%i, options=0x%06x)\n",
14261       dmacs, size, options);
14262
14263  data_msb_set (&buffer[0], options, 3);
14264
14265  /* buffer size divided by 2 (words count) */
14266  data_lsb_set (&buffer[3], size / 2, 3);
14267
14268  rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0401);
14269
14270  DBG (DBG_FNC, "- RTS_DMA_Enable_Write: %i\n", rst);
14271
14272  return rst;
14273}
14274
14275static SANE_Int
14276RTS_DMA_Cancel (struct st_device *dev)
14277{
14278  SANE_Int rst;
14279
14280  DBG (DBG_FNC, "+ RTS_DMA_Cancel:\n");
14281
14282  rst = IWrite_Word (dev->usb_handle, 0x0000, 0, 0x0600);
14283
14284  DBG (DBG_FNC, "- RTS_DMA_Cancel: %i\n", rst);
14285
14286  return rst;
14287}
14288
14289static SANE_Int
14290RTS_DMA_Reset (struct st_device *dev)
14291{
14292  SANE_Int rst;
14293
14294  DBG (DBG_FNC, "+ RTS_DMA_Reset:\n");
14295
14296  rst = IWrite_Word (dev->usb_handle, 0x0000, 0x0000, 0x0800);
14297
14298  DBG (DBG_FNC, "- RTS_DMA_Reset: %i\n", rst);
14299
14300  return rst;
14301}
14302
14303static SANE_Int
14304RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data)
14305{
14306  SANE_Int rst;
14307
14308  DBG (DBG_FNC, "+ RTS_EEPROM_WriteByte(address=%04x, data=%i):\n", address,
14309       data);
14310
14311  rst = IWrite_Byte (usb_handle, address, data, 0x200, 0x200);
14312
14313  DBG (DBG_FNC, "- RTS_EEPROM_WriteByte: %i\n", rst);
14314
14315  return rst;
14316}
14317
14318static SANE_Int
14319RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, SANE_Int * data)
14320{
14321  SANE_Int rst;
14322
14323  DBG (DBG_FNC, "+ RTS_EEPROM_ReadWord(address=%04x, data):\n", address);
14324
14325  rst = IRead_Word (usb_handle, address, data, 0x200);
14326
14327  DBG (DBG_FNC, "- RTS_EEPROM_ReadWord: %i\n", rst);
14328
14329  return rst;
14330}
14331
14332static SANE_Int
14333RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address,
14334		     SANE_Byte * data)
14335{
14336  SANE_Int rst;
14337
14338  DBG (DBG_FNC, "+ RTS_EEPROM_ReadByte(address=%04x, data):\n", address);
14339
14340  rst = IRead_Byte (usb_handle, address, data, 0x200);
14341
14342  DBG (DBG_FNC, "- RTS_EEPROM_ReadByte: %i\n", rst);
14343
14344  return rst;
14345}
14346
14347static SANE_Int
14348RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, SANE_Int data)
14349{
14350  SANE_Int rst;
14351
14352  DBG (DBG_FNC, "+ RTS_EEPROM_WriteWord(address=%04x, data=%i):\n", address,
14353       data);
14354
14355  rst = IWrite_Word (usb_handle, address, data, 0x0200);
14356
14357  DBG (DBG_FNC, "- RTS_EEPROM_WriteWord: %i\n", rst);
14358
14359  return rst;
14360}
14361
14362static SANE_Int
14363RTS_EEPROM_ReadInteger (USB_Handle usb_handle, SANE_Int address,
14364			SANE_Int * data)
14365{
14366  SANE_Int rst;
14367
14368  DBG (DBG_FNC, "+ RTS_EEPROM_ReadInteger(address=%04x, data):\n", address);
14369
14370  rst = IRead_Integer (usb_handle, address, data, 0x200);
14371
14372  DBG (DBG_FNC, "- RTS_EEPROM_ReadInteger: %i\n", rst);
14373
14374  return rst;
14375}
14376
14377static SANE_Int
14378RTS_EEPROM_WriteInteger (USB_Handle usb_handle, SANE_Int address,
14379			 SANE_Int data)
14380{
14381  SANE_Int rst;
14382
14383  DBG (DBG_FNC, "+ RTS_EEPROM_WriteInteger(address=%04x, data):\n", address);
14384
14385  rst = IWrite_Integer (usb_handle, address, data, 0x200);
14386
14387  DBG (DBG_FNC, "- RTS_EEPROM_WriteInteger: %i\n", rst);
14388
14389  return rst;
14390}
14391
14392static SANE_Int
14393RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, SANE_Int address,
14394			SANE_Byte * data, SANE_Int size)
14395{
14396  SANE_Int rst;
14397
14398  DBG (DBG_FNC, "+ RTS_EEPROM_WriteBuffer(address=%04x, data, size=%i):\n",
14399       address, size);
14400
14401  rst = IWrite_Buffer (usb_handle, address, data, size, 0x200);
14402
14403  DBG (DBG_FNC, "- RTS_EEPROM_WriteBuffer: %i\n", rst);
14404
14405  return rst;
14406}
14407
14408static void
14409WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, SANE_Int size,
14410		  SANE_Int depth)
14411{
14412  if ((wshading->rates != NULL) && (chnptr != NULL))
14413    {
14414      if (*chnptr < wshading->count)
14415	{
14416	  double maxvalue, chncolor;
14417	  SANE_Int chnsize;
14418	  SANE_Int pos;
14419	  SANE_Int icolor;
14420
14421	  maxvalue = (1 << depth) - 1;
14422	  chnsize = (depth > 8) ? 2 : 1;
14423
14424	  pos = 0;
14425	  while (pos < size)
14426	    {
14427	      /* get channel color */
14428	      chncolor = data_lsb_get (buffer + pos, chnsize);
14429
14430	      /* apply shading coefficient */
14431	      chncolor *= wshading->rates[*chnptr];
14432
14433	      /* care about limits */
14434	      chncolor = min (chncolor, maxvalue);
14435
14436	      /* save color */
14437	      icolor = chncolor;
14438	      data_lsb_set (buffer + pos, icolor, chnsize);
14439
14440	      *chnptr = *chnptr + 1;
14441	      if (*chnptr >= wshading->count)
14442		*chnptr = 0;
14443
14444	      pos += chnsize;
14445	    }
14446	}
14447    }
14448}
14449
14450static SANE_Int
14451WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs,
14452		    struct st_calibration *myCalib,
14453		    struct st_scanparams *scancfg)
14454{
14455  struct st_calibration_config *calibcfg;
14456  struct st_gain_offset myCalibTable;
14457  struct st_scanparams *myscancfg;
14458  SANE_Byte *myRegs;		/*f1bc */
14459  SANE_Int bytes_per_line;
14460  /**/ SANE_Int x, y, a, C;
14461  SANE_Byte *pattern;		/*f164 */
14462  double sumatorio;
14463  SANE_Int gainmode;
14464  SANE_Int rst;
14465  SANE_Byte *avg_colors;
14466
14467  DBG (DBG_FNC, "> WShading_Calibrate(*myCalib)\n");
14468
14469  memset (&myCalibTable, 0, sizeof (struct st_gain_offset));
14470  for (C = CL_RED; C <= CL_BLUE; C++)
14471    {
14472      myCalibTable.pag[C] = 3;
14473      myCalibTable.vgag1[C] = 4;
14474      myCalibTable.vgag2[C] = 4;
14475    }
14476
14477  calibcfg =
14478    (struct st_calibration_config *)
14479    malloc (sizeof (struct st_calibration_config));
14480  memset (calibcfg, 0x30, sizeof (struct st_calibration_config));
14481
14482  myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams));
14483  memcpy (myscancfg, scancfg, sizeof (struct st_scanparams));
14484
14485  myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
14486  memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
14487
14488  Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x,
14489		    myscancfg->depth);
14490  gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype);
14491
14492  Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode);
14493
14494  rst = OK;
14495
14496  switch (scan.scantype)
14497    {
14498    case ST_NORMAL:
14499      /*a184 */
14500      myscancfg->coord.left += scan.ser;
14501      myscancfg->coord.width &= 0xffff;
14502      break;
14503    case ST_TA:
14504    case ST_NEG:
14505      myscancfg->coord.left += scan.ser;
14506      break;
14507    }
14508
14509  /*a11b */
14510  if ((myscancfg->coord.width & 1) != 0)
14511    myscancfg->coord.width++;
14512
14513  myscancfg->coord.top = 1;
14514  myscancfg->coord.height = calibcfg->WShadingHeight;
14515
14516  myscancfg->sensorresolution = 0;
14517
14518  bytes_per_line =
14519    myscancfg->coord.width * (((myscancfg->colormode == CM_COLOR) ? 3 : 1) *
14520			      ((myscancfg->depth > 8) ? 2 : 1));
14521
14522  /*a1e8 */
14523  myscancfg->v157c = bytes_per_line;
14524  myscancfg->bytesperline = bytes_per_line;
14525
14526  /* allocate space for pattern */
14527  pattern =
14528    (SANE_Byte *) malloc (((myscancfg->coord.height) * bytes_per_line) *
14529			  sizeof (SANE_Byte));
14530  if (pattern == NULL)
14531    return ERROR;
14532
14533  /* Scan image */
14534  myCalib->shading_enabled = FALSE;
14535  rst =
14536    RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, pattern, myCalib,
14537		  0x20000000, gainmode);
14538
14539  if (rst != ERROR)
14540    {
14541      SANE_Int chn;
14542      double colors[3] = { 0, 0, 0 };
14543      double prueba;
14544      SANE_Int data;
14545      SANE_Int bytes_per_channel;
14546
14547      bytes_per_channel = (myscancfg->depth > 8) ? 2 : 1;
14548
14549      avg_colors = (SANE_Byte *) malloc (sizeof (SANE_Byte) * bytes_per_line);
14550
14551      if (avg_colors != NULL)
14552	{
14553	  wshading->ptr = 0;
14554	  wshading->count = bytes_per_line / bytes_per_channel;
14555
14556	  if (wshading->rates != NULL)
14557	    {
14558	      free (wshading->rates);
14559	      wshading->rates = NULL;
14560	    }
14561	  wshading->rates =
14562	    (double *) malloc (sizeof (double) * wshading->count);
14563
14564	  chn = 0;
14565	  for (x = 0; x < wshading->count; x++)
14566	    {
14567	      sumatorio = 0;
14568
14569	      for (y = 0; y < myscancfg->coord.height; y++)
14570		{
14571		  data =
14572		    data_lsb_get (pattern +
14573				  ((x * bytes_per_channel) +
14574				   (bytes_per_line * y)), bytes_per_channel);
14575		  sumatorio += data;
14576		}
14577
14578	      sumatorio /= myscancfg->coord.height;
14579	      a = sumatorio;
14580	      colors[chn] = max (colors[chn], sumatorio);
14581	      chn++;
14582	      if (chn > 2)
14583		chn = 0;
14584
14585	      data_lsb_set (avg_colors + (x * bytes_per_channel), a,
14586			    bytes_per_channel);
14587	    }
14588
14589	  DBG (DBG_FNC, " -> max colors RGB= %f %f %f\n", colors[0],
14590	       colors[1], colors[2]);
14591
14592	  chn = 0;
14593	  for (x = 0; x < wshading->count; x++)
14594	    {
14595	      data =
14596		data_lsb_get (avg_colors + (x * bytes_per_channel),
14597			      bytes_per_channel);
14598	      prueba = data;
14599	      *(wshading->rates + x) = colors[chn] / prueba;
14600	      chn++;
14601	      if (chn > 2)
14602		chn = 0;
14603	    }
14604	}
14605
14606      if (RTS_Debug->SaveCalibFile != FALSE)
14607	{
14608	  dbg_tiff_save ("whiteshading_jkd.tiff",
14609			 myscancfg->coord.width,
14610			 myscancfg->coord.height,
14611			 myscancfg->depth,
14612			 CM_COLOR,
14613			 scancfg->resolution_x,
14614			 scancfg->resolution_y,
14615			 pattern, (myscancfg->coord.height) * bytes_per_line);
14616	}
14617
14618#ifdef developing
14619      {
14620	FILE *archivo;
14621	char texto[1024];
14622
14623	/* apply correction to the pattern to see the result */
14624	chn = 0;
14625	for (x = 0; x < myscancfg->coord.height * wshading->count; x++)
14626	  {
14627	    data =
14628	      data_lsb_get (pattern + (x * bytes_per_channel),
14629			    bytes_per_channel);
14630	    sumatorio = data;
14631	    sumatorio *= wshading->rates[chn];
14632	    if (sumatorio > ((1 << myscancfg->depth) - 1))
14633	      sumatorio = (1 << myscancfg->depth) - 1;
14634
14635	    a = sumatorio;
14636	    data_lsb_set (pattern + (x * bytes_per_channel), a,
14637			  bytes_per_channel);
14638
14639	    chn++;
14640	    if (chn == wshading->count)
14641	      chn = 0;
14642	  }
14643
14644	/* save corrected pattern */
14645	dbg_tiff_save ("onwhiteshading_jkd.tiff",
14646		       myscancfg->coord.width,
14647		       myscancfg->coord.height,
14648		       myscancfg->depth,
14649		       CM_COLOR,
14650		       scancfg->resolution_x,
14651		       scancfg->resolution_y,
14652		       pattern, (myscancfg->coord.height) * bytes_per_line);
14653
14654	/* export coefficients */
14655	archivo = fopen ("wShading.txt", "w");
14656	for (x = 0; x < wshading->count; x++)
14657	  {
14658	    snprintf (texto, 1024, "%f", wshading->rates[x]);
14659	    fprintf (archivo, "%s\n", texto);
14660	  }
14661
14662	fclose (archivo);
14663      }
14664#endif
14665    }
14666
14667  free (pattern);
14668
14669  return OK;
14670}
14671
14672#ifdef developing
14673static SANE_Int
14674motor_pos (struct st_device *dev, SANE_Byte * Regs,
14675	   struct st_calibration *myCalib, struct st_scanparams *scancfg)
14676{
14677  struct st_calibration_config *calibcfg;
14678  struct st_gain_offset myCalibTable;
14679  struct st_scanparams *myscancfg;
14680  SANE_Byte *myRegs;		/*f1bc */
14681  SANE_Int bytes_per_line;
14682  /**/ SANE_Int a, C;
14683  SANE_Byte *scanbuffer;	/*f164 */
14684  SANE_Int gainmode;
14685  SANE_Int rst;
14686
14687  DBG (DBG_FNC, "> Calib_test(*myCalib)\n");
14688
14689  memset (&myCalibTable, 0, sizeof (struct st_gain_offset));
14690
14691  calibcfg =
14692    (struct st_calibration_config *)
14693    malloc (sizeof (struct st_calibration_config));
14694  memset (calibcfg, 0x30, sizeof (struct st_calibration_config));
14695
14696  myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams));
14697  memcpy (myscancfg, scancfg, sizeof (struct st_scanparams));
14698
14699  myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
14700  memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
14701
14702  Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x,
14703		    myscancfg->depth);
14704  gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype);
14705
14706  Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode);
14707
14708  rst = OK;
14709
14710  switch (scan.scantype)
14711    {
14712    case ST_NORMAL:
14713      /*a184 */
14714      myscancfg->coord.left += scan.ser;
14715      myscancfg->coord.width &= 0xffff;
14716      break;
14717    case ST_TA:
14718    case ST_NEG:
14719      myscancfg->coord.left += scan.ser;
14720      break;
14721    }
14722
14723  /*a11b */
14724  if ((myscancfg->coord.width & 1) != 0)
14725    myscancfg->coord.width++;
14726
14727  myscancfg->coord.top = 100;
14728  myscancfg->coord.height = 30;
14729
14730  bytes_per_line = myscancfg->coord.width * 3;
14731
14732  /*a1e8 */
14733  myscancfg->v157c = bytes_per_line;
14734  myscancfg->bytesperline = bytes_per_line;
14735
14736  scanbuffer =
14737    (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) *
14738			  sizeof (SANE_Byte));
14739  if (scanbuffer == NULL)
14740    return ERROR;
14741
14742  /* Scan image */
14743  myCalib->shading_enabled = FALSE;
14744  /*Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */
14745
14746  for (a = 0; a < 10; a++)
14747    {
14748      for (C = CL_RED; C <= CL_BLUE; C++)
14749	{
14750	  myCalibTable.pag[C] = 3;
14751	  myCalibTable.vgag1[C] = 4;
14752	  myCalibTable.vgag2[C] = 4;
14753	  myCalibTable.edcg1[C] = a * 20;
14754	}
14755
14756      dbg_ScanParams (myscancfg);
14757
14758      Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD,
14759		     5000);
14760      rst =
14761	RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer,
14762		      myCalib, 0x20000000, gainmode);
14763      Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
14764
14765      if (rst != ERROR)
14766	{
14767	  char name[30];
14768	  snprintf (name, 30, "calibtest-%i.tiff", a);
14769	  dbg_tiff_save (name,
14770			 myscancfg->coord.width,
14771			 myscancfg->coord.height,
14772			 myscancfg->depth,
14773			 CM_COLOR,
14774			 myscancfg->resolution_x,
14775			 myscancfg->resolution_y,
14776			 scanbuffer,
14777			 (myscancfg->coord.height + 16) * bytes_per_line);
14778	}
14779    }
14780
14781  free (scanbuffer);
14782
14783  exit (0);
14784  return OK;
14785}
14786
14787static SANE_Int
14788hp4370_prueba (struct st_device *dev)
14789{
14790  SANE_Int rst;
14791  SANE_Int data = 0x0530, a;
14792  SANE_Int transferred;
14793  SANE_Byte buffer[512];
14794
14795  for (a = 0; a < 256; a++)
14796    data_lsb_set (buffer + (a * 2), 0x9d7, 2);
14797
14798  rst = IWrite_Word (dev->usb_handle, 0x0000, data, 0x0800);
14799  RTS_DMA_Enable_Write (dev, 0x4, 512, 0);
14800  Bulk_Operation (dev, BLK_WRITE, 512, buffer, &transferred);
14801
14802  return rst;
14803}
14804
14805static SANE_Int
14806Calib_BlackShading_jkd (struct st_device *dev, SANE_Byte * Regs,
14807			struct st_calibration *myCalib,
14808			struct st_scanparams *scancfg)
14809{
14810  struct st_calibration_config *calibcfg;
14811  struct st_gain_offset myCalibTable;
14812  struct st_scanparams *myscancfg;
14813  SANE_Byte *myRegs;		/*f1bc */
14814  SANE_Int bytes_per_line;
14815  /**/ SANE_Int x, y, a, C;
14816  SANE_Byte *scanbuffer;	/*f164 */
14817  double sumatorio;
14818  SANE_Int gainmode;
14819  SANE_Int rst;
14820
14821  DBG (DBG_FNC, "> Calib_BlackShading_jkd(*myCalib)\n");
14822
14823  memset (&myCalibTable, 0, sizeof (struct st_gain_offset));
14824  for (C = CL_RED; C <= CL_BLUE; C++)
14825    {
14826      myCalibTable.pag[C] = 3;
14827      myCalibTable.vgag1[C] = 4;
14828      myCalibTable.vgag2[C] = 4;
14829    }
14830
14831  calibcfg =
14832    (struct st_calibration_config *)
14833    malloc (sizeof (struct st_calibration_config));
14834  memset (calibcfg, 0x30, sizeof (struct st_calibration_config));
14835
14836  myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams));
14837  memcpy (myscancfg, scancfg, sizeof (struct st_scanparams));
14838
14839  myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
14840  memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
14841
14842  Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x,
14843		    myscancfg->depth);
14844  gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype);
14845
14846  Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode);
14847
14848  rst = OK;
14849
14850  switch (scan.scantype)
14851    {
14852    case ST_NORMAL:
14853      /*a184 */
14854      myscancfg->coord.left += scan.ser;
14855      myscancfg->coord.width &= 0xffff;
14856      break;
14857    case ST_TA:
14858    case ST_NEG:
14859      myscancfg->coord.left += scan.ser;
14860      break;
14861    }
14862
14863  /*a11b */
14864  if ((myscancfg->coord.width & 1) != 0)
14865    myscancfg->coord.width++;
14866
14867  myscancfg->coord.top = 1;
14868  myscancfg->coord.height = calibcfg->BShadingHeight;
14869
14870  bytes_per_line = myscancfg->coord.width * 3;
14871
14872  /*a1e8 */
14873  myscancfg->v157c = bytes_per_line;
14874  myscancfg->bytesperline = bytes_per_line;
14875
14876  scanbuffer =
14877    (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) *
14878			  sizeof (SANE_Byte));
14879  if (scanbuffer == NULL)
14880    return ERROR;
14881
14882  /* Turn off lamp */
14883  Lamp_Status_Set (dev, NULL, FALSE, FLB_LAMP);
14884  usleep (200 * 1000);
14885
14886  /* Scan image */
14887  myCalib->shading_enabled = FALSE;
14888  rst =
14889    RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib,
14890		  0x101, gainmode);
14891
14892  /* Turn on lamp again */
14893  if (scan.scantype != ST_NORMAL)
14894    {
14895      Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP);
14896      usleep (1000 * 1000);
14897    }
14898  else
14899    Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP);
14900
14901  if (rst != ERROR)
14902    {
14903      jkd_black = (SANE_Byte *) malloc (bytes_per_line);
14904
14905      if (jkd_black != NULL)
14906	{
14907	  jkd_blackbpl = bytes_per_line;
14908
14909	  for (x = 0; x < bytes_per_line; x++)
14910	    {
14911	      sumatorio = 0;
14912
14913	      for (y = 0; y < myscancfg->coord.height + 16; y++)
14914		sumatorio += scanbuffer[x + (bytes_per_line * y)];
14915
14916	      sumatorio /= myscancfg->coord.height + 16;
14917	      a = sumatorio;
14918	      *(jkd_black + x) = _B0 (a);
14919	    }
14920	}
14921
14922      /*if (RTS_Debug->SaveCalibFile != FALSE) */
14923      {
14924	dbg_tiff_save ("blackshading_jkd.tiff",
14925		       myscancfg->coord.width,
14926		       myscancfg->coord.height,
14927		       myscancfg->depth,
14928		       CM_COLOR,
14929		       myscancfg->resolution_x,
14930		       myscancfg->resolution_y,
14931		       scanbuffer,
14932		       (myscancfg->coord.height + 16) * bytes_per_line);
14933      }
14934    }
14935
14936  free (scanbuffer);
14937
14938  return OK;
14939}
14940
14941static SANE_Int
14942Calib_test (struct st_device *dev, SANE_Byte * Regs,
14943	    struct st_calibration *myCalib, struct st_scanparams *scancfg)
14944{
14945  struct st_calibration_config *calibcfg;
14946  struct st_gain_offset myCalibTable;
14947  struct st_scanparams *myscancfg;
14948  SANE_Byte *myRegs;		/*f1bc */
14949  SANE_Int bytes_per_line;
14950  /**/ SANE_Int a, C;
14951  SANE_Byte *scanbuffer;	/*f164 */
14952  SANE_Int gainmode;
14953  SANE_Int rst;
14954
14955  DBG (DBG_FNC, "> Calib_test(*myCalib)\n");
14956
14957  memset (&myCalibTable, 0, sizeof (struct st_gain_offset));
14958
14959  calibcfg =
14960    (struct st_calibration_config *)
14961    malloc (sizeof (struct st_calibration_config));
14962  memset (calibcfg, 0x30, sizeof (struct st_calibration_config));
14963
14964  myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams));
14965  memcpy (myscancfg, scancfg, sizeof (struct st_scanparams));
14966
14967  myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte));
14968  memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte));
14969
14970  Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x,
14971		    myscancfg->depth);
14972  gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype);
14973
14974  Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode);
14975
14976  rst = OK;
14977
14978  switch (scan.scantype)
14979    {
14980    case ST_NORMAL:
14981      /*a184 */
14982      myscancfg->coord.left += scan.ser;
14983      myscancfg->coord.width &= 0xffff;
14984      break;
14985    case ST_TA:
14986    case ST_NEG:
14987      myscancfg->coord.left += scan.ser;
14988      break;
14989    }
14990
14991  /*a11b */
14992  if ((myscancfg->coord.width & 1) != 0)
14993    myscancfg->coord.width++;
14994
14995  myscancfg->coord.top = 100;
14996  myscancfg->coord.height = 30;
14997
14998  bytes_per_line = myscancfg->coord.width * 3;
14999
15000  /*a1e8 */
15001  myscancfg->v157c = bytes_per_line;
15002  myscancfg->bytesperline = bytes_per_line;
15003
15004  scanbuffer =
15005    (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) *
15006			  sizeof (SANE_Byte));
15007  if (scanbuffer == NULL)
15008    return ERROR;
15009
15010  /* Scan image */
15011  myCalib->shading_enabled = FALSE;
15012  /*Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */
15013
15014  for (a = 0; a < 10; a++)
15015    {
15016      for (C = CL_RED; C <= CL_BLUE; C++)
15017	{
15018	  myCalibTable.pag[C] = 3;
15019	  myCalibTable.vgag1[C] = 4;
15020	  myCalibTable.vgag2[C] = 4;
15021	  myCalibTable.edcg1[C] = a * 20;
15022	}
15023
15024      Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD,
15025		     5000);
15026      rst =
15027	RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer,
15028		      myCalib, 0x20000000, gainmode);
15029      Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove);
15030
15031      if (rst != ERROR)
15032	{
15033	  char name[30];
15034	  snprintf (name, 30, "calibtest-%i.tiff", a);
15035	  dbg_tiff_save (name,
15036			 myscancfg->coord.width,
15037			 myscancfg->coord.height,
15038			 myscancfg->depth,
15039			 CM_COLOR,
15040			 myscancfg->resolution_x,
15041			 myscancfg->resolution_y,
15042			 scanbuffer,
15043			 (myscancfg->coord.height + 16) * bytes_per_line);
15044	}
15045    }
15046
15047  free (scanbuffer);
15048
15049  exit (0);
15050  return OK;
15051}
15052
15053static void
15054prueba (SANE_Byte * a)
15055{
15056  /* SANE_Byte p[] = {}; */
15057  /*int z = 69; */
15058
15059  /*(a + 11) = 0x0; */
15060  /*a[1] = a[1] | 0x40; */
15061
15062  /*memcpy(a, &p, sizeof(p)); */
15063
15064  /*memcpy(a + 0x12, p, 10); */
15065  /*a[0x146] &= 0xdf; */
15066
15067}
15068
15069void
15070shadingtest1 (struct st_device *dev, SANE_Byte * Regs,
15071	      struct st_calibration *myCalib)
15072{
15073  USHORT *buffer;
15074  int a;
15075  int bit[2];
15076
15077  DBG (DBG_FNC, "+ shadingtest1(*Regs, *myCalib):\n");
15078
15079  if ((Regs == NULL) || (myCalib == NULL))
15080    return;
15081
15082  RTS_DMA_Reset (dev);
15083
15084  bit[0] = (Regs[0x60b] >> 6) & 1;
15085  bit[1] = (Regs[0x60b] >> 4) & 1;
15086  Regs[0x060b] &= 0xaf;
15087
15088  Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]);
15089
15090  Regs[0x1cf] = 0;		/* reset config. By default black shading disabled and pixel-rate */
15091  /*Regs[0x1cf] |= 2;  shadingbase 0x2000 */
15092  Regs[0x1cf] |= 4;		/* White shading enabled */
15093  Regs[0x1cf] |= 0x20;		/* 16 bits per channel */
15094
15095  Write_Byte (dev->usb_handle, 0xe9cf, Regs[0x01cf]);
15096
15097  buffer = (USHORT *) malloc (sizeof (USHORT) * myCalib->shadinglength);
15098
15099  DBG (DBG_FNC, " -> shading length = %i\n", myCalib->shadinglength);
15100
15101  /* fill buffer */
15102  for (a = 0; a < myCalib->shadinglength; a++)
15103    buffer[a] = RTS_Debug->shd + (a * 500);
15104
15105  for (a = 0; a < 3; a++)
15106    {
15107      RTS_DMA_Write (dev, a | 0x14, 0,
15108		     sizeof (USHORT) * myCalib->shadinglength,
15109		     (SANE_Byte *) buffer);
15110    }
15111
15112  data_bitset (&Regs[0x60b], 0x40, bit[0]);	 /*-x------*/
15113  data_bitset (&Regs[0x60b], 0x10, bit[1]);	 /*---x----*/
15114
15115  Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]);
15116
15117  DBG (DBG_FNC, "- shadingtest1\n");
15118}
15119
15120#endif
15121
15122#endif /* RTS8822_CORE */
15123