2000-11-20 Henning Meier-Geinitz <hmg@gmx.de>

* AUTHORS: Added Eugene S. Weiss.
	* PROJECTS: Removed Artec as6e backend.
	* README: Added link to man sane-as6e.5.
	* TODO: Removed as6e.
	* doc/Makefile.in: Added generation of as6e manpage.
        * backend/Makefile.in: Added entries for as6e.
	* backend/dll.conf: Added as6e.
	* backend/as6e.c backend/as6e.h backend/as6e.desc doc/sane-as6e.man:
	  Added backend for Artec AS6E parallel port scanner (from Eugene S.
	  Weiss <yossarian@users.sourceforge.net>).
DEVEL_2_0_BRANCH-1
Henning Geinitz 2000-11-20 22:59:02 +00:00
rodzic f0d5bc32ea
commit 32d8b87c92
10 zmienionych plików z 1050 dodań i 20 usunięć

Wyświetl plik

@ -12,6 +12,7 @@ Backends:
agfafocus: Karl Anders Øygard
apple: Milon Firikis
artec: Chris Pinkham (*)
as6e: Eugene S. Weiss (*)
avision: Meino Christian Cramer, Rene Rebe(*)
canon: Helmut Koeberle, Manuel Panea (*), and Markus Mertinat
coolscan: Didier Carlier, Andreas Rick (*)
@ -80,6 +81,7 @@ David F. Skoll <dskoll@iname.com>
David Huggins-Daines <bn711@freenet.carleton.ca>
David Mosberger <David.Mosberger@acm.org>
Didier Carlier <didier@sema.be>
Eugene S. Weiss <yossarian@users.sourceforge.net>
FUKUDA Kazuya <fukuda@avm.nhe.nec.co.jp>
Juergen G. Schimmer <schimmi@nbgm.siemens.de>
Feico W. Dillema <dillema@acm.org>

Wyświetl plik

@ -1,4 +1,4 @@
PROJECTS (2000-11-15)
PROJECTS (2000-11-19)
Here is a list of projects that various people have expressed interest
in. Before starting working on one of these projects, it may be a
@ -16,9 +16,6 @@ wip Work in progress. There is (more or less) working code. For details,
Backends:
---------
Artec AS6E (wip)
http://as6edriver.sourceforge.net/
Autobrightness/contrast for cameras etc. (planned?)
David Mosberger

1
README
Wyświetl plik

@ -105,6 +105,7 @@ below:
AGFA SnapScan sane-snapscan(5)
Apple sane-apple(5)
Artec sane-artec(5)
Artec AS6E parport sane-as6e(5)
Avision sane-avision(5)
Canon sane-canon(5)
Nikon Coolscan sane-coolscan(5)

Wyświetl plik

@ -51,10 +51,10 @@ COMPILE = $(CC) -c $(CFLAGS) $(DEFS) $(INCLUDES) $(CPPFLAGS)
@SET_MAKE@
PRELOADABLE_BACKENDS = abaton agfafocus apple artec avision canon coolscan \
dc25 @DC210@ dmc epson hp m3096g microtek microtek2 mustek mustek_pp \
@NET@ pie @PINT@ plustek pnm @QCAM@ ricoh s9036 sharp snapscan sp15c \
st400 tamarack umax @V4L@
PRELOADABLE_BACKENDS = abaton agfafocus apple artec as6e avision canon \
coolscan dc25 @DC210@ dmc epson hp m3096g microtek microtek2 mustek \
mustek_pp @NET@ pie @PINT@ plustek pnm @QCAM@ ricoh s9036 sharp \
snapscan sp15c st400 tamarack umax @V4L@
ALL_BACKENDS = $(PRELOADABLE_BACKENDS) dll
LIBS = $(addprefix libsane-,$(addsuffix .la,$(ALL_BACKENDS)))
@ -176,6 +176,8 @@ libsane-apple.la: ../sanei/sanei_scsi.lo
libsane-artec.la: ../sanei/sanei_config2.lo
libsane-artec.la: ../sanei/sanei_constrain_value.lo
libsane-artec.la: ../sanei/sanei_scsi.lo
libsane-as6e.la: ../sanei/sanei_config2.lo
libsane-as6e.la: ../sanei/sanei_constrain_value.lo
libsane-avision.la: ../sanei/sanei_config2.lo
libsane-avision.la: ../sanei/sanei_constrain_value.lo
libsane-avision.la: ../sanei/sanei_scsi.lo

