* Added support for Canon LiDE 35/40/50

* Reworked data conversion process to convert CIS data
merge-requests/1/head
Pierre Willenbrock 2005-11-19 22:51:01 +00:00
rodzic 0b1279193f
commit 02b1a07b5d
8 zmienionych plików z 5388 dodań i 3311 usunięć

Wyświetl plik

@ -1,3 +1,15 @@
2005-11-19 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
* backend/genesys_gl841.c backend/genesys_devices.c:
Added support for Canon LiDE 35/40/50
* backend/genesys.c backend/genesys_low.h
backend/genesys_gl646.c: Reworked data conversion
process to convert CIS data, added new slope
generation variant
* backend/genesys_conv.c backend/genesys_conv_hlp.c:
Moved conversion filter functions out of
backend/genesys.c
2005-11-18 Oliver Schwartz <Oliver.Schwartz@gmx.de>
* backend/snapscan-options.c: Disable 2400 DPI for

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,151 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2005 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
*/
/*
* Conversion filters for genesys backend
*/
/*8 bit*/
#define SINGLE_BYTE
#define BYTES_PER_COMPONENT 1
#define COMPONENT_TYPE u_int8_t
#define FUNC_NAME(f) f ## _8
#include "genesys_conv_hlp.c"
#undef FUNC_NAME
#undef COMPONENT_TYPE
#undef BYTES_PER_COMPONENT
#undef SINGLE_BYTE
/*16 bit*/
#define DOUBLE_BYTE
#define BYTES_PER_COMPONENT 2
#define COMPONENT_TYPE u_int16_t
#define FUNC_NAME(f) f ## _16
#include "genesys_conv_hlp.c"
#undef FUNC_NAME
#undef COMPONENT_TYPE
#undef BYTES_PER_COMPONENT
#undef DOUBLE_BYTE
static SANE_Status
genesys_reverse_bits(
u_int8_t *src_data,
u_int8_t *dst_data,
size_t bytes)
{
size_t i;
for(i = 0; i < bytes; i++) {
*dst_data++ = ~ *src_data++;
}
return SANE_STATUS_GOOD;
}
static SANE_Status
genesys_shrink_lines_1 (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int src_pixels,
unsigned int dst_pixels,
unsigned int channels)
{
/*in search for a correct implementation*/
unsigned int dst_x, src_x, y, c, cnt;
unsigned int avg[3];
u_int8_t *src = (u_int8_t *)src_data;
u_int8_t *dst = (u_int8_t *)dst_data;
src_pixels /= 8;
dst_pixels /= 8;
if (src_pixels > dst_pixels) {
/*take first _byte_*/
for(y = 0; y < lines; y++) {
cnt = src_pixels / 2;
src_x = 0;
for (dst_x = 0; dst_x < dst_pixels; dst_x++) {
while (cnt < src_pixels && src_x < src_pixels) {
cnt += dst_pixels;
for (c = 0; c < channels; c++)
avg[c] = *src++;
src_x++;
}
cnt -= src_pixels;
for (c = 0; c < channels; c++)
*dst++ = avg[c];
}
}
} else {
/*interpolate. copy pixels*/
for(y = 0; y < lines; y++) {
cnt = dst_pixels / 2;
dst_x = 0;
for (src_x = 0; src_x < src_pixels; src_x++) {
for (c = 0; c < channels; c++)
avg[c] = *src++;
while (cnt < dst_pixels && dst_x < dst_pixels) {
cnt += src_pixels;
for (c = 0; c < channels; c++)
*dst++ = avg[c];
dst_x++;
}
cnt -= dst_pixels;
}
}
}
return SANE_STATUS_GOOD;
}

Wyświetl plik

