kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'newyearsbranch' into 'master'
canon_lide70-sequel See merge request sane-project/backends!315merge-requests/393/merge
commit
f8193494ad
1
AUTHORS
1
AUTHORS
|
@ -13,6 +13,7 @@ Backends:
|
|||
Mitsuru Okaniwa, Ulrich Deiters
|
||||
canon630u: Nathan Rutman
|
||||
canon_dr: m. allan noah (*)
|
||||
canon_lide70: Juergen Ernst, pimvantend
|
||||
canon_pp: Matthew Duggan, Simon Krix
|
||||
cardscan: m. allan noah (*)
|
||||
coolscan: Didier Carlier, Andreas Rick
|
||||
|
|
|
@ -65,6 +65,7 @@ EXTRA_DIST += saned.conf.in
|
|||
BACKEND_CONFS= abaton.conf agfafocus.conf apple.conf artec.conf \
|
||||
artec_eplus48u.conf avision.conf bh.conf \
|
||||
canon630u.conf canon.conf canon_dr.conf \
|
||||
canon_lide70.conf \
|
||||
canon_pp.conf cardscan.conf coolscan2.conf coolscan3.conf \
|
||||
coolscan.conf dc210.conf dc240.conf dc25.conf \
|
||||
dell1600n_net.conf dmc.conf epjitsu.conf epson2.conf \
|
||||
|
@ -157,6 +158,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \
|
|||
libapple.la libartec.la libartec_eplus48u.la \
|
||||
libas6e.la libavision.la libbh.la \
|
||||
libcanon.la libcanon630u.la libcanon_dr.la \
|
||||
libcanon_lide70.la \
|
||||
libcanon_pp.la libcardscan.la libcoolscan.la \
|
||||
libcoolscan2.la libcoolscan3.la libdc25.la \
|
||||
libdc210.la libdc240.la libdell1600n_net.la \
|
||||
|
@ -190,6 +192,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \
|
|||
libsane-apple.la libsane-artec.la libsane-artec_eplus48u.la \
|
||||
libsane-as6e.la libsane-avision.la libsane-bh.la \
|
||||
libsane-canon.la libsane-canon630u.la libsane-canon_dr.la \
|
||||
libsane-canon_lide70.la \
|
||||
libsane-canon_pp.la libsane-cardscan.la libsane-coolscan.la \
|
||||
libsane-coolscan2.la libsane-coolscan3.la libsane-dc25.la \
|
||||
libsane-dc210.la libsane-dc240.la libsane-dell1600n_net.la \
|
||||
|
@ -344,6 +347,17 @@ libsane_canon_dr_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
|||
libsane_canon_dr_la_LIBADD = $(COMMON_LIBS) libcanon_dr.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += canon_dr.conf.in
|
||||
|
||||
libcanon_lide70_la_SOURCES = canon_lide70.c
|
||||
libcanon_lide70_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_lide70
|
||||
|
||||
nodist_libsane_canon_lide70_la_SOURCES = canon_lide70-s.c
|
||||
libsane_canon_lide70_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_lide70
|
||||
libsane_canon_lide70_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_canon_lide70_la_LIBADD = $(COMMON_LIBS) libcanon_lide70.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += canon_lide70.conf.in
|
||||
# TODO: Why are this distributed but not compiled?
|
||||
EXTRA_DIST += canon_lide70-common.c
|
||||
|
||||
libcanon_pp_la_SOURCES = canon_pp.c canon_pp.h canon_pp-io.c canon_pp-io.h canon_pp-dev.c canon_pp-dev.h
|
||||
libcanon_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_pp
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,960 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
BACKEND canon_lide70
|
||||
|
||||
Copyright (C) 2019 Juergen Ernst and pimvantend.
|
||||
|
||||
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.
|
||||
|
||||
This file implements a SANE backend for the Canon CanoScan LiDE 70 */
|
||||
|
||||
#define BUILD 0
|
||||
#define MM_IN_INCH 25.4
|
||||
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "../include/sane/sane.h"
|
||||
#include "../include/sane/sanei.h"
|
||||
#include "../include/sane/saneopts.h"
|
||||
#include "../include/sane/sanei_config.h"
|
||||
#include "../include/sane/sanei_usb.h"
|
||||
#define BACKEND_NAME canon_lide70
|
||||
#define CANONUSB_CONFIG_FILE "canon_lide70.conf"
|
||||
#include "../include/sane/sanei_backend.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
opt_num_opts = 0,
|
||||
opt_mode_group,
|
||||
opt_threshold,
|
||||
opt_mode,
|
||||
opt_resolution,
|
||||
opt_non_blocking,
|
||||
opt_geometry_group,
|
||||
opt_tl_x,
|
||||
opt_tl_y,
|
||||
opt_br_x,
|
||||
opt_br_y,
|
||||
/* must come last: */
|
||||
num_options
|
||||
}
|
||||
canon_opts;
|
||||
|
||||
#include "canon_lide70-common.c"
|
||||
|
||||
static size_t
|
||||
max_string_size (const 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;
|
||||
}
|
||||
|
||||
static SANE_String_Const mode_list[] = {
|
||||
SANE_VALUE_SCAN_MODE_COLOR,
|
||||
SANE_VALUE_SCAN_MODE_GRAY,
|
||||
SANE_VALUE_SCAN_MODE_LINEART,
|
||||
0
|
||||
};
|
||||
|
||||
static SANE_Fixed init_tl_x = SANE_FIX (0.0);
|
||||
static SANE_Fixed init_tl_y = SANE_FIX (0.0);
|
||||
static SANE_Fixed init_br_x = SANE_FIX (80.0);
|
||||
static SANE_Fixed init_br_y = SANE_FIX (100.0);
|
||||
static SANE_Int init_threshold = 75;
|
||||
static SANE_Int init_resolution = 600;
|
||||
static SANE_String init_mode = SANE_VALUE_SCAN_MODE_COLOR;
|
||||
static SANE_Int init_graymode = 0;
|
||||
static SANE_Bool init_non_blocking = SANE_FALSE;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/*
|
||||
Scan range
|
||||
*/
|
||||
|
||||
static const SANE_Range widthRange = {
|
||||
0, /* minimum */
|
||||
SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range heightRange = {
|
||||
0, /* minimum */
|
||||
/* SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600 - TOP_EDGE ), maximum */
|
||||
SANE_FIX (297.0),
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range threshold_range = {
|
||||
0,
|
||||
100,
|
||||
1
|
||||
};
|
||||
|
||||
static SANE_Int resolution_list[] = { 5,
|
||||
75,
|
||||
150,
|
||||
300,
|
||||
600,
|
||||
1200
|
||||
};
|
||||
|
||||
typedef struct Canon_Device
|
||||
{
|
||||
struct Canon_Device *next;
|
||||
SANE_String name;
|
||||
SANE_Device sane;
|
||||
}
|
||||
Canon_Device;
|
||||
|
||||
/* Canon_Scanner is the type used for the sane handle */
|
||||
typedef struct Canon_Scanner
|
||||
{
|
||||
struct Canon_Scanner *next;
|
||||
Canon_Device *device;
|
||||
CANON_Handle scan;
|
||||
}
|
||||
Canon_Scanner;
|
||||
|
||||
static int num_devices = 0;
|
||||
static const SANE_Device **devlist = NULL;
|
||||
static Canon_Device *first_dev = NULL;
|
||||
static Canon_Scanner *first_handle = NULL;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
static SANE_Status
|
||||
attach_scanner (const char *devicename, Canon_Device ** devp)
|
||||
{
|
||||
CANON_Handle scan;
|
||||
Canon_Device *dev;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (3, "attach_scanner: %s\n", devicename);
|
||||
|
||||
for (dev = first_dev; dev; dev = dev->next)
|
||||
{
|
||||
if (strcmp (dev->sane.name, devicename) == 0)
|
||||
{
|
||||
if (devp)
|
||||
*devp = dev;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
}
|
||||
|
||||
dev = malloc (sizeof (*dev));
|
||||
if (!dev)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
memset (dev, '\0', sizeof (Canon_Device)); /* clear structure */
|
||||
|
||||
DBG (4, "attach_scanner: opening %s\n", devicename);
|
||||
|
||||
status = CANON_open_device (&scan, devicename);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename);
|
||||
free (dev);
|
||||
return status;
|
||||
}
|
||||
dev->name = strdup (devicename);
|
||||
dev->sane.name = dev->name;
|
||||
dev->sane.vendor = "CANON";
|
||||
dev->sane.model = CANON_get_device_name (&scan);
|
||||
dev->sane.type = "flatbed scanner";
|
||||
CANON_close_device (&scan);
|
||||
|
||||
++num_devices;
|
||||
dev->next = first_dev;
|
||||
first_dev = dev;
|
||||
|
||||
if (devp)
|
||||
*devp = dev;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* callback function for sanei_usb_attach_matching_devices */
|
||||
static SANE_Status
|
||||
attach_one (const char *name)
|
||||
{
|
||||
attach_scanner (name, 0);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* Find our devices */
|
||||
SANE_Status
|
||||
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
|
||||
{
|
||||
char config_line[PATH_MAX];
|
||||
size_t len;
|
||||
FILE *fp;
|
||||
|
||||
DBG_INIT ();
|
||||
|
||||
#if 0
|
||||
DBG_LEVEL = 10;
|
||||
#endif
|
||||
|
||||
DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
|
||||
version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
|
||||
DBG (1, "sane_init: SANE Canon LiDE70 backend version %d.%d.%d from %s\n",
|
||||
V_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
|
||||
|
||||
if (version_code)
|
||||
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD);
|
||||
|
||||
sanei_usb_init ();
|
||||
|
||||
fp = sanei_config_open (CANONUSB_CONFIG_FILE);
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
/* no config-file: try these */
|
||||
attach_scanner ("/dev/scanner", 0);
|
||||
attach_scanner ("/dev/usbscanner", 0);
|
||||
attach_scanner ("/dev/usb/scanner", 0);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE);
|
||||
|
||||
while (sanei_config_read (config_line, sizeof (config_line), fp))
|
||||
{
|
||||
if (config_line[0] == '#')
|
||||
continue; /* ignore line comments */
|
||||
|
||||
len = strlen (config_line);
|
||||
|
||||
if (!len)
|
||||
continue; /* ignore empty lines */
|
||||
|
||||
DBG (4, "attach_matching_devices(%s)\n", config_line);
|
||||
sanei_usb_attach_matching_devices (config_line, attach_one);
|
||||
}
|
||||
|
||||
DBG (4, "finished reading configure file\n");
|
||||
|
||||
fclose (fp);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sane_exit (void)
|
||||
{
|
||||
Canon_Device *dev, *next;
|
||||
|
||||
DBG (3, "sane_exit\n");
|
||||
|
||||
for (dev = first_dev; dev; dev = next)
|
||||
{
|
||||
next = dev->next;
|
||||
free (dev->name);
|
||||
free (dev);
|
||||
}
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
|
||||
{
|
||||
Canon_Device *dev;
|
||||
int i;
|
||||
|
||||
DBG (3, "sane_get_devices(local_only = %d)\n", local_only);
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
|
||||
devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
|
||||
if (!devlist)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
i = 0;
|
||||
|
||||
for (dev = first_dev; i < num_devices; dev = dev->next)
|
||||
devlist[i++] = &dev->sane;
|
||||
|
||||
devlist[i++] = 0;
|
||||
|
||||
*device_list = devlist;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
init_options (CANON_Handle * chndl)
|
||||
{
|
||||
SANE_Option_Descriptor *od;
|
||||
|
||||
DBG (2, "begin init_options: chndl=%p\n", (void *) chndl);
|
||||
|
||||
/* opt_num_opts */
|
||||
od = &chndl->opt[opt_num_opts];
|
||||
od->name = "";
|
||||
od->title = SANE_TITLE_NUM_OPTIONS;
|
||||
od->desc = SANE_DESC_NUM_OPTIONS;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_num_opts].w = num_options;
|
||||
|
||||
DBG (2, "val[opt_num_opts]: %d\n", chndl->val[opt_num_opts].w);
|
||||
|
||||
/* opt_mode_group */
|
||||
od = &chndl->opt[opt_mode_group];
|
||||
od->name = "";
|
||||
od->title = SANE_I18N ("Scan Mode");
|
||||
od->desc = "";
|
||||
od->type = SANE_TYPE_GROUP;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = 0;
|
||||
od->cap = 0;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_mode_group].w = 0;
|
||||
|
||||
/* opt_mode */
|
||||
od = &chndl->opt[opt_mode];
|
||||
od->name = SANE_NAME_SCAN_MODE;
|
||||
od->title = SANE_TITLE_SCAN_MODE;
|
||||
od->desc = SANE_DESC_SCAN_MODE;
|
||||
od->type = SANE_TYPE_STRING;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = max_string_size (mode_list);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
od->constraint.string_list = mode_list;
|
||||
chndl->val[opt_mode].s = malloc (od->size);
|
||||
if (!chndl->val[opt_mode].s)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
strcpy (chndl->val[opt_mode].s, init_mode);
|
||||
chndl->graymode = init_graymode;
|
||||
|
||||
/* opt_threshold */
|
||||
od = &chndl->opt[opt_threshold];
|
||||
od->name = SANE_NAME_THRESHOLD;
|
||||
od->title = SANE_TITLE_THRESHOLD;
|
||||
od->desc = SANE_DESC_THRESHOLD;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_PERCENT;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &threshold_range;
|
||||
chndl->val[opt_threshold].w = init_threshold;
|
||||
|
||||
/* opt_resolution */
|
||||
od = &chndl->opt[opt_resolution];
|
||||
od->name = SANE_NAME_SCAN_RESOLUTION;
|
||||
od->title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
od->desc = SANE_DESC_SCAN_RESOLUTION;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_DPI;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
od->constraint.word_list = resolution_list;
|
||||
chndl->val[opt_resolution].w = init_resolution;
|
||||
|
||||
/* opt_non_blocking */
|
||||
od = &chndl->opt[opt_non_blocking];
|
||||
od->name = "non-blocking";
|
||||
od->title = SANE_I18N ("Use non-blocking IO");
|
||||
od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported "
|
||||
"by the frontend.");
|
||||
od->type = SANE_TYPE_BOOL;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_non_blocking].w = init_non_blocking;
|
||||
|
||||
/* opt_geometry_group */
|
||||
od = &chndl->opt[opt_geometry_group];
|
||||
od->name = "";
|
||||
od->title = SANE_I18N ("Geometry");
|
||||
od->desc = "";
|
||||
od->type = SANE_TYPE_GROUP;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = 0;
|
||||
od->cap = 0;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_geometry_group].w = 0;
|
||||
|
||||
/* opt_tl_x */
|
||||
od = &chndl->opt[opt_tl_x];
|
||||
od->name = SANE_NAME_SCAN_TL_X;
|
||||
od->title = SANE_TITLE_SCAN_TL_X;
|
||||
od->desc = SANE_DESC_SCAN_TL_X;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &widthRange;
|
||||
chndl->val[opt_tl_x].w = init_tl_x;
|
||||
|
||||
/* opt_tl_y */
|
||||
od = &chndl->opt[opt_tl_y];
|
||||
od->name = SANE_NAME_SCAN_TL_Y;
|
||||
od->title = SANE_TITLE_SCAN_TL_Y;
|
||||
od->desc = SANE_DESC_SCAN_TL_Y;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &heightRange;
|
||||
chndl->val[opt_tl_y].w = init_tl_y;
|
||||
|
||||
/* opt_br_x */
|
||||
od = &chndl->opt[opt_br_x];
|
||||
od->name = SANE_NAME_SCAN_BR_X;
|
||||
od->title = SANE_TITLE_SCAN_BR_X;
|
||||
od->desc = SANE_DESC_SCAN_BR_X;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &widthRange;
|
||||
chndl->val[opt_br_x].w = init_br_x;
|
||||
|
||||
/* opt_br_y */
|
||||
od = &chndl->opt[opt_br_y];
|
||||
od->name = SANE_NAME_SCAN_BR_Y;
|
||||
od->title = SANE_TITLE_SCAN_BR_Y;
|
||||
od->desc = SANE_DESC_SCAN_BR_Y;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &heightRange;
|
||||
chndl->val[opt_br_y].w = init_br_y;
|
||||
|
||||
DBG (2, "end init_options: chndl=%p\n", (void *) chndl);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
||||
{
|
||||
Canon_Device *dev;
|
||||
SANE_Status status;
|
||||
Canon_Scanner *scanner;
|
||||
|
||||
DBG (3, "sane_open\n");
|
||||
|
||||
if (devicename[0]) /* search for devicename */
|
||||
{
|
||||
DBG (4, "sane_open: devicename=%s\n", devicename);
|
||||
|
||||
for (dev = first_dev; dev; dev = dev->next)
|
||||
if (strcmp (dev->sane.name, devicename) == 0)
|
||||
break;
|
||||
|
||||
if (!dev)
|
||||
{
|
||||
status = attach_scanner (devicename, &dev);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG (2, "sane_open: no devicename, opening first device\n");
|
||||
dev = first_dev;
|
||||
}
|
||||
|
||||
if (!dev)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
scanner = malloc (sizeof (*scanner));
|
||||
|
||||
if (!scanner)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
memset (scanner, 0, sizeof (*scanner));
|
||||
scanner->device = dev;
|
||||
|
||||
status = CANON_open_device (&scanner->scan, dev->sane.name);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (scanner);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = init_options (&scanner->scan);
|
||||
|
||||
*handle = scanner;
|
||||
|
||||
/* insert newly opened handle into list of open handles: */
|
||||
scanner->next = first_handle;
|
||||
|
||||
first_handle = scanner;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
print_options (CANON_Handle * chndl)
|
||||
{
|
||||
SANE_Option_Descriptor *od;
|
||||
SANE_Word option_number;
|
||||
SANE_Char caps[1024];
|
||||
|
||||
for (option_number = 0; option_number < num_options; option_number++)
|
||||
{
|
||||
od = &chndl->opt[option_number];
|
||||
DBG (50, "-----> number: %d\n", option_number);
|
||||
DBG (50, " name: `%s'\n", od->name);
|
||||
DBG (50, " title: `%s'\n", od->title);
|
||||
DBG (50, " description: `%s'\n", od->desc);
|
||||
DBG (50, " type: %s\n",
|
||||
od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" :
|
||||
od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" :
|
||||
od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" :
|
||||
od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" :
|
||||
od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" :
|
||||
od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown");
|
||||
DBG (50, " unit: %s\n",
|
||||
od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" :
|
||||
od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" :
|
||||
od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" :
|
||||
od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" :
|
||||
od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" :
|
||||
od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" :
|
||||
od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" :
|
||||
"unknown");
|
||||
DBG (50, " size: %d\n", od->size);
|
||||
caps[0] = '\0';
|
||||
if (od->cap & SANE_CAP_SOFT_SELECT)
|
||||
strcat (caps, "SANE_CAP_SOFT_SELECT ");
|
||||
if (od->cap & SANE_CAP_HARD_SELECT)
|
||||
strcat (caps, "SANE_CAP_HARD_SELECT ");
|
||||
if (od->cap & SANE_CAP_SOFT_DETECT)
|
||||
strcat (caps, "SANE_CAP_SOFT_DETECT ");
|
||||
if (od->cap & SANE_CAP_EMULATED)
|
||||
strcat (caps, "SANE_CAP_EMULATED ");
|
||||
if (od->cap & SANE_CAP_AUTOMATIC)
|
||||
strcat (caps, "SANE_CAP_AUTOMATIC ");
|
||||
if (od->cap & SANE_CAP_INACTIVE)
|
||||
strcat (caps, "SANE_CAP_INACTIVE ");
|
||||
if (od->cap & SANE_CAP_ADVANCED)
|
||||
strcat (caps, "SANE_CAP_ADVANCED ");
|
||||
DBG (50, " capabilities: %s\n", caps);
|
||||
DBG (50, "constraint type: %s\n",
|
||||
od->constraint_type == SANE_CONSTRAINT_NONE ?
|
||||
"SANE_CONSTRAINT_NONE" :
|
||||
od->constraint_type == SANE_CONSTRAINT_RANGE ?
|
||||
"SANE_CONSTRAINT_RANGE" :
|
||||
od->constraint_type == SANE_CONSTRAINT_WORD_LIST ?
|
||||
"SANE_CONSTRAINT_WORD_LIST" :
|
||||
od->constraint_type == SANE_CONSTRAINT_STRING_LIST ?
|
||||
"SANE_CONSTRAINT_STRING_LIST" : "unknown");
|
||||
if (od->type == SANE_TYPE_INT)
|
||||
DBG (50, " value: %d\n", chndl->val[option_number].w);
|
||||
else if (od->type == SANE_TYPE_FIXED)
|
||||
DBG (50, " value: %f\n",
|
||||
SANE_UNFIX (chndl->val[option_number].w));
|
||||
else if (od->type == SANE_TYPE_STRING)
|
||||
DBG (50, " value: %s\n", chndl->val[option_number].s);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sane_close (SANE_Handle handle)
|
||||
{
|
||||
Canon_Scanner *prev, *scanner;
|
||||
SANE_Status res;
|
||||
|
||||
DBG (3, "sane_close\n");
|
||||
|
||||
scanner = handle;
|
||||
print_options (&scanner->scan);
|
||||
|
||||
if (!first_handle)
|
||||
{
|
||||
DBG (1, "ERROR: sane_close: no handles opened\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* remove handle from list of open handles: */
|
||||
|
||||
prev = NULL;
|
||||
|
||||
for (scanner = first_handle; scanner; scanner = scanner->next)
|
||||
{
|
||||
if (scanner == handle)
|
||||
break;
|
||||
|
||||
prev = scanner;
|
||||
}
|
||||
|
||||
if (!scanner)
|
||||
{
|
||||
DBG (1, "ERROR: sane_close: invalid handle %p\n", handle);
|
||||
return; /* oops, not a handle we know about */
|
||||
}
|
||||
|
||||
if (prev)
|
||||
prev->next = scanner->next;
|
||||
else
|
||||
first_handle = scanner->next;
|
||||
|
||||
res = CANON_close_device (&scanner->scan);
|
||||
DBG (3, "CANON_close_device returned: %d\n", res);
|
||||
free (scanner);
|
||||
}
|
||||
|
||||
const SANE_Option_Descriptor *
|
||||
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
CANON_Handle *chndl = &scanner->scan;
|
||||
|
||||
|
||||
DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n",
|
||||
(void *) handle, option);
|
||||
if (option < 0 || option >= num_options)
|
||||
{
|
||||
DBG (3, "sane_get_option_descriptor: option < 0 || "
|
||||
"option > num_options\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return &chndl->opt[option];
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
|
||||
void *value, SANE_Int * info)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
CANON_Handle *chndl = &scanner->scan;
|
||||
|
||||
SANE_Int myinfo = 0;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
|
||||
(void *) handle, option, action, (void *) value, (void *) info);
|
||||
|
||||
if (option < 0 || option >= num_options)
|
||||
{
|
||||
DBG (1, "sane_control_option: option < 0 || option > num_options\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (!SANE_OPTION_IS_ACTIVE (chndl->opt[option].cap))
|
||||
{
|
||||
DBG (1, "sane_control_option: option is inactive\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (chndl->opt[option].type == SANE_TYPE_GROUP)
|
||||
{
|
||||
DBG (1, "sane_control_option: option is a group\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case SANE_ACTION_SET_VALUE:
|
||||
if (!SANE_OPTION_IS_SETTABLE (chndl->opt[option].cap))
|
||||
{
|
||||
DBG (1, "sane_control_option: option is not setable\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
status = sanei_constrain_value (&chndl->opt[option], value, &myinfo);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (3, "sane_control_option: sanei_constrain_value returned %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
switch (option)
|
||||
{
|
||||
case opt_tl_x: /* Fixed with parameter reloading */
|
||||
case opt_tl_y:
|
||||
case opt_br_x:
|
||||
case opt_br_y:
|
||||
if (chndl->val[option].w == *(SANE_Fixed *) value)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
chndl->val[option].w = *(SANE_Fixed *) value;
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n",
|
||||
option, chndl->opt[option].name,
|
||||
SANE_UNFIX (*(SANE_Fixed *) value),
|
||||
chndl->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi");
|
||||
break;
|
||||
case opt_non_blocking:
|
||||
if (chndl->val[option].w == *(SANE_Bool *) value)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
chndl->val[option].w = *(SANE_Bool *) value;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %s\n",
|
||||
option, chndl->opt[option].name,
|
||||
*(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
|
||||
break;
|
||||
case opt_resolution:
|
||||
case opt_threshold:
|
||||
if (chndl->val[option].w == *(SANE_Int *) value)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
chndl->val[option].w = *(SANE_Int *) value;
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
myinfo |= SANE_INFO_RELOAD_OPTIONS;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %d\n",
|
||||
option, chndl->opt[option].name, *(SANE_Int *) value);
|
||||
break;
|
||||
case opt_mode:
|
||||
if (strcmp (chndl->val[option].s, value) == 0)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
strcpy (chndl->val[option].s, (SANE_String) value);
|
||||
|
||||
if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) ==
|
||||
0)
|
||||
{
|
||||
chndl->opt[opt_threshold].cap &= ~SANE_CAP_INACTIVE;
|
||||
chndl->graymode = 2;
|
||||
}
|
||||
if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
|
||||
{
|
||||
chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE;
|
||||
chndl->graymode = 0;
|
||||
}
|
||||
if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
|
||||
{
|
||||
chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE;
|
||||
chndl->graymode = 1;
|
||||
}
|
||||
|
||||
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
myinfo |= SANE_INFO_RELOAD_OPTIONS;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %s\n",
|
||||
option, chndl->opt[option].name, (SANE_String) value);
|
||||
break;
|
||||
default:
|
||||
DBG (1, "sane_control_option: trying to set unexpected option\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SANE_ACTION_GET_VALUE:
|
||||
switch (option)
|
||||
{
|
||||
case opt_num_opts:
|
||||
*(SANE_Word *) value = num_options;
|
||||
DBG (4, "sane_control_option: get option 0, value = %d\n",
|
||||
num_options);
|
||||
break;
|
||||
case opt_tl_x: /* Fixed options */
|
||||
case opt_tl_y:
|
||||
case opt_br_x:
|
||||
case opt_br_y:
|
||||
{
|
||||
*(SANE_Fixed *) value = chndl->val[option].w;
|
||||
DBG (4,
|
||||
"sane_control_option: get option %d (%s), value=%.1f %s\n",
|
||||
option, chndl->opt[option].name,
|
||||
SANE_UNFIX (*(SANE_Fixed *) value),
|
||||
chndl->opt[option].unit ==
|
||||
SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : "");
|
||||
break;
|
||||
}
|
||||
case opt_non_blocking:
|
||||
*(SANE_Bool *) value = chndl->val[option].w;
|
||||
DBG (4,
|
||||
"sane_control_option: get option %d (%s), value=%s\n",
|
||||
option, chndl->opt[option].name,
|
||||
*(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
|
||||
break;
|
||||
case opt_mode: /* String (list) options */
|
||||
strcpy (value, chndl->val[option].s);
|
||||
DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n",
|
||||
option, chndl->opt[option].name, (SANE_String) value);
|
||||
break;
|
||||
case opt_resolution:
|
||||
case opt_threshold:
|
||||
*(SANE_Int *) value = chndl->val[option].w;
|
||||
DBG (4, "sane_control_option: get option %d (%s), value=%d\n",
|
||||
option, chndl->opt[option].name, *(SANE_Int *) value);
|
||||
break;
|
||||
default:
|
||||
DBG (1, "sane_control_option: trying to get unexpected option\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DBG (1, "sane_control_option: trying unexpected action %d\n", action);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (info)
|
||||
*info = myinfo;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
||||
{
|
||||
Canon_Scanner *hndl = handle; /* Eliminate compiler warning */
|
||||
CANON_Handle *chndl = &hndl->scan;
|
||||
|
||||
int rc = SANE_STATUS_GOOD;
|
||||
int w = SANE_UNFIX (chndl->val[opt_br_x].w -
|
||||
chndl->val[opt_tl_x].w) / MM_IN_INCH *
|
||||
chndl->val[opt_resolution].w;
|
||||
int h =
|
||||
SANE_UNFIX (chndl->val[opt_br_y].w -
|
||||
chndl->val[opt_tl_y].w) / MM_IN_INCH *
|
||||
chndl->val[opt_resolution].w;
|
||||
|
||||
DBG (3, "sane_get_parameters\n");
|
||||
chndl->params.depth = 8;
|
||||
chndl->params.last_frame = SANE_TRUE;
|
||||
chndl->params.pixels_per_line = w;
|
||||
chndl->params.lines = h;
|
||||
|
||||
if (chndl->graymode == 1)
|
||||
{
|
||||
chndl->params.format = SANE_FRAME_GRAY;
|
||||
chndl->params.bytes_per_line = w;
|
||||
}
|
||||
else if (chndl->graymode == 2)
|
||||
{
|
||||
chndl->params.format = SANE_FRAME_GRAY;
|
||||
w /= 8;
|
||||
|
||||
if ((chndl->params.pixels_per_line % 8) != 0)
|
||||
w++;
|
||||
|
||||
chndl->params.bytes_per_line = w;
|
||||
chndl->params.depth = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
chndl->params.format = SANE_FRAME_RGB;
|
||||
chndl->params.bytes_per_line = w * 3;
|
||||
}
|
||||
|
||||
*params = chndl->params;
|
||||
DBG (1, "%d\n", chndl->params.format);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_start (SANE_Handle handle)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
CANON_Handle *chndl = &scanner->scan;
|
||||
SANE_Status res;
|
||||
|
||||
DBG (3, "sane_start\n");
|
||||
|
||||
res = sane_get_parameters (handle, &chndl->params);
|
||||
res = CANON_set_scan_parameters (&scanner->scan);
|
||||
|
||||
if (res != SANE_STATUS_GOOD)
|
||||
return res;
|
||||
|
||||
return CANON_start_scan (&scanner->scan);
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_read (SANE_Handle handle, SANE_Byte * data,
|
||||
SANE_Int max_length, SANE_Int * length)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
return CANON_read (&scanner->scan, data, max_length, length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sane_cancel (SANE_Handle handle)
|
||||
{
|
||||
DBG (3, "sane_cancel: handle = %p\n", handle);
|
||||
DBG (3, "sane_cancel: cancelling is unsupported in this backend\n");
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
|
||||
{
|
||||
DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
|
||||
non_blocking);
|
||||
if (non_blocking != SANE_FALSE)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
|
||||
{
|
||||
handle = handle; /* silence gcc */
|
||||
fd = fd; /* silence gcc */
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# Options for the canon_lide70 backend
|
||||
|
||||
# Autodetect the Canon CanoScan LiDE 70
|
||||
usb 0x04a9 0x2225
|
||||
|
||||
# device list for non-linux-systems (enable if autodetect fails):
|
||||
#/dev/scanner
|
||||
#/dev/usb/scanner0
|
|
@ -19,6 +19,7 @@ bh
|
|||
canon
|
||||
canon630u
|
||||
canon_dr
|
||||
canon_lide70
|
||||
#canon_pp
|
||||
cardscan
|
||||
coolscan
|
||||
|
|
|
@ -665,7 +665,7 @@ AC_ARG_ENABLE(local-backends,
|
|||
[turn off compilation of all backends but net]))
|
||||
|
||||
ALL_BACKENDS="abaton agfafocus apple artec artec_eplus48u as6e \
|
||||
avision bh canon canon630u canon_dr canon_pp cardscan \
|
||||
avision bh canon canon630u canon_dr canon_lide70 canon_pp cardscan \
|
||||
coolscan coolscan2 coolscan3 dc25 dc210 dc240 \
|
||||
dell1600n_net dmc epjitsu epson epson2 epsonds escl fujitsu \
|
||||
genesys gphoto2 gt68xx hp hp3500 hp3900 hp4200 hp5400 \
|
||||
|
|
|
@ -18,6 +18,7 @@ EXTRA_DIST = scanimage.man sane-config.man sane-find-scanner.man \
|
|||
# custom install/uninstall if we required man pages for every backend.
|
||||
|
||||
BACKEND_5MANS = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 \
|
||||
sane-canon_lide70.5 \
|
||||
sane-dll.5 sane-dc25.5 sane-dmc.5 sane-epson.5 sane-epson2.5 sane-epsonds.5 \
|
||||
sane-escl.5 sane-hp.5 sane-gphoto2.5 sane-leo.5 sane-lexmark.5 \
|
||||
sane-matsushita.5 sane-microtek.5 sane-microtek2.5 sane-mustek.5 \
|
||||
|
@ -40,6 +41,7 @@ BACKEND_5MANS = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 \
|
|||
sane-kvs40xx.5 sane-p5.5 sane-magicolor.5
|
||||
|
||||
EXTRA_DIST += sane-abaton.man sane-agfafocus.man sane-apple.man sane-as6e.man \
|
||||
sane-canon_lide70.man \
|
||||
sane-dll.man sane-dc25.man sane-dmc.man sane-epson.man \
|
||||
sane-epson2.man sane-epsonds.man sane-escl.man sane-hp.man sane-gphoto2.man \
|
||||
sane-leo.man sane-lexmark.man sane-matsushita.man sane-microtek.man \
|
||||
|
@ -150,6 +152,7 @@ DESC_FILES = descriptions/abaton.desc descriptions/agfafocus.desc \
|
|||
descriptions/artec_eplus48u.desc descriptions/as6e.desc \
|
||||
descriptions/avision.desc descriptions/bh.desc descriptions/canon630u.desc \
|
||||
descriptions/canon.desc descriptions/canon_dr.desc \
|
||||
descriptions/canon_lide70.desc \
|
||||
descriptions/canon_pp.desc descriptions/cardscan.desc \
|
||||
descriptions/coolscan2.desc descriptions/coolscan.desc \
|
||||
descriptions/coolscan3.desc \
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
;
|
||||
; SANE Backend specification file
|
||||
;
|
||||
; It's basically emacs-lisp --- so ";" indicates comment to end of line.
|
||||
; All syntactic elements are keyword tokens, followed by a string or
|
||||
; keyword argument, as specified.
|
||||
;
|
||||
; ":backend" *must* be specified.
|
||||
; All other information is optional (but what good is the file without it?).
|
||||
;
|
||||
|
||||
:backend "canon_lide70" ; name of backend
|
||||
:url "http://www.juergen-ernst.de/info_sane.html"
|
||||
:version "0" ; version of backend
|
||||
:manpage "sane-canon_lide70" ; name of manpage (if it exists)
|
||||
:devicetype :scanner ; start of a list of devices....
|
||||
; other types: :stillcam, :vidcam,
|
||||
; :meta, :api
|
||||
|
||||
:mfg "Canon" ; name a manufacturer
|
||||
:url "http://www.canon.com/"
|
||||
|
||||
;==================================================
|
||||
:model "CanoScan LiDE 70"
|
||||
:interface "USB"
|
||||
:usbid "0x04a9" "0x2225"
|
||||
:status :basic
|
||||
:comment "Please test!"
|
|
@ -395,13 +395,6 @@
|
|||
:status :unsupported
|
||||
:comment "Not supported. However, a stand-alone program for FreeBSD is available."
|
||||
|
||||
:model "CanoScan LiDE 70"
|
||||
:url "http://www.juergen-ernst.de/info_sane.html"
|
||||
:interface "USB"
|
||||
:usbid "0x04a9" "0x2225"
|
||||
:status :unsupported
|
||||
:comment "Philips chip. Backend started, see link"
|
||||
|
||||
:model "CanoScan LiDE 90"
|
||||
:url "unsupported/canon-lide-90.html"
|
||||
:interface "USB"
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
.TH sane\-canon_lide70 5 "26 Nov 2019" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
|
||||
.IX sane\-canon_lide70
|
||||
.SH NAME
|
||||
sane\-canon_lide70 \- SANE backend for the Canon LiDE 70 USB flatbed scanner
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B canon_lide70
|
||||
library implements a SANE (Scanner Access Now Easy) backend that
|
||||
provides access to the Canon Inc. CanoScan LiDE 70 flatbed scanner.
|
||||
.PP
|
||||
Due to Canon's unwillingness to provide scanner documentation, this
|
||||
software was developed by analyzing the USB traffic of the Windows
|
||||
XP driver. The precise meaning of the individual commands that are sent
|
||||
to the scanner is known only to a very limited extent. Some sophistication
|
||||
present in the Windows XP driver has been left out. There is, for example,
|
||||
no active calibration.
|
||||
.PP
|
||||
TESTERS ARE WELCOME. Send your bug reports and comments to
|
||||
the sane\-devel mailing list <sane\-devel@alioth-lists.debian.net>
|
||||
.PP
|
||||
The
|
||||
.B Canoscan LiDE 600
|
||||
(or 600f, with film unit) is closely related to the LiDE 70, but
|
||||
it probably will not work with this backend. The framework of this canon_lide70
|
||||
backend could likely be used to develop a backend for the LiDE 600 without too
|
||||
much difficulty.
|
||||
.PP
|
||||
.SH CONFIGURATION
|
||||
The
|
||||
.I @CONFIGDIR@/canon_lide70.conf
|
||||
file identifies the LiDE 70 by its vendor code 0x04a9 and its
|
||||
product code 0x2225. For the LiDE 600(f) the product code would be 0x2224.
|
||||
.PP
|
||||
.SH BACKEND SPECIFIC OPTIONS
|
||||
.PP
|
||||
.B Scan Mode:
|
||||
.TP
|
||||
\-\-resolution 75|150|300|600|1200 [default 600]
|
||||
.BR
|
||||
Sets the resolution of the scanned image in dots per inch. Scanning at 1200 dpi is very slow.
|
||||
.TP
|
||||
\-\-mode Color|Gray|Lineart [default: Color]
|
||||
.BR
|
||||
Selects the scan mode. Lineart means fully black and fully white pixels only.
|
||||
.TP
|
||||
\-\-threshold 0..100 (in steps of 1) [default 75]
|
||||
.BR
|
||||
Select minimum-brightness percentage to get a white point, relevant only for Lineart
|
||||
.TP
|
||||
\-\-non-blocking[=(yes|no)] [inactive]
|
||||
.BR
|
||||
This option has not yet been implemented. Scans are captured in a temporary file with a typical size of 100MB.
|
||||
.PP
|
||||
.B Geometry:
|
||||
.TP
|
||||
\-l 0..216.069 [default 0]
|
||||
Top-left x position of scan area in millimeters.
|
||||
.TP
|
||||
\-t 0..297 [default 0]
|
||||
Top-left y position of scan area in millimeters.
|
||||
.TP
|
||||
\-x 0..216.069 [default 80]
|
||||
Width of scan-area in millimeters.
|
||||
.TP
|
||||
\-y 0..297 [default 100]
|
||||
Height of scan-area in millimeters.
|
||||
.PP
|
||||
.SH FILES
|
||||
.TP
|
||||
.I @CONFIGDIR@/canon_lide70.conf
|
||||
The backend configuration file
|
||||
.TP
|
||||
.I @LIBDIR@/libsane\-canon_lide70.a
|
||||
The static library implementing this backend.
|
||||
.TP
|
||||
.I @LIBDIR@/libsane\-canon_lide70.so
|
||||
The shared library implementing this backend (present on systems that
|
||||
support dynamic loading).
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B SANE_DEBUG_CANON_LIDE70
|
||||
If the library was compiled with debug support enabled, this
|
||||
environment variable controls the debug level for this backend. Higher
|
||||
debug levels increase the verbosity of the output.
|
||||
|
||||
Example:
|
||||
.br
|
||||
SANE_DEBUG_CANON_LIDE70=128 scanimage > /dev/null
|
||||
.SH KNOWN PROBLEMS
|
||||
At low resolutions (75 and 150 dpi, implying high slider speeds)
|
||||
the scanner misses the top one millimeter of the scan area. This can
|
||||
be remedied by shifting the document one millimeter downward, in cases
|
||||
where such precision matters. Note that xsane uses the 75 dpi mode for
|
||||
prescans.
|
||||
.PP
|
||||
It is recommended that in xsane the gamma value be set to approximately 2.0
|
||||
to get more realistic colors. This also wipes out some artifacts caused by
|
||||
the lack of real calibration.
|
||||
.SH "SEE ALSO"
|
||||
sane(7), sane\-usb(5), sane\-find\-scanner(1), scanimage(1)
|
||||
.br
|
||||
http://www.juergen-ernst.de/info_sane.html
|
||||
.br
|
||||
.SH AUTHOR
|
||||
pimvantend, building upon pioneering work by Juergen Ernst.
|
|
@ -20,6 +20,7 @@ backend/canon-sane.c
|
|||
backend/canon.c
|
||||
backend/canon630u.c
|
||||
backend/canon_dr.c
|
||||
backend/canon_lide70.c
|
||||
backend/epjitsu.c
|
||||
backend/epson.c
|
||||
backend/epson.h
|
||||
|
|
Ładowanie…
Reference in New Issue