kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			3247 wiersze
		
	
	
		
			95 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			3247 wiersze
		
	
	
		
			95 KiB
		
	
	
	
		
			C
		
	
	
| /*
 | ||
|    check-usb-chip.c -- Find out what USB scanner chipset is used
 | ||
|    
 | ||
|    Copyright (C) 2003-2005 Henning Meier-Geinitz <henning@meier-geinitz.de>
 | ||
|    Copyright (C) 2003 Gerhard J<>ger <gerhard@gjaeger.de>
 | ||
|                       for LM983x tests
 | ||
|    Copyright (C) 2003 Gerard Klaver <gerard at gkall dot hobby dot nl>
 | ||
|                       for ICM532B tests
 | ||
| 
 | ||
|    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.
 | ||
| */
 | ||
| 
 | ||
| 
 | ||
| #include "../include/sane/config.h"
 | ||
| #include "../include/sane/sane.h"
 | ||
| #include <stdio.h>
 | ||
| #include <string.h>
 | ||
| #include <errno.h>
 | ||
| 
 | ||
| static int verbose = 0;
 | ||
| static SANE_Bool no_chipset_access;
 | ||
| #define TIMEOUT 1000
 | ||
| 
 | ||
| #ifdef HAVE_LIBUSB
 | ||
| #include <usb.h>
 | ||
| 
 | ||
| extern char *check_usb_chip (struct usb_device *dev, int verbosity,
 | ||
| 			     SANE_Bool from_file);
 | ||
| 
 | ||
| 
 | ||
| static int
 | ||
| prepare_interface (struct usb_device *dev, usb_dev_handle ** handle)
 | ||
| {
 | ||
|   int result;
 | ||
| 
 | ||
|   if (no_chipset_access)
 | ||
|     return 0;
 | ||
| 
 | ||
|   *handle = usb_open (dev);
 | ||
|   if (*handle == 0)
 | ||
|     {
 | ||
|       if (verbose > 1)
 | ||
| 	printf ("    Couldn't open device: %s\n", usb_strerror ());
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result =
 | ||
|     usb_set_configuration (*handle, dev->config[0].bConfigurationValue);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 1)
 | ||
| 	printf ("  Couldn't set configuration: %s\n", usb_strerror ());
 | ||
|       usb_close (*handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = usb_claim_interface (*handle, 0);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 1)
 | ||
| 	printf ("    Couldn't claim interface: %s\n", usb_strerror ());
 | ||
|       usb_close (*handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| finish_interface (usb_dev_handle * handle)
 | ||
| {
 | ||
|   usb_release_interface (handle, 0);
 | ||
|   usb_close (handle);
 | ||
| }
 | ||
| 
 | ||
| /* Check for Grandtech GT-6801 */
 | ||
| static char *
 | ||
| check_gt6801 (struct usb_device *dev)
 | ||
| {
 | ||
|   char req[64];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GT-6801 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6801 (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6801 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6801 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6801 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 1)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6801 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-6801 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we send a control message */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "GT-6801?";
 | ||
| 
 | ||
|   memset (req, 0, 64);
 | ||
|   req[0] = 0x2e;		/* get identification information */
 | ||
|   req[1] = 0x01;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0x2010, 0x3f40, req, 64, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send write control message (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0xc0, 0x01, 0x2011, 0x3f00, req, 64, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send read control message (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (req[0] != 0 || (req[1] != 0x2e && req[1] != 0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Unexpected result from control message (%0x/%0x)\n",
 | ||
| 		req[0], req[1]);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "GT-6801";
 | ||
| }
 | ||
| 
 | ||
| /* Check for Grandtech GT-6816 */
 | ||
| static char *
 | ||
| check_gt6816 (struct usb_device *dev)
 | ||
| {
 | ||
|   char req[64];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
|   int i;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GT-6816 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
 | ||
| 	  USB_CLASS_VENDOR_SPEC))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-6816 (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6816 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6816 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6816 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (dev->config[0].bNumInterfaces != 0x01)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6816 (bNumInterfaces = 0x%x)\n",
 | ||
| 		dev->config[0].bNumInterfaces);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-6816 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-6816 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-6816 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we send a control message */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "GT-6816?";
 | ||
| 
 | ||
|   memset (req, 0, 64);
 | ||
|   for (i = 0; i < 8; i++)
 | ||
|     {
 | ||
|       req[8 * i + 0] = 0x73;	/* check firmware */
 | ||
|       req[8 * i + 1] = 0x01;
 | ||
|     }
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x40, 0x04, 0x2012, 0x3f40, req, 64, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send write control message (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0xc0, 0x01, 0x2013, 0x3f00, req, 64, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       /* Before firmware upload, 64 bytes are returned. Some libusb
 | ||
| 	 implementations/operating systems can't seem to cope with short
 | ||
| 	 packets. */
 | ||
|       result =
 | ||
| 	usb_control_msg (handle, 0xc0, 0x01, 0x2013, 0x3f00, req, 8, TIMEOUT);
 | ||
|       if (result <= 0)
 | ||
| 	{
 | ||
| 	  if (verbose > 2)
 | ||
| 	    printf ("    Couldn't send read control message (%s)\n",
 | ||
| 		    strerror (errno));
 | ||
| 	  finish_interface (handle);
 | ||
| 	  return 0;
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   if (req[0] != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Unexpected result from control message (%0x/%0x)\n",
 | ||
| 		req[0], req[1]);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "GT-6816";
 | ||
| }
 | ||
| 
 | ||
| /* Check for Grandtech GT-8911 */
 | ||
| static char *
 | ||
| check_gt8911 (struct usb_device *dev)
 | ||
| {
 | ||
|   char req[64];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GT-8911 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
 | ||
| 	  USB_CLASS_VENDOR_SPEC))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 1, bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-8911 (check 2, bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 3, bDeviceSubClass = 0x%x)\n",
 | ||
| 	   dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 4, bDeviceProtocol = 0x%x)\n",
 | ||
| 	   dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-8911 (check 5, bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Check first endpoint descriptor block */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 6, bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 7, bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
| 
 | ||
|     }
 | ||
|   if (dev->config[0].bNumInterfaces < 2)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-8911 (check 8, bNumInterfaces = %d)\n",
 | ||
| 		dev->config[0].bNumInterfaces);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->config[0].interface[1].num_altsetting < 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GT-8911 (check 9, num_altsetting = %d)\n",
 | ||
| 		dev->config[0].interface[1].num_altsetting);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check fourth endpoint descriptor block */
 | ||
|   if ((dev->config[0].interface[1].altsetting[2].endpoint[0].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[1].altsetting[2].endpoint[0].
 | ||
| 	  bmAttributes != 0x01)
 | ||
|       || (dev->config[0].interface[1].altsetting[2].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x01d0)
 | ||
|       || (dev->config[0].interface[1].altsetting[2].endpoint[0].bInterval !=
 | ||
| 	  0x01))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 10, bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[1].altsetting[2].endpoint[1].
 | ||
|        bEndpointAddress != 0x04)
 | ||
|       || (dev->config[0].interface[1].altsetting[2].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[1].altsetting[2].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[1].altsetting[2].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 11, bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[1].altsetting[2].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we send a control message */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "GT-8911?";
 | ||
| 
 | ||
|   memset (req, 0, 8);
 | ||
|   req[0] = 0x55;
 | ||
|   req[1] = 0x66;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0xc0, 0x10, 0x41, 0x0000, req, 64, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 12, couldn't send read control message (%s))\n",
 | ||
| 	   strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0xc0, 0x10, 0x05, 0x0000, req, 64, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GT-8911 (check 13, couldn't send read control message (%s)\n",
 | ||
| 	   strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* tested on model hardware version 0xffffffc0, firmware version 0x10)) */
 | ||
|   if (verbose > 2)
 | ||
|     printf
 | ||
|       ("    Check 14, control message (hardware version %0x / firmware version %0x)\n",
 | ||
|        req[0], req[1]);
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "GT-8911";
 | ||
| }
 | ||
| 
 | ||
| /* Check for Mustek MA-1017 */
 | ||
| static char *
 | ||
| check_ma1017 (struct usb_device *dev)
 | ||
| {
 | ||
|   char req[2];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
|   char res;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for MA-1017 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
 | ||
| 	  USB_CLASS_PER_INTERFACE))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1017 (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x100)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1017 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1017 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1017 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1017 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1017 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x82)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1017 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0x01))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1017 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* read a register value */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "MA-1017?";
 | ||
| 
 | ||
|   req[0] = 0x00;
 | ||
|   req[1] = 0x02 | 0x20;
 | ||
|   result = usb_bulk_write (handle, 0x01, req, 2, 1000);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1017 (Error during bulk write)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   result = usb_bulk_read (handle, 0x82, &res, 1, 1000);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1017 (Error during bulk read)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Read one byte again to work around a bug in the MA-1017 chipset that 
 | ||
|      appears when an odd number of bytes is read or written. */
 | ||
|   result = usb_bulk_write (handle, 0x01, req, 2, 1000);
 | ||
|   result = usb_bulk_read (handle, 0x82, &res, 1, 1000);
 | ||
|   finish_interface (handle);
 | ||
|   return "MA-1017";
 | ||
| }
 | ||
| 
 | ||
| /* Check for Mustek MA-1015 */
 | ||
| static char *
 | ||
| check_ma1015 (struct usb_device *dev)
 | ||
| {
 | ||
|   char req[8];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
|   unsigned char res;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for MA-1015 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x100)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1015 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x08)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1015 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we read register 0 to find out if this is really a MA-1015 */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return 0;
 | ||
| 
 | ||
|   memset (req, 0, 8);
 | ||
|   req[0] = 33;
 | ||
|   req[1] = 0x00;
 | ||
|   result = usb_bulk_write (handle, 0x02, req, 8, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (Error during bulk write)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   result = usb_bulk_read (handle, 0x81, (char *) &res, 1, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (Error during bulk read)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (res != 0xa5)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1015 (got 0x%x, expected 0xa5)\n", res);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "MA-1015";
 | ||
| }
 | ||
| 
 | ||
| /* Check for Mustek MA-1509 */
 | ||
| static char *
 | ||
| check_ma1509 (struct usb_device *dev)
 | ||
| {
 | ||
|   char req[8];
 | ||
|   char inquiry[0x60];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for MA-1509 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1509 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x08))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1509 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x08)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0x10))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a MA-1509 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* This is a SCSI-over-USB chip, we'll read the inquiry */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "MA-1509?";
 | ||
| 
 | ||
|   memset (req, 0, 8);
 | ||
|   req[0] = 0x12;
 | ||
|   req[1] = 1;
 | ||
|   req[6] = 0x60;
 | ||
| 
 | ||
|   result = usb_bulk_write (handle, 0x02, req, 8, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (Error during bulk write)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   memset (inquiry, 0, 0x60);
 | ||
|   result = usb_bulk_read (handle, 0x81, (char *) inquiry, 0x60, TIMEOUT);
 | ||
|   if (result != 0x60)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (Error during bulk read: %d)\n",
 | ||
| 		result);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((inquiry[0] & 0x1f) != 0x06)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (inquiry [0] = %d)\n", inquiry[0]);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (strncmp (inquiry + 8, "SCANNER ", 8) != 0)
 | ||
|     {
 | ||
|       inquiry[16] = 0;
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a MA-1509 (vendor=%s)\n", inquiry + 8);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   inquiry[36] = 0;
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    MA-1509 version %s\n", inquiry + 32);
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "MA-1509";
 | ||
| }
 | ||
| 
 | ||
| /********** the lm983x section **********/
 | ||
| 
 | ||
| static int
 | ||
| lm983x_wb (usb_dev_handle * handle, unsigned char reg, unsigned char val)
 | ||
| {
 | ||
|   unsigned char buf[5];
 | ||
|   int result;
 | ||
| 
 | ||
|   buf[0] = 0;
 | ||
|   buf[1] = reg;
 | ||
|   buf[2] = 0;
 | ||
|   buf[3] = 1;
 | ||
|   buf[4] = val;
 | ||
| 
 | ||
|   result = usb_bulk_write (handle, 3, (char *) buf, 5, TIMEOUT);
 | ||
|   if (result != 5)
 | ||
|     return 0;
 | ||
| 
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| static int
 | ||
| lm983x_rb (usb_dev_handle * handle, unsigned char reg, unsigned char *val)
 | ||
| {
 | ||
|   unsigned char buf[5];
 | ||
|   int result;
 | ||
| 
 | ||
|   buf[0] = 1;
 | ||
|   buf[1] = reg;
 | ||
|   buf[2] = 0;
 | ||
|   buf[3] = 1;
 | ||
| 
 | ||
|   result = usb_bulk_write (handle, 3, (char *) buf, 4, TIMEOUT);
 | ||
|   if (result != 4)
 | ||
|     return 0;
 | ||
| 
 | ||
| 
 | ||
|   result = usb_bulk_read (handle, 2, (char *) val, 1, TIMEOUT);
 | ||
|   if (result != 1)
 | ||
|     return 0;
 | ||
| 
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| static char *
 | ||
| check_merlin (struct usb_device *dev)
 | ||
| {
 | ||
|   unsigned char val;
 | ||
|   int result;
 | ||
|   usb_dev_handle *handle;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for LM983[1,2,3] ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|        && (dev->descriptor.bDeviceClass != 0))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
 | ||
| 	  USB_CLASS_VENDOR_SPEC))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a LM983x (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->descriptor.bcdUSB != 0x110)
 | ||
|       && (dev->descriptor.bcdUSB != 0x101)
 | ||
|       && (dev->descriptor.bcdUSB != 0x100))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a LM983x (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a LM983x (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->descriptor.bDeviceProtocol != 0) &&
 | ||
|       (dev->descriptor.bDeviceProtocol != 0xff))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a LM983x (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a LM983x (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x1)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x10))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x82)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       /* Currently disabled as we have some problems in detection here ! */
 | ||
|       /*|| (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0) */
 | ||
|     )
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       /* Currently disabled as we have some problems in detection here ! */
 | ||
|       /* || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0) */
 | ||
|     )
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "LM983x?";
 | ||
| 
 | ||
|   result = lm983x_wb (handle, 0x07, 0x00);
 | ||
|   if (1 == result)
 | ||
|     result = lm983x_wb (handle, 0x08, 0x02);
 | ||
|   if (1 == result)
 | ||
|     result = lm983x_rb (handle, 0x07, &val);
 | ||
|   if (1 == result)
 | ||
|     result = lm983x_rb (handle, 0x08, &val);
 | ||
|   if (1 == result)
 | ||
|     result = lm983x_rb (handle, 0x69, &val);
 | ||
| 
 | ||
|   if (0 == result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("  Couldn't access LM983x registers.\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
| 
 | ||
|   switch (val)
 | ||
|     {
 | ||
|     case 4:
 | ||
|       return "LM9832/3";
 | ||
|       break;
 | ||
|     case 3:
 | ||
|       return "LM9831";
 | ||
|       break;
 | ||
|     case 2:
 | ||
|       return "LM9830";
 | ||
|       break;
 | ||
|     default:
 | ||
|       return "LM983x?";
 | ||
|       break;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /********** the gl646 section **********/
 | ||
| 
 | ||
| 
 | ||
| static int
 | ||
| gl646_write_reg (usb_dev_handle * handle, unsigned char reg,
 | ||
| 		 unsigned char val)
 | ||
| {
 | ||
|   int result;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x00, 0x00, 0x83, 0x00, (char *) ®, 0x01,
 | ||
| 		     TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     return 0;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x00, 0x00, 0x85, 0x00, (char *) &val, 0x01,
 | ||
| 		     TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     return 0;
 | ||
| 
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| static int
 | ||
| gl646_read_reg (usb_dev_handle * handle, unsigned char reg,
 | ||
| 		unsigned char *val)
 | ||
| {
 | ||
|   int result;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x00, 0x00, 0x83, 0x00, (char *) ®, 0x01,
 | ||
| 		     TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     return 0;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x80, 0x00, 0x84, 0x00, (char *) val, 0x01,
 | ||
| 		     TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     return 0;
 | ||
| 
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static char *
 | ||
| check_gl646 (struct usb_device *dev)
 | ||
| {
 | ||
|   unsigned char val;
 | ||
|   int result;
 | ||
|   usb_dev_handle *handle;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GL646 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 0x10))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646 (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x1)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  8))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "GL646?";
 | ||
| 
 | ||
|   result = gl646_write_reg (handle, 0x38, 0x15);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (writing register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = gl646_read_reg (handle, 0x4e, &val);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (reading register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (val != 0x15)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646 (reg 0x4e != reg 0x38)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "GL646";
 | ||
| }
 | ||
| 
 | ||
| /* Same as check_gl646, except that sanity check are different. */
 | ||
| static char *
 | ||
| check_gl646_hp (struct usb_device *dev)
 | ||
| {
 | ||
|   unsigned char val;
 | ||
|   int result;
 | ||
|   usb_dev_handle *handle;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GL646_HP ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != 0xff)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 0xff))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646_HP (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646_HP (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646_HP (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x1)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  8))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL646_HP (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "GL646_HP?";
 | ||
| 
 | ||
|   result = gl646_write_reg (handle, 0x38, 0x15);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (writing register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = gl646_read_reg (handle, 0x4e, &val);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (reading register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (val != 0x15)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL646_HP (reg 0x4e != reg 0x38)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
| 
 | ||
|   return "GL646_HP";
 | ||
| }
 | ||
| 
 | ||
| /* check for the combination of gl660 and gl646 */
 | ||
| static char *
 | ||
| check_gl660_gl646 (struct usb_device *dev)
 | ||
| {
 | ||
|   unsigned char val;
 | ||
|   int result;
 | ||
|   usb_dev_handle *handle;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GL660+GL646 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
 | ||
| 	  USB_CLASS_PER_INTERFACE))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL660+GL646 (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x200)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       ||
 | ||
|       ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	wMaxPacketSize != 0x40)
 | ||
|        && (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL660+GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       ||
 | ||
|       ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	wMaxPacketSize != 0x40)
 | ||
|        && (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL660+GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       ||
 | ||
|       ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	wMaxPacketSize != 0x1)
 | ||
|        && (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  8))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL660+GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "GL660+GL646?";
 | ||
| 
 | ||
|   result = gl646_write_reg (handle, 0x38, 0x15);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (writing register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = gl646_read_reg (handle, 0x4e, &val);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (reading register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (val != 0x15)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL660+GL646 (reg 0x4e != reg 0x38)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "GL660+GL646";
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /********** the gl841 section **********/
 | ||
| 
 | ||
| /* the various incarnations could be distinguished by the 
 | ||
|  * bcdDevice entry:
 | ||
|  *   >= 0x400 --> GL843 ( >= 0x500 --> 845???)
 | ||
|  *   >= 0x306 --> GL842 (probably >= 0x303???)
 | ||
|  *   >= 0x200 --> GL841
 | ||
|  */
 | ||
| static char *
 | ||
| check_gl841 (struct usb_device *dev)
 | ||
| {
 | ||
|   unsigned char val;
 | ||
|   int result;
 | ||
|   usb_dev_handle *handle;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for GL84x ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
 | ||
| 	  USB_CLASS_VENDOR_SPEC))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL841 (bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x200)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize != 0x40) &&
 | ||
| 	  (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL841 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize != 0x40) &&
 | ||
| 	  (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL841 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x1)
 | ||
|       ||
 | ||
|       ((dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 8)
 | ||
|        && (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	   16)))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a GL841 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result) {
 | ||
|     if (dev->descriptor.bcdDevice >= 0x400)
 | ||
| 	return "GL843?";
 | ||
|     if (dev->descriptor.bcdDevice >= 0x306)
 | ||
| 	return "GL842";
 | ||
|     else
 | ||
| 	return "GL841?";
 | ||
|   }
 | ||
| 
 | ||
|   result = gl646_write_reg (handle, 0x38, 0x15);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (writing register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = gl646_read_reg (handle, 0x38, &val);
 | ||
|   if (!result)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (reading register failed)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (val != 0x15)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a GL841 (reg 0x38 != 0x15)\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   if (dev->descriptor.bcdDevice >= 0x400)
 | ||
|     return "GL843";
 | ||
| 
 | ||
|   if (dev->descriptor.bcdDevice >= 0x306)
 | ||
|     return "GL842";
 | ||
| 
 | ||
|   return "GL841";
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /********** the icm532b section version 0.2 **********/
 | ||
| /*          no write and read test registers yet     */
 | ||
| 
 | ||
| static char *
 | ||
| check_icm532b (struct usb_device *dev)
 | ||
| {
 | ||
|   int result;
 | ||
|   usb_dev_handle *handle;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for ICM532B ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 0xff))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 1, bDeviceClass = %d, bInterfaceClass = %d)\n",
 | ||
| 	   dev->descriptor.bDeviceClass,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a ICM532B (check 2, bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 3, bDeviceSubClass = 0x%x)\n",
 | ||
| 	   dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 4, bDeviceProtocol = 0x%x)\n",
 | ||
| 	   dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 0x01)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a ICM532B (check 5, bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Check bEndpointAddress */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|       bEndpointAddress != 0x81)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 6, bEndpointAddress = %d)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Check bmAttributes */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|       bmAttributes != 0x01)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 7, bEndpointAddress = %d)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bmAttributes);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].bAlternateSetting != 0x00)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 8, bAlternateSetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[1].bAlternateSetting != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[1].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x100))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 9, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[1].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[1].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[2].bAlternateSetting != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[2].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x180))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 10, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[2].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[2].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[3].bAlternateSetting != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[3].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x200))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 11, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[3].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[3].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[4].bAlternateSetting != 0x04)
 | ||
|       || (dev->config[0].interface[0].altsetting[4].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x280))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 12, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[4].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[4].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[5].bAlternateSetting != 0x05)
 | ||
|       || (dev->config[0].interface[0].altsetting[5].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x300))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 13, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[5].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[5].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[6].bAlternateSetting != 0x06)
 | ||
|       || (dev->config[0].interface[0].altsetting[6].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x380))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 14, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[6].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[6].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[7].bAlternateSetting != 0x07)
 | ||
|       || (dev->config[0].interface[0].altsetting[7].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x3ff))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a ICM532B (check 15, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[7].bAlternateSetting,
 | ||
| 	   dev->config[0].interface[0].altsetting[7].endpoint[0].
 | ||
| 	   wMaxPacketSize);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "ICM532B?";
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "ICM532B";
 | ||
| }
 | ||
| /* ====================================== end of icm532b ==================*/
 | ||
| 
 | ||
| 
 | ||
| /* Check for the combination of a PowerVision PV8630 (USB->parport bridge)
 | ||
|    and National Semiconductor LM9830 */
 | ||
| static char *
 | ||
| check_pv8630_lm9830 (struct usb_device *dev)
 | ||
| {
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
|   char data;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for PV8630/LM9830 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a PV8630/LM9830 (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x100)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a PV8630/LM9830 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a PV8630/LM9830 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a PV8630/LM9830 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a PV8630/LM9830 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Endpoint 0 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a PV8630/LM9830 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Endpoint 1 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x82)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a PV8630/LM9830 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Endpoint 2 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0x01))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a PV8630/LM9830 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we write/read a register (red offset) */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "PV8630/LM9830?";
 | ||
| 
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0x38, 0x01, NULL, 0, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send write register number (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0x0f, 0x00,  NULL, 0, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send register data (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0x38, 0x01, NULL, 0, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send read register number (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0xc0, 0x00, 0, 0x00, &data, 1, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't read register data (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (data != 0x0f)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Data read != data written (%d/%d)\n", data, 0x0f);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "PV8630/LM9830";
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* Check for Toshiba M011 */
 | ||
| static char *
 | ||
| check_m011 (struct usb_device *dev)
 | ||
| {
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
|   char data;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for M011 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a M011 (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x100)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a M011 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != USB_CLASS_VENDOR_SPEC)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a M011 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != USB_CLASS_VENDOR_SPEC)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a M011 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 1)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a M011 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Endpoint 0 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x82)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a M011 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we write/read a register (red offset) */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "M011?";
 | ||
| 
 | ||
|   data = 0x63;
 | ||
| 
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0x40, 0x08, 0x34, 0x00, &data, 1, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't write register (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   data = 0;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg (handle, 0xc0, 0x00, 0x34, 0x00, &data, 1, TIMEOUT);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't read register (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (data != 0x63)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Data read != data written (%d/%d)\n", data, 0x63);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "M011";
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* Check for Realtek rts8858c */
 | ||
| static int
 | ||
| rts88xx_read_reg (usb_dev_handle * handle, unsigned char *req, unsigned char *res, int size)
 | ||
| {
 | ||
|   int result;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_bulk_write (handle, 0x02, (char *)req, 0x04, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     return 0;
 | ||
| 
 | ||
|   result =
 | ||
|     usb_bulk_read (handle,  0x81, (char *)res, size, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     return 0;
 | ||
| 
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| static char *
 | ||
| check_rts8858c (struct usb_device *dev)
 | ||
| {
 | ||
|   unsigned char req[4];
 | ||
|   unsigned char res[10];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for rts8858c ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a rts8858c (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x110)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a rts8858c (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a rts8858c (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a rts8858c (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a rts8858c (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a rts8858c (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x08)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a rts8858c (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0xFA))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a rts8858c (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we read 10 registers */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "rts8858c?";
 | ||
| 
 | ||
|   memset (req, 0, 4);
 | ||
|   req[0] = 0x80;		/* get registers 0x12-0x1c */
 | ||
|   req[1] = 0x12;
 | ||
|   req[2] = 0x00;
 | ||
|   req[3] = 0x0a;
 | ||
| 
 | ||
|   result = rts88xx_read_reg(handle,req,res,req[3]);
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't read registers\n");
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (res[1] != 0x03 || res[2] != 0x00)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Unexpected result from register reading (0x%0x/0x%0x)\n",
 | ||
| 		res[1], res[2]);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "rts8858c";
 | ||
| }	/* end of rts8858 detection */
 | ||
| 
 | ||
| 
 | ||
| /* Check for Service & Quality SQ113 */
 | ||
| static char *
 | ||
| check_sq113 (struct usb_device *dev)
 | ||
| {
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
|   unsigned char data;
 | ||
|   unsigned char buffer[4];
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for SQ113 ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x200)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check interface */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 255)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bInterfaceClass = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bInterfaceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bInterfaceSubClass != 255)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bInterfaceSubClass = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bInterfaceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bInterfaceProtocol != 255)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bInterfaceProtocol = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bInterfaceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a SQ113 (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Endpoint 0 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
| 	  && (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	      wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a SQ113 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Endpoint 1 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x82)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x40)
 | ||
| 	  && (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	      wMaxPacketSize != 0x200))
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a SQ113 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   /* Endpoint 2 */
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x1)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0x03))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a SQ113 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we read the status register */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "SQ113?";
 | ||
|   
 | ||
|   buffer [0] = 0x5f;
 | ||
|   buffer [1] = 0x00;
 | ||
|   buffer [2] = 0x5f;
 | ||
|   buffer [3] = 0x00;
 | ||
| 
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0xb0, 0, (char *) buffer, 4, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't set bank (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   data = 0x00;
 | ||
| 
 | ||
|   buffer [0] = 0x8b;
 | ||
|   buffer [1] = data;
 | ||
|   buffer [2] = 0x8b;
 | ||
|   buffer [3] = data;
 | ||
| 
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0xb0, 0, (char *) buffer, 4, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't write register (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   buffer [0] = 0x8b;
 | ||
|   buffer [1] = 0x8b;
 | ||
|   buffer [2] = 0x8b;
 | ||
|   buffer [3] = 0x8b;
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0x40, 0x01, 0x04, 0x8b, (char *) buffer, 4, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't set read register address (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = 
 | ||
|     usb_control_msg (handle, 0xc0, 0x01, 0x07, 0, (char *) buffer, 4, TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't read register (%s)\n",
 | ||
| 		usb_strerror ());
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((buffer[0] & 0x10) != 0x10)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Sensor not home? (0x%02x)\n", buffer[0]);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "SQ113";
 | ||
| }
 | ||
| 
 | ||
| /* Check for Realtek RTS8822L-01H chipset*/
 | ||
| static char *
 | ||
| check_rts8822l01h (struct usb_device *dev)
 | ||
| {
 | ||
|   char data[2];
 | ||
|   usb_dev_handle *handle;
 | ||
|   int result;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for RTS8822L-01H ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a RTS8822L-01H (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->descriptor.bcdUSB != 0x200)&&(dev->descriptor.bcdUSB != 0x110))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a RTS8822L-01H (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a RTS8822L-01H (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a RTS8822L-01H (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a RTS8822L-01H (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x200)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a RTS8822L-01H (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x200)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a RTS8822L-01H (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0x0c))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a RTS8822L-01H (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Now we read 1 register */
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return "rts8822L-01H?";
 | ||
| 
 | ||
|   memset (data, 0, 2);
 | ||
| 
 | ||
|   result =
 | ||
|     usb_control_msg(handle, 0xc0, 0x04, 0xfe11, 0x100, data, 0x02, TIMEOUT);
 | ||
| 
 | ||
|   if (result <= 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send read control message (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (data == 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Unexpected result from register 0xfe11 : 0x%0x%0x\n",
 | ||
| 		data[1], data[0]);
 | ||
|       finish_interface (handle);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   finish_interface (handle);
 | ||
|   return "RTS8822L-01H";
 | ||
| }	/* end of RTS8822L-01H detection */
 | ||
| 
 | ||
| /* Check for Silitek chipset found in HP5550/5590/7650 scanners */
 | ||
| static char *
 | ||
| check_hp5590 (struct usb_device *dev)
 | ||
| {
 | ||
|   usb_dev_handle 	*handle;
 | ||
|   int 			result;
 | ||
|   u_int8_t 		status;
 | ||
|   struct usb_ctrl_setup ctrl;
 | ||
|   u_int8_t 		data[0x32];
 | ||
|   u_int8_t 		ack;
 | ||
|   u_int8_t 		*ptr;
 | ||
|   int 			next_packet_size;
 | ||
|   unsigned int 		len;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("    checking for HP5550/5590/7650 chipset ...\n");
 | ||
| 
 | ||
|   /* Check device descriptor */
 | ||
|   if (dev->descriptor.bDeviceClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a HP5550/5590/7650 chipset (bDeviceClass = %d)\n",
 | ||
| 		dev->descriptor.bDeviceClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bcdUSB != 0x200)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a HP5550/5590/7650 chipset (bcdUSB = 0x%x)\n",
 | ||
| 		dev->descriptor.bcdUSB);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceSubClass != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a HP5550/5590/7650 chipset (bDeviceSubClass = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceSubClass);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if (dev->descriptor.bDeviceProtocol != 0xff)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a HP5550/5590/7650 chipset (bDeviceProtocol = 0x%x)\n",
 | ||
| 		dev->descriptor.bDeviceProtocol);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check endpoints */
 | ||
|   if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    this is not a HP5550/5590/7650 chipset (bNumEndpoints = %d)\n",
 | ||
| 		dev->config[0].interface[0].altsetting[0].bNumEndpoints);
 | ||
|       return 0;
 | ||
|     }
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
|        bEndpointAddress != 0x81)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	  wMaxPacketSize != 0x200)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a HP5550/5590/7650 chipset (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
|        bEndpointAddress != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  bmAttributes != 0x02)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	  wMaxPacketSize != 0x200)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval !=
 | ||
| 	  0x00))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a HP5550/5590/7650 chipset (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   if ((dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
|        bEndpointAddress != 0x83)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  bmAttributes != 0x03)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	  wMaxPacketSize != 0x01)
 | ||
|       || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval !=
 | ||
| 	  0x08))
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf
 | ||
| 	  ("    this is not a HP5550/5590/7650 chipset (bEndpointAddress = 0x%x, bmAttributes = 0x%x, "
 | ||
| 	   "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n",
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   bEndpointAddress,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].
 | ||
| 	   wMaxPacketSize,
 | ||
| 	   dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval);
 | ||
|       return 0;
 | ||
|     }
 | ||
| 
 | ||
|   result = prepare_interface (dev, &handle);
 | ||
|   if (!result)
 | ||
|     return NULL;
 | ||
| 
 | ||
|   /* USB-in-USB command URB - command 0x0012 (init scanner), returns 0x32 bytes */
 | ||
|   memset (&ctrl, 0, sizeof(ctrl));
 | ||
|   ctrl.bRequestType = 0xc0;
 | ||
|   ctrl.bRequest = 0x04;
 | ||
|   ctrl.wValue = 0x1200;
 | ||
|   ctrl.wIndex = 0x00;
 | ||
|   ctrl.wLength = sizeof(data);
 | ||
|   result = usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR,
 | ||
| 			    0x04, 0x8f, 0x00,
 | ||
