Blame src/parse.c

Packit Service aee942
/*
Packit Service aee942
    parse.c: parse CCID structure
Packit Service aee942
    Copyright (C) 2003-2010   Ludovic Rousseau
Packit Service aee942
Packit Service aee942
    This program is free software; you can redistribute it and/or modify
Packit Service aee942
    it under the terms of the GNU General Public License as published by
Packit Service aee942
    the Free Software Foundation; either version 2 of the License, or
Packit Service aee942
    (at your option) any later version.
Packit Service aee942
Packit Service aee942
    This program is distributed in the hope that it will be useful,
Packit Service aee942
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service aee942
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service aee942
    GNU General Public License for more details.
Packit Service aee942
Packit Service aee942
	You should have received a copy of the GNU General Public License along
Packit Service aee942
	with this program; if not, write to the Free Software Foundation, Inc., 51
Packit Service aee942
	Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service aee942
*/
Packit Service aee942
Packit Service aee942
#include <stdio.h>
Packit Service aee942
#include <string.h>
Packit Service aee942
# ifdef S_SPLINT_S
Packit Service aee942
# include <sys/types.h>
Packit Service aee942
# endif
Packit Service aee942
#include <errno.h>
Packit Service aee942
#include <unistd.h>
Packit Service aee942
Packit Service aee942
#include "defs.h"
Packit Service aee942
#include "ccid.h"
Packit Service aee942
Packit Service aee942
/* define DISPLAY_EXTRA_VALUES to display the extra (invalid) values
Packit Service aee942
 * returned by bNumClockSupported and bNumDataRatesSupported */
Packit Service aee942
#undef DISPLAY_EXTRA_VALUES
Packit Service aee942
Packit Service aee942
#ifndef TRUE
Packit Service aee942
#define TRUE 1
Packit Service aee942
#define FALSE 0
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
#define BLUE "\33[34m"
Packit Service aee942
#define RED "\33[31m"
Packit Service aee942
#define BRIGHT_RED "\33[01;31m"
Packit Service aee942
#define GREEN "\33[32m"
Packit Service aee942
#define MAGENTA "\33[35m"
Packit Service aee942
#define NORMAL "\33[0m"
Packit Service aee942
Packit Service aee942
/* global variables used in ccid_usb.c but defined in ifdhandler.c */
Packit Service aee942
int LogLevel = 1+2+4+8; /* full debug */
Packit Service aee942
int DriverOptions = 0;
Packit Service aee942
Packit Service aee942
static int ccid_parse_interface_descriptor(libusb_device_handle *handle,
Packit Service aee942
	struct libusb_device_descriptor desc,
Packit Service aee942
	struct libusb_config_descriptor *config_desc,
Packit Service aee942
	int num,
Packit Service aee942
	const struct libusb_interface *usb_interface);
