Hi all,
I've done the integration of the umax USB backend. I've tried to be as
less intrusive as possible. I don't expect to do more changes,
unless someone objects to the current code.
In the umax backend:
Most of the changes touching the SCSI code are the umax_scsi_* function
that replace the sanei_scsi_*. The code has been tested on the USB scanner
only. The SCSI part may have been broken (I can't check that).
In the sanei_usb code:
Added a sanei_usb_control_msg() function to send/received control
messages.
On linux, if you want to try it with a usb scanner, apply that patch to
the usb scanner driver before (or else bad things will happen):
http://marc.theaimsgroup.com/?l=linux-usb-devel&m=100645814202605&q=p3
Regards,
Frank.
diff -P -r -u sane-backends-1.0.6.orig/backend/dodebug
sane-backends-1.0.6/backend/dodebug
--- sane-backends-1.0.6.orig/backend/dodebug Wed Dec 31 18:00:00 1969
+++ sane-backends-1.0.6/backend/dodebug Wed Nov 21 16:26:23 2001
@@ -0,0 +1,4 @@
+setenv SANE_DEBUG_DLL 128
+setenv SANE_DEBUG_UMAX 128
+setenv SANE_DEBUG_SANEI_SCSI 128
+setenv SANE_DEBUG_SANEI_USB 128
diff -P -r -u sane-backends-1.0.6.orig/backend/umax-usb.c
sane-backends-1.0.6/backend/umax-usb.c
--- sane-backends-1.0.6.orig/backend/umax-usb.c Wed Dec 31 18:00:00 1969
+++ sane-backends-1.0.6/backend/umax-usb.c Thu Nov 22 22:31:37 2001
@@ -0,0 +1,425 @@
+/* ---------------------------------------------------------------------- */
+
+/* sane - Scanner Access Now Easy.
+
+ umax.c
+
+ (C) 2001 Frank Zago
+ (C) 2000 Adrian Perez Jorge (PV8630 code)
+
+ 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. */
+
+
+/* ---------------------------------------------------------------------- */
+
+/* USB specific parts */
+
+/*
+ * PV8630
+ *
+ * The following drives the PV 8630. The PowerVision 8630 is a USB to
+ * parallel converter.
+ * The defines comes from the sane 1220U backend.
+ * Most function do not check for errors because I don't know how to recover from
+these.
+ */
+
+/* request */
+#define PV8630_REQ_READBYTE 0x00
+#define PV8630_REQ_WRITEBYTE 0x01
+#define PV8630_REQ_EPPBULKREAD 0x02
+#define PV8630_REQ_EPPBULKWRITE 0x03
+#define PV8630_REQ_FLUSHBUFFER 0x04
+#define PV8630_REQ_ENABLEINTERRUPT 0x05
+#define PV8630_REQ_DISABLEINTERRUPT 0x06
+#define PV8630_REQ_READWORD 0x08
+#define PV8630_REQ_WRITEWORD 0x09
+
+/* index */
+#define PV8630_RDATA 0x00
+#define PV8630_REPPADDRESS 0x01
+#define PV8630_UNKNOWN 0x02
+#define PV8630_RMODE 0x03
+#define PV8630_RSTATUS 0x04
+
+/* Write one control byte */
+static void pv8630_write_byte(int fd, int value, int index)
+{
+ if (sanei_usb_control_msg(fd, 0x40, PV8630_REQ_WRITEBYTE, value, index, 0,
+NULL) != SANE_STATUS_GOOD) {
+ DBG(DBG_error, "usb_control_msg PV8630_REQ_WRITEBYTE error\n");
+ }
+}
+
+/* Read one control byte */
+static void pv8630_read_byte(int fd, unsigned char *data, int index)
+{
+ if (sanei_usb_control_msg(fd, 0xc0, PV8630_REQ_READBYTE, 0, index, 1, data) !=
+SANE_STATUS_GOOD) {
+ DBG(DBG_error, "usb_control_msg PV8630_REQ_READBYTE error\n");
+ }
+}
+
+/* Flush the buffer. */
+static void pv8630_flush_buffer(int fd)
+{
+ if (sanei_usb_control_msg(fd, 0x40, PV8630_REQ_FLUSHBUFFER, 0, 0, 0, NULL) !=
+SANE_STATUS_GOOD) {
+ DBG(DBG_error, "usb_control_msg PV8630_REQ_FLUSHBUFFER error\n");
+ }
+}
+
+/* Prepare a bulk write. len is the size of the data going to be
+ * written by pv8630_bulkwrite(). */
+static void pv8630_prep_bulkwrite(int fd, size_t len)
+{
+ if (sanei_usb_control_msg(fd, 0x40, PV8630_REQ_EPPBULKWRITE, len & 0xffff, len
+>> 16, 0, NULL) != SANE_STATUS_GOOD) {
+ DBG(DBG_error, "usb_control_msg PV8630_REQ_EPPBULKWRITE error\n");
+ }
+}
+
+/* Prepare a bulk read. len is the size of the data going to be
+ * read by pv8630_bulkread(). */
+static void pv8630_prep_bulkread(int fd, size_t len)
+{
+ if (sanei_usb_control_msg(fd, 0x40, PV8630_REQ_EPPBULKREAD, len & 0xffff, len
+>> 16, 0, NULL) != SANE_STATUS_GOOD) {
+ DBG(DBG_error, "usb_control_msg PV8630_REQ_EPPBULKREAD error\n");
+ }
+}
+
+/* Do a bulk write. The length must have previously been sent via
+ * pv8630_prep_bulkwrite(). */
+static void pv8630_bulkwrite(int fd, const void *data, size_t *len)
+{
+ if (sanei_usb_write_bulk(fd, (char *)data, len) != SANE_STATUS_GOOD) {
+ DBG(DBG_error, "sanei_usb_write_bulk error\n");
+ }
+}
+
+/* Do a bulk read. The length must have previously been sent via
+ * pv8630_prep_bulkread(). */
+static size_t pv8630_bulkread(int fd, void *data, size_t *len)
+{
+ if (sanei_usb_read_bulk(fd, data, len) != SANE_STATUS_GOOD) {
+ DBG(DBG_error, "sanei_usb_read_bulk error\n");
+ }
+
+ return(SANE_STATUS_GOOD);
+}
+
+/* Wait for the status register to present a given status. */
+static SANE_Status pv8630_status_wait(int fd, unsigned char status)
+{
+ unsigned char s;
+ int i;
+
+ for (i=0; i<1000; i++) {
+ pv8630_read_byte(fd, &s, PV8630_RSTATUS);
+ if (s == status) {
+ return(SANE_STATUS_GOOD);
+ }
+ usleep(100000);
+ }
+ DBG(DBG_error, "status never ok\n");
+
+ return(SANE_STATUS_IO_ERROR);
+}
+
+/* Apparently this will recover from some errors. */
+static void pv8630_mini_init_scanner(int fd)
+{
+ DBG(DBG_info, "mini_init_scanner\n");
+
+ /* Init the device (?) */
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+
+ pv8630_status_wait(fd, 0xd0);
+}
+
+/* Length of the CDB given the SCSI command. The last two might not be
+ 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. */
+ pv8630_write_byte(fd, 0x0c, PV8630_UNKNOWN);
+ pv8630_status_wait(fd, 0xf0);
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+
+ /* Send the CDB and check it's been received OK. */
+ pv8630_write_byte(fd, 0x16, PV8630_RMODE);
+ pv8630_flush_buffer(fd);
+ pv8630_prep_bulkwrite(fd, cmd_size);
+
+ tmp_len = cmd_size;
+ pv8630_bulkwrite(fd, src, &tmp_len);
+ pv8630_status_wait(fd, 0xf8);
+
+ pv8630_flush_buffer(fd);
+ pv8630_prep_bulkread(fd, 1);
+
+ result = 0xA5; /* to be sure */
+ tmp_len = 1;
+ pv8630_bulkread(fd, &result, &tmp_len);
+ if (result != 0) {
+ DBG(DBG_info, "error in 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) {
+ pv8630_flush_buffer(fd);
+ pv8630_prep_bulkwrite(fd, param_size);
+
+ tmp_len = param_size;
+ pv8630_bulkwrite(fd, param_ptr, &tmp_len);
+ pv8630_status_wait(fd, 0xf8);
+
+ pv8630_flush_buffer(fd);
+ pv8630_prep_bulkread(fd, 1);
+
+ result = 0xA5; /* to be sure */
+ tmp_len = 1;
+ pv8630_bulkread(fd, &result, &tmp_len);
+ if (result != 0) {
+ DBG(DBG_info, "error in 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) {
+ pv8630_flush_buffer(fd);
+ pv8630_prep_bulkread(fd, *dst_size);
+ pv8630_bulkread(fd, dst, dst_size);
+
+ DBG(DBG_info, " SCSI cmd returned %d bytes\n", *dst_size);
+
+ pv8630_status_wait(fd, 0xf8);
+
+ pv8630_flush_buffer(fd);
+ pv8630_prep_bulkread(fd, 1);
+
+ result = 0x5A; /* just to be sure */
+ tmp_len = 1;
+ pv8630_bulkread(fd, &result, &tmp_len);
+ if (result != 0) {
+ DBG(DBG_info, "error in pv8630_bulkread (got %02x)\n",
+result);
+ if (result == 8) {
+ pv8630_mini_init_scanner(fd);
+ }
+ return(SANE_STATUS_IO_ERROR);
+ }
+ }
+
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+ pv8630_status_wait(fd, 0xd0);
+
+ 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 */
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+
+ pv8630_status_wait(fd, 0xd0);
+
+ pv8630_write_byte(fd, 0x0c, PV8630_UNKNOWN);
+ pv8630_status_wait(fd, 0xf0);
+
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+ pv8630_status_wait(fd, 0xf0);
+
+ pv8630_write_byte(fd, 0x0c, PV8630_UNKNOWN);
+ pv8630_status_wait(fd, 0xf0);
+ pv8630_status_wait(fd, 0xf8);
+
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+ pv8630_write_byte(fd, 0x02, PV8630_RMODE);
+ pv8630_status_wait(fd, 0xd0);
+
+ pv8630_write_byte(fd, 0x0c, PV8630_UNKNOWN);
+ pv8630_status_wait(fd, 0xf0);
+
+ pv8630_write_byte(fd, 0x04, PV8630_UNKNOWN);
+
+ pv8630_write_byte(fd, 0x16, PV8630_RMODE);
+
+ DBG(DBG_info, "PV8630 initialized\n");
+
+ return(SANE_STATUS_GOOD);
+}
+
+/* End of the PV8630 code */
+
+/*
+ * 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.
+ */
+SANE_Status
+sanei_umaxusb_open (const char *dev, int *fdp,
+ SANEI_SCSI_Sense_Handler handler, void
+*handler_arg)
+{
+ *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(). */
+SANE_Status
+sanei_umaxusb_open_extended (const char *dev, int *fdp,
+ SANEI_SCSI_Sense_Handler handler, void
+*handler_arg, int *buffersize)
+{
+ return(sanei_umaxusb_open(dev, fdp, handler, handler_arg));
+}
+
+/* Close the scanner. */
+void
+sanei_umaxusb_close (int fd)
+{
+ close(fd);
+}
+
diff -P -r -u sane-backends-1.0.6.orig/backend/umax.c
sane-backends-1.0.6/backend/umax.c
--- sane-backends-1.0.6.orig/backend/umax.c Sat Oct 27 06:57:45 2001
+++ sane-backends-1.0.6/backend/umax.c Thu Nov 22 22:42:24 2001
@@ -129,12 +129,14 @@
#include "sane/saneopts.h"
#include "sane/sanei_scsi.h"
#include "sane/sanei_debug.h"
+#include "sane/sanei_usb.h"
#include <math.h>
#include <string.h>
#include "umax-scsidef.h"
#include "umax-scanner.c"
+#include "umax-usb.c"
#include "umax.h"
#include "sane/sanei_backend.h"
@@ -1218,6 +1220,104 @@
}
+/* ------------- Switches between the SCSI and USB commands
+-------------------------------- */
+
+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;
+ case SANE_UMAX_USB:
+ return sanei_umaxusb_cmd(dev->sfd, src, src_size, dst, dst_size);
+ break;
+ default:
+ return(SANE_STATUS_INVAL);
+ }
+}
+
+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;
+ case SANE_UMAX_USB:
+ return sanei_umaxusb_open_extended(devicename, &dev->sfd, handler,
+handler_arg, buffersize);
+ break;
+ default:
+ return(SANE_STATUS_INVAL);
+ }
+}
+
+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;
+ case SANE_UMAX_USB:
+ return sanei_umaxusb_open(devicename, &dev->sfd, handler,
+handler_arg);
+ break;
+ default:
+ return(SANE_STATUS_INVAL);
+ }
+}
+
+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;
+ case SANE_UMAX_USB:
+ sanei_umaxusb_close(dev->sfd);
+ dev->sfd=-1;
+ break;
+ }
+}
+
+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;
+ case SANE_UMAX_USB:
+ return sanei_umaxusb_req_enter (dev->sfd, src, src_size, dst,
+dst_size, idp);
+ break;
+ default:
+ return(SANE_STATUS_INVAL);
+ }
+}
+
+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;
+ case SANE_UMAX_USB:
+ return sanei_umaxusb_req_wait(id);
+ break;
+ default:
+ return(SANE_STATUS_INVAL);
+ }
+}
+
/* ------------------------------------------------------------ UMAX SCSI GET LAMP
STATUS ------------------ */
@@ -1228,7 +1328,7 @@
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));
@@ -1253,7 +1353,7 @@
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)
{
@@ -1273,7 +1373,7 @@
DBG(DBG_proc, "umax_set_lamp_status\n");
- 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 )
{
DBG(DBG_error, "ERROR: umax_set_lamp_status: open of %s failed:\n",
scanner->device->sane.name);
@@ -1287,8 +1387,7 @@
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;
}
@@ -1303,7 +1402,7 @@
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));
@@ -1324,7 +1423,7 @@
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));
@@ -1350,7 +1449,7 @@
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)
@@ -1382,7 +1481,7 @@
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)
{
@@ -1409,7 +1508,7 @@
( (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));
@@ -1444,7 +1543,7 @@
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));
@@ -1503,7 +1602,7 @@
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));
@@ -1529,7 +1628,7 @@
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));
@@ -1552,7 +1651,7 @@
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));
@@ -1617,7 +1716,7 @@
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));
@@ -1650,7 +1749,7 @@
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));
@@ -1702,7 +1801,7 @@
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));
@@ -1725,7 +1824,7 @@
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));
@@ -1746,7 +1845,7 @@
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));
@@ -2041,7 +2140,7 @@
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)
{
@@ -2070,7 +2169,7 @@
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));
@@ -2079,7 +2178,7 @@
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));
@@ -2128,7 +2227,7 @@
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));
@@ -2394,7 +2493,7 @@
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));
@@ -4052,11 +4151,14 @@
DBG(DBG_proc,"init\n");
dev->devicename = NULL;
- dev->sfd = -1;
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 {
+ 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;
@@ -4234,12 +4336,11 @@
}
}
- 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 */
@@ -4254,7 +4355,6 @@
static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp)
{
Umax_Device *dev;
- int sfd;
int i;
DBG(DBG_sane_proc,"attach_scanner: %s\n", devicename);
@@ -4280,10 +4380,17 @@
DBG(DBG_info, "attach_scanner: opening %s\n", devicename);
+ /* First, try to open the device as an USB device. If it fails, try
+ * the SCSI method. */
+ dev->bufsize = 16384; /* 16KB */
+ if (sanei_umaxusb_open (devicename, &dev->sfd, sense_handler, dev) ==
+SANE_STATUS_GOOD) {
+ dev->connection_type = SANE_UMAX_USB;
+ } else {
+
#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
dev->bufsize = 16384; /* 16KB */
- if (sanei_scsi_open_extended(devicename, &sfd, sense_handler, dev, (int *)
&dev->bufsize) != 0)
+ if (sanei_scsi_open_extended(devicename, &dev->sfd, sense_handler, dev, (int *)
+&dev->bufsize) != 0)
{
DBG(DBG_error, "ERROR: attach_scanner: opening %s failed\n", devicename);
free(dev);
@@ -4293,7 +4400,7 @@
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);
+ umax_scsi_close(dev);
free(dev);
return SANE_STATUS_NO_MEM;
}
@@ -4302,13 +4409,15 @@
#else
dev->bufsize = sanei_scsi_max_request_size;
- if (sanei_scsi_open(devicename, &sfd, sense_handler, dev) != 0)
+ if (sanei_scsi_open(devicename, dev, sense_handler, dev) != 0)
{
DBG(DBG_error, "ERROR: attach_scanner: open failed\n");
free(dev);
return SANE_STATUS_INVAL;
}
#endif
+ dev->connection_type = SANE_UMAX_SCSI;
+ }
DBG(DBG_info, "attach_scanner: allocating SCSI buffer[0]\n");
dev->buffer[0] = malloc(dev->bufsize);
/* allocate buffer */
@@ -4321,7 +4430,7 @@
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;
}
@@ -4332,13 +4441,11 @@
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;
@@ -4365,8 +4472,7 @@
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;
@@ -4421,7 +4527,7 @@
{
*devp = dev;
}
-
+ DBG(DBG_info, " NAMES %s %s\n", dev->sane.name, dev->devicename);
return SANE_STATUS_GOOD;
}
@@ -5398,7 +5504,7 @@
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
{
@@ -5451,11 +5557,15 @@
frontend_authorize_callback = authorize; /* store frontend authorize callback */
+ sanei_usb_init ();
+
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);
+ attach_scanner("/dev/usbscanner", 0);
+ return SANE_STATUS_GOOD;
}
DBG(DBG_info, "reading configure file %s\n", UMAX_CONFIG_FILE);
@@ -5492,6 +5602,34 @@
}
continue;
}
+ else if (strncmp(config_line, "usb", 3) == 0) {
+ const char *usb_device_name;
+ char *vendor, *product;
+ SANE_Word vendorID = 0, productID = 0;
+ const char *name;
+
+ name = sanei_config_skip_whitespace(config_line+3);
+
+ if (*name) {
+ name = sanei_config_get_string (name, &vendor);
+ if (vendor) {
+ vendorID = strtol (vendor, 0, 0);
+ free (vendor);
+ }
+ name = sanei_config_skip_whitespace (name);
+ }
+
+ name = sanei_config_skip_whitespace (name);
+ if (*name) {
+ name = sanei_config_get_string (name, &product);
+ if (product) {
+ productID = strtol (product, 0, 0);
+ free (product);
+ }
+ }
+
+ sanei_usb_find_devices (vendorID, productID, attach_one);
+ }
len = strlen (config_line);
@@ -5625,7 +5763,6 @@
memset(scanner, 0, sizeof (*scanner));
scanner->device = dev;
- scanner->device->sfd = -1;
if (scanner->device->inquiry_GIB & 32)
{
@@ -6666,7 +6803,7 @@
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 */
@@ -6684,8 +6821,7 @@
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;
}
}
@@ -6702,8 +6838,7 @@
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;
}
}
@@ -7057,7 +7192,7 @@
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");
@@ -7067,12 +7202,12 @@
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 */
{
@@ -7097,7 +7232,7 @@
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;
@@ -7105,7 +7240,7 @@
}
}
#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;
@@ -7120,8 +7255,7 @@
/* 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;
@@ -7304,8 +7438,7 @@
#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;
}
diff -P -r -u sane-backends-1.0.6.orig/backend/umax.conf
sane-backends-1.0.6/backend/umax.conf
--- sane-backends-1.0.6.orig/backend/umax.conf Sat Jun 23 20:02:26 2001
+++ sane-backends-1.0.6/backend/umax.conf Thu Nov 22 22:15:46 2001
@@ -23,6 +23,8 @@
scsi EPSON Perfection600
scsi ESCORT "Galleria 600S"
+usb 0x1606 0x0230
+
#
# device list for non-linux-systems:
/dev/scanner
diff -P -r -u sane-backends-1.0.6.orig/backend/umax.h
sane-backends-1.0.6/backend/umax.h
--- sane-backends-1.0.6.orig/backend/umax.h Sun Jun 17 17:49:17 2001
+++ sane-backends-1.0.6/backend/umax.h Thu Nov 22 22:46:23 2001
@@ -54,6 +54,7 @@
# include "sane/sanei_ipc.h"
#endif
+#include <usb.h>
/*
---------------------------------------------------------------------------------------------------------
*/
/* COMPILER OPTIONS: */
@@ -191,13 +192,18 @@
/* 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_SCSI 1
+#define SANE_UMAX_USB 2
+
SANE_Range x_dpi_range;
SANE_Range y_dpi_range;
SANE_Range x_range;
Binary files sane-backends-1.0.6.orig/core and sane-backends-1.0.6/core differ
diff -P -r -u sane-backends-1.0.6.orig/include/Makefile
sane-backends-1.0.6/include/Makefile
--- sane-backends-1.0.6.orig/include/Makefile Wed Dec 31 18:00:00 1969
+++ sane-backends-1.0.6/include/Makefile Wed Nov 21 15:41:45 2001
@@ -0,0 +1,8 @@
+# Generated automatically from Makefile.in by configure.
+# This is just a dummy to ensure that the include directory gets created
+# in a shadow-build.
+
+all:
+
+distclean:
+ rm -f Makefile
diff -P -r -u sane-backends-1.0.6.orig/include/sane/sanei_usb.h
sane-backends-1.0.6/include/sane/sanei_usb.h
--- sane-backends-1.0.6.orig/include/sane/sanei_usb.h Wed Sep 5 14:48:32 2001
+++ sane-backends-1.0.6/include/sane/sanei_usb.h Wed Nov 21 16:00:31 2001
@@ -25,21 +25,21 @@
#include "../include/sane/sane.h"
/* Initialize sanei_usb. Call this before any other sanei_usb function */
-void
+extern void
sanei_usb_init (void);
/* Get the vendor and product numbers for a given file descriptor. Currently,
only scanners supported by the Linux USB scanner module can be found. Linux
version must be 2.4.8 or higher. Returns SANE_STATUS_GOOD if the ids have
been found, otherwise SANE_STATUS_UNSUPPORTED. */
-SANE_Status
+extern SANE_Status
sanei_usb_get_vendor_product (SANE_Int fd, SANE_Word * vendor,
SANE_Word * product);
/* Find device names for given vendor and product ids. Above mentioned
limitations apply. The function attach is called for every device which
has been found.*/
-SANE_Status
+extern SANE_Status
sanei_usb_find_devices (SANE_Int vendor, SANE_Int product,
SANE_Status (*attach) (SANE_String_Const devname));
@@ -47,11 +47,11 @@
success, SANE_STATUS_GOOD is returned. If the file couldn't be accessed
due to permissions, SANE_STATUS_ACCESS_DENIED is returned. For every
other error, the return value is SANE_STATUS_INVAL. */
-SANE_Status
+extern SANE_Status
sanei_usb_open (SANE_String_Const devname, SANE_Int *fd);
/* Close an USB device represented by its file desciptor. */
-void
+extern void
sanei_usb_close (SANE_Int fd);
/* Initiate a bulk transfer read of up to zize bytes from the device to
@@ -59,7 +59,7 @@
read. Returns SANE_STATUS_GOOD on succes, SANE_STATUS_EOF if zero bytes
have been read, SANE_STATUS_IO_ERROR if an error occured during the read,
and SANE_STATUS_INVAL on every other error. */
-SANE_Status
+extern SANE_Status
sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size);
/* Initiate a bulk transfer write of up to size bytes from buffer to the
@@ -67,7 +67,7 @@
written. Returns SANE_STATUS_GOOD on succes, SANE_STATUS_IO_ERROR if an
error occured during the read, and SANE_STATUS_INVAL on every other
error. */
-SANE_Status
+extern SANE_Status
sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size);
/* A convenience function to support expanding device name patterns
@@ -84,4 +84,19 @@
extern void
sanei_usb_attach_matching_devices (const char *name,
SANE_Status (*attach) (const char *dev));
+
+/* Sends/Receives a control message to/from the USB device.
+ data is the buffer to send/receive the data. len is the length of
+ that data, or the length of the data to receive.
+
+ The function returns
+ SANE_STATUS_IO_ERROR on error,
+ SANE_STATUS_GOOD on success,
+ SANE_STATUS_UNSUPPORTED if the feature is not supported by the
+ OS or SANE.
+*/
+
+extern SANE_Status
+sanei_usb_control_msg( int fd, int rtype, int req, int value, int index, int len,
+void *data );
+
#endif /* sanei_usb_h */
diff -P -r -u sane-backends-1.0.6.orig/sanei/sanei_usb.c
sane-backends-1.0.6/sanei/sanei_usb.c
--- sane-backends-1.0.6.orig/sanei/sanei_usb.c Fri Oct 26 16:24:49 2001
+++ sane-backends-1.0.6/sanei/sanei_usb.c Thu Nov 22 22:25:03 2001
@@ -58,6 +58,31 @@
#include "../include/sane/sanei_usb.h"
#include "../include/sane/sanei_config.h"
+#if defined (__linux__)
+/* From /usr/src/linux/driver/usb/scanner.h */
+#define IOCTL_SCANNER_VENDOR _IOR('U', 0x20, int)
+#define IOCTL_SCANNER_PRODUCT _IOR('U', 0x21, int)
+#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, devrequest )
+ /* Older (unofficial) IOCTL numbers for Linux < v2.4.13 */
+#define IOCTL_SCANNER_VENDOR_OLD _IOR('u', 0xa0, int)
+#define IOCTL_SCANNER_PRODUCT_OLD _IOR('u', 0xa1, int)
+
+/* From /usr/src/linux/include/linux/usb.h */
+typedef struct {
+ unsigned char requesttype;
+ unsigned char request;
+ unsigned short value;
+ unsigned short index;
+ unsigned short length;
+} devrequest __attribute__ ((packed));
+
+/* From /usr/src/linux/driver/usb/scanner.h */
+struct ctrlmsg_ioctl {
+ devrequest req;
+ void *data;
+} cmsg;
+
+#endif /* __linux__ */
void
sanei_usb_init (void)
@@ -114,11 +139,6 @@
SANE_Word vendorID, productID;
#if defined (__linux__)
-#define IOCTL_SCANNER_VENDOR _IOR('U', 0x20, int)
-#define IOCTL_SCANNER_PRODUCT _IOR('U', 0x21, int)
- /* Older (unofficial) IOCTL numbers for Linux < v2.4.13 */
-#define IOCTL_SCANNER_VENDOR_OLD _IOR('u', 0xa0, int)
-#define IOCTL_SCANNER_PRODUCT_OLD _IOR('u', 0xa1, int)
/* read the vendor and product IDs via the IOCTLs */
if (ioctl (fd, IOCTL_SCANNER_VENDOR , &vendorID) == -1)
{
@@ -309,3 +329,39 @@
*size = write_size;
return SANE_STATUS_GOOD;
}
+
+#if defined(__linux__)
+
+/* Send/receive a control message to/from the USB device. */
+SANE_Status
+sanei_usb_control_msg( int fd, int rtype, int req, int value, int index, int len,
+void *data ) {
+ struct ctrlmsg_ioctl c;
+
+ c.req.requesttype = rtype;
+ c.req.request = req;
+ c.req.value = value;
+ c.req.index = index;
+ c.req.length = len;
+ c.data = data;
+
+ DBG(5, "control_msg: rtype = 0x%02x, req = %d, value = %d, index = %d, len =
+%d\n",
+ rtype, req, value, index, len );
+
+ if( ioctl(fd, SCANNER_IOCTL_CTRLMSG, &c) < 0 ) {
+ DBG(5, "control_msg: SCANNER_IOCTL_CTRLMSG error - %s\n",
+strerror(errno));
+ return SANE_STATUS_IO_ERROR;
+ }
+ return SANE_STATUS_GOOD;
+}
+
+#else
+
+UMAX_Status
+sanei_usb_control_msg( int fd, int rtype, int req, int value, int index, int len,
+void *data ) {
+ DBG (DBG_error, "control_msg: not supported on that OS\n");
+ return SANE_STATUS_UNSUPPORTED;
+}
+#endif /* __linux__ */
+
+
+