From 31d39a110b795b17b261d491fce9db854fd5517d Mon Sep 17 00:00:00 2001 From: Oliver Rauch Date: Thu, 7 Mar 2002 19:47:15 +0000 Subject: [PATCH] 2002-03-07 Oliver Rauch * updated umax backend to version 1.0.7-build-33 new file: umax-usb.c (by Frank Zago) --- backend/umax-scanner.c | 2 +- backend/umax-scanner.h | 2 +- backend/umax-scsidef.h | 2 +- backend/umax-uc1200s.c | 2 +- backend/umax-uc1200se.c | 2 +- backend/umax-uc1260.c | 2 +- backend/umax-uc630.c | 2 +- backend/umax-uc840.c | 2 +- backend/umax-ug630.c | 2 +- backend/umax-ug80.c | 2 +- backend/umax-usb.c | 327 +++++++++++++++++++++++++ backend/umax.c | 518 +++++++++++++++++++++++++--------------- backend/umax.conf | 82 ++++++- backend/umax.desc | 14 +- backend/umax.h | 27 +-- 15 files changed, 760 insertions(+), 228 deletions(-) create mode 100644 backend/umax-usb.c diff --git a/backend/umax-scanner.c b/backend/umax-scanner.c index 11843f936..b1de549b4 100644 --- a/backend/umax-scanner.c +++ b/backend/umax-scanner.c @@ -2,7 +2,7 @@ /* umax-scanner.c: scanner-definiton file for UMAX scanner driver. - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-scanner.h b/backend/umax-scanner.h index abdbf45fa..6c9a93a8a 100644 --- a/backend/umax-scanner.h +++ b/backend/umax-scanner.h @@ -2,7 +2,7 @@ /* umax-scanner.h: scanner-definiton header-file for UMAX scanner driver. - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-scsidef.h b/backend/umax-scsidef.h index e7c4048bc..de1d0d23e 100644 --- a/backend/umax-scsidef.h +++ b/backend/umax-scsidef.h @@ -3,7 +3,7 @@ /* umax-scsidef.h: scsi-definiton header file for UMAX scanner driver. Copyright (C) 1996-1997 Michael K. Johnson - Copyright (C) 1997-2001 Oliver Rauch + Copyright (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-uc1200s.c b/backend/umax-uc1200s.c index 1358ace73..97e54164f 100644 --- a/backend/umax-uc1200s.c +++ b/backend/umax-uc1200s.c @@ -3,7 +3,7 @@ /* umax-uc1200s.c: inquiry for UMAX scanner uc1200s - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-uc1200se.c b/backend/umax-uc1200se.c index b28c0df6a..defe65a65 100644 --- a/backend/umax-uc1200se.c +++ b/backend/umax-uc1200se.c @@ -3,7 +3,7 @@ /* umax-uc1200se.c: inquiry for UMAX scanner uc1200se - (C) 1998-2001 Oliver Rauch + (C) 1998-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-uc1260.c b/backend/umax-uc1260.c index bb1e0492a..7743cd4a2 100644 --- a/backend/umax-uc1260.c +++ b/backend/umax-uc1260.c @@ -2,7 +2,7 @@ /* umax-uc1260.c: inquiry for UMAX scanner uc1260 - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-uc630.c b/backend/umax-uc630.c index 6d36d6c37..26c68317b 100644 --- a/backend/umax-uc630.c +++ b/backend/umax-uc630.c @@ -2,7 +2,7 @@ /* umax-uc630.c: inquiry for UMAX scanner uc630 - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-uc840.c b/backend/umax-uc840.c index 8cc79004c..8f430feab 100644 --- a/backend/umax-uc840.c +++ b/backend/umax-uc840.c @@ -2,7 +2,7 @@ /* umax-uc840.c: inquiry for UMAX scanner uc840 - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-ug630.c b/backend/umax-ug630.c index a7e0716d4..0a584b2d5 100644 --- a/backend/umax-ug630.c +++ b/backend/umax-ug630.c @@ -2,7 +2,7 @@ /* umax-ug630.c: inquiry for UMAX scanner ug630 - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/backend/umax-ug80.c b/backend/umax-ug80.c index 92afc0d29..b9d1d4247 100644 --- a/backend/umax-ug80.c +++ b/backend/umax-ug80.c @@ -2,7 +2,7 @@ /* umax-ug80.c: inquiry for UMAX scanner ug80 - (C) 1998-2001 Oliver Rauch + (C) 1998-2002 Oliver Rauch Thanks to Andreas Hofmeister for his help! diff --git a/backend/umax-usb.c b/backend/umax-usb.c new file mode 100644 index 000000000..f737d70b8 --- /dev/null +++ b/backend/umax-usb.c @@ -0,0 +1,327 @@ +/* ---------------------------------------------------------------------- */ + +/* sane - Scanner Access Now Easy. + + umax-usb.c + + (C) 2001-2002 Frank Zago + + 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 UMAX USB flatbed scanners. */ + + +/* ---------------------------------------------------------------------- */ + +#include "../include/sane/sanei_usb.h" + +#include "sane/sanei_pv8630.h" + +/* USB specific parts */ + +/* Apparently this will recover from some errors. */ +static void pv8630_mini_init_scanner(int fd) +{ + DBG(DBG_info, "mini_init_scanner\n"); + + /* (re-)init the device (?) */ + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04 ); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02 ); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02 ); + + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); +} + +/* Length of the CDB given the SCSI command. The last two are not + correct (vendor reserved). */ +static u_char cdb_sizes[8] = { + 6, 10, 10, 6, 16, 12, 0, 0 +}; +#define CDB_SIZE(opcode) cdb_sizes[(((opcode) >> 5) & 7)] + +/* Sends a CDB to the scanner. Also sends the parameters and receives + * the data, if necessary. When this function returns with a + * SANE_STATUS_GOOD, the SCSI command has been completed. + * + * Note: I don't know about deferred commands. + */ +static SANE_Status sanei_umaxusb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) +{ + unsigned char result; + size_t cmd_size = CDB_SIZE (*(char *) src); + size_t param_size = src_size - cmd_size; + char * param_ptr = ((char *) src) + cmd_size; + size_t tmp_len; + + DBG(DBG_info, "Sending SCSI cmd 0x%02x cdb len %d, param len %d, result len %d\n", ((unsigned char *)src)[0], cmd_size, param_size, dst_size? *dst_size:0); + + /* This looks like some kinf of pre-initialization. */ + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); + + /* Send the CDB and check it's been received OK. */ + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x16); + sanei_pv8630_flush_buffer(fd); + sanei_pv8630_prep_bulkwrite(fd, cmd_size); + + tmp_len = cmd_size; + sanei_pv8630_bulkwrite(fd, src, &tmp_len); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); + + sanei_pv8630_flush_buffer(fd); + sanei_pv8630_prep_bulkread(fd, 1); + + result = 0xA5; /* to be sure */ + tmp_len = 1; + sanei_pv8630_bulkread(fd, &result, &tmp_len); + if (result != 0) { + DBG(DBG_info, "error in sanei_pv8630_bulkread (got %02x)\n", result); + if (result == 8) { + pv8630_mini_init_scanner(fd); + } + return(SANE_STATUS_IO_ERROR); + } + + /* Send the parameters and check they've been received OK. */ + if (param_size) { + sanei_pv8630_flush_buffer(fd); + sanei_pv8630_prep_bulkwrite(fd, param_size); + + tmp_len = param_size; + sanei_pv8630_bulkwrite(fd, param_ptr, &tmp_len); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); + + sanei_pv8630_flush_buffer(fd); + sanei_pv8630_prep_bulkread(fd, 1); + + result = 0xA5; /* to be sure */ + tmp_len = 1; + sanei_pv8630_bulkread(fd, &result, &tmp_len); + if (result != 0) { + DBG(DBG_info, "error in sanei_pv8630_bulkread (got %02x)\n", result); + if (result == 8) { + pv8630_mini_init_scanner(fd); + } + return(SANE_STATUS_IO_ERROR); + } + } + + /* If the SCSI command expect a return, get it. */ + if (dst_size != NULL && *dst_size != 0 && dst != NULL) { + sanei_pv8630_flush_buffer(fd); + sanei_pv8630_prep_bulkread(fd, *dst_size); + sanei_pv8630_bulkread(fd, dst, dst_size); + + DBG(DBG_info, " SCSI cmd returned %d bytes\n", *dst_size); + + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); + + sanei_pv8630_flush_buffer(fd); + sanei_pv8630_prep_bulkread(fd, 1); + + result = 0x5A; /* just to be sure */ + tmp_len = 1; + sanei_pv8630_bulkread(fd, &result, &tmp_len); + if (result != 0) { + DBG(DBG_info, "error in sanei_pv8630_bulkread (got %02x)\n", result); + if (result == 8) { + pv8630_mini_init_scanner(fd); + } + return(SANE_STATUS_IO_ERROR); + } + } + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); + + DBG(DBG_info, " SCSI command successfully executed\n"); + + return(SANE_STATUS_GOOD); +} + +/* Initialize the PowerVision 8630. */ +static SANE_Status pv8630_init_umaxusb_scanner(int fd) +{ + DBG(DBG_info, "Initializing the PV8630\n"); + + /* Init the device */ + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); + + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); + + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); + sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); + + sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); + + sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x16); + + DBG(DBG_info, "PV8630 initialized\n"); + + return(SANE_STATUS_GOOD); +} + + +/* + * SCSI functions for the emulation. + * + * The following functions emulate their sanei_scsi_* counterpart. + * + */ + + +/* + * sanei_umaxusb_req_wait() and sanei_umaxusb_req_enter() + * + * I don't know if it is possible to queue the reads to the + * scanner. So The queing is disabled. The performance does not seems + * to be bad anyway. + */ + +static void *umaxusb_req_buffer; /* keep the buffer ptr as an ID */ + +static SANE_Status sanei_umaxusb_req_enter (int fd, + const void *src, size_t src_size, + void *dst, size_t * dst_size, void **idp) +{ + umaxusb_req_buffer = *idp = dst; + return(sanei_umaxusb_cmd(fd, src, src_size, dst, dst_size)); +} + +static SANE_Status +sanei_umaxusb_req_wait (void *id) +{ + if (id != umaxusb_req_buffer) { + DBG(DBG_info, "sanei_umaxusb_req_wait: AIE, invalid id\n"); + return(SANE_STATUS_IO_ERROR); + } + return(SANE_STATUS_GOOD); +} + +/* Open the device. + */ +static SANE_Status +sanei_umaxusb_open (const char *dev, int *fdp, + SANEI_SCSI_Sense_Handler handler, void *handler_arg) +{ + handler = handler; /* silence gcc */ + handler_arg = handler_arg; /* silence gcc */ + + *fdp = open (dev, O_RDWR | O_EXCL); + if (*fdp == -1) { + SANE_Status status = SANE_STATUS_INVAL; + + if (errno == EACCES) + status = SANE_STATUS_ACCESS_DENIED; + + DBG (1, "sanei_umaxusb_open: open of `%s' failed: %s\n", + dev, strerror (errno)); + return status; + } else { + SANE_Word vendor; + SANE_Word product; + + /* We have openned the device. Check that it is a USB scanner. */ + if (sanei_usb_get_vendor_product (*fdp, &vendor, &product) != SANE_STATUS_GOOD) { + /* This is not a USB scanner, or SANE or the OS doesn't support it. */ + close(*fdp); + *fdp = -1; + return SANE_STATUS_UNSUPPORTED; + } + + /* So it's a scanner. Does this backend support it? + * Only the UMAX 2200 USB is currently supported. */ + if ((vendor != 0x1606) || (product != 0x0230)) { + close(*fdp); + *fdp = -1; + return SANE_STATUS_UNSUPPORTED; + } + + /* It's a good scanner. Initialize it. + * + * Note: pv8630_init_umaxusb_scanner() is for the UMAX + * 2200. Other UMAX scanner might need a different + * initialization routine. */ + + pv8630_init_umaxusb_scanner(*fdp); + } + + return(SANE_STATUS_GOOD); +} + +/* sanei_umaxusb_open_extended() is just a passthrough for sanei_umaxusb_open(). */ +static SANE_Status +sanei_umaxusb_open_extended (const char *dev, int *fdp, + SANEI_SCSI_Sense_Handler handler, void *handler_arg, int *buffersize) +{ + buffersize = buffersize; + return(sanei_umaxusb_open(dev, fdp, handler, handler_arg)); +} + +/* Close the scanner. */ +static void +sanei_umaxusb_close (int fd) +{ + close(fd); +} + + + + diff --git a/backend/umax.c b/backend/umax.c index 6d355d2e6..6cd3fb1c2 100644 --- a/backend/umax.c +++ b/backend/umax.c @@ -4,7 +4,7 @@ umax.c - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This file is part of the SANE package. @@ -49,7 +49,7 @@ /* --------------------------------------------------------------------------------------------------------- */ -#define BUILD 32 +#define BUILD 33 /* --------------------------------------------------------------------------------------------------------- */ @@ -130,20 +130,24 @@ in ADF mode this is done often: #include "sane/sanei_scsi.h" #include "sane/sanei_debug.h" +#ifdef UMAX_ENABLE_USB +# include "sane/sanei_usb.h" +#endif + #include #include #include "umax-scsidef.h" #include "umax-scanner.c" +#ifdef UMAX_ENABLE_USB +# include "umax-usb.c" +#endif + #include "umax.h" #include "sane/sanei_backend.h" #include "sane/sanei_config.h" -#ifdef HAVE_SANEI_IPC -#include "sane/sanei_ipc.h" -#endif - /* ------------------------------------------------------------ SANE DEFINES ------------------------------- */ #ifndef PATH_MAX @@ -200,6 +204,7 @@ static int umax_calibration_bytespp = -1; /* -1=auto */ static int umax_invert_shading_data = -1; /* -1=auto */ static int umax_lamp_control_available = 0; /* 0=disabled */ static int umax_gamma_lsb_padded = -1; /* -1=auto */ +static int umax_connection_type = 1; /* 1=scsi, 2=usb */ /* ------------------------------------------------------------ CALIBRATION MODE --------------------------- */ @@ -1216,6 +1221,136 @@ static unsigned char * umax_get_pixel_line(Umax_Device *dev) } +/* ============================================================ Switches between the SCSI and USB commands = */ + +/* ------------------------------------------------------------ UMAX SCSI CMD ------------------------------ */ + +static SANE_Status umax_scsi_cmd(Umax_Device *dev, const void *src, size_t src_size, void *dst, size_t * dst_size) +{ + switch (dev->connection_type) + { + case SANE_UMAX_SCSI: + return sanei_scsi_cmd(dev->sfd, src, src_size, dst, dst_size); + break; + +#ifdef UMAX_ENABLE_USB + case SANE_UMAX_USB: + return sanei_umaxusb_cmd(dev->sfd, src, src_size, dst, dst_size); + break; +#endif + + default: + return(SANE_STATUS_INVAL); + } +} + +/* ------------------------------------------------------------ UMAX SCSI OPEN EXTENDED -------------------- */ + +static SANE_Status umax_scsi_open_extended(const char *devicename, Umax_Device *dev, + SANEI_SCSI_Sense_Handler handler, void *handler_arg, int *buffersize) +{ + switch (dev->connection_type) + { + case SANE_UMAX_SCSI: + return sanei_scsi_open_extended(devicename, &dev->sfd, handler, handler_arg, buffersize); + break; + +#ifdef UMAX_ENABLE_USB + case SANE_UMAX_USB: + return sanei_umaxusb_open_extended(devicename, &dev->sfd, handler, handler_arg, buffersize); + break; +#endif + + default: + return(SANE_STATUS_INVAL); + } +} + +/* ------------------------------------------------------------ UMAX SCSI OPEN ----------------------------- */ + +static SANE_Status umax_scsi_open(const char *devicename, Umax_Device *dev, + SANEI_SCSI_Sense_Handler handler, void *handler_arg) +{ + switch (dev->connection_type) + { + case SANE_UMAX_SCSI: + return sanei_scsi_open(devicename, &dev->sfd, handler, handler_arg); + break; + +#ifdef UMAX_ENABLE_USB + case SANE_UMAX_USB: + return sanei_umaxusb_open(devicename, &dev->sfd, handler, handler_arg); + break; +#endif + + default: + return(SANE_STATUS_INVAL); + } +} + +/* ------------------------------------------------------------ UMAX SCSI CLOSE ---------------------------- */ + +static void umax_scsi_close(Umax_Device *dev) +{ + switch (dev->connection_type) + { + case SANE_UMAX_SCSI: + sanei_scsi_close(dev->sfd); + dev->sfd=-1; + break; + +#ifdef UMAX_ENABLE_USB + case SANE_UMAX_USB: + sanei_umaxusb_close(dev->sfd); + dev->sfd=-1; + break; +#endif + } +} + +/* ------------------------------------------------------------ UMAX SCSI REQ ENTER ------------------------ */ + +static SANE_Status umax_scsi_req_enter(Umax_Device *dev, const void *src, size_t src_size, + void *dst, size_t * dst_size, void **idp) +{ + switch (dev->connection_type) + { + case SANE_UMAX_SCSI: + return sanei_scsi_req_enter (dev->sfd, src, src_size, dst, dst_size, idp); + break; + +#ifdef UMAX_ENABLE_USB + case SANE_UMAX_USB: + return sanei_umaxusb_req_enter (dev->sfd, src, src_size, dst, dst_size, idp); + break; +#endif + + default: + return(SANE_STATUS_INVAL); + } +} + +/* ------------------------------------------------------------ UMAX SCSI REQ WAIT ------------------------- */ + +static SANE_Status umax_scsi_req_wait(Umax_Device *dev, void *id) +{ + switch (dev->connection_type) + { + case SANE_UMAX_SCSI: + return sanei_scsi_req_wait(id); + break; + +#ifdef UMAX_ENABLE_USB + case SANE_UMAX_USB: + return sanei_umaxusb_req_wait(id); + break; +#endif + + default: + return(SANE_STATUS_INVAL); + } +} + /* ------------------------------------------------------------ UMAX SCSI GET LAMP STATUS ------------------ */ @@ -1226,7 +1361,7 @@ static SANE_Status umax_scsi_get_lamp_status(Umax_Device *dev, int *lamp_on) DBG(DBG_proc, "umax_scsi_get_lamp_status\n"); - status = sanei_scsi_cmd(dev->sfd, get_lamp_status.cmd, get_lamp_status.size, dev->buffer[0], &size); + status = umax_scsi_cmd(dev, get_lamp_status.cmd, get_lamp_status.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_scsi_get_lamp_status: command returned status %s\n", sane_strstatus(status)); @@ -1251,7 +1386,7 @@ static SANE_Status umax_scsi_set_lamp_status(Umax_Device *dev, int lamp_on) DBG(DBG_info, "lamp_status=%d\n", lamp_on); set_lamp_status_lamp_on(set_lamp_status.cmd, lamp_on); - status = sanei_scsi_cmd(dev->sfd, set_lamp_status.cmd, set_lamp_status.size, NULL, NULL); + status = umax_scsi_cmd(dev, set_lamp_status.cmd, set_lamp_status.size, NULL, NULL); if (status) { @@ -1271,8 +1406,8 @@ static SANE_Status umax_set_lamp_status(SANE_Handle handle, int lamp_on) DBG(DBG_proc, "umax_set_lamp_status\n"); - if ( sanei_scsi_open(scanner->device->sane.name, &(scanner->device->sfd), sense_handler, - scanner->device) != SANE_STATUS_GOOD ) + if (umax_scsi_open(scanner->device->sane.name, scanner->device, sense_handler, + scanner->device) != SANE_STATUS_GOOD ) { DBG(DBG_error, "ERROR: umax_set_lamp_status: open of %s failed:\n", scanner->device->sane.name); return SANE_STATUS_INVAL; @@ -1285,8 +1420,7 @@ static SANE_Status umax_set_lamp_status(SANE_Handle handle, int lamp_on) status = umax_scsi_set_lamp_status(scanner->device, lamp_on); } - sanei_scsi_close(scanner->device->sfd); - scanner->device->sfd = -1; + umax_scsi_close(scanner->device); return status; } @@ -1301,7 +1435,7 @@ static SANE_Status umax_get_data_buffer_status(Umax_Device *dev) DBG(DBG_proc, "get_data_buffer_status\n"); set_GDBS_wait(get_data_buffer_status.cmd,1); /* wait for scanned data */ - status = sanei_scsi_cmd(dev->sfd, get_data_buffer_status.cmd, get_data_buffer_status.size, NULL, NULL); + status = umax_scsi_cmd(dev, get_data_buffer_status.cmd, get_data_buffer_status.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_get_data_buffer_status: command returned status %s\n", sane_strstatus(status)); @@ -1322,7 +1456,7 @@ static void umax_do_request_sense(Umax_Device *dev) DBG(DBG_proc, "do_request_sense\n"); set_RS_allocation_length(request_sense.cmd, rs_return_block_size); - status = sanei_scsi_cmd(dev->sfd, request_sense.cmd, request_sense.size, dev->buffer[0], &size); + status = umax_scsi_cmd(dev, request_sense.cmd, request_sense.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_request_sense: command returned status %s\n", sane_strstatus(status)); @@ -1348,7 +1482,7 @@ static SANE_Status umax_wait_scanner(Umax_Device *dev) return -1; } /* test unit ready */ - status = sanei_scsi_cmd(dev->sfd, test_unit_ready.cmd, test_unit_ready.size, NULL, NULL); + status = umax_scsi_cmd(dev, test_unit_ready.cmd, test_unit_ready.size, NULL, NULL); cnt++; if (status) @@ -1380,7 +1514,7 @@ static int umax_grab_scanner(Umax_Device *dev) DBG(DBG_proc, "grab_scanner\n"); WAIT_SCANNER; /* wait for scanner ready */ - status = sanei_scsi_cmd(dev->sfd, reserve_unit.cmd, reserve_unit.size, NULL, NULL); + status = umax_scsi_cmd(dev, reserve_unit.cmd, reserve_unit.size, NULL, NULL); if (status) { @@ -1407,7 +1541,7 @@ static int umax_reposition_scanner(Umax_Device *dev) ( (dev->inquiry_fb_length * dev->y_coordinate_base) ); DBG(DBG_info2, "trying to reposition scanner ...\n"); - status = sanei_scsi_cmd(dev->sfd, object_position.cmd, object_position.size, NULL, NULL); + status = umax_scsi_cmd(dev, object_position.cmd, object_position.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_reposition_scanner: command returned status %s\n", sane_strstatus(status)); @@ -1442,7 +1576,7 @@ static int umax_give_scanner(Umax_Device *dev) int status; DBG(DBG_info2, "trying to release scanner ...\n"); - status = sanei_scsi_cmd(dev->sfd, release_unit.cmd, release_unit.size, NULL, NULL); + status = umax_scsi_cmd(dev, release_unit.cmd, release_unit.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_give_scanner: command returned status %s\n", sane_strstatus(status)); @@ -1501,7 +1635,7 @@ static void umax_send_gamma_data(Umax_Device *dev, void *gamma_data, int color) memcpy(dest, data, 1024); /* copy data */ set_S_xfer_length(dev->buffer[0], 1026); /* set length */ - status = sanei_scsi_cmd(dev->sfd, dev->buffer[0], send.size + 1026, NULL, NULL); + status = umax_scsi_cmd(dev, dev->buffer[0], send.size + 1026, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=0, one color): command returned status %s\n", sane_strstatus(status)); @@ -1527,7 +1661,7 @@ static void umax_send_gamma_data(Umax_Device *dev, void *gamma_data, int color) memcpy(dest, data, 1024); /* copy blue data */ set_S_xfer_length(dev->buffer[0], 3076); /* set length */ - status = sanei_scsi_cmd(dev->sfd, dev->buffer[0], send.size + 3076, NULL, NULL); + status = umax_scsi_cmd(dev, dev->buffer[0], send.size + 3076, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=0, RGB): command returned status %s\n", sane_strstatus(status)); @@ -1550,7 +1684,7 @@ static void umax_send_gamma_data(Umax_Device *dev, void *gamma_data, int color) memcpy(dest, data, 256); /* copy data */ set_S_xfer_length(dev->buffer[0], 258); /* set length */ - status = sanei_scsi_cmd(dev->sfd, dev->buffer[0], send.size + 258, NULL, NULL); + status = umax_scsi_cmd(dev, dev->buffer[0], send.size + 258, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=1): command returned status %s\n", sane_strstatus(status)); @@ -1615,7 +1749,7 @@ static void umax_send_gamma_data(Umax_Device *dev, void *gamma_data, int color) set_S_xfer_length(dev->buffer[0], color*length+gamma_DCF2.size); /* set length */ memcpy(dest, data, color*length); /* copy data */ - status = sanei_scsi_cmd(dev->sfd, dev->buffer[0], send.size+gamma_DCF2.size + length * color, NULL, NULL); + status = umax_scsi_cmd(dev, dev->buffer[0], send.size+gamma_DCF2.size + length * color, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=2): command returned status %s\n", sane_strstatus(status)); @@ -1648,7 +1782,7 @@ static void umax_send_data(Umax_Device *dev, void *data, int size, int datatype) dest=dev->buffer[0] + send.size; memcpy(dest, data, size); /* copy data */ - status = sanei_scsi_cmd(dev->sfd, dev->buffer[0], send.size + size, NULL, NULL); + status = umax_scsi_cmd(dev, dev->buffer[0], send.size + size, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_data: command returned status %s\n", sane_strstatus(status)); @@ -1691,7 +1825,7 @@ static void umax_send_gain_data(Umax_Device *dev, void *data, int size) /* ------------------------------------------------------------ UMAX QUEUE READ IMAGE DATA REQ ------------- */ -static SANE_Status umax_queue_read_image_data_req(Umax_Device *dev, unsigned length, int bufnr) +static SANE_Status umax_queue_read_image_data_req(Umax_Device *dev, unsigned int length, int bufnr) { SANE_Status status; @@ -1700,7 +1834,7 @@ static SANE_Status umax_queue_read_image_data_req(Umax_Device *dev, unsigned len set_R_xfer_length(sread.cmd, length); /* set length */ set_R_datatype_code(sread.cmd, R_datatype_imagedata); /* set datatype */ - status = sanei_scsi_req_enter(dev->sfd, sread.cmd, sread.size, dev->buffer[bufnr], &length, &(dev->queue_id[bufnr])); + status = umax_scsi_req_enter(dev, sread.cmd, sread.size, dev->buffer[bufnr], &length, &(dev->queue_id[bufnr])); if (status) { DBG(DBG_error, "umax_queue_read_image_data_req: command returned status %s\n", sane_strstatus(status)); @@ -1723,7 +1857,7 @@ static int umax_wait_queued_image_data(Umax_Device *dev, int bufnr) DBG(DBG_proc, "umax_wait_queued_image_data for buffer[%d] (id=%p)\n", bufnr, dev->queue_id[bufnr]); - status = sanei_scsi_req_wait(dev->queue_id[bufnr]); + status = umax_scsi_req_wait(dev, dev->queue_id[bufnr]); if (status) { DBG(DBG_error, "umax_wait_queued_image_data: wait returned status %s\n", sane_strstatus(status)); @@ -1744,7 +1878,7 @@ static int umax_read_data(Umax_Device *dev, size_t length, int datatype) set_R_xfer_length(sread.cmd, length); /* set length */ set_R_datatype_code(sread.cmd, datatype); /* set datatype */ - status = sanei_scsi_cmd(dev->sfd, sread.cmd, sread.size, dev->buffer[0], &length); + status = umax_scsi_cmd(dev, sread.cmd, sread.size, dev->buffer[0], &length); if (status) { DBG(DBG_error, "umax_read_data: command returned status %s\n", sane_strstatus(status)); @@ -2039,7 +2173,7 @@ static SANE_Status umax_set_window_param(Umax_Device *dev) set_SW_xferlen(dev->buffer[0], (window_parameter_data_block.size + (window_descriptor_block.size * num_dblocks))); - status = sanei_scsi_cmd(dev->sfd, dev->buffer[0], set_window.size + window_parameter_data_block.size + + status = umax_scsi_cmd(dev, dev->buffer[0], set_window.size + window_parameter_data_block.size + (window_descriptor_block.size * num_dblocks), NULL, NULL); if (status) { @@ -2068,7 +2202,7 @@ static void umax_do_inquiry(Umax_Device *dev) size = 5; set_inquiry_return_size(inquiry.cmd, size); /* first get only 5 bytes to get size of inquiry_return_block */ - status = sanei_scsi_cmd(dev->sfd, inquiry.cmd, inquiry.size, dev->buffer[0], &size); + status = umax_scsi_cmd(dev, inquiry.cmd, inquiry.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_inquiry: command returned status %s\n", sane_strstatus(status)); @@ -2077,7 +2211,7 @@ static void umax_do_inquiry(Umax_Device *dev) size = get_inquiry_additional_length(dev->buffer[0]) + 5; set_inquiry_return_size(inquiry.cmd, size); /* then get inquiry with actual size */ - status = sanei_scsi_cmd(dev->sfd, inquiry.cmd, inquiry.size, dev->buffer[0], &size); + status = umax_scsi_cmd(dev, inquiry.cmd, inquiry.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_inquiry: command returned status %s\n", sane_strstatus(status)); @@ -2126,7 +2260,7 @@ static SANE_Status umax_start_scan(Umax_Device *dev) DBG(DBG_info,"starting scan\n"); - status = sanei_scsi_cmd(dev->sfd, scan.cmd, scan.size + size, NULL, NULL); + status = umax_scsi_cmd(dev, scan.cmd, scan.size + size, NULL, NULL); if (status) { DBG(DBG_error, "umax_start_scan: command returned status %s\n", sane_strstatus(status)); @@ -2392,7 +2526,7 @@ static void umax_do_new_inquiry(Umax_Device *dev, size_t size) /* call in memset(dev->buffer[0], '\0', 256); /* clear buffer */ set_inquiry_return_size(inquiry.cmd, size); - status = sanei_scsi_cmd(dev->sfd, inquiry.cmd, inquiry.size, dev->buffer[0], &size); + status = umax_scsi_cmd(dev, inquiry.cmd, inquiry.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_new_inquiry: command returned status %s\n", sane_strstatus(status)); @@ -3755,11 +3889,7 @@ static int umax_calculate_analog_gamma(double value) /* ------------------------------------------------------------ UMAX OUTPUT IMAGE DATA -------------------- */ -#ifdef HAVE_SANEI_IPC -static void umax_output_image_data(Umax_Device *dev, unsigned int data_to_read, int bufnr) -#else static void umax_output_image_data(Umax_Device *dev, FILE *fp, unsigned int data_to_read, int bufnr) -#endif { if (dev->do_color_ordering == 0) /* pixel ordering */ { @@ -3780,11 +3910,7 @@ static void umax_output_image_data(Umax_Device *dev, FILE *fp, unsigned int data dev->buffer[bufnr][i]=new; } } -#ifdef HAVE_SANEI_IPC - sanei_ipc_write(dev->ipc, dev->buffer[bufnr], 1, data_to_read); -#else fwrite(dev->buffer[bufnr], 1, data_to_read, fp); -#endif } else /* line ordering */ { @@ -3809,11 +3935,7 @@ static void umax_output_image_data(Umax_Device *dev, FILE *fp, unsigned int data pixelsource = umax_get_pixel_line(dev); if (pixelsource != NULL) { -#ifdef HAVE_SANEI_IPC - sanei_ipc_write(dev->ipc, pixelsource, bytes, dev->width_in_pixels * 3); -#else fwrite(pixelsource, bytes, dev->width_in_pixels * 3, fp); -#endif } } } @@ -3822,11 +3944,7 @@ static void umax_output_image_data(Umax_Device *dev, FILE *fp, unsigned int data /* ------------------------------------------------------------ UMAX READER PROCESS ------------------------ */ -#ifdef HAVE_SANEI_IPC -static int umax_reader_process(Umax_Device *dev, unsigned int image_size) -#else static int umax_reader_process(Umax_Device *dev, FILE *fp, unsigned int image_size) -#endif { int status; int bytes = 1; @@ -3922,11 +4040,7 @@ static int umax_reader_process(Umax_Device *dev, FILE *fp, unsigned int image_si } data_to_read = (data_left_to_read < dev->row_bufsize) ? data_left_to_read : dev->row_bufsize; -#ifdef HAVE_SANEI_IPC - umax_output_image_data(dev, data_to_read, bufnr_read); -#else umax_output_image_data(dev, fp, data_to_read, bufnr_read); -#endif data_left_to_read -= data_to_read; DBG(DBG_read, "umax_reader_process: buffer of %d bytes read; %d bytes to go\n", data_to_read, data_left_to_read); @@ -4055,12 +4169,20 @@ static void umax_init(Umax_Device *dev) /* umax_init is called once while { DBG(DBG_proc,"init\n"); - dev->devicename = NULL; - dev->sfd = -1; - dev->pixelbuffer = NULL; + dev->devicename = NULL; + dev->pixelbuffer = NULL; /* config file or predefined settings */ - dev->request_scsi_maxqueue = umax_scsi_maxqueue; + if (dev->connection_type == SANE_UMAX_SCSI) + { + dev->request_scsi_maxqueue = umax_scsi_maxqueue; + } + else /* SANE_UMAX_USB, USB does not support command queueing */ + { + DBG(DBG_info2, "setting request_scsi_maxqueue = 1 for USB connection\n"); + dev->request_scsi_maxqueue = 1; + } + dev->request_preview_lines = umax_preview_lines; dev->request_scan_lines = umax_scan_lines; dev->handle_bad_sense_error = umax_handle_bad_sense_error; @@ -4239,12 +4361,11 @@ static SANE_Status do_cancel(Umax_Scanner *scanner) } } - if (scanner->device->sfd >= 0) + if (scanner->device->sfd != -1) { umax_give_scanner(scanner->device); /* reposition and release scanner */ DBG(DBG_sane_info,"closing scannerdevice filedescriptor\n"); - sanei_scsi_close(scanner->device->sfd); - scanner->device->sfd = -1; + umax_scsi_close(scanner->device); } scanner->device->three_pass_color = 1; /* reset color in color scanning */ @@ -4256,26 +4377,27 @@ static SANE_Status do_cancel(Umax_Scanner *scanner) /* ------------------------------------------------------------ ATTACH SCANNER ----------------------------- */ -static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp) +static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp, int connection_type) { Umax_Device *dev; - int sfd; int i; - DBG(DBG_sane_proc,"attach_scanner: %s\n", devicename); + DBG(DBG_sane_proc,"attach_scanner: %s, connection_type %d\n", devicename, connection_type); - for (dev = first_dev; dev; dev = dev->next) + for (dev = first_dev; dev; dev = dev->next) /* search is scanner already is listed in devicelist */ { - if (strcmp(dev->sane.name, devicename) == 0) + if (strcmp(dev->sane.name, devicename) == 0) /* scanner is already listed */ { if (devp) { - *devp = dev; + *devp = dev; /* return pointer to device */ } return SANE_STATUS_GOOD; } } + /* scanner has not been attached yet */ + dev = malloc( sizeof(*dev) ); if (!dev) { @@ -4283,38 +4405,72 @@ static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp) } memset(dev, '\0', sizeof(Umax_Device)); /* clear structure */ - DBG(DBG_info, "attach_scanner: opening %s\n", devicename); + /* If connection type is not known (==0) then try to open the device as an USB device. */ + /* If it fails, try the SCSI method. */ -#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED - dev->bufsize = 16384; /* 16KB */ +#ifdef UMAX_ENABLE_USB + dev->connection_type = connection_type; /* 0 = unknown, 1=scsi, 2=usb */ - if (sanei_scsi_open_extended(devicename, &sfd, sense_handler, dev, (int *) &dev->bufsize) != 0) + if (dev->connection_type != SANE_UMAX_SCSI) { - DBG(DBG_error, "ERROR: attach_scanner: opening %s failed\n", devicename); - free(dev); - return SANE_STATUS_INVAL; - } + dev->bufsize = 16384; /* 16KB */ + DBG(DBG_info, "attach_scanner: opening usb device %s\n", devicename); - if (dev->bufsize < 4096) /* < 4KB */ - { - DBG(DBG_error, "ERROR: attach_scanner: sanei_scsi_open_extended returned too small scsi buffer\n"); - sanei_scsi_close(sfd); - free(dev); - return SANE_STATUS_NO_MEM; - } + if (sanei_umaxusb_open(devicename, &dev->sfd, sense_handler, dev) == SANE_STATUS_GOOD) + { + dev->connection_type = SANE_UMAX_USB; + } + else /* opening usb device failed */ + { + if (dev->connection_type == SANE_UMAX_USB) /* we know it is not a scsi device: error */ + { + DBG(DBG_error, "ERROR: attach_scanner: opening usb device %s failed\n", devicename); + free(dev); + return SANE_STATUS_INVAL; + } - DBG(DBG_info, "attach_scanner: sanei_scsi_open_extended returned scsi buffer size = %d\n", dev->bufsize); + DBG(DBG_info, "attach_scanner: failed to open %s as usb device\n", devicename); + } + } #else - dev->bufsize = sanei_scsi_max_request_size; - - if (sanei_scsi_open(devicename, &sfd, sense_handler, dev) != 0) - { - DBG(DBG_error, "ERROR: attach_scanner: open failed\n"); - free(dev); - return SANE_STATUS_INVAL; - } + dev->connection_type = SANE_UMAX_SCSI; #endif + if (dev->connection_type != SANE_UMAX_USB) /* not an USB device, then try as SCSI */ + { +#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED + dev->bufsize = 16384; /* 16KB */ + DBG(DBG_info, "attach_scanner: opening scsi device %s\n", devicename); + + if (sanei_scsi_open_extended(devicename, &dev->sfd, sense_handler, dev, (int *) &dev->bufsize) != 0) + { + DBG(DBG_error, "ERROR: attach_scanner: opening scsi device %s failed\n", devicename); + free(dev); + return SANE_STATUS_INVAL; + } + + if (dev->bufsize < 4096) /* < 4KB */ + { + DBG(DBG_error, "ERROR: attach_scanner: sanei_scsi_open_extended returned too small scsi buffer\n"); + umax_scsi_close(dev); + free(dev); + return SANE_STATUS_NO_MEM; + } + + DBG(DBG_info, "attach_scanner: sanei_scsi_open_extended returned scsi buffer size = %d\n", dev->bufsize); +#else + dev->bufsize = sanei_scsi_max_request_size; + + if (sanei_scsi_open(devicename, dev, sense_handler, dev) != 0) + { + DBG(DBG_error, "ERROR: attach_scanner: opening scsi device %s failed\n", devicename); + free(dev); + return SANE_STATUS_INVAL; + } +#endif + dev->connection_type = SANE_UMAX_SCSI; /* set connection type (may have been unknown == 0) */ + } + DBG(DBG_info, "attach_scanner: allocating SCSI buffer[0]\n"); dev->buffer[0] = malloc(dev->bufsize); /* allocate buffer */ @@ -4326,7 +4482,7 @@ static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp) if (!dev->buffer[0]) /* malloc failed */ { DBG(DBG_error, "ERROR: attach scanner: could not allocate buffer[0]\n"); - sanei_scsi_close(sfd); + umax_scsi_close(dev); free(dev); return SANE_STATUS_NO_MEM; } @@ -4337,13 +4493,11 @@ static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp) umax_initialize_values(dev); /* reset values */ dev->devicename = strdup(devicename); - dev->sfd = sfd; if (umax_identify_scanner(dev) != 0) { DBG(DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); - sanei_scsi_close(dev->sfd); - dev->sfd=-1; + umax_scsi_close(dev); free(dev->buffer[0]); free(dev); return SANE_STATUS_INVAL; @@ -4375,8 +4529,7 @@ static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp) DBG(DBG_inquiry,"==================== end of inquiry ====================\n"); DBG(DBG_inquiry,"\n"); - sanei_scsi_close(dev->sfd); - dev->sfd=-1; + umax_scsi_close(dev); dev->sane.name = dev->devicename; dev->sane.vendor = dev->vendor; @@ -4468,14 +4621,9 @@ static RETSIGTYPE reader_process_sigterm_handler(int signal) /* ------------------------------------------------------------ READER PROCESS ----------------------------- */ -#ifdef HAVE_SANEI_IPC -static int reader_process(Umax_Scanner *scanner) /* executed as a child process */ -{ -#else static int reader_process(Umax_Scanner *scanner, int pipe_fd) /* executed as a child process */ { FILE *fp; -#endif int status; unsigned int data_length; struct SIGACTION act; @@ -4516,24 +4664,16 @@ static int reader_process(Umax_Scanner *scanner, int pipe_fd) /* executed data_length = scanner->params.lines * scanner->params.bytes_per_line; -#ifndef HAVE_SANEI_IPC fp = fdopen (pipe_fd, "w"); if (!fp) { return SANE_STATUS_IO_ERROR; - } -#endif + } DBG(DBG_sane_info,"reader_process: starting to READ data\n"); - -#ifdef HAVE_SANEI_IPC - status = umax_reader_process(scanner->device, data_length); - sanei_ipc_detach_as_sender(scanner->device->ipc); -#else status = umax_reader_process(scanner->device, fp, data_length); fclose(fp); -#endif for (i = 1; idevice->request_scsi_maxqueue; i++) { @@ -5381,13 +5521,21 @@ static SANE_Status init_options(Umax_Scanner *scanner) } -/* ------------------------------------------------------------ ATTACH_ONE ---------------------------------- */ +/* ------------------------------------------------------------ ATTACH ONE SCSI ----------------------------- */ - -/* callback function for sanei_config_attach_matching_devices(dev_name, attach_one) */ -static SANE_Status attach_one(const char *name) +/* callback function for sanei_config_attach_matching_devices(dev_name, attach_one_scsi) */ +static SANE_Status attach_one_scsi(const char *name) { - attach_scanner(name, 0); + attach_scanner(name, 0, SANE_UMAX_SCSI); + return SANE_STATUS_GOOD; +} + +/* ------------------------------------------------------------ ATTACH ONE USB ------------------------------ */ + +/* callback function for sanei_usb_attach_matching_devices(dev_name, attach_one_usb) */ +static SANE_Status attach_one_usb(const char *name) +{ + attach_scanner(name, 0, SANE_UMAX_USB); return SANE_STATUS_GOOD; } @@ -5408,7 +5556,7 @@ static SANE_Status umax_test_configure_option(const char *option_str, char *test value = strtol(value_str, &end_ptr, 10); if (end_ptr == value_str || errno) { - DBG(DBG_error, "ERROR: inavlid value \"%s\" for option %s in %s\n", value_str, test_name, UMAX_CONFIG_FILE); + DBG(DBG_error, "ERROR: invalid value \"%s\" for option %s in %s\n", value_str, test_name, UMAX_CONFIG_FILE); } else { @@ -5446,12 +5594,12 @@ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) DBG(DBG_sane_init,"sane_init\n"); DBG(DBG_error,"This is sane-umax version %d.%d build %d\n", V_MAJOR, V_MINOR, BUILD); -#ifdef HAVE_SANEI_IPC - DBG(DBG_error,"compiled with sanei_ipc for inter-process-data-transfer\n"); +#ifdef UMAX_ENABLE_USB + DBG(DBG_error,"compiled with USB support for Astra 2200\n"); #else - DBG(DBG_error,"compiled with pipe for inter-process-data-transfer\n"); + DBG(DBG_error,"no USB support for Astra 2200\n"); #endif - DBG(DBG_error,"(C) 1997-2001 by Oliver Rauch\n"); + DBG(DBG_error,"(C) 1997-2002 by Oliver Rauch\n"); DBG(DBG_error,"EMAIL: Oliver.Rauch@rauch-domain.de\n"); if (version_code) @@ -5461,11 +5609,19 @@ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) frontend_authorize_callback = authorize; /* store frontend authorize callback */ +#ifdef UMAX_ENABLE_USB + sanei_usb_init(); +#endif + fp = sanei_config_open(UMAX_CONFIG_FILE); if (!fp) { - attach_scanner("/dev/scanner", 0); /* no config-file: /dev/scanner */ - return SANE_STATUS_GOOD; + /* no config-file: try /dev/scanner and /dev/usbscanner. */ + attach_scanner("/dev/scanner", 0, SANE_UMAX_SCSI); +#ifdef UMAX_ENABLE_USB + attach_scanner("/dev/usbscanner", 0, SANE_UMAX_USB); +#endif + return SANE_STATUS_GOOD; } DBG(DBG_info, "reading configure file %s\n", UMAX_CONFIG_FILE); @@ -5492,28 +5648,44 @@ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) else if (umax_test_configure_option(option_str, "slow-speed", &umax_slow, -1, 1)); else if (umax_test_configure_option(option_str, "care-about-smearing", &umax_smear, -1, 1)); else if (umax_test_configure_option(option_str, "calibration-full-ccd", &umax_calibration_area, -1, 1)); - else if (umax_test_configure_option(option_str, "calibration-width-offset", &umax_calibration_width_offset, -1, 65535)); + else if (umax_test_configure_option(option_str, "calibration-width-offset", &umax_calibration_width_offset, -99999, 65535)); else if (umax_test_configure_option(option_str, "calibration-bytes-pixel", &umax_calibration_bytespp, -1, 2)); else if (umax_test_configure_option(option_str, "invert-shading-data", &umax_invert_shading_data, -1, 1)); else if (umax_test_configure_option(option_str, "lamp-control-available", &umax_lamp_control_available, 0, 1)); else if (umax_test_configure_option(option_str, "gamma-lsb-padded", &umax_gamma_lsb_padded, -1, 1)); + else if (umax_test_configure_option(option_str, "connection-type", &umax_connection_type, 1, 2)); else { DBG(DBG_error,"ERROR: unknown option \"%s\" in %s\n", option_str, UMAX_CONFIG_FILE); } continue; } + else if (strncmp(config_line, "scsi", 4) == 0) + { + DBG(DBG_info,"sanei_config_attach_matching_devices(%s)\n", config_line); + sanei_config_attach_matching_devices(config_line, attach_one_scsi); + continue; + } + else if (strncmp(config_line, "usb", 3) == 0) + { +#ifdef UMAX_ENABLE_USB + DBG(DBG_info,"sanei_usb_attach_matching_devices(%s)\n", config_line); + sanei_usb_attach_matching_devices(config_line, attach_one_usb); +#else + DBG(DBG_info,"USB not supported, ignoring config line: %s\n", config_line); +#endif + continue; + } - len = strlen (config_line); + len = strlen(config_line); if (!len) /* ignore empty lines */ { continue; } - DBG(DBG_info,"attach_matching_devices(%s)\n", config_line); - /* ok, theis should be one or more devices: try to attach it/them */ - sanei_config_attach_matching_devices(config_line, attach_one); + /* umax_connection_type is set by umax.conf: 1=scsi, 2=usb */ + attach_scanner(config_line, 0, umax_connection_type); /* try to open as devicename */ } DBG(DBG_info, "finished reading configure file\n"); @@ -5595,7 +5767,7 @@ SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle *handle) DBG(DBG_sane_init,"sane_open\n"); - if (devicename[0]) /* search for devicename */ + if (devicename[0]) /* search for devicename */ { DBG(DBG_sane_info,"sane_open: devicename=%s\n", devicename); @@ -5603,13 +5775,13 @@ SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle *handle) { if (strcmp(dev->sane.name, devicename) == 0) { - break; + break; /* device found, exit for loop */ } } - if (!dev) + if (!dev) /* no device found */ { - status = attach_scanner(devicename, &dev); + status = attach_scanner(devicename, &dev, 0 /* connection-type not known */); /* try to open devicename and set dev */ if (status != SANE_STATUS_GOOD) { return status; @@ -5622,7 +5794,7 @@ SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle *handle) dev = first_dev; /* empty devicename -> use first device */ } - if (!dev) + if (!dev) /* no device found */ { return SANE_STATUS_INVAL; } @@ -5635,8 +5807,7 @@ SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle *handle) memset(scanner, 0, sizeof (*scanner)); - scanner->device = dev; - scanner->device->sfd = -1; + scanner->device = dev; if (scanner->device->inquiry_GIB & 32) { @@ -6260,7 +6431,7 @@ SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action } scanner->val[option].s = (SANE_Char *) strdup(val); /* update string for umax_set_max_geometry */ - DBG(DBG_info,"sane_control_option: set SOURCE = %s\n", val); + DBG(DBG_info,"sane_control_option: set SOURCE = %s\n", (SANE_Char *) val); umax_set_max_geometry(scanner); if (info) @@ -6677,15 +6848,13 @@ SANE_Status sane_start(SANE_Handle handle) const char *scan_source; int pause; int status; -#ifndef HAVE_SANEI_IPC int fds[2]; -#endif DBG(DBG_sane_init,"sane_start\n"); mode = scanner->val[OPT_MODE].s; - if (scanner->device->sfd < 0) /* first call, don`t run this routine again on multi frame or multi image scan */ + if (scanner->device->sfd == -1) /* first call, don`t run this routine again on multi frame or multi image scan */ { umax_initialize_values(scanner->device); /* reset values */ @@ -6703,8 +6872,7 @@ SANE_Status sane_start(SANE_Handle handle) else { DBG(DBG_error,"ERROR: Transparency Adapter not available\n"); - sanei_scsi_close(scanner->device->sfd); - scanner->device->sfd=-1; + umax_scsi_close(scanner->device); return SANE_STATUS_INVAL; } } @@ -6721,8 +6889,7 @@ SANE_Status sane_start(SANE_Handle handle) else { DBG(DBG_error,"ERROR: Automatic Document Feeder not available\n"); - sanei_scsi_close(scanner->device->sfd); - scanner->device->sfd=-1; + umax_scsi_close(scanner->device); return SANE_STATUS_INVAL; } } @@ -7076,7 +7243,7 @@ SANE_Status sane_start(SANE_Handle handle) scsi_bufsize = scanner->device->scsi_buffer_size_max; } - if (sanei_scsi_open_extended(scanner->device->sane.name, &(scanner->device->sfd), sense_handler, + if (umax_scsi_open_extended(scanner->device->sane.name, scanner->device, sense_handler, scanner->device, (int *) &scsi_bufsize) != 0) { DBG(DBG_error, "ERROR: sane_start: open failed\n"); @@ -7086,12 +7253,12 @@ SANE_Status sane_start(SANE_Handle handle) if (scsi_bufsize < scanner->device->scsi_buffer_size_min) /* minimum size must be available */ { - DBG(DBG_error, "ERROR: sane_start: sanei_scsi_open_extended returned too small scsi buffer\n"); - sanei_scsi_close((scanner->device->sfd)); + DBG(DBG_error, "ERROR: sane_start: umax_scsi_open_extended returned too small scsi buffer\n"); + umax_scsi_close((scanner->device)); scanner->scanning = SANE_FALSE; return SANE_STATUS_NO_MEM; } - DBG(DBG_info, "sane_start: sanei_scsi_open_extended returned scsi buffer size = %d\n", scsi_bufsize); + DBG(DBG_info, "sane_start: umax_scsi_open_extended returned scsi buffer size = %d\n", scsi_bufsize); if (scsi_bufsize < scanner->device->width_in_pixels) /* print warning when buffer is smaller than one scanline */ { @@ -7116,7 +7283,7 @@ SANE_Status sane_start(SANE_Handle handle) if (!scanner->device->buffer[0]) /* malloc failed */ { DBG(DBG_error, "ERROR: sane_start: could not allocate buffer[0]\n"); - sanei_scsi_close(scanner->device->sfd); + umax_scsi_close(scanner->device); scanner->device->bufsize = 0; scanner->scanning = SANE_FALSE; return SANE_STATUS_NO_MEM; @@ -7124,7 +7291,7 @@ SANE_Status sane_start(SANE_Handle handle) } } #else - if ( sanei_scsi_open(scanner->device->sane.name, &(scanner->device->sfd), sense_handler, + if ( umax_scsi_open(scanner->device->sane.name, scanner->device, sense_handler, scanner->device) != SANE_STATUS_GOOD ) { scanner->scanning = SANE_FALSE; @@ -7139,8 +7306,7 @@ SANE_Status sane_start(SANE_Handle handle) /* grab scanner */ if (umax_grab_scanner(scanner->device)) { - sanei_scsi_close(scanner->device->sfd); - scanner->device->sfd=-1; + umax_scsi_close(scanner->device); scanner->scanning = SANE_FALSE; DBG(DBG_warning,"WARNING: unable to reserve scanner: device busy\n"); return SANE_STATUS_DEVICE_BUSY; @@ -7312,19 +7478,12 @@ SANE_Status sane_start(SANE_Handle handle) } -#ifdef HAVE_SANEI_IPC - if (sanei_ipc_create(&scanner->device->ipc)) - { - DBG(DBG_error,"ERROR: could not create ipc\n"); -#else if (pipe(fds) < 0) { DBG(DBG_error,"ERROR: could not create pipe\n"); -#endif scanner->scanning = SANE_FALSE; umax_give_scanner(scanner->device); /* reposition and release scanner */ - sanei_scsi_close(scanner->device->sfd); - scanner->device->sfd=-1; + umax_scsi_close(scanner->device); return SANE_STATUS_IO_ERROR; } @@ -7334,11 +7493,7 @@ SANE_Status sane_start(SANE_Handle handle) sigset_t ignore_set; struct SIGACTION act; -#ifdef HAVE_SANEI_IPC - sanei_ipc_attach_as_sender(scanner->device->ipc); -#else close(fds[0]); -#endif sigfillset(&ignore_set); sigdelset(&ignore_set, SIGTERM); @@ -7347,19 +7502,11 @@ SANE_Status sane_start(SANE_Handle handle) memset(&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); -#ifdef HAVE_SANEI_IPC - _exit(reader_process(scanner)); /* don't use exit() since that would run the atexit() handlers */ -#else _exit(reader_process(scanner, fds[1])); /* don't use exit() since that would run the atexit() handlers */ -#endif } -#ifdef HAVE_SANEI_IPC - sanei_ipc_attach_as_receiver(scanner->device->ipc); -#else close(fds[1]); scanner->pipe = fds[0]; -#endif return SANE_STATUS_GOOD; } @@ -7375,11 +7522,7 @@ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE *len = 0; -#ifdef HAVE_SANEI_IPC - nread = sanei_ipc_read(scanner->device->ipc, buf, max_len); -#else nread = read(scanner->pipe, buf, max_len); -#endif DBG(DBG_sane_info, "sane_read: read %ld bytes\n", (long) nread); @@ -7413,21 +7556,15 @@ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE do_cancel(scanner); } -#ifdef HAVE_SANEI_IPC - sanei_ipc_detach_as_receiver(scanner->device->ipc); - sanei_ipc_destroy(&scanner->device->ipc); - return SANE_STATUS_EOF; -#else - DBG(DBG_sane_proc,"closing pipe\n"); + DBG(DBG_sane_proc,"closing pipe\n"); - if (scanner->pipe >= 0) - { - close(scanner->pipe); - scanner->pipe = -1; - } + if (scanner->pipe >= 0) + { + close(scanner->pipe); + scanner->pipe = -1; + } - return SANE_STATUS_EOF; -#endif + return SANE_STATUS_EOF; } return SANE_STATUS_GOOD; @@ -7461,15 +7598,11 @@ SANE_Status sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking) if (!scanner->scanning) { return SANE_STATUS_INVAL; } -#ifdef HAVE_SANEI_IPC - return sanei_ipc_set_io_mode(scanner->device->ipc, non_blocking); -#else if (fcntl(scanner->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; -#endif } @@ -7487,11 +7620,8 @@ SANE_Status sane_get_select_fd(SANE_Handle handle, SANE_Int *fd) return SANE_STATUS_INVAL; } -#ifdef HAVE_SANEI_IPC - *fd = scanner->device->ipc->fds[0]; -#else *fd = scanner->pipe; -#endif + return SANE_STATUS_GOOD; } diff --git a/backend/umax.conf b/backend/umax.conf index 1be943797..fb1846d70 100644 --- a/backend/umax.conf +++ b/backend/umax.conf @@ -1,16 +1,84 @@ # # Options for the umax backend +# + +# define scsi queueing depth #option scsi-maxqueue 2 + +# define scsi buffer size in bytes #option scsi-buffer-size-min 65536 #option scsi-buffer-size-max 262144 + +# define scan lines that shall be read in one block #option scan-lines 100 #option preview-lines 20 + +# define how to handle bad sense codes +# 0 = handle as device busy +# 1 = handle as ok +# 2 = handle as i/o error +# 3 = ignore bad error code - continue sense handler, #option handle-bad-sense-error 0 + +# define if a request sense command shall be executed #option execute-request-sense 0 + +# define if the preview bit shall be set when scanning in rgb mode #option force-preview-bit-rgb 0 + +# define if slow speed flag shall be set +# BE CAREFUL WITH THIS OPTION, IT MAY DESTROY YOUR SCANNER WHEN SET FALSE +# -1 = automatically set by driver - if known +# 0 = disabled +# 1 = enabled +#option slow-speed 0 + +# define if care-about-smeraring flag shall be set +# BE CAREFUL WITH THIS OPTION, IT MAY DESTROY YOUR SCANNER WHEN SET FALSE +# -1 = automatically set by driver - if known +# 0 = disabled +# 1 = enabled +#option care-about-smearing 0 + +# define if the calibration shall be done for selected scanarea or for each ccd pixel +# -1 = automatically set by driver - if known +# 0 = disabled +# 1 = enabled +#option calibration-full-ccd 1 + +# define if an offset of the calculate calibration with has to be used +# -99999 = auto +#option calibration-width-offset -99999 + +# define the number of pixels that is used for calibration +# -1 = disabled +# 0 = not set +# 1 = 1 byte/pixel, +# 2 = 2 bytes/pixel +#option calibration-bytes-pixel -1 + +# define if shading data shall be inverted befor sending it back to the scanner +# -1 = automatically set by driver - if known +# 0 = disabled +# 1 = enabled +#option invert-shading-data + +# define if the scanner supports lamp control commands +# 0 = automatically set by driver - if known +# 1 = enabled #option lamp-control-available 0 + +# define how 16 bit gamma data is padded +# -1 = automatically set by driver - if known +# 0 = gamma data is msb padded +# 1 = gamma data is lsb padded #option gamma-lsb-padded 0 -# + +# define connection type of following devices +# 1 = scsi +# 2 = usb +#option connection-type 1 + # linux device identification: #scsi vendor model type bus channel id lun scsi UMAX * Scanner @@ -25,7 +93,15 @@ scsi KYE ColorPage-HR5 scsi EPSON Perfection600 scsi ESCORT "Galleria 600S" -# -# device list for non-linux-systems: +# Umax Astra 2200 via USB: +# usb vendor product +usb 0x1606 0x0230 + +# scsi device list +option connection-type 1 /dev/scanner +# usb device list +option connection-type 2 +/dev/usbscanner + diff --git a/backend/umax.desc b/backend/umax.desc index e052d494c..9b7c502fd 100644 --- a/backend/umax.desc +++ b/backend/umax.desc @@ -22,18 +22,18 @@ :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com/" :url "http://support.umax.com/" -:url "http://www.umax.de/" :url "http://www.umax.com.tw/" :url "http://www.umaxweb.com.tw/" :url "http://support.umax.co.uk/" +:url "http://www.umax.de/en" :model "parallel scanners" ; name models for above-specified mfg. :interface "Parport" :comment "Not supported - see backend umax_pp" :model "USB scanners" :interface "USB" -:comment "Not supported - see backend umax1220u" +:comment "All but Astra2200/MX3 not supported - see backend umax1220u" :model "firewire scanners" -:interface "Firewire" +:interface "IEEE-1394" :comment "not tested" :model "Vista S6" :interface "SCSI" @@ -77,6 +77,9 @@ :model "Astra 2200 (SU)" :interface "SCSI" :comment "OK" +:model "Astra 2200 (SU)" +:interface "USB" +:comment "OK" :model "Astra 2400S" :interface "SCSI" :comment "OK" @@ -89,6 +92,9 @@ :model "Astra MX3" :interface "SCSI" :comment "OK" +:model "Astra MX3" +:interface "USB" +:comment "OK" :model "Mirage D-16L" :interface "SCSI" :comment "OK" @@ -117,7 +123,7 @@ :interface "SCSI" :comment "not tested" :model "PowerLook 1100" -:interface "IEE-1394" +:interface "IEEE-1394" :comment "Not tested" :model "PowerLook 2000" :interface "SCSI" diff --git a/backend/umax.h b/backend/umax.h index b6b48d848..3e86a1e63 100644 --- a/backend/umax.h +++ b/backend/umax.h @@ -2,7 +2,7 @@ /* umax.h - headerfile for SANE-backend for umax scanners - (C) 1997-2001 Oliver Rauch + (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -50,21 +50,14 @@ #include "sys/types.h" -#ifdef HAVE_SANEI_IPC -# include "sane/sanei_ipc.h" -#endif - - /* --------------------------------------------------------------------------------------------------------- */ /* COMPILER OPTIONS: */ - +#define UMAX_ENABLE_USB #define UMAX_HIDE_UNUSED + /* #define SANE_UMAX_DEBUG_S12 */ -/* #define PREVIEW_FIX_ON */ - /* #define UMAX_CALIBRATION_MODE_SELECTABLE */ - /* --------------------------------------------------------------------------------------------------------- */ @@ -191,13 +184,19 @@ typedef union /* LIST OF AVAILABLE SCANNERS, THE VALUES LISTED HERE ARE THE SAME FOR DIFFERENT APPLICATIONS THAT USE THE SAME DEVICE */ - + /* Umax_Device contains values relevant for the device that are not intersting for the sane interface */ typedef struct Umax_Device { struct Umax_Device *next; SANE_Device sane; + + int connection_type; +#define SANE_UMAX_UNKNOWN 0 +#define SANE_UMAX_SCSI 1 +#define SANE_UMAX_USB 2 + SANE_Range x_dpi_range; SANE_Range y_dpi_range; SANE_Range x_range; @@ -452,10 +451,6 @@ typedef struct Umax_Device int pause_for_moving; /* pause for moving scanhead over full scanarea in ms */ int lamp_control_available; /* is set when scanner supportes lamp control */ int gamma_lsb_padded; /* 16 bit gamma data is padded to lsb */ - -#ifdef HAVE_SANEI_IPC - sanei_ipc *ipc; -#endif } Umax_Device; @@ -486,9 +481,7 @@ typedef struct Umax_Scanner SANE_Parameters params; pid_t reader_pid; -#ifndef HAVE_SANEI_IPC int pipe; -#endif } Umax_Scanner;