895
backend/as6e.c 100644
Wyświetl plik

@ -0,0 +1,895 @@
/***************************************************************************
as6e.c - description
-------------------
begin : Mon Feb 21 20:27:05 EST 2000
copyright : (C) 2000 by Eugene Weiss
email : eweiss@sas.upenn.edu
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "../include/sane/config.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <limits.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include "as6e.h"
#include "../include/sane/sane.h"
#include "../include/sane/saneopts.h"
#define BACKENDNAME as6e
#include "../include/sane/sanei_backend.h"
#include "../include/sane/sanei_config.h"
static int num_devices;
static AS6E_Device *first_dev;
static AS6E_Scan *first_handle;
static SANE_Status attach (const char *devname, AS6E_Device ** devp);
/* static SANE_Status attach_one (const char *dev); */
static const SANE_String_Const mode_list[] = {
"Lineart", "Gray", "Color",
0
};
static const SANE_Word resolution_list[] = {
4, 300, 200, 100, 50
};
static const SANE_Range x_range = {
SANE_FIX (0),
SANE_FIX (215.91),
SANE_FIX (0)
};
static const SANE_Range y_range = {
SANE_FIX (0),
SANE_FIX (297.19),
SANE_FIX (0)
};
static const SANE_Range brightness_range = {
-100,
100,
1
};
static const SANE_Range contrast_range = {
-100,
100,
1
};
/*--------------------------------------------------------------------------*/
static SANE_Int as6e_unit_convert (SANE_Fixed value)
{
double precise;
SANE_Int return_value;
precise = SANE_UNFIX (value);
precise = (precise * 300) / MM_PER_INCH;
return_value = precise;
return return_value;
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
SANE_Int * len)
{
AS6E_Scan *s = handle;
SANE_Word buffer_offset = 0;
int written = 0, bytes_read = 0, maxbytes;
SANE_Word bytecounter, linebufcounter, ctlbytes;
SANE_Byte *linebuffer;
DBG (3, "\nreading %d bytes, %d bytes in carryover buffer", max_len,
s->scan_buffer_count);
if (s->image_counter >= s->bytes_to_read)
{
*len = 0;
if (s->scanning)
{
read (s->as6e_params.ctlinpipe, &written, sizeof (written));
if (written != -1)
printf ("\npipe error");
DBG (3, "\ntrying to read -1 ...written = %d", written);
}
s->scanning = SANE_FALSE;
DBG (1, "\nimage data complete, sending EOF...");
return SANE_STATUS_EOF;
} /*image complete */
linebuffer = s->line_buffer;
if (s->scan_buffer_count > 0)
{ /*there are leftover bytes from the last call */
if (s->scan_buffer_count <= max_len)
{
for (*len = 0; *len < s->scan_buffer_count; (*len)++)
{
buf[*len] = s->scan_buffer[*len];
buffer_offset++;
}
s->scan_buffer_count = 0;
if (s->scan_buffer_count == max_len)
{
s->scan_buffer_count = 0;
s->image_counter += max_len;
DBG (3, "\nreturning %d bytes from the carryover buffer", *len);
return SANE_STATUS_GOOD;
}
}
else
{
for (*len = 0; *len < max_len; (*len)++)
buf[*len] = s->scan_buffer[*len];
for (bytecounter = max_len;
bytecounter < s->scan_buffer_count; bytecounter++)
s->scan_buffer[bytecounter - max_len]
= s->scan_buffer[bytecounter];
s->scan_buffer_count -= max_len;
s->image_counter += max_len;
DBG (3, "\nreturning %d bytes from the carryover buffer", *len);
return SANE_STATUS_GOOD;
}
}
else
{
*len = 0; /*no bytes in the buffer */
if (!s->scanning)
{
DBG (1, "\nscan over returning %d", *len);
if (s->scan_buffer_count)
return SANE_STATUS_GOOD;
else
return SANE_STATUS_EOF;
}
}
while (*len < max_len)
{
DBG (3, "\ntrying to read number of bytes...");
ctlbytes = read (s->as6e_params.ctlinpipe, &written, sizeof (written));
DBG (3, "\nbytes written = %d, ctlbytes =%d", written, ctlbytes);
fflush (stdout);
if ((s->cancelled) && (written == 0))
{ /*first clear -1 from pipe */
DBG (1, "\nsending SANE_STATUS_CANCELLED");
read (s->as6e_params.ctlinpipe, &written, sizeof (written));
s->scanning = SANE_FALSE;
return SANE_STATUS_CANCELLED;
}
if (written == -1)
{
DBG (1, "\n-1READ Scanner through. returning %d bytes", *len);
s->image_counter += *len;
s->scanning = SANE_FALSE;
return SANE_STATUS_GOOD;
}
linebufcounter = 0;
DBG (3,
"\nlinebufctr reset, len =%d written =%d bytes_read =%d, max = %d",
*len, written, bytes_read, max_len);
maxbytes = written;
while (linebufcounter < written)
{
DBG (4, "\ntrying to read data pipe");
bytes_read =
read (s->as6e_params.datapipe, linebuffer + linebufcounter,
maxbytes);
linebufcounter += bytes_read;
maxbytes -= bytes_read;
DBG (3, "\nbytes_read = %d linebufcounter = %d", bytes_read,
linebufcounter);}
DBG (3, "\nwritten =%d max_len =%d len =%d", written, max_len, *len);
if (written <= (max_len - *len))
{
for (bytecounter = 0; bytecounter < written; bytecounter++)
{
buf[bytecounter + buffer_offset] = linebuffer[bytecounter];
(*len)++;
}
buffer_offset += written;
DBG (3, "\nbuffer offset = %d", buffer_offset);
}
else if (max_len > *len)
{ /*there's still room to send data */
for (bytecounter = 0; bytecounter < (max_len - *len); bytecounter++)
buf[bytecounter + buffer_offset] = linebuffer[bytecounter];
DBG (3, "\ntopping off buffer");
for (bytecounter = (max_len - *len); bytecounter < written;
bytecounter++)
{
s->scan_buffer[s->scan_buffer_count + bytecounter -
(max_len - *len)] = linebuffer[bytecounter];
}
s->scan_buffer_count += (written - (max_len - *len));
*len = max_len;
}
else
{ /*everything goes into the carryover buffer */
for (bytecounter = 0; bytecounter < written; bytecounter++)
s->scan_buffer[s->scan_buffer_count + bytecounter]
= linebuffer[bytecounter]; s->scan_buffer_count += written;
}
} /*while there's space in the buffer */
s->image_counter += *len;
DBG (3, "\nimage ctr = %d bytes_to_read = %d returning %d",
s->image_counter, s->bytes_to_read, *len);
return SANE_STATUS_GOOD;
}
/*--------------------------------------------------------------------------*/
void
sane_cancel (SANE_Handle h)
{
AS6E_Scan *s = h;
SANE_Word test;
DBG (2, "\ntrying to cancel...");
if (s->scanning)
{
test = kill (s->child_pid, SIGUSR1);
if (test == 0)
s->cancelled = SANE_TRUE;
}
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_start (SANE_Handle handle)
{
AS6E_Scan *s = handle;
SANE_Status status;
int repeat = 1;
SANE_Word numbytes;
int scan_params[8];
/* First make sure we have a current parameter set. Some of the
* parameters will be overwritten below, but that's OK. */
DBG (2, "\nsane_start");
status = sane_get_parameters (s, 0);
if (status != SANE_STATUS_GOOD)
return status;
DBG (1, "\nGot params again...");
numbytes = write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat));
if (numbytes != sizeof (repeat))
return (SANE_STATUS_IO_ERROR);
DBG (1, "\nsending start_scan signal");
scan_params[0] = s->as6e_params.resolution;
if (strcmp (s->value[OPT_MODE].s, "Color") == 0)
scan_params[1] = 0;
else if (strcmp (s->value[OPT_MODE].s, "Gray") == 0)
scan_params[1] = 1;
else if (strcmp (s->value[OPT_MODE].s, "Lineart") == 0)
scan_params[1] = 2;
else
return (SANE_STATUS_JAMMED); /*this should never happen */
scan_params[2] = s->as6e_params.startpos;
scan_params[3] = s->as6e_params.stoppos;
scan_params[4] = s->as6e_params.startline;
scan_params[5] = s->as6e_params.stopline;
scan_params[6] = s->value[OPT_BRIGHTNESS].w;
scan_params[7] = s->value[OPT_CONTRAST].w;
DBG (1, "\nscan params = %d %d %d %d %d %d %d %d", scan_params[0],
scan_params[1], scan_params[2], scan_params[3],
scan_params[4], scan_params[5], scan_params[6], scan_params[7]);
numbytes =
write (s->as6e_params.ctloutpipe, scan_params, sizeof (scan_params));
if (numbytes != sizeof (scan_params))
return (SANE_STATUS_IO_ERROR);
s->scanning = SANE_TRUE;
s->scan_buffer_count = 0;
s->image_counter = 0;
s->cancelled = 0;
return (SANE_STATUS_GOOD);
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
{
AS6E_Scan *s = handle;
SANE_String mode;
SANE_Word divisor = 1;
DBG (2, "\nsane_get_parameters");
if (!s->scanning)
{
memset (&s->sane_params, 0, sizeof (s->sane_params));
s->as6e_params.resolution = s->value[OPT_RESOLUTION].w;
s->as6e_params.startpos = as6e_unit_convert (s->value[OPT_TL_X].w);
s->as6e_params.stoppos = as6e_unit_convert (s->value[OPT_BR_X].w);
s->as6e_params.startline = as6e_unit_convert (s->value[OPT_TL_Y].w);
s->as6e_params.stopline = as6e_unit_convert (s->value[OPT_BR_Y].w);
if ((s->as6e_params.resolution == 200)
|| (s->as6e_params.resolution == 100)) divisor = 3;
else if (s->as6e_params.resolution == 50)
divisor = 6; /*get legal values for 200 dpi */
s->as6e_params.startpos = (s->as6e_params.startpos / divisor) * divisor;
s->as6e_params.stoppos = (s->as6e_params.stoppos / divisor) * divisor;
s->as6e_params.startline =
(s->as6e_params.startline / divisor) * divisor;
s->as6e_params.stopline = (s->as6e_params.stopline / divisor) * divisor;
s->sane_params.pixels_per_line =
(s->as6e_params.stoppos -
s->as6e_params.startpos) * s->as6e_params.resolution / 300;
s->sane_params.lines =
(s->as6e_params.stopline -
s->as6e_params.startline) * s->as6e_params.resolution / 300;
mode = s->value[OPT_MODE].s;
/* if ((strcmp (s->mode, "Lineart") == 0) ||
(strcmp (s->mode, "Halftone") == 0))
{
s->sane_params.format = SANE_FRAME_GRAY;
s->sane_params.bytes_per_line = (s->sane_params.pixels_per_line + 7) / 8;
s->sane_params.depth = 1;
} */
/*else*/ if ((strcmp (mode, "Gray") == 0)
|| (strcmp (mode, "Lineart") == 0))
{
s->sane_params.format = SANE_FRAME_GRAY;
s->sane_params.bytes_per_line = s->sane_params.pixels_per_line;
s->sane_params.depth = 8;
} /*grey frame */
else
{
s->sane_params.format = SANE_FRAME_RGB;
s->sane_params.bytes_per_line = 3 * s->sane_params.pixels_per_line;
s->sane_params.depth = 8;
} /*color frame */
s->bytes_to_read = s->sane_params.lines * s->sane_params.bytes_per_line;
s->sane_params.last_frame = SANE_TRUE;
} /*!scanning */
if (params)
*params = s->sane_params;
return (SANE_STATUS_GOOD);
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_control_option (SANE_Handle handle, SANE_Int option,
SANE_Action action, void *val, SANE_Int * info)
{
AS6E_Scan *s = handle;
SANE_Status status = 0;
SANE_Word cap;
DBG (2, "\nsane_control_option");
if (info)
*info = 0;
if (s->scanning)
return SANE_STATUS_DEVICE_BUSY;
if (option >= NUM_OPTIONS)
return SANE_STATUS_INVAL;
cap = s->options_list[option].cap;
if (!SANE_OPTION_IS_ACTIVE (cap))
return SANE_STATUS_INVAL;
if (action == SANE_ACTION_GET_VALUE)
{
DBG (1, "sane_control_option %d, get value\n", option);
switch (option)
{
/* word options: */
case OPT_RESOLUTION:
case OPT_TL_X:
case OPT_TL_Y:
case OPT_BR_X:
case OPT_BR_Y:
case OPT_NUM_OPTS:
case OPT_CONTRAST:
case OPT_BRIGHTNESS:
*(SANE_Word *) val = s->value[option].w;
return (SANE_STATUS_GOOD);
/* string options: */
case OPT_MODE:
strcpy (val, s->value[option].s);
return (SANE_STATUS_GOOD);
}
}
else if (action == SANE_ACTION_SET_VALUE)
{
DBG (1, "sane_control_option %d, set value\n", option);
if (!SANE_OPTION_IS_SETTABLE (cap))
return (SANE_STATUS_INVAL);
/* status = sanei_constrain_value (s->options_list[option], val, info);*/
if (status != SANE_STATUS_GOOD)
return (status);
switch (option)
{
/* (mostly) side-effect-free word options: */
case OPT_RESOLUTION:
case OPT_BR_X:
case OPT_BR_Y:
case OPT_TL_X:
case OPT_TL_Y:
if (info && s->value[option].w != *(SANE_Word *) val)
*info |= SANE_INFO_RELOAD_PARAMS;
/* fall through */
case OPT_NUM_OPTS:
case OPT_CONTRAST:
case OPT_BRIGHTNESS:
s->value[option].w = *(SANE_Word *) val;
DBG (1, "\nset brightness to");
return (SANE_STATUS_GOOD);
case OPT_MODE:
if (s->value[option].s)
free (s->value[option].s);
s->value[option].s = strdup (val);
return (SANE_STATUS_GOOD);
}
}
return (SANE_STATUS_INVAL);
}
/*--------------------------------------------------------------------------*/
const SANE_Option_Descriptor *
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
{
AS6E_Scan *s = handle;
DBG (2, "\nsane_get_option_descriptor");
if ((unsigned) option >= NUM_OPTIONS)
return (0);
return (&s->options_list[option]);
}
/*--------------------------------------------------------------------------*/
void
sane_close (SANE_Handle handle)
{
AS6E_Scan *prev, *s;
SANE_Word repeat = 0;
DBG (2, "\nsane_close");
/* remove handle from list of open handles: */
prev = 0;
for (s = first_handle; s; s = s->next)
{
if (s == handle)
break;
prev = s;
}
if (!s)
{
DBG (1, "close: invalid handle %p\n", handle);
return; /* oops, not a handle we know about */
}
if (s->scanning)
sane_cancel (handle);
write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat));
close (s->as6e_params.ctloutpipe);
free (s->scan_buffer);
free (s->line_buffer);
if (prev)
prev->next = s->next;
else
first_handle = s;
free (handle);
}
/*--------------------------------------------------------------------------*/
void
sane_exit (void)
{
AS6E_Device *next;
DBG (2, "\nsane_exit");
while (first_dev != NULL)
{
next = first_dev->next;
/* free((void *) first_dev->sane.name);*/
/* free((void *) first_dev->sane.model);*/
free (first_dev);
first_dev = next;
}
}
/*--------------------------------------------------------------------------*/
static SANE_Status
as6e_open (AS6E_Scan * s)
{
int data_processed, exec_result, as6e_status;
int ctloutpipe[2], ctlinpipe[2], datapipe[2];
char inpipe_desc[32], outpipe_desc[32], datapipe_desc[32];
pid_t fork_result;
DBG (1, "\nas6e_open");
memset (inpipe_desc, '\0', sizeof (inpipe_desc));
memset (outpipe_desc, '\0', sizeof (outpipe_desc));
memset (datapipe_desc, '\0', sizeof (datapipe_desc));
if ((pipe (ctloutpipe) == 0) && (pipe (ctlinpipe) == 0)
&& (pipe (datapipe) == 0))
{
fork_result = fork ();
if (fork_result == (pid_t) - 1)
{
fprintf (stderr, "Fork failure");
return (SANE_STATUS_IO_ERROR);
}
if (fork_result == 0)
{ /*in child */
sprintf (inpipe_desc, "%d", ctlinpipe[WRITEPIPE]);
sprintf (outpipe_desc, "%d", ctloutpipe[READPIPE]);
sprintf (datapipe_desc, "%d", datapipe[WRITEPIPE]);
exec_result =
execlp ("as6edriver", "as6edriver", "-s", inpipe_desc,
outpipe_desc, datapipe_desc, (char *) 0);
printf ("\nThe SANE backend was unable to start \"as6edriver\".");
printf ("\nThis must be installed in a driectory in your PATH.\n");
printf ("\nTo aquire the as6edriver program,");
printf ("\ngo to http://as6edriver.sourceforge.net.");
write (ctlinpipe[WRITEPIPE], &exec_result, sizeof (exec_result));
exit (-1);
}
else
{ /*parent process */
data_processed =
read (ctlinpipe[READPIPE], &as6e_status, sizeof (as6e_status));
DBG (1, "%d - read %d status = %d\n", getpid (), data_processed,
as6e_status); if (as6e_status == -2)
{
printf ("\nPort access denied.");
return (SANE_STATUS_IO_ERROR);
}
if (as6e_status == -1)
{
printf ("\nCould not contact scanner.");
return (SANE_STATUS_IO_ERROR);
}
if (as6e_status == 1)
printf ("\nUsing nibble mode.");
if (as6e_status == 2)
printf ("\nUsing byte mode.");
if (as6e_status == 3)
printf ("\nUsing EPP mode.");
s->as6e_params.ctlinpipe = ctlinpipe[READPIPE];
s->as6e_params.ctloutpipe = ctloutpipe[WRITEPIPE];
s->as6e_params.datapipe = datapipe[READPIPE];
s->child_pid = fork_result;
return (SANE_STATUS_GOOD);
} /*else */
}
else
return (SANE_STATUS_IO_ERROR);
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
{
char dev_name[PATH_MAX];
size_t len;
FILE *fp = NULL;
DBG_INIT();
DBG (2, "\nsane_init");
if (version_code)
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0);
/* fp = sanei_config_open (AS6E_CONFIG_FILE);*/
if (!fp)
{
/* attach ("as6edriver", 0);*/
return (attach ("as6edriver", 0));
}
while (fgets (dev_name, sizeof (dev_name), fp))
{
if (dev_name[0] == '#') /* ignore line comments */
continue;
len = strlen (dev_name);
if (dev_name[len - 1] == '\n')
dev_name[--len] = '\0';
if (!len)
continue; /* ignore empty lines */
/* sanei_config_attach_matching_devices (dev_name, attach_one);*/
}
fclose (fp);
return (SANE_STATUS_GOOD);
}
/*--------------------------------------------------------------------------*/
/*
static SANE_Status
attach_one (const char *dev)
{
DBG (2, "attach_one\n");
attach (dev, 0);
return (SANE_STATUS_GOOD);
}
*/
/*--------------------------------------------------------------------------*/
SANE_Status
sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
{
static const SANE_Device **devlist = 0;
AS6E_Device *dev;
int i;
DBG (3, "\nsane_get_devices");
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 size_t
max_string_size (const SANE_String_Const strings[])
{
size_t size, max_size = 0;
int i;
for (i = 0; strings[i]; ++i)
{
size = strlen (strings[i]) + 1;
if (size > max_size)
max_size = size;
}
return (max_size);
}
/*--------------------------------------------------------------------------*/
static void
initialize_options_list (AS6E_Scan * s)
{
SANE_Int option;
DBG (2, "\ninitialize_options_list");
for (option = 0; option < NUM_OPTIONS; ++option)
{
s->options_list[option].size = sizeof (SANE_Word);
s->options_list[option].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;}
s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT;
s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE;
s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word);
s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE;
s->value[OPT_NUM_OPTS].w = NUM_OPTIONS;
s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE;
s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
s->options_list[OPT_MODE].type = SANE_TYPE_STRING;
s->options_list[OPT_MODE].size = max_string_size (mode_list);
s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
s->options_list[OPT_MODE].constraint.string_list = mode_list;
s->value[OPT_MODE].s = strdup (mode_list[2]);
s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT;
s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list;
s->value[OPT_RESOLUTION].w = 200;
s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED;
s->options_list[OPT_TL_X].unit = SANE_UNIT_MM;
s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
s->options_list[OPT_TL_X].constraint.range = &x_range;
s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min;
s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED;
s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM;
s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
s->options_list[OPT_TL_Y].constraint.range = &y_range;
s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min;
s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED;
s->options_list[OPT_BR_X].unit = SANE_UNIT_MM;
s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
s->options_list[OPT_BR_X].constraint.range = &x_range;
s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max;
s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED;
s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM;
s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
s->options_list[OPT_BR_Y].constraint.range = &y_range;
s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max;
s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
s->options_list[OPT_CONTRAST].type = SANE_TYPE_INT;
s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE;
s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
s->options_list[OPT_CONTRAST].constraint.range = &brightness_range;
s->value[OPT_BRIGHTNESS].w = 10;
s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
s->options_list[OPT_BRIGHTNESS].constraint.range = &contrast_range;
s->value[OPT_CONTRAST].w = -32;
}
/*--------------------------------------------------------------------------*/
static int
check_for_driver (const char *devname)
{
#define NAMESIZE 128
struct stat statbuf;
mode_t modes;
char *path;
char fullname[NAMESIZE];
char dir[NAMESIZE];
int count = 0, offset = 0;
path = getenv ("PATH");
while (path[count] != '\0')
{
memset (fullname, '\0', sizeof (fullname));
memset (dir, '\0', sizeof (dir));
while ((path[count] != ':') && (path[count] != '\0'))
{
dir[count - offset] = path[count];
count++;
}
strncpy (fullname, dir, NAMESIZE);
strncat (fullname, "/", NAMESIZE);
strncat (fullname, devname, NAMESIZE);
stat (fullname, &statbuf);
modes = statbuf.st_mode;
if (S_ISREG (modes))
return (1); /* found as6edriver */
if (path[count] == '\0')
return (0); /* end of path --no driver found */
count++;
offset = count;
}
return (0);
}
/*--------------------------------------------------------------------------*/
static SANE_Status
attach (const char *devname, AS6E_Device ** devp)
{
AS6E_Device *dev;
/* SANE_Status status; */
DBG (2, "\nattach");
for (dev = first_dev; dev; dev = dev->next)
{
if (strcmp (dev->sane.name, devname) == 0)
{
if (devp)
*devp = dev;
return (SANE_STATUS_GOOD);
}
}
dev = malloc (sizeof (*dev));
if (!dev)
return (SANE_STATUS_NO_MEM);
memset (dev, 0, sizeof (*dev));
dev->sane.name = strdup (devname);
if (!check_for_driver (devname))
return (SANE_STATUS_INVAL);
dev->sane.model = "AS6E";
dev->sane.vendor = "Artec";
dev->sane.type = "flatbed scanner";
++num_devices;
dev->next = first_dev;
first_dev = dev;
if (devp)
*devp = dev;
return (SANE_STATUS_GOOD);
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
{
SANE_Status status;
AS6E_Device *dev;
AS6E_Scan *s;
DBG (2, "\nsane_open");
if (devicename[0])
{
for (dev = first_dev; dev; dev = dev->next)
if (strcmp (dev->sane.name, devicename) == 0)
break;
if (!dev)
{
status = attach (devicename, &dev);
if (status != SANE_STATUS_GOOD)
return (status);
}
}
else
{
/* empty devicname -> use first device */
dev = first_dev;
}
if (!dev)
return SANE_STATUS_INVAL;
s = malloc (sizeof (*s));
if (!s)
return SANE_STATUS_NO_MEM;
memset (s, 0, sizeof (*s));
s->scan_buffer = malloc (SCAN_BUF_SIZE);
if (!s->scan_buffer)
return SANE_STATUS_NO_MEM;
memset (s->scan_buffer, 0, SCAN_BUF_SIZE);
s->line_buffer = malloc (SCAN_BUF_SIZE);
if (!s->line_buffer)
return SANE_STATUS_NO_MEM;
memset (s->line_buffer, 0, SCAN_BUF_SIZE);
status = as6e_open (s);
if (status != SANE_STATUS_GOOD)
return status;
initialize_options_list (s);
s->scanning = 0;
/* insert newly opened handle into list of open handles: */
s->next = first_handle;
first_handle = s;
*handle = s;
return (status);
}
/*--------------------------------------------------------------------------*/
SANE_Status
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
{
DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking);
return (SANE_STATUS_UNSUPPORTED);
}
/*---------------------------------------------------------------------------*/
SANE_Status
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
{
return SANE_STATUS_UNSUPPORTED;
}

Wyświetl plik

@ -8,10 +8,10 @@
; All other information is optional (but what good is the file without it?).
;
:backend "as6e" ; name of backend
:version "(0.4.0)" ; version of backend
:status :alpha ; :alpha, :beta, :stable, :new
;:manpage "sane-as6e" ; name of manpage (if it exists)
:backend "as6e" ; name of backend
:version "0.4.2" ; version of backend
:status :new ; :alpha, :beta, :stable, :new
:manpage "sane-as6e" ; name of manpage (if it exists)
:url "http://as6edriver.sourceforge.net/"
:devicetype :scanner
@ -21,7 +21,7 @@
:model "AS6E"
:interface "Parport"
:comment "all modes working"
:comment "Requires the program 'as6edriver' to run."
; :comment and :url specifiers are optional after :mfg, :model, :desc,

98
backend/as6e.h 100644
Wyświetl plik

@ -0,0 +1,98 @@
/***************************************************************************
as6e.h - description
-------------------
begin : Mon Feb 21 2000
copyright : (C) 2000 by Eugene Weiss
email : eweiss@sas.upenn.edu
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <sys/stat.h>
#include <sys/types.h>
#include <sane/sane.h>
typedef union
{
SANE_Word w; /* word */
SANE_Word *wa; /* word array */
SANE_String s; /* string */
} Option_Value;
typedef enum
{
OPT_NUM_OPTS = 0,
OPT_MODE,
OPT_RESOLUTION,
OPT_TL_X, /* top-left x */
OPT_TL_Y, /* top-left y */
OPT_BR_X, /* bottom-right x */
OPT_BR_Y, /* bottom-right y */
OPT_BRIGHTNESS,
OPT_CONTRAST,
/* must come last */
NUM_OPTIONS
} AS6E_Option;
typedef struct
{
int color;
int resolution;
int startpos;
int stoppos;
int startline;
int stopline;
int ctloutpipe;
int ctlinpipe;
int datapipe;
} AS6E_Params;
typedef struct AS6E_Device
{
struct AS6E_Device *next;
SANE_Device sane;
} AS6E_Device;
typedef struct AS6E_Scan
{
struct AS6E_Scan *next;
SANE_Option_Descriptor options_list[NUM_OPTIONS];
Option_Value value[NUM_OPTIONS];
SANE_Bool scanning;
SANE_Bool cancelled;
SANE_Parameters sane_params;
AS6E_Params as6e_params;
pid_t child_pid;
size_t bytes_to_read;
SANE_Byte *scan_buffer;
SANE_Byte *line_buffer;
SANE_Word scan_buffer_count;
SANE_Word image_counter;
} AS6E_Scan;
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#define AS6E_CONFIG_FILE "as6e.conf"
#define READPIPE 0
#define WRITEPIPE 1
#define MM_PER_INCH 25.4
#define SCAN_BUF_SIZE 32768

