diff --git a/doc/Makefile.in b/doc/Makefile.in index b76a7a340..d7cd4fcb7 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -39,7 +39,7 @@ SECT5 = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 sane-dll.5 \ sane-tamarack.5 sane-ricoh.5 sane-avision.5 sane-plustek.5 \ sane-st400.5 sane-mustek_pp.5 sane-dc210.5 sane-v4l.5 \ sane-snapscan.5 sane-canon.5 sane-coolscan.5 sane-bh.5 sane-dc240.5 \ - sane-umax_pp.5 sane-sm3600.5 + sane-umax_pp.5 sane-sm3600.5 sane-usb.5 SECT7 = sane.7 MANPAGES = $(SECT1) $(SECT5) $(SECT7) READMES = README AUTHORS COPYING ChangeLog LEVEL2 LICENSE NEWS PROBLEMS \ diff --git a/doc/sane-usb.man b/doc/sane-usb.man new file mode 100644 index 000000000..4556023c1 --- /dev/null +++ b/doc/sane-usb.man @@ -0,0 +1,98 @@ +.TH sane-scsi 5 "11 Aug 2001" +.IX sane-usb +.SH NAME +sane-usb - USB configuration tips for SANE +.SH DESCRIPTION +This manual page contains tips and tricks on how to access scanners +with a USB interface. +.SH GENERAL INFO +Sane-backends currently use three methods of communicating with USB scanners: +.TP 2 +- +Using libusb (a library for usb access). This is used by the sm3600 backend +currently. +.TP +- +Access through sanei_usb, the SANE USB interface. Used by the mustek_usb +backend. +.TP +- +Direct access to the USB device files to access kernel scanner drivers +.PP +This manual page describes the access of USB scanners over the sanei_usb +interface. For point 1 and three of this list have a look at the backend's +manual page for details. +.PP +Currently USB access is only tested for Linux. It may work on FreeBSD but it's +not tested. +.PP +For scanners with a USB interface, it may be necessary to edit the +appropriate backend configuration file before using SANE for the first time. +For most systems, the configuration file should list the name of the USB +device file that the scanner is connected to (e.g., under Linux, +.B /dev/usb/scanner0 +or +.B /dev/usbscanner0 +is such a USB device). Do +.I not +create a symlink from +.B /dev/scanner +to the USB device because this link is used by the SCSI backends. The scanner +may be confused if it receives SCSI commands. For a detailed description of +each backend's configuration file, please refer to the relevant backend manual +page (e.g. sane-mustek_usb Mustek USB scanners). +.PP +For Linux, there is an alternate way of specifying scanner devices. This +alternate allows to identify scanners by the USB vendor and product numbers. +The syntax for specifying a scanner in this way is: +.PP +.RS +usb +.I VENDOR PRODUCT +.RE +.PP +where +.I VENDOR +is the USB vendor id, and +.I PRODUCT +is the USB product id of the scanner. Both ids are non-negative integer +numbers in decimal or hexadecimal format. The correct values for these fields +can be found by looking at the output of the command "cat +/proc/bus/usb/devices/". This is an example of a config file line: +.PP +.RS +usb 0x055f 0x0006 +.RE +.PP +would have the effect that all USB devices in the system with a vendor id of +0x55f and a product id of 0x0006 would be probed and recognized by the +backend. The same config line in decimal format looks like this: +.PP +.RS +usb 0x055f 0x0006 +.RE +.PP +When using a USB scanner, ensure that the access permission for the +USB device is set appropriately. We recommend to add a group +"scanner" to /etc/group which contains all users that should have +access to the scanner. The permission of the device should then be +set to allow group read and write access. For example, if the scanner +is at USB device +.BR /dev/usb/scanner0 , +then the following two commands would set the permission correctly: +.PP +.RS +$ chgrp scanner /dev/usb/scanner0 +.br +$ chmod 660 /dev/usb/scanner0 +.SH ENVIRONMENT +.TP +.B SANE_DEBUG_SANEI_USB +If the library was compiled with debug support enabled, this +environment variable controls the debug level for the USB I/O +subsystem. E.g., a value of 128 requests all debug output to be +printed. Smaller levels reduce verbosity. +.SH "SEE ALSO" +sane(7), sane\-find\-scanner(1), sane\-"backendname"(5), sane-scsi(5) +.SH AUTHOR +Henning Meier-Geinitz. Some parts were copied from the sane-scsi manual page. diff --git a/sanei/Makefile.in b/sanei/Makefile.in index e8a5ac4b2..0dd92242b 100644 --- a/sanei/Makefile.in +++ b/sanei/Makefile.in @@ -45,13 +45,13 @@ LIBSANEI_OBJS = sanei_ab306.o sanei_constrain_value.o sanei_init_debug.o \ sanei_net.o sanei_wire.o sanei_codec_ascii.o sanei_codec_bin.o \ sanei_save_values.o sanei_load_values.o \ sanei_scsi.o sanei_config.o sanei_config2.o sanei_pio.o sanei_pa4s2.o \ - sanei_auth.o + sanei_auth.o sanei_usb.o LIBSANEI_LTOBJS = sanei_ab306.lo sanei_constrain_value.lo sanei_init_debug.lo \ sanei_net.lo sanei_wire.lo sanei_codec_ascii.lo sanei_codec_bin.lo \ sanei_save_values.lo sanei_load_values.lo \ sanei_scsi.lo sanei_config.lo sanei_config2.lo sanei_pio.lo \ - sanei_pa4s2.lo sanei_auth.lo + sanei_pa4s2.lo sanei_auth.lo sanei_usb.lo TARGETS = libsanei.a TESTPROGRAMS = test_wire diff --git a/sanei/sanei_usb.c b/sanei/sanei_usb.c new file mode 100644 index 000000000..8222f5955 --- /dev/null +++ b/sanei/sanei_usb.c @@ -0,0 +1,253 @@ +/* sane - Scanner Access Now Easy. + Copyright (C) 2001 Henning Meier-Geinitz + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. + + This file provides a generic (?) USB interface. */ + +#include "../include/sane/config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BACKEND_NAME sanei_usb +#include "../include/sane/sane.h" +#include "../include/sane/sanei_debug.h" +#include "../include/sane/sanei_usb.h" + + +void +sanei_usb_init (void) +{ + DBG_INIT(); +} + +SANE_Status +sanei_usb_get_vendor_product (SANE_Int fd, SANE_Word * vendor, + SANE_Word * product) +{ + SANE_Word vendorID, productID; + +#if defined (__linux__) +#define IOCTL_SCANNER_VENDOR _IOR('u', 0xa0, int) +#define IOCTL_SCANNER_PRODUCT _IOR('u', 0xa1, int) + /* read the vendor and product IDs via the IOCTLs */ + if (ioctl (fd, IOCTL_SCANNER_VENDOR , &vendorID) == -1) + { + DBG (3, "sanei_usb_get_vendor_product: ioctl (vendor) of fd %d failed: " + "%s\n", fd, strerror (errno)); + /* just set the vendor ID to 0 */ + vendorID = 0; + } + if (ioctl (fd, IOCTL_SCANNER_PRODUCT , &productID) == -1) + { + DBG (3, "sanei_usb_get_vendor_product: ioctl (product) of ds %d failed: " + "%s\n", fd, strerror (errno)); + /* just set the product ID to 0 */ + productID = 0; + } + if (vendor) + *vendor = vendorID; + if (product) + *product = productID; +#else /* not defined (__linux__) */ + vendorID = 0; + productID = 0; +#endif /* not defined (__linux__) */ + + if (!vendorID || !productID) + { + DBG (3, "sanei_usb_get_vendor_product: fd %d: couldn't get " + "vendor+product ids. ioctl unsupported?\n", fd); + + return SANE_STATUS_UNSUPPORTED; + } + else + { + DBG (3, "sanei_usb_get_vendor_product: fd %d: vendorID: 0x%x, " + "productID: 0x%x\n", fd, vendorID, productID); + return SANE_STATUS_GOOD; + } +} + + +static void +check_vendor_product (SANE_String_Const devname, SANE_Word vendor, + SANE_Word product, + SANE_Status (*attach) (SANE_String_Const dev)) +{ + SANE_Status status; + SANE_Word devvendor, devproduct; + SANE_Int fd; + + status = sanei_usb_open (devname, &fd); + if (status != SANE_STATUS_GOOD) + return; + + status = sanei_usb_get_vendor_product (fd, &devvendor, &devproduct); + sanei_usb_close (fd); + if (status == SANE_STATUS_GOOD) + { + if (devvendor == vendor && devproduct == product) + { + if (attach) + attach (devname); + } + } + return; +} + +SANE_Status +sanei_usb_find_devices (SANE_Int vendor, SANE_Int product, + SANE_Status (*attach) (SANE_String_Const dev)) +{ + SANE_String *prefix; + SANE_String prefixlist[] = {"/dev/usbscanner", + "/dev/usb/scanner", + 0}; + SANE_Char devname[30]; + int devcount; + +#define SANEI_USB_MAX_DEVICES 16 + + DBG (3, "sanei_usb_find_devices: vendor=0x%x, product=0x%x, attach=%p\n", + vendor, product, attach); + + for (prefix = prefixlist; *prefix; prefix++) + { + check_vendor_product (*prefix, vendor, product, attach); + for (devcount = 0; devcount < SANEI_USB_MAX_DEVICES; + devcount++) + { + snprintf (devname, sizeof (devname), "%s%d", *prefix, + devcount); + check_vendor_product (devname, vendor, product, attach); + } + } + return SANE_STATUS_GOOD; +} + +SANE_Status +sanei_usb_open (SANE_String_Const devname, SANE_Int *fd) +{ + if (!fd) + { + DBG (1, "sanei_usb_open: fd == NULL\n", fd); + return SANE_STATUS_INVAL; + } + *fd = open (devname, O_RDWR); + if (*fd < 0) + { + SANE_Status status = SANE_STATUS_INVAL; + + DBG (1, "sanei_usb_open: open failed: %s\n", strerror (errno)); + if (errno == EACCES) + status = SANE_STATUS_ACCESS_DENIED; + return status; + } + DBG (5, "sanei_usb_open: fd %d opened\n", *fd); + return SANE_STATUS_GOOD; +} + +void +sanei_usb_close (SANE_Int fd) +{ + DBG (5, "sanei_usb_close: closing fd %d\n", fd); + close (fd); + return; +} + +SANE_Status +sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size) +{ + ssize_t read_size; + + if (!size) + { + DBG (1, "sanei_usb_read_bulk: size == NULL\n"); + return SANE_STATUS_INVAL; + } + + read_size = read (fd, buffer, *size); + if (read_size < 0) + { + DBG (1, "sanei_usb_read_bulk: read failed: %s\n", strerror (errno)); + *size = 0; + return SANE_STATUS_IO_ERROR; + } + if (read_size == 0) + { + DBG (3, "sanei_usb_read_bulk: read returned EOF\n"); + *size = 0; + return SANE_STATUS_EOF; + } + DBG (5, "sanei_usb_read_bulk: wanted %lu bytes, got %l bytes\n", + *size, read_size); + *size = read_size; + return SANE_STATUS_GOOD; +} + +SANE_Status +sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size) +{ + ssize_t write_size; + + if (!size) + { + DBG (1, "sanei_usb_write_bulk: size == NULL\n"); + return SANE_STATUS_INVAL; + } + + write_size = write (fd, buffer, *size); + if (write_size < 0) + { + DBG (1, "sanei_usb_write_bulk: write failed: %s\n", strerror (errno)); + *size = 0; + return SANE_STATUS_IO_ERROR; + } + DBG (5, "sanei_usb_read_write: wanted %lu bytes, wrote %l bytes\n", + *size, write_size); + *size = write_size; + return SANE_STATUS_GOOD; +}