1
/* sane - Scanner Access Now Easy.
3
Copyright (C) 2012-2013 St�phane Voltz <stef.dev@free.fr>
6
This file is part of the SANE package.
8
This program is free software; you can redistribute it and/or
9
modify it under the terms of the GNU General Public License as
10
published by the Free Software Foundation; either version 2 of the
11
License, or (at your option) any later version.
13
This program is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23
As a special exception, the authors of SANE give permission for
24
additional uses of the libraries contained in this release of SANE.
26
The exception is that, if you link a SANE library with other files
27
to produce an executable, this does not by itself cause the
28
resulting executable to be covered by the GNU General Public
29
License. Your use of that executable is in no way restricted on
30
account of linking the SANE library code into it.
32
This exception does not, however, invalidate any other reasons why
33
the executable file might be covered by the GNU General Public
36
If you submit changes to SANE to the maintainers to be included in
37
a subsequent release, you agree by submitting the changes that
38
those changes may be distributed with this exception intact.
40
If you write modifications of your own for SANE, it is your choice
41
whether to permit this exception to apply to your modifications.
42
If you do not wish that, delete this exception notice.
47
* This file handles GL846 and GL845 ASICs since they are really close to each other.
50
#define BACKEND_NAME genesys_gl846
52
#include "genesys_gl846.h"
54
/****************************************************************************
56
****************************************************************************/
58
/* ------------------------------------------------------------------------ */
59
/* Read and write RAM, registers and AFE */
60
/* ------------------------------------------------------------------------ */
63
/** @brief read scanned data
64
* Read in 0xeff0 maximum sized blocks. This read is done in 2
65
* parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the
66
* remainder. Read addr is always 0x10000000 with the memory layout setup.
67
* @param dev device to read data from
68
* @param addr address within ASIC memory space, unused but kept for API
69
* @param data pointer where to store the read data
70
* @param len size to read
73
gl846_bulk_read_data (Genesys_Device * dev, uint8_t addr,
74
uint8_t * data, size_t len)
77
size_t size, target, read, done;
81
DBG (DBG_io, "gl846_bulk_read_data: requesting %lu bytes at addr=0x%02x\n", (u_long) len, addr);
84
return SANE_STATUS_GOOD;
89
/* loop until computed data size is read */
101
/* hard coded 0x10000000 addr */
107
/* data size to transfer */
108
outdata[4] = (size & 0xff);
109
outdata[5] = ((size >> 8) & 0xff);
110
outdata[6] = ((size >> 16) & 0xff);
111
outdata[7] = ((size >> 24) & 0xff);
114
sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
115
VALUE_BUFFER, 0x00, sizeof (outdata),
117
if (status != SANE_STATUS_GOOD)
119
DBG (DBG_error, "%s failed while writing command: %s\n",
120
__FUNCTION__, sane_strstatus (status));
124
/* blocks must be multiple of 512 but not last block */
133
"gl846_bulk_read_data: trying to read %lu bytes of data\n",
135
status = sanei_usb_read_bulk (dev->dn, buffer, &read);
136
if (status != SANE_STATUS_GOOD)
139
"gl846_bulk_read_data failed while reading bulk data: %s\n",
140
sane_strstatus (status));
144
DBG (DBG_io2, "gl846_bulk_read_data: %lu bytes of data read\n", (u_long) done);
146
/* read less than 512 bytes remainder */
151
"gl846_bulk_read_data: trying to read %lu bytes of data\n",
153
status = sanei_usb_read_bulk (dev->dn, buffer+done, &read);
154
if (status != SANE_STATUS_GOOD)
157
"gl846_bulk_read_data failed while reading bulk data: %s\n",
158
sane_strstatus (status));
162
DBG (DBG_io2, "gl846_bulk_read_data: %lu bytes of data read\n", (u_long) done);
165
DBG (DBG_io2, "%s: read %lu bytes, %lu remaining\n", __FUNCTION__,
166
(u_long) size, (u_long) (target - size));
172
if (DBG_LEVEL >= DBG_data && dev->binary!=NULL)
174
fwrite(data, len, 1, dev->binary);
179
return SANE_STATUS_GOOD;
182
/****************************************************************************
184
****************************************************************************/
187
gl846_get_fast_feed_bit (Genesys_Register_Set * regs)
189
Genesys_Register_Set *r = NULL;
191
r = sanei_genesys_get_address (regs, REG02);
192
if (r && (r->value & REG02_FASTFED))
198
gl846_get_filter_bit (Genesys_Register_Set * regs)
200
Genesys_Register_Set *r = NULL;
202
r = sanei_genesys_get_address (regs, REG04);
203
if (r && (r->value & REG04_FILTER))
209
gl846_get_lineart_bit (Genesys_Register_Set * regs)
211
Genesys_Register_Set *r = NULL;
213
r = sanei_genesys_get_address (regs, REG04);
214
if (r && (r->value & REG04_LINEART))
220
gl846_get_bitset_bit (Genesys_Register_Set * regs)
222
Genesys_Register_Set *r = NULL;
224
r = sanei_genesys_get_address (regs, REG04);
225
if (r && (r->value & REG04_BITSET))
231
gl846_get_gain4_bit (Genesys_Register_Set * regs)
233
Genesys_Register_Set *r = NULL;
235
r = sanei_genesys_get_address (regs, 0x06);
236
if (r && (r->value & REG06_GAIN4))
242
gl846_test_buffer_empty_bit (SANE_Byte val)
244
if (val & REG41_BUFEMPTY)
250
gl846_test_motor_flag_bit (SANE_Byte val)
252
if (val & REG41_MOTORENB)
258
* compute the step multiplier used
261
gl846_get_step_multiplier (Genesys_Register_Set * regs)
263
Genesys_Register_Set *r = NULL;
266
r = sanei_genesys_get_address (regs, 0x9d);
269
value = (r->value & 0x0f)>>1;
272
DBG (DBG_io, "%s: step multiplier is %d\n", __FUNCTION__, value);
276
/** @brief sensor profile
277
* search for the database of motor profiles and get the best one. Each
278
* profile is at a specific dpihw. Use LiDE 110 table by default.
279
* @param sensor_type sensor id
280
* @param dpi hardware dpi for the scan
281
* @return a pointer to a Sensor_Profile struct
283
static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi)
290
while(i<sizeof(sensors)/sizeof(Sensor_Profile))
293
if(sensors[i].sensor_type==sensor_type && sensors[i].dpi==dpi)
295
return &(sensors[i]);
299
if(sensors[i].sensor_type==sensor_type)
307
if(sensors[i].dpi>=dpi
308
&& sensors[i].dpi<sensors[idx].dpi)
317
/* default fallback */
320
DBG (DBG_warn,"%s: using default sensor profile\n",__FUNCTION__);
324
return &(sensors[idx]);
327
/**@brief compute exposure to use
328
* compute the sensor exposure based on target resolution
330
static int gl846_compute_exposure(Genesys_Device *dev, int xres)
332
Sensor_Profile *sensor;
334
sensor=get_sensor_profile(dev->model->ccd_type, xres);
335
return sensor->exposure;
339
/** @brief sensor specific settings
342
gl846_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs, int dpi)
344
Genesys_Register_Set *r;
345
Sensor_Profile *sensor;
350
dpihw=sanei_genesys_compute_dpihw(dev,dpi);
352
for (i = 0x06; i < 0x0e; i++)
354
r = sanei_genesys_get_address (regs, 0x10 + i);
356
r->value = dev->sensor.regs_0x10_0x1d[i];
359
for (i = 0; i < 9; i++)
361
r = sanei_genesys_get_address (regs, 0x52 + i);
363
r->value = dev->sensor.regs_0x52_0x5e[i];
366
/* set EXPDUMMY and CKxMAP */
367
dpihw=sanei_genesys_compute_dpihw(dev,dpi);
368
sensor=get_sensor_profile(dev->model->ccd_type, dpihw);
370
sanei_genesys_set_reg_from_set(regs,REG_EXPDMY,(uint8_t)((sensor->expdummy) & 0xff));
372
/* if no calibration has been done, set default values for exposures */
373
exp=dev->sensor.regs_0x10_0x1d[0]*256+dev->sensor.regs_0x10_0x1d[1];
378
sanei_genesys_set_double(regs,REG_EXPR,exp);
380
exp=dev->sensor.regs_0x10_0x1d[2]*256+dev->sensor.regs_0x10_0x1d[3];
385
sanei_genesys_set_double(regs,REG_EXPG,exp);
387
exp=dev->sensor.regs_0x10_0x1d[4]*256+dev->sensor.regs_0x10_0x1d[5];
392
sanei_genesys_set_double(regs,REG_EXPB,exp);
394
sanei_genesys_set_triple(regs,REG_CK1MAP,sensor->ck1map);
395
sanei_genesys_set_triple(regs,REG_CK3MAP,sensor->ck3map);
396
sanei_genesys_set_triple(regs,REG_CK4MAP,sensor->ck4map);
398
/* order of the sub-segments */
399
dev->order=sensor->order;
401
r = sanei_genesys_get_address (regs, 0x17);
402
r->value = sensor->r17;
408
/* returns the max register bulk size */
410
gl846_bulk_full_size (void)
412
return GENESYS_GL846_MAX_REGS;
415
/** @brief set all registers to default values .
416
* This function is called only once at the beginning and
417
* fills register startup values for registers reused across scans.
418
* Those that are rarely modified or not modified are written
420
* @param dev device structure holding register set to initialize
423
gl846_init_registers (Genesys_Device * dev)
428
GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
538
/* fine tune upon device description */
539
dev->reg[reg_0x05].value &= ~REG05_DPIHW;
540
switch (dev->sensor.optical_res)
543
dev->reg[reg_0x05].value |= REG05_DPIHW_600;
546
dev->reg[reg_0x05].value |= REG05_DPIHW_1200;
549
dev->reg[reg_0x05].value |= REG05_DPIHW_2400;
552
dev->reg[reg_0x05].value |= REG05_DPIHW_4800;
556
/* initalize calibration reg */
557
memcpy (dev->calib_reg, dev->reg,
558
GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
563
/**@brief send slope table for motor movement
564
* Send slope_table in machine byte order
565
* @param dev device to send slope table
566
* @param table_nr index of the slope table in ASIC memory
567
* Must be in the [0-4] range.
568
* @param slope_table pointer to 16 bit values array of the slope table
569
* @param steps number of elements in the slope table
572
gl846_send_slope_table (Genesys_Device * dev, int table_nr,
573
uint16_t * slope_table, int steps)
580
DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __FUNCTION__,
584
if(table_nr<0 || table_nr>4)
586
DBG (DBG_error, "%s: invalid table number %d!\n", __FUNCTION__, table_nr);
587
return SANE_STATUS_INVAL;
590
table = (uint8_t *) malloc (steps * 2);
591
for (i = 0; i < steps; i++)
593
table[i * 2] = slope_table[i] & 0xff;
594
table[i * 2 + 1] = slope_table[i] >> 8;
597
if (DBG_LEVEL >= DBG_io)
599
sprintf (msg, "write slope %d (%d)=", table_nr, steps);
600
for (i = 0; i < steps; i++)
602
sprintf (msg+strlen(msg), "%d", slope_table[i]);
604
DBG (DBG_io, "%s: %s\n", __FUNCTION__, msg);
607
/* slope table addresses are fixed */
608
status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, 0x10000000 + 0x4000 * table_nr, steps * 2, table);
609
if (status != SANE_STATUS_GOOD)
612
"%s: write to AHB failed writing slope table %d (%s)\n",
613
__FUNCTION__, table_nr, sane_strstatus (status));
622
* Set register values of Analog Device type frontend
625
gl846_set_adi_fe (Genesys_Device * dev, uint8_t set)
627
SANE_Status status = SANE_STATUS_GOOD;
634
/* wait for FE to be ready */
635
status = sanei_genesys_get_status (dev, &val8);
636
while (val8 & REG41_FEBUSY);
639
status = sanei_genesys_get_status (dev, &val8);
644
DBG (DBG_proc, "%s(): setting DAC %u\n", __FUNCTION__, dev->model->dac_type);
646
/* sets to default values */
647
sanei_genesys_init_fe (dev);
650
/* write them to analog frontend */
651
val = dev->frontend.reg[0];
652
status = sanei_genesys_fe_write_data (dev, 0x00, val);
653
if (status != SANE_STATUS_GOOD)
655
DBG (DBG_error, "%s: failed to write reg0: %s\n", __FUNCTION__,
656
sane_strstatus (status));
659
val = dev->frontend.reg[1];
660
status = sanei_genesys_fe_write_data (dev, 0x01, val);
661
if (status != SANE_STATUS_GOOD)
663
DBG (DBG_error, "%s: failed to write reg1: %s\n", __FUNCTION__,
664
sane_strstatus (status));
668
for (i = 0; i < 3; i++)
670
val = dev->frontend.gain[i];
671
status = sanei_genesys_fe_write_data (dev, 0x02 + i, val);
672
if (status != SANE_STATUS_GOOD)
675
"%s: failed to write gain %d: %s\n", __FUNCTION__, i,
676
sane_strstatus (status));
680
for (i = 0; i < 3; i++)
682
val = dev->frontend.offset[i];
683
status = sanei_genesys_fe_write_data (dev, 0x05 + i, val);
684
if (status != SANE_STATUS_GOOD)
687
"%s: failed to write offset %d: %s\n", __FUNCTION__, i,
688
sane_strstatus (status));
698
gl846_homsnr_gpio(Genesys_Device *dev)
701
SANE_Status status=SANE_STATUS_GOOD;
703
RIE (sanei_genesys_read_register (dev, REG6C, &val));
705
RIE (sanei_genesys_write_register (dev, REG6C, val));
710
/* Set values of analog frontend */
712
gl846_set_fe (Genesys_Device * dev, uint8_t set)
716
DBG(DBG_proc, "gl846_set_fe (%s)\n",
717
set == AFE_INIT ? "init" : set == AFE_SET ? "set" :
718
set == AFE_POWER_SAVE ? "powersave" : "huh?");
720
/* route to specific analog frontend setup */
721
switch (dev->reg[reg_0x04].value & REG04_FESET)
723
case 0x02: /* ADI FE */
724
status = gl846_set_adi_fe(dev, set);
727
DBG(DBG_proc, "gl846_set_fe(): unsupported frontend type %d\n",
728
dev->reg[reg_0x04].value & REG04_FESET);
729
status = SANE_STATUS_UNSUPPORTED;
737
/** @brief set up motor related register for scan
740
gl846_init_motor_regs_scan (Genesys_Device * dev,
741
Genesys_Register_Set * reg,
742
unsigned int scan_exposure_time,
745
unsigned int scan_lines,
746
unsigned int scan_dummy,
747
unsigned int feed_steps,
753
unsigned int fast_dpi;
754
uint16_t scan_table[SLOPE_TABLE_SIZE];
755
uint16_t fast_table[SLOPE_TABLE_SIZE];
756
int scan_steps, fast_steps, factor;
757
unsigned int feedl, dist;
758
Genesys_Register_Set *r;
760
unsigned int min_restep = 0x20;
763
unsigned int ccdlmt,tgtime;
766
DBG (DBG_proc, "gl846_init_motor_regs_scan : scan_exposure_time=%d, "
767
"scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, "
768
"feed_steps=%d, scan_power_mode=%d, flags=%x\n",
772
scan_lines, scan_dummy, feed_steps, scan_power_mode, flags);
774
/* get step multiplier */
775
factor = gl846_get_step_multiplier (reg);
778
/* no fast fed since feed works well */
779
if(dev->settings.yres==4444 && feed_steps>100
780
&& ((flags & MOTOR_FLAG_FEED)==0))
784
DBG (DBG_io, "%s: use_fast_fed=%d\n", __FUNCTION__, use_fast_fed);
786
sanei_genesys_set_triple(reg, REG_LINCNT, scan_lines);
787
DBG (DBG_io, "%s: lincnt=%d\n", __FUNCTION__, scan_lines);
789
/* compute register 02 value */
790
r = sanei_genesys_get_address (reg, REG02);
792
r->value |= REG02_MTRPWR;
795
r->value |= REG02_FASTFED;
797
r->value &= ~REG02_FASTFED;
799
if (flags & MOTOR_FLAG_AUTO_GO_HOME)
800
r->value |= REG02_AGOHOME | REG02_NOTHOME;
802
if ((flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE)
803
||(scan_yres>=dev->sensor.optical_res))
805
r->value |= REG02_ACDCDIS;
808
/* scan and backtracking slope table */
809
sanei_genesys_slope_table(scan_table,
813
dev->motor.base_ydpi,
816
dev->model->motor_type,
818
RIE(gl846_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps*factor));
819
RIE(gl846_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps*factor));
822
fast_dpi=sanei_genesys_get_lowest_ydpi(dev);
823
fast_step_type=scan_step_type;
824
if(scan_step_type>=2)
829
sanei_genesys_slope_table(fast_table,
833
dev->motor.base_ydpi,
836
dev->model->motor_type,
839
/* manual override of high start value */
840
fast_table[0]=fast_table[1];
842
RIE(gl846_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps*factor));
843
RIE(gl846_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps*factor));
844
RIE(gl846_send_slope_table (dev, HOME_TABLE, fast_table, fast_steps*factor));
846
/* correct move distance by acceleration and deceleration amounts */
850
feedl<<=fast_step_type;
851
dist=(scan_steps+2*fast_steps)*factor;
852
/* TODO read and decode REGAB */
853
r = sanei_genesys_get_address (reg, 0x5e);
854
dist += (r->value & 31);
856
r = sanei_genesys_get_address (reg, REG_FEDCNT);
861
feedl<<=scan_step_type;
862
dist=scan_steps*factor;
863
if (flags & MOTOR_FLAG_FEED)
866
DBG (DBG_io2, "%s: scan steps=%d\n", __FUNCTION__, scan_steps);
867
DBG (DBG_io2, "%s: acceleration distance=%d\n", __FUNCTION__, dist);
869
/* check for overflow */
875
sanei_genesys_set_triple(reg,REG_FEEDL,feedl);
876
DBG (DBG_io ,"%s: feedl=%d\n",__FUNCTION__,feedl);
878
r = sanei_genesys_get_address (reg, REG0C);
879
ccdlmt=(r->value & REG0C_CCDLMT)+1;
881
r = sanei_genesys_get_address (reg, REG1C);
882
tgtime=1<<(r->value & REG1C_TGTIME);
884
/* hi res motor speed GPIO */
886
RIE (sanei_genesys_read_register (dev, REG6C, &effective));
889
/* if quarter step, bipolar Vref2 */
891
if (scan_step_type > 1)
893
if (scan_step_type < 3)
895
val = effective & ~REG6C_GPIO13;
899
val = effective | REG6C_GPIO13;
906
RIE (sanei_genesys_write_register (dev, REG6C, val));
911
RIE (sanei_genesys_read_register (dev, REG6C, &effective));
912
val = effective | REG6C_GPIO10;
913
RIE (sanei_genesys_write_register (dev, REG6C, val));
916
if(dev->model->gpo_type==GPO_IMG101)
918
if(scan_yres==sanei_genesys_compute_dpihw(dev,scan_yres))
926
RIE (sanei_genesys_write_register (dev, REG7E, val));
929
min_restep=scan_steps/2-1;
932
r = sanei_genesys_get_address (reg, REG_FWDSTEP);
933
r->value = min_restep;
934
r = sanei_genesys_get_address (reg, REG_BWDSTEP);
935
r->value = min_restep;
937
sanei_genesys_calculate_zmode2(use_fast_fed,
938
scan_exposure_time*ccdlmt*tgtime,
946
DBG (DBG_info, "gl846_init_motor_regs_scan: z1 = %d\n", z1);
947
sanei_genesys_set_triple(reg, REG60, z1 | (scan_step_type << (16+REG60S_STEPSEL)));
949
DBG (DBG_info, "gl846_init_motor_regs_scan: z2 = %d\n", z2);
950
sanei_genesys_set_triple(reg, REG63, z2 | (scan_step_type << (16+REG63S_FSTPSEL)));
952
r = sanei_genesys_get_address (reg, 0x1e);
953
r->value &= 0xf0; /* 0 dummy lines */
954
r->value |= scan_dummy; /* dummy lines */
956
r = sanei_genesys_get_address (reg, REG67);
959
r = sanei_genesys_get_address (reg, REG68);
962
r = sanei_genesys_get_address (reg, REG_STEPNO);
963
r->value = scan_steps;
965
r = sanei_genesys_get_address (reg, REG_FASTNO);
966
r->value = scan_steps;
968
r = sanei_genesys_get_address (reg, REG_FSHDEC);
969
r->value = scan_steps;
971
r = sanei_genesys_get_address (reg, REG_FMOVNO);
972
r->value = fast_steps;
974
r = sanei_genesys_get_address (reg, REG_FMOVDEC);
975
r->value = fast_steps;
978
return SANE_STATUS_GOOD;
982
/** @brief set up registers related to sensor
983
* Set up the following registers
986
0x10-0x015 R/G/B exposures
996
0x35,0x36,0x37 MAXWD [25:2] (>>2)
1001
gl846_init_optical_regs_scan (Genesys_Device * dev,
1002
Genesys_Register_Set * reg,
1003
unsigned int exposure_time,
1006
unsigned int pixels,
1009
SANE_Bool half_ccd, int color_filter, int flags)
1011
unsigned int words_per_line;
1012
unsigned int startx, endx, used_pixels;
1013
unsigned int dpiset, dpihw,segnb,cksel,factor;
1015
Genesys_Register_Set *r;
1017
Sensor_Profile *sensor;
1019
DBG (DBG_proc, "gl846_init_optical_regs_scan : exposure_time=%d, "
1020
"used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, "
1021
"half_ccd=%d, flags=%x\n", exposure_time,
1022
used_res, start, pixels, channels, depth, half_ccd, flags);
1024
/* resolution is divided according to CKSEL */
1025
r = sanei_genesys_get_address (reg, REG18);
1026
cksel= (r->value & REG18_CKSEL)+1;
1027
DBG (DBG_io2, "%s: cksel=%d\n", __FUNCTION__, cksel);
1029
/* to manage high resolution device while keeping good
1030
* low resolution scanning speed, we make hardware dpi vary */
1031
dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel);
1032
factor=dev->sensor.optical_res/dpihw;
1033
DBG (DBG_io2, "%s: dpihw=%d (factor=%d)\n", __FUNCTION__, dpihw, factor);
1035
/* sensor parameters */
1036
sensor=get_sensor_profile(dev->model->ccd_type, dpihw);
1037
gl846_setup_sensor (dev, reg, dpihw);
1038
dpiset = used_res * cksel;
1040
/* start and end coordinate in optical dpi coordinates */
1041
startx = start/cksel+dev->sensor.CCD_start_xoffset;
1042
used_pixels=pixels/cksel;
1044
/* end of sensor window */
1045
endx = startx + used_pixels;
1047
/* sensors are built from 600 dpi segments for LiDE 100/200
1048
* and 1200 dpi for the 700F */
1049
if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR)
1058
/* compute pixel coordinate in the given dpihw space,
1059
* taking segments into account */
1060
startx/=factor*segnb;
1062
dev->len=endx-startx;
1066
/* in cas of multi-segments sensor, we have to add the witdh
1067
* of the sensor crossed by the scan area */
1068
if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR && segnb>1)
1070
dev->dist = sensor->segcnt;
1073
/* use a segcnt rounded to next even number */
1074
endx += ((dev->dist+1)&0xfffe)*(segnb-1);
1075
used_pixels=endx-startx;
1077
status = gl846_set_fe (dev, AFE_SET);
1078
if (status != SANE_STATUS_GOOD)
1081
"gl846_init_optical_regs_scan: failed to set frontend: %s\n",
1082
sane_strstatus (status));
1086
/* enable shading */
1087
r = sanei_genesys_get_address (reg, REG01);
1088
r->value &= ~REG01_SCAN;
1089
r->value |= REG01_SHDAREA;
1090
if ((flags & OPTICAL_FLAG_DISABLE_SHADING) ||
1091
(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
1093
r->value &= ~REG01_DVDSET;
1097
r->value |= REG01_DVDSET;
1100
r = sanei_genesys_get_address (reg, REG03);
1101
r->value &= ~REG03_AVEENB;
1103
if (flags & OPTICAL_FLAG_DISABLE_LAMP)
1104
r->value &= ~REG03_LAMPPWR;
1106
r->value |= REG03_LAMPPWR;
1109
r = sanei_genesys_get_address (reg, 0x2e);
1110
r->value = dev->settings.threshold;
1111
r = sanei_genesys_get_address (reg, 0x2f);
1112
r->value = dev->settings.threshold;
1114
/* monochrome / color scan */
1115
r = sanei_genesys_get_address (reg, REG04);
1119
r->value &= ~REG04_BITSET;
1120
r->value |= REG04_LINEART;
1123
r->value &= ~(REG04_LINEART | REG04_BITSET);
1126
r->value &= ~REG04_LINEART;
1127
r->value |= REG04_BITSET;
1131
r->value &= ~(REG04_FILTER | REG04_AFEMOD);
1134
switch (color_filter)
1137
r->value |= 0x24; /* red filter */
1140
r->value |= 0x2c; /* blue filter */
1143
r->value |= 0x28; /* green filter */
1148
r->value |= 0x20; /* mono */
1151
r = sanei_genesys_get_address (reg, REG05);
1154
r->value &= ~REG05_DPIHW;
1158
r->value |= REG05_DPIHW_600;
1161
r->value |= REG05_DPIHW_1200;
1164
r->value |= REG05_DPIHW_2400;
1167
r->value |= REG05_DPIHW_4800;
1171
/* enable gamma tables */
1172
if (flags & OPTICAL_FLAG_DISABLE_GAMMA)
1173
r->value &= ~REG05_GMMENB;
1175
r->value |= REG05_GMMENB;
1177
/* CIS scanners can do true gray by setting LEDADD */
1178
/* we set up LEDADD only when asked */
1179
if (dev->model->is_cis == SANE_TRUE)
1181
r = sanei_genesys_get_address (reg, 0x87);
1182
r->value &= ~REG87_LEDADD;
1183
if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD))
1185
r->value |= REG87_LEDADD;
1188
r = sanei_genesys_get_address (reg, 0x01);
1189
r->value &= ~REG01_TRUEGRAY;
1190
if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD))
1192
r->value |= REG01_TRUEGRAY;
1196
/* words(16bit) before gamma, conversion to 8 bit or lineart*/
1197
words_per_line = (used_pixels * dpiset) / dpihw;
1201
words_per_line = (words_per_line+7)/8 ;
1202
dev->len = (dev->len >> 3) + ((dev->len & 7) ? 1 : 0);
1203
dev->dist = (dev->dist >> 3) + ((dev->dist & 7) ? 1 : 0);
1207
words_per_line *= bytes;
1212
dev->bpl = words_per_line;
1215
dev->line_interp = 0;
1217
sanei_genesys_set_double(reg,REG_DPISET,dpiset);
1218
DBG (DBG_io2, "%s: dpiset used=%d\n", __FUNCTION__, dpiset);
1220
sanei_genesys_set_double(reg,REG_STRPIXEL,startx);
1221
sanei_genesys_set_double(reg,REG_ENDPIXEL,endx);
1222
DBG (DBG_io2, "%s: startx=%d\n", __FUNCTION__, startx);
1223
DBG (DBG_io2, "%s: endx =%d\n", __FUNCTION__, endx);
1225
DBG (DBG_io2, "%s: used_pixels=%d\n", __FUNCTION__, used_pixels);
1226
DBG (DBG_io2, "%s: pixels =%d\n", __FUNCTION__, pixels);
1227
DBG (DBG_io2, "%s: depth =%d\n", __FUNCTION__, depth);
1228
DBG (DBG_io2, "%s: dev->bpl =%lu\n", __FUNCTION__, (unsigned long)dev->bpl);
1229
DBG (DBG_io2, "%s: dev->len =%lu\n", __FUNCTION__, (unsigned long)dev->len);
1230
DBG (DBG_io2, "%s: dev->dist =%lu\n", __FUNCTION__, (unsigned long)dev->dist);
1231
DBG (DBG_io2, "%s: dev->segnb =%lu\n", __FUNCTION__, (unsigned long)dev->segnb);
1233
words_per_line *= channels;
1234
dev->wpl = words_per_line;
1236
if(dev->oe_buffer.buffer!=NULL)
1238
sanei_genesys_buffer_free (&(dev->oe_buffer));
1240
RIE (sanei_genesys_buffer_alloc (&(dev->oe_buffer), dev->wpl));
1242
/* MAXWD is expressed in 4 words unit */
1243
sanei_genesys_set_triple(reg, REG_MAXWD, (words_per_line >> 2));
1244
DBG (DBG_io2, "%s: words_per_line used=%d\n", __FUNCTION__, words_per_line);
1246
sanei_genesys_set_double(reg, REG_LPERIOD, exposure_time);
1247
DBG (DBG_io2, "%s: exposure_time used=%d\n", __FUNCTION__, exposure_time);
1249
r = sanei_genesys_get_address (reg, 0x34);
1250
r->value = dev->sensor.dummy_pixel;
1253
return SANE_STATUS_GOOD;
1256
/* set up registers for an actual scan
1258
* this function sets up the scanner to scan in normal or single line mode
1260
#ifndef UNIT_TESTING
1264
gl846_init_scan_regs (Genesys_Device * dev,
1265
Genesys_Register_Set * reg,
1266
float xres, /*dpi */
1267
float yres, /*dpi */
1268
float startx, /*optical_res, from dummy_pixel+1 */
1269
float starty, /*base_ydpi, from home! */
1273
unsigned int channels,
1278
int start, used_pixels;
1281
unsigned int lincnt;
1282
unsigned int oflags; /**> optical flags */
1283
unsigned int mflags; /**> motor flags */
1289
int scan_step_type = 1;
1290
int scan_power_mode = 0;
1292
size_t requested_buffer_size, read_buffer_size;
1294
SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */
1299
"gl846_init_scan_regs settings:\n"
1300
"Resolution : %gDPI/%gDPI\n"
1303
"Startpos : %g/%g\n"
1304
"Depth/Channels: %u/%u\n"
1306
xres, yres, lines, pixels, startx, starty, depth, channels, flags);
1308
/* we may have 2 domains for ccd: xres below or above half ccd max dpi */
1309
if (dev->sensor.optical_res < 2 * xres ||
1310
!(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE))
1312
half_ccd = SANE_FALSE;
1316
half_ccd = SANE_TRUE;
1320
optical_res = dev->sensor.optical_res;
1325
if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
1326
stagger = (4 * yres) / dev->motor.base_ydpi;
1329
DBG (DBG_info, "gl846_init_scan_regs : stagger=%d lines\n", stagger);
1332
if (flags & SCAN_FLAG_USE_OPTICAL_RES)
1334
used_res = optical_res;
1338
/* resolution is choosen from a list */
1342
/* compute scan parameters values */
1343
/* pixels are allways given at full optical resolution */
1344
/* use detected left margin and fixed value */
1346
/* add x coordinates */
1352
/* compute correct pixels number */
1354
used_pixels = (pixels * optical_res) / xres;
1356
/* round up pixels number if needed */
1357
if (used_pixels * xres < pixels * optical_res)
1363
/* cis color scan is effectively a gray scan with 3 gray lines per color
1364
line and a FILTER of 0 */
1365
if (dev->model->is_cis)
1366
slope_dpi = yres * channels;
1370
slope_dpi = slope_dpi * (1 + dummy);
1372
exposure_time = gl846_compute_exposure (dev, used_res);
1373
scan_step_type = sanei_genesys_compute_step_type(gl846_motors, dev->model->motor_type, exposure_time);
1375
DBG (DBG_info, "gl846_init_scan_regs : exposure_time=%d pixels\n", exposure_time);
1376
DBG (DBG_info, "gl846_init_scan_regs : scan_step_type=%d\n", scan_step_type);
1378
/*** optical parameters ***/
1379
/* in case of dynamic lineart, we use an internal 8 bit gray scan
1380
* to generate 1 lineart data */
1381
if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (dev->settings.scan_mode == SCAN_MODE_LINEART))
1386
/* we enable true gray for cis scanners only, and just when doing
1387
* scan since color calibration is OK for this mode
1390
if(flags & SCAN_FLAG_DISABLE_SHADING)
1391
oflags |= OPTICAL_FLAG_DISABLE_SHADING;
1392
if(flags & SCAN_FLAG_DISABLE_GAMMA)
1393
oflags |= OPTICAL_FLAG_DISABLE_GAMMA;
1394
if(flags & SCAN_FLAG_DISABLE_LAMP)
1395
oflags |= OPTICAL_FLAG_DISABLE_LAMP;
1397
if (dev->model->is_cis && dev->settings.true_gray)
1399
oflags |= OPTICAL_FLAG_ENABLE_LEDADD;
1402
status = gl846_init_optical_regs_scan (dev,
1414
if (status != SANE_STATUS_GOOD)
1417
/*** motor parameters ***/
1420
max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags);
1423
lincnt = lines + max_shift + stagger;
1425
/* add tl_y to base movement */
1427
DBG (DBG_info, "gl846_init_scan_regs: move=%d steps\n", move);
1430
if(flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE)
1431
mflags |= MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE;
1432
if(flags & SCAN_FLAG_FEEDING)
1433
mflags |= MOTOR_FLAG_FEED;
1435
status = gl846_init_motor_regs_scan (dev,
1440
dev->model->is_cis ? lincnt *
1441
channels : lincnt, dummy, move,
1445
if (status != SANE_STATUS_GOOD)
1449
/*** prepares data reordering ***/
1451
/* words_per_line */
1452
bytes_per_line = (used_pixels * used_res) / optical_res;
1453
bytes_per_line = (bytes_per_line * channels * depth) / 8;
1455
requested_buffer_size = 8 * bytes_per_line;
1456
/* we must use a round number of bytes_per_line */
1458
if (requested_buffer_size > BULKIN_MAXSIZE)
1459
requested_buffer_size =
1460
(BULKIN_MAXSIZE / bytes_per_line) * bytes_per_line;
1464
2 * requested_buffer_size +
1465
((max_shift + stagger) * used_pixels * channels * depth) / 8;
1467
RIE (sanei_genesys_buffer_free (&(dev->read_buffer)));
1468
RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size));
1470
RIE (sanei_genesys_buffer_free (&(dev->lines_buffer)));
1471
RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size));
1473
RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer)));
1474
RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer),
1475
requested_buffer_size));
1477
RIE (sanei_genesys_buffer_free (&(dev->out_buffer)));
1478
RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer),
1479
(8 * dev->settings.pixels * channels *
1483
dev->read_bytes_left = bytes_per_line * lincnt;
1486
"gl846_init_scan_regs: physical bytes to read = %lu\n",
1487
(u_long) dev->read_bytes_left);
1488
dev->read_active = SANE_TRUE;
1491
dev->current_setup.pixels = (used_pixels * used_res) / optical_res;
1492
dev->current_setup.lines = lincnt;
1493
dev->current_setup.depth = depth;
1494
dev->current_setup.channels = channels;
1495
dev->current_setup.exposure_time = exposure_time;
1496
dev->current_setup.xres = used_res;
1497
dev->current_setup.yres = yres;
1498
dev->current_setup.half_ccd = half_ccd;
1499
dev->current_setup.stagger = stagger;
1500
dev->current_setup.max_shift = max_shift + stagger;
1502
/* TODO: should this be done elsewhere? */
1503
/* scan bytes to send to the frontend */
1506
(dev->settings.pixels * dev->settings.lines * channels * depth) / 8;
1507
but it suffers from integer overflow so we do the following:
1509
1 bit color images store color data byte-wise, eg byte 0 contains
1510
8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains
1512
This does not fix the overflow, though.
1513
644mp*16 = 10gp, leading to an overflow
1517
dev->total_bytes_read = 0;
1519
dev->total_bytes_to_read =
1520
((dev->settings.pixels * dev->settings.lines) / 8 +
1521
(((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) *
1524
dev->total_bytes_to_read =
1525
dev->settings.pixels * dev->settings.lines * channels * (depth / 8);
1527
DBG (DBG_info, "gl846_init_scan_regs: total bytes to send = %lu\n",
1528
(u_long) dev->total_bytes_to_read);
1532
return SANE_STATUS_GOOD;
1536
gl846_calculate_current_setup (Genesys_Device * dev)
1542
float xres; /*dpi */
1543
float yres; /*dpi */
1544
float startx; /*optical_res, from dummy_pixel+1 */
1550
unsigned int lincnt;
1558
SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */
1562
"gl846_calculate_current_setup settings:\n"
1563
"Resolution: %uDPI\n"
1566
"Startpos : %.3f/%.3f\n"
1567
"Scan mode : %d\n\n",
1568
dev->settings.yres, dev->settings.lines, dev->settings.pixels,
1569
dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
1572
if (dev->settings.scan_mode == 4) /* single pass color */
1578
depth = dev->settings.depth;
1579
if (dev->settings.scan_mode == 0)
1583
start = SANE_UNFIX (dev->model->x_offset);
1584
start += dev->settings.tl_x;
1585
start = (start * dev->sensor.optical_res) / MM_PER_INCH;
1588
xres = dev->settings.xres; /*dpi */
1589
yres = dev->settings.yres; /*dpi */
1590
startx = start; /*optical_res, from dummy_pixel+1 */
1591
pixels = dev->settings.pixels;
1592
lines = dev->settings.lines;
1595
"gl846_calculate_current_setup settings:\n"
1596
"Resolution : %gDPI/%gDPI\n"
1600
"Depth/Channels: %u/%u\n\n",
1601
xres, yres, lines, pixels, startx, depth, channels);
1604
/* we have 2 domains for ccd: xres below or above half ccd max dpi */
1605
if ((dev->sensor.optical_res < 2 * xres) ||
1606
!(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE))
1608
half_ccd = SANE_FALSE;
1612
half_ccd = SANE_TRUE;
1616
optical_res = dev->sensor.optical_res;
1619
if (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)
1620
stagger = (4 * yres) / dev->motor.base_ydpi;
1623
DBG (DBG_info, "gl846_calculate_current_setup: stagger=%d lines\n",
1626
/* resolution is choosen from a fixed list */
1629
/* compute scan parameters values */
1630
/* pixels are allways given at half or full CCD optical resolution */
1631
/* use detected left margin and fixed value */
1633
/* compute correct pixels number */
1634
used_pixels = (pixels * optical_res) / used_res;
1638
/* cis color scan is effectively a gray scan with 3 gray lines per color
1639
line and a FILTER of 0 */
1640
if (dev->model->is_cis)
1641
slope_dpi = yres * channels;
1645
slope_dpi = slope_dpi * (1 + dummy);
1647
exposure_time = gl846_compute_exposure (dev, used_res);
1648
DBG (DBG_info, "%s : exposure_time=%d pixels\n", __FUNCTION__, exposure_time);
1651
max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0);
1654
lincnt = lines + max_shift + stagger;
1656
dev->current_setup.pixels = (used_pixels * used_res) / optical_res;
1657
dev->current_setup.lines = lincnt;
1658
dev->current_setup.depth = depth;
1659
dev->current_setup.channels = channels;
1660
dev->current_setup.exposure_time = exposure_time;
1661
dev->current_setup.xres = used_res;
1662
dev->current_setup.yres = yres;
1663
dev->current_setup.half_ccd = half_ccd;
1664
dev->current_setup.stagger = stagger;
1665
dev->current_setup.max_shift = max_shift + stagger;
1668
return SANE_STATUS_GOOD;
1672
gl846_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set)
1675
DBG (DBG_proc, "gl846_set_motor_power\n");
1679
sanei_genesys_set_reg_from_set (regs, REG02,
1680
sanei_genesys_read_reg_from_set (regs,
1686
sanei_genesys_set_reg_from_set (regs, REG02,
1687
sanei_genesys_read_reg_from_set (regs,
1694
gl846_set_lamp_power (Genesys_Device __sane_unused__ * dev,
1695
Genesys_Register_Set * regs, SANE_Bool set)
1699
sanei_genesys_set_reg_from_set (regs, REG03,
1700
sanei_genesys_read_reg_from_set (regs, REG03)
1705
sanei_genesys_set_reg_from_set (regs, REG03,
1706
sanei_genesys_read_reg_from_set (regs, REG03)
1711
/*for fast power saving methods only, like disabling certain amplifiers*/
1713
gl846_save_power (Genesys_Device * dev, SANE_Bool enable)
1715
DBG (DBG_proc, "gl846_save_power: enable = %d\n", enable);
1717
return SANE_STATUS_INVAL;
1720
return SANE_STATUS_GOOD;
1724
gl846_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
1726
DBG (DBG_proc, "gl846_set_powersaving (delay = %d)\n", delay);
1728
return SANE_STATUS_INVAL;
1731
return SANE_STATUS_GOOD;
1735
gl846_start_action (Genesys_Device * dev)
1737
return sanei_genesys_write_register (dev, 0x0f, 0x01);
1740
#ifndef UNIT_TESTING
1744
gl846_stop_action (Genesys_Device * dev)
1752
/* post scan gpio : without that HOMSNR is unreliable */
1753
gl846_homsnr_gpio(dev);
1754
status = sanei_genesys_get_status (dev, &val);
1755
if (DBG_LEVEL >= DBG_io)
1757
sanei_genesys_print_status (val);
1760
status = sanei_genesys_read_register (dev, REG40, &val40);
1761
if (status != SANE_STATUS_GOOD)
1764
"%s: failed to read home sensor: %s\n", __FUNCTION__,
1765
sane_strstatus (status));
1770
/* only stop action if needed */
1771
if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG))
1773
DBG (DBG_info, "%s: already stopped\n", __FUNCTION__);
1775
return SANE_STATUS_GOOD;
1779
val = sanei_genesys_read_reg_from_set (dev->reg, REG01);
1781
sanei_genesys_set_reg_from_set (dev->reg, REG01, val);
1782
status = sanei_genesys_write_register (dev, REG01, val);
1783
if (status != SANE_STATUS_GOOD)
1786
"%s: failed to write register 01: %s\n", __FUNCTION__,
1787
sane_strstatus (status));
1790
usleep (100 * 1000);
1795
status = sanei_genesys_get_status (dev, &val);
1796
if (DBG_LEVEL >= DBG_io)
1798
sanei_genesys_print_status (val);
1800
status = sanei_genesys_read_register (dev, REG40, &val40);
1801
if (status != SANE_STATUS_GOOD)
1804
"%s: failed to read home sensor: %s\n", __FUNCTION__,
1805
sane_strstatus (status));
1810
/* if scanner is in command mode, we are done */
1811
if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)
1812
&& !(val & REG41_MOTORENB))
1815
return SANE_STATUS_GOOD;
1818
usleep (100 * 1000);
1823
return SANE_STATUS_IO_ERROR;
1826
/* Send the low-level scan command */
1827
#ifndef UNIT_TESTING
1831
gl846_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
1832
SANE_Bool start_motor)
1836
Genesys_Register_Set *r;
1840
/* XXX STEF XXX SCAN GPIO */
1842
RIE (sanei_genesys_read_register (dev, REG6C, &val));
1843
RIE (sanei_genesys_write_register (dev, REG6C, val));
1846
val = REG0D_CLRLNCNT;
1847
RIE (sanei_genesys_write_register (dev, REG0D, val));
1848
val = REG0D_CLRMCNT;
1849
RIE (sanei_genesys_write_register (dev, REG0D, val));
1851
RIE (sanei_genesys_read_register (dev, REG01, &val));
1853
RIE (sanei_genesys_write_register (dev, REG01, val));
1854
r = sanei_genesys_get_address (reg, REG01);
1859
RIE (sanei_genesys_write_register (dev, REG0F, 1));
1863
RIE (sanei_genesys_write_register (dev, REG0F, 0));
1872
/* Send the stop scan command */
1873
#ifndef UNIT_TESTING
1877
gl846_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
1878
SANE_Bool check_stop)
1882
DBG (DBG_proc, "gl846_end_scan (check_stop = %d)\n", check_stop);
1884
return SANE_STATUS_INVAL;
1886
if (dev->model->is_sheetfed == SANE_TRUE)
1888
status = SANE_STATUS_GOOD;
1890
else /* flat bed scanners */
1892
status = gl846_stop_action (dev);
1893
if (status != SANE_STATUS_GOOD)
1896
"gl846_end_scan: failed to stop: %s\n",
1897
sane_strstatus (status));
1906
/* Moves the slider to the home (top) postion slowly */
1907
#ifndef UNIT_TESTING
1911
gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
1913
Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
1915
Genesys_Register_Set *r;
1921
DBG (DBG_proc, "gl846_slow_back_home (wait_until_home = %d)\n",
1927
return SANE_STATUS_GOOD;
1930
/* post scan gpio : without that HOMSNR is unreliable */
1931
gl846_homsnr_gpio(dev);
1933
/* first read gives HOME_SENSOR true */
1934
status = sanei_genesys_get_status (dev, &val);
1935
if (status != SANE_STATUS_GOOD)
1938
"gl846_slow_back_home: failed to read home sensor: %s\n",
1939
sane_strstatus (status));
1942
if (DBG_LEVEL >= DBG_io)
1944
sanei_genesys_print_status (val);
1946
usleep (100000); /* sleep 100 ms */
1948
/* second is reliable */
1949
status = sanei_genesys_get_status (dev, &val);
1950
if (status != SANE_STATUS_GOOD)
1953
"gl846_slow_back_home: failed to read home sensor: %s\n",
1954
sane_strstatus (status));
1957
if (DBG_LEVEL >= DBG_io)
1959
sanei_genesys_print_status (val);
1962
/* is sensor at home? */
1965
DBG (DBG_info, "%s: already at home, completed\n", __FUNCTION__);
1966
dev->scanhead_position_in_steps = 0;
1968
return SANE_STATUS_GOOD;
1971
memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
1973
resolution=sanei_genesys_get_lowest_ydpi(dev);
1975
/* TODO add scan_mode to the API */
1976
scan_mode= dev->settings.scan_mode;
1977
dev->settings.scan_mode=SCAN_MODE_LINEART;
1978
gl846_init_scan_regs (dev,
1989
SCAN_FLAG_DISABLE_SHADING |
1990
SCAN_FLAG_DISABLE_GAMMA |
1991
SCAN_FLAG_IGNORE_LINE_DISTANCE);
1992
dev->settings.scan_mode=scan_mode;
1994
/* clear scan and feed count */
1995
RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT));
1997
/* set up for reverse */
1998
r = sanei_genesys_get_address (local_reg, REG02);
1999
r->value |= REG02_MTRREV;
2001
RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS));
2003
status = gl846_start_action (dev);
2004
if (status != SANE_STATUS_GOOD)
2007
"gl846_slow_back_home: failed to start motor: %s\n",
2008
sane_strstatus (status));
2009
gl846_stop_action (dev);
2010
/* send original registers */
2011
dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS);
2015
/* post scan gpio : without that HOMSNR is unreliable */
2016
gl846_homsnr_gpio(dev);
2018
if (wait_until_home)
2020
while (loop < 300) /* do not wait longer then 30 seconds */
2022
status = sanei_genesys_get_status (dev, &val);
2023
if (status != SANE_STATUS_GOOD)
2026
"gl846_slow_back_home: failed to read home sensor: %s\n",
2027
sane_strstatus (status));
2031
if (val & HOMESNR) /* home sensor */
2033
DBG (DBG_info, "gl846_slow_back_home: reached home position\n");
2034
gl846_stop_action (dev);
2035
dev->scanhead_position_in_steps = 0;
2037
return SANE_STATUS_GOOD;
2039
usleep (100000); /* sleep 100 ms */
2043
/* when we come here then the scanner needed too much time for this, so we better stop the motor */
2044
gl846_stop_action (dev);
2046
"gl846_slow_back_home: timeout while waiting for scanhead to go home\n");
2047
return SANE_STATUS_IO_ERROR;
2050
DBG (DBG_info, "gl846_slow_back_home: scanhead is still moving\n");
2052
return SANE_STATUS_GOOD;
2055
/* Automatically set top-left edge of the scan area by scanning a 200x200 pixels
2056
area at 600 dpi from very top of scanner */
2058
gl846_search_start_position (Genesys_Device * dev)
2063
Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
2069
DBG (DBG_proc, "gl846_search_start_position\n");
2071
memcpy (local_reg, dev->reg,
2072
GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
2074
/* sets for a 200 lines * 600 pixels */
2075
/* normal scan with no shading */
2077
status = gl846_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, /*we should give a small offset here~60 steps */
2078
600, dev->model->search_lines, 8, 1, 1, /*green */
2079
SCAN_FLAG_DISABLE_SHADING |
2080
SCAN_FLAG_DISABLE_GAMMA |
2081
SCAN_FLAG_IGNORE_LINE_DISTANCE);
2082
if (status != SANE_STATUS_GOOD)
2085
"gl846_search_start_position: failed to set up registers: %s\n",
2086
sane_strstatus (status));
2091
/* send to scanner */
2092
status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS);
2093
if (status != SANE_STATUS_GOOD)
2096
"gl846_search_start_position: failed to bulk write registers: %s\n",
2097
sane_strstatus (status));
2102
size = pixels * dev->model->search_lines;
2104
data = malloc (size);
2108
"gl846_search_start_position: failed to allocate memory\n");
2109
return SANE_STATUS_NO_MEM;
2112
status = gl846_begin_scan (dev, local_reg, SANE_TRUE);
2113
if (status != SANE_STATUS_GOOD)
2117
"gl846_search_start_position: failed to begin scan: %s\n",
2118
sane_strstatus (status));
2122
/* waits for valid data */
2124
sanei_genesys_test_buffer_empty (dev, &steps);
2127
/* now we're on target, we can read data */
2128
status = sanei_genesys_read_data_from_scanner (dev, data, size);
2129
if (status != SANE_STATUS_GOOD)
2133
"gl846_search_start_position: failed to read data: %s\n",
2134
sane_strstatus (status));
2138
if (DBG_LEVEL >= DBG_data)
2139
sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels,
2140
dev->model->search_lines);
2142
status = gl846_end_scan (dev, local_reg, SANE_TRUE);
2143
if (status != SANE_STATUS_GOOD)
2147
"gl846_search_start_position: failed to end scan: %s\n",
2148
sane_strstatus (status));
2152
/* update regs to copy ASIC internal state */
2153
memcpy (dev->reg, local_reg,
2154
GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
2156
/*TODO: find out where sanei_genesys_search_reference_point
2157
stores information, and use that correctly*/
2159
sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels,
2160
dev->model->search_lines);
2161
if (status != SANE_STATUS_GOOD)
2165
"gl846_search_start_position: failed to set search reference point: %s\n",
2166
sane_strstatus (status));
2171
return SANE_STATUS_GOOD;
2175
* sets up register for coarse gain calibration
2176
* todo: check it for scanners using it */
2178
gl846_init_regs_for_coarse_calibration (Genesys_Device * dev)
2184
DBG (DBG_proc, "gl846_init_regs_for_coarse_calibration\n");
2187
cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */
2190
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
2195
status = gl846_init_scan_regs (dev,
2201
dev->sensor.optical_res / cksel,
2205
dev->settings.color_filter,
2206
SCAN_FLAG_DISABLE_SHADING |
2207
SCAN_FLAG_DISABLE_GAMMA |
2208
SCAN_FLAG_SINGLE_LINE |
2209
SCAN_FLAG_IGNORE_LINE_DISTANCE);
2210
if (status != SANE_STATUS_GOOD)
2213
"gl846_init_register_for_coarse_calibration: Failed to setup scan: %s\n",
2214
sane_strstatus (status));
2219
"gl846_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n",
2220
dev->sensor.optical_res / cksel, dev->settings.xres);
2222
status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS);
2223
if (status != SANE_STATUS_GOOD)
2226
"gl846_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n",
2227
sane_strstatus (status));
2232
return SANE_STATUS_GOOD;
2235
/** @brief moves the slider to steps at motor base dpi
2236
* @param dev device to work on
2237
* @param steps number of steps to move in base_dpi line count
2239
#ifndef UNIT_TESTING
2243
gl846_feed (Genesys_Device * dev, unsigned int steps)
2245
Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
2247
Genesys_Register_Set *r;
2252
DBG (DBG_io, "%s: steps=%d\n", __FUNCTION__, steps);
2254
/* prepare local registers */
2255
memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
2257
resolution=sanei_genesys_get_lowest_ydpi(dev);
2258
gl846_init_scan_regs (dev,
2268
dev->settings.color_filter,
2269
SCAN_FLAG_DISABLE_SHADING |
2270
SCAN_FLAG_DISABLE_GAMMA |
2272
SCAN_FLAG_IGNORE_LINE_DISTANCE);
2274
/* set exposure to zero */
2275
sanei_genesys_set_triple(local_reg,REG_EXPR,0);
2276
sanei_genesys_set_triple(local_reg,REG_EXPG,0);
2277
sanei_genesys_set_triple(local_reg,REG_EXPB,0);
2279
/* clear scan and feed count */
2280
RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT));
2281
RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT));
2283
/* set up for no scan */
2284
r = sanei_genesys_get_address (local_reg, REG01);
2285
r->value &= ~REG01_SCAN;
2287
/* send registers */
2288
RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS));
2290
status = gl846_start_action (dev);
2291
if (status != SANE_STATUS_GOOD)
2293
DBG (DBG_error, "%s: failed to start motor: %s\n", __FUNCTION__, sane_strstatus (status));
2294
gl846_stop_action (dev);
2296
/* restore original registers */
2297
dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS);
2301
/* wait until feed count reaches the required value, but do not
2305
status = sanei_genesys_get_status (dev, &val);
2307
while (status == SANE_STATUS_GOOD && !(val & FEEDFSH));
2309
/* then stop scanning */
2310
RIE(gl846_stop_action (dev));
2313
return SANE_STATUS_GOOD;
2317
/* init registers for shading calibration */
2319
gl846_init_regs_for_shading (Genesys_Device * dev)
2325
dev->calib_channels = 3;
2327
/* initial calibration reg values */
2328
memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
2330
dev->calib_resolution = sanei_genesys_compute_dpihw(dev,dev->settings.xres);
2331
dev->calib_lines = dev->model->shading_lines;
2332
if(dev->calib_resolution==4800)
2333
dev->calib_lines *= 2;
2334
dev->calib_pixels = (dev->sensor.sensor_pixels*dev->calib_resolution)/dev->sensor.optical_res;
2335
DBG (DBG_io, "%s: calib_lines = %d\n", __FUNCTION__, (unsigned int)dev->calib_lines);
2336
DBG (DBG_io, "%s: calib_pixels = %d\n", __FUNCTION__, (unsigned int)dev->calib_pixels);
2338
/* this is aworkaround insufficent distance for slope
2339
* motor acceleration TODO special motor slope for shading */
2341
if(dev->calib_resolution<1200)
2346
status = gl846_init_scan_regs (dev,
2348
dev->calib_resolution,
2349
dev->calib_resolution,
2355
dev->calib_channels,
2356
dev->settings.color_filter,
2357
SCAN_FLAG_DISABLE_SHADING |
2358
SCAN_FLAG_DISABLE_GAMMA |
2359
SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |
2360
SCAN_FLAG_IGNORE_LINE_DISTANCE);
2362
if (status != SANE_STATUS_GOOD)
2364
DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status));
2368
status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS);
2369
if (status != SANE_STATUS_GOOD)
2371
DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__, sane_strstatus (status));
2375
/* we use GENESYS_FLAG_SHADING_REPARK */
2376
dev->scanhead_position_in_steps = 0;
2379
return SANE_STATUS_GOOD;
2382
/** @brief set up registers for the actual scan
2385
gl846_init_regs_for_scan (Genesys_Device * dev)
2397
"gl846_init_regs_for_scan settings:\nResolution: %uDPI\n"
2398
"Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n",
2399
dev->settings.yres, dev->settings.lines, dev->settings.pixels,
2400
dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode);
2403
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
2409
depth = dev->settings.depth;
2410
if (dev->settings.scan_mode == SCAN_MODE_LINEART)
2414
/* steps to move to reach scanning area:
2415
- first we move to physical start of scanning
2416
either by a fixed steps amount from the black strip
2417
or by a fixed amount from parking position,
2418
minus the steps done during shading calibration
2419
- then we move by the needed offset whitin physical
2422
assumption: steps are expressed at maximum motor resolution
2425
SANE_Fixed y_offset;
2427
SANE_Fixed y_offset_calib;
2428
mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
2430
/* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
2431
relative from origin, else, it is from parking position */
2433
move_dpi = dev->motor.base_ydpi;
2435
move = SANE_UNFIX (dev->model->y_offset);
2436
move += dev->settings.tl_y;
2437
move = (move * move_dpi) / MM_PER_INCH;
2438
move -= dev->scanhead_position_in_steps;
2439
DBG (DBG_info, "%s: move=%f steps\n",__FUNCTION__, move);
2441
/* fast move to scan area */
2442
/* we don't move fast the whole distance since it would involve
2443
* computing acceleration/deceleration distance for scan
2444
* resolution. So leave a remainder for it so scan makes the final
2446
if(channels*dev->settings.yres>=600 && move>700)
2448
status = gl846_feed (dev, move-500);
2449
if (status != SANE_STATUS_GOOD)
2451
DBG (DBG_error, "%s: failed to move to scan area\n",__FUNCTION__);
2457
DBG (DBG_info, "gl846_init_regs_for_scan: move=%f steps\n", move);
2458
DBG (DBG_info, "%s: move=%f steps\n", __FUNCTION__, move);
2461
start = SANE_UNFIX (dev->model->x_offset);
2462
start += dev->settings.tl_x;
2463
start = (start * dev->sensor.optical_res) / MM_PER_INCH;
2467
/* emulated lineart from gray data is required for now */
2468
if(dev->settings.scan_mode == SCAN_MODE_LINEART
2469
&& dev->settings.dynamic_lineart)
2471
flags |= SCAN_FLAG_DYNAMIC_LINEART;
2474
/* backtracking isn't handled well, so don't enable it */
2475
flags |= SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE;
2477
status = gl846_init_scan_regs (dev,
2483
dev->settings.pixels,
2484
dev->settings.lines,
2487
dev->settings.color_filter,
2490
if (status != SANE_STATUS_GOOD)
2494
return SANE_STATUS_GOOD;
2499
* Send shading calibration data. The buffer is considered to always hold values
2500
* for all the channels.
2503
gl846_send_shading_data (Genesys_Device * dev, uint8_t * data, int size)
2505
SANE_Status status = SANE_STATUS_GOOD;
2506
uint32_t addr, length, i, x, factor, pixels;
2507
uint32_t dpiset, dpihw, strpixel, endpixel;
2509
uint32_t lines, channels;
2510
uint8_t val,*buffer,*ptr,*src;
2513
DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size);
2515
/* shading data is plit in 3 (up to 5 with IR) areas
2516
write(0x10014000,0x00000dd8)
2517
URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x....
2518
write(0x1003e000,0x00000dd8)
2519
write(0x10068000,0x00000dd8)
2521
length = (uint32_t) (size / 3);
2522
sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&tempo);
2524
sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&tempo);
2527
/* compute deletion factor */
2528
sanei_genesys_get_double(dev->reg,REG_DPISET,&tempo);
2530
DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d, DPISET=%d\n",__FUNCTION__,strpixel,endpixel,endpixel-strpixel,dpiset);
2531
dpihw=sanei_genesys_compute_dpihw(dev,dpiset);
2532
factor=dpihw/dpiset;
2533
DBG( DBG_io2, "%s: factor=%d\n",__FUNCTION__,factor);
2535
if(DBG_LEVEL>=DBG_data)
2537
dev->binary=fopen("binary.pnm","wb");
2538
sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines);
2539
channels=dev->current_setup.channels;
2540
if(dev->binary!=NULL)
2542
fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255);
2546
pixels=endpixel-strpixel;
2548
/* since we're using SHDAREA, substract startx coordinate from shading */
2549
strpixel-=((dev->sensor.CCD_start_xoffset*600)/dev->sensor.optical_res);
2551
/* turn pixel value into bytes 2x16 bits words */
2555
/* allocate temporary buffer */
2556
buffer=(uint8_t *)malloc(pixels);
2557
memset(buffer,0,pixels);
2558
DBG( DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n",__FUNCTION__,pixels,pixels);
2560
/* base addr of data has been written in reg D0-D4 in 4K word, so AHB address
2561
* is 8192*reg value */
2563
/* write actual color channel data */
2566
/* build up actual shading data by copying the part from the full width one
2567
* to the one corresponding to SHDAREA */
2570
/* iterate on both sensor segment */
2571
for(x=0;x<pixels;x+=4*factor)
2573
/* coefficient source */
2574
src=(data+strpixel+i*length)+x;
2576
/* coefficient copy */
2582
/* next shading coefficient */
2586
RIE (sanei_genesys_read_register (dev, 0xd0+i, &val));
2587
addr = val * 8192 + 0x10000000;
2588
status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, addr, pixels, buffer);
2589
if (status != SANE_STATUS_GOOD)
2591
DBG (DBG_error, "gl846_send_shading_data; write to AHB failed (%s)\n",
2592
sane_strstatus (status));
2603
/** @brief calibrates led exposure
2604
* Calibrate exposure by scanning a white area until the used exposure gives
2605
* data white enough.
2606
* @param dev device to calibrate
2609
gl846_led_calibration (Genesys_Device * dev)
2616
SANE_Status status = SANE_STATUS_GOOD;
2618
int channels, depth;
2619
int avg[3], top[3], bottom[3];
2623
Sensor_Profile *sensor;
2625
SANE_Bool acceptable;
2629
move = SANE_UNFIX (dev->model->y_offset_calib);
2630
move = (move * (dev->motor.base_ydpi/4)) / MM_PER_INCH;
2633
RIE(gl846_feed (dev, move));
2635
DBG (DBG_io, "%s: move=%f steps\n", __FUNCTION__, move);
2637
/* offset calibration is always done in color mode */
2640
used_res=sanei_genesys_compute_dpihw(dev,dev->settings.xres);
2641
sensor=get_sensor_profile(dev->model->ccd_type, used_res);
2642
num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res;
2644
/* initial calibration reg values */
2645
memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
2647
/* set up for the calibration scan */
2648
status = gl846_init_scan_regs (dev,
2658
dev->settings.color_filter,
2659
SCAN_FLAG_DISABLE_SHADING |
2660
SCAN_FLAG_DISABLE_GAMMA |
2661
SCAN_FLAG_SINGLE_LINE |
2662
SCAN_FLAG_IGNORE_LINE_DISTANCE);
2663
if (status != SANE_STATUS_GOOD)
2665
DBG (DBG_error, "%s: failed to setup scan: %s\n", __FUNCTION__, sane_strstatus (status));
2669
total_size = num_pixels * channels * (depth/8) * 1; /* colors * bytes_per_color * scan lines */
2670
line = malloc (total_size);
2672
return SANE_STATUS_NO_MEM;
2674
/* initial loop values and boundaries */
2675
exp[0]=sensor->expr;
2676
exp[1]=sensor->expg;
2677
exp[2]=sensor->expb;
2689
/* no move during led calibration */
2690
gl846_set_motor_power (dev->calib_reg, SANE_FALSE);
2693
/* set up exposure */
2694
sanei_genesys_set_double(dev->calib_reg,REG_EXPR,exp[0]);
2695
sanei_genesys_set_double(dev->calib_reg,REG_EXPG,exp[1]);
2696
sanei_genesys_set_double(dev->calib_reg,REG_EXPB,exp[2]);
2698
/* write registers and scan data */
2699
RIEF (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), line);
2701
DBG (DBG_info, "gl846_led_calibration: starting line reading\n");
2702
RIEF (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), line);
2703
RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line);
2706
RIEF (gl846_stop_action (dev), line);
2708
if (DBG_LEVEL >= DBG_data)
2710
snprintf (fn, 20, "led_%02d.pnm", turn);
2711
sanei_genesys_write_pnm_file (fn, line, depth, channels, num_pixels, 1);
2714
/* compute average */
2715
for (j = 0; j < channels; j++)
2718
for (i = 0; i < num_pixels; i++)
2720
if (dev->model->is_cis)
2722
line[i * 2 + j * 2 * num_pixels + 1] * 256 +
2723
line[i * 2 + j * 2 * num_pixels];
2726
line[i * 2 * channels + 2 * j + 1] * 256 +
2727
line[i * 2 * channels + 2 * j];
2731
avg[j] /= num_pixels;
2734
DBG (DBG_info, "gl846_led_calibration: average: %d,%d,%d\n", avg[0], avg[1], avg[2]);
2736
/* check if exposure gives average within the boundaries */
2737
acceptable = SANE_TRUE;
2740
if(avg[i]<bottom[i])
2742
exp[i]=(exp[i]*bottom[i])/avg[i];
2743
acceptable = SANE_FALSE;
2747
exp[i]=(exp[i]*top[i])/avg[i];
2748
acceptable = SANE_FALSE;
2754
while (!acceptable && turn < 100);
2756
DBG (DBG_info, "gl846_led_calibration: acceptable exposure: %d,%d,%d\n", exp[0], exp[1], exp[2]);
2758
/* set these values as final ones for scan */
2759
sanei_genesys_set_double(dev->reg,REG_EXPR,exp[0]);
2760
sanei_genesys_set_double(dev->reg,REG_EXPG,exp[1]);
2761
sanei_genesys_set_double(dev->reg,REG_EXPB,exp[2]);
2763
/* store in this struct since it is the one used by cache calibration */
2764
dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff;
2765
dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff;
2766
dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff;
2767
dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff;
2768
dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff;
2769
dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff;
2771
/* cleanup before return */
2777
status=gl846_slow_back_home (dev, SANE_TRUE);
2785
* set up GPIO/GPOE for idle state
2788
gl846_init_gpio (Genesys_Device * dev)
2790
SANE_Status status = SANE_STATUS_GOOD;
2795
/* search GPIO profile */
2796
while(gpios[idx].sensor_id!=0 && dev->model->gpo_type!=gpios[idx].sensor_id)
2800
if(gpios[idx].sensor_id==0)
2802
DBG (DBG_error, "%s: failed to find GPIO profile for sensor_id=%d\n", __FUNCTION__, dev->model->ccd_type);
2803
return SANE_STATUS_INVAL;
2806
RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7));
2807
RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6));
2809
RIE (sanei_genesys_write_register (dev, REG6B, gpios[idx].r6b));
2810
RIE (sanei_genesys_write_register (dev, REG6C, gpios[idx].r6c));
2811
RIE (sanei_genesys_write_register (dev, REG6D, gpios[idx].r6d));
2812
RIE (sanei_genesys_write_register (dev, REG6E, gpios[idx].r6e));
2813
RIE (sanei_genesys_write_register (dev, REG6F, gpios[idx].r6f));
2815
RIE (sanei_genesys_write_register (dev, REGA8, gpios[idx].ra8));
2816
RIE (sanei_genesys_write_register (dev, REGA9, gpios[idx].ra9));
2823
* set memory layout by filling values in dedicated registers
2826
gl846_init_memory_layout (Genesys_Device * dev)
2828
SANE_Status status = SANE_STATUS_GOOD;
2834
/* point to per model memory layout */
2836
while(layouts[idx].model!=NULL && strcmp(dev->model->name,layouts[idx].model)!=0)
2838
if(strcmp(dev->model->name,layouts[idx].model)!=0)
2841
if(layouts[idx].model==NULL)
2843
DBG(DBG_error, "%s: failed to find memory layout for model %s!\n", __FUNCTION__, dev->model->name);
2844
return SANE_STATUS_INVAL;
2847
/* CLKSET and DRAMSEL */
2848
val = layouts[idx].dramsel;
2849
RIE (sanei_genesys_write_register (dev, REG0B, val));
2850
dev->reg[reg_0x0b].value = val;
2852
/* prevent further writings by bulk write register */
2853
dev->reg[reg_0x0b].address = 0x00;
2855
/* setup base address for shading and scanned data. */
2858
sanei_genesys_write_register (dev, 0xe0+i, layouts[idx].rx[i]);
2866
* initialize ASIC from power on condition
2868
#ifndef UNIT_TESTING
2872
gl846_boot (Genesys_Device * dev, SANE_Bool cold)
2879
/* reset ASIC if cold boot */
2882
RIE (sanei_genesys_write_register (dev, 0x0e, 0x01));
2883
RIE (sanei_genesys_write_register (dev, 0x0e, 0x00));
2886
if(dev->usb_mode == 1)
2894
RIE (sanei_genesys_write_0x8c (dev, 0x0f, val));
2897
RIE (sanei_genesys_read_register (dev, REG40, &val));
2898
if (val & REG40_CHKVER)
2900
RIE (sanei_genesys_read_register (dev, 0x00, &val));
2901
DBG (DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __FUNCTION__, val);
2904
/* Set default values for registers */
2905
gl846_init_registers (dev);
2907
/* Write initial registers */
2908
RIE (dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS));
2910
/* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */
2911
val = dev->reg[reg_0x0b].value & REG0B_DRAMSEL;
2912
val = (val | REG0B_ENBDRAM);
2913
RIE (sanei_genesys_write_register (dev, REG0B, val));
2914
dev->reg[reg_0x0b].value = val;
2917
if (dev->model->is_cis)
2919
SETREG (0x08, REG08_CIS_LINE);
2920
RIE (sanei_genesys_write_register (dev, 0x08, dev->reg[reg_0x08].value));
2924
RIE (sanei_genesys_write_0x8c (dev, 0x10, 0x0e));
2925
RIE (sanei_genesys_write_0x8c (dev, 0x13, 0x0e));
2928
RIE (gl846_init_gpio (dev));
2930
/* setup internal memory layout */
2931
RIE (gl846_init_memory_layout (dev));
2933
SETREG (0xf8, 0x05);
2934
RIE (sanei_genesys_write_register (dev, 0xf8, dev->reg[reg_0xf8].value));
2937
return SANE_STATUS_GOOD;
2941
* initialize backend and ASIC : registers, motor tables, and gamma tables
2942
* then ensure scanner's head is at home
2944
#ifndef UNIT_TESTING
2947
SANE_Status gl846_init (Genesys_Device * dev)
2954
status=sanei_genesys_asic_init(dev, GENESYS_GL846_MAX_REGS);
2961
gl846_update_hardware_sensors (Genesys_Scanner * s)
2963
/* do what is needed to get a new set of events, but try to not lose
2966
SANE_Status status = SANE_STATUS_GOOD;
2968
uint8_t scan, file, email, copy;
2969
switch(s->dev->model->gpo_type)
2977
RIE (sanei_genesys_read_register (s->dev, REG6D, &val));
2979
if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b)
2980
s->val[OPT_SCAN_SW].b = (val & scan) == 0;
2981
if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b)
2982
s->val[OPT_FILE_SW].b = (val & file) == 0;
2983
if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b)
2984
s->val[OPT_EMAIL_SW].b = (val & email) == 0;
2985
if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b)
2986
s->val[OPT_COPY_SW].b = (val & copy) == 0;
2991
/** @brief search for a full width black or white strip.
2992
* This function searches for a black or white stripe across the scanning area.
2993
* When searching backward, the searched area must completely be of the desired
2994
* color since this area will be used for calibration which scans forward.
2995
* @param dev scanner device
2996
* @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward
2997
* @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip
2998
* @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not
3001
gl846_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
3003
unsigned int pixels, lines, channels;
3005
Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS];
3008
int steps, depth, dpi;
3009
unsigned int pass, count, found, x, y;
3011
Genesys_Register_Set *r;
3013
DBG (DBG_proc, "gl846_search_strip %s %s\n", black ? "black" : "white",
3014
forward ? "forward" : "reverse");
3016
gl846_set_fe (dev, AFE_SET);
3017
status = gl846_stop_action (dev);
3018
if (status != SANE_STATUS_GOOD)
3021
"gl846_search_strip: failed to stop: %s\n",
3022
sane_strstatus (status));
3026
/* set up for a gray scan at lowest dpi */
3028
for (x = 0; x < MAX_RESOLUTIONS; x++)
3030
if (dev->model->xdpi_values[x] > 0 && dev->model->xdpi_values[x] < dpi)
3031
dpi = dev->model->xdpi_values[x];
3035
/* lines = (10 * dpi) / MM_PER_INCH; */
3036
/* shading calibation is done with dev->motor.base_ydpi */
3037
lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
3039
pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res;
3040
size = pixels * channels * lines * (depth / 8);
3041
data = malloc (size);
3044
DBG (DBG_error, "gl846_search_strip: failed to allocate memory\n");
3045
return SANE_STATUS_NO_MEM;
3047
dev->scanhead_position_in_steps = 0;
3049
memcpy (local_reg, dev->reg,
3050
GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set));
3052
status = gl846_init_scan_regs (dev,
3063
SCAN_FLAG_DISABLE_SHADING |
3064
SCAN_FLAG_DISABLE_GAMMA);
3065
if (status != SANE_STATUS_GOOD)
3069
"gl846_search_strip: failed to setup for scan: %s\n",
3070
sane_strstatus (status));
3074
/* set up for reverse or forward */
3075
r = sanei_genesys_get_address (local_reg, REG02);
3077
r->value &= ~REG02_MTRREV;
3079
r->value |= REG02_MTRREV;
3082
status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS);
3083
if (status != SANE_STATUS_GOOD)
3087
"gl846_search_strip: Failed to bulk write registers: %s\n",
3088
sane_strstatus (status));
3092
status = gl846_begin_scan (dev, local_reg, SANE_TRUE);
3093
if (status != SANE_STATUS_GOOD)
3097
"gl846_search_strip: failed to begin scan: %s\n",
3098
sane_strstatus (status));
3102
/* waits for valid data */
3104
sanei_genesys_test_buffer_empty (dev, &steps);
3107
/* now we're on target, we can read data */
3108
status = sanei_genesys_read_data_from_scanner (dev, data, size);
3109
if (status != SANE_STATUS_GOOD)
3113
"gl846_search_start_position: failed to read data: %s\n",
3114
sane_strstatus (status));
3118
status = gl846_stop_action (dev);
3119
if (status != SANE_STATUS_GOOD)
3122
DBG (DBG_error, "gl846_search_strip: gl846_stop_action failed\n");
3127
if (DBG_LEVEL >= DBG_data)
3129
sprintf (title, "search_strip_%s_%s%02d.pnm",
3130
black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass);
3131
sanei_genesys_write_pnm_file (title, data, depth, channels, pixels,
3135
/* loop until strip is found or maximum pass number done */
3137
while (pass < 20 && !found)
3139
status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS);
3140
if (status != SANE_STATUS_GOOD)
3143
"gl846_search_strip: Failed to bulk write registers: %s\n",
3144
sane_strstatus (status));
3148
/* now start scan */
3149
status = gl846_begin_scan (dev, local_reg, SANE_TRUE);
3150
if (status != SANE_STATUS_GOOD)
3154
"gl846_search_strip: failed to begin scan: %s\n",
3155
sane_strstatus (status));
3159
/* waits for valid data */
3161
sanei_genesys_test_buffer_empty (dev, &steps);
3164
/* now we're on target, we can read data */
3165
status = sanei_genesys_read_data_from_scanner (dev, data, size);
3166
if (status != SANE_STATUS_GOOD)
3170
"gl846_search_start_position: failed to read data: %s\n",
3171
sane_strstatus (status));
3175
status = gl846_stop_action (dev);
3176
if (status != SANE_STATUS_GOOD)
3179
DBG (DBG_error, "gl846_search_strip: gl846_stop_action failed\n");
3183
if (DBG_LEVEL >= DBG_data)
3185
sprintf (title, "search_strip_%s_%s%02d.pnm",
3186
black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass);
3187
sanei_genesys_write_pnm_file (title, data, depth, channels,
3191
/* search data to find black strip */
3192
/* when searching forward, we only need one line of the searched color since we
3193
* will scan forward. But when doing backward search, we need all the area of the
3197
for (y = 0; y < lines && !found; y++)
3200
/* count of white/black pixels depending on the color searched */
3201
for (x = 0; x < pixels; x++)
3203
/* when searching for black, detect white pixels */
3204
if (black && data[y * pixels + x] > 90)
3208
/* when searching for white, detect black pixels */
3209
if (!black && data[y * pixels + x] < 60)
3215
/* at end of line, if count >= 3%, line is not fully of the desired color
3216
* so we must go to next line of the buffer */
3217
/* count*100/pixels < 3 */
3218
if ((count * 100) / pixels < 3)
3222
"gl846_search_strip: strip found forward during pass %d at line %d\n",
3228
"gl846_search_strip: pixels=%d, count=%d (%d%%)\n",
3229
pixels, count, (100 * count) / pixels);
3233
else /* since calibration scans are done forward, we need the whole area
3234
to be of the required color when searching backward */
3237
for (y = 0; y < lines; y++)
3239
/* count of white/black pixels depending on the color searched */
3240
for (x = 0; x < pixels; x++)
3242
/* when searching for black, detect white pixels */
3243
if (black && data[y * pixels + x] > 90)
3247
/* when searching for white, detect black pixels */
3248
if (!black && data[y * pixels + x] < 60)
3255
/* at end of area, if count >= 3%, area is not fully of the desired color
3256
* so we must go to next buffer */
3257
if ((count * 100) / (pixels * lines) < 3)
3261
"gl846_search_strip: strip found backward during pass %d \n",
3267
"gl846_search_strip: pixels=%d, count=%d (%d%%)\n",
3268
pixels, count, (100 * count) / pixels);
3276
status = SANE_STATUS_GOOD;
3277
DBG (DBG_info, "gl846_search_strip: %s strip found\n",
3278
black ? "black" : "white");
3282
status = SANE_STATUS_UNSUPPORTED;
3283
DBG (DBG_info, "gl846_search_strip: %s strip not found\n",
3284
black ? "black" : "white");
3292
* average dark pixels of a 8 bits scan
3295
dark_average (uint8_t * data, unsigned int pixels, unsigned int lines,
3296
unsigned int channels, unsigned int black)
3298
unsigned int i, j, k, average, count;
3299
unsigned int avg[3];
3302
/* computes average value on black margin */
3303
for (k = 0; k < channels; k++)
3307
for (i = 0; i < lines; i++)
3309
for (j = 0; j < black; j++)
3311
val = data[i * channels * pixels + j + k];
3318
DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]);
3321
for (i = 0; i < channels; i++)
3323
average /= channels;
3324
DBG (DBG_info, "dark_average: average = %d\n", average);
3329
gl846_offset_calibration (Genesys_Device * dev)
3331
SANE_Status status = SANE_STATUS_GOOD;
3332
uint8_t *first_line, *second_line, reg04;
3333
unsigned int channels, bpp;
3335
int pass = 0, avg, total_size;
3336
int topavg, bottomavg, resolution, lines;
3337
int top, bottom, black_pixels, pixels;
3341
/* no gain nor offset for AKM AFE */
3342
RIE (sanei_genesys_read_register (dev, REG04, ®04));
3343
if ((reg04 & REG04_FESET) == 0x02)
3349
/* offset calibration is always done in color mode */
3351
resolution=dev->sensor.optical_res;
3352
dev->calib_pixels = dev->sensor.sensor_pixels;
3355
pixels= (dev->sensor.sensor_pixels*resolution) / dev->sensor.optical_res;
3356
black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res;
3357
DBG (DBG_io2, "gl846_offset_calibration: black_pixels=%d\n", black_pixels);
3359
status = gl846_init_scan_regs (dev,
3369
dev->settings.color_filter,
3370
SCAN_FLAG_DISABLE_SHADING |
3371
SCAN_FLAG_DISABLE_GAMMA |
3372
SCAN_FLAG_SINGLE_LINE |
3373
SCAN_FLAG_IGNORE_LINE_DISTANCE);
3374
if (status != SANE_STATUS_GOOD)
3377
"gl846_offset_calibration: failed to setup scan: %s\n",
3378
sane_strstatus (status));
3381
gl846_set_motor_power (dev->calib_reg, SANE_FALSE);
3383
/* allocate memory for scans */
3384
total_size = pixels * channels * lines * (bpp/8); /* colors * bytes_per_color * scan lines */
3386
first_line = malloc (total_size);
3388
return SANE_STATUS_NO_MEM;
3390
second_line = malloc (total_size);
3394
return SANE_STATUS_NO_MEM;
3398
dev->frontend.gain[0] = 0;
3399
dev->frontend.gain[1] = 0;
3400
dev->frontend.gain[2] = 0;
3402
/* scan with no move */
3404
dev->frontend.offset[0] = bottom;
3405
dev->frontend.offset[1] = bottom;
3406
dev->frontend.offset[2] = bottom;
3408
RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line);
3409
RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line);
3410
DBG (DBG_info, "gl846_offset_calibration: starting first line reading\n");
3411
RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line);
3412
RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line);
3413
if (DBG_LEVEL >= DBG_data)
3415
snprintf(title,20,"offset%03d.pnm",bottom);
3416
sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines);
3419
bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels);
3420
DBG (DBG_io2, "gl846_offset_calibration: bottom avg=%d\n", bottomavg);
3424
dev->frontend.offset[0] = top;
3425
dev->frontend.offset[1] = top;
3426
dev->frontend.offset[2] = top;
3427
RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line);
3428
RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line);
3429
DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n");
3430
RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line);
3431
RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line);
3433
topavg = dark_average (second_line, pixels, lines, channels, black_pixels);
3434
DBG (DBG_io2, "gl846_offset_calibration: top avg=%d\n", topavg);
3436
/* loop until acceptable level */
3437
while ((pass < 32) && (top - bottom > 1))
3441
/* settings for new scan */
3442
dev->frontend.offset[0] = (top + bottom) / 2;
3443
dev->frontend.offset[1] = (top + bottom) / 2;
3444
dev->frontend.offset[2] = (top + bottom) / 2;
3446
/* scan with no move */
3447
RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line);
3448
RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line);
3449
DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n");
3450
RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line);
3451
RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line);
3453
if (DBG_LEVEL >= DBG_data)
3455
sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]);
3456
sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines);
3459
avg = dark_average (second_line, pixels, lines, channels, black_pixels);
3460
DBG (DBG_info, "gl846_offset_calibration: avg=%d offset=%d\n", avg,
3461
dev->frontend.offset[1]);
3463
/* compute new boundaries */
3467
top = dev->frontend.offset[1];
3472
bottom = dev->frontend.offset[1];
3475
DBG (DBG_info, "gl846_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]);
3477
/* cleanup before return */
3482
return SANE_STATUS_GOOD;
3486
gl846_coarse_gain_calibration (Genesys_Device * dev, int dpi)
3490
uint8_t *line, reg04;
3492
SANE_Status status = SANE_STATUS_GOOD;
3494
float gain[3],coeff;
3495
int val, code, lines;
3499
DBG (DBG_proc, "gl846_coarse_gain_calibration: dpi = %d\n", dpi);
3501
/* no gain nor offset for AKM AFE */
3502
RIE (sanei_genesys_read_register (dev, REG04, ®04));
3503
if ((reg04 & REG04_FESET) == 0x02)
3509
/* coarse gain calibration is always done in color mode */
3513
if(dev->settings.xres<dev->sensor.optical_res)
3516
/*resolution=dev->sensor.optical_res/2;*/
3517
resolution=dev->sensor.optical_res;
3521
resolution=dev->sensor.optical_res;
3526
pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res;
3528
status = gl846_init_scan_regs (dev,
3538
dev->settings.color_filter,
3539
SCAN_FLAG_DISABLE_SHADING |
3540
SCAN_FLAG_DISABLE_GAMMA |
3541
SCAN_FLAG_SINGLE_LINE |
3542
SCAN_FLAG_IGNORE_LINE_DISTANCE);
3543
gl846_set_motor_power (dev->calib_reg, SANE_FALSE);
3545
if (status != SANE_STATUS_GOOD)
3548
"gl846_coarse_calibration: failed to setup scan: %s\n",
3549
sane_strstatus (status));
3553
RIE (dev->model->cmd_set->bulk_write_register
3554
(dev, dev->calib_reg, GENESYS_GL846_MAX_REGS));
3556
total_size = pixels * channels * (16/bpp) * lines;
3558
line = malloc (total_size);
3560
return SANE_STATUS_NO_MEM;
3562
RIEF (gl846_set_fe(dev, AFE_SET), line);
3563
RIEF (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), line);
3564
RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line);
3566
if (DBG_LEVEL >= DBG_data)
3567
sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines);
3569
/* average value on each channel */
3570
for (j = 0; j < channels; j++)
3573
for (i = pixels/4; i < (pixels*3/4); i++)
3577
if (dev->model->is_cis)
3579
line[i * 2 + j * 2 * pixels + 1] * 256 +
3580
line[i * 2 + j * 2 * pixels];
3583
line[i * 2 * channels + 2 * j + 1] * 256 +
3584
line[i * 2 * channels + 2 * j];
3588
if (dev->model->is_cis)
3589
val = line[i + j * pixels];
3591
val = line[i * channels + j];
3596
max[j] = max[j] / (pixels/2);
3598
gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j];
3600
/* turn logical gain value into gain code, checking for overflow */
3601
code = 283 - 208 / gain[j];
3606
dev->frontend.gain[j] = code;
3609
"gl846_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n",
3610
j, max[j], gain[j], dev->frontend.gain[j]);
3613
if (dev->model->is_cis)
3615
if (dev->frontend.gain[0] > dev->frontend.gain[1])
3616
dev->frontend.gain[0] = dev->frontend.gain[1];
3617
if (dev->frontend.gain[0] > dev->frontend.gain[2])
3618
dev->frontend.gain[0] = dev->frontend.gain[2];
3619
dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0];
3624
dev->frontend.gain[0] = dev->frontend.gain[1];
3625
dev->frontend.gain[2] = dev->frontend.gain[1];
3630
RIE (gl846_stop_action (dev));
3632
status=gl846_slow_back_home (dev, SANE_TRUE);
3639
/** the gl846 command set */
3640
static Genesys_Command_Set gl846_cmd_set = {
3641
"gl846-generic", /* the name of this set */
3645
gl846_init_regs_for_coarse_calibration,
3646
gl846_init_regs_for_shading,
3647
gl846_init_regs_for_scan,
3649
gl846_get_filter_bit,
3650
gl846_get_lineart_bit,
3651
gl846_get_bitset_bit,
3652
gl846_get_gain4_bit,
3653
gl846_get_fast_feed_bit,
3654
gl846_test_buffer_empty_bit,
3655
gl846_test_motor_flag_bit,
3657
gl846_bulk_full_size,
3660
gl846_set_powersaving,
3663
gl846_set_motor_power,
3664
gl846_set_lamp_power,
3669
sanei_genesys_send_gamma_table,
3671
gl846_search_start_position,
3673
gl846_offset_calibration,
3674
gl846_coarse_gain_calibration,
3675
gl846_led_calibration,
3677
gl846_slow_back_home,
3679
sanei_genesys_bulk_write_register,
3681
gl846_bulk_read_data,
3683
gl846_update_hardware_sensors,
3690
sanei_genesys_is_compatible_calibration,
3692
gl846_send_shading_data,
3693
gl846_calculate_current_setup,
3698
sanei_gl846_init_cmd_set (Genesys_Device * dev)
3700
dev->model->cmd_set = &gl846_cmd_set;
3701
return SANE_STATUS_GOOD;
3704
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */