kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			1120 wiersze
		
	
	
		
			32 KiB
		
	
	
	
		
			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;
 | |
| }
 |