@ -0,0 +1,341 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2005 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
*/
/*
* Conversion filters for genesys backend
*/
static SANE_Status
FUNC_NAME(genesys_reorder_components_cis) (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int pixels)
{
unsigned int x, y;
u_int8_t *src[3];
u_int8_t *dst = dst_data;
unsigned int rest = pixels * 2 * BYTES_PER_COMPONENT;
src[0] = src_data + pixels * BYTES_PER_COMPONENT * 0;
src[1] = src_data + pixels * BYTES_PER_COMPONENT * 1;
src[2] = src_data + pixels * BYTES_PER_COMPONENT * 2;
for(y = 0; y < lines; y++) {
for(x = 0; x < pixels; x++) {
#ifndef DOUBLE_BYTE
*dst++ = *src[0]++;
*dst++ = *src[1]++;
*dst++ = *src[2]++;
#else
# ifndef WORDS_BIGENDIAN
*dst++ = *src[0]++;
*dst++ = *src[0]++;
*dst++ = *src[1]++;
*dst++ = *src[1]++;
*dst++ = *src[2]++;
*dst++ = *src[2]++;
# else
*dst++ = src[0][1];
*dst++ = src[0][0];
*dst++ = src[1][1];
*dst++ = src[1][0];
*dst++ = src[2][1];
*dst++ = src[2][0];
src[0] += 2;
src[1] += 2;
src[2] += 2;
# endif
#endif
}
src[0] += rest;
src[1] += rest;
src[2] += rest;
}
return SANE_STATUS_GOOD;
}
static SANE_Status
FUNC_NAME(genesys_reorder_components_cis_bgr) (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int pixels)
{
unsigned int x, y;
u_int8_t *src[3];
u_int8_t *dst = dst_data;
unsigned int rest = pixels * 2 * BYTES_PER_COMPONENT;
src[0] = src_data + pixels * BYTES_PER_COMPONENT * 0;
src[1] = src_data + pixels * BYTES_PER_COMPONENT * 1;
src[2] = src_data + pixels * BYTES_PER_COMPONENT * 2;
for(y = 0; y < lines; y++) {
for(x = 0; x < pixels; x++) {
#ifndef DOUBLE_BYTE
*dst++ = *src[2]++;
*dst++ = *src[1]++;
*dst++ = *src[0]++;
#else
# ifndef WORDS_BIGENDIAN
*dst++ = *src[2]++;
*dst++ = *src[2]++;
*dst++ = *src[1]++;
*dst++ = *src[1]++;
*dst++ = *src[0]++;
*dst++ = *src[0]++;
# else
*dst++ = src[2][1];
*dst++ = src[2][0];
*dst++ = src[1][1];
*dst++ = src[1][0];
*dst++ = src[0][1];
*dst++ = src[0][0];
src[0] += 2;
src[1] += 2;
src[2] += 2;
# endif
#endif
}
src[0] += rest;
src[1] += rest;
src[2] += rest;
}
return SANE_STATUS_GOOD;
}
static SANE_Status
FUNC_NAME(genesys_reorder_components_bgr) (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int pixels)
{
unsigned int c;
u_int8_t *src = src_data;
u_int8_t *dst = dst_data;
for(c = 0; c < lines * pixels; c++) {
#ifndef DOUBLE_BYTE
*dst++ = src[2];
*dst++ = src[1];
*dst++ = src[0];
src += 3;
#else
# ifndef WORDS_BIGENDIAN
*dst++ = src[2 * 2 + 0];
*dst++ = src[2 * 2 + 1];
*dst++ = src[1 * 2 + 0];
*dst++ = src[1 * 2 + 1];
*dst++ = src[0 * 2 + 0];
*dst++ = src[0 * 2 + 1];
# else
*dst++ = src[2 * 2 + 1];
*dst++ = src[2 * 2 + 0];
*dst++ = src[1 * 2 + 1];
*dst++ = src[1 * 2 + 0];
*dst++ = src[0 * 2 + 1];
*dst++ = src[0 * 2 + 0];
# endif
src += 3 * 2;
#endif
}
return SANE_STATUS_GOOD;
}
#if defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN)
static SANE_Status
FUNC_NAME(genesys_reorder_components_endian) (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int pixels,
unsigned int channels)
{
unsigned int c;
u_int8_t *src = src_data;
u_int8_t *dst = dst_data;
for(c = 0; c < lines * pixels * channels; c++) {
*dst++ = src[1];
*dst++ = src[0];
src += 2;
}
return SANE_STATUS_GOOD;
}
#endif /*defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN)*/
static SANE_Status
FUNC_NAME(genesys_reverse_ccd) (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int pixels,
unsigned int channels,
unsigned int *ccd_shift,
unsigned int component_count)
{
unsigned int x, y, c;
COMPONENT_TYPE *src = (COMPONENT_TYPE *)src_data;
COMPONENT_TYPE *dst = (COMPONENT_TYPE *)dst_data;
COMPONENT_TYPE *srcp;
COMPONENT_TYPE *dstp;
unsigned int pitch = pixels * channels;
unsigned int ccd_shift_pitch[12];
unsigned int *csp;
for (c = 0; c < component_count; c++)
ccd_shift_pitch[c] = ccd_shift[c] * pitch;
/*
* cache efficiency:
we are processing a single line component_count times, so it should fit
into the cpu cache for maximum efficiency. our lines take
maximum 252kb(3 channels, 16bit, 2400dpi, full gl841 shading range)
* instruction efficiency:
the innermost loop runs long and consists of 3 adds, one compare,
2 derefences.
*/
/*
for (y = 0; y < lines; y++) {
csp = ccd_shift_pitch;
for (c = 0; c < component_count; c++) {
srcp = src + c + *csp++;
dstp = dst + c;
for (x = 0; x < pitch; x += component_count) {
*dstp = *srcp;
srcp += component_count;
dstp += component_count;
}
}
dst += pitch;
src += pitch;
}
*/
/*
* cache efficency:
here only line_dist_pitch needs to stay in cache. 12*4 = 48 bytes
* instruction efficiency:
we have a short running inner loop, consisting of 4 incs, 2 compare, 1 add,
2 dereference and 1 indexed dereference.
the enclosing loop is long running, consisting of 1 add, 1 compare.
*/
srcp = src;
dstp = dst;
for (y = 0; y < lines; y++) {
for (x = 0; x < pitch; x += component_count) {
csp = ccd_shift_pitch;
for (c = 0; c < component_count && c + x < pitch; c++) {
*dstp = srcp[*csp++];
dstp++;
srcp++;
}
}
}
return SANE_STATUS_GOOD;
}
static SANE_Status
FUNC_NAME(genesys_shrink_lines) (
u_int8_t *src_data,
u_int8_t *dst_data,
unsigned int lines,
unsigned int src_pixels,
unsigned int dst_pixels,
unsigned int channels)
{
unsigned int dst_x, src_x, y, c, cnt;
unsigned int avg[3];
unsigned int count;
COMPONENT_TYPE *src = (COMPONENT_TYPE *)src_data;
COMPONENT_TYPE *dst = (COMPONENT_TYPE *)dst_data;
if (src_pixels > dst_pixels) {
/*average*/
for(y = 0; y < lines; y++) {
cnt = src_pixels / 2;
src_x = 0;
for (dst_x = 0; dst_x < dst_pixels; dst_x++) {
count = 0;
while (cnt < src_pixels && src_x < src_pixels) {
cnt += dst_pixels;
for (c = 0; c < channels; c++)
avg[c] += *src++;
src_x++;
count++;
}
cnt -= src_pixels;
for (c = 0; c < channels; c++)
*dst++ = avg[c] / count;
}
}
} else {
/*interpolate. copy pixels*/
for(y = 0; y < lines; y++) {
cnt = dst_pixels / 2;
dst_x = 0;
for (src_x = 0; src_x < src_pixels; src_x++) {
for (c = 0; c < channels; c++)
avg[c] = *src++;
while (cnt < dst_pixels && dst_x < dst_pixels) {
cnt += src_pixels;
for (c = 0; c < channels; c++)
*dst++ = avg[c];
dst_x++;
}
cnt -= dst_pixels;
}
}
}
return SANE_STATUS_GOOD;
}

Wyświetl plik