Packit Service aee942
Packit Service aee942
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					main
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
int main(int argc, char *argv[])
Packit Service aee942
{
Packit Service aee942
	libusb_device **devs, *dev;
Packit Service aee942
	int nb = 0, r, i;
Packit Service aee942
	unsigned char buffer[256];
Packit Service aee942
	char class_ff = FALSE;
Packit Service aee942
	ssize_t cnt;
Packit Service aee942
Packit Service aee942
	if ((argc > 1) && (0 == strcmp(argv[1], "-p")))
Packit Service aee942
		class_ff = TRUE;
Packit Service aee942
Packit Service aee942
	r = libusb_init(NULL);
Packit Service aee942
	if (r < 0)
Packit Service aee942
	{
Packit Service aee942
		(void)printf("libusb_init() failed\n");
Packit Service aee942
        return r;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	cnt = libusb_get_device_list(NULL, &devs);
Packit Service aee942
    if (cnt < 0)
Packit Service aee942
	{
Packit Service aee942
		(void)printf("libusb_get_device_list() failed\n");
Packit Service aee942
        return (int)cnt;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/* for every device */
Packit Service aee942
	i = 0;
Packit Service aee942
	while ((dev = devs[i++]) != NULL)
Packit Service aee942
	{
Packit Service aee942
		struct libusb_device_descriptor desc;
Packit Service aee942
		struct libusb_config_descriptor *config_desc;
Packit Service aee942
		struct libusb_device_handle *handle;
Packit Service aee942
		const struct libusb_interface *usb_interface = NULL;
Packit Service aee942
#ifndef __APPLE__
Packit Service aee942
		int interface;
Packit Service aee942
#endif
Packit Service aee942
		int num = 0;
Packit Service aee942
Packit Service aee942
		r = libusb_open(dev, &handle);
Packit Service aee942
		if (r < 0)
Packit Service aee942
		{
Packit Service aee942
			(void)fprintf(stderr, "Can't libusb_open(): %s\n", strerror(errno));
Packit Service aee942
			if (getuid())
Packit Service aee942
			{
Packit Service aee942
				(void)fprintf(stderr,
Packit Service aee942
					BRIGHT_RED "Please, restart the command as root\n" NORMAL);
Packit Service aee942
				return 1;
Packit Service aee942
			}
Packit Service aee942
			continue;
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		r = libusb_get_device_descriptor(dev, &desc);
Packit Service aee942
        if (r < 0)
Packit Service aee942
		{
Packit Service aee942
            (void)fprintf(stderr,
Packit Service aee942
				BRIGHT_RED "failed to get device descriptor" NORMAL);
Packit Service aee942
            return 1;
Packit Service aee942
        }
Packit Service aee942
Packit Service aee942
		(void)fprintf(stderr,
Packit Service aee942
			"Parsing USB bus/device: %04X:%04X (bus %d, device %d)\n",
Packit Service aee942
			desc.idVendor, desc.idProduct,
Packit Service aee942
            libusb_get_bus_number(dev), libusb_get_device_address(dev));
Packit Service aee942
Packit Service aee942
		(void)fprintf(stderr, " idVendor:  0x%04X", desc.idVendor);
Packit Service aee942
		r = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer,
Packit Service aee942
			buffer, sizeof(buffer));
Packit Service aee942
		if (r < 0)
Packit Service aee942
		{
Packit Service aee942
			(void)fprintf(stderr, "  Can't get iManufacturer string\n");
Packit Service aee942
			if (getuid())
Packit Service aee942
			{
Packit Service aee942
				(void)fprintf(stderr,
Packit Service aee942
					BRIGHT_RED "Please, restart the command as root\n" NORMAL);
Packit Service aee942
				return 1;
Packit Service aee942
			}
Packit Service aee942
		}
Packit Service aee942
		else
Packit Service aee942
			(void)fprintf(stderr,
Packit Service aee942
				"  iManufacturer: " BLUE "%s\n" NORMAL, buffer);
Packit Service aee942
Packit Service aee942
		(void)fprintf(stderr, " idProduct: 0x%04X", desc.idProduct);
Packit Service aee942
		r = libusb_get_string_descriptor_ascii(handle, desc.iProduct,
Packit Service aee942
			buffer, sizeof(buffer));
Packit Service aee942
		if (r < 0)
Packit Service aee942
			(void)fprintf(stderr, "  Can't get iProduct string\n");
Packit Service aee942
		else
Packit Service aee942
			(void)fprintf(stderr, "  iProduct: " BLUE "%s\n" NORMAL, buffer);
Packit Service aee942
Packit Service aee942
again:
Packit Service aee942
		/* check if the device has bInterfaceClass == 11 */
Packit Service aee942
		r = libusb_get_active_config_descriptor(dev, &config_desc);
Packit Service aee942
		if (r < 0)
Packit Service aee942
		{
Packit Service aee942
			(void)fprintf(stderr, "  Can't get config descriptor: %d\n", r);
Packit Service aee942
			(void)libusb_close(handle);
Packit Service aee942
			continue;
Packit Service aee942
		}
Packit Service aee942
Packit Service aee942
		usb_interface = get_ccid_usb_interface(config_desc, &num);
Packit Service aee942
		if (NULL == usb_interface)
Packit Service aee942
		{
Packit Service aee942
			(void)libusb_close(handle);
Packit Service aee942
			/* only if we found no CCID interface */
Packit Service aee942
			if (0 == num)
Packit Service aee942
				(void)fprintf(stderr, RED "  NOT a CCID/ICCD device\n" NORMAL);
Packit Service aee942
			continue;
Packit Service aee942
		}
Packit Service aee942
		if (!class_ff && (0xFF == usb_interface->altsetting->bInterfaceClass))
Packit Service aee942
		{
Packit Service aee942
			(void)libusb_close(handle);
Packit Service aee942
			(void)fprintf(stderr, MAGENTA "  Found a possibly CCID/ICCD device (bInterfaceClass = 0xFF). Use %s -p\n" NORMAL, argv[0]);
Packit Service aee942
			continue;
Packit Service aee942
		}
Packit Service aee942
		(void)fprintf(stderr,
Packit Service aee942
			GREEN "  Found a CCID/ICCD device at interface %d\n" NORMAL, num);
Packit Service aee942
Packit Service aee942
		/* now we found a free reader and we try to use it */
Packit Service aee942
#if 0
Packit Service aee942
		if (NULL == dev->config)
Packit Service aee942
		{
Packit Service aee942
			(void)libusb_close(handle);
Packit Service aee942
			(void)fprintf(stderr, "No dev->config found for %s/%s\n",
Packit Service aee942
					bus->dirname, dev->filename);
Packit Service aee942
			continue;
Packit Service aee942
		}
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
#ifndef __APPLE__
Packit Service aee942
		interface = usb_interface->altsetting->bInterfaceNumber;
Packit Service aee942
		r = libusb_claim_interface(handle, interface);
Packit Service aee942
		if (r < 0)
Packit Service aee942
		{
Packit Service aee942
			(void)fprintf(stderr,
Packit Service aee942
				"Can't claim interface (bus %d, device %d): %s\n",
Packit Service aee942
				libusb_get_bus_number(dev), libusb_get_device_address(dev),
Packit Service aee942
				strerror(errno));
Packit Service aee942
			(void)libusb_close(handle);
Packit Service aee942
Packit Service aee942
			if (EBUSY == errno)
Packit Service aee942
			{
Packit Service aee942
				(void)fprintf(stderr,
Packit Service aee942
					BRIGHT_RED " Please, stop pcscd and retry\n\n" NORMAL);
Packit Service aee942
Packit Service aee942
				if (class_ff)
Packit Service aee942
					/* maybe the device with Class = 0xFF is NOT a CCID
Packit Service aee942
					 * reader */
Packit Service aee942
					continue;
Packit Service aee942
				else
Packit Service aee942
					return TRUE;
Packit Service aee942
			}
Packit Service aee942
			continue;
Packit Service aee942
		}
Packit Service aee942
#endif
Packit Service aee942
Packit Service aee942
		(void)ccid_parse_interface_descriptor(handle, desc, config_desc, num,
Packit Service aee942
			usb_interface);
Packit Service aee942
		nb++;
Packit Service aee942
Packit Service aee942
#ifndef __APPLE__
Packit Service aee942
		(void)libusb_release_interface(handle, interface);
Packit Service aee942
#endif
Packit Service aee942
		/* check for another CCID interface on the same device */
Packit Service aee942
		num++;
Packit Service aee942
		goto again;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	if ((0 == nb) && (0 != geteuid()))
Packit Service aee942
		(void)fprintf(stderr,
Packit Service aee942
			"Can't find any CCID device.\nMaybe you must run parse as root?\n");
Packit Service aee942
Packit Service aee942
	libusb_exit(NULL);
Packit Service aee942
Packit Service aee942
	return 0;
Packit Service aee942
} /* main */
Packit Service aee942
Packit Service aee942
Packit Service aee942
/*****************************************************************************
Packit Service aee942
 *
Packit Service aee942
 *					Parse a CCID USB Descriptor
Packit Service aee942
 *
Packit Service aee942
 ****************************************************************************/
Packit Service aee942
static int ccid_parse_interface_descriptor(libusb_device_handle *handle,
Packit Service aee942
	struct libusb_device_descriptor desc,
Packit Service aee942
	struct libusb_config_descriptor *config_desc,
Packit Service aee942
	int num,
Packit Service aee942
	const struct libusb_interface *usb_interface)
Packit Service aee942
{
Packit Service aee942
	const struct libusb_interface_descriptor *usb_interface_descriptor;
Packit Service aee942
	const unsigned char *device_descriptor;
Packit Service aee942
	unsigned char buffer[256*sizeof(int)];  /* maximum is 256 records */
Packit Service aee942
	int r;
Packit Service aee942
Packit Service aee942
	/*
Packit Service aee942
	 * Vendor/model name
Packit Service aee942
	 */
Packit Service aee942
	(void)printf(" idVendor: 0x%04X\n", desc.idVendor);
Packit Service aee942
	r = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer,
Packit Service aee942
		buffer, sizeof(buffer));
Packit Service aee942
	if (r < 0)
Packit Service aee942
	{
Packit Service aee942
		(void)printf("  Can't get iManufacturer string\n");
Packit Service aee942
		if (getuid())
Packit Service aee942
		{
Packit Service aee942
			(void)fprintf(stderr,
Packit Service aee942
				BRIGHT_RED "Please, restart the command as root\n\n" NORMAL);
Packit Service aee942
			return TRUE;
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
	else
Packit Service aee942
		(void)printf("  iManufacturer: %s\n", buffer);
Packit Service aee942
Packit Service aee942
	(void)printf(" idProduct: 0x%04X\n", desc.idProduct);
Packit Service aee942
	r =  libusb_get_string_descriptor_ascii(handle, desc.iProduct,
Packit Service aee942
		buffer, sizeof(buffer));
Packit Service aee942
	if (r < 0)
Packit Service aee942
		(void)printf("  Can't get iProduct string\n");
Packit Service aee942
	else
Packit Service aee942
		(void)printf("  iProduct: %s\n", buffer);
Packit Service aee942
Packit Service aee942
	(void)printf(" bcdDevice: %X.%02X (firmware release?)\n",
Packit Service aee942
		desc.bcdDevice >> 8, desc.bcdDevice & 0xFF);
Packit Service aee942
Packit Service aee942
	usb_interface_descriptor = get_ccid_usb_interface(config_desc, &num)->altsetting;
Packit Service aee942
Packit Service aee942
	(void)printf(" bLength: %d\n", usb_interface_descriptor->bLength);
Packit Service aee942
Packit Service aee942
	(void)printf(" bDescriptorType: %d\n", usb_interface_descriptor->bDescriptorType);
Packit Service aee942
Packit Service aee942
	(void)printf(" bInterfaceNumber: %d\n", usb_interface_descriptor->bInterfaceNumber);
Packit Service aee942
Packit Service aee942
	(void)printf(" bAlternateSetting: %d\n", usb_interface_descriptor->bAlternateSetting);
Packit Service aee942
Packit Service aee942
	(void)printf(" bNumEndpoints: %d\n", usb_interface_descriptor->bNumEndpoints);
Packit Service aee942
	switch (usb_interface_descriptor->bNumEndpoints)
Packit Service aee942
	{
Packit Service aee942
		case 0:
Packit Service aee942
			(void)printf("  Control only\n");
Packit Service aee942
			break;
Packit Service aee942
		case 1:
Packit Service aee942
			(void)printf("  Interrupt-IN\n");
Packit Service aee942
			break;
Packit Service aee942
		case 2:
Packit Service aee942
			(void)printf("  bulk-IN and bulk-OUT\n");
Packit Service aee942
			break;
Packit Service aee942
		case 3:
Packit Service aee942
			(void)printf("  bulk-IN, bulk-OUT and Interrupt-IN\n");
Packit Service aee942
			break;
Packit Service aee942
		default:
Packit Service aee942
			(void)printf("  UNKNOWN value\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	(void)printf(" bInterfaceClass: 0x%02X", usb_interface_descriptor->bInterfaceClass);
Packit Service aee942
	if (usb_interface_descriptor->bInterfaceClass == 0x0b)
Packit Service aee942
		(void)printf(" [Chip Card Interface Device Class (CCID)]\n");
Packit Service aee942
	else
Packit Service aee942
	{
Packit Service aee942
		(void)printf("\n  NOT A CCID DEVICE\n");
Packit Service aee942
		if (usb_interface_descriptor->bInterfaceClass != 0xFF)
Packit Service aee942
			return TRUE;
Packit Service aee942
		else
Packit Service aee942
			(void)printf("  Class is 0xFF (proprietary)\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	(void)printf(" bInterfaceSubClass: %d\n",
Packit Service aee942
		usb_interface_descriptor->bInterfaceSubClass);
Packit Service aee942
	if (usb_interface_descriptor->bInterfaceSubClass)
Packit Service aee942
		(void)printf("  UNSUPPORTED SubClass\n");
Packit Service aee942
Packit Service aee942
	(void)printf(" bInterfaceProtocol: %d\n",
Packit Service aee942
		usb_interface_descriptor->bInterfaceProtocol);
Packit Service aee942
	switch (usb_interface_descriptor->bInterfaceProtocol)
Packit Service aee942
	{
Packit Service aee942
		case 0:
Packit Service aee942
			(void)printf("  bulk transfer, optional interrupt-IN (CCID)\n");
Packit Service aee942
			break;
Packit Service aee942
		case 1:
Packit Service aee942
			(void)printf("  ICCD Version A, Control transfers, (no interrupt-IN)\n");
Packit Service aee942
			break;
Packit Service aee942
		case 2:
Packit Service aee942
			(void)printf("  ICCD Version B, Control transfers, (optional interrupt-IN)\n");
Packit Service aee942
			break;
Packit Service aee942
		default:
Packit Service aee942
			(void)printf("  UNSUPPORTED InterfaceProtocol\n");
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	r = libusb_get_string_descriptor_ascii(handle, usb_interface_descriptor->iInterface,
Packit Service aee942
		buffer, sizeof(buffer));
Packit Service aee942
	if (r < 0)
Packit Service aee942
		(void)printf(" Can't get iInterface string\n");
Packit Service aee942
	else
Packit Service aee942
		(void)printf(" iInterface: %s\n", buffer);
Packit Service aee942
Packit Service aee942
	device_descriptor = get_ccid_device_descriptor(usb_interface);
Packit Service aee942
	if (NULL == device_descriptor)
Packit Service aee942
	{
Packit Service aee942
		(void)printf("\n  NOT A CCID DEVICE\n");
Packit Service aee942
		return TRUE;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	/*
Packit Service aee942
	 * CCID Class Descriptor
Packit Service aee942
	 */
Packit Service aee942
	(void)printf(" CCID Class Descriptor\n");
Packit Service aee942
Packit Service aee942
	(void)printf("  bLength: 0x%02X\n", device_descriptor[0]);
Packit Service aee942
	if (device_descriptor[0] != 0x36)
Packit Service aee942
	{
Packit Service aee942
		(void)printf("   UNSUPPORTED bLength\n");
Packit Service aee942
		return TRUE;
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	(void)printf("  bDescriptorType: 0x%02X\n", device_descriptor[1]);
Packit Service aee942
	if (device_descriptor[1] != 0x21)
Packit Service aee942
	{
Packit Service aee942
		if (0xFF == device_descriptor[1])
Packit Service aee942
			(void)printf("   PROPRIETARY bDescriptorType\n");
Packit Service aee942
		else
Packit Service aee942
		{
Packit Service aee942
			(void)printf("   UNSUPPORTED bDescriptorType\n");
Packit Service aee942
			return TRUE;
Packit Service aee942
		}
Packit Service aee942
	}
Packit Service aee942
Packit Service aee942
	(void)printf("  bcdCCID: %X.%02X\n", device_descriptor[3], device_descriptor[2]);
Packit Service aee942
	(void)printf("  bMaxSlotIndex: 0x%02X\n", device_descriptor[4]);
Packit Service aee942
	(void)printf("  bVoltageSupport: 0x%02X\n", device_descriptor[5]);
Packit Service aee942
	if (device_descriptor[5] & 0x01)
Packit Service aee942
		(void)printf("   5.0V\n");
Packit Service aee942
	if (device_descriptor[5] & 0x02)
Packit Service aee942
		(void)printf("   3.0V\n");
Packit Service aee942
	if (device_descriptor[5] & 0x04)
Packit Service aee942
		(void)printf("   1.8V\n");
Packit Service aee942
Packit Service aee942
	(void)printf("  dwProtocols: 0x%02X%02X 0x%02X%02X\n", device_descriptor[9], device_descriptor[8],
Packit Service aee942
		device_descriptor[7], device_descriptor[6]);
Packit Service aee942
	if (device_descriptor[6] & 0x01)
Packit Service aee942
		(void)printf("   T=0\n");
Packit Service aee942
	if (device_descriptor[6] & 0x02)
Packit Service aee942
		(void)printf("   T=1\n");
Packit Service aee942
Packit Service aee942
	(void)printf("  dwDefaultClock: %.3f MHz\n", dw2i(device_descriptor, 10)/1000.0);
Packit Service aee942
	(void)printf("  dwMaximumClock: %.3f MHz\n", dw2i(device_descriptor, 14)/1000.0);
Packit Service aee942
	(void)printf("  bNumClockSupported: %d%s\n", device_descriptor[18],
Packit Service aee942
		device_descriptor[18] ? "" : " (will use whatever is returned)");
Packit Service aee942
	{
Packit Service aee942
		int n;
Packit Service aee942
Packit Service aee942
		/* See CCID 3.7.2 page 25 */
Packit Service aee942
		n = libusb_control_transfer(handle,
Packit Service aee942
			0xA1, /* request type */
Packit Service aee942
			0x02, /* GET CLOCK FREQUENCIES */
Packit Service aee942
			0x00, /* value */
Packit Service aee942
			usb_interface_descriptor->bInterfaceNumber, /* interface */
Packit Service aee942
			buffer,
Packit Service aee942
			sizeof(buffer),
Packit Service aee942
			2 * 1000);
Packit Service aee942
Packit Service aee942
		/* we got an error? */
Packit Service aee942
		if (n <= 0)
Packit Service aee942
		{
Packit Service aee942
			(void)(void)printf("   IFD does not support GET CLOCK FREQUENCIES request: %s\n", strerror(errno));
Packit Service aee942
			if (EBUSY == errno)
Packit Service aee942
			{
Packit Service aee942
				(void)fprintf(stderr,
Packit Service aee942
					BRIGHT_RED "   Please, stop pcscd and retry\n\n" NORMAL);
Packit Service aee942
				return TRUE;
Packit Service aee942
			}
Packit Service aee942
		}
Packit Service aee942
		else
Packit Service aee942
			if (n % 4)	/* not a multiple of 4 */
Packit Service aee942
				(void)printf("   wrong size for GET CLOCK FREQUENCIES: %d\n", n);
Packit Service aee942
			else
Packit Service aee942
			{
Packit Service aee942
				int i;
Packit Service aee942
Packit Service aee942
				/* we do not get the expected number of data rates */
Packit Service aee942
				if ((n != device_descriptor[18]*4) && device_descriptor[18])
Packit Service aee942
				{
Packit Service aee942
					(void)printf("   Got %d clock frequencies but was expecting %d\n",
Packit Service aee942
						n/4, device_descriptor[18]);
Packit Service aee942
Packit Service aee942
					/* we got more data than expected */
Packit Service aee942
#ifndef DISPLAY_EXTRA_VALUES
Packit Service aee942
					if (n > device_descriptor[18]*4)
Packit Service aee942
						n = device_descriptor[18]*4;
Packit Service aee942
#endif
Packit Service aee942
				}
Packit Service aee942
Packit Service aee942
				for (i=0; i
Packit Service aee942
					(void)printf("   Support %d kHz\n", dw2i(buffer, i));
Packit Service aee942
			}
Packit Service aee942
	}
Packit Service aee942
	(void)printf("  dwDataRate: %d bps\n", dw2i(device_descriptor, 19));
Packit Service aee942
	(void)printf("  dwMaxDataRate: %d bps\n", dw2i(device_descriptor, 23));
Packit Service aee942
	(void)printf("  bNumDataRatesSupported: %d%s\n", device_descriptor[27],
Packit Service aee942
		device_descriptor[27] ? "" : " (will use whatever is returned)");
Packit Service aee942
	{
Packit Service aee942
		int n;
Packit Service aee942
Packit Service aee942
		/* See CCID 3.7.3 page 25 */
Packit Service aee942
		n = libusb_control_transfer(handle,
Packit Service aee942
			0xA1, /* request type */
Packit Service aee942
			0x03, /* GET DATA RATES */
Packit Service aee942
			0x00, /* value */
Packit Service aee942
			usb_interface_descriptor->bInterfaceNumber, /* interface */
Packit Service aee942
			buffer,
Packit Service aee942
			sizeof(buffer),
Packit Service aee942
			2 * 1000);
Packit Service aee942
Packit Service aee942
		/* we got an error? */
Packit Service aee942
		if (n <= 0)
Packit Service aee942
			(void)printf("   IFD does not support GET_DATA_RATES request: %s\n",
Packit Service aee942
				strerror(errno));
Packit Service aee942
		else
Packit Service aee942
			if (n % 4)	/* not a multiple of 4 */
Packit Service aee942
				(void)printf("   wrong size for GET_DATA_RATES: %d\n", n);
Packit Service aee942
			else
Packit Service aee942
			{
Packit Service aee942
				int i;
Packit Service aee942
Packit Service aee942
				/* we do not get the expected number of data rates */
Packit Service aee942
				if ((n != device_descriptor[27]*4) && device_descriptor[27])
Packit Service aee942
				{
Packit Service aee942
					(void)printf("   Got %d data rates but was expecting %d\n", n/4,
Packit Service aee942
						device_descriptor[27]);
Packit Service aee942
Packit Service aee942
					/* we got more data than expected */
Packit Service aee942
#ifndef DISPLAY_EXTRA_VALUES
Packit Service aee942
					if (n > device_descriptor[27]*4)
Packit Service aee942
						n = device_descriptor[27]*4;
Packit Service aee942
#endif
Packit Service aee942
				}
Packit Service aee942
Packit Service aee942
				for (i=0; i
Packit Service aee942
					(void)printf("   Support %d bps\n", dw2i(buffer, i));
Packit Service aee942
			}
Packit Service aee942
	}
Packit Service aee942
	(void)printf("  dwMaxIFSD: %d\n", dw2i(device_descriptor, 28));
Packit Service aee942
	(void)printf("  dwSynchProtocols: 0x%08X\n", dw2i(device_descriptor, 32));
Packit Service aee942
	if (device_descriptor[32] & 0x01)
Packit Service aee942
			(void)printf("   2-wire protocol\n");
Packit Service aee942
	if (device_descriptor[32] & 0x02)
Packit Service aee942
			(void)printf("   3-wire protocol\n");
Packit Service aee942
	if (device_descriptor[32] & 0x04)
Packit Service aee942
			(void)printf("   I2C protocol\n");
Packit Service aee942
Packit Service aee942
	(void)printf("  dwMechanical: 0x%08X\n", dw2i(device_descriptor, 36));
Packit Service aee942
	if (device_descriptor[36] == 0)
Packit Service aee942
		(void)printf("   No special characteristics\n");
Packit Service aee942
	if (device_descriptor[36] & 0x01)
Packit Service aee942
		(void)printf("   Card accept mechanism\n");
Packit Service aee942
	if (device_descriptor[36] & 0x02)
Packit Service aee942
		(void)printf("   Card ejection mechanism\n");
Packit Service aee942
	if (device_descriptor[36] & 0x04)
Packit Service aee942
		(void)printf("   Card capture mechanism\n");
Packit Service aee942
	if (device_descriptor[36] & 0x08)
Packit Service aee942
		(void)printf("   Card lock/unlock mechanism\n");
Packit Service aee942
Packit Service aee942
	(void)printf("  dwFeatures: 0x%08X\n", dw2i(device_descriptor, 40));
Packit Service aee942
	if (dw2i(device_descriptor, 40) == 0)
Packit Service aee942
		(void)printf("   No special characteristics\n");
Packit Service aee942
	if (device_descriptor[40] & 0x02)
Packit Service aee942
		(void)printf("   ....02 Automatic parameter configuration based on ATR data\n");
Packit Service aee942
	if (device_descriptor[40] & 0x04)
Packit Service aee942
		(void)printf("   ....04 Automatic activation of ICC on inserting\n");
Packit Service aee942
	if (device_descriptor[40] & 0x08)
Packit Service aee942
		(void)printf("   ....08 Automatic ICC voltage selection\n");
Packit Service aee942
	if (device_descriptor[40] & 0x10)
Packit Service aee942
		(void)printf("   ....10 Automatic ICC clock frequency change according to parameters\n");
Packit Service aee942
	if (device_descriptor[40] & 0x20)
Packit Service aee942
		(void)printf("   ....20 Automatic baud rate change according to frequency and Fi, Di params\n");
Packit Service aee942
	if (device_descriptor[40] & 0x40)
Packit Service aee942
		(void)printf("   ....40 Automatic parameters negotiation made by the CCID\n");
Packit Service aee942
	if (device_descriptor[40] & 0x80)
Packit Service aee942
		(void)printf("   ....80 Automatic PPS made by the CCID\n");
Packit Service aee942
	if (device_descriptor[41] & 0x01)
Packit Service aee942
		(void)printf("   ..01.. CCID can set ICC in clock stop mode\n");
Packit Service aee942
	if (device_descriptor[41] & 0x02)
Packit Service aee942
		(void)printf("   ..02.. NAD value other than 00 accepted (T=1)\n");
Packit Service aee942
	if (device_descriptor[41] & 0x04)
Packit Service aee942
		(void)printf("   ..04.. Automatic IFSD exchange as first exchange (T=1)\n");
Packit Service aee942
	if (device_descriptor[41] & 0x08)
Packit Service aee942
		(void)printf("   ..08.. Unknown (ICCD?)\n");
Packit Service aee942
	switch (device_descriptor[42] & 0x07)
Packit Service aee942
	{
Packit Service aee942
		case 0x00:
Packit Service aee942
			(void)printf("   00.... Character level exchange\n");
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0x01:
Packit Service aee942
			(void)printf("   01.... TPDU level exchange\n");
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0x02:
Packit Service aee942
			(void)printf("   02.... Short APDU level exchange\n");
Packit Service aee942
			break;
Packit Service aee942
Packit Service aee942
		case 0x04:
Packit Service aee942
			(void)printf("   04.... Short and Extended APDU level exchange\n");
Packit Service aee942
			break;
Packit Service aee942
	}
Packit Service aee942
	if (device_descriptor[42] & 0x10)
Packit Service aee942
		(void)printf("   10.... USB Wake up signaling supported on card insertion and removal\n");
Packit Service aee942
Packit Service aee942
	(void)printf("  dwMaxCCIDMessageLength: %d bytes\n", dw2i(device_descriptor, 44));
Packit Service aee942
	(void)printf("  bClassGetResponse: 0x%02X\n", device_descriptor[48]);
Packit Service aee942
	if (0xFF == device_descriptor[48])
Packit Service aee942
		(void)printf("   echoes the APDU class\n");
Packit Service aee942
	(void)printf("  bClassEnvelope: 0x%02X\n", device_descriptor[49]);
Packit Service aee942
	if (0xFF == device_descriptor[49])
Packit Service aee942
		(void)printf("   echoes the APDU class\n");
Packit Service aee942
	(void)printf("  wLcdLayout: 0x%04X\n", (device_descriptor[51] << 8)+device_descriptor[50]);
Packit Service aee942
	if (device_descriptor[51])
Packit Service aee942
		(void)printf("   %2d lines\n", device_descriptor[51]);
Packit Service aee942
	if (device_descriptor[50])
Packit Service aee942
		(void)printf("   %2d characters per line\n", device_descriptor[50]);
Packit Service aee942
	(void)printf("  bPINSupport: 0x%02X\n", device_descriptor[52]);
Packit Service aee942
	if (device_descriptor[52] & 0x01)
Packit Service aee942
		(void)printf("   PIN Verification supported\n");
Packit Service aee942
	if (device_descriptor[52] & 0x02)
Packit Service aee942
		(void)printf("   PIN Modification supported\n");
Packit Service aee942
	(void)printf("  bMaxCCIDBusySlots: %d\n", device_descriptor[53]);
Packit Service aee942
Packit Service aee942
	return FALSE;
Packit Service aee942
} /* ccid_parse_interface_descriptor */
Packit Service aee942