diff options
Diffstat (limited to 'tools/check-usb-chip.c')
-rw-r--r-- | tools/check-usb-chip.c | 4128 |
1 files changed, 4128 insertions, 0 deletions
diff --git a/tools/check-usb-chip.c b/tools/check-usb-chip.c new file mode 100644 index 0000000..68b8f79 --- /dev/null +++ b/tools/check-usb-chip.c @@ -0,0 +1,4128 @@ +/* + 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 Jaeger <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" + +#ifdef HAVE_LIBUSB + +#include "../include/sane/sane.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#ifdef HAVE_LUSB0_USB_H +#include <lusb0_usb.h> +#else +#include <usb.h> +#endif + +#include "../include/_stdint.h" + +static int verbose = 0; +static SANE_Bool no_chipset_access; +#define TIMEOUT 1000 + +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: + * 0x701 --> GL124 + * 0x700 --> ? + * 0x605 --> GL845 + * 0x603 --> GL847 + * 0x601 --> GL846 + * 0x500 --> GL843 + * 0x300 --> GL842 (perhaps only >= 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 GL84x (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 GL84x (bcdUSB = 0x%x)\n", + dev->descriptor.bcdUSB); + return 0; + } + if (dev->descriptor.bDeviceSubClass != 0xff) + { + if (verbose > 2) + printf (" this is not a GL84x (bDeviceSubClass = 0x%x)\n", + dev->descriptor.bDeviceSubClass); + return 0; + } + if (dev->descriptor.bDeviceProtocol != 0xff) + { + if (verbose > 2) + printf (" this is not a GL84x (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 GL84x (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 GL84x (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 GL84x (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 GL84x (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 == 0x702) + return "GL124?"; + if (dev->descriptor.bcdDevice == 0x701) + return "GL124?"; + if (dev->descriptor.bcdDevice >= 0x700) + return "GL848+?"; + if (dev->descriptor.bcdDevice >= 0x603) + return "GL847?"; + if (dev->descriptor.bcdDevice >= 0x600) + return "GL846?"; + if (dev->descriptor.bcdDevice >= 0x500) + return "GL845?"; + if (dev->descriptor.bcdDevice >= 0x400) + return "GL843?"; + if (dev->descriptor.bcdDevice >= 0x300) + return "GL842?"; + else + return "GL841?"; + } + + result = gl646_write_reg (handle, 0x38, 0x15); + if (!result) + { + if (verbose > 2) + printf (" this is not a GL84x (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 GL84x (reading register failed)\n"); + finish_interface (handle); + return 0; + } + + if (val != 0x15) + { + if (verbose > 2) + printf (" this is not a GL84x (reg 0x38 != 0x15)\n"); + finish_interface (handle); + return 0; + } + finish_interface (handle); + + if (dev->descriptor.bcdDevice == 0x702) + return "GL128"; + if (dev->descriptor.bcdDevice == 0x701) + return "GL124"; + if (dev->descriptor.bcdDevice >= 0x700) + return "GL848+"; + if (dev->descriptor.bcdDevice >= 0x605) + return "GL845"; + if (dev->descriptor.bcdDevice >= 0x603) + return "GL847"; + if (dev->descriptor.bcdDevice >= 0x600) + return "GL846"; + if (dev->descriptor.bcdDevice >= 0x500) + return "GL843"; + if (dev->descriptor.bcdDevice >= 0x300) + 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 rts88xx */ +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 */ + +static char * +check_rts88x1 (struct usb_device *dev) +{ + unsigned char req[4]; + unsigned char res[243]; + usb_dev_handle *handle; + int result; + + if (verbose > 2) + printf (" checking for rts8801/rts8891 ...\n"); + + /* Check device descriptor */ + if (dev->descriptor.bDeviceClass != 0) + { + if (verbose > 2) + printf (" this is not a rts8801/rts8891 (bDeviceClass = %d)\n", + dev->descriptor.bDeviceClass); + return 0; + } + if (dev->descriptor.bcdUSB != 0x110) + { + if (verbose > 2) + printf (" this is not a rts8801/rts8891 (bcdUSB = 0x%x)\n", + dev->descriptor.bcdUSB); + return 0; + } + if (dev->descriptor.bDeviceSubClass != 0) + { + if (verbose > 2) + printf (" this is not a rts8801/rts8891 (bDeviceSubClass = 0x%x)\n", + dev->descriptor.bDeviceSubClass); + return 0; + } + if (dev->descriptor.bDeviceProtocol != 0) + { + if (verbose > 2) + printf (" this is not a rts8801/rts8891 (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 rts8801/rts8891 (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 rts8801/rts8891 (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 rts8801/rts8891 (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 rts8801/rts8891 (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 "rts8801/rts8891?"; + + memset (req, 0, 4); + req[0] = 0x80; /* get registers 0x00-0xF2 */ + req[1] = 0x00; + req[2] = 0x00; + req[3] = 0xf3; + + 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; + } + + /* test CCD and link registers */ + if (res[0xb0] != 0x80 || ((res[0] & 0x0f)!=0x05)) + { + if (verbose > 2) + printf (" Unexpected result from register reading (0x%0x/0x%0x)\n", + res[0xb0], res[2]); + finish_interface (handle); + return 0; + } + finish_interface (handle); + return "rts8801/rts8891"; +} /* end of rts8801/rts8891 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 RTS8822 chipset*/ +static char * +check_rts8822 (struct usb_device *dev) +{ + char data[2]; + usb_dev_handle *handle; + int result; + + if (verbose > 2) + printf (" checking for RTS8822 ...\n"); + + /* Check device descriptor */ + if (dev->descriptor.bDeviceClass != 0) + { + if (verbose > 2) + printf (" this is not a RTS8822 (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 RTS8822 (bcdUSB = 0x%x)\n", + dev->descriptor.bcdUSB); + return 0; + } + if (dev->descriptor.bDeviceSubClass != 0) + { + if (verbose > 2) + printf (" this is not a RTS8822 (bDeviceSubClass = 0x%x)\n", + dev->descriptor.bDeviceSubClass); + return 0; + } + if (dev->descriptor.bDeviceProtocol != 0) + { + if (verbose > 2) + printf (" this is not a RTS8822 (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 RTS8822 (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 RTS8822 (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 RTS8822 (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 RTS8822 (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 "RTS8822?"; + + 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] == 0)&&(data[1] == 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 "RTS8822"; +} /* end of RTS8822 detection */ + +/* Check for Silitek chipset found in HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 scanners */ +static char * +check_hp5590 (struct usb_device *dev) +{ + usb_dev_handle *handle; + int result; + uint8_t status; + struct usb_ctrl_setup ctrl; + uint8_t data[0x32]; + uint8_t ack; + uint8_t *ptr; + int next_packet_size; + unsigned int len; +#define HP5590_NAMES "HP4500C/4570C/5500C/5550C/5590/7650" + + if (verbose > 2) + printf (" checking for " HP5590_NAMES " chipset ...\n"); + + /* Check device descriptor */ + if (dev->descriptor.bDeviceClass != 0xff) + { + if (verbose > 2) + printf (" this is not a " HP5590_NAMES " chipset (bDeviceClass = %d)\n", + dev->descriptor.bDeviceClass); + return 0; + } + if (dev->descriptor.bcdUSB != 0x200) + { + if (verbose > 2) + printf (" this is not a " HP5590_NAMES " chipset (bcdUSB = 0x%x)\n", + dev->descriptor.bcdUSB); + return 0; + } + if (dev->descriptor.bDeviceSubClass != 0xff) + { + if (verbose > 2) + printf (" this is not a " HP5590_NAMES " chipset (bDeviceSubClass = 0x%x)\n", + dev->descriptor.bDeviceSubClass); + return 0; + } + if (dev->descriptor.bDeviceProtocol != 0xff) + { + if (verbose > 2) + printf (" this is not a " HP5590_NAMES " 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 " HP5590_NAMES " 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 " HP5590_NAMES " 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 " HP5590_NAMES " 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 " HP5590_NAMES " 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 HP5590_NAMES; +} + +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_rts8822 (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 (!chip_name) + chip_name = check_rts88x1 (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 */ + +#ifdef HAVE_LIBUSB_1_0 + +#include <libusb.h> + +#include "../include/sane/sane.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "../include/_stdint.h" + +#define TIMEOUT 1000 + + +/** @brief detect used chip + * + * Try to detect the chip used by a device that looks like a scanner by + * trying some basic operation like reading/writing registers. + * @param dev libusb_device to probe + * @param verbosity level of messages verbosity + * @param from_file SANE_True if data read from file + * @return a string containing the name of the detected scanner chip + */ +char *check_usb_chip (int verbosity, + struct libusb_device_descriptor desc, + libusb_device_handle * hdl, + struct libusb_config_descriptor *config0); + +static int verbose = 0; + +static int +genesys_write_reg (libusb_device_handle * handle, unsigned char reg, + unsigned char val) +{ + int result; + unsigned char data[2]; + + data[0] = reg; + data[1] = val; + + result = libusb_control_transfer (handle, + 0x40, + 0x04, 0x83, 0x00, data, 0x02, TIMEOUT); + if (result < 0) + return 0; + return 1; +} + +static int +genesys_read_reg (libusb_device_handle * handle, unsigned char reg, + unsigned char *val) +{ + int result; + + result = libusb_control_transfer (handle, + 0x40, + 0x0c, 0x83, 0x00, ®, 0x01, TIMEOUT); + if (result < 0) + return 0; + + result = libusb_control_transfer (handle, + 0xc0, + 0x0c, 0x84, 0x00, val, 0x01, TIMEOUT); + if (result < 0) + return 0; + + return 1; +} + +/** @brief check for genesys GL646 chips + * + * @param dev libusb device + * @param hdl libusb opened handle + * @param config0 configuration 0 from get config _descriptor + * @return a string with ASIC name, or NULL if not recognized + */ +static char * +check_gl646 (libusb_device_handle * handle, + struct libusb_device_descriptor desc, + struct libusb_config_descriptor *config0) +{ + unsigned char val; + int result; + + if (desc.bcdUSB != 0x110) + { + if (verbose > 2) + printf (" this is not a GL646 (bcdUSB = 0x%x)\n", desc.bcdUSB); + return 0; + } + if (desc.bDeviceSubClass != 0x00) + { + if (verbose > 2) + printf (" this is not a GL646 (bDeviceSubClass = 0x%x)\n", + desc.bDeviceSubClass); + return 0; + } + if (desc.bDeviceProtocol != 0) + { + if (verbose > 2) + printf (" this is not a GL646 (bDeviceProtocol = 0x%x)\n", + desc.bDeviceProtocol); + return 0; + } + + /* Check endpoints */ + if (config0->interface[0].altsetting[0].bNumEndpoints != 3) + { + if (verbose > 2) + printf (" this is not a GL646 (bNumEndpoints = %d)\n", + config0->interface[0].altsetting[0].bNumEndpoints); + return 0; + } + + if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != + 0x81) + || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != + 0x02) + || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != + 0x40) + || (config0->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", + config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[0].bmAttributes, + config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[0].bInterval); + return 0; + } + + if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != + 0x02) + || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != + 0x02) + || (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != + 0x40) + || (config0->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", + config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[1].bmAttributes, + config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[1].bInterval); + return 0; + } + + if ((config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress != + 0x83) + || (config0->interface[0].altsetting[0].endpoint[2].bmAttributes != + 0x03) + || (config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize != + 0x1) + || (config0->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", + config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[2].bmAttributes, + config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[2].bInterval); + return 0; + } + + result = genesys_write_reg (handle, 0x38, 0x15); + if (!result) + { + if (verbose > 2) + printf (" this is not a GL646 (writing register failed)\n"); + return 0; + } + + result = genesys_read_reg (handle, 0x4e, &val); + if (!result) + { + if (verbose > 2) + printf (" this is not a GL646 (reading register failed)\n"); + return 0; + } + + if (val != 0x15) + { + if (verbose > 2) + printf (" this is not a GL646 (reg 0x4e != reg 0x38)\n"); + return 0; + } + + return "GL646"; +} + +/** @brief check for gt6801 chip + * + * @param dev libusb device + * @param hdl libusb opened handle + * @param config0 configuration 0 from get config _descriptor + * @return a string with ASIC name, or NULL if not recognized + */ +static char * +check_gt6801 (libusb_device_handle * handle, + struct libusb_device_descriptor desc, + struct libusb_config_descriptor *config0) +{ + unsigned char req[64]; + int result; + + if (verbose > 2) + printf (" checking for GT-6801 ...\n"); + + /* Check device descriptor */ + if (desc.bDeviceClass != LIBUSB_CLASS_VENDOR_SPEC) + { + if (verbose > 2) + printf (" this is not a GT-6801 (bDeviceClass = %d)\n", + desc.bDeviceClass); + return 0; + } + if (desc.bcdUSB != 0x110) + { + if (verbose > 2) + printf (" this is not a GT-6801 (bcdUSB = 0x%x)\n", desc.bcdUSB); + return 0; + } + if (desc.bDeviceSubClass != 0xff) + { + if (verbose > 2) + printf (" this is not a GT-6801 (bDeviceSubClass = 0x%x)\n", + desc.bDeviceSubClass); + return 0; + } + if (desc.bDeviceProtocol != 0xff) + { + if (verbose > 2) + printf (" this is not a GT-6801 (bDeviceProtocol = 0x%x)\n", + desc.bDeviceProtocol); + return 0; + } + + /* Check endpoints */ + if (config0->interface[0].altsetting[0].bNumEndpoints != 1) + { + if (verbose > 2) + printf (" this is not a GT-6801 (bNumEndpoints = %d)\n", + config0->interface[0].altsetting[0].bNumEndpoints); + return 0; + } + if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) + || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x02) + || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x40) + || (config0->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", + config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[0].bmAttributes, + config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[0].bInterval); + return 0; + } + + /* Now we send a control message */ + + memset (req, 0, 64); + req[0] = 0x2e; /* get identification information */ + req[1] = 0x01; + + result = libusb_control_transfer (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)); + return NULL; + } + result = libusb_control_transfer (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)); + return NULL; + } + 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]); + return NULL; + } + return "GT-6801"; +} + +/** @brief check for gt6816 chip + * + * @param dev libusb device + * @param hdl libusb opened handle + * @param config0 configuration 0 from get config _descriptor + * @return a string with ASIC name, or NULL if not recognized + */ +static char * +check_gt6816 (libusb_device_handle * handle, + struct libusb_device_descriptor desc, + struct libusb_config_descriptor *config0) +{ + unsigned char req[64]; + int result,i; + + if (verbose > 2) + printf (" checking for GT-6816 ...\n"); + + /* Check device descriptor */ + if ((desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) + || (config0->interface[0].altsetting[0].bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)) + { + if (verbose > 2) + printf + (" this is not a GT-6816 (bDeviceClass = %d, bInterfaceClass = %d)\n", + desc.bDeviceClass, + config0->interface[0].altsetting[0].bInterfaceClass); + return 0; + } + if (desc.bcdUSB != 0x110) + { + if (verbose > 2) + printf (" this is not a GT-6816 (bcdUSB = 0x%x)\n", desc.bcdUSB); + return 0; + } + if (desc.bDeviceSubClass != 0x00) + { + if (verbose > 2) + printf (" this is not a GT-6816 (bDeviceSubClass = 0x%x)\n", + desc.bDeviceSubClass); + return 0; + } + if (desc.bDeviceProtocol != 0x00) + { + if (verbose > 2) + printf (" this is not a GT-6816 (bDeviceProtocol = 0x%x)\n", + desc.bDeviceProtocol); + return 0; + } + + if (config0->bNumInterfaces != 0x01) + { + if (verbose > 2) + printf (" this is not a GT-6816 (bNumInterfaces = 0x%x)\n", + config0->bNumInterfaces); + return 0; + } + + /* Check endpoints */ + if (config0->interface[0].altsetting[0].bNumEndpoints != 2) + { + if (verbose > 2) + printf (" this is not a GT-6816 (bNumEndpoints = %d)\n", + config0->interface[0].altsetting[0].bNumEndpoints); + return 0; + } + if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) + || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x02) + || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x40) + || (config0->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", + config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[0].bmAttributes, + config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[0].bInterval); + return 0; + } + if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != 0x02) + || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != 0x02) + || (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x40) + || (config0->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", + config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[1].bmAttributes, + config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[1].bInterval); + return 0; + } + + /* Now we send a control message */ + + memset (req, 0, 64); + for (i = 0; i < 8; i++) + { + req[8 * i + 0] = 0x73; /* check firmware */ + req[8 * i + 1] = 0x01; + } + + result = libusb_control_transfer (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)); + return NULL; + } + result = libusb_control_transfer (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 = libusb_control_transfer (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)); + return NULL; + } + } + if (req[0] != 0) + { + if (verbose > 2) + printf (" Unexpected result from control message (%0x/%0x)\n", + req[0], req[1]); + return NULL; + } + return "GT-6816"; +} + +/** @brief check for known genesys chip + * + * Try to check if the scanner use a known genesys ASIC. + * The various incarnations could be distinguished by the + * bcdDevice entry: + * 0x701 --> GL124 + * 0x700 --> ? + * 0x605 --> GL845 + * 0x603 --> GL847 + * 0x601 --> GL846 + * 0x500 --> GL843 + * 0x300 --> GL842 (perhaps only >= 0x303 ?) + * 0x200 --> GL841 + * + * @param dev libusb device + * @param hdl libusb opened handle + * @param config0 configuration 0 from get config _descriptor + * @return a string with ASIC name, or NULL if not recognized + */ +static char * +check_genesys (libusb_device_handle * handle, + struct libusb_device_descriptor desc, + struct libusb_config_descriptor *config0) +{ + unsigned char val; + int result; + + if (verbose > 2) + printf (" checking for GLxxx ...\n"); + + /* Check GL646 device descriptor */ + if ((desc.bDeviceClass == LIBUSB_CLASS_PER_INTERFACE) + && (config0->interface[0].altsetting[0].bInterfaceClass == 0x10)) + { + return check_gl646 (handle, desc, config0); + } + if (verbose > 2) + { + printf + (" this is not a GL646 (bDeviceClass = %d, bInterfaceClass = %d)\n", + desc.bDeviceClass, + config0->interface[0].altsetting[0].bInterfaceClass); + } + + /* Check device desc */ + if ((desc.bDeviceClass != LIBUSB_CLASS_VENDOR_SPEC) + || (config0->interface[0].altsetting[0].bInterfaceClass != + LIBUSB_CLASS_VENDOR_SPEC)) + { + if (verbose > 2) + printf + (" this is not a GLxxx (bDeviceClass = %d, bInterfaceClass = %d)\n", + desc.bDeviceClass, + config0->interface[0].altsetting[0].bInterfaceClass); + return NULL; + } + + if (desc.bDeviceSubClass != 0xff) + { + if (verbose > 2) + printf (" this is not a GLxxx (bDeviceSubClass = 0x%x)\n", + desc.bDeviceSubClass); + return NULL; + } + if (desc.bDeviceProtocol != 0xff) + { + if (verbose > 2) + printf (" this is not a GLxxx (bDeviceProtocol = 0x%x)\n", + desc.bDeviceProtocol); + return NULL; + } + + /* Check endpoints */ + if (config0->interface[0].altsetting[0].bNumEndpoints != 3) + { + if (verbose > 2) + printf (" this is not a GLxxx (bNumEndpoints = %d)\n", + config0->interface[0].altsetting[0].bNumEndpoints); + return NULL; + } + + if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != + 0x81) + || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != + 0x02) + || + ((config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != + 0x40) + && (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != + 0x200)) + || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) + { + if (verbose > 2) + printf + (" this is not a GLxxx (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " + "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", + config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[0].bmAttributes, + config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[0].bInterval); + return NULL; + } + + if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != + 0x02) + || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != + 0x02) + || + ((config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != + 0x40) + && (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != + 0x200)) + || (config0->interface[0].altsetting[0].endpoint[1].bInterval != 0)) + { + if (verbose > 2) + printf + (" this is not a GLxxx (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " + "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", + config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[1].bmAttributes, + config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[1].bInterval); + return NULL; + } + + if ((config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress != + 0x83) + || (config0->interface[0].altsetting[0].endpoint[2].bmAttributes != + 0x03) + || (config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize != + 0x1) + || ((config0->interface[0].altsetting[0].endpoint[2].bInterval != 8) + && (config0->interface[0].altsetting[0].endpoint[2].bInterval != + 16))) + { + if (verbose > 2) + printf + (" this is not a GLxxx (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " + "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", + config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress, + config0->interface[0].altsetting[0].endpoint[2].bmAttributes, + config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize, + config0->interface[0].altsetting[0].endpoint[2].bInterval); + return NULL; + } + + /* write then read a register using common read/write control message */ + result = genesys_write_reg (handle, 0x38, 0x15); + if (!result) + { + if (verbose > 2) + printf (" this is not a GLxxx (writing register failed)\n"); + return NULL; + } + + result = genesys_read_reg (handle, 0x38, &val); + if (!result) + { + if (verbose > 2) + printf (" this is not a GLxxx (reading register failed)\n"); + return NULL; + } + + if (val != 0x15) + { + if (verbose > 2) + printf (" this is not a GLxxx (reg 0x38 != 0x15)\n"); + return NULL; + } + + /* decide revision number based on bcdUsb heuristics */ + if (desc.bcdDevice == 0x702) + return "GL128"; + if (desc.bcdDevice == 0x701) + return "GL124"; + if (desc.bcdDevice >= 0x700) + return "GL848+"; + if (desc.bcdDevice >= 0x605) + return "GL845"; + if (desc.bcdDevice >= 0x603) + return "GL847"; + if (desc.bcdDevice >= 0x600) + return "GL846"; + if (desc.bcdDevice >= 0x500) + return "GL843"; + if (desc.bcdDevice >= 0x300) + return "GL842"; + if (desc.bcdDevice > 0x101) + return "GL841"; + return "GL646_HP"; +} + +char * +check_usb_chip (int verbosity, + struct libusb_device_descriptor desc, + libusb_device_handle * hdl, + struct libusb_config_descriptor *config0) +{ + char *chip_name = NULL; + int ret; + + verbose = verbosity; + + if (verbose > 2) + printf ("\n<trying to find out which USB chip is used>\n"); + + /* set config if needed */ + if (desc.bNumConfigurations > 1) + { + ret = libusb_set_configuration (hdl, config0->bConfigurationValue); + if (ret < 0) + { + if (verbose > 2) + printf ("couldnt set device to configuration %d\n", + config0->bConfigurationValue); + return NULL; + } + } + + /* claim the interface (only interface 0 is currently handled */ + ret = libusb_claim_interface (hdl, 0); + if (ret < 0) + { + if (verbose > 2) + printf ("could not claim USB device interface\n"); + return NULL; + } + + /* now USB is opened and set up, actual chip detection */ + + if (!chip_name) + chip_name = check_gt6801 (hdl, desc, config0); + + if (!chip_name) + chip_name = check_gt6816 (hdl, desc, config0); + + if (!chip_name) + chip_name = check_genesys (hdl, desc, config0); + + 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); + } + + /* close USB device */ + libusb_release_interface (hdl, 0); + return chip_name; +} +#endif /* HAVE_LIBUSB_1_0 */ |