@ -4,6 +4,7 @@
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de>
Copyright (C) 2004, 2005 Stephane Voltz <svoltz@numericable.fr>
Copyright (C) 2005 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
This file is part of the SANE package.
@ -55,38 +56,51 @@ static Genesys_Frontend Wolfson[] = {
, {0x00, 0x00, 0x00}
, {0x80, 0x80, 0x80}
, {0x02, 0x02, 0x02}
, {0x00, 0x00, 0x00}
}
, /* UMAX */
{{0x00, 0x03, 0x05, 0x03}
, {0x00, 0x00, 0x00}
, {0xc8, 0xc8, 0xc8}
, {0x04, 0x04, 0x04}
, {0x00, 0x00, 0x00}
}
, /* ST12 */
{{0x00, 0x03, 0x05, 0x21}
, {0x00, 0x00, 0x00}
, {0xc8, 0xc8, 0xc8}
, {0x06, 0x06, 0x06}
, {0x00, 0x00, 0x00}
}
, /* ST24 */
{{0x00, 0x03, 0x05, 0x12}
, {0x00, 0x00, 0x00}
, {0xc8, 0xc8, 0xc8}
, {0x04, 0x04, 0x04}
, {0x00, 0x00, 0x00}
}
, /* MD6228/MD6471 */
{{0x00, 0x03, 0x05, 0x02}
, {0x00, 0x00, 0x00}
, {0xc0, 0xc0, 0xc0}
, {0x07, 0x07, 0x07}
, {0x00, 0x00, 0x00}
}
, /* HP2400c */
{{0x00, 0x03, 0x04, 0x02}
, {0x00, 0x00, 0x00}
, {0xb0, 0xb0, 0xb0}
, {0x04, 0x04, 0x04}
, {0x00, 0x00, 0x00}
}
, /* HP2300c */
{{0x00, 0x3d, 0x08, 0x00}
, {0x00, 0x00, 0x00}
, {0xe1, 0xe1, 0xe1}
, {0x93, 0x93, 0x93}
, {0x00, 0x19, 0x06}
}
, /* CANONLIDE35 */
};
@ -180,11 +194,34 @@ static Genesys_Sensor Sensor[] = {
,
2.1, 2.1, 2.1,
NULL, NULL, NULL}
,
/* CANOLIDE35 */
{1200,
/*TODO: find a good reason for keeping all three following variables*/
87, /*(black)*/
87, /* (dummy)*/
0, /* (startxoffset)*/
10400, /*sensor_pixels*/
210,
200,
{0x00, 0x00, 0x00, 0x00},
{0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x50,
0x00, 0x00, 0x00, 0x00 /* TODO(these do no harm, but may be neccessery for CCD)*/
},
{0x05, 0x07,
0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis*/
0x3a, 0x03,
0x40, /*TODO: bit7*/
0x00, 0x00, 0x00, 0x00 /*TODO (these do no harm, but may be neccessery for CCD)*/
}
,
0.45, 0.45, 0.45,
NULL, NULL, NULL}
};
/** for General Purpose Output specific settings:
* initial GPO value (registers 0x66-0x67)
* GPO enable mask (registers 0x68-0x69)
* initial GPO value (registers 0x66-0x67/0x6c-0x6d)
* GPO enable mask (registers 0x68-0x69/0x6e-0x6f)
*/
static Genesys_Gpo Gpo[] = {
/* UMAX */
@ -234,6 +271,14 @@ static Genesys_Gpo Gpo[] = {
{0x00, 0x00}
,
}
,
/* CANONLIDE35 */
{
{0x81, 0x80}
,
{0xef, 0x80}
,
}
};
#define MOTOR_ST24 2
@ -241,24 +286,112 @@ static Genesys_Motor Motor[] = {
/* UMAX */
{
1200, /* motor base steps */
2400 /* maximum motor resolution */
}
,
2400, /* maximum motor resolution */
1, /* maximum step mode*/
{{
11000, /* maximum start speed */
3000, /* maximum end speed */
128, /* step count */
1.0, /* nonlinearity */
},
{
11000,
3000,
128,
1.0,
},
},
},
{ /* MD5345/6228/6471 */
1200,
2400}
,
2400,
1,
{{
2000,
1375,
128,
0.5,
},
{
2000,
1375,
128,
0.5,
},
},
},
{ /* ST24 */
2400,
2400}
,
2400,
1,
{{
2289,
2100,
128,
0.3,
},
{
2289,
2100,
128,
0.3,
},
},
},
{ /* HP 2400c */
1200,
2400}
,
2400,
1,
{{
11000,
3000,
128,
1.0,
},
{
11000,
3000,
128,
1.0,
},
},
},
{ /* HP 2300c */
600,
1200}
1200,
1,
{{
3200,
1200,
128,
0.5,
},
{
3200,
1200,
128,
0.5,
},
},
},
{ /* Canon LiDE 35 */
1200,
2400,
1,
{{
3000,
1300,
50,
0.8,
},
{
3000,
1400,
50,
0.8,
},
},
},
};
/* here we have the various device settings...
@ -309,7 +442,7 @@ static Genesys_Model canon_lide_50_model = {
"canon-lide-50", /* Name */
"Canon", /* Device vendor string */
"LiDE 35/50", /* Device model name */
GENESYS_GL646,
GENESYS_GL841,
NULL,
{1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */
@ -317,13 +450,13 @@ static Genesys_Model canon_lide_50_model = {
{16, 8, 0}, /* possible depths in gray mode */
{16, 8, 0}, /* possible depths in color mode */
SANE_FIX (3.5), /* Start of scan area in mm (x) */
SANE_FIX (7.5), /* Start of scan area in mm (y) */
SANE_FIX (0.42), /* Start of scan area in mm (x) */
SANE_FIX (7.9), /* Start of scan area in mm (y) */
SANE_FIX (218.0), /* Size of scan area in mm (x) */
SANE_FIX (299.0), /* Size of scan area in mm (y) */
SANE_FIX (0.0), /* Start of white strip in mm (y) */
SANE_FIX (1.0), /* Start of black mark in mm (x) */
SANE_FIX (3.0), /* Start of white strip in mm (y) */
SANE_FIX (0.0), /* Start of black mark in mm (x) */
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */
@ -334,17 +467,20 @@ static Genesys_Model canon_lide_50_model = {
0, 0, 0, /* RGB CCD Line-distance correction in pixel */
COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */
COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */
SANE_TRUE, /* Is this a CIS scanner? */
CCD_UMAX,
DAC_WOLFSON_UMAX,
GPO_UMAX,
MOTOR_UMAX,
GENESYS_FLAG_UNTESTED, /* Which flags are needed for this scanner? */
/* untested, values set by hmg */
20,
200
CCD_CANONLIDE35,
DAC_CANONLIDE35,
GPO_CANONLIDE35,
MOTOR_CANONLIDE35,
GENESYS_FLAG_UNTESTED
| GENESYS_FLAG_LAZY_INIT
| GENESYS_FLAG_SKIP_WARMUP
| GENESYS_FLAG_OFFSET_CALIBRATION
| GENESYS_FLAG_DARK_WHITE_CALIBRATION, /* Which flags are needed for this scanner? */
300,
400
};
static Genesys_Model hp2300c_model = {

Wyświetl plik

@ -3,7 +3,8 @@
Copyright (C) 2003 Oliver Rauch
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
Copyright (C) 2004 Gerhard Jaeger <gerhard@gjaeger.de>
Copyright (C) 2004, 2005 Stephane Voltz <svoltz@numericable.fr>
Copyright (C) 2004, 2005 Stephane Voltz <stefdev@modulonet.fr>
Copyright (C) 2005 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
This file is part of the SANE package.
@ -249,6 +250,209 @@ enum
GENESYS_GL646_MAX_REGS
};
/* Write to many registers */
static SANE_Status
gl646_bulk_write_register (Genesys_Device * dev,
Genesys_Register_Set * reg, size_t size)
{
SANE_Status status;
u_int8_t outdata[8];
unsigned int i;
/* handle differently sized register sets, reg[0x00] is the last one */
i = 0;
while ((i < size / 2) && (reg[i].address != 0))
i++;
size = i * 2;
DBG (DBG_io, "gl646_bulk_write_register (size = %lu)\n",
(u_long) size);
outdata[0] = BULK_OUT;
outdata[1] = BULK_REGISTER;
outdata[2] = 0x00;
outdata[3] = 0x00;
outdata[4] = (size & 0xff);
outdata[5] = ((size >> 8) & 0xff);
outdata[6] = ((size >> 16) & 0xff);
outdata[7] = ((size >> 24) & 0xff);
status =
sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
VALUE_BUFFER, INDEX, sizeof (outdata), outdata);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_write_register: failed while writing command: %s\n",
sane_strstatus (status));
return status;
}
status = sanei_usb_write_bulk (dev->dn, (u_int8_t *) reg, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_write_register: failed while writing bulk data: %s\n",
sane_strstatus (status));
return status;
}
for (i = 0; i < size / 2; i++)
DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", ((u_int8_t *) reg)[2 * i],
((u_int8_t *) reg)[2 * i + 1]);
DBG (DBG_io, "gl646_bulk_write_register: wrote %d bytes\n", size);
return status;
}
/* Write bulk data (e.g. shading, gamma) */
static SANE_Status
gl646_bulk_write_data (Genesys_Device * dev, u_int8_t addr,
u_int8_t * data, size_t len)
{
SANE_Status status;
size_t size;
u_int8_t outdata[8];
DBG (DBG_io, "gl646_bulk_write_data writing %lu bytes\n",
(u_long) len);
status =
sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
VALUE_SET_REGISTER, INDEX, 1, &addr);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_write_data failed while setting register: %s\n",
sane_strstatus (status));
return status;
}
while (len)
{
if (len > BULKOUT_MAXSIZE)
size = BULKOUT_MAXSIZE;
else
size = len;
outdata[0] = BULK_OUT;
outdata[1] = BULK_RAM;
outdata[2] = 0x00;
outdata[3] = 0x00;
outdata[4] = (size & 0xff);
outdata[5] = ((size >> 8) & 0xff);
outdata[6] = ((size >> 16) & 0xff);
outdata[7] = ((size >> 24) & 0xff);
status =
sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
VALUE_BUFFER, INDEX, sizeof (outdata),
outdata);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_write_data failed while writing command: %s\n",
sane_strstatus (status));
return status;
}
status = sanei_usb_write_bulk (dev->dn, data, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_write_data failed while writing bulk data: %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_io2,
"gl646_bulk_write_data wrote %lu bytes, %lu remaining\n",
(u_long) size, (u_long) (len - size));
len -= size;
data += size;
}
DBG (DBG_io, "gl646_bulk_write_data: completed\n");
return status;
}
/* Read bulk data (e.g. scanned data) */
static SANE_Status
gl646_bulk_read_data (Genesys_Device * dev, u_int8_t addr,
u_int8_t * data, size_t len)
{
SANE_Status status;
size_t size;
u_int8_t outdata[8];
DBG (DBG_io, "gl646_bulk_read_data: requesting %lu bytes\n",
(u_long) len);
status =
sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER,
VALUE_SET_REGISTER, INDEX, 1, &addr);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_read_data failed while setting register: %s\n",
sane_strstatus (status));
return status;
}
outdata[0] = BULK_IN;
outdata[1] = BULK_RAM;
outdata[2] = 0x00;
outdata[3] = 0x00;
outdata[4] = (len & 0xff);
outdata[5] = ((len >> 8) & 0xff);
outdata[6] = ((len >> 16) & 0xff);
outdata[7] = ((len >> 24) & 0xff);
status =
sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER,
VALUE_BUFFER, INDEX, sizeof (outdata), outdata);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_read_data failed while writing command: %s\n",
sane_strstatus (status));
return status;
}
while (len)
{
if (len > BULKIN_MAXSIZE)
size = BULKIN_MAXSIZE;
else
size = len;
DBG (DBG_io2,
"gl646_bulk_read_data: trying to read %lu bytes of data\n",
(u_long) size);
status = sanei_usb_read_bulk (dev->dn, data, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_bulk_read_data failed while reading bulk data: %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_io2,
"gl646_bulk_read_data read %lu bytes, %lu remaining\n",
(u_long) size, (u_long) (len - size));
len -= size;
data += size;
}
DBG (DBG_io, "gl646_bulk_read_data: completed\n");
return status;
}
static SANE_Bool
gl646_get_fast_feed_bit (Genesys_Register_Set * regs)
@ -606,7 +810,7 @@ gl646_asic_test (Genesys_Device * dev)
return status;
}
status = sanei_genesys_bulk_write_data (dev, 0x3c, data, size);
status = gl646_bulk_write_data (dev, 0x3c, data, size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "gl646_asic_test: failed to bulk write data: %s\n",
@ -627,7 +831,7 @@ gl646_asic_test (Genesys_Device * dev)
}
status =
sanei_genesys_bulk_read_data (dev, 0x45, (u_int8_t *) verify_data,
gl646_bulk_read_data (dev, 0x45, (u_int8_t *) verify_data,
verify_size);
if (status != SANE_STATUS_GOOD)
{
@ -881,7 +1085,7 @@ gl646_send_slope_table (Genesys_Device * dev, int table_nr,
}
status =
sanei_genesys_bulk_write_data (dev, 0x3c, (u_int8_t *) slope_table,
gl646_bulk_write_data (dev, 0x3c, (u_int8_t *) slope_table,
steps * 2);
if (status != SANE_STATUS_GOOD)
{
@ -1064,6 +1268,24 @@ gl646_set_lamp_power (Genesys_Register_Set * regs, SANE_Bool set)
}
}
static SANE_Status
gl646_save_power(Genesys_Device * dev, SANE_Bool enable) {
DBG(DBG_proc, "gl646_save_power: enable = %d\n", enable);
if (enable)
{
gl646_set_fe (dev, AFE_POWER_SAVE);
}
else
{
}
return SANE_STATUS_GOOD;
}
static SANE_Status
gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
{
@ -1139,7 +1361,7 @@ gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
local_reg[5].value = exposure_time & 255; /* lowbyte */
status =
sanei_genesys_bulk_write_register (dev, local_reg, sizeof (local_reg));
gl646_bulk_write_register (dev, local_reg, sizeof (local_reg));
if (status != SANE_STATUS_GOOD)
DBG (DBG_error,
"gl646_set_powersaving: Failed to bulk write registers: %s\n",
@ -1173,7 +1395,7 @@ gl646_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
local_reg[2].value = 0x00; /* do not start motor yet */
status =
sanei_genesys_bulk_write_register (dev, local_reg, sizeof (local_reg));
gl646_bulk_write_register (dev, local_reg, sizeof (local_reg));
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -1239,7 +1461,7 @@ gl646_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
static SANE_Status
gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
{
Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS];
Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS+1];
SANE_Status status;
u_int8_t val = 0;
u_int8_t prepare_steps;
@ -1284,7 +1506,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
usleep (200000UL);
}
memcpy (local_reg, dev->reg, GENESYS_GL646_MAX_REGS * 2);
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * 2);
prepare_steps = 4;
exposure_time = 6 * MOTOR_SPEED_MAX;
@ -1388,7 +1610,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
}
status =
sanei_genesys_bulk_write_register (dev, local_reg,
gl646_bulk_write_register (dev, local_reg,
GENESYS_GL646_MAX_REGS * 2);
if (status != SANE_STATUS_GOOD)
{
@ -1405,7 +1627,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
sane_strstatus (status));
sanei_genesys_stop_motor (dev);
/* send original registers */
sanei_genesys_bulk_write_register (dev, dev->reg,
gl646_bulk_write_register (dev, dev->reg,
GENESYS_GL646_MAX_REGS * 2);
return status;
}
@ -1541,7 +1763,7 @@ gl646_park_head (Genesys_Device * dev, Genesys_Register_Set * reg,
local_reg[i++].value = LOBYTE (exposure_time);
/* writes register */
status = sanei_genesys_bulk_write_register (dev, local_reg, i * 2);
status = gl646_bulk_write_register (dev, local_reg, i * 2);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
@ -1569,7 +1791,7 @@ gl646_park_head (Genesys_Device * dev, Genesys_Register_Set * reg,
sane_strstatus (status));
sanei_genesys_stop_motor (dev);
/* restore original registers */
sanei_genesys_bulk_write_register (dev, reg,
gl646_bulk_write_register (dev, reg,
GENESYS_GL646_MAX_REGS * 2);
return status;
}
@ -1631,7 +1853,7 @@ gl646_search_start_position (Genesys_Device * dev)
SANE_Status status;
u_int8_t *data;
u_int16_t slope_table0[256];
Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS];
Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS + 1];
int i, steps;
int exposure_time, half_ccd = 0;
struct timeval tv;
@ -1642,7 +1864,7 @@ gl646_search_start_position (Genesys_Device * dev)
DBG (DBG_proc, "gl646_search_start_position\n");
memset (local_reg, 0, sizeof (local_reg));
memcpy (local_reg, dev->reg, GENESYS_GL646_MAX_REGS * 2);
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * 2);
gettimeofday (&tv, NULL);
/* is scanner warm enough ? */
@ -1770,7 +1992,7 @@ gl646_search_start_position (Genesys_Device * dev)
/* send to scanner */
status =
sanei_genesys_bulk_write_register (dev, local_reg,
gl646_bulk_write_register (dev, local_reg,
GENESYS_GL646_MAX_REGS * 2);
if (status != SANE_STATUS_GOOD)
{
@ -1890,7 +2112,7 @@ gl646_search_start_position (Genesys_Device * dev)
/* update regs to copy ASIC internal state */
dev->reg[reg_0x01].value = local_reg[reg_0x01].value;
dev->reg[reg_0x02].value = local_reg[reg_0x02].value;
memcpy (dev->reg, local_reg, GENESYS_GL646_MAX_REGS * 2);
memcpy (dev->reg, local_reg, (GENESYS_GL646_MAX_REGS + 1) * 2);
status =
sanei_genesys_search_reference_point (dev, data, start_pixel, dpi, pixels,
@ -2058,7 +2280,7 @@ gl646_init_regs_for_coarse_calibration (Genesys_Device * dev)
}
status =
sanei_genesys_bulk_write_register (dev, dev->calib_reg,
gl646_bulk_write_register (dev, dev->calib_reg,
GENESYS_GL646_MAX_REGS * 2);
if (status != SANE_STATUS_GOOD)
{
@ -2341,7 +2563,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
}
status =
sanei_genesys_bulk_write_register (dev, dev->calib_reg,
gl646_bulk_write_register (dev, dev->calib_reg,
GENESYS_GL646_MAX_REGS * 2);
if (status != SANE_STATUS_GOOD)
{
@ -2389,9 +2611,15 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
int dummy;
u_int32_t steps_sum, z1, z2;
SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */
SANE_Status status;
unsigned int stagger;
unsigned int max_shift;
float read_factor;
size_t requested_buffer_size;
size_t read_buffer_size;
DBG (DBG_info,
"gl646_init_register_for_scan settings:\nResolution: %ux%uDPI\n"
"gl646_init_regs_for_scan settings:\nResolution: %ux%uDPI\n"
"Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n",
dev->settings.xres, dev->settings.yres, dev->settings.lines,
dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y,
@ -2421,16 +2649,16 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
else if (i <= 24)
dpiset = dev->sensor.optical_res / 12;
DBG (DBG_info,
"gl646_init_register_for_scan : i=%d, dpiset=%d, half_ccd=%d\n", i,
"gl646_init_regs_for_scan : i=%d, dpiset=%d, half_ccd=%d\n", i,
dpiset, half_ccd);
/* sigh ... MD6471 motor's provide vertically shifted columns at hi res ... */
if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
dev->stagger = (4 * dev->settings.yres) / dev->motor.base_ydpi;
stagger = (4 * dev->settings.yres) / dev->motor.base_ydpi;
else
dev->stagger = 0;
DBG (DBG_info, "gl646_init_register_for_scan : stagger=%d lines\n",
dev->stagger);
stagger = 0;
DBG (DBG_info, "gl646_init_regs_for_scan : stagger=%d lines\n",
stagger);
/* compute scan parameters values */
/* pixels are allways given at half or full CCD optical resolution */
@ -2444,11 +2672,11 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
start += (dev->settings.tl_x * dev->sensor.optical_res) / MM_PER_INCH;
if (half_ccd)
start = start / 2;
if (dev->stagger > 0)
if (stagger > 0)
start = start | 1;
/* compute correct pixels number */
dev->read_factor = 0.0;
read_factor = 0.0;
pixels =
(dev->settings.pixels * dev->sensor.optical_res) / dev->settings.xres;
if (half_ccd)
@ -2462,10 +2690,10 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
pixels = ((pixels + i - 1) / i) * i;
/* sets flag for reading */
/* the 2 factor is due to the fact that dpiset = 2 desired ccd dpi */
dev->read_factor = (float) pixels / (float) (dev->settings.pixels * 2);
read_factor = (float) pixels / (float) (dev->settings.pixels * 2);
DBG (DBG_info,
"gl646_init_register_for_scan : rounding up pixels, factor=%f\n",
dev->read_factor);
"gl646_init_regs_for_scan : rounding up pixels, factor=%f\n",
read_factor);
}
end = start + pixels;
@ -2480,17 +2708,17 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
/* all values are assumed >= 0 */
if (channels > 1)
{
dev->max_shift = dev->model->ld_shift_r;
if (dev->model->ld_shift_b > dev->max_shift)
dev->max_shift = dev->model->ld_shift_b;
if (dev->model->ld_shift_g > dev->max_shift)
dev->max_shift = dev->model->ld_shift_g;
dev->max_shift =
(dev->max_shift * dev->settings.yres) / dev->motor.base_ydpi;
max_shift = dev->model->ld_shift_r;
if (dev->model->ld_shift_b > max_shift)
max_shift = dev->model->ld_shift_b;
if (dev->model->ld_shift_g > max_shift)
max_shift = dev->model->ld_shift_g;
max_shift =
(max_shift * dev->settings.yres) / dev->motor.base_ydpi;
}
else
{
dev->max_shift = 0;
max_shift = 0;
}
/* enable shading */
@ -2597,7 +2825,7 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
slope_dpi = 100;
slope_dpi = slope_dpi * (1 + dummy);
lincnt = dev->settings.lines - 1 + dev->max_shift + dev->stagger;
lincnt = dev->settings.lines - 1 + max_shift + stagger;
dev->reg[reg_0x25].value = LOBYTE (HIWORD (lincnt)); /* scan line numbers - here one line */
dev->reg[reg_0x26].value = HIBYTE (LOWORD (lincnt));
@ -2696,30 +2924,30 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
move = (SANE_UNFIX (dev->model->y_offset_calib) * move_dpi) / MM_PER_INCH;
else
move = 0;
DBG (DBG_info, "gl646_init_register_for_scan: move=%d steps\n", move);
DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move);
move += (SANE_UNFIX (dev->model->y_offset) * move_dpi) / MM_PER_INCH;
DBG (DBG_info, "gl646_init_register_for_scan: move=%d steps\n", move);
DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move);
/* add tl_y to base movement */
/* move += (dev->settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; */
move += (dev->settings.tl_y * move_dpi) / MM_PER_INCH;
DBG (DBG_info, "gl646_init_register_for_scan: move=%d steps\n", move);
DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move);
/* substract current head position */
move -= dev->scanhead_position_in_steps - dev->stagger;
DBG (DBG_info, "gl646_init_register_for_scan: move=%d steps\n", move);
move -= dev->scanhead_position_in_steps - stagger;
DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move);
if ((dev->reg[reg_0x02].value & REG02_FASTFED)
&& (dev->model->motor_type == MOTOR_HP2300))
{
move *= 2;
DBG (DBG_info, "gl646_init_register_for_scan: move=%d steps\n", move);
DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move);
}
/* round it */
move = ((move + dummy) / (dummy + 1)) * (dummy + 1);
DBG (DBG_info, "gl646_init_register_for_scan: move=%d steps\n", move);
DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move);
/* set feed steps number of motor move */
dev->reg[reg_0x3d].value = LOBYTE (HIWORD (move));
@ -2731,8 +2959,8 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
dev->slope_table0,
dev->reg[reg_0x21].value,
move, dev->reg[reg_0x22].value, &z1, &z2);
DBG (DBG_info, "gl646_init_register_for_scan: z1 = %d\n", z1);
DBG (DBG_info, "gl646_init_register_for_scan: z2 = %d\n", z2);
DBG (DBG_info, "gl646_init_regs_for_scan: z1 = %d\n", z1);
DBG (DBG_info, "gl646_init_regs_for_scan: z2 = %d\n", z2);
dev->reg[reg_0x60].value = HIBYTE (z1);
dev->reg[reg_0x61].value = LOBYTE (z1);
dev->reg[reg_0x62].value = HIBYTE (z2);
@ -2752,64 +2980,113 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
dev->reg[reg_0x67].value = dev->gpo.enable[1];
/* prepares data reordering */
dev->words_per_line = words_per_line;
/* we must use a round number of words_per_line */
dev->requested_buffer_size =
(BULKIN_MAXSIZE / dev->words_per_line) * dev->words_per_line;
requested_buffer_size =
(BULKIN_MAXSIZE / words_per_line) * words_per_line;
dev->read_buffer_size =
2 * dev->requested_buffer_size +
((dev->max_shift + dev->stagger) * pixels * channels * depth) / 8;
if (dev->read_buffer != NULL)
{
free (dev->read_buffer);
free (dev->resize_buffer);
}
dev->read_buffer = (SANE_Byte *) malloc (dev->read_buffer_size);
if (dev->read_buffer == NULL)
return SANE_STATUS_NO_MEM;
dev->resize_buffer = (SANE_Byte *) malloc (dev->requested_buffer_size);
if (dev->resize_buffer == NULL)
{
free (dev->read_buffer);
dev->read_buffer = NULL;
return SANE_STATUS_NO_MEM;
}
read_buffer_size =
2 * requested_buffer_size +
((max_shift + stagger) * pixels * channels * depth) / 8;
RIE(sanei_genesys_buffer_free(&(dev->read_buffer)));
RIE(sanei_genesys_buffer_alloc(&(dev->read_buffer), read_buffer_size));
RIE(sanei_genesys_buffer_free(&(dev->lines_buffer)));
RIE(sanei_genesys_buffer_alloc(&(dev->lines_buffer), read_buffer_size));
RIE(sanei_genesys_buffer_free(&(dev->shrink_buffer)));
RIE(sanei_genesys_buffer_alloc(&(dev->shrink_buffer),
requested_buffer_size));
RIE(sanei_genesys_buffer_free(&(dev->out_buffer)));
RIE(sanei_genesys_buffer_alloc(&(dev->out_buffer),
(8 * dev->settings.pixels * channels * depth) / 8));
dev->read_pos = 0;
dev->total_bytes_read = 0;
dev->read_bytes_in_buffer = 0;
/* scan bytes to read */
dev->read_bytes_left = dev->words_per_line * (lincnt + 1);
dev->read_bytes_left = words_per_line * (lincnt + 1);
DBG (DBG_info,
"gl646_init_regs_for_scan: physical bytes to read = %lu\n",
(u_long) dev->read_bytes_left);
dev->read_active = SANE_TRUE;
dev->current_setup.pixels = (pixels * dpiset) / dev->sensor.optical_res;
if (half_ccd)
dev->current_setup.pixels &= ~1;
dev->current_setup.lines = lincnt + 1;
dev->current_setup.depth = depth;
dev->current_setup.channels = channels;
dev->current_setup.exposure_time = exposure_time;
if (half_ccd)
dev->current_setup.xres = dpiset / 2;
else
dev->current_setup.xres = dpiset ;
dev->current_setup.yres = dev->settings.yres;
dev->current_setup.half_ccd = half_ccd;
dev->current_setup.stagger = stagger;
dev->current_setup.max_shift = max_shift + stagger;
/* TODO: should this be done elsewhere? */
/* scan bytes to send to the frontend */
/* theory :
target_size =
(dev->settings.pixels * dev->settings.lines * channels * depth) / 8;
but it suffers from integer overflow so we do the following: */
switch (depth)
{
case 1:
dev->bytes_to_read =
(size_t) (dev->settings.pixels * dev->settings.lines * channels) / 8;
break;
case 8:
dev->bytes_to_read =
(size_t) (dev->settings.pixels * dev->settings.lines * channels);
break;
case 16:
dev->bytes_to_read =
(size_t) (dev->settings.pixels * dev->settings.lines * channels * 2);
break;
}
DBG (DBG_info,
"gl646_init_register_for_scan: physical bytes to read = %lu\n",
(u_long) dev->read_bytes_left);
DBG (DBG_info, "gl646_init_register_for_scan: total bytes to send = %lu\n",
(u_long) dev->bytes_to_read);
dev->read_active = SANE_TRUE;
but it suffers from integer overflow so we do the following:
DBG (DBG_proc, "gl646_init_register_for_scan: completed\n");
1 bit color images store color data byte-wise, eg byte 0 contains
8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains
8 bits of blue.
This does not fix the overflow, though.
644mp*16 = 10gp, leading to an overflow
-- pierre
*/
dev->total_bytes_read = 0;
if (depth == 1)
dev->total_bytes_to_read =
((dev->settings.pixels * dev->settings.lines) / 8) * channels;
else
dev->total_bytes_to_read =
dev->settings.pixels * dev->settings.lines * channels * (depth / 8);
DBG (DBG_info, "gl646_init_regs_for_scan: total bytes to send = %lu\n",
(u_long) dev->total_bytes_to_read);
/* END TODO */
status =
gl646_send_slope_table (dev, 0, dev->slope_table0,
sanei_genesys_read_reg_from_set
(dev->reg, 0x21));
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_init_regs_for_scan: failed to send slope table 0: %s\n",
sane_strstatus (status));
return status;
}
status =
gl646_send_slope_table (dev, 1, dev->slope_table1,
sanei_genesys_read_reg_from_set
(dev->reg, 0x6b));
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_init_regs_for_scan: failed to send slope table 1: %s\n",
sane_strstatus (status));
return status;
}
DBG (DBG_proc, "gl646_init_regs_for_scan: completed\n");
return SANE_STATUS_GOOD;
}
@ -2898,7 +3175,7 @@ gl646_send_gamma_table (Genesys_Device * dev, SANE_Bool generic)
/* send data */
status =
sanei_genesys_bulk_write_data (dev, 0x3c, (u_int8_t *) gamma,
gl646_bulk_write_data (dev, 0x3c, (u_int8_t *) gamma,
size * 2 * 3);
if (status != SANE_STATUS_GOOD)
{
@ -2914,6 +3191,14 @@ gl646_send_gamma_table (Genesys_Device * dev, SANE_Bool generic)
return SANE_STATUS_GOOD;
}
/* this function does the led calibration.
*/
static SANE_Status
gl646_led_calibration (Genesys_Device * dev)
{
DBG(DBG_error,"Implementation for led calibration missing\n");
return SANE_STATUS_INVAL;
}
/* this function does the offset calibration by scanning one line of the calibration
area below scanner's top. There is a black margin and the remaining is white.
@ -3129,7 +3414,7 @@ ST12: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x3f 0x66 0x00 0x67
RIE (gl646_set_fe (dev, AFE_SET));
RIE (sanei_genesys_bulk_write_register
RIE (gl646_bulk_write_register
(dev, dev->calib_reg, GENESYS_GL646_MAX_REGS * 2));
first_line = malloc (total_size);
@ -3480,7 +3765,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
DBG (DBG_proc, "gl646_warmup_lamp\n");
memcpy (local_reg, dev->reg, GENESYS_GL646_MAX_REGS * 2);
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * 2);
*total_size = num_pixels * 3 * 2 * 1; /* colors * bytes_per_color * scan lines */
/* ST12: 0x01 0x00 0x02 0x41 0x03 0x1f 0x04 0x53 0x05 0x10 0x06 0x10 0x08 0x02 0x09 0x00 0x0a 0x06 0x0b 0x04 */
@ -3567,9 +3852,9 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
local_reg[reg_0x24].value = local_reg[reg_0x21].value; /* table one steps number backward slope curve of the acc/dec */
local_reg[reg_0x25].value = HIWORD (LOBYTE (lincnt)); /* scan line numbers - here one line */
local_reg[reg_0x26].value = LOWORD (HIBYTE (lincnt));
local_reg[reg_0x27].value = LOWORD (LOBYTE (lincnt));
local_reg[reg_0x25].value = LOBYTE (HIWORD (lincnt)); /* scan line numbers - here one line */
local_reg[reg_0x26].value = HIBYTE (LOWORD (lincnt));
local_reg[reg_0x27].value = LOBYTE (LOWORD (lincnt));
local_reg[reg_0x2c].value = HIBYTE (dpi);
local_reg[reg_0x2d].value = LOBYTE (dpi);
@ -3593,7 +3878,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
local_reg[reg_0x37].value = LOBYTE (LOWORD (words_per_line));
exposure_time = sanei_genesys_exposure_time (dev, local_reg, dpi),
local_reg[reg_0x38].value = HIBYTE (exposure_time);
local_reg[reg_0x38].value = HIBYTE (exposure_time);
local_reg[reg_0x39].value = LOBYTE (exposure_time);
/* monochrome scan */
@ -3648,7 +3933,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
RIE (gl646_set_fe (dev, AFE_INIT));
RIE (sanei_genesys_bulk_write_register
RIE (gl646_bulk_write_register
(dev, local_reg, GENESYS_GL646_MAX_REGS * 2));
return status;
@ -3663,7 +3948,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
static SANE_Status
gl646_repark_head (Genesys_Device * dev)
{
Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS];
Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS + 1];
u_int16_t slope_table[256];
int exposure_time; /* todo : modify sanei_genesys_exposure_time() */
SANE_Status status;
@ -3675,7 +3960,7 @@ gl646_repark_head (Genesys_Device * dev)
DBG (DBG_proc, "gl646_repark_head\n");
memset (local_reg, 0, sizeof (local_reg));
memcpy (local_reg, dev->reg, GENESYS_GL646_MAX_REGS * 2);
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * 2);
local_reg[reg_0x01].value =
local_reg[reg_0x01].value & ~REG01_DVDSET & ~REG01_FASTMOD & ~REG01_SCAN;
@ -3786,7 +4071,7 @@ gl646_repark_head (Genesys_Device * dev)
}
status =
sanei_genesys_bulk_write_register (dev, local_reg,
gl646_bulk_write_register (dev, local_reg,
GENESYS_GL646_MAX_REGS * 2);
if (status != SANE_STATUS_GOOD)
{
@ -3852,7 +4137,6 @@ gl646_init (Genesys_Device * dev)
}
}
sanei_genesys_init_structs (dev);
dev->dark_average_data = NULL;
dev->white_average_data = NULL;
@ -3981,7 +4265,7 @@ gl646_init (Genesys_Device * dev)
usleep (10000UL); /* sleep 100 ms */
/* Write initial registers */
RIE (sanei_genesys_bulk_write_register
RIE (gl646_bulk_write_register
(dev, dev->reg, GENESYS_GL646_MAX_REGS * 2));
/* Test ASIC and RAM */
@ -4027,7 +4311,7 @@ gl646_init (Genesys_Device * dev)
}
/* initial calibration reg values */
memcpy (dev->calib_reg, dev->reg, GENESYS_GL646_MAX_REGS * 2);
memcpy (dev->calib_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * 2);
/* Set powersaving (default = 15 minutes) */
RIE (gl646_set_powersaving (dev, 15));
@ -4059,6 +4343,7 @@ static Genesys_Command_Set gl646_cmd_set = {
gl646_set_fe,
gl646_set_powersaving,
gl646_save_power,
gl646_set_motor_power,
gl646_set_lamp_power,
@ -4066,14 +4351,19 @@ static Genesys_Command_Set gl646_cmd_set = {
gl646_end_scan,
gl646_send_gamma_table,
gl646_send_slope_table,
gl646_search_start_position,
gl646_offset_calibration,
gl646_coarse_gain_calibration,
gl646_led_calibration,
gl646_slow_back_home,
gl646_park_head,
gl646_bulk_write_register,
gl646_bulk_write_data,
gl646_bulk_read_data,
};
SANE_Status

Plik diff jest za duży Load Diff

Wyświetl plik

@ -3,7 +3,8 @@
Copyright (C) 2003 Oliver Rauch
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de>
Copyright (C) 2004, 2005 Stephane Voltz <stephane.voltz@numericable.fr>
Copyright (C) 2004, 2005 Stephane Voltz <stefdev@modulonet.fr>
Copyright (C) 2005 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
Parts of the structs have been taken from the gt68xx backend by
Sergey Vlasov <vsu@altlinux.ru> et al.
@ -83,8 +84,16 @@
#define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /* do dark calibration */
#define GENESYS_FLAG_STAGGERED_LINE (1 << 9) /* pixel columns are shifted vertically for hi-res modes */
#define GENESYS_FLAG_MUST_WAIT (1 << 10) /* tells wether the scanner should wait 1 minute after init
before doing anything */
#define GENESYS_FLAG_MUST_WAIT (1 << 10) /* tells wether the scanner
should wait 1 minute after
init before doing anything
*/
#define GENESYS_FLAG_ALT_SLOPE_CREATE (1 << 11) /* use alternative slope
creation function */
#define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /*yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/
/* USB control message values */
#define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN)
@ -112,7 +121,7 @@
#define BULK_RAM 0x00
#define BULK_REGISTER 0x11
#define BULKIN_MAXSIZE 0xFFC0
#define BULKIN_MAXSIZE 0xFE00
#define BULKOUT_MAXSIZE 0xF000
/* AFE values */
@ -146,13 +155,14 @@ typedef struct
u_int8_t sign[3];
u_int8_t offset[3];
u_int8_t gain[3];
u_int8_t reg2[3];
} Genesys_Frontend;
typedef struct
{
int optical_res;
int black_pixels;
int dummy_pixel;
int dummy_pixel; /* value of dummy register. */
int CCD_start_xoffset; /* last pixel of CCD margin at optical resolution */
int sensor_pixels; /* total pixels used by the sensor */
int fau_gain_white_ref; /* TA CCD target code (reference gain) */
@ -176,8 +186,22 @@ typedef struct
typedef struct
{
SANE_Int base_ydpi; /* motor base steps */
SANE_Int optical_ydpi; /* maximum resolution in y-direction */
SANE_Int maximum_start_speed; /* maximum speed allowed when accelerating from standstill. Unit: pixeltime/step */
SANE_Int maximum_speed; /* maximum speed allowed. Unit: pixeltime/step */
SANE_Int minimum_steps; /* number of steps used for default curve */
float g; /* power for non-linear acceleration curves. */
/* vs*(1-i^g)+ve*(i^g) where
vs = start speed, ve = end speed,
i = 0.0 for first entry and i = 1.0 for last entry in default table*/
} Genesys_Motor_Slope;
typedef struct
{
SANE_Int base_ydpi; /* motor base steps. Unit: 1/" */
SANE_Int optical_ydpi; /* maximum resolution in y-direction. Unit: 1/" */
SANE_Int max_step_type; /* maximum step type. 0-2 */
Genesys_Motor_Slope slopes[3]; /* slopes to derive individual slopes from */
} Genesys_Motor;
typedef enum Genesys_Color_Order
@ -195,7 +219,8 @@ Genesys_Color_Order;
#define GENESYS_GL646 646
#define GENESYS_GL841 841
#define GENESYS_MAX_REGS 135
/*135 registers for gl841 + 1 null-reg*/
#define GENESYS_MAX_REGS 136
#define DAC_WOLFSON_UMAX 0
#define DAC_WOLFSON_ST12 1
@ -203,6 +228,7 @@ Genesys_Color_Order;
#define DAC_WOLFSON_5345 3
#define DAC_WOLFSON_HP2400 4
#define DAC_WOLFSON_HP2300 5
#define DAC_CANONLIDE35 6
#define CCD_UMAX 0
#define CCD_ST12 1 /* SONY ILX548: 5340 Pixel ??? */
@ -210,6 +236,7 @@ Genesys_Color_Order;
#define CCD_5345 3
#define CCD_HP2400 4
#define CCD_HP2300 5
#define CCD_CANONLIDE35 6
#define GPO_UMAX 0
#define GPO_ST12 1
@ -217,12 +244,14 @@ Genesys_Color_Order;
#define GPO_5345 3
#define GPO_HP2400 4
#define GPO_HP2300 5
#define GPO_CANONLIDE35 6
#define MOTOR_UMAX 0
#define MOTOR_5345 1
#define MOTOR_ST24 2
#define MOTOR_HP2400 3
#define MOTOR_HP2300 4
#define MOTOR_CANONLIDE35 5
/* Forward typedefs */
@ -268,6 +297,7 @@ typedef struct Genesys_Command_Set
SANE_Status (*set_fe) (Genesys_Device * dev, u_int8_t set);
SANE_Status (*set_powersaving) (Genesys_Device * dev, int delay);
SANE_Status (*save_power) (Genesys_Device * dev, SANE_Bool enable);
void (*set_motor_power) (Genesys_Register_Set * regs, SANE_Bool set);
void (*set_lamp_power) (Genesys_Register_Set * regs, SANE_Bool set);
@ -280,18 +310,25 @@ typedef struct Genesys_Command_Set
SANE_Bool check_stop);
SANE_Status (*send_gamma_table) (Genesys_Device * dev, SANE_Bool generic);
SANE_Status (*send_slope_table) (Genesys_Device * dev, int table_nr,
u_int16_t * slope_table, int steps);
SANE_Status (*search_start_position) (Genesys_Device * dev);
SANE_Status (*offset_calibration) (Genesys_Device * dev);
SANE_Status (*coarse_gain_calibration) (Genesys_Device * dev, int dpi);
SANE_Status (*led_calibration) (Genesys_Device * dev);
SANE_Status (*slow_back_home) (Genesys_Device * dev,
SANE_Bool wait_until_home);
SANE_Status (*park_head) (Genesys_Device * dev,
Genesys_Register_Set * reg,
SANE_Bool wait_until_home);
SANE_Status (*bulk_write_register) (Genesys_Device * dev,
Genesys_Register_Set * reg,
size_t size);
SANE_Status (*bulk_write_data) (Genesys_Device * dev, u_int8_t addr,
u_int8_t * data, size_t len);
SANE_Status (*bulk_read_data) (Genesys_Device * dev, u_int8_t addr,
u_int8_t * data, size_t len);
} Genesys_Command_Set;
@ -354,17 +391,38 @@ typedef struct
double tl_x; /* x start on scan table in mm */
double tl_y; /* y start on scan table in mm */
int lines; /* number of lines at scan resolution */
int pixels; /* number of pixels at scan resolution */
unsigned int lines; /* number of lines at scan resolution */
unsigned int pixels; /* number of pixels at scan resolution */
int depth; /* bit depth of the scan */
unsigned int depth;/* bit depth of the scan */
/* todo : remove these fields ? */
int exposure_time;
int color_filter; /* todo: check, may be make it an advanced option */
unsigned int color_filter; /* todo: check, may be make it an advanced option */
} Genesys_Settings;
typedef struct Genesys_Current_Setup
{
int pixels; /* pixel count expected from scanner */
int lines; /* line count expected from scanner */
int depth; /* depth expected from scanner */
int channels; /* channel count expected from scanner */
int exposure_time; /* used exposure time */
float xres; /* used xres */
float yres; /* used yres*/
SANE_Bool half_ccd; /* half ccd mode */
SANE_Int stagger;
SANE_Int max_shift; /* max shift of any ccd component, including staggered pixels*/
} Genesys_Current_Setup;
typedef struct Genesys_Buffer
{
SANE_Byte *buffer;
size_t size;
size_t pos; /* current position in read buffer */
size_t avail; /* data bytes currently in buffer */
} Genesys_Buffer;
struct Genesys_Device
{
@ -392,22 +450,18 @@ struct Genesys_Device
SANE_Int lamp_off_time;
SANE_Bool read_active;
SANE_Byte *read_buffer;
SANE_Byte *resize_buffer;
size_t words_per_line;
float read_factor; /* line shrinking factor */
size_t requested_buffer_size;
size_t read_buffer_size;
size_t read_pos; /* current position in data buffer */
size_t read_bytes_in_buffer; /* data bytes currently in buffer */
size_t read_bytes_left; /* bytes to read from scanner */
size_t total_bytes_read; /* total bytes read sent to frontend */
size_t bytes_to_read; /* total bytes read to be sent to frontend */
SANE_Int max_shift; /* maximum line number that has to be read
to enable data reordering */
SANE_Int stagger; /* numbre of scan lines needed to process
staggering effect */
Genesys_Buffer read_buffer;
Genesys_Buffer lines_buffer;
Genesys_Buffer shrink_buffer;
Genesys_Buffer out_buffer;
size_t read_bytes_left; /* bytes to read from scanner */
size_t total_bytes_read; /* total bytes read sent to frontend */
size_t total_bytes_to_read; /* total bytes read to be sent to frontend */
Genesys_Current_Setup current_setup; /* contains the real used values */
struct Genesys_Device *next;
};
@ -453,7 +507,7 @@ extern SANE_Status
sanei_genesys_init_shading_data (Genesys_Device * dev, int pixels_per_line);
extern SANE_Status sanei_genesys_read_feed_steps (Genesys_Device * dev,
int *steps);
unsigned int *steps);
extern void
sanei_genesys_calculate_zmode2 (SANE_Bool two_table,
@ -472,14 +526,6 @@ sanei_genesys_calculate_zmode (Genesys_Device * dev,
u_int8_t fwdstep, u_int8_t tgtime,
u_int32_t * z1, u_int32_t * z2);
extern SANE_Status
sanei_genesys_bulk_write_data (Genesys_Device * dev, u_int8_t addr,
u_int8_t * data, size_t len);
extern SANE_Status
sanei_genesys_bulk_read_data (Genesys_Device * dev, u_int8_t addr,
u_int8_t * data, size_t len);
extern SANE_Status
sanei_genesys_set_buffer_address (Genesys_Device * dev, u_int32_t addr);
@ -487,6 +533,11 @@ extern SANE_Status
sanei_genesys_fe_write_data (Genesys_Device * dev, u_int8_t addr,
u_int16_t data);
extern SANE_Int
sanei_genesys_exposure_time2 (Genesys_Device * dev,
float ydpi, int step_type, int endpixel,
int led_exposure);
extern SANE_Int
sanei_genesys_exposure_time (Genesys_Device * dev, Genesys_Register_Set * reg,
int xdpi);
@ -497,15 +548,20 @@ sanei_genesys_create_slope_table (Genesys_Device * dev,
int step_type, int exposure_time,
SANE_Bool same_speed, double yres);
SANE_Int
sanei_genesys_create_slope_table3 (Genesys_Device * dev,
u_int8_t * slope_table, int max_step,
unsigned int use_steps,
int step_type, int exposure_time,
double yres,
unsigned int *used_steps,
unsigned int *final_exposure);
extern void
sanei_genesys_create_gamma_table (u_int16_t * gamma_table, float size,
sanei_genesys_create_gamma_table (u_int16_t * gamma_table, int size,
float maximum, float gamma_max,
float gamma);
extern SANE_Status
sanei_genesys_bulk_write_register (Genesys_Device * dev,
Genesys_Register_Set * reg, size_t size);
extern SANE_Status sanei_genesys_start_motor (Genesys_Device * dev);
extern SANE_Status sanei_genesys_stop_motor (Genesys_Device * dev);
@ -526,6 +582,24 @@ extern SANE_Status
sanei_genesys_read_data_from_scanner (Genesys_Device * dev, u_int8_t * data,
size_t size);
extern SANE_Status
sanei_genesys_buffer_alloc(Genesys_Buffer * buf, size_t size);
extern SANE_Status
sanei_genesys_buffer_free(Genesys_Buffer * buf);
extern SANE_Byte *
sanei_genesys_buffer_get_write_pos(Genesys_Buffer * buf, size_t size);
extern SANE_Byte *
sanei_genesys_buffer_get_read_pos(Genesys_Buffer * buf);
extern SANE_Status
sanei_genesys_buffer_produce(Genesys_Buffer * buf, size_t size);
extern SANE_Status
sanei_genesys_buffer_consume(Genesys_Buffer * buf, size_t size);
/*---------------------------------------------------------------------------*/
/* ASIC specific functions declarations */