Wyświetl plik

@ -5,6 +5,7 @@ agfafocus
apple
avision
artec
as6e
canon
coolscan
#dc25

Wyświetl plik

@ -31,13 +31,14 @@ LN_S = @LN_S@
@SET_MAKE@
SECT1 = saned.1 scanimage.1 xscanimage.1 xcam.1
SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-dll.5 sane-dc25.5 \
sane-dmc.5 sane-epson.5 sane-hp.5 sane-microtek.5 sane-microtek2.5 \
sane-mustek.5 sane-net.5 sane-pie.5 sane-pint.5 sane-pnm.5 sane-umax.5 \
sane-qcam.5 sane-scsi.5 sane-artec.5 sane-fujitsu.5 sane-sharp.5 \
sane-s9036.5 sane-tamarack.5 sane-ricoh.5 sane-avision.5 \
sane-plustek.5 sane-st400.5 sane-mustek_pp.5 sane-dc210.5 \
sane-v4l.5 sane-snapscan.5 sane-canon.5 sane-coolscan.5
SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 \
sane-dc25.5 sane-dmc.5 sane-epson.5 sane-hp.5 sane-microtek.5 \
sane-microtek2.5 sane-mustek.5 sane-net.5 sane-pie.5 sane-pint.5 \
sane-pnm.5 sane-umax.5 sane-qcam.5 sane-scsi.5 sane-artec.5 \
sane-fujitsu.5 sane-sharp.5 sane-s9036.5 sane-tamarack.5 \
sane-ricoh.5 sane-avision.5 sane-plustek.5 sane-st400.5 \
sane-mustek_pp.5 sane-dc210.5 sane-v4l.5 sane-snapscan.5 \
sane-canon.5 sane-coolscan.5
MANPAGES = $(SECT1) $(SECT5)
DOCS = sane.ps sane.dvi
LATEX = TEXINPUTS=$(srcdir):$$TEXINPUTS latex

33
doc/sane-as6e.man 100644
Wyświetl plik

@ -0,0 +1,33 @@
.TH sane-as6e 5 " November 19, 2000" "SANE Artec AS6E Backend "
.SH NAME
sane-as6e \-SANE backend for using the Artec AS6E parallel port interface scanner.
.SH DESCRIPTION
The
.B sane-as6e
library implements a SANE (Scanner Access Now Easy) backend
that provides access to Artec AS6E flatbed scanner.
.B It requires the as6edriver program in order to operate.
The as6edriver program is
.B not
included with the SANE package.
It can be found at
.B http://as6edriver.sourceforge.net
. See the as6edriver documentation for technical information.
.PP
.SH FILES
.B as6edriver
-driver program that controls the scanner.
.SH BUGS
.SH SEE ALSO
as6edriver(5)
.SH AUTHOR
Eugene S. Weiss
.SH EMAIL-CONTACT
yossarian@users.sourceforge.net