| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | /* sane - Scanner Access Now Easy.
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |    Copyright (C) 2001, 2002 Henning Meier-Geinitz | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  |    Copyright (C) 2001 Frank Zago (sanei_usb_control_msg) | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |    This file is part of the SANE package. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |    modify it under the terms of the GNU General Public License as | 
					
						
							|  |  |  |    published by the Free Software Foundation; either version 2 of the | 
					
						
							|  |  |  |    License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This program is distributed in the hope that it will be useful, but | 
					
						
							|  |  |  |    WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |    General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 
					
						
							|  |  |  |    MA 02111-1307, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    As a special exception, the authors of SANE give permission for | 
					
						
							|  |  |  |    additional uses of the libraries contained in this release of SANE. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The exception is that, if you link a SANE library with other files | 
					
						
							|  |  |  |    to produce an executable, this does not by itself cause the | 
					
						
							|  |  |  |    resulting executable to be covered by the GNU General Public | 
					
						
							|  |  |  |    License.  Your use of that executable is in no way restricted on | 
					
						
							|  |  |  |    account of linking the SANE library code into it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This exception does not, however, invalidate any other reasons why | 
					
						
							|  |  |  |    the executable file might be covered by the GNU General Public | 
					
						
							|  |  |  |    License. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    If you submit changes to SANE to the maintainers to be included in | 
					
						
							|  |  |  |    a subsequent release, you agree by submitting the changes that | 
					
						
							|  |  |  |    those changes may be distributed with this exception intact. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    If you write modifications of your own for SANE, it is your choice | 
					
						
							|  |  |  |    whether to permit this exception to apply to your modifications. | 
					
						
							|  |  |  |    If you do not wish that, delete this exception notice. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |    This file provides a generic USB interface.  */ | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "../include/sane/config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-05 19:48:24 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <sys/ioctl.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | #ifdef HAVE_LIBUSB
 | 
					
						
							|  |  |  | #include <usb.h>
 | 
					
						
							|  |  |  | #endif /* HAVE_LIBUSB */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | #define BACKEND_NAME	sanei_usb
 | 
					
						
							|  |  |  | #include "../include/sane/sane.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_debug.h"
 | 
					
						
							|  |  |  | #include "../include/sane/sanei_usb.h"
 | 
					
						
							| 
									
										
										
										
											2001-09-05 19:48:24 +00:00
										 |  |  | #include "../include/sane/sanei_config.h"
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 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 */
 | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | #if defined (__linux__)
 | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | /* From /usr/src/linux/driver/usb/scanner.h */ | 
					
						
							|  |  |  | #define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
 | 
					
						
							|  |  |  | #define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
 | 
					
						
							|  |  |  | #define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, devrequest)
 | 
					
						
							|  |  |  | /* Older (unofficial) IOCTL numbers for Linux < v2.4.13 */ | 
					
						
							|  |  |  | #define SCANNER_IOCTL_VENDOR_OLD _IOR('u', 0xa0, int)
 | 
					
						
							|  |  |  | #define SCANNER_IOCTL_PRODUCT_OLD _IOR('u', 0xa1, int)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | /* From /usr/src/linux/include/linux/usb.h */ | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  |   unsigned char requesttype; | 
					
						
							|  |  |  |   unsigned char request; | 
					
						
							|  |  |  |   unsigned short value; | 
					
						
							|  |  |  |   unsigned short index; | 
					
						
							|  |  |  |   unsigned short length; | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | devrequest __attribute__ ((packed)); | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* From /usr/src/linux/driver/usb/scanner.h */ | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | struct ctrlmsg_ioctl | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   devrequest req; | 
					
						
							|  |  |  |   void *data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | cmsg; | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | #endif /* __linux__ */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sanei_usb_init (void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   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 */
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-05 19:48:24 +00:00
										 |  |  | /* This logically belongs to sanei_config.c but not every backend that
 | 
					
						
							|  |  |  |    uses sanei_config() wants to depend on sanei_usb.  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sanei_usb_attach_matching_devices (const char *name, | 
					
						
							|  |  |  | 				   SANE_Status (*attach) (const char *dev)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *vendor, *product; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (strncmp (name, "usb", 3) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       SANE_Word vendorID = 0, productID = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       name += 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       name = sanei_config_skip_whitespace (name); | 
					
						
							|  |  |  |       if (*name) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  name = sanei_config_get_string (name, &vendor); | 
					
						
							|  |  |  | 	  if (vendor) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      vendorID = strtol (vendor, 0, 0); | 
					
						
							|  |  |  | 	      free (vendor); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  name = sanei_config_skip_whitespace (name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       name = sanei_config_skip_whitespace (name); | 
					
						
							|  |  |  |       if (*name) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  name = sanei_config_get_string (name, &product); | 
					
						
							|  |  |  | 	  if (product) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      productID = strtol (product, 0, 0); | 
					
						
							|  |  |  | 	      free (product); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       sanei_usb_find_devices (vendorID, productID, attach); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2001-09-05 19:48:24 +00:00
										 |  |  |     (*attach) (name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | SANE_Status | 
					
						
							|  |  |  | sanei_usb_get_vendor_product (SANE_Int fd, SANE_Word * vendor, | 
					
						
							|  |  |  | 			      SANE_Word * product) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-05-30 19:23:22 +00:00
										 |  |  |   SANE_Word vendorID = 0; | 
					
						
							|  |  |  |   SANE_Word productID = 0; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   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) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | #if defined (__linux__)
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       /* read the vendor and product IDs via the IOCTLs */ | 
					
						
							|  |  |  |       if (ioctl (devices[fd].fd, SCANNER_IOCTL_VENDOR, &vendorID) == -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (ioctl (devices[fd].fd, SCANNER_IOCTL_VENDOR_OLD, &vendorID) | 
					
						
							|  |  |  | 	      == -1) | 
					
						
							|  |  |  | 	    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 ... */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (devices[fd].method == sanei_usb_method_libusb) | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | #ifdef HAVE_LIBUSB
 | 
					
						
							|  |  |  |       vendorID = usb_device (devices[fd].libusb_handle)->descriptor.idVendor; | 
					
						
							|  |  |  |       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 */
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       DBG (1, "sanei_usb_get_vendor_product: access method %d not " | 
					
						
							|  |  |  | 	   "implemented\n", devices[fd].method); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   if (vendor) | 
					
						
							|  |  |  |     *vendor = vendorID; | 
					
						
							|  |  |  |   if (product) | 
					
						
							|  |  |  |     *product = productID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!vendorID || !productID) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       DBG (3, "sanei_usb_get_vendor_product: device %d: Your OS doesn't " | 
					
						
							|  |  |  | 	   "seem to support detection of vendor+product ids\n", fd); | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |       return SANE_STATUS_UNSUPPORTED; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       DBG (3, "sanei_usb_get_vendor_product: device %d: vendorID: 0x%04x, " | 
					
						
							|  |  |  | 	   "productID: 0x%04x\n", fd, vendorID, productID); | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |       return SANE_STATUS_GOOD; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-10 18:39:48 +00:00
										 |  |  | static SANE_Status | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | check_vendor_product (SANE_String_Const devname, SANE_Word vendor, | 
					
						
							|  |  |  | 		      SANE_Word product, | 
					
						
							|  |  |  | 		      SANE_Status (*attach) (SANE_String_Const dev)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SANE_Status status; | 
					
						
							|  |  |  |   SANE_Word devvendor, devproduct; | 
					
						
							|  |  |  |   SANE_Int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   status = sanei_usb_open (devname, &fd); | 
					
						
							|  |  |  |   if (status != SANE_STATUS_GOOD) | 
					
						
							| 
									
										
										
										
											2002-02-10 18:39:48 +00:00
										 |  |  |     return status; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   status = sanei_usb_get_vendor_product (fd, &devvendor, &devproduct); | 
					
						
							|  |  |  |   sanei_usb_close (fd); | 
					
						
							|  |  |  |   if (status == SANE_STATUS_GOOD) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (devvendor == vendor && devproduct == product) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (attach) | 
					
						
							|  |  |  | 	    attach (devname); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-02-10 18:39:48 +00:00
										 |  |  |   return status; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							|  |  |  | sanei_usb_find_devices (SANE_Int vendor, SANE_Int product, | 
					
						
							|  |  |  | 			SANE_Status (*attach) (SANE_String_Const dev)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SANE_String *prefix; | 
					
						
							| 
									
										
										
										
											2001-08-16 21:20:20 +00:00
										 |  |  |   SANE_String prefixlist[] = { | 
					
						
							|  |  |  | #if defined(__linux__)
 | 
					
						
							|  |  |  |     "/dev/usbscanner", | 
					
						
							|  |  |  |     "/dev/usb/scanner", | 
					
						
							|  |  |  | #elif defined(__FreeBSD__)
 | 
					
						
							|  |  |  |     "/dev/uscanner", | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |     0 | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   SANE_Char devname[1024]; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   int devcount; | 
					
						
							| 
									
										
										
										
											2002-02-10 18:39:48 +00:00
										 |  |  |   SANE_Status status; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | #define SANEI_USB_MAX_DEVICE_FILES 16
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   DBG (3, | 
					
						
							|  |  |  |        "sanei_usb_find_devices: vendor=0x%04x, product=0x%04x, attach=%p\n", | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |        vendor, product, attach); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   /* First we check the device files for access over the kernel scanner
 | 
					
						
							|  |  |  |      drivers */ | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   for (prefix = prefixlist; *prefix; prefix++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-02-10 18:39:48 +00:00
										 |  |  |       status = check_vendor_product (*prefix, vendor, product, attach); | 
					
						
							|  |  |  |       if (status == SANE_STATUS_UNSUPPORTED) | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 	break;			/* give up if we can't detect vendor/product */ | 
					
						
							|  |  |  |       for (devcount = 0; devcount < SANEI_USB_MAX_DEVICE_FILES; devcount++) | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 	  snprintf (devname, sizeof (devname), "%s%d", *prefix, devcount); | 
					
						
							| 
									
										
										
										
											2002-02-10 18:39:48 +00:00
										 |  |  | 	  status = check_vendor_product (devname, vendor, product, attach); | 
					
						
							|  |  |  | 	  if (status == SANE_STATUS_UNSUPPORTED) | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 	    break;		/* give up if we can't detect vendor/product */ | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   /* 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 */
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | sanei_usb_open (SANE_String_Const devname, SANE_Int * fd) | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   int devcount; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   if (!fd) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       DBG (1, "sanei_usb_open: can't open `%s': fd == NULL\n", devname); | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (devcount = 0; | 
					
						
							|  |  |  |        devcount < MAX_DEVICES && devices[devcount].open == SANE_TRUE; | 
					
						
							|  |  |  |        devcount++) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       /* Using kernel scanner driver */ | 
					
						
							|  |  |  |       devices[devcount].fd = open (devname, O_RDWR); | 
					
						
							|  |  |  |       if (devices[devcount].fd < 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  SANE_Status status = SANE_STATUS_INVAL; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | 	  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; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   devices[devcount].open = SANE_TRUE; | 
					
						
							|  |  |  |   *fd = devcount; | 
					
						
							|  |  |  |   DBG (3, "sanei_usb_open: opened usb device `%s' (*fd=%d)\n", | 
					
						
							|  |  |  |        devname, devcount); | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | sanei_usb_close (SANE_Int fd) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   DBG (5, "sanei_usb_close: closing device %d\n", 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; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | sanei_usb_read_bulk (SANE_Int fd, SANE_Byte * buffer, size_t * size) | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   ssize_t read_size = 0; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!size) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sanei_usb_read_bulk: size == NULL\n"); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   if (read_size < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sanei_usb_read_bulk: read failed: %s\n", strerror (errno)); | 
					
						
							|  |  |  |       *size = 0; | 
					
						
							|  |  |  |       return SANE_STATUS_IO_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (read_size == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (3, "sanei_usb_read_bulk: read returned EOF\n"); | 
					
						
							|  |  |  |       *size = 0; | 
					
						
							|  |  |  |       return SANE_STATUS_EOF; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-08-26 10:39:54 +00:00
										 |  |  |   DBG (5, "sanei_usb_read_bulk: wanted %lu bytes, got %ld bytes\n", | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |        (unsigned long) *size, (unsigned long) read_size); | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   *size = read_size; | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | sanei_usb_write_bulk (SANE_Int fd, SANE_Byte * buffer, size_t * size) | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   ssize_t write_size = 0; | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!size) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sanei_usb_write_bulk: size == NULL\n"); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   if (write_size < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sanei_usb_write_bulk: write failed: %s\n", strerror (errno)); | 
					
						
							|  |  |  |       *size = 0; | 
					
						
							|  |  |  |       return SANE_STATUS_IO_ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-08-26 10:39:54 +00:00
										 |  |  |   DBG (5, "sanei_usb_write_bulk: wanted %lu bytes, wrote %ld bytes\n", | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |        (unsigned long) *size, (unsigned long) write_size); | 
					
						
							| 
									
										
										
										
											2001-08-11 13:12:39 +00:00
										 |  |  |   *size = write_size; | 
					
						
							|  |  |  |   return SANE_STATUS_GOOD; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | SANE_Status | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  | sanei_usb_control_msg (SANE_Int fd, SANE_Int rtype, SANE_Int req, | 
					
						
							|  |  |  | 		       SANE_Int value, SANE_Int index, SANE_Int len, | 
					
						
							|  |  |  | 		       SANE_Byte * data) | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |   if (fd >= MAX_DEVICES || fd < 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       DBG (1, "sanei_usb_control_msg: fd >= MAX_DEVICES || fd < 0\n"); | 
					
						
							|  |  |  |       return SANE_STATUS_INVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (devices[fd].method == sanei_usb_method_scanner_driver) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  | #if defined(__linux__)
 | 
					
						
							| 
									
										
										
										
											2002-07-03 14:07:44 +00:00
										 |  |  |       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; | 
					
						
							| 
									
										
										
										
											2002-01-03 19:18:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } |