2005-10-03 13:27:03 +00:00
|
|
|
/* sane - Scanner Access Now Easy.
|
|
|
|
|
|
|
|
Copyright (C) 2000-2005 Mustek.
|
|
|
|
Originally maintained by Mustek
|
|
|
|
|
|
|
|
Copyright (C) 2001-2005 by Henning Meier-Geinitz.
|
|
|
|
|
|
|
|
This file is part of the SANE package.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
|
|
MA 02111-1307, USA.
|
|
|
|
|
|
|
|
As a special exception, the authors of SANE give permission for
|
|
|
|
additional uses of the libraries contained in this release of SANE.
|
|
|
|
|
|
|
|
The exception is that, if you link a SANE library with other files
|
|
|
|
to produce an executable, this does not by itself cause the
|
|
|
|
resulting executable to be covered by the GNU General Public
|
|
|
|
License. Your use of that executable is in no way restricted on
|
|
|
|
account of linking the SANE library code into it.
|
|
|
|
|
|
|
|
This exception does not, however, invalidate any other reasons why
|
|
|
|
the executable file might be covered by the GNU General Public
|
|
|
|
License.
|
|
|
|
|
|
|
|
If you submit changes to SANE to the maintainers to be included in
|
|
|
|
a subsequent release, you agree by submitting the changes that
|
|
|
|
those changes may be distributed with this exception intact.
|
|
|
|
|
|
|
|
If you write modifications of your own for SANE, it is your choice
|
|
|
|
whether to permit this exception to apply to your modifications.
|
|
|
|
If you do not wish that, delete this exception notice.
|
|
|
|
|
|
|
|
This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro
|
|
|
|
and similar USB2 scanners. */
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
#define BUILD 11
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 22:59:19 +00:00
|
|
|
#include "sane/config.h"
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2011-04-23 22:59:19 +00:00
|
|
|
#include "sane/sane.h"
|
|
|
|
#include "sane/sanei.h"
|
|
|
|
#include "sane/saneopts.h"
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
#define BACKEND_NAME mustek_usb2
|
2011-04-23 22:59:19 +00:00
|
|
|
#include "sane/sanei_backend.h"
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
#include "mustek_usb2.h"
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
static const SANE_Device **devlist = NULL;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
static const SANE_Range u8_range = {
|
2011-04-10 16:42:05 +00:00
|
|
|
0, /* minimum */
|
|
|
|
255, /* maximum */
|
|
|
|
0 /* quantization */
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
static SANE_Range x_range = {
|
2011-04-10 16:42:05 +00:00
|
|
|
SANE_FIX (0.0),
|
|
|
|
SANE_FIX (8.3 * MM_PER_INCH),
|
|
|
|
SANE_FIX (0.0)
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static SANE_Range y_range = {
|
2011-04-10 16:42:05 +00:00
|
|
|
SANE_FIX (0.0),
|
|
|
|
SANE_FIX (11.6 * MM_PER_INCH),
|
|
|
|
SANE_FIX (0.0)
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static SANE_String_Const mode_list[] = {
|
|
|
|
SANE_I18N ("Color48"),
|
|
|
|
SANE_I18N ("Color24"),
|
|
|
|
SANE_I18N ("Gray16"),
|
|
|
|
SANE_I18N ("Gray8"),
|
2010-02-11 04:48:21 +00:00
|
|
|
SANE_VALUE_SCAN_MODE_LINEART,
|
2011-04-10 16:42:05 +00:00
|
|
|
NULL
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static SANE_String_Const negative_mode_list[] = {
|
|
|
|
SANE_I18N ("Color24"),
|
2011-04-10 16:42:05 +00:00
|
|
|
NULL
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static SANE_String_Const source_list[] = {
|
|
|
|
SANE_I18N ("Reflective"),
|
|
|
|
SANE_I18N ("Positive"),
|
|
|
|
SANE_I18N ("Negative"),
|
2011-04-10 16:42:05 +00:00
|
|
|
NULL
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
static const Scanner_Model mustek_A2nu2_model = {
|
|
|
|
"Mustek", /* device vendor string */
|
|
|
|
"BearPaw 2448TA Pro", /* device model name */
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-03-13 23:50:30 +00:00
|
|
|
{1200, 600, 300, 150, 75, 0}, /* possible resolutions */
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 17:21:52 +00:00
|
|
|
SANE_FIX (8.5 * MM_PER_INCH), /* size of scan area in mm (x) */
|
|
|
|
SANE_FIX (11.8 * MM_PER_INCH), /* size of scan area in mm (y) */
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
SANE_FIX (1.46 * MM_PER_INCH), /* size of scan area in TA mode in mm (x) */
|
|
|
|
SANE_FIX (6.45 * MM_PER_INCH), /* size of scan area in TA mode in mm (y) */
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
SANE_FALSE /* invert order of the CCD/CIS colors? */
|
2005-10-03 13:27:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
static void
|
2011-04-23 17:21:52 +00:00
|
|
|
calc_parameters (Mustek_Scanner * s, TARGETIMAGE * pTarget)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
SANE_String val, val_source;
|
2011-04-10 16:42:05 +00:00
|
|
|
float x1, y1, x2, y2;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
if (s->val[OPT_PREVIEW].w)
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->wXDpi = 75;
|
2011-04-10 16:42:05 +00:00
|
|
|
else
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->wXDpi = s->val[OPT_RESOLUTION].w;
|
|
|
|
pTarget->wYDpi = pTarget->wXDpi;
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
x1 = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH;
|
|
|
|
y1 = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH;
|
|
|
|
x2 = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH;
|
|
|
|
y2 = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH;
|
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->wX = (unsigned short) ((x1 * pTarget->wXDpi) + 0.5);
|
|
|
|
pTarget->wY = (unsigned short) ((y1 * pTarget->wYDpi) + 0.5);
|
|
|
|
pTarget->wWidth = (unsigned short) (((x2 - x1) * pTarget->wXDpi) + 0.5);
|
|
|
|
pTarget->wHeight = (unsigned short) (((y2 - y1) * pTarget->wYDpi) + 0.5);
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->wLineartThreshold = s->val[OPT_THRESHOLD].w;
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
val_source = s->val[OPT_SOURCE].s;
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_DET, "scan source = %s\n", val_source);
|
2011-04-17 12:23:46 +00:00
|
|
|
if (strcmp (val_source, source_list[SS_POSITIVE]) == 0)
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->ssScanSource = SS_POSITIVE;
|
2011-04-17 12:23:46 +00:00
|
|
|
else if (strcmp (val_source, source_list[SS_NEGATIVE]) == 0)
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->ssScanSource = SS_NEGATIVE;
|
2011-04-10 16:42:05 +00:00
|
|
|
else
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->ssScanSource = SS_REFLECTIVE;
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
val = s->val[OPT_MODE].s;
|
|
|
|
if (strcmp (val, mode_list[CM_RGB48]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
if (s->val[OPT_PREVIEW].w)
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_DET, "preview, set color mode CM_RGB24\n");
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_RGB24;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
else
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_RGB48;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
else if (strcmp (val, mode_list[CM_RGB24]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_RGB24;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
else if (strcmp (val, mode_list[CM_GRAY16]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
if (s->val[OPT_PREVIEW].w)
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_DET, "preview, set color mode CM_GRAY8\n");
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_GRAY8;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
else
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_GRAY16;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
else if (strcmp (val, mode_list[CM_GRAY8]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_GRAY8;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
else
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-20 21:10:53 +00:00
|
|
|
pTarget->cmColorMode = CM_TEXT;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-23 17:21:52 +00:00
|
|
|
s->params.pixels_per_line = pTarget->wWidth;
|
|
|
|
s->params.lines = pTarget->wHeight;
|
|
|
|
s->params.last_frame = SANE_TRUE;
|
2011-04-20 21:10:53 +00:00
|
|
|
|
|
|
|
switch (pTarget->cmColorMode)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-10 16:42:05 +00:00
|
|
|
case CM_RGB48:
|
2011-04-23 17:21:52 +00:00
|
|
|
s->params.format = SANE_FRAME_RGB;
|
|
|
|
s->params.depth = 16;
|
|
|
|
s->params.bytes_per_line = s->params.pixels_per_line * 6;
|
2005-10-03 13:27:03 +00:00
|
|
|
break;
|
2011-04-10 16:42:05 +00:00
|
|
|
case CM_RGB24:
|
2011-04-23 17:21:52 +00:00
|
|
|
s->params.format = SANE_FRAME_RGB;
|
|
|
|
s->params.depth = 8;
|
|
|
|
s->params.bytes_per_line = s->params.pixels_per_line * 3;
|
2011-04-10 16:42:05 +00:00
|
|
|
break;
|
|
|
|
case CM_GRAY16:
|
2011-04-23 17:21:52 +00:00
|
|
|
s->params.format = SANE_FRAME_GRAY;
|
|
|
|
s->params.depth = 16;
|
|
|
|
s->params.bytes_per_line = s->params.pixels_per_line * 2;
|
2011-04-10 16:42:05 +00:00
|
|
|
break;
|
|
|
|
case CM_GRAY8:
|
2011-04-23 17:21:52 +00:00
|
|
|
s->params.format = SANE_FRAME_GRAY;
|
|
|
|
s->params.depth = 8;
|
|
|
|
s->params.bytes_per_line = s->params.pixels_per_line;
|
2011-04-10 16:42:05 +00:00
|
|
|
break;
|
|
|
|
case CM_TEXT:
|
2011-04-23 17:21:52 +00:00
|
|
|
s->params.format = SANE_FRAME_GRAY;
|
|
|
|
s->params.depth = 1;
|
|
|
|
s->params.bytes_per_line = s->params.pixels_per_line / 8;
|
2005-10-03 13:27:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
static size_t
|
|
|
|
max_string_size (SANE_String_Const *strings)
|
|
|
|
{
|
|
|
|
size_t size, max_size = 0;
|
|
|
|
SANE_Int i;
|
|
|
|
|
|
|
|
for (i = 0; strings[i]; i++)
|
|
|
|
{
|
|
|
|
size = strlen (strings[i]) + 1;
|
|
|
|
if (size > max_size)
|
|
|
|
max_size = size;
|
|
|
|
}
|
|
|
|
return max_size;
|
|
|
|
}
|
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
static SANE_Status
|
|
|
|
init_options (Mustek_Scanner * s)
|
|
|
|
{
|
2011-04-23 13:28:26 +00:00
|
|
|
SANE_Status status;
|
|
|
|
SANE_Bool hasTA;
|
2011-04-10 16:42:05 +00:00
|
|
|
SANE_Int option, count = 0;
|
|
|
|
SANE_Word *dpi_list;
|
2011-04-20 21:10:53 +00:00
|
|
|
TARGETIMAGE target;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
memset (s->opt, 0, sizeof (s->opt));
|
|
|
|
memset (s->val, 0, sizeof (s->val));
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
for (option = 0; option < NUM_OPTIONS; option++)
|
|
|
|
s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
|
|
|
|
|
|
|
/* number of options */
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
|
|
|
|
s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
|
|
|
|
s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
|
|
|
|
s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_NUM_OPTS].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
|
|
|
|
s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
/* "standard" group */
|
|
|
|
s->opt[OPT_MODE_GROUP].name = SANE_NAME_STANDARD;
|
|
|
|
s->opt[OPT_MODE_GROUP].title = SANE_TITLE_STANDARD;
|
|
|
|
s->opt[OPT_MODE_GROUP].desc = SANE_DESC_STANDARD;
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
|
|
|
|
s->opt[OPT_MODE_GROUP].cap = 0;
|
|
|
|
s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
|
|
|
|
|
|
|
|
/* scan mode */
|
|
|
|
s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
|
|
|
|
s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
|
|
|
|
s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
|
|
|
|
s->opt[OPT_MODE].type = SANE_TYPE_STRING;
|
|
|
|
s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
|
|
|
s->opt[OPT_MODE].size = max_string_size (mode_list);
|
|
|
|
s->opt[OPT_MODE].constraint.string_list = mode_list;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
/* scan source */
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
|
|
|
|
s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
|
|
|
|
s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
|
|
|
|
s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
|
|
|
|
s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
|
|
|
s->opt[OPT_SOURCE].size = max_string_size (source_list);
|
|
|
|
s->opt[OPT_SOURCE].constraint.string_list = source_list;
|
2011-04-17 12:23:46 +00:00
|
|
|
s->val[OPT_SOURCE].s = strdup (source_list[SS_REFLECTIVE]);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_IsTAConnected (&s->state, &hasTA);
|
2011-04-23 13:28:26 +00:00
|
|
|
if ((status != SANE_STATUS_GOOD) || !hasTA)
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
/* resolution */
|
2011-04-10 16:42:05 +00:00
|
|
|
while (s->model.dpi_values[count] != 0)
|
|
|
|
count++;
|
2005-10-03 13:27:03 +00:00
|
|
|
dpi_list = malloc ((count + 1) * sizeof (SANE_Word));
|
|
|
|
if (!dpi_list)
|
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
dpi_list[0] = count;
|
2011-04-10 16:42:05 +00:00
|
|
|
memcpy (&dpi_list[1], s->model.dpi_values, count * sizeof (SANE_Word));
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
|
|
|
|
s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
|
|
|
|
s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
|
|
|
|
s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
|
|
|
|
s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_RESOLUTION].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
|
|
|
s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->val[OPT_RESOLUTION].w = dpi_list[1];
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
/* preview */
|
|
|
|
s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
|
|
|
|
s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
|
|
|
|
s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
|
|
|
|
s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_PREVIEW].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->val[OPT_PREVIEW].w = SANE_FALSE;
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
/* "enhancement" group */
|
|
|
|
s->opt[OPT_ENHANCEMENT_GROUP].name = SANE_NAME_ENHANCEMENT;
|
|
|
|
s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT;
|
|
|
|
s->opt[OPT_ENHANCEMENT_GROUP].desc = SANE_DESC_ENHANCEMENT;
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
|
|
|
|
s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
|
|
|
|
s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
|
|
|
|
|
|
|
|
/* threshold */
|
|
|
|
s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
|
|
|
|
s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
|
|
|
|
s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
|
|
|
|
s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
|
|
|
|
s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_THRESHOLD].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
|
|
|
|
s->opt[OPT_THRESHOLD].constraint.range = &u8_range;
|
|
|
|
s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
|
|
|
|
s->val[OPT_THRESHOLD].w = DEF_LINEARTTHRESHOLD;
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
/* "geometry" group: */
|
|
|
|
s->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY;
|
|
|
|
s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY;
|
|
|
|
s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY;
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
|
|
|
|
s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
|
|
|
|
s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
|
|
|
|
|
|
|
|
x_range.max = s->model.x_size;
|
|
|
|
y_range.max = s->model.y_size;
|
|
|
|
|
|
|
|
/* top-left x */
|
|
|
|
s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
|
|
|
|
s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
|
|
|
|
s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
|
|
|
|
s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
|
|
|
|
s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_TL_X].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
|
|
|
|
s->opt[OPT_TL_X].constraint.range = &x_range;
|
|
|
|
s->val[OPT_TL_X].w = 0;
|
|
|
|
|
|
|
|
/* top-left y */
|
|
|
|
s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
|
|
|
|
s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
|
|
|
|
s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
|
|
|
|
s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
|
|
|
|
s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_TL_Y].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
|
|
|
|
s->opt[OPT_TL_Y].constraint.range = &y_range;
|
|
|
|
s->val[OPT_TL_Y].w = 0;
|
|
|
|
|
|
|
|
/* bottom-right x */
|
|
|
|
s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
|
|
|
|
s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
|
|
|
|
s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
|
|
|
|
s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
|
|
|
|
s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_BR_X].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
|
|
|
|
s->opt[OPT_BR_X].constraint.range = &x_range;
|
|
|
|
s->val[OPT_BR_X].w = x_range.max;
|
|
|
|
|
|
|
|
/* bottom-right y */
|
|
|
|
s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
|
|
|
|
s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
|
|
|
|
s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
|
|
|
|
s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
|
|
|
|
s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_BR_Y].size = sizeof (SANE_Word);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
|
|
|
|
s->opt[OPT_BR_Y].constraint.range = &y_range;
|
|
|
|
s->val[OPT_BR_Y].w = y_range.max;
|
|
|
|
|
2011-04-23 17:21:52 +00:00
|
|
|
calc_parameters (s, &target);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-13 23:50:30 +00:00
|
|
|
/****************************** SANE API functions ****************************/
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
SANE_Status
|
2011-04-10 16:42:05 +00:00
|
|
|
sane_init (SANE_Int * version_code,
|
|
|
|
SANE_Auth_Callback __sane_unused__ authorize)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
DBG_INIT ();
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
DBG (DBG_ERR, "SANE Mustek USB2 backend version %d.%d build %d from %s\n",
|
2008-11-26 21:21:31 +00:00
|
|
|
SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
if (version_code)
|
2008-11-26 21:21:31 +00:00
|
|
|
*version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sane_exit (void)
|
|
|
|
{
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 15:22:15 +00:00
|
|
|
free (devlist);
|
|
|
|
devlist = NULL;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
2011-04-21 21:23:18 +00:00
|
|
|
sane_get_devices (const SANE_Device *** device_list,
|
|
|
|
SANE_Bool __sane_unused__ local_only)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 15:22:15 +00:00
|
|
|
free (devlist);
|
2011-04-10 16:42:05 +00:00
|
|
|
devlist = calloc (2, sizeof (devlist[0]));
|
|
|
|
if (!devlist)
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
|
|
|
|
/* HOLD: This is ugly (only one scanner!) and should go to sane_init */
|
2011-04-20 22:12:26 +00:00
|
|
|
if (Scanner_IsPresent ())
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-10 16:42:05 +00:00
|
|
|
SANE_Device *sane_device = malloc (sizeof (*sane_device));
|
|
|
|
if (!sane_device)
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
sane_device->name = strdup (device_name);
|
|
|
|
sane_device->vendor = strdup ("Mustek");
|
|
|
|
sane_device->model = strdup ("BearPaw 2448 TA Pro");
|
|
|
|
sane_device->type = strdup ("flatbed scanner");
|
2011-04-10 16:42:05 +00:00
|
|
|
devlist[0] = sane_device;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
*device_list = devlist;
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
|
|
|
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
|
|
|
{
|
2011-04-23 13:28:26 +00:00
|
|
|
SANE_Status status;
|
2005-10-03 13:27:03 +00:00
|
|
|
Mustek_Scanner *s;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_FUNC, "devicename=%s\n", devicename);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 17:04:31 +00:00
|
|
|
s = malloc (sizeof (*s));
|
|
|
|
if (!s)
|
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
memset (s, 0, sizeof (*s));
|
|
|
|
s->model = mustek_A2nu2_model;
|
|
|
|
|
|
|
|
Scanner_Init (&s->state);
|
2011-03-12 15:20:36 +00:00
|
|
|
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_PowerControl (&s->state, SANE_FALSE, SANE_FALSE);
|
2011-04-23 13:28:26 +00:00
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
return status;
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_BackHome (&s->state);
|
2011-04-23 13:28:26 +00:00
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
return status;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
init_options (s);
|
|
|
|
*handle = s;
|
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sane_close (SANE_Handle handle)
|
|
|
|
{
|
|
|
|
Mustek_Scanner *s = handle;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 17:04:31 +00:00
|
|
|
Scanner_PowerControl (&s->state, SANE_FALSE, SANE_FALSE);
|
|
|
|
Scanner_BackHome (&s->state);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 15:22:15 +00:00
|
|
|
free (s->scan_buf);
|
2011-04-17 17:00:30 +00:00
|
|
|
s->scan_buf = NULL;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
free (handle);
|
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const SANE_Option_Descriptor *
|
|
|
|
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|
|
|
{
|
|
|
|
Mustek_Scanner *s = handle;
|
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
if ((option >= NUM_OPTIONS) || (option < 0))
|
|
|
|
return NULL;
|
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
DBG (DBG_FUNC, "sane_get_option_descriptor: option = %s (%d)\n",
|
|
|
|
s->opt[option].name, option);
|
2011-04-10 16:42:05 +00:00
|
|
|
return &s->opt[option];
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
|
|
|
sane_control_option (SANE_Handle handle, SANE_Int option,
|
|
|
|
SANE_Action action, void *val, SANE_Int * info)
|
|
|
|
{
|
|
|
|
Mustek_Scanner *s = handle;
|
|
|
|
SANE_Status status;
|
|
|
|
SANE_Word cap;
|
|
|
|
SANE_Int myinfo = 0;
|
2011-04-20 21:10:53 +00:00
|
|
|
TARGETIMAGE target;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_FUNC, "action = %s, option = %s (%d)\n",
|
2011-04-10 16:42:05 +00:00
|
|
|
(action == SANE_ACTION_GET_VALUE) ? "get" :
|
2011-04-17 19:00:26 +00:00
|
|
|
(action == SANE_ACTION_SET_VALUE) ? "set" :
|
|
|
|
(action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown",
|
2005-10-03 13:27:03 +00:00
|
|
|
s->opt[option].name, option);
|
|
|
|
|
|
|
|
if (info)
|
|
|
|
*info = 0;
|
|
|
|
|
|
|
|
if (s->bIsScanning)
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "scanner is busy\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_DEVICE_BUSY;
|
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
if ((option >= NUM_OPTIONS) || (option < 0))
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "option index out of range\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_INVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cap = s->opt[option].cap;
|
|
|
|
if (!SANE_OPTION_IS_ACTIVE (cap))
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "option %d is inactive\n", option);
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_INVAL;
|
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
if (action == SANE_ACTION_GET_VALUE)
|
|
|
|
{
|
|
|
|
switch (option)
|
|
|
|
{
|
|
|
|
/* word options: */
|
|
|
|
case OPT_NUM_OPTS:
|
|
|
|
case OPT_RESOLUTION:
|
|
|
|
case OPT_PREVIEW:
|
|
|
|
case OPT_THRESHOLD:
|
|
|
|
case OPT_TL_X:
|
|
|
|
case OPT_TL_Y:
|
|
|
|
case OPT_BR_X:
|
|
|
|
case OPT_BR_Y:
|
|
|
|
*(SANE_Word *) val = s->val[option].w;
|
|
|
|
break;
|
|
|
|
/* string options: */
|
|
|
|
case OPT_MODE:
|
|
|
|
strcpy (val, s->val[option].s);
|
|
|
|
break;
|
|
|
|
case OPT_SOURCE:
|
|
|
|
strcpy (val, s->val[option].s);
|
|
|
|
break;
|
|
|
|
default:
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "unknown option %d\n", option);
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (action == SANE_ACTION_SET_VALUE)
|
|
|
|
{
|
|
|
|
if (!SANE_OPTION_IS_SETTABLE (cap))
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "option %d is not settable\n", option);
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_INVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = sanei_constrain_value (s->opt + option, val, &myinfo);
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_WARN, "sanei_constrain_value returned error: %s\n",
|
|
|
|
sane_strstatus (status));
|
2005-10-03 13:27:03 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (option)
|
|
|
|
{
|
|
|
|
/* (mostly) side-effect-free word options: */
|
|
|
|
case OPT_RESOLUTION:
|
|
|
|
case OPT_PREVIEW:
|
|
|
|
case OPT_TL_X:
|
|
|
|
case OPT_TL_Y:
|
|
|
|
case OPT_BR_X:
|
|
|
|
case OPT_BR_Y:
|
|
|
|
s->val[option].w = *(SANE_Word *) val;
|
2011-04-23 17:21:52 +00:00
|
|
|
calc_parameters (s, &target);
|
2005-10-03 13:27:03 +00:00
|
|
|
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
|
|
|
break;
|
|
|
|
case OPT_THRESHOLD:
|
|
|
|
s->val[option].w = *(SANE_Word *) val;
|
|
|
|
break;
|
|
|
|
/* side-effect-free word-array options: */
|
|
|
|
case OPT_MODE:
|
2011-04-23 15:22:15 +00:00
|
|
|
free (s->val[option].s);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->val[option].s = strdup (val);
|
2010-02-11 04:48:21 +00:00
|
|
|
if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
|
2005-10-03 13:27:03 +00:00
|
|
|
else
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
|
2011-04-23 17:21:52 +00:00
|
|
|
calc_parameters (s, &target);
|
2005-10-03 13:27:03 +00:00
|
|
|
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
|
|
|
break;
|
|
|
|
case OPT_SOURCE:
|
|
|
|
if (strcmp (s->val[option].s, val) != 0)
|
2011-04-10 16:42:05 +00:00
|
|
|
{ /* something changed */
|
2011-04-23 15:22:15 +00:00
|
|
|
free (s->val[option].s);
|
2005-10-03 13:27:03 +00:00
|
|
|
s->val[option].s = strdup (val);
|
2011-04-17 12:23:46 +00:00
|
|
|
if (strcmp (s->val[option].s, source_list[SS_REFLECTIVE]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
s->opt[OPT_MODE].size = max_string_size (mode_list);
|
|
|
|
s->opt[OPT_MODE].constraint.string_list = mode_list;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]);
|
2005-10-03 13:27:03 +00:00
|
|
|
x_range.max = s->model.x_size;
|
|
|
|
y_range.max = s->model.y_size;
|
|
|
|
}
|
2011-04-17 12:23:46 +00:00
|
|
|
else if (strcmp (s->val[option].s, source_list[SS_NEGATIVE]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-10 16:42:05 +00:00
|
|
|
s->opt[OPT_MODE].size = max_string_size (negative_mode_list);
|
|
|
|
s->opt[OPT_MODE].constraint.string_list = negative_mode_list;
|
|
|
|
s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]);
|
2005-10-03 13:27:03 +00:00
|
|
|
x_range.max = s->model.x_size_ta;
|
|
|
|
y_range.max = s->model.y_size_ta;
|
|
|
|
}
|
2011-04-17 12:23:46 +00:00
|
|
|
else if (strcmp (s->val[option].s, source_list[SS_POSITIVE]) == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
s->opt[OPT_MODE].size = max_string_size (mode_list);
|
|
|
|
s->opt[OPT_MODE].constraint.string_list = mode_list;
|
2011-04-10 16:42:05 +00:00
|
|
|
s->val[OPT_MODE].s = strdup (mode_list[CM_RGB24]);
|
2005-10-03 13:27:03 +00:00
|
|
|
x_range.max = s->model.x_size_ta;
|
|
|
|
y_range.max = s->model.y_size_ta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
|
|
|
break;
|
|
|
|
default:
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "unknown option %d\n", option);
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "unknown action %d for option %d\n", action, option);
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_INVAL;
|
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
if (info)
|
|
|
|
*info = myinfo;
|
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
|
|
|
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
|
|
|
{
|
|
|
|
Mustek_Scanner *s = handle;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "params.format = %d\n", s->params.format);
|
|
|
|
DBG (DBG_INFO, "params.depth = %d\n", s->params.depth);
|
|
|
|
DBG (DBG_INFO, "params.pixels_per_line = %d\n", s->params.pixels_per_line);
|
|
|
|
DBG (DBG_INFO, "params.bytes_per_line = %d\n", s->params.bytes_per_line);
|
|
|
|
DBG (DBG_INFO, "params.lines = %d\n", s->params.lines);
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
if (params)
|
2005-10-03 13:27:03 +00:00
|
|
|
*params = s->params;
|
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
|
|
|
sane_start (SANE_Handle handle)
|
|
|
|
{
|
2011-04-23 13:28:26 +00:00
|
|
|
SANE_Status status;
|
2005-10-03 13:27:03 +00:00
|
|
|
Mustek_Scanner *s = handle;
|
2011-04-20 21:10:53 +00:00
|
|
|
TARGETIMAGE target;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2011-04-10 16:42:05 +00:00
|
|
|
|
|
|
|
if ((s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w) ||
|
|
|
|
(s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w))
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_CRIT, "top left >= bottom right -- exiting\n");
|
2011-04-10 16:42:05 +00:00
|
|
|
return SANE_FALSE;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2011-04-23 17:21:52 +00:00
|
|
|
status = Scanner_Reset (&s->state);
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
calc_parameters (s, &target);
|
2011-04-20 21:10:53 +00:00
|
|
|
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "target.wX=%d\n", target.wX);
|
|
|
|
DBG (DBG_INFO, "target.wY=%d\n", target.wY);
|
|
|
|
DBG (DBG_INFO, "target.wWidth=%d\n", target.wWidth);
|
|
|
|
DBG (DBG_INFO, "target.wHeight=%d\n", target.wHeight);
|
|
|
|
DBG (DBG_INFO, "target.wLineartThreshold=%d\n", target.wLineartThreshold);
|
|
|
|
DBG (DBG_INFO, "target.wXDpi=%d\n", target.wXDpi);
|
|
|
|
DBG (DBG_INFO, "target.wYDpi=%d\n", target.wYDpi);
|
|
|
|
DBG (DBG_INFO, "target.cmColorMode=%d\n", target.cmColorMode);
|
|
|
|
DBG (DBG_INFO, "target.ssScanSource=%d\n", target.ssScanSource);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
s->bInvertImage = ((target.cmColorMode == CM_TEXT) ^
|
|
|
|
(target.ssScanSource == SS_NEGATIVE));
|
2011-04-10 16:42:05 +00:00
|
|
|
s->read_rows = s->params.lines;
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "read_rows=%d\n", s->read_rows);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-03-11 12:12:31 +00:00
|
|
|
DBG (DBG_INFO, "SCANNING...\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
s->bIsScanning = SANE_TRUE;
|
|
|
|
|
2011-04-23 15:22:15 +00:00
|
|
|
free (s->scan_buf);
|
2011-04-17 17:00:30 +00:00
|
|
|
s->scan_buf = malloc (SCAN_BUFFER_SIZE);
|
|
|
|
if (!s->scan_buf)
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_NO_MEM;
|
2011-04-17 17:00:30 +00:00
|
|
|
s->scan_buf_len = 0;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 13:28:26 +00:00
|
|
|
if (target.ssScanSource == SS_REFLECTIVE)
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_PowerControl (&s->state, SANE_TRUE, SANE_FALSE);
|
2011-04-23 13:28:26 +00:00
|
|
|
else
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_PowerControl (&s->state, SANE_FALSE, SANE_TRUE);
|
2011-04-23 13:28:26 +00:00
|
|
|
if (status != SANE_STATUS_GOOD)
|
|
|
|
return status;
|
|
|
|
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_SetupScan (&s->state, &target);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2011-04-23 13:28:26 +00:00
|
|
|
return status;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
|
|
|
sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
|
|
|
|
SANE_Int * len)
|
|
|
|
{
|
2011-04-23 13:28:26 +00:00
|
|
|
SANE_Status status;
|
2005-10-03 13:27:03 +00:00
|
|
|
Mustek_Scanner *s = handle;
|
2011-04-10 16:42:05 +00:00
|
|
|
SANE_Byte *tempbuf;
|
|
|
|
long int tempbuf_size;
|
2011-04-20 21:10:53 +00:00
|
|
|
SANE_Int lines, lines_read;
|
|
|
|
unsigned short lines_received;
|
|
|
|
int i;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_FUNC, "max_len=%d\n", max_len);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-10 16:42:05 +00:00
|
|
|
if (!buf || !len)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_ERR, "output parameter is null!\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_INVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
*len = 0;
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
if (!s->bIsScanning)
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_WARN, "scan was cancelled, is over or has not been " \
|
2005-10-03 13:27:03 +00:00
|
|
|
"initiated yet\n");
|
|
|
|
return SANE_STATUS_CANCELLED;
|
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_DBG, "before read data, read_row=%d\n", s->read_rows);
|
2011-04-17 17:00:30 +00:00
|
|
|
if (s->scan_buf_len == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
if (s->read_rows > 0)
|
|
|
|
{
|
2011-04-20 21:10:53 +00:00
|
|
|
lines = SCAN_BUFFER_SIZE / s->params.bytes_per_line;
|
|
|
|
lines = _MIN (lines, s->read_rows);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
tempbuf_size = lines * s->params.bytes_per_line + 3 * 1024 + 1;
|
2011-04-10 16:42:05 +00:00
|
|
|
tempbuf = malloc (tempbuf_size);
|
|
|
|
if (!tempbuf)
|
|
|
|
return SANE_STATUS_NO_MEM;
|
|
|
|
memset (tempbuf, 0, tempbuf_size);
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "buffer size is %ld\n", tempbuf_size);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
|
|
|
s->bIsReading = SANE_TRUE;
|
2011-04-20 21:10:53 +00:00
|
|
|
lines_received = (unsigned short) lines;
|
2011-04-23 17:04:31 +00:00
|
|
|
status = Scanner_GetRows (&s->state, tempbuf, &lines_received,
|
2011-04-23 13:28:26 +00:00
|
|
|
s->model.isRGBInvert);
|
|
|
|
if (status != SANE_STATUS_GOOD)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
s->bIsReading = SANE_FALSE;
|
2011-04-23 13:28:26 +00:00
|
|
|
return status;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
if (s->bInvertImage)
|
|
|
|
{
|
|
|
|
for (i = 0; i < (lines_received * s->params.bytes_per_line); i++)
|
|
|
|
tempbuf[i] ^= 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->scan_buf_len = lines_received * s->params.bytes_per_line;
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "scan_buf_len=%ld\n", (long int) s->scan_buf_len);
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-17 17:00:30 +00:00
|
|
|
memcpy (s->scan_buf, tempbuf, s->scan_buf_len);
|
|
|
|
if (s->scan_buf_len < SCAN_BUFFER_SIZE)
|
2011-04-10 16:42:05 +00:00
|
|
|
{
|
2011-04-17 17:00:30 +00:00
|
|
|
memset (s->scan_buf + s->scan_buf_len, 0,
|
|
|
|
SCAN_BUFFER_SIZE - s->scan_buf_len);
|
2011-04-10 16:42:05 +00:00
|
|
|
}
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_DBG, "after memcpy\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
free (tempbuf);
|
2011-04-17 17:00:30 +00:00
|
|
|
s->scan_buf_start = s->scan_buf;
|
2011-04-20 21:10:53 +00:00
|
|
|
s->read_rows -= lines_received;
|
2011-04-17 17:14:53 +00:00
|
|
|
s->bIsReading = SANE_FALSE;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
else
|
2011-04-10 16:42:05 +00:00
|
|
|
{
|
2011-04-17 17:00:30 +00:00
|
|
|
s->scan_buf_len = 0;
|
2011-04-10 16:42:05 +00:00
|
|
|
}
|
|
|
|
|
2011-04-17 17:00:30 +00:00
|
|
|
if (s->scan_buf_len == 0)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_FUNC, "scan finished -- exit\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
sane_cancel (handle);
|
|
|
|
return SANE_STATUS_EOF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-20 21:10:53 +00:00
|
|
|
lines_read = _MIN (max_len, s->scan_buf_len);
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_DBG, "lines_read=%d\n", lines_read);
|
2011-04-20 21:10:53 +00:00
|
|
|
*len = lines_read;
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-17 17:00:30 +00:00
|
|
|
memcpy (buf, s->scan_buf_start, lines_read);
|
|
|
|
s->scan_buf_len -= lines_read;
|
|
|
|
s->scan_buf_start += lines_read;
|
2011-04-20 21:10:53 +00:00
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
return SANE_STATUS_GOOD;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sane_cancel (SANE_Handle handle)
|
|
|
|
{
|
|
|
|
Mustek_Scanner *s = handle;
|
|
|
|
int i;
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_ENTER ();
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
if (s->bIsScanning)
|
|
|
|
{
|
|
|
|
s->bIsScanning = SANE_FALSE;
|
|
|
|
if (s->read_rows > 0)
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "warning: is scanning\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
else
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "scan finished\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
|
2011-04-23 17:04:31 +00:00
|
|
|
Scanner_StopScan (&s->state);
|
|
|
|
Scanner_BackHome (&s->state);
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2005-10-03 13:27:03 +00:00
|
|
|
for (i = 0; i < 20; i++)
|
|
|
|
{
|
2011-04-10 16:42:05 +00:00
|
|
|
if (!s->bIsReading)
|
2011-03-06 13:48:40 +00:00
|
|
|
break;
|
2011-04-17 17:00:30 +00:00
|
|
|
sleep (1);
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
2011-04-10 16:42:05 +00:00
|
|
|
|
2011-04-23 15:22:15 +00:00
|
|
|
free (s->scan_buf);
|
|
|
|
s->scan_buf = NULL;
|
|
|
|
s->scan_buf_start = NULL;
|
2005-10-03 13:27:03 +00:00
|
|
|
s->read_rows = 0;
|
2011-04-17 17:00:30 +00:00
|
|
|
s->scan_buf_len = 0;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-21 21:23:18 +00:00
|
|
|
DBG (DBG_INFO, "not scanning\n");
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
2011-04-21 21:25:34 +00:00
|
|
|
DBG_LEAVE ();
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
2011-03-30 18:57:54 +00:00
|
|
|
sane_set_io_mode (SANE_Handle __sane_unused__ handle,
|
|
|
|
SANE_Bool __sane_unused__ non_blocking)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
2011-03-30 18:57:54 +00:00
|
|
|
return SANE_STATUS_UNSUPPORTED;
|
2005-10-03 13:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SANE_Status
|
2011-03-30 18:57:54 +00:00
|
|
|
sane_get_select_fd (SANE_Handle __sane_unused__ handle,
|
|
|
|
SANE_Int __sane_unused__ * fd)
|
2005-10-03 13:27:03 +00:00
|
|
|
{
|
|
|
|
return SANE_STATUS_UNSUPPORTED;
|
|
|
|
}
|