sane-project-backends/tools/sane-find-scanner.c

1120 wiersze
32 KiB
C

/* sane-find-scanner.c
Copyright (C) 1997-2002 Oliver Rauch, Henning Meier-Geinitz, and others.
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.
*/
#include "../include/sane/config.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#ifdef HAVE_LIBUSB
#include "usb.h"
#endif
#include "../include/sane/sanei.h"
#include "../include/sane/sanei_scsi.h"
#include "../include/sane/sanei_usb.h"
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
static const char *prog_name;
static int verbose = 1;
static SANE_Bool force = SANE_FALSE;
static SANE_Bool device_found = SANE_FALSE;
static SANE_Bool libusb_device_found = SANE_FALSE;
static SANE_Bool unknown_found = SANE_FALSE;
typedef struct
{
unsigned char *cmd;
size_t size;
}
scsiblk;
#define INQUIRY 0x12
#define set_inquiry_return_size(icb,val) icb[0x04]=val
#define IN_periph_devtype_cpu 0x03
#define IN_periph_devtype_scanner 0x06
#define get_scsi_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08)
#define get_scsi_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010)
#define get_scsi_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04)
#define get_scsi_inquiry_periph_devtype(in) (in[0] & 0x1f)
#define get_scsi_inquiry_additional_length(in) in[0x04]
#define set_scsi_inquiry_length(out,n) out[0x04]=n-5
static unsigned char inquiryC[] = {
INQUIRY, 0x00, 0x00, 0x00, 0xff, 0x00
};
static scsiblk inquiry = {
inquiryC, sizeof (inquiryC)
};
static void
usage (char *msg)
{
fprintf (stderr, "Usage: %s [-hvqf] [devname ...]\n", prog_name);
fprintf (stderr, "\t-h: print this help message\n");
fprintf (stderr, "\t-v: be more verbose (can be used multiple times)\n");
fprintf (stderr, "\t-q: be quiet (print only devices, no comments)\n");
fprintf (stderr, "\t-f: force opening devname as SCSI even if it looks "
"like USB\n");
if (msg)
fprintf (stderr, "\t%s\n", msg);
}
/* if SCSI generic is optional on your OS, and there is a software test
which will determine if it is included, add it here. If you are sure
that SCSI generic was found, return 1. If SCSI generic is always
available in your OS, return 1 */
static int
check_sg (void)
{
#if defined(__linux__)
/* Assumption: /proc/devices lines are shorter than 256 characters */
char line[256], driver[256] = "";
FILE *stream;
stream = fopen ("/proc/devices", "r");
/* Likely reason for failure, no /proc => probably no SG either */
if (stream == NULL)
return 0;
while (fgets (line, sizeof (line) - 1, stream))
{
if (sscanf (line, " %*d %s\n", driver) > 0 && !strcmp (driver, "sg"))
break;
}
fclose (stream);
if (strcmp (driver, "sg"))
{
return 0;
}
else
{
return 1;
}
#endif
return 1; /* Give up, and assume yes to avoid false negatives */
}
/* Display a buffer in the log. Display by lines of 16 bytes. */
static void
hexdump (const char *comment, unsigned char *buf, const int length)
{
int i;
char line[128];
char *ptr;
char asc_buf[17];
char *asc_ptr;
printf (" %s\n", comment);
i = 0;
goto start;
do
{
if (i < length)
{
ptr += sprintf (ptr, " %2.2x", *buf);
if (*buf >= 32 && *buf <= 127)
{
asc_ptr += sprintf (asc_ptr, "%c", *buf);
}
else
{
asc_ptr += sprintf (asc_ptr, ".");
}
}
else
{
/* After the length; do nothing. */
ptr += sprintf (ptr, " ");
}
i++;
buf++;
if ((i % 16) == 0)
{
/* It's a new line */
printf (" %s %s\n", line, asc_buf);
start:
ptr = line;
*ptr = '\0';
asc_ptr = asc_buf;
*asc_ptr = '\0';
ptr += sprintf (ptr, " %3.3d:", i);
}
}
while (i < ((length + 15) & ~15));
}
static SANE_Status
scanner_do_scsi_inquiry (unsigned char *buffer, int sfd)
{
size_t size;
SANE_Status status;
memset (buffer, '\0', 256); /* clear buffer */
size = 5; /* first get only 5 bytes to get size of
inquiry_return_block */
set_inquiry_return_size (inquiry.cmd, size);
status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size);
if (status != SANE_STATUS_GOOD)
return (status);
size = get_scsi_inquiry_additional_length (buffer) + 5;
/* then get inquiry with actual size */
set_inquiry_return_size (inquiry.cmd, size);
status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size);
return (status);
}
static void
scanner_identify_scsi_scanner (unsigned char *buffer, int sfd,
char *devicename)
{
unsigned char vendor[9];
unsigned char product[17];
unsigned char version[5];
unsigned char *pp;
unsigned int devtype;
SANE_Status status;
static char *devtypes[] = {
"disk", "tape", "printer", "processor", "CD-writer",
"CD-drive", "scanner", "optical-drive", "jukebox",
"communicator"
};
status = scanner_do_scsi_inquiry (buffer, sfd);
if (status != SANE_STATUS_GOOD)
{
if (verbose > 1)
printf ("inquiry for device %s failed (%s)\n",
devicename, sane_strstatus (status));
return;
}
if (verbose > 2)
hexdump ("Inquiry for device:", buffer,
get_scsi_inquiry_additional_length (buffer) + 5);
devtype = get_scsi_inquiry_periph_devtype (buffer);
if (verbose <= 1 && devtype != IN_periph_devtype_scanner
/* old HP scanners use the CPU id ... */
&& devtype != IN_periph_devtype_cpu)
return; /* no, continue searching */
get_scsi_inquiry_vendor ((char *) buffer, (char *) vendor);
get_scsi_inquiry_product ((char *) buffer, (char *) product);
get_scsi_inquiry_version ((char *) buffer, (char *) version);
pp = &vendor[7];
vendor[8] = '\0';
while (pp >= vendor && (*pp == ' ' || *pp >= 127))
*pp-- = '\0';
pp = &product[15];
product[16] = '\0';
while (pp >= product && (*pp == ' ' || *pp >= 127))
*pp-- = '\0';
pp = &version[3];
version[4] = '\0';
while (pp >= version && (*pp == ' ' || *(pp - 1) >= 127))
*pp-- = '\0';
device_found = SANE_TRUE;
printf ("found SCSI %s \"%s %s %s\" at %s\n",
devtype < NELEMS (devtypes) ? devtypes[devtype] : "unknown device",
vendor, product, version, devicename);
return;
}
static void
check_scsi_file (char *file_name)
{
int result;
int sfd;
unsigned char buffer[16384];
if (strstr (file_name, "usb")
|| strstr (file_name, "uscanner") || strstr (file_name, "ugen"))
{
if (force)
{
if (verbose > 1)
printf ("checking %s even though it looks like a USB device...",
file_name);
}
else
{
if (verbose > 1)
printf ("ignored %s (not a SCSI device)\n", file_name);
return;
}
}
else if (verbose > 1)
printf ("checking %s...", file_name);
result = sanei_scsi_open (file_name, &sfd, NULL, NULL);
if (verbose > 1)
{
if (result != 0)
printf (" failed to open (%s)\n", sane_strstatus (result));
else
printf (" open ok\n");
}
if (result == SANE_STATUS_GOOD)
{
scanner_identify_scsi_scanner (buffer, sfd, file_name);
sanei_scsi_close (sfd);
}
return;
}
static void
check_usb_file (char *file_name)
{
SANE_Status result;
SANE_Word vendor, product;
SANE_Int fd;
if (!strstr (file_name, "usb")
&& !strstr (file_name, "uscanner") && !strstr (file_name, "ugen"))
{
if (force)
{
if (verbose > 1)
printf ("checking %s even though doesn't look like a "
"USB device...", file_name);
}
else
{
if (verbose > 1)
printf ("ignored %s (not a USB device)\n", file_name);
return;
}
}
else if (verbose > 1)
printf ("checking %s...", file_name);
result = sanei_usb_open (file_name, &fd);
if (result != SANE_STATUS_GOOD)
{
if (verbose > 1)
printf (" failed to open (%s)\n", sane_strstatus (result));
}
else
{
result = sanei_usb_get_vendor_product (fd, &vendor, &product);
if (result == SANE_STATUS_GOOD)
{
if (verbose > 1)
printf (" open ok, vendor and product ids were identified\n");
printf ("found USB scanner (vendor=0x%04x, "
"product=0x%04x) at %s\n", vendor, product, file_name);
}
else
{
if (verbose > 1)
printf (" open ok, but vendor and product could NOT be "
"identified\n");
printf ("found USB scanner (UNKNOWN vendor and product) "
"at device %s\n", file_name);
unknown_found = SANE_TRUE;
}
device_found = SANE_TRUE;
sanei_usb_close (fd);
}
}
#ifdef HAVE_LIBUSB
static char *
get_libusb_string_descriptor (struct usb_device *dev, int index)
{
usb_dev_handle *handle;
char *buffer;
struct usb_string_descriptor *sd;
int size = 100;
int i;
if (!index)
return 0;
buffer = calloc (1, size + 1);
if (!buffer)
return 0;
sd = (struct usb_string_descriptor *) buffer;
handle = usb_open (dev);
if (!handle)
return 0;
if (usb_control_msg (handle,
USB_ENDPOINT_IN + USB_TYPE_STANDARD + USB_RECIP_DEVICE,
USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) + index, 0, buffer,
size, 1000) < 0)
{
usb_close (handle);
return 0;
}
if (sd->bLength < 2 || sd->bLength > size
|| sd->bDescriptorType != USB_DT_STRING)
{
usb_close (handle);
return 0;
}
size = sd->bLength - 2;
for (i = 0; i < (size / 2); i++)
buffer[i] = buffer[2 + 2 * i];
buffer[i] = 0;
usb_close (handle);
return buffer;
}
static char *
get_libusb_vendor (struct usb_device *dev)
{
return get_libusb_string_descriptor (dev, dev->descriptor.iManufacturer);
}
static char *
get_libusb_product (struct usb_device *dev)
{
return get_libusb_string_descriptor (dev, dev->descriptor.iProduct);
}
static void
check_libusb_device (struct usb_device *dev)
{
int is_scanner = 0;
char *vendor = get_libusb_vendor (dev);
char *product = get_libusb_product (dev);
int interface_nr;
if (!dev->config)
{
if (verbose > 1)
printf ("device 0x%04x/0x%04x is not configured\n",
dev->descriptor.idVendor, dev->descriptor.idProduct);
return;
}
if (verbose > 2)
{
/* print everything we know about the device */
int config_nr;
struct usb_device_descriptor *d = &dev->descriptor;
printf ("\n");
printf ("<device descriptor of 0x%04x/0x%04x at %s:%s",
d->idVendor, d->idProduct, dev->bus->dirname, dev->filename);
if (vendor || product)
{
printf (" (%s%s%s)", vendor ? vendor : "",
(vendor && product) ? " " : "", product ? product : "");
}
printf (">\n");
printf ("bLength %d\n", d->bLength);
printf ("bDescriptorType %d\n", d->bDescriptorType);
printf ("bcdUSB %d.%d%d\n", d->bcdUSB >> 8,
(d->bcdUSB >> 4) & 15, d->bcdUSB & 15);
printf ("bDeviceClass %d\n", d->bDeviceClass);
printf ("bDeviceSubClass %d\n", d->bDeviceSubClass);
printf ("bDeviceProtocol %d\n", d->bDeviceProtocol);
printf ("bMaxPacketSize0 %d\n", d->bMaxPacketSize0);
printf ("idVendor 0x%04X\n", d->idVendor);
printf ("idProduct 0x%04X\n", d->idProduct);
printf ("bcdDevice %d.%d%d\n", d->bcdDevice >> 8,
(d->bcdDevice >> 4) & 15, d->bcdDevice & 15);
printf ("iManufacturer %d (%s)\n", d->iManufacturer,
d->iManufacturer
? get_libusb_string_descriptor (dev, d->iManufacturer) : "");
printf ("iProduct %d (%s)\n", d->iProduct,
d->iProduct
? get_libusb_string_descriptor (dev, d->iProduct) : "");
printf ("iSerialNumber %d (%s)\n", d->iSerialNumber,
d->iSerialNumber
? get_libusb_string_descriptor (dev, d->iSerialNumber) : "");
printf ("bNumConfigurations %d\n", d->bNumConfigurations);
for (config_nr = 0; config_nr < d->bNumConfigurations; config_nr++)
{
struct usb_config_descriptor *c = &dev->config[config_nr];
int interface_nr;
printf (" <configuration %d>\n", config_nr);
printf (" bLength %d\n", c->bLength);
printf (" bDescriptorType %d\n", c->bDescriptorType);
printf (" wTotalLength %d\n", c->wTotalLength);
printf (" bNumInterfaces %d\n", c->bNumInterfaces);
printf (" bConfigurationValue %d\n", c->bConfigurationValue);
printf (" iConfiguration %d (%s)\n", c->iConfiguration,
c->iConfiguration ?
get_libusb_string_descriptor (dev, c->iConfiguration) : "");
printf (" bmAttributes %d (%s%s)\n", c->bmAttributes,
c->bmAttributes & 64 ? "Self-powered" : "",
c->bmAttributes & 32 ? "Remote Wakeup" : "");
printf (" MaxPower %d mA\n", c->MaxPower * 2);
for (interface_nr = 0; interface_nr < c->bNumInterfaces;
interface_nr++)
{
struct usb_interface *interface = &c->interface[interface_nr];
int alt_setting_nr;
printf (" <interface %d>\n", interface_nr);
for (alt_setting_nr = 0;
alt_setting_nr < interface->num_altsetting;
alt_setting_nr++)
{
struct usb_interface_descriptor *i
= &interface->altsetting[0];
int ep_nr;
printf (" <altsetting %d>\n", alt_setting_nr);
printf (" bLength %d\n", i->bLength);
printf (" bDescriptorType %d\n", i->bDescriptorType);
printf (" bInterfaceNumber %d\n", i->bInterfaceNumber);
printf (" bAlternateSetting %d\n", i->bAlternateSetting);
printf (" bNumEndpoints %d\n", i->bNumEndpoints);
printf (" bInterfaceClass %d\n", i->bInterfaceClass);
printf (" bInterfaceSubClass %d\n",
i->bInterfaceSubClass);
printf (" bInterfaceProtocol %d\n",
i->bInterfaceProtocol);
printf (" iInterface %d (%s)\n", i->iInterface,
i->iInterface
? get_libusb_string_descriptor (dev,
i->
iInterface) : "");
for (ep_nr = 0; ep_nr < i->bNumEndpoints; ep_nr++)
{
struct usb_endpoint_descriptor *e = &i->endpoint[ep_nr];
char *ep_type;
switch (e->bmAttributes & USB_ENDPOINT_TYPE_MASK)
{
case USB_ENDPOINT_TYPE_CONTROL:
ep_type = "control";
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
ep_type = "isochronous";
break;
case USB_ENDPOINT_TYPE_BULK:
ep_type = "bulk";
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
ep_type = "interrupt";
break;
default:
ep_type = "unknown";
break;
}
printf (" <endpoint %d>\n", ep_nr);
printf (" bLength %d\n", e->bLength);
printf (" bDescriptorType %d\n",
e->bDescriptorType);
printf (" bEndpointAddress 0x%02X (%s 0x%02X)\n",
e->bEndpointAddress,
e->bEndpointAddress & USB_ENDPOINT_DIR_MASK ?
"in" : "out",
e->
bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK);
printf (" bmAttributes %d (%s)\n",
e->bmAttributes, ep_type);
printf (" wMaxPacketSize %d\n",
e->wMaxPacketSize);
printf (" bInterval %d ms\n", e->bInterval);
printf (" bRefresh %d\n", e->bRefresh);
printf (" bSynchAddress %d\n", e->bSynchAddress);
}
}
}
}
}
/* Some heuristics, which device may be a scanner */
if (dev->descriptor.idVendor == 0) /* hub */
--is_scanner;
if (dev->descriptor.idProduct == 0) /* hub */
--is_scanner;
for (interface_nr = 0; interface_nr < dev->config[0].bNumInterfaces && is_scanner <= 0; interface_nr++)
{
switch (dev->descriptor.bDeviceClass)
{
case USB_CLASS_VENDOR_SPEC:
++is_scanner;
break;
case USB_CLASS_PER_INTERFACE:
switch (dev->config[0].interface[interface_nr].altsetting[0].bInterfaceClass)
{
case USB_CLASS_VENDOR_SPEC:
case USB_CLASS_PER_INTERFACE:
case 16: /* data? */
++is_scanner;
break;
}
break;
}
}
if (is_scanner > 0)
{
printf ("found USB scanner (vendor=0x%04x", dev->descriptor.idVendor);
if (vendor)
printf (" [%s]", vendor);
printf (", product=0x%04x", dev->descriptor.idProduct);
if (product)
printf (" [%s]", product);
printf (") at libusb:%s:%s\n", dev->bus->dirname, dev->filename);
libusb_device_found = SANE_TRUE;
device_found = SANE_TRUE;
}
}
#endif /* HAVE_LIBUSB */
static DIR *
scan_directory (char *dir_name)
{
struct stat stat_buf;
DIR *dir;
if (verbose > 2)
printf ("scanning directory %s\n", dir_name);
if (stat (dir_name, &stat_buf) < 0)
{
if (verbose > 1)
printf ("cannot stat `%s' (%s)\n", dir_name, strerror (errno));
return 0;
}
if (!S_ISDIR (stat_buf.st_mode))
{
if (verbose > 1)
printf ("`%s' is not a directory\n", dir_name);
return 0;
}
if ((dir = opendir (dir_name)) == 0)
{
if (verbose > 1)
printf ("cannot read directory `%s' (%s)\n", dir_name,
strerror (errno));
return 0;
}
return dir;
}
static char *
get_next_file (char *dir_name, DIR * dir)
{
struct dirent *dir_entry;
static char file_name[PATH_MAX];
do
{
dir_entry = readdir (dir);
if (!dir_entry)
return 0;
}
while (strcmp (dir_entry->d_name, ".") == 0
|| strcmp (dir_entry->d_name, "..") == 0);
if (strlen (dir_name) + strlen (dir_entry->d_name) + 1 > PATH_MAX)
{
if (verbose > 1)
printf ("filename too long\n");
return 0;
}
sprintf (file_name, "%s%s", dir_name, dir_entry->d_name);
return file_name;
}
int
main (int argc, char **argv)
{
char **dev_list, **usb_dev_list, *dev_name, **ap;
prog_name = strrchr (argv[0], '/');
if (prog_name)
++prog_name;
else
prog_name = argv[0];
for (ap = argv + 1; ap < argv + argc; ++ap)
{
if ((*ap)[0] != '-')
break;
switch ((*ap)[1])
{
case '?':
case 'h':
usage (0);
exit (0);
case 'v':
++verbose;
break;
case 'q':
--verbose;
break;
case 'f':
force = SANE_TRUE;
break;
default:
printf ("unknown option: -%c, try -h for help\n", (*ap)[1]);
exit (0);
}
}
if (ap < argv + argc)
{
dev_list = ap;
usb_dev_list = ap;
}
else
{
static char *default_dev_list[] = {
#if defined(__sgi)
"/dev/scsi/sc0d1l0", "/dev/scsi/sc0d2l0",
"/dev/scsi/sc0d3l0", "/dev/scsi/sc0d4l0",
"/dev/scsi/sc0d5l0", "/dev/scsi/sc0d6l0",
"/dev/scsi/sc0d7l0", "/dev/scsi/sc0d8l0",
"/dev/scsi/sc0d9l0", "/dev/scsi/sc0d10l0",
"/dev/scsi/sc0d11l0", "/dev/scsi/sc0d12l0",
"/dev/scsi/sc0d13l0", "/dev/scsi/sc0d14l0",
"/dev/scsi/sc0d15l0",
"/dev/scsi/sc1d1l0", "/dev/scsi/sc1d2l0",
"/dev/scsi/sc1d3l0", "/dev/scsi/sc1d4l0",
"/dev/scsi/sc1d5l0", "/dev/scsi/sc1d6l0",
"/dev/scsi/sc1d7l0", "/dev/scsi/sc1d8l0",
"/dev/scsi/sc1d9l0", "/dev/scsi/sc1d10l0",
"/dev/scsi/sc1d11l0", "/dev/scsi/sc1d12l0",
"/dev/scsi/sc1d13l0", "/dev/scsi/sc1d14l0",
"/dev/scsi/sc1d15l0",
"/dev/scsi/sc2d1l0", "/dev/scsi/sc2d2l0",
"/dev/scsi/sc2d3l0", "/dev/scsi/sc2d4l0",
"/dev/scsi/sc2d5l0", "/dev/scsi/sc2d6l0",
"/dev/scsi/sc2d7l0", "/dev/scsi/sc2d8l0",
"/dev/scsi/sc2d9l0", "/dev/scsi/sc2d10l0",
"/dev/scsi/sc2d11l0", "/dev/scsi/sc2d12l0",
"/dev/scsi/sc2d13l0", "/dev/scsi/sc2d14l0",
"/dev/scsi/sc2d15l0",
"/dev/scsi/sc3d1l0", "/dev/scsi/sc3d2l0",
"/dev/scsi/sc3d3l0", "/dev/scsi/sc3d4l0",
"/dev/scsi/sc3d5l0", "/dev/scsi/sc3d6l0",
"/dev/scsi/sc3d7l0", "/dev/scsi/sc3d8l0",
"/dev/scsi/sc3d9l0", "/dev/scsi/sc3d10l0",
"/dev/scsi/sc3d11l0", "/dev/scsi/sc3d12l0",
"/dev/scsi/sc3d13l0", "/dev/scsi/sc3d14l0",
"/dev/scsi/sc3d15l0",
"/dev/scsi/sc4d1l0", "/dev/scsi/sc4d2l0",
"/dev/scsi/sc4d3l0", "/dev/scsi/sc4d4l0",
"/dev/scsi/sc4d5l0", "/dev/scsi/sc4d6l0",
"/dev/scsi/sc4d7l0", "/dev/scsi/sc4d8l0",
"/dev/scsi/sc4d9l0", "/dev/scsi/sc4d10l0",
"/dev/scsi/sc4d11l0", "/dev/scsi/sc4d12l0",
"/dev/scsi/sc4d13l0", "/dev/scsi/sc4d14l0",
"/dev/scsi/sc4d15l0",
"/dev/scsi/sc5d1l0", "/dev/scsi/sc5d2l0",
"/dev/scsi/sc5d3l0", "/dev/scsi/sc5d4l0",
"/dev/scsi/sc5d5l0", "/dev/scsi/sc5d6l0",
"/dev/scsi/sc5d7l0", "/dev/scsi/sc5d8l0",
"/dev/scsi/sc5d9l0", "/dev/scsi/sc5d10l0",
"/dev/scsi/sc5d11l0", "/dev/scsi/sc5d12l0",
"/dev/scsi/sc5d13l0", "/dev/scsi/sc5d14l0",
"/dev/scsi/sc5d15l0",
"/dev/scsi/sc6d1l0", "/dev/scsi/sc6d2l0",
"/dev/scsi/sc6d3l0", "/dev/scsi/sc6d4l0",
"/dev/scsi/sc6d5l0", "/dev/scsi/sc6d6l0",
"/dev/scsi/sc6d7l0", "/dev/scsi/sc6d8l0",
"/dev/scsi/sc6d9l0", "/dev/scsi/sc6d10l0",
"/dev/scsi/sc6d11l0", "/dev/scsi/sc6d12l0",
"/dev/scsi/sc6d13l0", "/dev/scsi/sc6d14l0",
"/dev/scsi/sc6d15l0",
"/dev/scsi/sc7d1l0", "/dev/scsi/sc7d2l0",
"/dev/scsi/sc7d3l0", "/dev/scsi/sc7d4l0",
"/dev/scsi/sc7d5l0", "/dev/scsi/sc7d6l0",
"/dev/scsi/sc7d7l0", "/dev/scsi/sc7d8l0",
"/dev/scsi/sc7d9l0", "/dev/scsi/sc7d10l0",
"/dev/scsi/sc7d11l0", "/dev/scsi/sc7d12l0",
"/dev/scsi/sc7d13l0", "/dev/scsi/sc7d14l0",
"/dev/scsi/sc7d15l0",
"/dev/scsi/sc8d1l0", "/dev/scsi/sc8d2l0",
"/dev/scsi/sc8d3l0", "/dev/scsi/sc8d4l0",
"/dev/scsi/sc8d5l0", "/dev/scsi/sc8d6l0",
"/dev/scsi/sc8d7l0", "/dev/scsi/sc8d8l0",
"/dev/scsi/sc8d9l0", "/dev/scsi/sc8d10l0",
"/dev/scsi/sc8d11l0", "/dev/scsi/sc8d12l0",
"/dev/scsi/sc8d13l0", "/dev/scsi/sc8d14l0",
"/dev/scsi/sc8d15l0",
"/dev/scsi/sc9d1l0", "/dev/scsi/sc9d2l0",
"/dev/scsi/sc9d3l0", "/dev/scsi/sc9d4l0",
"/dev/scsi/sc9d5l0", "/dev/scsi/sc9d6l0",
"/dev/scsi/sc9d7l0", "/dev/scsi/sc9d8l0",
"/dev/scsi/sc9d9l0", "/dev/scsi/sc9d10l0",
"/dev/scsi/sc9d11l0", "/dev/scsi/sc9d12l0",
"/dev/scsi/sc9d13l0", "/dev/scsi/sc9d14l0",
"/dev/scsi/sc9d15l0",
"/dev/scsi/sc10d1l0", "/dev/scsi/sc10d2l0",
"/dev/scsi/sc10d3l0", "/dev/scsi/sc10d4l0",
"/dev/scsi/sc10d5l0", "/dev/scsi/sc10d6l0",
"/dev/scsi/sc10d7l0", "/dev/scsi/sc10d8l0",
"/dev/scsi/sc10d9l0", "/dev/scsi/sc10d10l0",
"/dev/scsi/sc10d11l0", "/dev/scsi/sc10d12l0",
"/dev/scsi/sc10d13l0", "/dev/scsi/sc10d14l0",
"/dev/scsi/sc10d15l0",
"/dev/scsi/sc11d1l0", "/dev/scsi/sc11d2l0",
"/dev/scsi/sc11d3l0", "/dev/scsi/sc11d4l0",
"/dev/scsi/sc11d5l0", "/dev/scsi/sc11d6l0",
"/dev/scsi/sc11d7l0", "/dev/scsi/sc11d8l0",
"/dev/scsi/sc11d9l0", "/dev/scsi/sc11d10l0",
"/dev/scsi/sc11d11l0", "/dev/scsi/sc11d12l0",
"/dev/scsi/sc11d13l0", "/dev/scsi/sc11d14l0",
"/dev/scsi/sc11d15l0",
"/dev/scsi/sc12d1l0", "/dev/scsi/sc12d2l0",
"/dev/scsi/sc12d3l0", "/dev/scsi/sc12d4l0",
"/dev/scsi/sc12d5l0", "/dev/scsi/sc12d6l0",
"/dev/scsi/sc12d7l0", "/dev/scsi/sc12d8l0",
"/dev/scsi/sc12d9l0", "/dev/scsi/sc12d10l0",
"/dev/scsi/sc12d11l0", "/dev/scsi/sc12d12l0",
"/dev/scsi/sc12d13l0", "/dev/scsi/sc12d14l0",
"/dev/scsi/sc12d15l0",
"/dev/scsi/sc13d1l0", "/dev/scsi/sc13d2l0",
"/dev/scsi/sc13d3l0", "/dev/scsi/sc13d4l0",
"/dev/scsi/sc13d5l0", "/dev/scsi/sc13d6l0",
"/dev/scsi/sc13d7l0", "/dev/scsi/sc13d8l0",
"/dev/scsi/sc13d9l0", "/dev/scsi/sc13d10l0",
"/dev/scsi/sc13d11l0", "/dev/scsi/sc13d12l0",
"/dev/scsi/sc13d13l0", "/dev/scsi/sc13d14l0",
"/dev/scsi/sc13d15l0",
"/dev/scsi/sc14d1l0", "/dev/scsi/sc14d2l0",
"/dev/scsi/sc14d3l0", "/dev/scsi/sc14d4l0",
"/dev/scsi/sc14d5l0", "/dev/scsi/sc14d6l0",
"/dev/scsi/sc14d7l0", "/dev/scsi/sc14d8l0",
"/dev/scsi/sc14d9l0", "/dev/scsi/sc14d10l0",
"/dev/scsi/sc14d11l0", "/dev/scsi/sc14d12l0",
"/dev/scsi/sc14d13l0", "/dev/scsi/sc14d14l0",
"/dev/scsi/sc14d15l0",
"/dev/scsi/sc15d1l0", "/dev/scsi/sc15d2l0",
"/dev/scsi/sc15d3l0", "/dev/scsi/sc15d4l0",
"/dev/scsi/sc15d5l0", "/dev/scsi/sc15d6l0",
"/dev/scsi/sc15d7l0", "/dev/scsi/sc15d8l0",
"/dev/scsi/sc15d9l0", "/dev/scsi/sc15d10l0",
"/dev/scsi/sc15d11l0", "/dev/scsi/sc15d12l0",
"/dev/scsi/sc15d13l0", "/dev/scsi/sc15d14l0",
"/dev/scsi/sc15d15l0",
#elif defined(__EMX__)
"b0t0l0", "b0t1l0", "b0t2l0", "b0t3l0",
"b0t4l0", "b0t5l0", "b0t6l0", "b0t7l0",
"b1t0l0", "b1t1l0", "b1t2l0", "b1t3l0",
"b1t4l0", "b1t5l0", "b1t6l0", "b1t7l0",
"b2t0l0", "b2t1l0", "b2t2l0", "b2t3l0",
"b2t4l0", "b2t5l0", "b2t6l0", "b2t7l0",
"b3t0l0", "b3t1l0", "b3t2l0", "b3t3l0",
"b3t4l0", "b3t5l0", "b3t6l0", "b3t7l0",
#elif defined(__linux__)
"/dev/scanner",
"/dev/sg0", "/dev/sg1", "/dev/sg2", "/dev/sg3",
"/dev/sg4", "/dev/sg5", "/dev/sg6", "/dev/sg7",
"/dev/sg8", "/dev/sg9",
"/dev/sga", "/dev/sgb", "/dev/sgc", "/dev/sgd",
"/dev/sge", "/dev/sgf", "/dev/sgg", "/dev/sgh",
"/dev/sgi", "/dev/sgj", "/dev/sgk", "/dev/sgl",
"/dev/sgm", "/dev/sgn", "/dev/sgo", "/dev/sgp",
"/dev/sgq", "/dev/sgr", "/dev/sgs", "/dev/sgt",
"/dev/sgu", "/dev/sgv", "/dev/sgw", "/dev/sgx",
"/dev/sgy", "/dev/sgz",
#elif defined(__NeXT__)
"/dev/sg0a", "/dev/sg0b", "/dev/sg0c", "/dev/sg0d",
"/dev/sg0e", "/dev/sg0f", "/dev/sg0g", "/dev/sg0h",
"/dev/sg1a", "/dev/sg1b", "/dev/sg1c", "/dev/sg1d",
"/dev/sg1e", "/dev/sg1f", "/dev/sg1g", "/dev/sg1h",
"/dev/sg2a", "/dev/sg2b", "/dev/sg2c", "/dev/sg2d",
"/dev/sg2e", "/dev/sg2f", "/dev/sg2g", "/dev/sg2h",
"/dev/sg3a", "/dev/sg3b", "/dev/sg3c", "/dev/sg3d",
"/dev/sg3e", "/dev/sg3f", "/dev/sg3g", "/dev/sg3h",
#elif defined(_AIX)
"/dev/scanner",
"/dev/gsc0", "/dev/gsc1", "/dev/gsc2", "/dev/gsc3",
"/dev/gsc4", "/dev/gsc5", "/dev/gsc6", "/dev/gsc7",
"/dev/gsc8", "/dev/gsc9", "/dev/gsc10", "/dev/gsc11",
"/dev/gsc12", "/dev/gsc13", "/dev/gsc14", "/dev/gsc15",
#elif defined(__sun)
"/dev/scg0a", "/dev/scg0b", "/dev/scg0c", "/dev/scg0d",
"/dev/scg0e", "/dev/scg0f", "/dev/scg0g",
"/dev/scg1a", "/dev/scg1b", "/dev/scg1c", "/dev/scg1d",
"/dev/scg1e", "/dev/scg1f", "/dev/scg1g",
"/dev/scg2a", "/dev/scg2b", "/dev/scg2c", "/dev/scg2d",
"/dev/scg2e", "/dev/scg2f", "/dev/scg2g",
"/dev/sg/0", "/dev/sg/1", "/dev/sg/2", "/dev/sg/3",
"/dev/sg/4", "/dev/sg/5", "/dev/sg/6",
"/dev/scsi/scanner/", "/dev/scsi/processor/",
#elif defined(HAVE_CAMLIB_H)
"/dev/scanner", "/dev/scanner0", "/dev/scanner1",
"/dev/pass0", "/dev/pass1", "/dev/pass2", "/dev/pass3",
"/dev/pass4", "/dev/pass5", "/dev/pass6", "/dev/pass7",
#elif defined(__FreeBSD__)
"/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4",
"/dev/uk5", "/dev/uk6",
#elif defined(__NetBSD__)
"/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4",
"/dev/uk5", "/dev/uk6",
"/dev/ss0",
#elif defined(__OpenBSD__)
"/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4",
"/dev/uk5", "/dev/uk6",
#elif defined(__hpux)
"/dev/rscsi/",
#endif
0
};
static char *usb_default_dev_list[] = {
#if defined(__linux__)
"/dev/usb/scanner",
"/dev/usb/scanner0", "/dev/usb/scanner1",
"/dev/usb/scanner2", "/dev/usb/scanner3",
"/dev/usb/scanner4", "/dev/usb/scanner5",
"/dev/usb/scanner5", "/dev/usb/scanner7",
"/dev/usb/scanner8", "/dev/usb/scanner9",
"/dev/usb/scanner10", "/dev/usb/scanner11",
"/dev/usb/scanner12", "/dev/usb/scanner13",
"/dev/usb/scanner14", "/dev/usb/scanner15",
"/dev/usbscanner",
"/dev/usbscanner0", "/dev/usbscanner1",
"/dev/usbscanner2", "/dev/usbscanner3",
"/dev/usbscanner4", "/dev/usbscanner5",
"/dev/usbscanner6", "/dev/usbscanner7",
"/dev/usbscanner8", "/dev/usbscanner9",
"/dev/usbscanner10", "/dev/usbscanner11",
"/dev/usbscanner12", "/dev/usbscanner13",
"/dev/usbscanner14", "/dev/usbscanner15",
#elif defined(__FreeBSD__)
"/dev/uscanner",
"/dev/uscanner0", "/dev/uscanner1",
"/dev/uscanner2", "/dev/uscanner3",
"/dev/uscanner4", "/dev/uscanner5",
"/dev/uscanner6", "/dev/uscanner7",
"/dev/uscanner8", "/dev/uscanner9",
"/dev/uscanner10", "/dev/uscanner11",
"/dev/uscanner12", "/dev/uscanner13",
"/dev/uscanner14", "/dev/uscanner15",
#elif defined(__OpenBSD__)
"/dev/uscanner",
"/dev/uscanner0", "/dev/uscanner1",
"/dev/uscanner2", "/dev/uscanner3",
"/dev/uscanner4", "/dev/uscanner5",
"/dev/uscanner6", "/dev/uscanner7",
"/dev/uscanner8", "/dev/uscanner9",
"/dev/uscanner10", "/dev/uscanner11",
"/dev/uscanner12", "/dev/uscanner13",
"/dev/uscanner14", "/dev/uscanner15",
#endif
0
};
dev_list = default_dev_list;
usb_dev_list = usb_default_dev_list;
}
if (verbose > 0)
printf ("\n");
if (verbose > 1)
printf ("searching for SCSI scanners:\n");
while ((dev_name = *dev_list++))
{
if (strlen (dev_name) == 0)
continue; /* Empty device names ... */
if (dev_name[strlen (dev_name) - 1] == '/')
{
/* check whole directories */
DIR *dir;
char *file_name;
dir = scan_directory (dev_name);
if (!dir)
continue;
while ((file_name = get_next_file (dev_name, dir)))
check_scsi_file (file_name);
}
else
{
/* check device files */
check_scsi_file (dev_name);
}
}
if (device_found)
{
if (verbose > 0)
printf
(" # Your SCSI scanner was detected. It may or may not be "
"supported by SANE. Try\n # scanimage -L and read the backend's "
"manpage.\n");
}
else
{
if (verbose > 0)
printf
(" # No SCSI scanners found. If you expected something different, "
"make sure that\n # you have loaded a SCSI driver for your SCSI "
"adapter.\n");
if (!check_sg ())
{
if (verbose > 0)
printf
(" # Also you need support for SCSI Generic (sg) in your "
"operating system.\n # If using Linux, try \"modprobe "
"sg\".\n");
}
}
if (verbose > 0)
printf ("\n");
device_found = SANE_FALSE;
sanei_usb_init ();
if (verbose > 1)
printf ("searching for USB scanners:\n");
while ((dev_name = *usb_dev_list++))
{
if (strlen (dev_name) == 0)
continue; /* Empty device names ... */
if (dev_name[strlen (dev_name) - 1] == '/')
{
/* check whole directories */
DIR *dir;
char *file_name;
dir = scan_directory (dev_name);
if (!dir)
continue;
while ((file_name = get_next_file (dev_name, dir)))
check_usb_file (file_name);
}
else
{
/* check device files */
check_usb_file (dev_name);
}
}
#ifdef HAVE_LIBUSB
/* Now the libusb devices */
{
struct usb_bus *bus;
struct usb_device *dev;
if (ap < argv + argc)
{
/* user-specified devices not useful for libusb */
if (verbose > 1)
printf ("ignoring libusb devices\n");
}
else
{
if (verbose > 2)
printf ("trying libusb:\n");
for (bus = usb_get_busses (); bus; bus = bus->next)
{
for (dev = bus->devices; dev; dev = dev->next)
{
check_libusb_device (dev);
} /* for (dev) */
} /* for (bus) */
} /* if (usb_dev_list == ap) */
}
#endif /* HAVE_LIBUSB */
if (device_found)
{
if (libusb_device_found)
{
if (verbose > 0)
printf
(" # Your USB scanner was (probably) detected. It "
"may or may not be supported by\n # SANE. Try scanimage "
"-L and read the backend's manpage.\n");
}
else if (verbose > 0)
printf
(" # Your USB scanner was detected. It may or may not "
"be supported by\n # SANE. Try scanimage -L and read the "
"backend's manpage.\n");
if (unknown_found && verbose > 0)
printf
(" # `UNKNOWN vendor and product' means that there seems to be a "
"scanner at this\n # device file but the vendor and product ids "
"couldn't be identified.\n # Currently identification only works "
"with Linux versions >= 2.4.8. You may\n # need to configure your "
"backend manually, see the backend's manpage.\n");
}
else
{
if (verbose > 0)
printf
(" # No USB scanners found. If you expected something different, "
"make sure that\n # you have loaded a driver for your USB host "
"controller and have installed a\n # kernel scanner module.\n");
}
if (verbose > 0)
printf ("\n # Scanners connected to the parallel port or other "
"proprietary ports can't be\n # detected by this program.\n");
if (getuid ())
if (verbose > 0)
printf
("\n # You may want to run this program as root to find all devices. "
"Once you\n # found the scanner devices, be sure to adjust access "
"permissions as\n # necessary.\n");
if (verbose > 1)
printf ("done\n");
return 0;
}