| 			    (char *) &ctrl, sizeof (ctrl), TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send send USB-in-USB command (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   /* Get confirmation for USB-in-USB command */
 | ||
|   result = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR, 
 | ||
| 			    0x0c, 0x8e, 0x20,
 | ||
| 			    (char *) &status, sizeof(status), TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't read USB-in-USB confirmation (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check the confirmation received */
 | ||
|   if (status != 0x01)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Didn't get correct confirmation for USB-in-USB command "
 | ||
| 	        "(needed: 0x01, got: 0x%02x\n",
 | ||
| 	        status);
 | ||
|       finish_interface (handle);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   /* Read data in 8 byte packets */
 | ||
|   ptr = data;
 | ||
|   len = sizeof(data);
 | ||
|   while (len)
 | ||
|     {
 | ||
|       next_packet_size = 8;
 | ||
|       if (len < 8)
 | ||
| 	next_packet_size = len;
 | ||
| 
 | ||
|       /* Read data packet */
 | ||
|       result = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR,
 | ||
| 				0x04, 0x90, 0x00,
 | ||
| 				(char *) ptr, next_packet_size, TIMEOUT);
 | ||
|       if (result < 0)
 | ||
| 	{
 | ||
| 	  if (verbose > 2)
 | ||
| 	    printf ("    Couldn't read USB-in-USB data (%s)\n",
 | ||
| 		    strerror (errno));
 | ||
| 	  finish_interface (handle);
 | ||
| 	  return NULL;
 | ||
| 	}
 | ||
| 
 | ||
|       /* Check if all of the requested data was received */
 | ||
|       if (result != next_packet_size)
 | ||
| 	{
 | ||
| 	  if (verbose > 2)
 | ||
| 	    printf ("    Incomplete USB-in-USB data received (needed: %u, got: %u)\n",
 | ||
| 		    next_packet_size, result);
 | ||
| 	  finish_interface (handle);
 | ||
| 	  return NULL;
 | ||
| 	}
 | ||
| 
 | ||
|       ptr += next_packet_size;
 | ||
|       len -= next_packet_size;
 | ||
|     }
 | ||
| 
 | ||
|   /* Acknowledge the whole received data */
 | ||
|   ack = 0;
 | ||
|   result = usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR,
 | ||
| 			    0x0c, 0x8f, 0x00,
 | ||
| 			    (char *) &ack, sizeof(ack), TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't send USB-in-USB data confirmation (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   /* Get confirmation for acknowledge */
 | ||
|   result = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR,
 | ||
| 			    0x0c, 0x8e, 0x20,
 | ||
| 			    (char *) &status, sizeof(status), TIMEOUT);
 | ||
|   if (result < 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Couldn't read USB-in-USB confirmation for data confirmation (%s)\n",
 | ||
| 		strerror (errno));
 | ||
|       finish_interface (handle);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check the confirmation received */
 | ||
|   if (status != 0x01)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("    Didn't get correct confirmation for USB-in-USB command "
 | ||
| 	        "(needed: 0x01, got: 0x%02x\n",
 | ||
| 	        status);
 | ||
|       finish_interface (handle);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   /* Check vendor ID */
 | ||
|   if (memcmp (data+1, "SILITEK", 7) != 0)
 | ||
|     {
 | ||
|       if (verbose > 2)
 | ||
| 	printf ("   Incorrect product ID received\n");
 | ||
|       finish_interface (handle);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   finish_interface (handle);
 | ||
|   return "HP5550/5590/7650";
 | ||
| }
 | ||
| 
 | ||
| char *
 | ||
| check_usb_chip (struct usb_device *dev, int verbosity, SANE_Bool from_file)
 | ||
| {
 | ||
|   char *chip_name = 0;
 | ||
| 
 | ||
|   verbose = verbosity;
 | ||
|   no_chipset_access = from_file;
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     printf ("\n<trying to find out which USB chip is used>\n");
 | ||
| 
 | ||
|   chip_name = check_gt6801 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_gt6816 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_gt8911 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_ma1017 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_ma1015 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_ma1509 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_merlin (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_gl646 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_gl646_hp (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_gl660_gl646 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_gl841 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_icm532b (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_pv8630_lm9830 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_m011 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_rts8822l01h (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_rts8858c (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_sq113 (dev);
 | ||
| 
 | ||
|   if (!chip_name)
 | ||
|     chip_name = check_hp5590 (dev);
 | ||
| 
 | ||
|   if (verbose > 2)
 | ||
|     {
 | ||
|       if (chip_name)
 | ||
| 	printf ("<This USB chip looks like a %s (result from %s)>\n\n",
 | ||
| 		chip_name, PACKAGE_STRING);
 | ||
|       else
 | ||
| 	printf ("<Couldn't determine the type of the USB chip (result from %s)>\n\n",
 | ||
| 		PACKAGE_STRING);
 | ||
|     }
 | ||
| 
 | ||
|   return chip_name;
 | ||
| }
 | ||
| 
 | ||
| #endif /* HAVE_LIBUSB */
 |