1141cc406Sopenharmony_ci/* sane-find-scanner.c 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 1997-2013 Oliver Rauch, Henning Meier-Geinitz, and others. 4141cc406Sopenharmony_ci 5141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 6141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 7141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 8141cc406Sopenharmony_ci License, or (at your option) any later version. 9141cc406Sopenharmony_ci 10141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 11141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13141cc406Sopenharmony_ci General Public License for more details. 14141cc406Sopenharmony_ci 15141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 16141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci */ 19141cc406Sopenharmony_ci 20141cc406Sopenharmony_ci#include "../include/sane/config.h" 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci#include <string.h> 23141cc406Sopenharmony_ci#include <stdlib.h> 24141cc406Sopenharmony_ci#include <stdio.h> 25141cc406Sopenharmony_ci#include <unistd.h> 26141cc406Sopenharmony_ci#include <sys/types.h> 27141cc406Sopenharmony_ci#include <sys/stat.h> 28141cc406Sopenharmony_ci#include <dirent.h> 29141cc406Sopenharmony_ci#include <errno.h> 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_ci#if defined (HAVE_DDK_NTDDSCSI_H) || defined (HAVE_NTDDSCSI_H) 32141cc406Sopenharmony_ci# define WIN32_SCSI 33141cc406Sopenharmony_ci# include <windows.h> 34141cc406Sopenharmony_ci# if defined (HAVE_DDK_NTDDSCSI_H) 35141cc406Sopenharmony_ci# include <ddk/scsi.h> 36141cc406Sopenharmony_ci# include <ddk/ntddscsi.h> 37141cc406Sopenharmony_ci# elif defined (HAVE_NTDDSCSI_H) 38141cc406Sopenharmony_ci# include <ntddscsi.h> 39141cc406Sopenharmony_ci# endif 40141cc406Sopenharmony_ci#endif 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci#include "../include/sane/sanei.h" 43141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h" 44141cc406Sopenharmony_ci#include "../include/sane/sanei_pa4s2.h" 45141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h" 46141cc406Sopenharmony_ci 47141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB_LEGACY 48141cc406Sopenharmony_ci#ifdef HAVE_LUSB0_USB_H 49141cc406Sopenharmony_ci#include <lusb0_usb.h> 50141cc406Sopenharmony_ci#else 51141cc406Sopenharmony_ci#include <usb.h> 52141cc406Sopenharmony_ci#endif 53141cc406Sopenharmony_ciextern char * check_usb_chip (struct usb_device *dev, int verbosity, SANE_Bool from_file); 54141cc406Sopenharmony_ci#endif 55141cc406Sopenharmony_ci 56141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB 57141cc406Sopenharmony_ci#include <libusb.h> 58141cc406Sopenharmony_ciextern char * check_usb_chip (int verbosity, 59141cc406Sopenharmony_ci struct libusb_device_descriptor desc, 60141cc406Sopenharmony_ci libusb_device_handle *hdl, 61141cc406Sopenharmony_ci struct libusb_config_descriptor *config0); 62141cc406Sopenharmony_ci#endif 63141cc406Sopenharmony_ci 64141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h" 65141cc406Sopenharmony_ci 66141cc406Sopenharmony_ci#ifndef PATH_MAX 67141cc406Sopenharmony_ci# define PATH_MAX 1024 68141cc406Sopenharmony_ci#endif 69141cc406Sopenharmony_ci 70141cc406Sopenharmony_cistatic const char *prog_name; 71141cc406Sopenharmony_cistatic int verbose = 1; 72141cc406Sopenharmony_cistatic SANE_Bool force = SANE_FALSE; 73141cc406Sopenharmony_cistatic SANE_Bool device_found = SANE_FALSE; 74141cc406Sopenharmony_cistatic SANE_Bool libusb_device_found = SANE_FALSE; 75141cc406Sopenharmony_cistatic SANE_Bool unknown_found = SANE_FALSE; 76141cc406Sopenharmony_ci 77141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB 78141cc406Sopenharmony_cilibusb_context *sfs_usb_ctx; 79141cc406Sopenharmony_ci#endif 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_citypedef struct 82141cc406Sopenharmony_ci{ 83141cc406Sopenharmony_ci unsigned char *cmd; 84141cc406Sopenharmony_ci size_t size; 85141cc406Sopenharmony_ci} 86141cc406Sopenharmony_ciscsiblk; 87141cc406Sopenharmony_ci 88141cc406Sopenharmony_ci#define INQUIRY 0x12 89141cc406Sopenharmony_ci#define set_inquiry_return_size(icb,val) icb[0x04]=val 90141cc406Sopenharmony_ci#define IN_periph_devtype_cpu 0x03 91141cc406Sopenharmony_ci#define IN_periph_devtype_scanner 0x06 92141cc406Sopenharmony_ci#define get_scsi_inquiry_vendor(in, buf) snprintf(buf, 0x08 + 1, "%.*s", \ 93141cc406Sopenharmony_ci 0x08, in + 0x08) 94141cc406Sopenharmony_ci#define get_scsi_inquiry_product(in, buf) snprintf(buf, 0x10 + 1, "%.*s", \ 95141cc406Sopenharmony_ci 0x10, in + 0x10) 96141cc406Sopenharmony_ci#define get_scsi_inquiry_version(in, buf) snprintf(buf, 0x04 + 1, "%.*s", \ 97141cc406Sopenharmony_ci 0x04, in + 0x20) 98141cc406Sopenharmony_ci#define get_scsi_inquiry_periph_devtype(in) (in[0] & 0x1f) 99141cc406Sopenharmony_ci#define get_scsi_inquiry_additional_length(in) in[0x04] 100141cc406Sopenharmony_ci#define set_scsi_inquiry_length(out,n) out[0x04]=n-5 101141cc406Sopenharmony_ci 102141cc406Sopenharmony_cistatic unsigned char inquiryC[] = { 103141cc406Sopenharmony_ci INQUIRY, 0x00, 0x00, 0x00, 0xff, 0x00 104141cc406Sopenharmony_ci}; 105141cc406Sopenharmony_cistatic scsiblk inquiry = { 106141cc406Sopenharmony_ci inquiryC, sizeof (inquiryC) 107141cc406Sopenharmony_ci}; 108141cc406Sopenharmony_ci 109141cc406Sopenharmony_cistatic void 110141cc406Sopenharmony_ciusage (char *msg) 111141cc406Sopenharmony_ci{ 112141cc406Sopenharmony_ci fprintf (stderr, "Usage: %s [-hvqf] [devname ...]\n", prog_name); 113141cc406Sopenharmony_ci fprintf (stderr, "\t-h: print this help message\n"); 114141cc406Sopenharmony_ci fprintf (stderr, "\t-v: be more verbose (can be used multiple times)\n"); 115141cc406Sopenharmony_ci fprintf (stderr, "\t-q: be quiet (print only devices, no comments)\n"); 116141cc406Sopenharmony_ci fprintf (stderr, "\t-f: force opening devname as SCSI even if it looks " 117141cc406Sopenharmony_ci "like USB\n"); 118141cc406Sopenharmony_ci fprintf (stderr, "\t-p: enable scanning for parallel port devices\n"); 119141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB_LEGACY 120141cc406Sopenharmony_ci fprintf (stderr, "\t-F file: try to detect chipset from given " 121141cc406Sopenharmony_ci "/proc/bus/usb/devices file\n"); 122141cc406Sopenharmony_ci#endif 123141cc406Sopenharmony_ci if (msg) 124141cc406Sopenharmony_ci fprintf (stderr, "\t%s\n", msg); 125141cc406Sopenharmony_ci} 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci/* if SCSI generic is optional on your OS, and there is a software test 128141cc406Sopenharmony_ci which will determine if it is included, add it here. If you are sure 129141cc406Sopenharmony_ci that SCSI generic was found, return 1. If SCSI generic is always 130141cc406Sopenharmony_ci available in your OS, return 1 */ 131141cc406Sopenharmony_ci 132141cc406Sopenharmony_cistatic int 133141cc406Sopenharmony_cicheck_sg (void) 134141cc406Sopenharmony_ci{ 135141cc406Sopenharmony_ci#if defined(__linux__) 136141cc406Sopenharmony_ci /* Assumption: /proc/devices lines are shorter than 256 characters */ 137141cc406Sopenharmony_ci char line[256], driver[256] = ""; 138141cc406Sopenharmony_ci FILE *stream; 139141cc406Sopenharmony_ci 140141cc406Sopenharmony_ci stream = fopen ("/proc/devices", "r"); 141141cc406Sopenharmony_ci /* Likely reason for failure, no /proc => probably no SG either */ 142141cc406Sopenharmony_ci if (stream == NULL) 143141cc406Sopenharmony_ci return 0; 144141cc406Sopenharmony_ci 145141cc406Sopenharmony_ci while (fgets (line, sizeof (line) - 1, stream)) 146141cc406Sopenharmony_ci { 147141cc406Sopenharmony_ci if (sscanf (line, " %*d %s\n", driver) > 0 && !strcmp (driver, "sg")) 148141cc406Sopenharmony_ci break; 149141cc406Sopenharmony_ci } 150141cc406Sopenharmony_ci fclose (stream); 151141cc406Sopenharmony_ci 152141cc406Sopenharmony_ci if (strcmp (driver, "sg")) 153141cc406Sopenharmony_ci { 154141cc406Sopenharmony_ci return 0; 155141cc406Sopenharmony_ci } 156141cc406Sopenharmony_ci else 157141cc406Sopenharmony_ci { 158141cc406Sopenharmony_ci return 1; 159141cc406Sopenharmony_ci } 160141cc406Sopenharmony_ci#endif 161141cc406Sopenharmony_ci return 1; /* Give up, and assume yes to avoid false negatives */ 162141cc406Sopenharmony_ci} 163141cc406Sopenharmony_ci 164141cc406Sopenharmony_ci/* Display a buffer in the log. Display by lines of 16 bytes. */ 165141cc406Sopenharmony_cistatic void 166141cc406Sopenharmony_cihexdump (const char *comment, unsigned char *buf, const int length) 167141cc406Sopenharmony_ci{ 168141cc406Sopenharmony_ci int i; 169141cc406Sopenharmony_ci char line[128]; 170141cc406Sopenharmony_ci char *ptr; 171141cc406Sopenharmony_ci char asc_buf[17]; 172141cc406Sopenharmony_ci char *asc_ptr; 173141cc406Sopenharmony_ci 174141cc406Sopenharmony_ci printf (" %s\n", comment); 175141cc406Sopenharmony_ci 176141cc406Sopenharmony_ci i = 0; 177141cc406Sopenharmony_ci goto start; 178141cc406Sopenharmony_ci 179141cc406Sopenharmony_ci do 180141cc406Sopenharmony_ci { 181141cc406Sopenharmony_ci if (i < length) 182141cc406Sopenharmony_ci { 183141cc406Sopenharmony_ci ptr += sprintf (ptr, " %2.2x", *buf); 184141cc406Sopenharmony_ci 185141cc406Sopenharmony_ci if (*buf >= 32 && *buf <= 127) 186141cc406Sopenharmony_ci { 187141cc406Sopenharmony_ci asc_ptr += sprintf (asc_ptr, "%c", *buf); 188141cc406Sopenharmony_ci } 189141cc406Sopenharmony_ci else 190141cc406Sopenharmony_ci { 191141cc406Sopenharmony_ci asc_ptr += sprintf (asc_ptr, "."); 192141cc406Sopenharmony_ci } 193141cc406Sopenharmony_ci } 194141cc406Sopenharmony_ci else 195141cc406Sopenharmony_ci { 196141cc406Sopenharmony_ci /* After the length; do nothing. */ 197141cc406Sopenharmony_ci ptr += sprintf (ptr, " "); 198141cc406Sopenharmony_ci } 199141cc406Sopenharmony_ci 200141cc406Sopenharmony_ci i++; 201141cc406Sopenharmony_ci buf++; 202141cc406Sopenharmony_ci 203141cc406Sopenharmony_ci if ((i % 16) == 0) 204141cc406Sopenharmony_ci { 205141cc406Sopenharmony_ci /* It's a new line */ 206141cc406Sopenharmony_ci printf (" %s %s\n", line, asc_buf); 207141cc406Sopenharmony_ci 208141cc406Sopenharmony_ci start: 209141cc406Sopenharmony_ci ptr = line; 210141cc406Sopenharmony_ci *ptr = '\0'; 211141cc406Sopenharmony_ci asc_ptr = asc_buf; 212141cc406Sopenharmony_ci *asc_ptr = '\0'; 213141cc406Sopenharmony_ci 214141cc406Sopenharmony_ci ptr += sprintf (ptr, " %3.3d:", i); 215141cc406Sopenharmony_ci } 216141cc406Sopenharmony_ci 217141cc406Sopenharmony_ci } 218141cc406Sopenharmony_ci while (i < ((length + 15) & ~15)); 219141cc406Sopenharmony_ci} 220141cc406Sopenharmony_ci 221141cc406Sopenharmony_cistatic SANE_Status 222141cc406Sopenharmony_ciscanner_do_scsi_inquiry (unsigned char *buffer, int sfd) 223141cc406Sopenharmony_ci{ 224141cc406Sopenharmony_ci size_t size; 225141cc406Sopenharmony_ci SANE_Status status; 226141cc406Sopenharmony_ci 227141cc406Sopenharmony_ci memset (buffer, '\0', 256); /* clear buffer */ 228141cc406Sopenharmony_ci 229141cc406Sopenharmony_ci size = 5; /* first get only 5 bytes to get size of 230141cc406Sopenharmony_ci inquiry_return_block */ 231141cc406Sopenharmony_ci set_inquiry_return_size (inquiry.cmd, size); 232141cc406Sopenharmony_ci status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size); 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 235141cc406Sopenharmony_ci return (status); 236141cc406Sopenharmony_ci 237141cc406Sopenharmony_ci size = get_scsi_inquiry_additional_length (buffer) + 5; 238141cc406Sopenharmony_ci 239141cc406Sopenharmony_ci /* then get inquiry with actual size */ 240141cc406Sopenharmony_ci set_inquiry_return_size (inquiry.cmd, size); 241141cc406Sopenharmony_ci status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size); 242141cc406Sopenharmony_ci 243141cc406Sopenharmony_ci return (status); 244141cc406Sopenharmony_ci} 245141cc406Sopenharmony_ci 246141cc406Sopenharmony_cistatic void 247141cc406Sopenharmony_ciscanner_identify_scsi_scanner (unsigned char *buffer, int sfd, 248141cc406Sopenharmony_ci char *devicename) 249141cc406Sopenharmony_ci{ 250141cc406Sopenharmony_ci unsigned char vendor[9]; 251141cc406Sopenharmony_ci unsigned char product[17]; 252141cc406Sopenharmony_ci unsigned char version[5]; 253141cc406Sopenharmony_ci unsigned char *pp; 254141cc406Sopenharmony_ci unsigned int devtype; 255141cc406Sopenharmony_ci SANE_Status status; 256141cc406Sopenharmony_ci static char *devtypes[] = { 257141cc406Sopenharmony_ci "disk", "tape", "printer", "processor", "CD-writer", 258141cc406Sopenharmony_ci "CD-drive", "scanner", "optical-drive", "jukebox", 259141cc406Sopenharmony_ci "communicator" 260141cc406Sopenharmony_ci }; 261141cc406Sopenharmony_ci status = scanner_do_scsi_inquiry (buffer, sfd); 262141cc406Sopenharmony_ci if (status != SANE_STATUS_GOOD) 263141cc406Sopenharmony_ci { 264141cc406Sopenharmony_ci if (verbose > 1) 265141cc406Sopenharmony_ci printf ("inquiry for device %s failed (%s)\n", 266141cc406Sopenharmony_ci devicename, sane_strstatus (status)); 267141cc406Sopenharmony_ci return; 268141cc406Sopenharmony_ci } 269141cc406Sopenharmony_ci 270141cc406Sopenharmony_ci if (verbose > 2) 271141cc406Sopenharmony_ci hexdump ("Inquiry for device:", buffer, 272141cc406Sopenharmony_ci get_scsi_inquiry_additional_length (buffer) + 5); 273141cc406Sopenharmony_ci 274141cc406Sopenharmony_ci devtype = get_scsi_inquiry_periph_devtype (buffer); 275141cc406Sopenharmony_ci if (verbose <= 1 && devtype != IN_periph_devtype_scanner 276141cc406Sopenharmony_ci /* old HP scanners use the CPU id ... */ 277141cc406Sopenharmony_ci && devtype != IN_periph_devtype_cpu) 278141cc406Sopenharmony_ci return; /* no, continue searching */ 279141cc406Sopenharmony_ci 280141cc406Sopenharmony_ci get_scsi_inquiry_vendor ((char *) buffer, (char *) vendor); 281141cc406Sopenharmony_ci get_scsi_inquiry_product ((char *) buffer, (char *) product); 282141cc406Sopenharmony_ci get_scsi_inquiry_version ((char *) buffer, (char *) version); 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci pp = &vendor[7]; 285141cc406Sopenharmony_ci vendor[8] = '\0'; 286141cc406Sopenharmony_ci while (pp >= vendor && (*pp == ' ' || *pp >= 127)) 287141cc406Sopenharmony_ci *pp-- = '\0'; 288141cc406Sopenharmony_ci 289141cc406Sopenharmony_ci pp = &product[15]; 290141cc406Sopenharmony_ci product[16] = '\0'; 291141cc406Sopenharmony_ci while (pp >= product && (*pp == ' ' || *pp >= 127)) 292141cc406Sopenharmony_ci *pp-- = '\0'; 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci pp = &version[3]; 295141cc406Sopenharmony_ci version[4] = '\0'; 296141cc406Sopenharmony_ci while (pp >= version && (*pp == ' ' || *(pp - 1) >= 127)) 297141cc406Sopenharmony_ci *pp-- = '\0'; 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci device_found = SANE_TRUE; 300141cc406Sopenharmony_ci printf ("found SCSI %s \"%s %s %s\" at %s\n", 301141cc406Sopenharmony_ci devtype < NELEMS (devtypes) ? devtypes[devtype] : "unknown device", 302141cc406Sopenharmony_ci vendor, product, version, devicename); 303141cc406Sopenharmony_ci return; 304141cc406Sopenharmony_ci} 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_cistatic void 307141cc406Sopenharmony_cicheck_scsi_file (char *file_name) 308141cc406Sopenharmony_ci{ 309141cc406Sopenharmony_ci int result; 310141cc406Sopenharmony_ci int sfd; 311141cc406Sopenharmony_ci unsigned char buffer[16384]; 312141cc406Sopenharmony_ci 313141cc406Sopenharmony_ci if (strstr (file_name, "usb") 314141cc406Sopenharmony_ci || strstr (file_name, "uscanner") || strstr (file_name, "ugen")) 315141cc406Sopenharmony_ci { 316141cc406Sopenharmony_ci if (force) 317141cc406Sopenharmony_ci { 318141cc406Sopenharmony_ci if (verbose > 1) 319141cc406Sopenharmony_ci printf ("checking %s even though it looks like a USB device...", 320141cc406Sopenharmony_ci file_name); 321141cc406Sopenharmony_ci } 322141cc406Sopenharmony_ci else 323141cc406Sopenharmony_ci { 324141cc406Sopenharmony_ci if (verbose > 1) 325141cc406Sopenharmony_ci printf ("ignored %s (not a SCSI device)\n", file_name); 326141cc406Sopenharmony_ci return; 327141cc406Sopenharmony_ci } 328141cc406Sopenharmony_ci } 329141cc406Sopenharmony_ci else if (verbose > 1) 330141cc406Sopenharmony_ci printf ("checking %s...", file_name); 331141cc406Sopenharmony_ci 332141cc406Sopenharmony_ci result = sanei_scsi_open (file_name, &sfd, NULL, NULL); 333141cc406Sopenharmony_ci 334141cc406Sopenharmony_ci if (verbose > 1) 335141cc406Sopenharmony_ci { 336141cc406Sopenharmony_ci if (result != 0) 337141cc406Sopenharmony_ci printf (" failed to open (%s)\n", sane_strstatus (result)); 338141cc406Sopenharmony_ci else 339141cc406Sopenharmony_ci printf (" open ok\n"); 340141cc406Sopenharmony_ci } 341141cc406Sopenharmony_ci 342141cc406Sopenharmony_ci if (result == SANE_STATUS_GOOD) 343141cc406Sopenharmony_ci { 344141cc406Sopenharmony_ci scanner_identify_scsi_scanner (buffer, sfd, file_name); 345141cc406Sopenharmony_ci sanei_scsi_close (sfd); 346141cc406Sopenharmony_ci } 347141cc406Sopenharmony_ci return; 348141cc406Sopenharmony_ci} 349141cc406Sopenharmony_ci 350141cc406Sopenharmony_cistatic void 351141cc406Sopenharmony_cicheck_usb_file (char *file_name) 352141cc406Sopenharmony_ci{ 353141cc406Sopenharmony_ci SANE_Status result; 354141cc406Sopenharmony_ci SANE_Word vendor, product; 355141cc406Sopenharmony_ci SANE_Int fd; 356141cc406Sopenharmony_ci 357141cc406Sopenharmony_ci if (!strstr (file_name, "usb") 358141cc406Sopenharmony_ci && !strstr (file_name, "uscanner") && !strstr (file_name, "ugen")) 359141cc406Sopenharmony_ci { 360141cc406Sopenharmony_ci if (force) 361141cc406Sopenharmony_ci { 362141cc406Sopenharmony_ci if (verbose > 1) 363141cc406Sopenharmony_ci printf ("checking %s even though doesn't look like a " 364141cc406Sopenharmony_ci "USB device...", file_name); 365141cc406Sopenharmony_ci } 366141cc406Sopenharmony_ci else 367141cc406Sopenharmony_ci { 368141cc406Sopenharmony_ci if (verbose > 1) 369141cc406Sopenharmony_ci printf ("ignored %s (not a USB device)\n", file_name); 370141cc406Sopenharmony_ci return; 371141cc406Sopenharmony_ci } 372141cc406Sopenharmony_ci } 373141cc406Sopenharmony_ci else if (verbose > 1) 374141cc406Sopenharmony_ci printf ("checking %s...", file_name); 375141cc406Sopenharmony_ci 376141cc406Sopenharmony_ci result = sanei_usb_open (file_name, &fd); 377141cc406Sopenharmony_ci 378141cc406Sopenharmony_ci if (result != SANE_STATUS_GOOD) 379141cc406Sopenharmony_ci { 380141cc406Sopenharmony_ci if (verbose > 1) 381141cc406Sopenharmony_ci printf (" failed to open (%s)\n", sane_strstatus (result)); 382141cc406Sopenharmony_ci } 383141cc406Sopenharmony_ci else 384141cc406Sopenharmony_ci { 385141cc406Sopenharmony_ci result = sanei_usb_get_vendor_product (fd, &vendor, &product); 386141cc406Sopenharmony_ci if (result == SANE_STATUS_GOOD) 387141cc406Sopenharmony_ci { 388141cc406Sopenharmony_ci if (verbose > 1) 389141cc406Sopenharmony_ci printf (" open ok, vendor and product ids were identified\n"); 390141cc406Sopenharmony_ci printf ("found possible USB scanner (vendor=0x%04x, " 391141cc406Sopenharmony_ci "product=0x%04x) at %s\n", vendor, product, file_name); 392141cc406Sopenharmony_ci } 393141cc406Sopenharmony_ci else 394141cc406Sopenharmony_ci { 395141cc406Sopenharmony_ci if (verbose > 1) 396141cc406Sopenharmony_ci printf (" open ok, but vendor and product could NOT be " 397141cc406Sopenharmony_ci "identified\n"); 398141cc406Sopenharmony_ci printf ("found possible USB scanner (UNKNOWN vendor and " 399141cc406Sopenharmony_ci "product) at %s\n", file_name); 400141cc406Sopenharmony_ci unknown_found = SANE_TRUE; 401141cc406Sopenharmony_ci } 402141cc406Sopenharmony_ci device_found = SANE_TRUE; 403141cc406Sopenharmony_ci sanei_usb_close (fd); 404141cc406Sopenharmony_ci } 405141cc406Sopenharmony_ci} 406141cc406Sopenharmony_ci 407141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB_LEGACY 408141cc406Sopenharmony_ci 409141cc406Sopenharmony_cistatic char * 410141cc406Sopenharmony_ciget_libusb_string_descriptor (struct usb_device *dev, int index) 411141cc406Sopenharmony_ci{ 412141cc406Sopenharmony_ci usb_dev_handle *handle; 413141cc406Sopenharmony_ci char *buffer, short_buffer[2]; 414141cc406Sopenharmony_ci struct usb_string_descriptor *sd; 415141cc406Sopenharmony_ci int size = 2; 416141cc406Sopenharmony_ci int i; 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci if (!index) 419141cc406Sopenharmony_ci return 0; 420141cc406Sopenharmony_ci 421141cc406Sopenharmony_ci handle = usb_open (dev); 422141cc406Sopenharmony_ci if (!handle) 423141cc406Sopenharmony_ci return 0; 424141cc406Sopenharmony_ci 425141cc406Sopenharmony_ci sd = (struct usb_string_descriptor *) short_buffer; 426141cc406Sopenharmony_ci 427141cc406Sopenharmony_ci if (usb_control_msg (handle, 428141cc406Sopenharmony_ci USB_ENDPOINT_IN + USB_TYPE_STANDARD + USB_RECIP_DEVICE, 429141cc406Sopenharmony_ci USB_REQ_GET_DESCRIPTOR, 430141cc406Sopenharmony_ci (USB_DT_STRING << 8) + index, 0, short_buffer, 431141cc406Sopenharmony_ci size, 1000) < 0) 432141cc406Sopenharmony_ci { 433141cc406Sopenharmony_ci usb_close (handle); 434141cc406Sopenharmony_ci return 0; 435141cc406Sopenharmony_ci } 436141cc406Sopenharmony_ci 437141cc406Sopenharmony_ci if (sd->bLength < 2 438141cc406Sopenharmony_ci || sd->bDescriptorType != USB_DT_STRING) 439141cc406Sopenharmony_ci { 440141cc406Sopenharmony_ci usb_close (handle); 441141cc406Sopenharmony_ci return 0; 442141cc406Sopenharmony_ci } 443141cc406Sopenharmony_ci 444141cc406Sopenharmony_ci size = sd->bLength; 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ci buffer = calloc (1, size + 1); 447141cc406Sopenharmony_ci if (!buffer) 448141cc406Sopenharmony_ci return 0; 449141cc406Sopenharmony_ci 450141cc406Sopenharmony_ci sd = (struct usb_string_descriptor *) buffer; 451141cc406Sopenharmony_ci 452141cc406Sopenharmony_ci if (usb_control_msg (handle, 453141cc406Sopenharmony_ci USB_ENDPOINT_IN + USB_TYPE_STANDARD + USB_RECIP_DEVICE, 454141cc406Sopenharmony_ci USB_REQ_GET_DESCRIPTOR, 455141cc406Sopenharmony_ci (USB_DT_STRING << 8) + index, 0, buffer, 456141cc406Sopenharmony_ci size, 1000) < 0) 457141cc406Sopenharmony_ci { 458141cc406Sopenharmony_ci usb_close (handle); 459141cc406Sopenharmony_ci free (buffer); 460141cc406Sopenharmony_ci return 0; 461141cc406Sopenharmony_ci } 462141cc406Sopenharmony_ci 463141cc406Sopenharmony_ci if (sd->bLength < 2 || sd->bLength > size 464141cc406Sopenharmony_ci || sd->bDescriptorType != USB_DT_STRING) 465141cc406Sopenharmony_ci { 466141cc406Sopenharmony_ci usb_close (handle); 467141cc406Sopenharmony_ci free (buffer); 468141cc406Sopenharmony_ci return 0; 469141cc406Sopenharmony_ci } 470141cc406Sopenharmony_ci size = sd->bLength - 2; 471141cc406Sopenharmony_ci for (i = 0; i < (size / 2); i++) 472141cc406Sopenharmony_ci buffer[i] = buffer[2 + 2 * i]; 473141cc406Sopenharmony_ci buffer[i] = 0; 474141cc406Sopenharmony_ci 475141cc406Sopenharmony_ci usb_close (handle); 476141cc406Sopenharmony_ci return buffer; 477141cc406Sopenharmony_ci} 478141cc406Sopenharmony_ci 479141cc406Sopenharmony_cistatic char * 480141cc406Sopenharmony_ciget_libusb_vendor (struct usb_device *dev) 481141cc406Sopenharmony_ci{ 482141cc406Sopenharmony_ci return get_libusb_string_descriptor (dev, dev->descriptor.iManufacturer); 483141cc406Sopenharmony_ci} 484141cc406Sopenharmony_ci 485141cc406Sopenharmony_cistatic char * 486141cc406Sopenharmony_ciget_libusb_product (struct usb_device *dev) 487141cc406Sopenharmony_ci{ 488141cc406Sopenharmony_ci return get_libusb_string_descriptor (dev, dev->descriptor.iProduct); 489141cc406Sopenharmony_ci} 490141cc406Sopenharmony_ci 491141cc406Sopenharmony_cistatic void 492141cc406Sopenharmony_cicheck_libusb_device (struct usb_device *dev, SANE_Bool from_file) 493141cc406Sopenharmony_ci{ 494141cc406Sopenharmony_ci int is_scanner = 0; 495141cc406Sopenharmony_ci char *vendor; 496141cc406Sopenharmony_ci char *product; 497141cc406Sopenharmony_ci int interface_nr; 498141cc406Sopenharmony_ci 499141cc406Sopenharmony_ci if (!dev->config) 500141cc406Sopenharmony_ci { 501141cc406Sopenharmony_ci if (verbose > 1) 502141cc406Sopenharmony_ci printf ("device 0x%04x/0x%04x is not configured\n", 503141cc406Sopenharmony_ci dev->descriptor.idVendor, dev->descriptor.idProduct); 504141cc406Sopenharmony_ci return; 505141cc406Sopenharmony_ci } 506141cc406Sopenharmony_ci 507141cc406Sopenharmony_ci vendor = get_libusb_vendor (dev); 508141cc406Sopenharmony_ci product = get_libusb_product (dev); 509141cc406Sopenharmony_ci 510141cc406Sopenharmony_ci if (verbose > 2) 511141cc406Sopenharmony_ci { 512141cc406Sopenharmony_ci /* print everything we know about the device */ 513141cc406Sopenharmony_ci char *buf; 514141cc406Sopenharmony_ci int config_nr; 515141cc406Sopenharmony_ci struct usb_device_descriptor *d = &dev->descriptor; 516141cc406Sopenharmony_ci 517141cc406Sopenharmony_ci printf ("\n"); 518141cc406Sopenharmony_ci printf ("<device descriptor of 0x%04x/0x%04x at %s:%s", 519141cc406Sopenharmony_ci d->idVendor, d->idProduct, dev->bus->dirname, dev->filename); 520141cc406Sopenharmony_ci if (vendor || product) 521141cc406Sopenharmony_ci { 522141cc406Sopenharmony_ci printf (" (%s%s%s)", vendor ? vendor : "", 523141cc406Sopenharmony_ci (vendor && product) ? " " : "", product ? product : ""); 524141cc406Sopenharmony_ci } 525141cc406Sopenharmony_ci printf (">\n"); 526141cc406Sopenharmony_ci printf ("bLength %d\n", d->bLength); 527141cc406Sopenharmony_ci printf ("bDescriptorType %d\n", d->bDescriptorType); 528141cc406Sopenharmony_ci printf ("bcdUSB %d.%d%d\n", d->bcdUSB >> 8, 529141cc406Sopenharmony_ci (d->bcdUSB >> 4) & 15, d->bcdUSB & 15); 530141cc406Sopenharmony_ci printf ("bDeviceClass %d\n", d->bDeviceClass); 531141cc406Sopenharmony_ci printf ("bDeviceSubClass %d\n", d->bDeviceSubClass); 532141cc406Sopenharmony_ci printf ("bDeviceProtocol %d\n", d->bDeviceProtocol); 533141cc406Sopenharmony_ci printf ("bMaxPacketSize0 %d\n", d->bMaxPacketSize0); 534141cc406Sopenharmony_ci printf ("idVendor 0x%04X\n", d->idVendor); 535141cc406Sopenharmony_ci printf ("idProduct 0x%04X\n", d->idProduct); 536141cc406Sopenharmony_ci printf ("bcdDevice %d.%d%d\n", d->bcdDevice >> 8, 537141cc406Sopenharmony_ci (d->bcdDevice >> 4) & 15, d->bcdDevice & 15); 538141cc406Sopenharmony_ci printf ("iManufacturer %d (%s)\n", d->iManufacturer, 539141cc406Sopenharmony_ci (vendor) ? vendor : ""); 540141cc406Sopenharmony_ci printf ("iProduct %d (%s)\n", d->iProduct, 541141cc406Sopenharmony_ci (product) ? product : ""); 542141cc406Sopenharmony_ci 543141cc406Sopenharmony_ci buf = get_libusb_string_descriptor (dev, d->iSerialNumber); 544141cc406Sopenharmony_ci printf ("iSerialNumber %d (%s)\n", d->iSerialNumber, 545141cc406Sopenharmony_ci (buf) ? buf : ""); 546141cc406Sopenharmony_ci if (buf) 547141cc406Sopenharmony_ci free (buf); 548141cc406Sopenharmony_ci printf ("bNumConfigurations %d\n", d->bNumConfigurations); 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci for (config_nr = 0; config_nr < d->bNumConfigurations; config_nr++) 551141cc406Sopenharmony_ci { 552141cc406Sopenharmony_ci struct usb_config_descriptor *c = &dev->config[config_nr]; 553141cc406Sopenharmony_ci int interface_nr; 554141cc406Sopenharmony_ci 555141cc406Sopenharmony_ci printf (" <configuration %d>\n", config_nr); 556141cc406Sopenharmony_ci printf (" bLength %d\n", c->bLength); 557141cc406Sopenharmony_ci printf (" bDescriptorType %d\n", c->bDescriptorType); 558141cc406Sopenharmony_ci printf (" wTotalLength %d\n", c->wTotalLength); 559141cc406Sopenharmony_ci printf (" bNumInterfaces %d\n", c->bNumInterfaces); 560141cc406Sopenharmony_ci printf (" bConfigurationValue %d\n", c->bConfigurationValue); 561141cc406Sopenharmony_ci buf = get_libusb_string_descriptor (dev, c->iConfiguration); 562141cc406Sopenharmony_ci printf (" iConfiguration %d (%s)\n", c->iConfiguration, 563141cc406Sopenharmony_ci (buf) ? buf : ""); 564141cc406Sopenharmony_ci if (buf) 565141cc406Sopenharmony_ci free (buf); 566141cc406Sopenharmony_ci printf (" bmAttributes %d (%s%s)\n", c->bmAttributes, 567141cc406Sopenharmony_ci c->bmAttributes & 64 ? "Self-powered" : "", 568141cc406Sopenharmony_ci c->bmAttributes & 32 ? "Remote Wakeup" : ""); 569141cc406Sopenharmony_ci printf (" MaxPower %d mA\n", c->MaxPower * 2); 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci for (interface_nr = 0; interface_nr < c->bNumInterfaces; 572141cc406Sopenharmony_ci interface_nr++) 573141cc406Sopenharmony_ci { 574141cc406Sopenharmony_ci struct usb_interface *interface = &c->interface[interface_nr]; 575141cc406Sopenharmony_ci int alt_setting_nr; 576141cc406Sopenharmony_ci 577141cc406Sopenharmony_ci printf (" <interface %d>\n", interface_nr); 578141cc406Sopenharmony_ci for (alt_setting_nr = 0; 579141cc406Sopenharmony_ci alt_setting_nr < interface->num_altsetting; 580141cc406Sopenharmony_ci alt_setting_nr++) 581141cc406Sopenharmony_ci { 582141cc406Sopenharmony_ci struct usb_interface_descriptor *i 583141cc406Sopenharmony_ci = &interface->altsetting[alt_setting_nr]; 584141cc406Sopenharmony_ci int ep_nr; 585141cc406Sopenharmony_ci printf (" <altsetting %d>\n", alt_setting_nr); 586141cc406Sopenharmony_ci printf (" bLength %d\n", i->bLength); 587141cc406Sopenharmony_ci printf (" bDescriptorType %d\n", i->bDescriptorType); 588141cc406Sopenharmony_ci printf (" bInterfaceNumber %d\n", i->bInterfaceNumber); 589141cc406Sopenharmony_ci printf (" bAlternateSetting %d\n", i->bAlternateSetting); 590141cc406Sopenharmony_ci printf (" bNumEndpoints %d\n", i->bNumEndpoints); 591141cc406Sopenharmony_ci printf (" bInterfaceClass %d\n", i->bInterfaceClass); 592141cc406Sopenharmony_ci printf (" bInterfaceSubClass %d\n", 593141cc406Sopenharmony_ci i->bInterfaceSubClass); 594141cc406Sopenharmony_ci printf (" bInterfaceProtocol %d\n", 595141cc406Sopenharmony_ci i->bInterfaceProtocol); 596141cc406Sopenharmony_ci buf = get_libusb_string_descriptor (dev, i->iInterface); 597141cc406Sopenharmony_ci printf (" iInterface %d (%s)\n", i->iInterface, 598141cc406Sopenharmony_ci (buf) ? buf : ""); 599141cc406Sopenharmony_ci if (buf) 600141cc406Sopenharmony_ci free (buf); 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci for (ep_nr = 0; ep_nr < i->bNumEndpoints; ep_nr++) 603141cc406Sopenharmony_ci { 604141cc406Sopenharmony_ci struct usb_endpoint_descriptor *e = &i->endpoint[ep_nr]; 605141cc406Sopenharmony_ci char *ep_type; 606141cc406Sopenharmony_ci 607141cc406Sopenharmony_ci switch (e->bmAttributes & USB_ENDPOINT_TYPE_MASK) 608141cc406Sopenharmony_ci { 609141cc406Sopenharmony_ci case USB_ENDPOINT_TYPE_CONTROL: 610141cc406Sopenharmony_ci ep_type = "control"; 611141cc406Sopenharmony_ci break; 612141cc406Sopenharmony_ci case USB_ENDPOINT_TYPE_ISOCHRONOUS: 613141cc406Sopenharmony_ci ep_type = "isochronous"; 614141cc406Sopenharmony_ci break; 615141cc406Sopenharmony_ci case USB_ENDPOINT_TYPE_BULK: 616141cc406Sopenharmony_ci ep_type = "bulk"; 617141cc406Sopenharmony_ci break; 618141cc406Sopenharmony_ci case USB_ENDPOINT_TYPE_INTERRUPT: 619141cc406Sopenharmony_ci ep_type = "interrupt"; 620141cc406Sopenharmony_ci break; 621141cc406Sopenharmony_ci default: 622141cc406Sopenharmony_ci ep_type = "unknown"; 623141cc406Sopenharmony_ci break; 624141cc406Sopenharmony_ci } 625141cc406Sopenharmony_ci printf (" <endpoint %d>\n", ep_nr); 626141cc406Sopenharmony_ci printf (" bLength %d\n", e->bLength); 627141cc406Sopenharmony_ci printf (" bDescriptorType %d\n", 628141cc406Sopenharmony_ci e->bDescriptorType); 629141cc406Sopenharmony_ci printf (" bEndpointAddress 0x%02X (%s 0x%02X)\n", 630141cc406Sopenharmony_ci e->bEndpointAddress, 631141cc406Sopenharmony_ci e->bEndpointAddress & USB_ENDPOINT_DIR_MASK ? 632141cc406Sopenharmony_ci "in" : "out", 633141cc406Sopenharmony_ci e-> 634141cc406Sopenharmony_ci bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK); 635141cc406Sopenharmony_ci printf (" bmAttributes %d (%s)\n", 636141cc406Sopenharmony_ci e->bmAttributes, ep_type); 637141cc406Sopenharmony_ci printf (" wMaxPacketSize %d\n", 638141cc406Sopenharmony_ci e->wMaxPacketSize); 639141cc406Sopenharmony_ci printf (" bInterval %d ms\n", e->bInterval); 640141cc406Sopenharmony_ci printf (" bRefresh %d\n", e->bRefresh); 641141cc406Sopenharmony_ci printf (" bSynchAddress %d\n", e->bSynchAddress); 642141cc406Sopenharmony_ci } 643141cc406Sopenharmony_ci } 644141cc406Sopenharmony_ci } 645141cc406Sopenharmony_ci } 646141cc406Sopenharmony_ci 647141cc406Sopenharmony_ci } 648141cc406Sopenharmony_ci 649141cc406Sopenharmony_ci /* Some heuristics, which device may be a scanner */ 650141cc406Sopenharmony_ci if (dev->descriptor.idVendor == 0) /* hub */ 651141cc406Sopenharmony_ci --is_scanner; 652141cc406Sopenharmony_ci if (dev->descriptor.idProduct == 0) /* hub */ 653141cc406Sopenharmony_ci --is_scanner; 654141cc406Sopenharmony_ci 655141cc406Sopenharmony_ci for (interface_nr = 0; interface_nr < dev->config[0].bNumInterfaces && is_scanner <= 0; interface_nr++) 656141cc406Sopenharmony_ci { 657141cc406Sopenharmony_ci switch (dev->descriptor.bDeviceClass) 658141cc406Sopenharmony_ci { 659141cc406Sopenharmony_ci case USB_CLASS_VENDOR_SPEC: 660141cc406Sopenharmony_ci ++is_scanner; 661141cc406Sopenharmony_ci break; 662141cc406Sopenharmony_ci case USB_CLASS_PER_INTERFACE: 663141cc406Sopenharmony_ci if (dev->config[0].interface[interface_nr].num_altsetting == 0 || 664141cc406Sopenharmony_ci !dev->config[0].interface[interface_nr].altsetting) 665141cc406Sopenharmony_ci break; 666141cc406Sopenharmony_ci switch (dev->config[0].interface[interface_nr].altsetting[0].bInterfaceClass) 667141cc406Sopenharmony_ci { 668141cc406Sopenharmony_ci case USB_CLASS_VENDOR_SPEC: 669141cc406Sopenharmony_ci case USB_CLASS_PER_INTERFACE: 670141cc406Sopenharmony_ci case 16: /* data? */ 671141cc406Sopenharmony_ci ++is_scanner; 672141cc406Sopenharmony_ci break; 673141cc406Sopenharmony_ci } 674141cc406Sopenharmony_ci break; 675141cc406Sopenharmony_ci } 676141cc406Sopenharmony_ci } 677141cc406Sopenharmony_ci 678141cc406Sopenharmony_ci if (is_scanner > 0) 679141cc406Sopenharmony_ci { 680141cc406Sopenharmony_ci char * chipset = check_usb_chip (dev, verbose, from_file); 681141cc406Sopenharmony_ci 682141cc406Sopenharmony_ci printf ("found possible USB scanner (vendor=0x%04x", 683141cc406Sopenharmony_ci dev->descriptor.idVendor); 684141cc406Sopenharmony_ci if (vendor) 685141cc406Sopenharmony_ci printf (" [%s]", vendor); 686141cc406Sopenharmony_ci printf (", product=0x%04x", dev->descriptor.idProduct); 687141cc406Sopenharmony_ci if (product) 688141cc406Sopenharmony_ci printf (" [%s]", product); 689141cc406Sopenharmony_ci if (chipset) 690141cc406Sopenharmony_ci printf (", chip=%s", chipset); 691141cc406Sopenharmony_ci if (from_file) 692141cc406Sopenharmony_ci printf (")\n"); 693141cc406Sopenharmony_ci else 694141cc406Sopenharmony_ci printf (") at libusb:%s:%s\n", dev->bus->dirname, dev->filename); 695141cc406Sopenharmony_ci 696141cc406Sopenharmony_ci libusb_device_found = SANE_TRUE; 697141cc406Sopenharmony_ci device_found = SANE_TRUE; 698141cc406Sopenharmony_ci } 699141cc406Sopenharmony_ci 700141cc406Sopenharmony_ci if (vendor) 701141cc406Sopenharmony_ci free (vendor); 702141cc406Sopenharmony_ci 703141cc406Sopenharmony_ci if (product) 704141cc406Sopenharmony_ci free (product); 705141cc406Sopenharmony_ci} 706141cc406Sopenharmony_ci#endif /* HAVE_LIBUSB_LEGACY */ 707141cc406Sopenharmony_ci 708141cc406Sopenharmony_ci 709141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB 710141cc406Sopenharmony_cistatic char * 711141cc406Sopenharmony_cisfs_libusb_strerror (int errcode) 712141cc406Sopenharmony_ci{ 713141cc406Sopenharmony_ci /* Error codes & descriptions from the libusb-1.0 documentation */ 714141cc406Sopenharmony_ci 715141cc406Sopenharmony_ci switch (errcode) 716141cc406Sopenharmony_ci { 717141cc406Sopenharmony_ci case LIBUSB_SUCCESS: 718141cc406Sopenharmony_ci return "Success (no error)"; 719141cc406Sopenharmony_ci 720141cc406Sopenharmony_ci case LIBUSB_ERROR_IO: 721141cc406Sopenharmony_ci return "Input/output error"; 722141cc406Sopenharmony_ci 723141cc406Sopenharmony_ci case LIBUSB_ERROR_INVALID_PARAM: 724141cc406Sopenharmony_ci return "Invalid parameter"; 725141cc406Sopenharmony_ci 726141cc406Sopenharmony_ci case LIBUSB_ERROR_ACCESS: 727141cc406Sopenharmony_ci return "Access denied (insufficient permissions)"; 728141cc406Sopenharmony_ci 729141cc406Sopenharmony_ci case LIBUSB_ERROR_NO_DEVICE: 730141cc406Sopenharmony_ci return "No such device (it may have been disconnected)"; 731141cc406Sopenharmony_ci 732141cc406Sopenharmony_ci case LIBUSB_ERROR_NOT_FOUND: 733141cc406Sopenharmony_ci return "Entity not found"; 734141cc406Sopenharmony_ci 735141cc406Sopenharmony_ci case LIBUSB_ERROR_BUSY: 736141cc406Sopenharmony_ci return "Resource busy"; 737141cc406Sopenharmony_ci 738141cc406Sopenharmony_ci case LIBUSB_ERROR_TIMEOUT: 739141cc406Sopenharmony_ci return "Operation timed out"; 740141cc406Sopenharmony_ci 741141cc406Sopenharmony_ci case LIBUSB_ERROR_OVERFLOW: 742141cc406Sopenharmony_ci return "Overflow"; 743141cc406Sopenharmony_ci 744141cc406Sopenharmony_ci case LIBUSB_ERROR_PIPE: 745141cc406Sopenharmony_ci return "Pipe error"; 746141cc406Sopenharmony_ci 747141cc406Sopenharmony_ci case LIBUSB_ERROR_INTERRUPTED: 748141cc406Sopenharmony_ci return "System call interrupted (perhaps due to signal)"; 749141cc406Sopenharmony_ci 750141cc406Sopenharmony_ci case LIBUSB_ERROR_NO_MEM: 751141cc406Sopenharmony_ci return "Insufficient memory"; 752141cc406Sopenharmony_ci 753141cc406Sopenharmony_ci case LIBUSB_ERROR_NOT_SUPPORTED: 754141cc406Sopenharmony_ci return "Operation not supported or unimplemented on this platform"; 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_ci case LIBUSB_ERROR_OTHER: 757141cc406Sopenharmony_ci return "Other error"; 758141cc406Sopenharmony_ci 759141cc406Sopenharmony_ci default: 760141cc406Sopenharmony_ci return "Unknown libusb-1.0 error code"; 761141cc406Sopenharmony_ci } 762141cc406Sopenharmony_ci} 763141cc406Sopenharmony_ci 764141cc406Sopenharmony_cistatic char * 765141cc406Sopenharmony_ciget_libusb_string_descriptor (libusb_device_handle *hdl, int index) 766141cc406Sopenharmony_ci{ 767141cc406Sopenharmony_ci unsigned char *buffer, short_buffer[2]; 768141cc406Sopenharmony_ci int size; 769141cc406Sopenharmony_ci int ret; 770141cc406Sopenharmony_ci int i; 771141cc406Sopenharmony_ci 772141cc406Sopenharmony_ci if (!index) 773141cc406Sopenharmony_ci return NULL; 774141cc406Sopenharmony_ci 775141cc406Sopenharmony_ci ret = libusb_get_descriptor (hdl, LIBUSB_DT_STRING, index, 776141cc406Sopenharmony_ci short_buffer, sizeof (short_buffer)); 777141cc406Sopenharmony_ci if (ret < 0) 778141cc406Sopenharmony_ci { 779141cc406Sopenharmony_ci printf ("could not fetch string descriptor: %s\n", 780141cc406Sopenharmony_ci sfs_libusb_strerror (ret)); 781141cc406Sopenharmony_ci return NULL; 782141cc406Sopenharmony_ci } 783141cc406Sopenharmony_ci 784141cc406Sopenharmony_ci if ((short_buffer[0] < 2) /* descriptor length */ 785141cc406Sopenharmony_ci || (short_buffer[1] != LIBUSB_DT_STRING)) /* descriptor type */ 786141cc406Sopenharmony_ci return NULL; 787141cc406Sopenharmony_ci 788141cc406Sopenharmony_ci size = short_buffer[0]; 789141cc406Sopenharmony_ci 790141cc406Sopenharmony_ci buffer = calloc (1, size + 1); 791141cc406Sopenharmony_ci if (!buffer) 792141cc406Sopenharmony_ci return NULL; 793141cc406Sopenharmony_ci 794141cc406Sopenharmony_ci ret = libusb_get_descriptor (hdl, LIBUSB_DT_STRING, index, 795141cc406Sopenharmony_ci buffer, size); 796141cc406Sopenharmony_ci if (ret < 0) 797141cc406Sopenharmony_ci { 798141cc406Sopenharmony_ci printf ("could not fetch string descriptor (again): %s\n", 799141cc406Sopenharmony_ci sfs_libusb_strerror (ret)); 800141cc406Sopenharmony_ci free (buffer); 801141cc406Sopenharmony_ci return NULL; 802141cc406Sopenharmony_ci } 803141cc406Sopenharmony_ci 804141cc406Sopenharmony_ci if ((buffer[0] < 2) || (buffer[0] > size) /* descriptor length */ 805141cc406Sopenharmony_ci || (buffer[1] != LIBUSB_DT_STRING)) /* descriptor type */ 806141cc406Sopenharmony_ci { 807141cc406Sopenharmony_ci free (buffer); 808141cc406Sopenharmony_ci return NULL; 809141cc406Sopenharmony_ci } 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci size = buffer[0] - 2; 812141cc406Sopenharmony_ci for (i = 0; i < (size / 2); i++) 813141cc406Sopenharmony_ci buffer[i] = buffer[2 + 2 * i]; 814141cc406Sopenharmony_ci buffer[i] = '\0'; 815141cc406Sopenharmony_ci 816141cc406Sopenharmony_ci return (char *) buffer; 817141cc406Sopenharmony_ci} 818141cc406Sopenharmony_ci 819141cc406Sopenharmony_cistatic void 820141cc406Sopenharmony_cicheck_libusb_device (libusb_device *dev, SANE_Bool from_file) 821141cc406Sopenharmony_ci{ 822141cc406Sopenharmony_ci libusb_device_handle *hdl; 823141cc406Sopenharmony_ci struct libusb_device_descriptor desc; 824141cc406Sopenharmony_ci struct libusb_config_descriptor *config0; 825141cc406Sopenharmony_ci 826141cc406Sopenharmony_ci int is_scanner = 0; 827141cc406Sopenharmony_ci char *vendor; 828141cc406Sopenharmony_ci char *product; 829141cc406Sopenharmony_ci unsigned short vid, pid; 830141cc406Sopenharmony_ci unsigned char busno, address; 831141cc406Sopenharmony_ci int config; 832141cc406Sopenharmony_ci int intf; 833141cc406Sopenharmony_ci int ret; 834141cc406Sopenharmony_ci 835141cc406Sopenharmony_ci busno = libusb_get_bus_number (dev); 836141cc406Sopenharmony_ci address = libusb_get_device_address (dev); 837141cc406Sopenharmony_ci 838141cc406Sopenharmony_ci ret = libusb_get_device_descriptor (dev, &desc); 839141cc406Sopenharmony_ci if (ret < 0) 840141cc406Sopenharmony_ci { 841141cc406Sopenharmony_ci printf ("could not get device descriptor for device at %03d:%03d: %s\n", 842141cc406Sopenharmony_ci busno, address, sfs_libusb_strerror (ret)); 843141cc406Sopenharmony_ci return; 844141cc406Sopenharmony_ci } 845141cc406Sopenharmony_ci 846141cc406Sopenharmony_ci vid = desc.idVendor; 847141cc406Sopenharmony_ci pid = desc.idProduct; 848141cc406Sopenharmony_ci 849141cc406Sopenharmony_ci ret = libusb_open (dev, &hdl); 850141cc406Sopenharmony_ci if (ret < 0) 851141cc406Sopenharmony_ci { 852141cc406Sopenharmony_ci printf ("could not open USB device 0x%04x/0x%04x at %03d:%03d: %s\n", 853141cc406Sopenharmony_ci vid, pid, busno, address, sfs_libusb_strerror (ret)); 854141cc406Sopenharmony_ci return; 855141cc406Sopenharmony_ci } 856141cc406Sopenharmony_ci 857141cc406Sopenharmony_ci ret = libusb_get_configuration (hdl, &config); 858141cc406Sopenharmony_ci if (ret < 0) 859141cc406Sopenharmony_ci { 860141cc406Sopenharmony_ci printf ("could not get configuration for device 0x%04x/0x%04x at %03d:%03d: %s\n", 861141cc406Sopenharmony_ci vid, pid, busno, address, sfs_libusb_strerror (ret)); 862141cc406Sopenharmony_ci libusb_close (hdl); 863141cc406Sopenharmony_ci return; 864141cc406Sopenharmony_ci } 865141cc406Sopenharmony_ci 866141cc406Sopenharmony_ci if (config == 0) 867141cc406Sopenharmony_ci { 868141cc406Sopenharmony_ci if (verbose > 1) 869141cc406Sopenharmony_ci printf ("device 0x%04x/0x%04x at %03d:%03d is not configured\n", 870141cc406Sopenharmony_ci vid, pid, busno, address); 871141cc406Sopenharmony_ci libusb_close (hdl); 872141cc406Sopenharmony_ci return; 873141cc406Sopenharmony_ci } 874141cc406Sopenharmony_ci 875141cc406Sopenharmony_ci vendor = get_libusb_string_descriptor (hdl, desc.iManufacturer); 876141cc406Sopenharmony_ci product = get_libusb_string_descriptor (hdl, desc.iProduct); 877141cc406Sopenharmony_ci 878141cc406Sopenharmony_ci if (verbose > 2) 879141cc406Sopenharmony_ci { 880141cc406Sopenharmony_ci /* print everything we know about the device */ 881141cc406Sopenharmony_ci char *buf; 882141cc406Sopenharmony_ci int config_nr; 883141cc406Sopenharmony_ci 884141cc406Sopenharmony_ci printf ("\n"); 885141cc406Sopenharmony_ci printf ("<device descriptor of 0x%04x/0x%04x at %03d:%03d", 886141cc406Sopenharmony_ci vid, pid, busno, address); 887141cc406Sopenharmony_ci if (vendor || product) 888141cc406Sopenharmony_ci { 889141cc406Sopenharmony_ci printf (" (%s%s%s)", (vendor) ? vendor : "", 890141cc406Sopenharmony_ci (vendor && product) ? " " : "", (product) ? product : ""); 891141cc406Sopenharmony_ci } 892141cc406Sopenharmony_ci printf (">\n"); 893141cc406Sopenharmony_ci printf ("bLength %d\n", desc.bLength); 894141cc406Sopenharmony_ci printf ("bDescriptorType %d\n", desc.bDescriptorType); 895141cc406Sopenharmony_ci printf ("bcdUSB %d.%d%d\n", desc.bcdUSB >> 8, 896141cc406Sopenharmony_ci (desc.bcdUSB >> 4) & 15, desc.bcdUSB & 15); 897141cc406Sopenharmony_ci printf ("bDeviceClass %d\n", desc.bDeviceClass); 898141cc406Sopenharmony_ci printf ("bDeviceSubClass %d\n", desc.bDeviceSubClass); 899141cc406Sopenharmony_ci printf ("bDeviceProtocol %d\n", desc.bDeviceProtocol); 900141cc406Sopenharmony_ci printf ("bMaxPacketSize0 %d\n", desc.bMaxPacketSize0); 901141cc406Sopenharmony_ci printf ("idVendor 0x%04X\n", desc.idVendor); 902141cc406Sopenharmony_ci printf ("idProduct 0x%04X\n", desc.idProduct); 903141cc406Sopenharmony_ci printf ("bcdDevice %d.%d%d\n", desc.bcdDevice >> 8, 904141cc406Sopenharmony_ci (desc.bcdDevice >> 4) & 15, desc.bcdDevice & 15); 905141cc406Sopenharmony_ci printf ("iManufacturer %d (%s)\n", desc.iManufacturer, 906141cc406Sopenharmony_ci (vendor) ? vendor : ""); 907141cc406Sopenharmony_ci printf ("iProduct %d (%s)\n", desc.iProduct, 908141cc406Sopenharmony_ci (product) ? product : ""); 909141cc406Sopenharmony_ci buf = get_libusb_string_descriptor (hdl, desc.iSerialNumber); 910141cc406Sopenharmony_ci printf ("iSerialNumber %d (%s)\n", desc.iSerialNumber, 911141cc406Sopenharmony_ci (buf) ? buf : ""); 912141cc406Sopenharmony_ci if (buf) 913141cc406Sopenharmony_ci free (buf); 914141cc406Sopenharmony_ci printf ("bNumConfigurations %d\n", desc.bNumConfigurations); 915141cc406Sopenharmony_ci 916141cc406Sopenharmony_ci for (config_nr = 0; config_nr < desc.bNumConfigurations; config_nr++) 917141cc406Sopenharmony_ci { 918141cc406Sopenharmony_ci struct libusb_config_descriptor *c; 919141cc406Sopenharmony_ci 920141cc406Sopenharmony_ci ret = libusb_get_config_descriptor (dev, config_nr, &c); 921141cc406Sopenharmony_ci if (ret < 0) 922141cc406Sopenharmony_ci { 923141cc406Sopenharmony_ci printf ("could not get configuration descriptor %d: %s\n", 924141cc406Sopenharmony_ci config_nr, sfs_libusb_strerror (ret)); 925141cc406Sopenharmony_ci continue; 926141cc406Sopenharmony_ci } 927141cc406Sopenharmony_ci 928141cc406Sopenharmony_ci printf (" <configuration %d>\n", config_nr); 929141cc406Sopenharmony_ci printf (" bLength %d\n", c->bLength); 930141cc406Sopenharmony_ci printf (" bDescriptorType %d\n", c->bDescriptorType); 931141cc406Sopenharmony_ci printf (" wTotalLength %d\n", c->wTotalLength); 932141cc406Sopenharmony_ci printf (" bNumInterfaces %d\n", c->bNumInterfaces); 933141cc406Sopenharmony_ci printf (" bConfigurationValue %d\n", c->bConfigurationValue); 934141cc406Sopenharmony_ci 935141cc406Sopenharmony_ci buf = get_libusb_string_descriptor (hdl, c->iConfiguration); 936141cc406Sopenharmony_ci printf (" iConfiguration %d (%s)\n", c->iConfiguration, 937141cc406Sopenharmony_ci (buf) ? buf : ""); 938141cc406Sopenharmony_ci free (buf); 939141cc406Sopenharmony_ci 940141cc406Sopenharmony_ci printf (" bmAttributes %d (%s%s)\n", c->bmAttributes, 941141cc406Sopenharmony_ci c->bmAttributes & 64 ? "Self-powered" : "", 942141cc406Sopenharmony_ci c->bmAttributes & 32 ? "Remote Wakeup" : ""); 943141cc406Sopenharmony_ci printf (" MaxPower %d mA\n", c->MaxPower * 2); 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ci for (intf = 0; intf < c->bNumInterfaces; intf++) 946141cc406Sopenharmony_ci { 947141cc406Sopenharmony_ci const struct libusb_interface *interface; 948141cc406Sopenharmony_ci int alt_setting_nr; 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci interface = &c->interface[intf]; 951141cc406Sopenharmony_ci 952141cc406Sopenharmony_ci printf (" <interface %d>\n", intf); 953141cc406Sopenharmony_ci for (alt_setting_nr = 0; 954141cc406Sopenharmony_ci alt_setting_nr < interface->num_altsetting; 955141cc406Sopenharmony_ci alt_setting_nr++) 956141cc406Sopenharmony_ci { 957141cc406Sopenharmony_ci const struct libusb_interface_descriptor *i; 958141cc406Sopenharmony_ci int ep_nr; 959141cc406Sopenharmony_ci 960141cc406Sopenharmony_ci i = &interface->altsetting[alt_setting_nr]; 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci printf (" <altsetting %d>\n", alt_setting_nr); 963141cc406Sopenharmony_ci printf (" bLength %d\n", i->bLength); 964141cc406Sopenharmony_ci printf (" bDescriptorType %d\n", i->bDescriptorType); 965141cc406Sopenharmony_ci printf (" bInterfaceNumber %d\n", i->bInterfaceNumber); 966141cc406Sopenharmony_ci printf (" bAlternateSetting %d\n", i->bAlternateSetting); 967141cc406Sopenharmony_ci printf (" bNumEndpoints %d\n", i->bNumEndpoints); 968141cc406Sopenharmony_ci printf (" bInterfaceClass %d\n", i->bInterfaceClass); 969141cc406Sopenharmony_ci printf (" bInterfaceSubClass %d\n", 970141cc406Sopenharmony_ci i->bInterfaceSubClass); 971141cc406Sopenharmony_ci printf (" bInterfaceProtocol %d\n", 972141cc406Sopenharmony_ci i->bInterfaceProtocol); 973141cc406Sopenharmony_ci 974141cc406Sopenharmony_ci buf = NULL; 975141cc406Sopenharmony_ci buf = get_libusb_string_descriptor (hdl, i->iInterface); 976141cc406Sopenharmony_ci printf (" iInterface %d (%s)\n", i->iInterface, 977141cc406Sopenharmony_ci (buf) ? buf : ""); 978141cc406Sopenharmony_ci free (buf); 979141cc406Sopenharmony_ci for (ep_nr = 0; ep_nr < i->bNumEndpoints; ep_nr++) 980141cc406Sopenharmony_ci { 981141cc406Sopenharmony_ci const struct libusb_endpoint_descriptor *e; 982141cc406Sopenharmony_ci char *ep_type; 983141cc406Sopenharmony_ci 984141cc406Sopenharmony_ci e = &i->endpoint[ep_nr]; 985141cc406Sopenharmony_ci 986141cc406Sopenharmony_ci switch (e->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) 987141cc406Sopenharmony_ci { 988141cc406Sopenharmony_ci case LIBUSB_TRANSFER_TYPE_CONTROL: 989141cc406Sopenharmony_ci ep_type = "control"; 990141cc406Sopenharmony_ci break; 991141cc406Sopenharmony_ci case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 992141cc406Sopenharmony_ci ep_type = "isochronous"; 993141cc406Sopenharmony_ci break; 994141cc406Sopenharmony_ci case LIBUSB_TRANSFER_TYPE_BULK: 995141cc406Sopenharmony_ci ep_type = "bulk"; 996141cc406Sopenharmony_ci break; 997141cc406Sopenharmony_ci case LIBUSB_TRANSFER_TYPE_INTERRUPT: 998141cc406Sopenharmony_ci ep_type = "interrupt"; 999141cc406Sopenharmony_ci break; 1000141cc406Sopenharmony_ci default: 1001141cc406Sopenharmony_ci ep_type = "unknown"; 1002141cc406Sopenharmony_ci break; 1003141cc406Sopenharmony_ci } 1004141cc406Sopenharmony_ci printf (" <endpoint %d>\n", ep_nr); 1005141cc406Sopenharmony_ci printf (" bLength %d\n", e->bLength); 1006141cc406Sopenharmony_ci printf (" bDescriptorType %d\n", 1007141cc406Sopenharmony_ci e->bDescriptorType); 1008141cc406Sopenharmony_ci printf (" bEndpointAddress 0x%02X (%s 0x%02X)\n", 1009141cc406Sopenharmony_ci e->bEndpointAddress, 1010141cc406Sopenharmony_ci e->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK ? 1011141cc406Sopenharmony_ci "in" : "out", 1012141cc406Sopenharmony_ci e-> 1013141cc406Sopenharmony_ci bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK); 1014141cc406Sopenharmony_ci printf (" bmAttributes %d (%s)\n", 1015141cc406Sopenharmony_ci e->bmAttributes, ep_type); 1016141cc406Sopenharmony_ci printf (" wMaxPacketSize %d\n", 1017141cc406Sopenharmony_ci e->wMaxPacketSize); 1018141cc406Sopenharmony_ci printf (" bInterval %d ms\n", e->bInterval); 1019141cc406Sopenharmony_ci printf (" bRefresh %d\n", e->bRefresh); 1020141cc406Sopenharmony_ci printf (" bSynchAddress %d\n", e->bSynchAddress); 1021141cc406Sopenharmony_ci } 1022141cc406Sopenharmony_ci } 1023141cc406Sopenharmony_ci } 1024141cc406Sopenharmony_ci } 1025141cc406Sopenharmony_ci } 1026141cc406Sopenharmony_ci 1027141cc406Sopenharmony_ci 1028141cc406Sopenharmony_ci /* Some heuristics, which device may be a scanner */ 1029141cc406Sopenharmony_ci if (desc.idVendor == 0) /* hub */ 1030141cc406Sopenharmony_ci --is_scanner; 1031141cc406Sopenharmony_ci if (desc.idProduct == 0) /* hub */ 1032141cc406Sopenharmony_ci --is_scanner; 1033141cc406Sopenharmony_ci 1034141cc406Sopenharmony_ci ret = libusb_get_config_descriptor (dev, 0, &config0); 1035141cc406Sopenharmony_ci if (ret < 0) 1036141cc406Sopenharmony_ci { 1037141cc406Sopenharmony_ci printf ("could not get config[0] descriptor: %s\n", 1038141cc406Sopenharmony_ci sfs_libusb_strerror (ret)); 1039141cc406Sopenharmony_ci 1040141cc406Sopenharmony_ci goto out_free; 1041141cc406Sopenharmony_ci } 1042141cc406Sopenharmony_ci 1043141cc406Sopenharmony_ci for (intf = 0; (intf < config0->bNumInterfaces) && (is_scanner <= 0); intf++) 1044141cc406Sopenharmony_ci { 1045141cc406Sopenharmony_ci switch (desc.bDeviceClass) 1046141cc406Sopenharmony_ci { 1047141cc406Sopenharmony_ci case USB_CLASS_VENDOR_SPEC: 1048141cc406Sopenharmony_ci ++is_scanner; 1049141cc406Sopenharmony_ci break; 1050141cc406Sopenharmony_ci case USB_CLASS_PER_INTERFACE: 1051141cc406Sopenharmony_ci if ((config0->interface[intf].num_altsetting == 0) 1052141cc406Sopenharmony_ci || !config0->interface[intf].altsetting) 1053141cc406Sopenharmony_ci break; 1054141cc406Sopenharmony_ci switch (config0->interface[intf].altsetting[0].bInterfaceClass) 1055141cc406Sopenharmony_ci { 1056141cc406Sopenharmony_ci case USB_CLASS_VENDOR_SPEC: 1057141cc406Sopenharmony_ci case USB_CLASS_PER_INTERFACE: 1058141cc406Sopenharmony_ci case 16: /* data? */ 1059141cc406Sopenharmony_ci ++is_scanner; 1060141cc406Sopenharmony_ci break; 1061141cc406Sopenharmony_ci } 1062141cc406Sopenharmony_ci break; 1063141cc406Sopenharmony_ci } 1064141cc406Sopenharmony_ci } 1065141cc406Sopenharmony_ci 1066141cc406Sopenharmony_ci if (is_scanner > 0) 1067141cc406Sopenharmony_ci { 1068141cc406Sopenharmony_ci char *chipset = NULL; 1069141cc406Sopenharmony_ci 1070141cc406Sopenharmony_ci if(!from_file) 1071141cc406Sopenharmony_ci chipset = check_usb_chip (verbose, desc, hdl, config0); 1072141cc406Sopenharmony_ci 1073141cc406Sopenharmony_ci printf ("found possible USB scanner (vendor=0x%04x", vid); 1074141cc406Sopenharmony_ci if (vendor) 1075141cc406Sopenharmony_ci printf (" [%s]", vendor); 1076141cc406Sopenharmony_ci printf (", product=0x%04x", pid); 1077141cc406Sopenharmony_ci if (product) 1078141cc406Sopenharmony_ci printf (" [%s]", product); 1079141cc406Sopenharmony_ci if (chipset) 1080141cc406Sopenharmony_ci printf (", chip=%s", chipset); 1081141cc406Sopenharmony_ci if (from_file) 1082141cc406Sopenharmony_ci printf (")\n"); 1083141cc406Sopenharmony_ci else 1084141cc406Sopenharmony_ci printf (") at libusb:%03d:%03d\n", busno, address); 1085141cc406Sopenharmony_ci 1086141cc406Sopenharmony_ci libusb_device_found = SANE_TRUE; 1087141cc406Sopenharmony_ci device_found = SANE_TRUE; 1088141cc406Sopenharmony_ci } 1089141cc406Sopenharmony_ci 1090141cc406Sopenharmony_ci libusb_free_config_descriptor (config0); 1091141cc406Sopenharmony_ci 1092141cc406Sopenharmony_ci out_free: 1093141cc406Sopenharmony_ci libusb_close (hdl); 1094141cc406Sopenharmony_ci if (vendor) 1095141cc406Sopenharmony_ci free (vendor); 1096141cc406Sopenharmony_ci 1097141cc406Sopenharmony_ci if (product) 1098141cc406Sopenharmony_ci free (product); 1099141cc406Sopenharmony_ci} 1100141cc406Sopenharmony_ci#endif /* HAVE_LIBUSB */ 1101141cc406Sopenharmony_ci 1102141cc406Sopenharmony_ci 1103141cc406Sopenharmony_cistatic DIR * 1104141cc406Sopenharmony_ciscan_directory (char *dir_name) 1105141cc406Sopenharmony_ci{ 1106141cc406Sopenharmony_ci struct stat stat_buf; 1107141cc406Sopenharmony_ci DIR *dir; 1108141cc406Sopenharmony_ci 1109141cc406Sopenharmony_ci if (verbose > 2) 1110141cc406Sopenharmony_ci printf ("scanning directory %s\n", dir_name); 1111141cc406Sopenharmony_ci 1112141cc406Sopenharmony_ci if (stat (dir_name, &stat_buf) < 0) 1113141cc406Sopenharmony_ci { 1114141cc406Sopenharmony_ci if (verbose > 1) 1115141cc406Sopenharmony_ci printf ("cannot stat `%s' (%s)\n", dir_name, strerror (errno)); 1116141cc406Sopenharmony_ci return 0; 1117141cc406Sopenharmony_ci } 1118141cc406Sopenharmony_ci if (!S_ISDIR (stat_buf.st_mode)) 1119141cc406Sopenharmony_ci { 1120141cc406Sopenharmony_ci if (verbose > 1) 1121141cc406Sopenharmony_ci printf ("`%s' is not a directory\n", dir_name); 1122141cc406Sopenharmony_ci return 0; 1123141cc406Sopenharmony_ci } 1124141cc406Sopenharmony_ci if ((dir = opendir (dir_name)) == 0) 1125141cc406Sopenharmony_ci { 1126141cc406Sopenharmony_ci if (verbose > 1) 1127141cc406Sopenharmony_ci printf ("cannot read directory `%s' (%s)\n", dir_name, 1128141cc406Sopenharmony_ci strerror (errno)); 1129141cc406Sopenharmony_ci return 0; 1130141cc406Sopenharmony_ci } 1131141cc406Sopenharmony_ci return dir; 1132141cc406Sopenharmony_ci} 1133141cc406Sopenharmony_ci 1134141cc406Sopenharmony_cistatic char * 1135141cc406Sopenharmony_ciget_next_file (char *dir_name, DIR * dir) 1136141cc406Sopenharmony_ci{ 1137141cc406Sopenharmony_ci struct dirent *dir_entry; 1138141cc406Sopenharmony_ci static char file_name[PATH_MAX]; 1139141cc406Sopenharmony_ci 1140141cc406Sopenharmony_ci do 1141141cc406Sopenharmony_ci { 1142141cc406Sopenharmony_ci dir_entry = readdir (dir); 1143141cc406Sopenharmony_ci if (!dir_entry) 1144141cc406Sopenharmony_ci return 0; 1145141cc406Sopenharmony_ci } 1146141cc406Sopenharmony_ci while (strcmp (dir_entry->d_name, ".") == 0 1147141cc406Sopenharmony_ci || strcmp (dir_entry->d_name, "..") == 0); 1148141cc406Sopenharmony_ci 1149141cc406Sopenharmony_ci if (strlen (dir_name) + strlen (dir_entry->d_name) + 1 > PATH_MAX) 1150141cc406Sopenharmony_ci { 1151141cc406Sopenharmony_ci if (verbose > 1) 1152141cc406Sopenharmony_ci printf ("filename too long\n"); 1153141cc406Sopenharmony_ci return 0; 1154141cc406Sopenharmony_ci } 1155141cc406Sopenharmony_ci sprintf (file_name, "%s%s", dir_name, dir_entry->d_name); 1156141cc406Sopenharmony_ci return file_name; 1157141cc406Sopenharmony_ci} 1158141cc406Sopenharmony_ci 1159141cc406Sopenharmony_ci#if defined(WIN32_SCSI) 1160141cc406Sopenharmony_ci/* Return a list of potential scanners. There's a lot of hardcoded values here that might break on a system with lots of scsi devices. */ 1161141cc406Sopenharmony_cistatic char **build_scsi_dev_list(void) 1162141cc406Sopenharmony_ci{ 1163141cc406Sopenharmony_ci char **dev_list; 1164141cc406Sopenharmony_ci int dev_list_index; 1165141cc406Sopenharmony_ci int hca; 1166141cc406Sopenharmony_ci HANDLE fd; 1167141cc406Sopenharmony_ci char scsi_hca_name[20]; 1168141cc406Sopenharmony_ci char buffer[4096]; 1169141cc406Sopenharmony_ci DWORD BytesReturned; 1170141cc406Sopenharmony_ci BOOL ret; 1171141cc406Sopenharmony_ci size_t dev_list_size; 1172141cc406Sopenharmony_ci PSCSI_ADAPTER_BUS_INFO adapter; 1173141cc406Sopenharmony_ci PSCSI_INQUIRY_DATA inquiry; 1174141cc406Sopenharmony_ci int i; 1175141cc406Sopenharmony_ci 1176141cc406Sopenharmony_ci /* Allocate room for about 100 scanners. That should be enough. */ 1177141cc406Sopenharmony_ci dev_list_size = 100; 1178141cc406Sopenharmony_ci dev_list_index = 0; 1179141cc406Sopenharmony_ci dev_list = calloc(1, dev_list_size * sizeof(char *)); 1180141cc406Sopenharmony_ci 1181141cc406Sopenharmony_ci hca = 0; 1182141cc406Sopenharmony_ci 1183141cc406Sopenharmony_ci for(hca = 0; ; hca++) { 1184141cc406Sopenharmony_ci 1185141cc406Sopenharmony_ci /* Open the adapter */ 1186141cc406Sopenharmony_ci snprintf(scsi_hca_name, 20, "\\\\.\\Scsi%d:", hca); 1187141cc406Sopenharmony_ci fd = CreateFile(scsi_hca_name, GENERIC_READ | GENERIC_WRITE, 1188141cc406Sopenharmony_ci FILE_SHARE_READ | FILE_SHARE_WRITE, 1189141cc406Sopenharmony_ci NULL, OPEN_EXISTING, 1190141cc406Sopenharmony_ci FILE_FLAG_RANDOM_ACCESS, NULL ); 1191141cc406Sopenharmony_ci 1192141cc406Sopenharmony_ci if (fd == INVALID_HANDLE_VALUE) { 1193141cc406Sopenharmony_ci /* Assume there is no more adapter. This is wrong in the case 1194141cc406Sopenharmony_ci * of hot-plug stuff, but I have yet to see it on a user 1195141cc406Sopenharmony_ci * machine. */ 1196141cc406Sopenharmony_ci break; 1197141cc406Sopenharmony_ci } 1198141cc406Sopenharmony_ci 1199141cc406Sopenharmony_ci /* Get the inquiry info for the devices on that hca. */ 1200141cc406Sopenharmony_ci ret = DeviceIoControl(fd, 1201141cc406Sopenharmony_ci IOCTL_SCSI_GET_INQUIRY_DATA, 1202141cc406Sopenharmony_ci NULL, 1203141cc406Sopenharmony_ci 0, 1204141cc406Sopenharmony_ci buffer, 1205141cc406Sopenharmony_ci sizeof(buffer), 1206141cc406Sopenharmony_ci &BytesReturned, 1207141cc406Sopenharmony_ci FALSE); 1208141cc406Sopenharmony_ci 1209141cc406Sopenharmony_ci if(ret == 0) 1210141cc406Sopenharmony_ci { 1211141cc406Sopenharmony_ci CloseHandle(fd); 1212141cc406Sopenharmony_ci continue; 1213141cc406Sopenharmony_ci } 1214141cc406Sopenharmony_ci 1215141cc406Sopenharmony_ci adapter = (PSCSI_ADAPTER_BUS_INFO)buffer; 1216141cc406Sopenharmony_ci 1217141cc406Sopenharmony_ci for(i = 0; i < adapter->NumberOfBuses; i++) { 1218141cc406Sopenharmony_ci 1219141cc406Sopenharmony_ci if (adapter->BusData[i].InquiryDataOffset == 0) { 1220141cc406Sopenharmony_ci /* No device here */ 1221141cc406Sopenharmony_ci continue; 1222141cc406Sopenharmony_ci } 1223141cc406Sopenharmony_ci 1224141cc406Sopenharmony_ci inquiry = (PSCSI_INQUIRY_DATA) (buffer + 1225141cc406Sopenharmony_ci adapter->BusData[i].InquiryDataOffset); 1226141cc406Sopenharmony_ci while(1) { 1227141cc406Sopenharmony_ci /* Check if it is a scanner or a processor 1228141cc406Sopenharmony_ci * device. Ignore the other 1229141cc406Sopenharmony_ci * device types. */ 1230141cc406Sopenharmony_ci if (inquiry->InquiryDataLength >= 5 && 1231141cc406Sopenharmony_ci ((inquiry->InquiryData[0] & 0x1f) == 3 || 1232141cc406Sopenharmony_ci (inquiry->InquiryData[0] & 0x1f) == 6)) { 1233141cc406Sopenharmony_ci char device_name[20]; 1234141cc406Sopenharmony_ci sprintf(device_name, "h%db%dt%dl%d", hca, inquiry->PathId, inquiry->TargetId, inquiry->Lun); 1235141cc406Sopenharmony_ci dev_list[dev_list_index] = strdup(device_name); 1236141cc406Sopenharmony_ci dev_list_index++; 1237141cc406Sopenharmony_ci } 1238141cc406Sopenharmony_ci 1239141cc406Sopenharmony_ci if (inquiry->NextInquiryDataOffset == 0) { 1240141cc406Sopenharmony_ci /* No device here */ 1241141cc406Sopenharmony_ci break; 1242141cc406Sopenharmony_ci } else { 1243141cc406Sopenharmony_ci inquiry = (PSCSI_INQUIRY_DATA) (buffer + 1244141cc406Sopenharmony_ci inquiry->NextInquiryDataOffset); 1245141cc406Sopenharmony_ci } 1246141cc406Sopenharmony_ci } 1247141cc406Sopenharmony_ci } 1248141cc406Sopenharmony_ci 1249141cc406Sopenharmony_ci CloseHandle(fd); 1250141cc406Sopenharmony_ci 1251141cc406Sopenharmony_ci } 1252141cc406Sopenharmony_ci 1253141cc406Sopenharmony_ci return dev_list; 1254141cc406Sopenharmony_ci 1255141cc406Sopenharmony_ci} 1256141cc406Sopenharmony_ci#endif 1257141cc406Sopenharmony_ci 1258141cc406Sopenharmony_ci#if defined (HAVE_IOKIT_CDB_IOSCSILIB_H) || \ 1259141cc406Sopenharmony_ci defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ 1260141cc406Sopenharmony_ci defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) 1261141cc406Sopenharmony_cichar **scsi_dev_list; 1262141cc406Sopenharmony_ciint scsi_dev_list_index; 1263141cc406Sopenharmony_ci 1264141cc406Sopenharmony_cistatic SANE_Status AddToSCSIDeviceList (const char *dev) { 1265141cc406Sopenharmony_ci if (scsi_dev_list_index < 99) { 1266141cc406Sopenharmony_ci scsi_dev_list [scsi_dev_list_index] = strdup (dev); 1267141cc406Sopenharmony_ci scsi_dev_list_index++; 1268141cc406Sopenharmony_ci return SANE_STATUS_GOOD; 1269141cc406Sopenharmony_ci } 1270141cc406Sopenharmony_ci else 1271141cc406Sopenharmony_ci return SANE_STATUS_NO_MEM; 1272141cc406Sopenharmony_ci} 1273141cc406Sopenharmony_ci 1274141cc406Sopenharmony_cistatic char **build_scsi_dev_list(void) 1275141cc406Sopenharmony_ci{ 1276141cc406Sopenharmony_ci scsi_dev_list_index = 0; 1277141cc406Sopenharmony_ci scsi_dev_list = malloc (100 * sizeof(char *)); 1278141cc406Sopenharmony_ci sanei_scsi_find_devices (NULL, NULL, NULL, -1, -1, -1, -1, 1279141cc406Sopenharmony_ci AddToSCSIDeviceList); 1280141cc406Sopenharmony_ci scsi_dev_list [scsi_dev_list_index] = NULL; 1281141cc406Sopenharmony_ci return scsi_dev_list; 1282141cc406Sopenharmony_ci} 1283141cc406Sopenharmony_ci#endif 1284141cc406Sopenharmony_ci 1285141cc406Sopenharmony_cistatic int 1286141cc406Sopenharmony_cicheck_mustek_pp_device (void) 1287141cc406Sopenharmony_ci{ 1288141cc406Sopenharmony_ci const char **devices; 1289141cc406Sopenharmony_ci int ctr = 0, found = 0, scsi = 0; 1290141cc406Sopenharmony_ci 1291141cc406Sopenharmony_ci if (verbose > 1) 1292141cc406Sopenharmony_ci printf ("searching for Mustek parallel port scanners:\n"); 1293141cc406Sopenharmony_ci 1294141cc406Sopenharmony_ci devices = sanei_pa4s2_devices (); 1295141cc406Sopenharmony_ci 1296141cc406Sopenharmony_ci while (devices[ctr] != NULL) { 1297141cc406Sopenharmony_ci int fd; 1298141cc406Sopenharmony_ci SANE_Status result; 1299141cc406Sopenharmony_ci 1300141cc406Sopenharmony_ci /* ordinary parallel port scanner type */ 1301141cc406Sopenharmony_ci if (verbose > 1) 1302141cc406Sopenharmony_ci printf ("checking %s...", devices[ctr]); 1303141cc406Sopenharmony_ci 1304141cc406Sopenharmony_ci result = sanei_pa4s2_open (devices[ctr], &fd); 1305141cc406Sopenharmony_ci 1306141cc406Sopenharmony_ci if (verbose > 1) 1307141cc406Sopenharmony_ci { 1308141cc406Sopenharmony_ci if (result != 0) 1309141cc406Sopenharmony_ci printf (" failed to open (%s)\n", sane_strstatus (result)); 1310141cc406Sopenharmony_ci else 1311141cc406Sopenharmony_ci printf (" open ok\n"); 1312141cc406Sopenharmony_ci } 1313141cc406Sopenharmony_ci 1314141cc406Sopenharmony_ci if (result == 0) { 1315141cc406Sopenharmony_ci printf ("found possible Mustek parallel port scanner at \"%s\"\n", 1316141cc406Sopenharmony_ci devices[ctr]); 1317141cc406Sopenharmony_ci found++; 1318141cc406Sopenharmony_ci sanei_pa4s2_close(fd); 1319141cc406Sopenharmony_ci } 1320141cc406Sopenharmony_ci 1321141cc406Sopenharmony_ci /* trying scsi over pp devices */ 1322141cc406Sopenharmony_ci if (verbose > 1) 1323141cc406Sopenharmony_ci printf ("checking %s (SCSI emulation)...", devices[ctr]); 1324141cc406Sopenharmony_ci 1325141cc406Sopenharmony_ci result = sanei_pa4s2_scsi_pp_open (devices[ctr], &fd); 1326141cc406Sopenharmony_ci 1327141cc406Sopenharmony_ci if (verbose > 1) 1328141cc406Sopenharmony_ci { 1329141cc406Sopenharmony_ci if (result != 0) 1330141cc406Sopenharmony_ci printf (" failed to open (%s)\n", sane_strstatus (result)); 1331141cc406Sopenharmony_ci else 1332141cc406Sopenharmony_ci printf (" open ok\n"); 1333141cc406Sopenharmony_ci } 1334141cc406Sopenharmony_ci 1335141cc406Sopenharmony_ci if (result == 0) { 1336141cc406Sopenharmony_ci printf ("found possible Mustek SCSI over PP scanner at \"%s\"\n", 1337141cc406Sopenharmony_ci devices[ctr]); 1338141cc406Sopenharmony_ci scsi++; 1339141cc406Sopenharmony_ci sanei_pa4s2_close(fd); 1340141cc406Sopenharmony_ci } 1341141cc406Sopenharmony_ci 1342141cc406Sopenharmony_ci ctr++; 1343141cc406Sopenharmony_ci } 1344141cc406Sopenharmony_ci 1345141cc406Sopenharmony_ci free(devices); 1346141cc406Sopenharmony_ci 1347141cc406Sopenharmony_ci if (found > 0 && verbose > 0) 1348141cc406Sopenharmony_ci printf("\n # Your Mustek parallel port scanner was detected. It may or\n" 1349141cc406Sopenharmony_ci " # may not be supported by SANE. Please read the sane-mustek_pp\n" 1350141cc406Sopenharmony_ci " # man-page for setup instructions.\n"); 1351141cc406Sopenharmony_ci 1352141cc406Sopenharmony_ci if (scsi > 0 && verbose > 0) 1353141cc406Sopenharmony_ci printf("\n # Your Mustek parallel port scanner was detected. It may or\n" 1354141cc406Sopenharmony_ci " # may not be supported by SANE. Please read the sane-mustek_pp\n" 1355141cc406Sopenharmony_ci " # man-page for setup instructions.\n"); 1356141cc406Sopenharmony_ci 1357141cc406Sopenharmony_ci return (found > 0 || scsi > 0); 1358141cc406Sopenharmony_ci} 1359141cc406Sopenharmony_ci 1360141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB_LEGACY 1361141cc406Sopenharmony_cistatic SANE_Bool 1362141cc406Sopenharmony_ciparse_num (char* search, const char* line, int base, long int * number) 1363141cc406Sopenharmony_ci{ 1364141cc406Sopenharmony_ci char* start_number; 1365141cc406Sopenharmony_ci 1366141cc406Sopenharmony_ci start_number = strstr (line, search); 1367141cc406Sopenharmony_ci if (start_number == NULL) 1368141cc406Sopenharmony_ci return SANE_FALSE; 1369141cc406Sopenharmony_ci start_number += strlen (search); 1370141cc406Sopenharmony_ci 1371141cc406Sopenharmony_ci *number = strtol (start_number, NULL, base); 1372141cc406Sopenharmony_ci if (verbose > 2) 1373141cc406Sopenharmony_ci printf ("Found %s%ld\n", search, *number); 1374141cc406Sopenharmony_ci return SANE_TRUE; 1375141cc406Sopenharmony_ci} 1376141cc406Sopenharmony_ci 1377141cc406Sopenharmony_cistatic SANE_Bool 1378141cc406Sopenharmony_ciparse_bcd (char* search, const char* line, long int * number) 1379141cc406Sopenharmony_ci{ 1380141cc406Sopenharmony_ci char* start_number; 1381141cc406Sopenharmony_ci char* end_number; 1382141cc406Sopenharmony_ci int first_part; 1383141cc406Sopenharmony_ci int second_part; 1384141cc406Sopenharmony_ci 1385141cc406Sopenharmony_ci start_number = strstr (line, search); 1386141cc406Sopenharmony_ci if (start_number == NULL) 1387141cc406Sopenharmony_ci return SANE_FALSE; 1388141cc406Sopenharmony_ci start_number += strlen (search); 1389141cc406Sopenharmony_ci 1390141cc406Sopenharmony_ci first_part = strtol (start_number, &end_number, 10); 1391141cc406Sopenharmony_ci start_number = end_number + 1; /* skip colon */ 1392141cc406Sopenharmony_ci second_part = strtol (start_number, NULL, 10); 1393141cc406Sopenharmony_ci *number = ((first_part / 10) << 12) + ((first_part % 10) << 8) 1394141cc406Sopenharmony_ci + ((second_part / 10) << 4) + (second_part % 10); 1395141cc406Sopenharmony_ci if (verbose > 2) 1396141cc406Sopenharmony_ci printf ("Found %s%ld\n", search, *number); 1397141cc406Sopenharmony_ci return SANE_TRUE; 1398141cc406Sopenharmony_ci} 1399141cc406Sopenharmony_ci 1400141cc406Sopenharmony_cistatic void 1401141cc406Sopenharmony_ciparse_file (char *filename) 1402141cc406Sopenharmony_ci{ 1403141cc406Sopenharmony_ci FILE * parsefile; 1404141cc406Sopenharmony_ci char line [PATH_MAX], *token; 1405141cc406Sopenharmony_ci const char * p; 1406141cc406Sopenharmony_ci struct usb_device *dev = 0; 1407141cc406Sopenharmony_ci long int number = 0; 1408141cc406Sopenharmony_ci int current_config = 1; 1409141cc406Sopenharmony_ci int current_if = -1; 1410141cc406Sopenharmony_ci int current_as = -1; 1411141cc406Sopenharmony_ci int current_ep = -1; 1412141cc406Sopenharmony_ci 1413141cc406Sopenharmony_ci if (verbose > 1) 1414141cc406Sopenharmony_ci printf ("trying to open %s\n", filename); 1415141cc406Sopenharmony_ci parsefile = fopen (filename, "r"); 1416141cc406Sopenharmony_ci 1417141cc406Sopenharmony_ci if (parsefile == NULL) 1418141cc406Sopenharmony_ci { 1419141cc406Sopenharmony_ci if (verbose > 0) 1420141cc406Sopenharmony_ci printf ("opening %s failed: %s\n", filename, strerror (errno)); 1421141cc406Sopenharmony_ci return; 1422141cc406Sopenharmony_ci } 1423141cc406Sopenharmony_ci 1424141cc406Sopenharmony_ci while (sanei_config_read (line, PATH_MAX, parsefile)) 1425141cc406Sopenharmony_ci { 1426141cc406Sopenharmony_ci if (verbose > 2) 1427141cc406Sopenharmony_ci printf ("parsing line: `%s'\n", line); 1428141cc406Sopenharmony_ci p = sanei_config_get_string (line, &token); 1429141cc406Sopenharmony_ci if (!token || !p || token[0] == '\0') 1430141cc406Sopenharmony_ci continue; 1431141cc406Sopenharmony_ci if (token[1] != ':') 1432141cc406Sopenharmony_ci { 1433141cc406Sopenharmony_ci if (verbose > 2) 1434141cc406Sopenharmony_ci printf ("missing `:'?\n"); 1435141cc406Sopenharmony_ci continue; 1436141cc406Sopenharmony_ci } 1437141cc406Sopenharmony_ci switch (token[0]) 1438141cc406Sopenharmony_ci { 1439141cc406Sopenharmony_ci case 'T': 1440141cc406Sopenharmony_ci if (dev) 1441141cc406Sopenharmony_ci check_libusb_device (dev, SANE_TRUE); 1442141cc406Sopenharmony_ci dev = calloc (1, sizeof (struct usb_device)); 1443141cc406Sopenharmony_ci dev->bus = calloc (1, sizeof (struct usb_bus)); 1444141cc406Sopenharmony_ci current_config = 1; 1445141cc406Sopenharmony_ci current_if = -1; 1446141cc406Sopenharmony_ci current_as = -1; 1447141cc406Sopenharmony_ci current_ep = -1; 1448141cc406Sopenharmony_ci break; 1449141cc406Sopenharmony_ci case 'D': 1450141cc406Sopenharmony_ci if (parse_bcd ("Ver=", line, &number)) 1451141cc406Sopenharmony_ci dev->descriptor.bcdUSB = number; 1452141cc406Sopenharmony_ci if (parse_num ("Cls=", line, 16, &number)) 1453141cc406Sopenharmony_ci dev->descriptor.bDeviceClass = number; 1454141cc406Sopenharmony_ci if (parse_num ("Sub=", line, 16, &number)) 1455141cc406Sopenharmony_ci dev->descriptor.bDeviceSubClass = number; 1456141cc406Sopenharmony_ci if (parse_num ("Prot=", line, 16, &number)) 1457141cc406Sopenharmony_ci dev->descriptor.bDeviceProtocol = number; 1458141cc406Sopenharmony_ci if (parse_num ("MxPS=", line, 10, &number)) 1459141cc406Sopenharmony_ci dev->descriptor.bMaxPacketSize0 = number; 1460141cc406Sopenharmony_ci if (parse_num ("#Cfgs=", line, 10, &number)) 1461141cc406Sopenharmony_ci dev->descriptor.bNumConfigurations = number; 1462141cc406Sopenharmony_ci dev->config = calloc (number, sizeof (struct usb_config_descriptor)); 1463141cc406Sopenharmony_ci break; 1464141cc406Sopenharmony_ci case 'P': 1465141cc406Sopenharmony_ci if (parse_num ("Vendor=", line, 16, &number)) 1466141cc406Sopenharmony_ci dev->descriptor.idVendor = number; 1467141cc406Sopenharmony_ci if (parse_num ("ProdID=", line, 16, &number)) 1468141cc406Sopenharmony_ci dev->descriptor.idProduct = number; 1469141cc406Sopenharmony_ci if (parse_bcd ("Rev=", line, &number)) 1470141cc406Sopenharmony_ci dev->descriptor.bcdDevice = number; 1471141cc406Sopenharmony_ci break; 1472141cc406Sopenharmony_ci case 'C': 1473141cc406Sopenharmony_ci current_if = -1; 1474141cc406Sopenharmony_ci current_as = -1; 1475141cc406Sopenharmony_ci current_ep = -1; 1476141cc406Sopenharmony_ci if (parse_num ("Cfg#=", line, 10, &number)) 1477141cc406Sopenharmony_ci { 1478141cc406Sopenharmony_ci current_config = number - 1; 1479141cc406Sopenharmony_ci dev->config[current_config].bConfigurationValue = number; 1480141cc406Sopenharmony_ci } 1481141cc406Sopenharmony_ci if (parse_num ("Ifs=", line, 10, &number)) 1482141cc406Sopenharmony_ci dev->config[current_config].bNumInterfaces = number; 1483141cc406Sopenharmony_ci dev->config[current_config].interface 1484141cc406Sopenharmony_ci = calloc (number, sizeof (struct usb_interface)); 1485141cc406Sopenharmony_ci if (parse_num ("Atr=", line, 16, &number)) 1486141cc406Sopenharmony_ci dev->config[current_config].bmAttributes = number; 1487141cc406Sopenharmony_ci if (parse_num ("MxPwr=", line, 10, &number)) 1488141cc406Sopenharmony_ci dev->config[current_config].MaxPower = number / 2; 1489141cc406Sopenharmony_ci break; 1490141cc406Sopenharmony_ci case 'I': 1491141cc406Sopenharmony_ci current_ep = -1; 1492141cc406Sopenharmony_ci if (parse_num ("If#=", line, 10, &number)) 1493141cc406Sopenharmony_ci { 1494141cc406Sopenharmony_ci if (current_if != number) 1495141cc406Sopenharmony_ci { 1496141cc406Sopenharmony_ci current_if = number; 1497141cc406Sopenharmony_ci current_as = -1; 1498141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting 1499141cc406Sopenharmony_ci = calloc (20, sizeof (struct usb_interface_descriptor)); 1500141cc406Sopenharmony_ci /* Can't read number of altsettings */ 1501141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].num_altsetting = 1; 1502141cc406Sopenharmony_ci } 1503141cc406Sopenharmony_ci else 1504141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].num_altsetting++; 1505141cc406Sopenharmony_ci } 1506141cc406Sopenharmony_ci if (parse_num ("Alt=", line, 10, &number)) 1507141cc406Sopenharmony_ci { 1508141cc406Sopenharmony_ci current_as = number; 1509141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceNumber 1510141cc406Sopenharmony_ci = current_if; 1511141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].bAlternateSetting 1512141cc406Sopenharmony_ci = current_as; 1513141cc406Sopenharmony_ci } 1514141cc406Sopenharmony_ci if (parse_num ("#EPs=", line, 10, &number)) 1515141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].bNumEndpoints 1516141cc406Sopenharmony_ci = number; 1517141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].endpoint 1518141cc406Sopenharmony_ci = calloc (number, sizeof (struct usb_endpoint_descriptor)); 1519141cc406Sopenharmony_ci if (parse_num ("Cls=", line, 16, &number)) 1520141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceClass 1521141cc406Sopenharmony_ci = number; 1522141cc406Sopenharmony_ci if (parse_num ("Sub=", line, 16, &number)) 1523141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceSubClass 1524141cc406Sopenharmony_ci = number; 1525141cc406Sopenharmony_ci if (parse_num ("Prot=", line, 16, &number)) 1526141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceProtocol 1527141cc406Sopenharmony_ci = number; 1528141cc406Sopenharmony_ci break; 1529141cc406Sopenharmony_ci case 'E': 1530141cc406Sopenharmony_ci current_ep++; 1531141cc406Sopenharmony_ci if (parse_num ("Ad=", line, 16, &number)) 1532141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as] 1533141cc406Sopenharmony_ci .endpoint[current_ep].bEndpointAddress = number; 1534141cc406Sopenharmony_ci if (parse_num ("Atr=", line, 16, &number)) 1535141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as] 1536141cc406Sopenharmony_ci .endpoint[current_ep].bmAttributes = number; 1537141cc406Sopenharmony_ci if (parse_num ("MxPS=", line, 10, &number)) 1538141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as] 1539141cc406Sopenharmony_ci .endpoint[current_ep].wMaxPacketSize = number; 1540141cc406Sopenharmony_ci if (parse_num ("Ivl=", line, 10, &number)) 1541141cc406Sopenharmony_ci dev->config[current_config].interface[current_if].altsetting[current_as] 1542141cc406Sopenharmony_ci .endpoint[current_ep].bInterval = number; 1543141cc406Sopenharmony_ci break; 1544141cc406Sopenharmony_ci case 'S': 1545141cc406Sopenharmony_ci case 'B': 1546141cc406Sopenharmony_ci continue; 1547141cc406Sopenharmony_ci default: 1548141cc406Sopenharmony_ci if (verbose > 1) 1549141cc406Sopenharmony_ci printf ("ignoring unknown line identifier: %c\n", token[0]); 1550141cc406Sopenharmony_ci continue; 1551141cc406Sopenharmony_ci } 1552141cc406Sopenharmony_ci free (token); 1553141cc406Sopenharmony_ci } 1554141cc406Sopenharmony_ci if (dev) 1555141cc406Sopenharmony_ci check_libusb_device (dev, SANE_TRUE); 1556141cc406Sopenharmony_ci fclose (parsefile); 1557141cc406Sopenharmony_ci return; 1558141cc406Sopenharmony_ci} 1559141cc406Sopenharmony_ci#endif 1560141cc406Sopenharmony_ci 1561141cc406Sopenharmony_ciint 1562141cc406Sopenharmony_cimain (int argc, char **argv) 1563141cc406Sopenharmony_ci{ 1564141cc406Sopenharmony_ci char **dev_list, **usb_dev_list, *dev_name, **ap; 1565141cc406Sopenharmony_ci int enable_pp_checks = SANE_FALSE; 1566141cc406Sopenharmony_ci 1567141cc406Sopenharmony_ci prog_name = strrchr (argv[0], '/'); 1568141cc406Sopenharmony_ci if (prog_name) 1569141cc406Sopenharmony_ci ++prog_name; 1570141cc406Sopenharmony_ci else 1571141cc406Sopenharmony_ci prog_name = argv[0]; 1572141cc406Sopenharmony_ci 1573141cc406Sopenharmony_ci for (ap = argv + 1; ap < argv + argc; ++ap) 1574141cc406Sopenharmony_ci { 1575141cc406Sopenharmony_ci if ((*ap)[0] != '-') 1576141cc406Sopenharmony_ci break; 1577141cc406Sopenharmony_ci switch ((*ap)[1]) 1578141cc406Sopenharmony_ci { 1579141cc406Sopenharmony_ci case '?': 1580141cc406Sopenharmony_ci case 'h': 1581141cc406Sopenharmony_ci usage (0); 1582141cc406Sopenharmony_ci exit (0); 1583141cc406Sopenharmony_ci 1584141cc406Sopenharmony_ci case 'v': 1585141cc406Sopenharmony_ci ++verbose; 1586141cc406Sopenharmony_ci break; 1587141cc406Sopenharmony_ci 1588141cc406Sopenharmony_ci case 'q': 1589141cc406Sopenharmony_ci --verbose; 1590141cc406Sopenharmony_ci break; 1591141cc406Sopenharmony_ci 1592141cc406Sopenharmony_ci case 'f': 1593141cc406Sopenharmony_ci force = SANE_TRUE; 1594141cc406Sopenharmony_ci break; 1595141cc406Sopenharmony_ci 1596141cc406Sopenharmony_ci case 'p': 1597141cc406Sopenharmony_ci enable_pp_checks = SANE_TRUE; 1598141cc406Sopenharmony_ci break; 1599141cc406Sopenharmony_ci 1600141cc406Sopenharmony_ci case 'F': 1601141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB_LEGACY 1602141cc406Sopenharmony_ci parse_file ((char *) (*(++ap))); 1603141cc406Sopenharmony_ci#elif defined(HAVE_LIBUSB) 1604141cc406Sopenharmony_ci printf ("option -F not implemented with libusb-1.0\n"); 1605141cc406Sopenharmony_ci#else 1606141cc406Sopenharmony_ci printf ("libusb not available: option -F can't be used\n"); 1607141cc406Sopenharmony_ci#endif 1608141cc406Sopenharmony_ci exit (0); 1609141cc406Sopenharmony_ci 1610141cc406Sopenharmony_ci case '-': 1611141cc406Sopenharmony_ci if (!strcmp((*ap), "--help")) 1612141cc406Sopenharmony_ci { 1613141cc406Sopenharmony_ci usage (0); 1614141cc406Sopenharmony_ci exit (0); 1615141cc406Sopenharmony_ci } 1616141cc406Sopenharmony_ci // fall through 1617141cc406Sopenharmony_ci default: 1618141cc406Sopenharmony_ci printf ("unknown option: -%c, try -h for help\n", (*ap)[1]); 1619141cc406Sopenharmony_ci exit (0); 1620141cc406Sopenharmony_ci } 1621141cc406Sopenharmony_ci } 1622141cc406Sopenharmony_ci if (ap < argv + argc) 1623141cc406Sopenharmony_ci { 1624141cc406Sopenharmony_ci dev_list = ap; 1625141cc406Sopenharmony_ci usb_dev_list = ap; 1626141cc406Sopenharmony_ci } 1627141cc406Sopenharmony_ci else 1628141cc406Sopenharmony_ci { 1629141cc406Sopenharmony_ci static char *default_dev_list[] = { 1630141cc406Sopenharmony_ci#if defined(__sgi) 1631141cc406Sopenharmony_ci "/dev/scsi/sc0d1l0", "/dev/scsi/sc0d2l0", 1632141cc406Sopenharmony_ci "/dev/scsi/sc0d3l0", "/dev/scsi/sc0d4l0", 1633141cc406Sopenharmony_ci "/dev/scsi/sc0d5l0", "/dev/scsi/sc0d6l0", 1634141cc406Sopenharmony_ci "/dev/scsi/sc0d7l0", "/dev/scsi/sc0d8l0", 1635141cc406Sopenharmony_ci "/dev/scsi/sc0d9l0", "/dev/scsi/sc0d10l0", 1636141cc406Sopenharmony_ci "/dev/scsi/sc0d11l0", "/dev/scsi/sc0d12l0", 1637141cc406Sopenharmony_ci "/dev/scsi/sc0d13l0", "/dev/scsi/sc0d14l0", 1638141cc406Sopenharmony_ci "/dev/scsi/sc0d15l0", 1639141cc406Sopenharmony_ci "/dev/scsi/sc1d1l0", "/dev/scsi/sc1d2l0", 1640141cc406Sopenharmony_ci "/dev/scsi/sc1d3l0", "/dev/scsi/sc1d4l0", 1641141cc406Sopenharmony_ci "/dev/scsi/sc1d5l0", "/dev/scsi/sc1d6l0", 1642141cc406Sopenharmony_ci "/dev/scsi/sc1d7l0", "/dev/scsi/sc1d8l0", 1643141cc406Sopenharmony_ci "/dev/scsi/sc1d9l0", "/dev/scsi/sc1d10l0", 1644141cc406Sopenharmony_ci "/dev/scsi/sc1d11l0", "/dev/scsi/sc1d12l0", 1645141cc406Sopenharmony_ci "/dev/scsi/sc1d13l0", "/dev/scsi/sc1d14l0", 1646141cc406Sopenharmony_ci "/dev/scsi/sc1d15l0", 1647141cc406Sopenharmony_ci "/dev/scsi/sc2d1l0", "/dev/scsi/sc2d2l0", 1648141cc406Sopenharmony_ci "/dev/scsi/sc2d3l0", "/dev/scsi/sc2d4l0", 1649141cc406Sopenharmony_ci "/dev/scsi/sc2d5l0", "/dev/scsi/sc2d6l0", 1650141cc406Sopenharmony_ci "/dev/scsi/sc2d7l0", "/dev/scsi/sc2d8l0", 1651141cc406Sopenharmony_ci "/dev/scsi/sc2d9l0", "/dev/scsi/sc2d10l0", 1652141cc406Sopenharmony_ci "/dev/scsi/sc2d11l0", "/dev/scsi/sc2d12l0", 1653141cc406Sopenharmony_ci "/dev/scsi/sc2d13l0", "/dev/scsi/sc2d14l0", 1654141cc406Sopenharmony_ci "/dev/scsi/sc2d15l0", 1655141cc406Sopenharmony_ci "/dev/scsi/sc3d1l0", "/dev/scsi/sc3d2l0", 1656141cc406Sopenharmony_ci "/dev/scsi/sc3d3l0", "/dev/scsi/sc3d4l0", 1657141cc406Sopenharmony_ci "/dev/scsi/sc3d5l0", "/dev/scsi/sc3d6l0", 1658141cc406Sopenharmony_ci "/dev/scsi/sc3d7l0", "/dev/scsi/sc3d8l0", 1659141cc406Sopenharmony_ci "/dev/scsi/sc3d9l0", "/dev/scsi/sc3d10l0", 1660141cc406Sopenharmony_ci "/dev/scsi/sc3d11l0", "/dev/scsi/sc3d12l0", 1661141cc406Sopenharmony_ci "/dev/scsi/sc3d13l0", "/dev/scsi/sc3d14l0", 1662141cc406Sopenharmony_ci "/dev/scsi/sc3d15l0", 1663141cc406Sopenharmony_ci "/dev/scsi/sc4d1l0", "/dev/scsi/sc4d2l0", 1664141cc406Sopenharmony_ci "/dev/scsi/sc4d3l0", "/dev/scsi/sc4d4l0", 1665141cc406Sopenharmony_ci "/dev/scsi/sc4d5l0", "/dev/scsi/sc4d6l0", 1666141cc406Sopenharmony_ci "/dev/scsi/sc4d7l0", "/dev/scsi/sc4d8l0", 1667141cc406Sopenharmony_ci "/dev/scsi/sc4d9l0", "/dev/scsi/sc4d10l0", 1668141cc406Sopenharmony_ci "/dev/scsi/sc4d11l0", "/dev/scsi/sc4d12l0", 1669141cc406Sopenharmony_ci "/dev/scsi/sc4d13l0", "/dev/scsi/sc4d14l0", 1670141cc406Sopenharmony_ci "/dev/scsi/sc4d15l0", 1671141cc406Sopenharmony_ci "/dev/scsi/sc5d1l0", "/dev/scsi/sc5d2l0", 1672141cc406Sopenharmony_ci "/dev/scsi/sc5d3l0", "/dev/scsi/sc5d4l0", 1673141cc406Sopenharmony_ci "/dev/scsi/sc5d5l0", "/dev/scsi/sc5d6l0", 1674141cc406Sopenharmony_ci "/dev/scsi/sc5d7l0", "/dev/scsi/sc5d8l0", 1675141cc406Sopenharmony_ci "/dev/scsi/sc5d9l0", "/dev/scsi/sc5d10l0", 1676141cc406Sopenharmony_ci "/dev/scsi/sc5d11l0", "/dev/scsi/sc5d12l0", 1677141cc406Sopenharmony_ci "/dev/scsi/sc5d13l0", "/dev/scsi/sc5d14l0", 1678141cc406Sopenharmony_ci "/dev/scsi/sc5d15l0", 1679141cc406Sopenharmony_ci "/dev/scsi/sc6d1l0", "/dev/scsi/sc6d2l0", 1680141cc406Sopenharmony_ci "/dev/scsi/sc6d3l0", "/dev/scsi/sc6d4l0", 1681141cc406Sopenharmony_ci "/dev/scsi/sc6d5l0", "/dev/scsi/sc6d6l0", 1682141cc406Sopenharmony_ci "/dev/scsi/sc6d7l0", "/dev/scsi/sc6d8l0", 1683141cc406Sopenharmony_ci "/dev/scsi/sc6d9l0", "/dev/scsi/sc6d10l0", 1684141cc406Sopenharmony_ci "/dev/scsi/sc6d11l0", "/dev/scsi/sc6d12l0", 1685141cc406Sopenharmony_ci "/dev/scsi/sc6d13l0", "/dev/scsi/sc6d14l0", 1686141cc406Sopenharmony_ci "/dev/scsi/sc6d15l0", 1687141cc406Sopenharmony_ci "/dev/scsi/sc7d1l0", "/dev/scsi/sc7d2l0", 1688141cc406Sopenharmony_ci "/dev/scsi/sc7d3l0", "/dev/scsi/sc7d4l0", 1689141cc406Sopenharmony_ci "/dev/scsi/sc7d5l0", "/dev/scsi/sc7d6l0", 1690141cc406Sopenharmony_ci "/dev/scsi/sc7d7l0", "/dev/scsi/sc7d8l0", 1691141cc406Sopenharmony_ci "/dev/scsi/sc7d9l0", "/dev/scsi/sc7d10l0", 1692141cc406Sopenharmony_ci "/dev/scsi/sc7d11l0", "/dev/scsi/sc7d12l0", 1693141cc406Sopenharmony_ci "/dev/scsi/sc7d13l0", "/dev/scsi/sc7d14l0", 1694141cc406Sopenharmony_ci "/dev/scsi/sc7d15l0", 1695141cc406Sopenharmony_ci "/dev/scsi/sc8d1l0", "/dev/scsi/sc8d2l0", 1696141cc406Sopenharmony_ci "/dev/scsi/sc8d3l0", "/dev/scsi/sc8d4l0", 1697141cc406Sopenharmony_ci "/dev/scsi/sc8d5l0", "/dev/scsi/sc8d6l0", 1698141cc406Sopenharmony_ci "/dev/scsi/sc8d7l0", "/dev/scsi/sc8d8l0", 1699141cc406Sopenharmony_ci "/dev/scsi/sc8d9l0", "/dev/scsi/sc8d10l0", 1700141cc406Sopenharmony_ci "/dev/scsi/sc8d11l0", "/dev/scsi/sc8d12l0", 1701141cc406Sopenharmony_ci "/dev/scsi/sc8d13l0", "/dev/scsi/sc8d14l0", 1702141cc406Sopenharmony_ci "/dev/scsi/sc8d15l0", 1703141cc406Sopenharmony_ci "/dev/scsi/sc9d1l0", "/dev/scsi/sc9d2l0", 1704141cc406Sopenharmony_ci "/dev/scsi/sc9d3l0", "/dev/scsi/sc9d4l0", 1705141cc406Sopenharmony_ci "/dev/scsi/sc9d5l0", "/dev/scsi/sc9d6l0", 1706141cc406Sopenharmony_ci "/dev/scsi/sc9d7l0", "/dev/scsi/sc9d8l0", 1707141cc406Sopenharmony_ci "/dev/scsi/sc9d9l0", "/dev/scsi/sc9d10l0", 1708141cc406Sopenharmony_ci "/dev/scsi/sc9d11l0", "/dev/scsi/sc9d12l0", 1709141cc406Sopenharmony_ci "/dev/scsi/sc9d13l0", "/dev/scsi/sc9d14l0", 1710141cc406Sopenharmony_ci "/dev/scsi/sc9d15l0", 1711141cc406Sopenharmony_ci "/dev/scsi/sc10d1l0", "/dev/scsi/sc10d2l0", 1712141cc406Sopenharmony_ci "/dev/scsi/sc10d3l0", "/dev/scsi/sc10d4l0", 1713141cc406Sopenharmony_ci "/dev/scsi/sc10d5l0", "/dev/scsi/sc10d6l0", 1714141cc406Sopenharmony_ci "/dev/scsi/sc10d7l0", "/dev/scsi/sc10d8l0", 1715141cc406Sopenharmony_ci "/dev/scsi/sc10d9l0", "/dev/scsi/sc10d10l0", 1716141cc406Sopenharmony_ci "/dev/scsi/sc10d11l0", "/dev/scsi/sc10d12l0", 1717141cc406Sopenharmony_ci "/dev/scsi/sc10d13l0", "/dev/scsi/sc10d14l0", 1718141cc406Sopenharmony_ci "/dev/scsi/sc10d15l0", 1719141cc406Sopenharmony_ci "/dev/scsi/sc11d1l0", "/dev/scsi/sc11d2l0", 1720141cc406Sopenharmony_ci "/dev/scsi/sc11d3l0", "/dev/scsi/sc11d4l0", 1721141cc406Sopenharmony_ci "/dev/scsi/sc11d5l0", "/dev/scsi/sc11d6l0", 1722141cc406Sopenharmony_ci "/dev/scsi/sc11d7l0", "/dev/scsi/sc11d8l0", 1723141cc406Sopenharmony_ci "/dev/scsi/sc11d9l0", "/dev/scsi/sc11d10l0", 1724141cc406Sopenharmony_ci "/dev/scsi/sc11d11l0", "/dev/scsi/sc11d12l0", 1725141cc406Sopenharmony_ci "/dev/scsi/sc11d13l0", "/dev/scsi/sc11d14l0", 1726141cc406Sopenharmony_ci "/dev/scsi/sc11d15l0", 1727141cc406Sopenharmony_ci "/dev/scsi/sc12d1l0", "/dev/scsi/sc12d2l0", 1728141cc406Sopenharmony_ci "/dev/scsi/sc12d3l0", "/dev/scsi/sc12d4l0", 1729141cc406Sopenharmony_ci "/dev/scsi/sc12d5l0", "/dev/scsi/sc12d6l0", 1730141cc406Sopenharmony_ci "/dev/scsi/sc12d7l0", "/dev/scsi/sc12d8l0", 1731141cc406Sopenharmony_ci "/dev/scsi/sc12d9l0", "/dev/scsi/sc12d10l0", 1732141cc406Sopenharmony_ci "/dev/scsi/sc12d11l0", "/dev/scsi/sc12d12l0", 1733141cc406Sopenharmony_ci "/dev/scsi/sc12d13l0", "/dev/scsi/sc12d14l0", 1734141cc406Sopenharmony_ci "/dev/scsi/sc12d15l0", 1735141cc406Sopenharmony_ci "/dev/scsi/sc13d1l0", "/dev/scsi/sc13d2l0", 1736141cc406Sopenharmony_ci "/dev/scsi/sc13d3l0", "/dev/scsi/sc13d4l0", 1737141cc406Sopenharmony_ci "/dev/scsi/sc13d5l0", "/dev/scsi/sc13d6l0", 1738141cc406Sopenharmony_ci "/dev/scsi/sc13d7l0", "/dev/scsi/sc13d8l0", 1739141cc406Sopenharmony_ci "/dev/scsi/sc13d9l0", "/dev/scsi/sc13d10l0", 1740141cc406Sopenharmony_ci "/dev/scsi/sc13d11l0", "/dev/scsi/sc13d12l0", 1741141cc406Sopenharmony_ci "/dev/scsi/sc13d13l0", "/dev/scsi/sc13d14l0", 1742141cc406Sopenharmony_ci "/dev/scsi/sc13d15l0", 1743141cc406Sopenharmony_ci "/dev/scsi/sc14d1l0", "/dev/scsi/sc14d2l0", 1744141cc406Sopenharmony_ci "/dev/scsi/sc14d3l0", "/dev/scsi/sc14d4l0", 1745141cc406Sopenharmony_ci "/dev/scsi/sc14d5l0", "/dev/scsi/sc14d6l0", 1746141cc406Sopenharmony_ci "/dev/scsi/sc14d7l0", "/dev/scsi/sc14d8l0", 1747141cc406Sopenharmony_ci "/dev/scsi/sc14d9l0", "/dev/scsi/sc14d10l0", 1748141cc406Sopenharmony_ci "/dev/scsi/sc14d11l0", "/dev/scsi/sc14d12l0", 1749141cc406Sopenharmony_ci "/dev/scsi/sc14d13l0", "/dev/scsi/sc14d14l0", 1750141cc406Sopenharmony_ci "/dev/scsi/sc14d15l0", 1751141cc406Sopenharmony_ci "/dev/scsi/sc15d1l0", "/dev/scsi/sc15d2l0", 1752141cc406Sopenharmony_ci "/dev/scsi/sc15d3l0", "/dev/scsi/sc15d4l0", 1753141cc406Sopenharmony_ci "/dev/scsi/sc15d5l0", "/dev/scsi/sc15d6l0", 1754141cc406Sopenharmony_ci "/dev/scsi/sc15d7l0", "/dev/scsi/sc15d8l0", 1755141cc406Sopenharmony_ci "/dev/scsi/sc15d9l0", "/dev/scsi/sc15d10l0", 1756141cc406Sopenharmony_ci "/dev/scsi/sc15d11l0", "/dev/scsi/sc15d12l0", 1757141cc406Sopenharmony_ci "/dev/scsi/sc15d13l0", "/dev/scsi/sc15d14l0", 1758141cc406Sopenharmony_ci "/dev/scsi/sc15d15l0", 1759141cc406Sopenharmony_ci#elif defined(__EMX__) 1760141cc406Sopenharmony_ci "b0t0l0", "b0t1l0", "b0t2l0", "b0t3l0", 1761141cc406Sopenharmony_ci "b0t4l0", "b0t5l0", "b0t6l0", "b0t7l0", 1762141cc406Sopenharmony_ci "b1t0l0", "b1t1l0", "b1t2l0", "b1t3l0", 1763141cc406Sopenharmony_ci "b1t4l0", "b1t5l0", "b1t6l0", "b1t7l0", 1764141cc406Sopenharmony_ci "b2t0l0", "b2t1l0", "b2t2l0", "b2t3l0", 1765141cc406Sopenharmony_ci "b2t4l0", "b2t5l0", "b2t6l0", "b2t7l0", 1766141cc406Sopenharmony_ci "b3t0l0", "b3t1l0", "b3t2l0", "b3t3l0", 1767141cc406Sopenharmony_ci "b3t4l0", "b3t5l0", "b3t6l0", "b3t7l0", 1768141cc406Sopenharmony_ci#elif defined(__linux__) 1769141cc406Sopenharmony_ci "/dev/scanner", 1770141cc406Sopenharmony_ci "/dev/sg0", "/dev/sg1", "/dev/sg2", "/dev/sg3", 1771141cc406Sopenharmony_ci "/dev/sg4", "/dev/sg5", "/dev/sg6", "/dev/sg7", 1772141cc406Sopenharmony_ci "/dev/sg8", "/dev/sg9", 1773141cc406Sopenharmony_ci "/dev/sga", "/dev/sgb", "/dev/sgc", "/dev/sgd", 1774141cc406Sopenharmony_ci "/dev/sge", "/dev/sgf", "/dev/sgg", "/dev/sgh", 1775141cc406Sopenharmony_ci "/dev/sgi", "/dev/sgj", "/dev/sgk", "/dev/sgl", 1776141cc406Sopenharmony_ci "/dev/sgm", "/dev/sgn", "/dev/sgo", "/dev/sgp", 1777141cc406Sopenharmony_ci "/dev/sgq", "/dev/sgr", "/dev/sgs", "/dev/sgt", 1778141cc406Sopenharmony_ci "/dev/sgu", "/dev/sgv", "/dev/sgw", "/dev/sgx", 1779141cc406Sopenharmony_ci "/dev/sgy", "/dev/sgz", 1780141cc406Sopenharmony_ci#elif defined(__NeXT__) 1781141cc406Sopenharmony_ci "/dev/sg0a", "/dev/sg0b", "/dev/sg0c", "/dev/sg0d", 1782141cc406Sopenharmony_ci "/dev/sg0e", "/dev/sg0f", "/dev/sg0g", "/dev/sg0h", 1783141cc406Sopenharmony_ci "/dev/sg1a", "/dev/sg1b", "/dev/sg1c", "/dev/sg1d", 1784141cc406Sopenharmony_ci "/dev/sg1e", "/dev/sg1f", "/dev/sg1g", "/dev/sg1h", 1785141cc406Sopenharmony_ci "/dev/sg2a", "/dev/sg2b", "/dev/sg2c", "/dev/sg2d", 1786141cc406Sopenharmony_ci "/dev/sg2e", "/dev/sg2f", "/dev/sg2g", "/dev/sg2h", 1787141cc406Sopenharmony_ci "/dev/sg3a", "/dev/sg3b", "/dev/sg3c", "/dev/sg3d", 1788141cc406Sopenharmony_ci "/dev/sg3e", "/dev/sg3f", "/dev/sg3g", "/dev/sg3h", 1789141cc406Sopenharmony_ci#elif defined(_AIX) 1790141cc406Sopenharmony_ci "/dev/scanner", 1791141cc406Sopenharmony_ci "/dev/gsc0", "/dev/gsc1", "/dev/gsc2", "/dev/gsc3", 1792141cc406Sopenharmony_ci "/dev/gsc4", "/dev/gsc5", "/dev/gsc6", "/dev/gsc7", 1793141cc406Sopenharmony_ci "/dev/gsc8", "/dev/gsc9", "/dev/gsc10", "/dev/gsc11", 1794141cc406Sopenharmony_ci "/dev/gsc12", "/dev/gsc13", "/dev/gsc14", "/dev/gsc15", 1795141cc406Sopenharmony_ci#elif defined(__sun) 1796141cc406Sopenharmony_ci "/dev/scg0a", "/dev/scg0b", "/dev/scg0c", "/dev/scg0d", 1797141cc406Sopenharmony_ci "/dev/scg0e", "/dev/scg0f", "/dev/scg0g", 1798141cc406Sopenharmony_ci "/dev/scg1a", "/dev/scg1b", "/dev/scg1c", "/dev/scg1d", 1799141cc406Sopenharmony_ci "/dev/scg1e", "/dev/scg1f", "/dev/scg1g", 1800141cc406Sopenharmony_ci "/dev/scg2a", "/dev/scg2b", "/dev/scg2c", "/dev/scg2d", 1801141cc406Sopenharmony_ci "/dev/scg2e", "/dev/scg2f", "/dev/scg2g", 1802141cc406Sopenharmony_ci "/dev/sg/0", "/dev/sg/1", "/dev/sg/2", "/dev/sg/3", 1803141cc406Sopenharmony_ci "/dev/sg/4", "/dev/sg/5", "/dev/sg/6", 1804141cc406Sopenharmony_ci "/dev/scsi/scanner/", "/dev/scsi/processor/", 1805141cc406Sopenharmony_ci#elif defined(HAVE_CAMLIB_H) 1806141cc406Sopenharmony_ci "/dev/scanner", "/dev/scanner0", "/dev/scanner1", 1807141cc406Sopenharmony_ci "/dev/pass0", "/dev/pass1", "/dev/pass2", "/dev/pass3", 1808141cc406Sopenharmony_ci "/dev/pass4", "/dev/pass5", "/dev/pass6", "/dev/pass7", 1809141cc406Sopenharmony_ci#elif defined(__FreeBSD__) || defined(__DragonFly__) 1810141cc406Sopenharmony_ci "/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4", 1811141cc406Sopenharmony_ci "/dev/uk5", "/dev/uk6", 1812141cc406Sopenharmony_ci#elif defined(__NetBSD__) 1813141cc406Sopenharmony_ci "/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4", 1814141cc406Sopenharmony_ci "/dev/uk5", "/dev/uk6", 1815141cc406Sopenharmony_ci "/dev/ss0", 1816141cc406Sopenharmony_ci#elif defined(__OpenBSD__) 1817141cc406Sopenharmony_ci "/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4", 1818141cc406Sopenharmony_ci "/dev/uk5", "/dev/uk6", 1819141cc406Sopenharmony_ci#elif defined(__hpux) 1820141cc406Sopenharmony_ci "/dev/rscsi/", 1821141cc406Sopenharmony_ci#endif 1822141cc406Sopenharmony_ci 0 1823141cc406Sopenharmony_ci }; 1824141cc406Sopenharmony_ci static char *usb_default_dev_list[] = { 1825141cc406Sopenharmony_ci#if defined(__linux__) 1826141cc406Sopenharmony_ci "/dev/usb/scanner", 1827141cc406Sopenharmony_ci "/dev/usb/scanner0", "/dev/usb/scanner1", 1828141cc406Sopenharmony_ci "/dev/usb/scanner2", "/dev/usb/scanner3", 1829141cc406Sopenharmony_ci "/dev/usb/scanner4", "/dev/usb/scanner5", 1830141cc406Sopenharmony_ci "/dev/usb/scanner5", "/dev/usb/scanner7", 1831141cc406Sopenharmony_ci "/dev/usb/scanner8", "/dev/usb/scanner9", 1832141cc406Sopenharmony_ci "/dev/usb/scanner10", "/dev/usb/scanner11", 1833141cc406Sopenharmony_ci "/dev/usb/scanner12", "/dev/usb/scanner13", 1834141cc406Sopenharmony_ci "/dev/usb/scanner14", "/dev/usb/scanner15", 1835141cc406Sopenharmony_ci "/dev/usbscanner", 1836141cc406Sopenharmony_ci "/dev/usbscanner0", "/dev/usbscanner1", 1837141cc406Sopenharmony_ci "/dev/usbscanner2", "/dev/usbscanner3", 1838141cc406Sopenharmony_ci "/dev/usbscanner4", "/dev/usbscanner5", 1839141cc406Sopenharmony_ci "/dev/usbscanner6", "/dev/usbscanner7", 1840141cc406Sopenharmony_ci "/dev/usbscanner8", "/dev/usbscanner9", 1841141cc406Sopenharmony_ci "/dev/usbscanner10", "/dev/usbscanner11", 1842141cc406Sopenharmony_ci "/dev/usbscanner12", "/dev/usbscanner13", 1843141cc406Sopenharmony_ci "/dev/usbscanner14", "/dev/usbscanner15", 1844141cc406Sopenharmony_ci#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) 1845141cc406Sopenharmony_ci "/dev/uscanner", 1846141cc406Sopenharmony_ci "/dev/uscanner0", "/dev/uscanner1", 1847141cc406Sopenharmony_ci "/dev/uscanner2", "/dev/uscanner3", 1848141cc406Sopenharmony_ci "/dev/uscanner4", "/dev/uscanner5", 1849141cc406Sopenharmony_ci "/dev/uscanner6", "/dev/uscanner7", 1850141cc406Sopenharmony_ci "/dev/uscanner8", "/dev/uscanner9", 1851141cc406Sopenharmony_ci "/dev/uscanner10", "/dev/uscanner11", 1852141cc406Sopenharmony_ci "/dev/uscanner12", "/dev/uscanner13", 1853141cc406Sopenharmony_ci "/dev/uscanner14", "/dev/uscanner15", 1854141cc406Sopenharmony_ci#endif 1855141cc406Sopenharmony_ci 0 1856141cc406Sopenharmony_ci }; 1857141cc406Sopenharmony_ci 1858141cc406Sopenharmony_ci#if defined (WIN32_SCSI) || \ 1859141cc406Sopenharmony_ci defined (HAVE_IOKIT_CDB_IOSCSILIB_H) || \ 1860141cc406Sopenharmony_ci defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ 1861141cc406Sopenharmony_ci defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) 1862141cc406Sopenharmony_ci /* Build a list of valid of possible scanners found */ 1863141cc406Sopenharmony_ci dev_list = build_scsi_dev_list(); 1864141cc406Sopenharmony_ci#else 1865141cc406Sopenharmony_ci dev_list = default_dev_list; 1866141cc406Sopenharmony_ci#endif 1867141cc406Sopenharmony_ci 1868141cc406Sopenharmony_ci usb_dev_list = usb_default_dev_list; 1869141cc406Sopenharmony_ci } 1870141cc406Sopenharmony_ci if (verbose > 1) 1871141cc406Sopenharmony_ci printf ("This is sane-find-scanner from %s\n", PACKAGE_STRING); 1872141cc406Sopenharmony_ci 1873141cc406Sopenharmony_ci if (verbose > 0) 1874141cc406Sopenharmony_ci printf ("\n # sane-find-scanner will now attempt to detect your scanner. If the" 1875141cc406Sopenharmony_ci "\n # result is different from what you expected, first make sure your" 1876141cc406Sopenharmony_ci "\n # scanner is powered up and properly connected to your computer.\n\n"); 1877141cc406Sopenharmony_ci 1878141cc406Sopenharmony_ci if (verbose > 1) 1879141cc406Sopenharmony_ci printf ("searching for SCSI scanners:\n"); 1880141cc406Sopenharmony_ci 1881141cc406Sopenharmony_ci while ((dev_name = *dev_list++)) 1882141cc406Sopenharmony_ci { 1883141cc406Sopenharmony_ci if (strlen (dev_name) == 0) 1884141cc406Sopenharmony_ci continue; /* Empty device names ... */ 1885141cc406Sopenharmony_ci 1886141cc406Sopenharmony_ci if (dev_name[strlen (dev_name) - 1] == '/') 1887141cc406Sopenharmony_ci { 1888141cc406Sopenharmony_ci /* check whole directories */ 1889141cc406Sopenharmony_ci DIR *dir; 1890141cc406Sopenharmony_ci char *file_name; 1891141cc406Sopenharmony_ci 1892141cc406Sopenharmony_ci dir = scan_directory (dev_name); 1893141cc406Sopenharmony_ci if (!dir) 1894141cc406Sopenharmony_ci continue; 1895141cc406Sopenharmony_ci 1896141cc406Sopenharmony_ci while ((file_name = get_next_file (dev_name, dir))) 1897141cc406Sopenharmony_ci check_scsi_file (file_name); 1898141cc406Sopenharmony_ci } 1899141cc406Sopenharmony_ci else 1900141cc406Sopenharmony_ci { 1901141cc406Sopenharmony_ci /* check device files */ 1902141cc406Sopenharmony_ci check_scsi_file (dev_name); 1903141cc406Sopenharmony_ci } 1904141cc406Sopenharmony_ci } 1905141cc406Sopenharmony_ci if (device_found) 1906141cc406Sopenharmony_ci { 1907141cc406Sopenharmony_ci if (verbose > 0) 1908141cc406Sopenharmony_ci printf 1909141cc406Sopenharmony_ci (" # Your SCSI scanner was detected. It may or may not be " 1910141cc406Sopenharmony_ci "supported by SANE. Try\n # scanimage -L and read the backend's " 1911141cc406Sopenharmony_ci "manpage.\n"); 1912141cc406Sopenharmony_ci } 1913141cc406Sopenharmony_ci else 1914141cc406Sopenharmony_ci { 1915141cc406Sopenharmony_ci if (verbose > 0) 1916141cc406Sopenharmony_ci printf 1917141cc406Sopenharmony_ci (" # No SCSI scanners found. If you expected something different, " 1918141cc406Sopenharmony_ci "make sure that\n # you have loaded a kernel SCSI driver for your SCSI " 1919141cc406Sopenharmony_ci "adapter.\n"); 1920141cc406Sopenharmony_ci if (!check_sg ()) 1921141cc406Sopenharmony_ci { 1922141cc406Sopenharmony_ci if (verbose > 0) 1923141cc406Sopenharmony_ci printf 1924141cc406Sopenharmony_ci (" # Also you need support for SCSI Generic (sg) in your " 1925141cc406Sopenharmony_ci "operating system.\n # If using Linux, try \"modprobe " 1926141cc406Sopenharmony_ci "sg\".\n"); 1927141cc406Sopenharmony_ci } 1928141cc406Sopenharmony_ci } 1929141cc406Sopenharmony_ci if (verbose > 0) 1930141cc406Sopenharmony_ci printf ("\n"); 1931141cc406Sopenharmony_ci device_found = SANE_FALSE; 1932141cc406Sopenharmony_ci sanei_usb_init (); 1933141cc406Sopenharmony_ci if (verbose > 1) 1934141cc406Sopenharmony_ci printf ("searching for USB scanners:\n"); 1935141cc406Sopenharmony_ci 1936141cc406Sopenharmony_ci while ((dev_name = *usb_dev_list++)) 1937141cc406Sopenharmony_ci { 1938141cc406Sopenharmony_ci if (strlen (dev_name) == 0) 1939141cc406Sopenharmony_ci continue; /* Empty device names ... */ 1940141cc406Sopenharmony_ci 1941141cc406Sopenharmony_ci if (dev_name[strlen (dev_name) - 1] == '/') 1942141cc406Sopenharmony_ci { 1943141cc406Sopenharmony_ci /* check whole directories */ 1944141cc406Sopenharmony_ci DIR *dir; 1945141cc406Sopenharmony_ci char *file_name; 1946141cc406Sopenharmony_ci 1947141cc406Sopenharmony_ci dir = scan_directory (dev_name); 1948141cc406Sopenharmony_ci if (!dir) 1949141cc406Sopenharmony_ci continue; 1950141cc406Sopenharmony_ci 1951141cc406Sopenharmony_ci while ((file_name = get_next_file (dev_name, dir))) 1952141cc406Sopenharmony_ci check_usb_file (file_name); 1953141cc406Sopenharmony_ci } 1954141cc406Sopenharmony_ci else 1955141cc406Sopenharmony_ci { 1956141cc406Sopenharmony_ci /* check device files */ 1957141cc406Sopenharmony_ci check_usb_file (dev_name); 1958141cc406Sopenharmony_ci } 1959141cc406Sopenharmony_ci } 1960141cc406Sopenharmony_ci#ifdef HAVE_LIBUSB_LEGACY 1961141cc406Sopenharmony_ci /* Now the libusb devices */ 1962141cc406Sopenharmony_ci { 1963141cc406Sopenharmony_ci struct usb_bus *bus; 1964141cc406Sopenharmony_ci struct usb_device *dev; 1965141cc406Sopenharmony_ci 1966141cc406Sopenharmony_ci if (ap < argv + argc) 1967141cc406Sopenharmony_ci { 1968141cc406Sopenharmony_ci /* user-specified devices not useful for libusb */ 1969141cc406Sopenharmony_ci if (verbose > 1) 1970141cc406Sopenharmony_ci printf ("ignoring libusb devices\n"); 1971141cc406Sopenharmony_ci } 1972141cc406Sopenharmony_ci else 1973141cc406Sopenharmony_ci { 1974141cc406Sopenharmony_ci if (verbose > 2) 1975141cc406Sopenharmony_ci printf ("trying libusb:\n"); 1976141cc406Sopenharmony_ci for (bus = usb_get_busses (); bus; bus = bus->next) 1977141cc406Sopenharmony_ci { 1978141cc406Sopenharmony_ci for (dev = bus->devices; dev; dev = dev->next) 1979141cc406Sopenharmony_ci { 1980141cc406Sopenharmony_ci check_libusb_device (dev, SANE_FALSE); 1981141cc406Sopenharmony_ci } /* for (dev) */ 1982141cc406Sopenharmony_ci } /* for (bus) */ 1983141cc406Sopenharmony_ci } 1984141cc406Sopenharmony_ci } 1985141cc406Sopenharmony_ci#elif defined(HAVE_LIBUSB) 1986141cc406Sopenharmony_ci /* Now the libusb-1.0 devices */ 1987141cc406Sopenharmony_ci { 1988141cc406Sopenharmony_ci if (ap < argv + argc) 1989141cc406Sopenharmony_ci { 1990141cc406Sopenharmony_ci /* user-specified devices not useful for libusb */ 1991141cc406Sopenharmony_ci if (verbose > 1) 1992141cc406Sopenharmony_ci printf ("ignoring libusb devices\n"); 1993141cc406Sopenharmony_ci } 1994141cc406Sopenharmony_ci else 1995141cc406Sopenharmony_ci { 1996141cc406Sopenharmony_ci libusb_device **devlist; 1997141cc406Sopenharmony_ci ssize_t devcnt; 1998141cc406Sopenharmony_ci int i; 1999141cc406Sopenharmony_ci int ret; 2000141cc406Sopenharmony_ci 2001141cc406Sopenharmony_ci if (verbose > 2) 2002141cc406Sopenharmony_ci printf ("trying libusb:\n"); 2003141cc406Sopenharmony_ci 2004141cc406Sopenharmony_ci ret = libusb_init (&sfs_usb_ctx); 2005141cc406Sopenharmony_ci if (ret < 0) 2006141cc406Sopenharmony_ci { 2007141cc406Sopenharmony_ci printf ("# Could not initialize libusb-1.0, error %d\n", ret); 2008141cc406Sopenharmony_ci printf ("# Skipping libusb devices\n"); 2009141cc406Sopenharmony_ci 2010141cc406Sopenharmony_ci goto failed_libusb_1_0; 2011141cc406Sopenharmony_ci } 2012141cc406Sopenharmony_ci 2013141cc406Sopenharmony_ci if (verbose > 3) 2014141cc406Sopenharmony_ci#if LIBUSB_API_VERSION >= 0x01000106 2015141cc406Sopenharmony_ci libusb_set_option (sfs_usb_ctx, LIBUSB_OPTION_LOG_LEVEL, 2016141cc406Sopenharmony_ci LIBUSB_LOG_LEVEL_INFO); 2017141cc406Sopenharmony_ci#else 2018141cc406Sopenharmony_ci libusb_set_debug (sfs_usb_ctx, 3); 2019141cc406Sopenharmony_ci#endif 2020141cc406Sopenharmony_ci 2021141cc406Sopenharmony_ci devcnt = libusb_get_device_list (sfs_usb_ctx, &devlist); 2022141cc406Sopenharmony_ci if (devcnt < 0) 2023141cc406Sopenharmony_ci { 2024141cc406Sopenharmony_ci printf ("# Could not get device list, error %d\n", ret); 2025141cc406Sopenharmony_ci 2026141cc406Sopenharmony_ci goto deinit_libusb_1_0; 2027141cc406Sopenharmony_ci } 2028141cc406Sopenharmony_ci 2029141cc406Sopenharmony_ci for (i = 0; i < devcnt; i++) 2030141cc406Sopenharmony_ci { 2031141cc406Sopenharmony_ci check_libusb_device (devlist[i], SANE_FALSE); 2032141cc406Sopenharmony_ci } 2033141cc406Sopenharmony_ci 2034141cc406Sopenharmony_ci libusb_free_device_list (devlist, 1); 2035141cc406Sopenharmony_ci 2036141cc406Sopenharmony_ci deinit_libusb_1_0: 2037141cc406Sopenharmony_ci libusb_exit (sfs_usb_ctx); 2038141cc406Sopenharmony_ci 2039141cc406Sopenharmony_ci failed_libusb_1_0: 2040141cc406Sopenharmony_ci ; /* init failed, jumping here */ 2041141cc406Sopenharmony_ci } 2042141cc406Sopenharmony_ci } 2043141cc406Sopenharmony_ci#else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ 2044141cc406Sopenharmony_ci if (verbose > 1) 2045141cc406Sopenharmony_ci printf ("libusb not available\n"); 2046141cc406Sopenharmony_ci#endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ 2047141cc406Sopenharmony_ci 2048141cc406Sopenharmony_ci if (device_found) 2049141cc406Sopenharmony_ci { 2050141cc406Sopenharmony_ci if (libusb_device_found) 2051141cc406Sopenharmony_ci { 2052141cc406Sopenharmony_ci if (verbose > 0) 2053141cc406Sopenharmony_ci printf 2054141cc406Sopenharmony_ci (" # Your USB scanner was (probably) detected. It " 2055141cc406Sopenharmony_ci "may or may not be supported by\n # SANE. Try scanimage " 2056141cc406Sopenharmony_ci "-L and read the backend's manpage.\n"); 2057141cc406Sopenharmony_ci } 2058141cc406Sopenharmony_ci else if (verbose > 0) 2059141cc406Sopenharmony_ci printf 2060141cc406Sopenharmony_ci (" # Your USB scanner was detected. It may or may not " 2061141cc406Sopenharmony_ci "be supported by\n # SANE. Try scanimage -L and read the " 2062141cc406Sopenharmony_ci "backend's manpage.\n"); 2063141cc406Sopenharmony_ci if (unknown_found && verbose > 0) 2064141cc406Sopenharmony_ci printf 2065141cc406Sopenharmony_ci (" # `UNKNOWN vendor and product' means that there seems to be a " 2066141cc406Sopenharmony_ci "scanner at this\n # device file but the vendor and product ids " 2067141cc406Sopenharmony_ci "couldn't be identified.\n # Currently identification only works " 2068141cc406Sopenharmony_ci "with Linux versions >= 2.4.8. You may\n # need to configure your " 2069141cc406Sopenharmony_ci "backend manually, see the backend's manpage.\n"); 2070141cc406Sopenharmony_ci } 2071141cc406Sopenharmony_ci else 2072141cc406Sopenharmony_ci { 2073141cc406Sopenharmony_ci if (verbose > 0) 2074141cc406Sopenharmony_ci printf 2075141cc406Sopenharmony_ci (" # No USB scanners found. If you expected something different, " 2076141cc406Sopenharmony_ci "make sure that\n # you have loaded a kernel driver for your USB host " 2077141cc406Sopenharmony_ci "controller and have setup\n # the USB system correctly. " 2078141cc406Sopenharmony_ci "See man sane-usb for details.\n"); 2079141cc406Sopenharmony_ci#if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) 2080141cc406Sopenharmony_ci if (verbose > 0) 2081141cc406Sopenharmony_ci printf (" # SANE has been built without libusb support. This may be a " 2082141cc406Sopenharmony_ci "reason\n # for not detecting USB scanners. Read README for " 2083141cc406Sopenharmony_ci "more details.\n"); 2084141cc406Sopenharmony_ci#endif 2085141cc406Sopenharmony_ci } 2086141cc406Sopenharmony_ci if (enable_pp_checks == SANE_TRUE) 2087141cc406Sopenharmony_ci { 2088141cc406Sopenharmony_ci if (!check_mustek_pp_device() && verbose > 0) 2089141cc406Sopenharmony_ci printf ("\n # No Mustek parallel port scanners found. If you expected" 2090141cc406Sopenharmony_ci " something\n # different, make sure the scanner is correctly" 2091141cc406Sopenharmony_ci " connected to your computer\n # and you have appropriate" 2092141cc406Sopenharmony_ci " access rights.\n"); 2093141cc406Sopenharmony_ci } 2094141cc406Sopenharmony_ci else if (verbose > 0) 2095141cc406Sopenharmony_ci printf ("\n # Not checking for parallel port scanners.\n"); 2096141cc406Sopenharmony_ci if (verbose > 0) 2097141cc406Sopenharmony_ci printf ("\n # Most Scanners connected to the parallel port or other " 2098141cc406Sopenharmony_ci "proprietary ports\n # can't be detected by this program.\n"); 2099141cc406Sopenharmony_ci#ifdef HAVE_GETUID 2100141cc406Sopenharmony_ci if (getuid ()) 2101141cc406Sopenharmony_ci if (verbose > 0) 2102141cc406Sopenharmony_ci printf 2103141cc406Sopenharmony_ci ("\n # You may want to run this program as root to find all devices. " 2104141cc406Sopenharmony_ci "Once you\n # found the scanner devices, be sure to adjust access " 2105141cc406Sopenharmony_ci "permissions as\n # necessary.\n"); 2106141cc406Sopenharmony_ci#endif 2107141cc406Sopenharmony_ci 2108141cc406Sopenharmony_ci if (verbose > 1) 2109141cc406Sopenharmony_ci printf ("done\n"); 2110141cc406Sopenharmony_ci 2111141cc406Sopenharmony_ci return 0; 2112141cc406Sopenharmony_ci} 2113