kopia lustrzana https://gitlab.com/sane-project/backends
Added support for libusb.
Henning Meier-Geinitz <henning@meier-geinitz.de>DEVEL_2_0_BRANCH-1
rodzic
a8c8969925
commit
e3476bd389
|
|
@ -1,5 +1,5 @@
|
||||||
/* sane - Scanner Access Now Easy.
|
/* sane - Scanner Access Now Easy.
|
||||||
Copyright (C) 2001 Henning Meier-Geinitz
|
Copyright (C) 2001, 2002 Henning Meier-Geinitz
|
||||||
This file is part of the SANE package.
|
This file is part of the SANE package.
|
||||||
|
|
||||||
SANE is free software; you can redistribute it and/or modify it
|
SANE is free software; you can redistribute it and/or modify it
|
||||||
|
|
@ -20,10 +20,12 @@
|
||||||
/** @file sanei_usb.h
|
/** @file sanei_usb.h
|
||||||
* This file provides a generic USB interface.
|
* This file provides a generic USB interface.
|
||||||
*
|
*
|
||||||
* Currently, only access to device files as provided by the Linux USB
|
* Currently, two access methods to USB devices are provided:
|
||||||
* scanner driver is supported. FreeBSD and OpenBSD with their uscanner
|
* - Access to device
|
||||||
* drivers also work. However, detection and control messages aren't
|
* files as used by the Linux kernel USB scanner driver is supported. FreeBSD
|
||||||
* supported on these platforms.
|
* and OpenBSD with their uscanner drivers also work this way. However,
|
||||||
|
* detection and control messages aren't supported on these platforms.
|
||||||
|
* - Access using libusb (where available).
|
||||||
*
|
*
|
||||||
* @sa sanei_lm983x.h, sanei_pa4s2.h, sanei_pio.h, sanei_scsi.h, and <a
|
* @sa sanei_lm983x.h, sanei_pa4s2.h, sanei_pio.h, sanei_scsi.h, and <a
|
||||||
* href="http://www.mostang.com/sane/man/sane-usb.5.html">man sane-usb(5)</a>
|
* href="http://www.mostang.com/sane/man/sane-usb.5.html">man sane-usb(5)</a>
|
||||||
|
|
@ -36,12 +38,90 @@
|
||||||
#include "../include/sane/config.h"
|
#include "../include/sane/config.h"
|
||||||
#include "../include/sane/sane.h"
|
#include "../include/sane/sane.h"
|
||||||
|
|
||||||
|
/* USB spec defines */
|
||||||
|
#ifndef USB_CLASS_PER_INTERFACE
|
||||||
|
/* Also defined in libusb */
|
||||||
|
/* Device and/or interface class codes */
|
||||||
|
#define USB_CLASS_PER_INTERFACE 0x00
|
||||||
|
#define USB_CLASS_AUDIO 0x01
|
||||||
|
#define USB_CLASS_COMM 0x02
|
||||||
|
#define USB_CLASS_HID 0x03
|
||||||
|
#define USB_CLASS_PRINTER 0x07
|
||||||
|
#define USB_CLASS_MASS_STORAGE 0x08
|
||||||
|
#define USB_CLASS_HUB 0x09
|
||||||
|
#define USB_CLASS_DATA 0x0a
|
||||||
|
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||||
|
|
||||||
|
/* USB descriptor types */
|
||||||
|
#define USB_DT_DEVICE 0x01
|
||||||
|
#define USB_DT_CONFIG 0x02
|
||||||
|
#define USB_DT_STRING 0x03
|
||||||
|
#define USB_DT_INTERFACE 0x04
|
||||||
|
#define USB_DT_ENDPOINT 0x05
|
||||||
|
|
||||||
|
#define USB_DT_HID 0x21
|
||||||
|
#define USB_DT_REPORT 0x22
|
||||||
|
#define USB_DT_PHYSICAL 0x23
|
||||||
|
#define USB_DT_HUB 0x29
|
||||||
|
|
||||||
|
/* Descriptor sizes per descriptor type */
|
||||||
|
#define USB_DT_DEVICE_SIZE 18
|
||||||
|
#define USB_DT_CONFIG_SIZE 9
|
||||||
|
#define USB_DT_INTERFACE_SIZE 9
|
||||||
|
#define USB_DT_ENDPOINT_SIZE 7
|
||||||
|
#define USB_DT_ENDPOINT_AUDIO_SIZE 9
|
||||||
|
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||||
|
|
||||||
|
/* Endpoint descriptor values */
|
||||||
|
#define USB_ENDPOINT_ADDRESS_MASK 0x0f
|
||||||
|
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||||
|
|
||||||
|
#define USB_ENDPOINT_TYPE_MASK 0x03
|
||||||
|
#define USB_ENDPOINT_TYPE_CONTROL 0
|
||||||
|
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1
|
||||||
|
#define USB_ENDPOINT_TYPE_BULK 2
|
||||||
|
#define USB_ENDPOINT_TYPE_INTERRUPT 3
|
||||||
|
|
||||||
|
/* Standard requests */
|
||||||
|
#define USB_REQ_GET_STATUS 0x00
|
||||||
|
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||||
|
#define USB_REQ_SET_FEATURE 0x03
|
||||||
|
#define USB_REQ_SET_ADDRESS 0x05
|
||||||
|
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||||
|
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||||
|
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||||
|
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||||
|
#define USB_REQ_GET_INTERFACE 0x0A
|
||||||
|
#define USB_REQ_SET_INTERFACE 0x0B
|
||||||
|
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||||
|
|
||||||
|
/* USB types */
|
||||||
|
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||||
|
#define USB_TYPE_CLASS (0x01 << 5)
|
||||||
|
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||||
|
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||||
|
|
||||||
|
/* USB recipients */
|
||||||
|
#define USB_RECIP_DEVICE 0x00
|
||||||
|
#define USB_RECIP_INTERFACE 0x01
|
||||||
|
#define USB_RECIP_ENDPOINT 0x02
|
||||||
|
#define USB_RECIP_OTHER 0x03
|
||||||
|
|
||||||
|
#endif /* not USB_CLASS_PER_INTERFACE */
|
||||||
|
|
||||||
|
/* Not defined in libsub */
|
||||||
|
#define USB_TYPE_MASK (0x03 << 5)
|
||||||
|
#define USB_RECIP_MASK 0x1f
|
||||||
|
|
||||||
|
/* USB directions */
|
||||||
|
#define USB_DIR_OUT 0
|
||||||
|
#define USB_DIR_IN 0x80
|
||||||
|
|
||||||
/** Initialize sanei_usb.
|
/** Initialize sanei_usb.
|
||||||
*
|
*
|
||||||
* Call this before any other sanei_usb function.
|
* Call this before any other sanei_usb function.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void sanei_usb_init (void);
|
||||||
sanei_usb_init (void);
|
|
||||||
|
|
||||||
/** Get the vendor and product ids.
|
/** Get the vendor and product ids.
|
||||||
*
|
*
|
||||||
|
|
@ -89,15 +169,13 @@ sanei_usb_find_devices (SANE_Int vendor, SANE_Int product,
|
||||||
* permissions
|
* permissions
|
||||||
* - SANE_STATUS_INVAL - on every other error
|
* - SANE_STATUS_INVAL - on every other error
|
||||||
*/
|
*/
|
||||||
extern SANE_Status
|
extern SANE_Status sanei_usb_open (SANE_String_Const devname, SANE_Int * fd);
|
||||||
sanei_usb_open (SANE_String_Const devname, SANE_Int *fd);
|
|
||||||
|
|
||||||
/** Close a USB device.
|
/** Close a USB device.
|
||||||
*
|
*
|
||||||
* @param fd file descriptor of the device
|
* @param fd file descriptor of the device
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void sanei_usb_close (SANE_Int fd);
|
||||||
sanei_usb_close (SANE_Int fd);
|
|
||||||
|
|
||||||
/** Initiate a bulk transfer read.
|
/** Initiate a bulk transfer read.
|
||||||
*
|
*
|
||||||
|
|
@ -114,9 +192,9 @@ sanei_usb_close (SANE_Int fd);
|
||||||
* - SANE_STATUS_IO_ERROR - if an error occured during the read
|
* - SANE_STATUS_IO_ERROR - if an error occured during the read
|
||||||
* - SANE_STATUS_INVAL - on every other error
|
* - SANE_STATUS_INVAL - on every other error
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
extern SANE_Status
|
extern SANE_Status
|
||||||
sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size);
|
sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t * size);
|
||||||
|
|
||||||
/** Initiate a bulk transfer write.
|
/** Initiate a bulk transfer write.
|
||||||
*
|
*
|
||||||
|
|
@ -133,7 +211,7 @@ sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size);
|
||||||
* - SANE_STATUS_INVAL - on every other error
|
* - SANE_STATUS_INVAL - on every other error
|
||||||
*/
|
*/
|
||||||
extern SANE_Status
|
extern SANE_Status
|
||||||
sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size);
|
sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t * size);
|
||||||
|
|
||||||
/** Send/receive a control message to/from a USB device.
|
/** Send/receive a control message to/from a USB device.
|
||||||
*
|
*
|
||||||
|
|
@ -162,7 +240,7 @@ sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size);
|
||||||
extern SANE_Status
|
extern SANE_Status
|
||||||
sanei_usb_control_msg (SANE_Int fd, SANE_Int rtype, SANE_Int req,
|
sanei_usb_control_msg (SANE_Int fd, SANE_Int rtype, SANE_Int req,
|
||||||
SANE_Int value, SANE_Int index, SANE_Int len,
|
SANE_Int value, SANE_Int index, SANE_Int len,
|
||||||
SANE_Byte *data);
|
SANE_Byte * data);
|
||||||
|
|
||||||
/** Expand device name patterns into a list of devices.
|
/** Expand device name patterns into a list of devices.
|
||||||
*
|
*
|
||||||
|
|
@ -179,7 +257,7 @@ sanei_usb_control_msg (SANE_Int fd, SANE_Int rtype, SANE_Int req,
|
||||||
* @param attach attach function
|
* @param attach attach function
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
sanei_usb_attach_matching_devices (const char *name,
|
sanei_usb_attach_matching_devices (const char *name,
|
||||||
SANE_Status (*attach) (const char *dev));
|
SANE_Status (*attach) (const char *dev));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* sane - Scanner Access Now Easy.
|
/* sane - Scanner Access Now Easy.
|
||||||
Copyright (C) 2001 Henning Meier-Geinitz
|
Copyright (C) 2001, 2002 Henning Meier-Geinitz
|
||||||
Copyright (C) 2001 Frank Zago (sanei_usb_control_msg)
|
Copyright (C) 2001 Frank Zago (sanei_usb_control_msg)
|
||||||
This file is part of the SANE package.
|
This file is part of the SANE package.
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
whether to permit this exception to apply to your modifications.
|
whether to permit this exception to apply to your modifications.
|
||||||
If you do not wish that, delete this exception notice.
|
If you do not wish that, delete this exception notice.
|
||||||
|
|
||||||
This file provides a generic (?) USB interface. */
|
This file provides a generic USB interface. */
|
||||||
|
|
||||||
#include "../include/sane/config.h"
|
#include "../include/sane/config.h"
|
||||||
|
|
||||||
|
|
@ -53,14 +53,47 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
#include <usb.h>
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
|
|
||||||
#define BACKEND_NAME sanei_usb
|
#define BACKEND_NAME sanei_usb
|
||||||
#include "../include/sane/sane.h"
|
#include "../include/sane/sane.h"
|
||||||
#include "../include/sane/sanei_debug.h"
|
#include "../include/sane/sanei_debug.h"
|
||||||
#include "../include/sane/sanei_usb.h"
|
#include "../include/sane/sanei_usb.h"
|
||||||
#include "../include/sane/sanei_config.h"
|
#include "../include/sane/sanei_config.h"
|
||||||
|
|
||||||
#if defined (__linux__)
|
typedef enum
|
||||||
|
{
|
||||||
|
sanei_usb_method_scanner_driver = 0, /* kernel scanner driver
|
||||||
|
(Linux, BSD) */
|
||||||
|
sanei_usb_method_libusb
|
||||||
|
}
|
||||||
|
sanei_usb_access_method_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SANE_Bool open;
|
||||||
|
sanei_usb_access_method_type method;
|
||||||
|
int fd;
|
||||||
|
SANE_Int bulk_in_ep;
|
||||||
|
SANE_Int bulk_out_ep;
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
usb_dev_handle *libusb_handle;
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
|
}
|
||||||
|
device_list_type;
|
||||||
|
|
||||||
|
#define MAX_DEVICES 100
|
||||||
|
|
||||||
|
/* per-device information, using the functions fd as index */
|
||||||
|
static device_list_type devices[MAX_DEVICES];
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
int libusb_timeout = 30 * 1000; /* 30 seconds */
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
|
|
||||||
|
#if defined (__linux__)
|
||||||
/* From /usr/src/linux/driver/usb/scanner.h */
|
/* From /usr/src/linux/driver/usb/scanner.h */
|
||||||
#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
|
#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
|
||||||
#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
|
#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
|
||||||
|
|
@ -69,30 +102,46 @@
|
||||||
#define SCANNER_IOCTL_VENDOR_OLD _IOR('u', 0xa0, int)
|
#define SCANNER_IOCTL_VENDOR_OLD _IOR('u', 0xa0, int)
|
||||||
#define SCANNER_IOCTL_PRODUCT_OLD _IOR('u', 0xa1, int)
|
#define SCANNER_IOCTL_PRODUCT_OLD _IOR('u', 0xa1, int)
|
||||||
|
|
||||||
/* From /usr/src/linux/include/linux/usb.h */
|
/* From /usr/src/linux/include/linux/usb.h */
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
unsigned char requesttype;
|
unsigned char requesttype;
|
||||||
unsigned char request;
|
unsigned char request;
|
||||||
unsigned short value;
|
unsigned short value;
|
||||||
unsigned short index;
|
unsigned short index;
|
||||||
unsigned short length;
|
unsigned short length;
|
||||||
} devrequest __attribute__ ((packed));
|
}
|
||||||
|
devrequest __attribute__ ((packed));
|
||||||
|
|
||||||
/* From /usr/src/linux/driver/usb/scanner.h */
|
/* From /usr/src/linux/driver/usb/scanner.h */
|
||||||
struct ctrlmsg_ioctl {
|
struct ctrlmsg_ioctl
|
||||||
devrequest req;
|
{
|
||||||
void *data;
|
devrequest req;
|
||||||
} cmsg;
|
void *data;
|
||||||
|
}
|
||||||
|
cmsg;
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sanei_usb_init (void)
|
sanei_usb_init (void)
|
||||||
{
|
{
|
||||||
DBG_INIT();
|
DBG_INIT ();
|
||||||
|
|
||||||
|
memset (devices, 0, sizeof (devices));
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
usb_init ();
|
||||||
|
#ifdef DBG_LEVEL
|
||||||
|
if (DBG_LEVEL > 4)
|
||||||
|
usb_set_debug (255);
|
||||||
|
#endif /* DBG_LEVEL */
|
||||||
|
usb_find_busses ();
|
||||||
|
usb_find_devices ();
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This logically belongs to sanei_config.c but not every backend that
|
/* This logically belongs to sanei_config.c but not every backend that
|
||||||
uses sanei_config() wants to depend on sanei_usb. */
|
uses sanei_config() wants to depend on sanei_usb. */
|
||||||
void
|
void
|
||||||
|
|
@ -131,7 +180,7 @@ sanei_usb_attach_matching_devices (const char *name,
|
||||||
}
|
}
|
||||||
sanei_usb_find_devices (vendorID, productID, attach);
|
sanei_usb_find_devices (vendorID, productID, attach);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(*attach) (name);
|
(*attach) (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,38 +191,66 @@ sanei_usb_get_vendor_product (SANE_Int fd, SANE_Word * vendor,
|
||||||
SANE_Word vendorID = 0;
|
SANE_Word vendorID = 0;
|
||||||
SANE_Word productID = 0;
|
SANE_Word productID = 0;
|
||||||
|
|
||||||
|
if (fd >= MAX_DEVICES || fd < 0)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_get_vendor_product: fd >= MAX_DEVICES || fd < 0\n");
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices[fd].method == sanei_usb_method_scanner_driver)
|
||||||
|
{
|
||||||
#if defined (__linux__)
|
#if defined (__linux__)
|
||||||
/* read the vendor and product IDs via the IOCTLs */
|
/* read the vendor and product IDs via the IOCTLs */
|
||||||
if (ioctl (fd, SCANNER_IOCTL_VENDOR , &vendorID) == -1)
|
if (ioctl (devices[fd].fd, SCANNER_IOCTL_VENDOR, &vendorID) == -1)
|
||||||
{
|
{
|
||||||
if (ioctl (fd, SCANNER_IOCTL_VENDOR_OLD , &vendorID) == -1)
|
if (ioctl (devices[fd].fd, SCANNER_IOCTL_VENDOR_OLD, &vendorID)
|
||||||
DBG (3, "sanei_usb_get_vendor_product: ioctl (vendor) of fd %d "
|
== -1)
|
||||||
"failed: %s\n", fd, strerror (errno));
|
DBG (3, "sanei_usb_get_vendor_product: ioctl (vendor) "
|
||||||
|
"of device %d failed: %s\n", fd, strerror (errno));
|
||||||
|
}
|
||||||
|
if (ioctl (devices[fd].fd, SCANNER_IOCTL_PRODUCT, &productID) == -1)
|
||||||
|
{
|
||||||
|
if (ioctl (devices[fd].fd, SCANNER_IOCTL_PRODUCT_OLD,
|
||||||
|
&productID) == -1)
|
||||||
|
DBG (3, "sanei_usb_get_vendor_product: ioctl (product) "
|
||||||
|
"of device %d failed: %s\n", fd, strerror (errno));
|
||||||
|
}
|
||||||
|
#endif /* defined (__linux__) */
|
||||||
|
/* put more os-dependant stuff ... */
|
||||||
}
|
}
|
||||||
if (ioctl (fd, SCANNER_IOCTL_PRODUCT , &productID) == -1)
|
else if (devices[fd].method == sanei_usb_method_libusb)
|
||||||
{
|
{
|
||||||
if (ioctl (fd, SCANNER_IOCTL_PRODUCT_OLD , &productID) == -1)
|
#ifdef HAVE_LIBUSB
|
||||||
DBG (3, "sanei_usb_get_vendor_product: ioctl (product) of fd %d "
|
vendorID = usb_device (devices[fd].libusb_handle)->descriptor.idVendor;
|
||||||
"failed: %s\n", fd, strerror (errno));
|
productID =
|
||||||
|
usb_device (devices[fd].libusb_handle)->descriptor.idProduct;
|
||||||
|
#else
|
||||||
|
DBG (1, "sanei_usb_get_vendor_product: libusb support missing\n");
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_get_vendor_product: access method %d not "
|
||||||
|
"implemented\n", devices[fd].method);
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (vendor)
|
if (vendor)
|
||||||
*vendor = vendorID;
|
*vendor = vendorID;
|
||||||
if (product)
|
if (product)
|
||||||
*product = productID;
|
*product = productID;
|
||||||
#endif /* not defined (__linux__) */
|
|
||||||
|
|
||||||
if (!vendorID || !productID)
|
if (!vendorID || !productID)
|
||||||
{
|
{
|
||||||
DBG (3, "sanei_usb_get_vendor_product: fd %d: Your OS doesn't seem to "
|
DBG (3, "sanei_usb_get_vendor_product: device %d: Your OS doesn't "
|
||||||
"support detection of vendor+product ids\n",
|
"seem to support detection of vendor+product ids\n", fd);
|
||||||
fd);
|
|
||||||
|
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG (3, "sanei_usb_get_vendor_product: fd %d: vendorID: 0x%x, "
|
DBG (3, "sanei_usb_get_vendor_product: device %d: vendorID: 0x%04x, "
|
||||||
"productID: 0x%x\n", fd, vendorID, productID);
|
"productID: 0x%04x\n", fd, vendorID, productID);
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,68 +294,285 @@ sanei_usb_find_devices (SANE_Int vendor, SANE_Int product,
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
"/dev/uscanner",
|
"/dev/uscanner",
|
||||||
#endif
|
#endif
|
||||||
0};
|
0
|
||||||
SANE_Char devname[30];
|
};
|
||||||
|
SANE_Char devname[1024];
|
||||||
int devcount;
|
int devcount;
|
||||||
SANE_Status status;
|
SANE_Status status;
|
||||||
|
|
||||||
#define SANEI_USB_MAX_DEVICES 16
|
#define SANEI_USB_MAX_DEVICE_FILES 16
|
||||||
|
|
||||||
DBG (3, "sanei_usb_find_devices: vendor=0x%x, product=0x%x, attach=%p\n",
|
DBG (3,
|
||||||
|
"sanei_usb_find_devices: vendor=0x%04x, product=0x%04x, attach=%p\n",
|
||||||
vendor, product, attach);
|
vendor, product, attach);
|
||||||
|
|
||||||
|
/* First we check the device files for access over the kernel scanner
|
||||||
|
drivers */
|
||||||
for (prefix = prefixlist; *prefix; prefix++)
|
for (prefix = prefixlist; *prefix; prefix++)
|
||||||
{
|
{
|
||||||
status = check_vendor_product (*prefix, vendor, product, attach);
|
status = check_vendor_product (*prefix, vendor, product, attach);
|
||||||
if (status == SANE_STATUS_UNSUPPORTED)
|
if (status == SANE_STATUS_UNSUPPORTED)
|
||||||
return status; /* give up if we can't detect vendor/product */
|
break; /* give up if we can't detect vendor/product */
|
||||||
for (devcount = 0; devcount < SANEI_USB_MAX_DEVICES;
|
for (devcount = 0; devcount < SANEI_USB_MAX_DEVICE_FILES; devcount++)
|
||||||
devcount++)
|
|
||||||
{
|
{
|
||||||
snprintf (devname, sizeof (devname), "%s%d", *prefix,
|
snprintf (devname, sizeof (devname), "%s%d", *prefix, devcount);
|
||||||
devcount);
|
|
||||||
status = check_vendor_product (devname, vendor, product, attach);
|
status = check_vendor_product (devname, vendor, product, attach);
|
||||||
if (status == SANE_STATUS_UNSUPPORTED)
|
if (status == SANE_STATUS_UNSUPPORTED)
|
||||||
return status; /* give up if we can't detect vendor/product */
|
break; /* give up if we can't detect vendor/product */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Now we will check all the devices libusb finds (if available) */
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
{
|
||||||
|
struct usb_bus *bus;
|
||||||
|
struct usb_device *dev;
|
||||||
|
|
||||||
|
for (bus = usb_get_busses (); bus; bus = bus->next)
|
||||||
|
{
|
||||||
|
for (dev = bus->devices; dev; dev = dev->next)
|
||||||
|
{
|
||||||
|
if (dev->descriptor.idVendor == vendor
|
||||||
|
&& dev->descriptor.idProduct == product)
|
||||||
|
{
|
||||||
|
DBG (3,
|
||||||
|
"sanei_usb_find_devices: found matching libusb device "
|
||||||
|
"(bus=%s, filename=%s, vendor=0x%04x, product=0x%04x)\n",
|
||||||
|
bus->dirname, dev->filename, dev->descriptor.idVendor,
|
||||||
|
dev->descriptor.idProduct);
|
||||||
|
snprintf (devname, sizeof (devname), "libusb:%s:%s",
|
||||||
|
bus->dirname, dev->filename);
|
||||||
|
attach (devname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DBG (5, "sanei_usb_find_devices: found libusb device "
|
||||||
|
"(bus=%s, filename=%s, vendor=0x%04x, product=0x%04x)\n",
|
||||||
|
bus->dirname, dev->filename, dev->descriptor.idVendor,
|
||||||
|
dev->descriptor.idProduct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBUSB */
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
SANE_Status
|
SANE_Status
|
||||||
sanei_usb_open (SANE_String_Const devname, SANE_Int *fd)
|
sanei_usb_open (SANE_String_Const devname, SANE_Int * fd)
|
||||||
{
|
{
|
||||||
|
int devcount;
|
||||||
|
|
||||||
if (!fd)
|
if (!fd)
|
||||||
{
|
{
|
||||||
DBG (1, "sanei_usb_open: fd == NULL\n");
|
DBG (1, "sanei_usb_open: can't open `%s': fd == NULL\n", devname);
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
*fd = open (devname, O_RDWR);
|
|
||||||
if (*fd < 0)
|
|
||||||
{
|
|
||||||
SANE_Status status = SANE_STATUS_INVAL;
|
|
||||||
|
|
||||||
DBG (1, "sanei_usb_open: open failed: %s\n", strerror (errno));
|
for (devcount = 0;
|
||||||
if (errno == EACCES)
|
devcount < MAX_DEVICES && devices[devcount].open == SANE_TRUE;
|
||||||
status = SANE_STATUS_ACCESS_DENIED;
|
devcount++)
|
||||||
return status;
|
;
|
||||||
|
|
||||||
|
if (devices[devcount].open)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_open: can't open `%s': "
|
||||||
|
"maximum amount of devices (%d) reached\n", devname, MAX_DEVICES);
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
}
|
}
|
||||||
DBG (5, "sanei_usb_open: fd %d opened\n", *fd);
|
|
||||||
|
memset (&devices[devcount], 0, sizeof (devices[devcount]));
|
||||||
|
|
||||||
|
if (strncmp (devname, "libusb:", 7) == 0)
|
||||||
|
{
|
||||||
|
/* Using libusb */
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
SANE_String start, end, bus_string, dev_string;
|
||||||
|
struct usb_bus *bus;
|
||||||
|
struct usb_device *dev;
|
||||||
|
struct usb_interface_descriptor *interface;
|
||||||
|
SANE_Int result;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
|
||||||
|
DBG (5, "sanei_usb_open: trying to open device `%s'\n", devname);
|
||||||
|
start = strchr (devname, ':');
|
||||||
|
if (!start)
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
start++;
|
||||||
|
end = strchr (start, ':');
|
||||||
|
if (!end)
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
bus_string = strndup (start, end - start);
|
||||||
|
if (!bus_string)
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
|
|
||||||
|
start = strchr (start, ':');
|
||||||
|
if (!start)
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
start++;
|
||||||
|
dev_string = strdup (start);
|
||||||
|
if (!dev_string)
|
||||||
|
return SANE_STATUS_NO_MEM;
|
||||||
|
|
||||||
|
for (bus = usb_get_busses (); bus; bus = bus->next)
|
||||||
|
{
|
||||||
|
if (strcmp (bus->dirname, bus_string) == 0)
|
||||||
|
{
|
||||||
|
for (dev = bus->devices; dev; dev = dev->next)
|
||||||
|
{
|
||||||
|
if (strcmp (dev->filename, dev_string) == 0)
|
||||||
|
devices[devcount].libusb_handle = usb_open (dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!devices[devcount].libusb_handle)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_open: can't open device `%s': "
|
||||||
|
"not found or libusb error (%s)\n", devname, strerror (errno));
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
devices[devcount].method = sanei_usb_method_libusb;
|
||||||
|
|
||||||
|
dev = usb_device (devices[devcount].libusb_handle);
|
||||||
|
|
||||||
|
if (dev->descriptor.bNumConfigurations > 1)
|
||||||
|
{
|
||||||
|
DBG (3, "sanei_usb_open: more than one "
|
||||||
|
"configuration (%d), choosing config 0\n",
|
||||||
|
dev->descriptor.bNumConfigurations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->config[0].interface->num_altsetting > 1)
|
||||||
|
{
|
||||||
|
DBG (3, "sanei_usb_open: more than one "
|
||||||
|
"alternate setting (%d), choosing interface 0\n",
|
||||||
|
dev->config[0].interface->num_altsetting);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = usb_claim_interface (devices[devcount].libusb_handle, 0);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
SANE_Status status = SANE_STATUS_INVAL;
|
||||||
|
|
||||||
|
DBG (1, "sanei_usb_open: libusb complained: %s\n", usb_strerror ());
|
||||||
|
if (errno == EPERM)
|
||||||
|
{
|
||||||
|
DBG (1, "Make sure you run as root or set appropriate "
|
||||||
|
"permissions\n");
|
||||||
|
status = SANE_STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
else if (errno == EBUSY)
|
||||||
|
{
|
||||||
|
DBG (1, "Maybe the kernel scanner driver claims the "
|
||||||
|
"scanner's interface?\n");
|
||||||
|
status = SANE_STATUS_DEVICE_BUSY;
|
||||||
|
}
|
||||||
|
usb_close (devices[devcount].libusb_handle);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
interface = &dev->config[0].interface->altsetting[0];
|
||||||
|
|
||||||
|
/* Now we look for usable endpoints */
|
||||||
|
for (num = 0; num < interface->bNumEndpoints; num++)
|
||||||
|
{
|
||||||
|
struct usb_endpoint_descriptor *endpoint;
|
||||||
|
int address, direction, transfer_type;
|
||||||
|
|
||||||
|
endpoint = &interface->endpoint[num];
|
||||||
|
address = endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK;
|
||||||
|
direction = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
|
||||||
|
transfer_type = endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK;
|
||||||
|
|
||||||
|
if (transfer_type != USB_ENDPOINT_TYPE_BULK)
|
||||||
|
{
|
||||||
|
DBG (5, "sanei_usb_open: ignoring %s-%s endpoint "
|
||||||
|
"(address: %d)\n",
|
||||||
|
transfer_type == USB_ENDPOINT_TYPE_CONTROL ? "control" :
|
||||||
|
transfer_type == USB_ENDPOINT_TYPE_ISOCHRONOUS
|
||||||
|
? "isochronous" : "interrupt",
|
||||||
|
direction ? "in" : "out", address);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DBG (5, "sanei_usb_open: found bulk-%s endpoint (address %d)\n",
|
||||||
|
direction ? "in" : "out", address);
|
||||||
|
if (direction) /* in */
|
||||||
|
{
|
||||||
|
if (devices[devcount].bulk_in_ep)
|
||||||
|
DBG (3, "sanei_usb_open: we already have a bulk-in endpoint "
|
||||||
|
"(address: %d), ignoring the new one\n",
|
||||||
|
devices[devcount].bulk_in_ep);
|
||||||
|
else
|
||||||
|
devices[devcount].bulk_in_ep = address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (devices[devcount].bulk_out_ep)
|
||||||
|
DBG (3, "sanei_usb_open: we already have a bulk-out endpoint "
|
||||||
|
"(address: %d), ignoring the new one\n",
|
||||||
|
devices[devcount].bulk_out_ep);
|
||||||
|
else
|
||||||
|
devices[devcount].bulk_out_ep = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* not HAVE_LIBUSB */
|
||||||
|
DBG (1, "sanei_usb_open: can't open device `%s': "
|
||||||
|
"libusb support missing\n", devname);
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
|
#endif /* not HAVE_LIBUSB */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Using kernel scanner driver */
|
||||||
|
devices[devcount].fd = open (devname, O_RDWR);
|
||||||
|
if (devices[devcount].fd < 0)
|
||||||
|
{
|
||||||
|
SANE_Status status = SANE_STATUS_INVAL;
|
||||||
|
|
||||||
|
if (errno == EACCES)
|
||||||
|
status = SANE_STATUS_ACCESS_DENIED;
|
||||||
|
else if (errno == ENOENT)
|
||||||
|
{
|
||||||
|
DBG (5, "sanei_usb_open: open of `%s' failed: %s\n",
|
||||||
|
devname, strerror (errno));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
DBG (1, "sanei_usb_open: open of `%s' failed: %s\n",
|
||||||
|
devname, strerror (errno));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
devices[devcount].method = sanei_usb_method_scanner_driver;
|
||||||
|
}
|
||||||
|
devices[devcount].open = SANE_TRUE;
|
||||||
|
*fd = devcount;
|
||||||
|
DBG (3, "sanei_usb_open: opened usb device `%s' (*fd=%d)\n",
|
||||||
|
devname, devcount);
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sanei_usb_close (SANE_Int fd)
|
sanei_usb_close (SANE_Int fd)
|
||||||
{
|
{
|
||||||
DBG (5, "sanei_usb_close: closing fd %d\n", fd);
|
DBG (5, "sanei_usb_close: closing device %d\n", fd);
|
||||||
close (fd);
|
if (fd >= MAX_DEVICES || fd < 0)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_close: fd >= MAX_DEVICES || fd < 0\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (devices[fd].method == sanei_usb_method_scanner_driver)
|
||||||
|
close (devices[fd].fd);
|
||||||
|
else
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
usb_close (devices[fd].libusb_handle);
|
||||||
|
#else
|
||||||
|
DBG (1, "sanei_usb_close: libusb support missing\n");
|
||||||
|
#endif
|
||||||
|
devices[fd].open = SANE_FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SANE_Status
|
SANE_Status
|
||||||
sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size)
|
sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t * size)
|
||||||
{
|
{
|
||||||
ssize_t read_size;
|
ssize_t read_size = 0;
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
{
|
{
|
||||||
|
|
@ -286,7 +580,40 @@ sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_size = read (fd, buffer, *size);
|
if (fd >= MAX_DEVICES || fd < 0)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_read_bulk: fd >= MAX_DEVICES || fd < 0\n");
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
if (devices[fd].method == sanei_usb_method_scanner_driver)
|
||||||
|
read_size = read (devices[fd].fd, buffer, *size);
|
||||||
|
else if (devices[fd].method == sanei_usb_method_libusb)
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
{
|
||||||
|
if (devices[fd].bulk_in_ep)
|
||||||
|
read_size = usb_bulk_read (devices[fd].libusb_handle,
|
||||||
|
devices[fd].bulk_in_ep, (char *) buffer,
|
||||||
|
(int) *size, libusb_timeout);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_read_bulk: can't read without a bulk-in "
|
||||||
|
"endpoint\n");
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* not HAVE_LIBUSB */
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_read_bulk: libusb support missing\n");
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
#endif /* not HAVE_LIBUSB */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_read_bulk: access method %d not implemented\n",
|
||||||
|
devices[fd].method);
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (read_size < 0)
|
if (read_size < 0)
|
||||||
{
|
{
|
||||||
DBG (1, "sanei_usb_read_bulk: read failed: %s\n", strerror (errno));
|
DBG (1, "sanei_usb_read_bulk: read failed: %s\n", strerror (errno));
|
||||||
|
|
@ -300,15 +627,15 @@ sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size)
|
||||||
return SANE_STATUS_EOF;
|
return SANE_STATUS_EOF;
|
||||||
}
|
}
|
||||||
DBG (5, "sanei_usb_read_bulk: wanted %lu bytes, got %ld bytes\n",
|
DBG (5, "sanei_usb_read_bulk: wanted %lu bytes, got %ld bytes\n",
|
||||||
(unsigned long) *size, (unsigned long) read_size);
|
(unsigned long) *size, (unsigned long) read_size);
|
||||||
*size = read_size;
|
*size = read_size;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
SANE_Status
|
SANE_Status
|
||||||
sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size)
|
sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t * size)
|
||||||
{
|
{
|
||||||
ssize_t write_size;
|
ssize_t write_size = 0;
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
{
|
{
|
||||||
|
|
@ -316,7 +643,41 @@ sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_size = write (fd, buffer, *size);
|
if (fd >= MAX_DEVICES || fd < 0)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_write_bulk: fd >= MAX_DEVICES || fd < 0\n");
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices[fd].method == sanei_usb_method_scanner_driver)
|
||||||
|
write_size = write (devices[fd].fd, buffer, *size);
|
||||||
|
else if (devices[fd].method == sanei_usb_method_libusb)
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
{
|
||||||
|
if (devices[fd].bulk_in_ep)
|
||||||
|
write_size = usb_bulk_write (devices[fd].libusb_handle,
|
||||||
|
devices[fd].bulk_out_ep, (char *) buffer,
|
||||||
|
(int) *size, libusb_timeout);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_write_bulk: can't write without a bulk-out "
|
||||||
|
"endpoint\n");
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* not HAVE_LIBUSB */
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_write_bulk: libusb support missing\n");
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
#endif /* not HAVE_LIBUSB */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_read_bulk: access method %d not implemented\n",
|
||||||
|
devices[fd].method);
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (write_size < 0)
|
if (write_size < 0)
|
||||||
{
|
{
|
||||||
DBG (1, "sanei_usb_write_bulk: write failed: %s\n", strerror (errno));
|
DBG (1, "sanei_usb_write_bulk: write failed: %s\n", strerror (errno));
|
||||||
|
|
@ -324,38 +685,75 @@ sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t *size)
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
DBG (5, "sanei_usb_write_bulk: wanted %lu bytes, wrote %ld bytes\n",
|
DBG (5, "sanei_usb_write_bulk: wanted %lu bytes, wrote %ld bytes\n",
|
||||||
(unsigned long) *size, (unsigned long) write_size);
|
(unsigned long) *size, (unsigned long) write_size);
|
||||||
*size = write_size;
|
*size = write_size;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
SANE_Status
|
SANE_Status
|
||||||
sanei_usb_control_msg(SANE_Int fd, SANE_Int rtype, SANE_Int req,
|
sanei_usb_control_msg (SANE_Int fd, SANE_Int rtype, SANE_Int req,
|
||||||
SANE_Int value, SANE_Int index, SANE_Int len,
|
SANE_Int value, SANE_Int index, SANE_Int len,
|
||||||
SANE_Byte *data )
|
SANE_Byte * data)
|
||||||
{
|
{
|
||||||
#if defined(__linux__)
|
if (fd >= MAX_DEVICES || fd < 0)
|
||||||
struct ctrlmsg_ioctl c;
|
|
||||||
|
|
||||||
c.req.requesttype = rtype;
|
|
||||||
c.req.request = req;
|
|
||||||
c.req.value = value;
|
|
||||||
c.req.index = index;
|
|
||||||
c.req.length = len;
|
|
||||||
c.data = data;
|
|
||||||
|
|
||||||
DBG(5, "sanei_usb_control_msg: rtype = 0x%02x, req = %d, value = %d, "
|
|
||||||
"index = %d, len = %d\n", rtype, req, value, index, len);
|
|
||||||
|
|
||||||
if (ioctl(fd, SCANNER_IOCTL_CTRLMSG, &c) < 0)
|
|
||||||
{
|
{
|
||||||
DBG(5, "sanei_usb_control_msg: SCANNER_IOCTL_CTRLMSG error - %s\n",
|
DBG (1, "sanei_usb_control_msg: fd >= MAX_DEVICES || fd < 0\n");
|
||||||
strerror(errno));
|
return SANE_STATUS_INVAL;
|
||||||
return SANE_STATUS_IO_ERROR;
|
}
|
||||||
|
|
||||||
|
if (devices[fd].method == sanei_usb_method_scanner_driver)
|
||||||
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
|
struct ctrlmsg_ioctl c;
|
||||||
|
|
||||||
|
c.req.requesttype = rtype;
|
||||||
|
c.req.request = req;
|
||||||
|
c.req.value = value;
|
||||||
|
c.req.index = index;
|
||||||
|
c.req.length = len;
|
||||||
|
c.data = data;
|
||||||
|
|
||||||
|
DBG (5, "sanei_usb_control_msg: rtype = 0x%02x, req = %d, value = %d, "
|
||||||
|
"index = %d, len = %d\n", rtype, req, value, index, len);
|
||||||
|
|
||||||
|
if (ioctl (devices[fd].fd, SCANNER_IOCTL_CTRLMSG, &c) < 0)
|
||||||
|
{
|
||||||
|
DBG (5, "sanei_usb_control_msg: SCANNER_IOCTL_CTRLMSG error - %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
return SANE_STATUS_IO_ERROR;
|
||||||
|
}
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
#else /* not __linux__ */
|
||||||
|
DBG (5, "sanei_usb_control_msg: not supported on this OS\n");
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
|
#endif /* not __linux__ */
|
||||||
|
}
|
||||||
|
else if (devices[fd].method == sanei_usb_method_libusb)
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = usb_control_msg (devices[fd].libusb_handle, rtype, req,
|
||||||
|
value, index, (char *) data, len,
|
||||||
|
libusb_timeout);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_control_msg: libusb complained: %s\n",
|
||||||
|
usb_strerror ());
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
#else /* not HAVE_LIBUSB */
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_control_msg: libusb support missing\n");
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
#endif /* not HAVE_LIBUSB */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG (1, "sanei_usb_read_bulk: access method %d not implemented\n",
|
||||||
|
devices[fd].method);
|
||||||
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
return SANE_STATUS_GOOD;
|
|
||||||
#else
|
|
||||||
DBG (5, "sanei_usb_control_msg: not supported on this OS\n");
|
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
|
||||||
#endif /* __linux__ */
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue