示例#1
0
文件: ccid_usb.c 项目: baerwolf/CCID
/*****************************************************************************
 *
 *					ReadUSB
 *
 ****************************************************************************/
status_t ReadUSB(unsigned int reader_index, unsigned int * length,
	unsigned char *buffer)
{
	int rv;
	int actual_length;
	char debug_header[] = "<- 121234 ";
	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
	int duplicate_frame = 0;

read_again:
	(void)snprintf(debug_header, sizeof(debug_header), "<- %06X ",
		(int)reader_index);

	rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle,
		usbDevice[reader_index].bulk_in, buffer, *length,
		&actual_length, usbDevice[reader_index].ccid.readTimeout);

	if (rv < 0)
	{
		*length = 0;
		DEBUG_CRITICAL5("read failed (%d/%d): %d %s",
			usbDevice[reader_index].bus_number,
			usbDevice[reader_index].device_address, rv, libusb_error_name(rv));

		if (LIBUSB_ERROR_NO_DEVICE == rv)
			return STATUS_NO_SUCH_DEVICE;

		return STATUS_UNSUCCESSFUL;
	}

	*length = actual_length;

	DEBUG_XXD(debug_header, buffer, *length);

#define BSEQ_OFFSET 6
	if ((*length >= BSEQ_OFFSET)
		&& (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1))
	{
		duplicate_frame++;
		if (duplicate_frame > 10)
		{
			DEBUG_CRITICAL("Too many duplicate frame detected");
			return STATUS_UNSUCCESSFUL;
		}
		DEBUG_INFO1("Duplicate frame detected");
		goto read_again;
	}

	return STATUS_SUCCESS;
} /* ReadUSB */
示例#2
0
文件: ccid.c 项目: ZuyingWo/ccid
/*****************************************************************************
 *
 *					dump_gemalto_firmware_features
 *
 ****************************************************************************/
static void dump_gemalto_firmware_features(struct GEMALTO_FIRMWARE_FEATURES *gff)
{
	DEBUG_INFO2("Dumping Gemalto firmware features (%zd bytes):",
		sizeof(struct GEMALTO_FIRMWARE_FEATURES));

#define YESNO(x) (x) ? "yes" : "no"

	DEBUG_INFO2(" bLogicalLCDLineNumber: %d", gff->bLogicalLCDLineNumber);
	DEBUG_INFO2(" bLogicalLCDRowNumber: %d", gff->bLogicalLCDRowNumber);
	DEBUG_INFO2(" bLcdInfo: 0x%02X", gff->bLcdInfo);
	DEBUG_INFO2(" bEntryValidationCondition: 0x%02X",
		gff->bEntryValidationCondition);

	DEBUG_INFO1(" Reader supports PC/SCv2 features:");
	DEBUG_INFO2("  VerifyPinStart: %s", YESNO(gff->VerifyPinStart));
	DEBUG_INFO2("  VerifyPinFinish: %s", YESNO(gff->VerifyPinFinish));
	DEBUG_INFO2("  ModifyPinStart: %s", YESNO(gff->ModifyPinStart));
	DEBUG_INFO2("  ModifyPinFinish: %s", YESNO(gff->ModifyPinFinish));
	DEBUG_INFO2("  GetKeyPressed: %s", YESNO(gff->GetKeyPressed));
	DEBUG_INFO2("  VerifyPinDirect: %s", YESNO(gff->VerifyPinDirect));
	DEBUG_INFO2("  ModifyPinDirect: %s", YESNO(gff->ModifyPinDirect));
	DEBUG_INFO2("  Abort: %s", YESNO(gff->Abort));
	DEBUG_INFO2("  GetKey: %s", YESNO(gff->GetKey));
	DEBUG_INFO2("  WriteDisplay: %s", YESNO(gff->WriteDisplay));
	DEBUG_INFO2("  SetSpeMessage: %s", YESNO(gff->SetSpeMessage));
	DEBUG_INFO2("  bTimeOut2: %s", YESNO(gff->bTimeOut2));
	DEBUG_INFO2("  bPPDUSupportOverXferBlock: %s",
		YESNO(gff->bPPDUSupportOverXferBlock));
	DEBUG_INFO2("  bPPDUSupportOverEscape: %s",
		YESNO(gff->bPPDUSupportOverEscape));

	DEBUG_INFO2(" bListSupportedLanguages: %s",
		YESNO(gff->bListSupportedLanguages));
	DEBUG_INFO2(" bNumberMessageFix: %s", YESNO(gff->bNumberMessageFix));

	DEBUG_INFO2(" VersionNumber: 0x%02X", gff->VersionNumber);
	DEBUG_INFO2(" MinimumPINSize: %d", gff->MinimumPINSize);
	DEBUG_INFO2(" MaximumPINSize: %d", gff->MaximumPINSize);
	DEBUG_INFO2(" Firewall: %s", YESNO(gff->Firewall));
	if (gff->Firewall && gff->FirewalledCommand_SW1
		&& gff->FirewalledCommand_SW2)
	{
		DEBUG_INFO2("  FirewalledCommand_SW1: 0x%02X",
			gff->FirewalledCommand_SW1);
		DEBUG_INFO2("  FirewalledCommand_SW2: 0x%02X",
			gff->FirewalledCommand_SW2);
	}

} /* dump_gemalto_firmware_features */
示例#3
0
/*****************************************************************************
 *
 *					close_libusb_if_needed
 *
 ****************************************************************************/
static void close_libusb_if_needed(void)
{
	int i, to_exit = TRUE;

	/* if at least 1 reader is still in use we do not exit libusb */
	for (i=0; i<CCID_DRIVER_MAX_READERS; i++)
	{
		if (usbDevice[i].dev_handle != NULL)
			to_exit = FALSE;
	}

	if (to_exit)
	{
		DEBUG_INFO1("libusb_exit");
		libusb_exit(ctx);
		ctx = NULL;
	}
} /* close_libusb_if_needed */
示例#4
0
/*****************************************************************************
 *
 *					ccid_open_hack_pre
 *
 ****************************************************************************/
int ccid_open_hack_pre(unsigned int reader_index)
{
	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);

	switch (ccid_descriptor->readerID)
	{
		case MYSMARTPAD:
			ccid_descriptor->dwMaxIFSD = 254;
			break;

		case CL1356D:
			/* the firmware needs some time to initialize */
			(void)sleep(1);
			ccid_descriptor->readTimeout = 60*1000; /* 60 seconds */
			break;

		case GEMPCTWIN:
		case GEMPCKEY:
		case DELLSCRK:
			/* Only the chipset with firmware version 2.00 is "bogus"
			 * The reader may send packets of 0 bytes when the reader is
			 * connected to a USB 3 port */
			if (0x0200 == ccid_descriptor->IFD_bcdDevice)
			{
				ccid_descriptor->zlp = TRUE;
				DEBUG_INFO1("ZLP fixup");
			}
			break;

		case OZ776_7772:
			ccid_descriptor->dwMaxDataRate = 9600;
			break;

		case SCR331NTTCOM:
			ccid_descriptor->bInterfaceProtocol = 0;
			break;
	}

	/* CCID */
	if ((PROTOCOL_CCID == ccid_descriptor->bInterfaceProtocol)
		&& (3 == ccid_descriptor -> bNumEndpoints))
	{
#ifndef TWIN_SERIAL
		/* just wait for 100ms in case a notification is in the pipe */
		(void)InterruptRead(reader_index, 100);
#endif
	}

	/* ICCD type A */
	if (PROTOCOL_ICCD_A == ccid_descriptor->bInterfaceProtocol)
	{
		unsigned char tmp[MAX_ATR_SIZE];
		unsigned int n = sizeof(tmp);

		DEBUG_COMM("ICCD type A");
		(void)CmdPowerOff(reader_index);
		(void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
		(void)CmdPowerOff(reader_index);
	}

	/* ICCD type B */
	if (PROTOCOL_ICCD_B == ccid_descriptor->bInterfaceProtocol)
	{
		unsigned char tmp[MAX_ATR_SIZE];
		unsigned int n = sizeof(tmp);

		DEBUG_COMM("ICCD type B");
		if (CCID_CLASS_SHORT_APDU ==
			(ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK))
		{
			/* use the extended APDU comm alogorithm */
			ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
			ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
		}

		(void)CmdPowerOff(reader_index);
		(void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
		(void)CmdPowerOff(reader_index);
	}

	return 0;
} /* ccid_open_hack_pre */
示例#5
0
double delayImpl(DATA* data, int exprNumber, double exprValue, double time, double delayTime, double delayMax)
{
  RINGBUFFER* delayStruct = data->simulationInfo.delayStructure[exprNumber];
  int length = ringBufferLength(delayStruct);

  DEBUG_INFO4(LOG_EVENTS, "delayImpl: exprNumber = %d, exprValue = %g, time = %g, delayTime = %g", exprNumber, exprValue, time, delayTime);

  /* Check for errors */

  ASSERT1(0 <= exprNumber, "invalid exprNumber = %d", exprNumber);
  ASSERT1(exprNumber < data->modelData.nDelayExpressions, "invalid exprNumber = %d", exprNumber);

  if(time <= data->simulationInfo.tStart)
  {
    DEBUG_INFO1(LOG_EVENTS, "delayImpl: Entered at time < starting time: %g.", exprValue);
    return (exprValue);
  }

  if(delayTime < 0.0)
  {
    ASSERT1(0.0 < delayTime, "Negative delay requested: delayTime = %g", delayTime);
    THROW("Negative delay requested");
  }

  if(length == 0)
  {
    /*  This occurs in the initialization phase */
    DEBUG_INFO1(LOG_EVENTS, "delayImpl: Missing initial value, using argument value %g instead.", exprValue);
    return (exprValue);
  }

  /*
   * Returns: expr(time?delayTime) for time>time.start + delayTime and
   *          expr(time.start) for time <= time.start + delayTime.
   * The arguments, i.e., expr, delayTime and delayMax, need to be subtypes of Real.
   * DelayMax needs to be additionally a parameter expression.
   * The following relation shall hold: 0 <= delayTime <= delayMax,
   * otherwise an error occurs. If delayMax is not supplied in the argument list,
   * delayTime need to be a parameter expression. See also Section 3.7.2.1.
   * For non-scalar arguments the function is vectorized according to Section 10.6.12.
   */
  if(time <= data->simulationInfo.tStart + delayTime)
  {
    double res = ((TIME_AND_VALUE*)getRingData(delayStruct, 0))->value;
    DEBUG_INFO2(LOG_EVENTS, "findTime: time <= tStart + delayTime: [%d] = %g",exprNumber, res);
    return res;
  }
  else
  {
    /* return expr(time-delayTime) */
    double timeStamp = time - delayTime;
    double time0, time1, value0, value1;
    int i;

    ASSERT1(0.0 <= delayTime, "Negative delay requested: delayTime = %g", delayTime);

    /* find the row for the lower limit */
    if(timeStamp > ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->time)
    {
      /* delay between the last accepted time step and the current time */
      time0 = ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->time;
      value0 = ((TIME_AND_VALUE*)getRingData(delayStruct, length - 1))->value;
      time1 = time;
      value1 = exprValue;
    }
    else
    {
      i = findTime(timeStamp, delayStruct);
      ASSERT2(i < length, "%d = i < length = %d", i, length);
      time0 = ((TIME_AND_VALUE*)getRingData(delayStruct, i))->time;
      value0 = ((TIME_AND_VALUE*)getRingData(delayStruct, i))->value;

      /* was it the last value? */
      if(i+1 == length)
      {
        if(0 < i && delayMax == delayTime)
          dequeueNFirstRingDatas(delayStruct, i-1);
        DEBUG_INFO3(LOG_EVENTS, "delayImpl: dequeueNFirstRingDatas[%d] %g = %g", i, delayMax, delayTime);
        return value0;
      }
      time1 = ((TIME_AND_VALUE*)getRingData(delayStruct, i+1))->time;
      value1 = ((TIME_AND_VALUE*)getRingData(delayStruct, i+1))->value;
      if(0 < i && delayMax == delayTime)
        dequeueNFirstRingDatas(delayStruct, i-1);
    }
    /* was it an exact match?*/
    if(time0 == timeStamp){
      DEBUG_INFO2(LOG_EVENTS, "delayImpl: Exact match at %g = %g", timeStamp, value0);

      return value0;
    } else if(time1 == timeStamp) {
      DEBUG_INFO2(LOG_EVENTS, "delayImpl: Exact match at %g = %g", timeStamp, value1);

      return value1;
    } else {
      /* linear interpolation */
      double timedif = time1 - time0;
      double dt0 = time1 - timeStamp;
      double dt1 = timeStamp - time0;
      double retVal = (value0 * dt0 + value1 * dt1) / timedif;
      DEBUG_INFO3(LOG_EVENTS, "delayImpl: Linear interpolation of %g between %g and %g", timeStamp, time0, time1);

      DEBUG_INFO4(LOG_EVENTS, "delayImpl: Linear interpolation of %g value: %g and %g = %g", timeStamp, value0, value1, retVal);
      return retVal;
    }
  }

}
示例#6
0
文件: ccid_usb.c 项目: baerwolf/CCID
/*****************************************************************************
 *
 *					OpenUSBByName
 *
 ****************************************************************************/
status_t OpenUSBByName(unsigned int reader_index, /*@null@*/ char *device)
{
	unsigned int alias;
	struct libusb_device_handle *dev_handle;
	char infofile[FILENAME_MAX];
#ifndef __APPLE__
	unsigned int device_vendor, device_product;
	unsigned int device_bus = 0;
	unsigned int device_addr = 0;
#else
	/* 100 ms delay */
	struct timespec sleep_time = { 0, 100 * 1000 * 1000 };
	int count_libusb = 10;
#endif
	int interface_number = -1;
	int i;
	static int previous_reader_index = -1;
	libusb_device **devs, *dev;
	ssize_t cnt;
	list_t plist, *values, *ifdVendorID, *ifdProductID, *ifdFriendlyName;
	int rv;
	int claim_failed = FALSE;
	int return_value = STATUS_SUCCESS;

	DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, device);

#ifndef __APPLE__
	/* device name specified */
	if (device)
	{
		char *dirname;

		/* format: usb:%04x/%04x, vendor, product */
		if (strncmp("usb:", device, 4) != 0)
		{
			DEBUG_CRITICAL2("device name does not start with \"usb:\": %s",
				device);
			return STATUS_UNSUCCESSFUL;
		}

		if (sscanf(device, "usb:%x/%x", &device_vendor, &device_product) != 2)
		{
			DEBUG_CRITICAL2("device name can't be parsed: %s", device);
			return STATUS_UNSUCCESSFUL;
		}

		/* format usb:%04x/%04x:libudev:%d:%s
		 * with %d set to
		 * 01 (or whatever the interface number is)
		 * and %s set to
		 * /dev/bus/usb/008/004
		 */
		if ((dirname = strstr(device, "libudev:")) != NULL)
		{
			/* convert the interface number, bus and device ids */
			if (sscanf(dirname + 8, "%d:/dev/bus/usb/%d/%d", &interface_number, &device_bus, &device_addr) == 3) {
				DEBUG_COMM2("interface_number: %d", interface_number);
				DEBUG_COMM3("usb bus/device: %d/%d", device_bus, device_addr);
			}
		}
	}
#endif

	/* is the reader_index already used? */
	if (usbDevice[reader_index].dev_handle != NULL)
	{
		DEBUG_CRITICAL2("USB driver with index %X already in use",
			reader_index);
		return STATUS_UNSUCCESSFUL;
	}

	/* Info.plist full patch filename */
	(void)snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
		PCSCLITE_HP_DROPDIR, BUNDLE);
	DEBUG_INFO2("Using: %s", infofile);

	rv = bundleParse(infofile, &plist);
	if (rv)
		return STATUS_UNSUCCESSFUL;

#define GET_KEY(key, values) \
	rv = LTPBundleFindValueWithKey(&plist, key, &values); \
	if (rv) \
	{ \
		DEBUG_CRITICAL2("Value/Key not defined for " key " in %s", infofile); \
		return_value = STATUS_UNSUCCESSFUL; \
		goto end1; \
	} \
	else \
		DEBUG_INFO2(key ": %s", (char *)list_get_at(values, 0));

	/* general driver info */
	GET_KEY("ifdManufacturerString", values)
	GET_KEY("ifdProductString", values)
	GET_KEY("Copyright", values)

	if (NULL == ctx)
	{
		rv = libusb_init(&ctx);
		if (rv != 0)
		{
			DEBUG_CRITICAL2("libusb_init failed: %s", libusb_error_name(rv));
			return_value = STATUS_UNSUCCESSFUL;
			goto end1;
		}
	}

#define GET_KEYS(key, values) \
	rv = LTPBundleFindValueWithKey(&plist, key, values); \
	if (rv) \
	{ \
		DEBUG_CRITICAL2("Value/Key not defined for " key " in %s", infofile); \
		return_value = STATUS_UNSUCCESSFUL; \
		goto end1; \
	}

	GET_KEYS("ifdVendorID", &ifdVendorID)
	GET_KEYS("ifdProductID", &ifdProductID);
	GET_KEYS("ifdFriendlyName", &ifdFriendlyName)

	/* The 3 lists do not have the same size */
	if ((list_size(ifdVendorID) != list_size(ifdProductID))
		|| (list_size(ifdVendorID) != list_size(ifdFriendlyName)))
	{
		DEBUG_CRITICAL2("Error parsing %s", infofile);
		return_value = STATUS_UNSUCCESSFUL;
		goto end1;
	}

#ifdef __APPLE__
again_libusb:
#endif
	cnt = libusb_get_device_list(ctx, &devs);
	if (cnt < 0)
	{
		DEBUG_CRITICAL("libusb_get_device_list() failed\n");
		return_value = STATUS_UNSUCCESSFUL;
		goto end1;
	}

	/* for any supported reader */
	for (alias=0; alias<list_size(ifdVendorID); alias++)
	{
		unsigned int vendorID, productID;
		char *friendlyName;

		vendorID = strtoul(list_get_at(ifdVendorID, alias), NULL, 0);
		productID = strtoul(list_get_at(ifdProductID, alias), NULL, 0);
		friendlyName = list_get_at(ifdFriendlyName, alias);

#ifndef __APPLE__
		/* the device was specified but is not the one we are trying to find */
		if (device
			&& (vendorID != device_vendor || productID != device_product))
			continue;
#else
		/* Leopard puts the friendlyname in the device argument */
		if (device && strcmp(device, friendlyName))
			continue;
#endif

		/* for every device */
		i = 0;
		while ((dev = devs[i++]) != NULL)
		{
			struct libusb_device_descriptor desc;
			struct libusb_config_descriptor *config_desc;
			uint8_t bus_number = libusb_get_bus_number(dev);
			uint8_t device_address = libusb_get_device_address(dev);

#ifndef __APPLE__
			if ((device_bus || device_addr)
				&& ((bus_number != device_bus)
				|| (device_address != device_addr))) {
				/* not USB the device we are looking for */
				continue;
			}
#endif
			DEBUG_COMM3("Try device: %d/%d", bus_number, device_address);

			int r = libusb_get_device_descriptor(dev, &desc);
			if (r < 0)
			{
				DEBUG_INFO3("failed to get device descriptor for %d/%d",
					bus_number, device_address);
				continue;
			}

			DEBUG_COMM3("vid/pid : %04X/%04X", desc.idVendor, desc.idProduct);

			if (desc.idVendor == vendorID && desc.idProduct == productID)
			{
				int already_used;
				const struct libusb_interface *usb_interface = NULL;
				int interface;
				int num = 0;
				const unsigned char *device_descriptor;
				int readerID = (vendorID << 16) + productID;

#ifdef USE_COMPOSITE_AS_MULTISLOT
				static int static_interface = 1;

				/* simulate a composite device as when libudev is used */
				if ((GEMALTOPROXDU == readerID)
					|| (GEMALTOPROXSU == readerID)
					|| (FEITIANR502DUAL == readerID))
				{
						/*
						 * We can't talk to the two CCID interfaces
						 * at the same time (the reader enters a
						 * dead lock). So we simulate a multi slot
						 * reader. By default multi slot readers
						 * can't use the slots at the same time. See
						 * TAG_IFD_SLOT_THREAD_SAFE
						 *
						 * One side effect is that the two readers
						 * are seen by pcscd as one reader so the
						 * interface name is the same for the two.
						 *
	* So we have:
	* 0: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 00
	* 1: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 01
	* instead of
	* 0: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 00
	* 1: Gemalto Prox-DU [Prox-DU Contactless_09A00795] (09A00795) 01 00
						 */

					/* the CCID interfaces are 1 and 2 */
					interface_number = static_interface;
				}
#endif
				/* is it already opened? */
				already_used = FALSE;

				DEBUG_COMM3("Checking device: %d/%d",
					bus_number, device_address);
				for (r=0; r<CCID_DRIVER_MAX_READERS; r++)
				{
					if (usbDevice[r].dev_handle)
					{
						/* same bus, same address */
						if (usbDevice[r].bus_number == bus_number
							&& usbDevice[r].device_address == device_address)
							already_used = TRUE;
					}
				}

				/* this reader is already managed by us */
				if (already_used)
				{
					if ((previous_reader_index != -1)
						&& usbDevice[previous_reader_index].dev_handle
						&& (usbDevice[previous_reader_index].bus_number == bus_number)
						&& (usbDevice[previous_reader_index].device_address == device_address)
						&& usbDevice[previous_reader_index].ccid.bCurrentSlotIndex < usbDevice[previous_reader_index].ccid.bMaxSlotIndex)
					{
						/* we reuse the same device
						 * and the reader is multi-slot */
						usbDevice[reader_index] = usbDevice[previous_reader_index];
						/* The other slots of GemCore SIM Pro firmware
						 * 1.0 do not have the same data rates.
						 * Firmware 2.0 do not have this limitation */
						if ((GEMCOREPOSPRO == readerID)
							|| ((GEMCORESIMPRO == readerID)
							&& (usbDevice[reader_index].ccid.IFD_bcdDevice < 0x0200)))
						{
							usbDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialCustomDataRates;
							usbDevice[reader_index].ccid.dwMaxDataRate = 125000;
						}

						*usbDevice[reader_index].nb_opened_slots += 1;
						usbDevice[reader_index].ccid.bCurrentSlotIndex++;
						usbDevice[reader_index].ccid.dwSlotStatus =
							IFD_ICC_PRESENT;
						DEBUG_INFO2("Opening slot: %d",
							usbDevice[reader_index].ccid.bCurrentSlotIndex);

						/* This is a multislot reader
						 * Init the multislot stuff for this next slot */
						usbDevice[reader_index].multislot_extension = Multi_CreateNextSlot(previous_reader_index);
						goto end;
					}
					else
					{
						/* if an interface number is given by HAL we
						 * continue with this device. */
						if (-1 == interface_number)
						{
							DEBUG_INFO3("USB device %d/%d already in use."
								" Checking next one.",
								bus_number, device_address);
							continue;
						}
					}
				}

				DEBUG_COMM3("Trying to open USB bus/device: %d/%d",
					bus_number, device_address);

				r = libusb_open(dev, &dev_handle);
				if (r < 0)
				{
					DEBUG_CRITICAL4("Can't libusb_open(%d/%d): %s",
						bus_number, device_address, libusb_error_name(r));

					continue;
				}

again:
				r = libusb_get_active_config_descriptor(dev, &config_desc);
				if (r < 0)
				{
#ifdef __APPLE__
					/* Some early Gemalto Ezio CB+ readers have
					 * bDeviceClass, bDeviceSubClass and bDeviceProtocol set
					 * to 0xFF (proprietary) instead of 0x00.
					 *
					 * So on Mac OS X the reader configuration is not done
					 * by the OS/kernel and we do it ourself.
					 */
					if ((0xFF == desc.bDeviceClass)
						&& (0xFF == desc.bDeviceSubClass)
						&& (0xFF == desc.bDeviceProtocol))
					{
						r = libusb_set_configuration(dev_handle, 1);
						if (r < 0)
						{
							(void)libusb_close(dev_handle);
							DEBUG_CRITICAL4("Can't set configuration on %d/%d: %s",
									bus_number, device_address,
									libusb_error_name(r));
							continue;
						}
					}

					/* recall */
					r = libusb_get_active_config_descriptor(dev, &config_desc);
					if (r < 0)
					{
#endif
						(void)libusb_close(dev_handle);
						DEBUG_CRITICAL4("Can't get config descriptor on %d/%d: %s",
							bus_number, device_address, libusb_error_name(r));
						continue;
					}
#ifdef __APPLE__
				}
#endif


				usb_interface = get_ccid_usb_interface(config_desc, &num);
				if (usb_interface == NULL)
				{
					(void)libusb_close(dev_handle);
					if (0 == num)
						DEBUG_CRITICAL3("Can't find a CCID interface on %d/%d",
							bus_number, device_address);
					interface_number = -1;
					continue;
				}

				device_descriptor = get_ccid_device_descriptor(usb_interface);
				if (NULL == device_descriptor)
				{
					(void)libusb_close(dev_handle);
					DEBUG_CRITICAL3("Unable to find the device descriptor for %d/%d",
						bus_number, device_address);
					return_value = STATUS_UNSUCCESSFUL;
					goto end2;
				}

				interface = usb_interface->altsetting->bInterfaceNumber;
				if (interface_number >= 0 && interface != interface_number)
				{
					/* an interface was specified and it is not the
					 * current one */
					DEBUG_INFO3("Found interface %d but expecting %d",
						interface, interface_number);
					DEBUG_INFO3("Wrong interface for USB device %d/%d."
						" Checking next one.", bus_number, device_address);

					/* check for another CCID interface on the same device */
					num++;

					goto again;
				}

				r = libusb_claim_interface(dev_handle, interface);
				if (r < 0)
				{
					(void)libusb_close(dev_handle);
					DEBUG_CRITICAL4("Can't claim interface %d/%d: %s",
						bus_number, device_address, libusb_error_name(r));
					claim_failed = TRUE;
					interface_number = -1;
					continue;
				}

				DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)",
					desc.idVendor, desc.idProduct, friendlyName);
				DEBUG_INFO3("Using USB bus/device: %d/%d",
					bus_number, device_address);

				/* check for firmware bugs */
				if (ccid_check_firmware(&desc))
				{
					(void)libusb_close(dev_handle);
					return_value = STATUS_UNSUCCESSFUL;
					goto end2;
				}

#ifdef USE_COMPOSITE_AS_MULTISLOT
				/* use the next interface for the next "slot" */
				static_interface++;

				/* reset for a next reader */
				if (static_interface > 2)
					static_interface = (FEITIANR502DUAL == readerID) ? 0: 1;
#endif

				/* Get Endpoints values*/
				(void)get_end_points(config_desc, &usbDevice[reader_index], num);

				/* store device information */
				usbDevice[reader_index].dev_handle = dev_handle;
				usbDevice[reader_index].bus_number = bus_number;
				usbDevice[reader_index].device_address = device_address;
				usbDevice[reader_index].interface = interface;
				usbDevice[reader_index].real_nb_opened_slots = 1;
				usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots;
				usbDevice[reader_index].polling_transfer = NULL;

				/* CCID common informations */
				usbDevice[reader_index].ccid.real_bSeq = 0;
				usbDevice[reader_index].ccid.pbSeq = &usbDevice[reader_index].ccid.real_bSeq;
				usbDevice[reader_index].ccid.readerID =
					(desc.idVendor << 16) + desc.idProduct;
				usbDevice[reader_index].ccid.dwFeatures = dw2i(device_descriptor, 40);
				usbDevice[reader_index].ccid.wLcdLayout =
					(device_descriptor[51] << 8) + device_descriptor[50];
				usbDevice[reader_index].ccid.bPINSupport = device_descriptor[52];
				usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(device_descriptor, 44);
				usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(device_descriptor, 28);
				usbDevice[reader_index].ccid.dwDefaultClock = dw2i(device_descriptor, 10);
				usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(device_descriptor, 23);
				usbDevice[reader_index].ccid.bMaxSlotIndex = device_descriptor[4];
				usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;
				usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
				if (device_descriptor[27])
					usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index, config_desc, num);
				else
				{
					usbDevice[reader_index].ccid.arrayOfSupportedDataRates = NULL;
					DEBUG_INFO1("bNumDataRatesSupported is 0");
				}
				usbDevice[reader_index].ccid.bInterfaceProtocol = usb_interface->altsetting->bInterfaceProtocol;
				usbDevice[reader_index].ccid.bNumEndpoints = usb_interface->altsetting->bNumEndpoints;
				usbDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
				usbDevice[reader_index].ccid.bVoltageSupport = device_descriptor[5];
				usbDevice[reader_index].ccid.sIFD_serial_number = NULL;
				usbDevice[reader_index].ccid.gemalto_firmware_features = NULL;
				if (desc.iSerialNumber)
				{
					unsigned char serial[128];
					int ret;

					ret = libusb_get_string_descriptor_ascii(dev_handle,
							desc.iSerialNumber, serial,
							sizeof(serial));
					if (ret > 0)
						usbDevice[reader_index].ccid.sIFD_serial_number
							= strdup((char *)serial);
				}

				usbDevice[reader_index].ccid.sIFD_iManufacturer = NULL;
				if (desc.iManufacturer)
				{
					unsigned char iManufacturer[128];
					int ret;

					ret = libusb_get_string_descriptor_ascii(dev_handle,
							desc.iManufacturer, iManufacturer,
							sizeof(iManufacturer));
					if (ret > 0)
						usbDevice[reader_index].ccid.sIFD_iManufacturer
							= strdup((char *)iManufacturer);
				}

				usbDevice[reader_index].ccid.IFD_bcdDevice = desc.bcdDevice;

				/* If this is a multislot reader, init the multislot stuff */
				if (usbDevice[reader_index].ccid.bMaxSlotIndex)
					usbDevice[reader_index].multislot_extension = Multi_CreateFirstSlot(reader_index);
				else
					usbDevice[reader_index].multislot_extension = NULL;

				goto end;
			}
		}
	}
end:
	if (usbDevice[reader_index].dev_handle == NULL)
	{
		/* free the libusb allocated list & devices */
		libusb_free_device_list(devs, 1);

#ifdef __APPLE__
		/* give some time to libusb to detect the new USB devices on Mac OS X */
		if (count_libusb > 0)
		{
			count_libusb--;
			DEBUG_INFO2("Wait after libusb: %d", count_libusb);
			nanosleep(&sleep_time, NULL);

			goto again_libusb;
		}
#endif
		/* failed */
		close_libusb_if_needed();

		if (claim_failed)
			return STATUS_COMM_ERROR;
		DEBUG_INFO1("Device not found?");
		return STATUS_NO_SUCH_DEVICE;
	}

	/* memorise the current reader_index so we can detect
	 * a new OpenUSBByName on a multi slot reader */
	previous_reader_index = reader_index;

end2:
	/* free the libusb allocated list & devices */
	libusb_free_device_list(devs, 1);

end1:
	/* free bundle list */
	bundleRelease(&plist);

	if (return_value != STATUS_SUCCESS)
		close_libusb_if_needed();

	return return_value;
} /* OpenUSBByName */
  /*! \fn ipopt_initialization
   *
   *  This function is used if ipopt is choosen for initialization.
   *
   *  \param [ref] [data]
   *  \param [ref] [initData]
   *  \param [in]  [useScaling]
   *
   *  \author lochel
   */
  int ipopt_initialization(DATA *data, INIT_DATA *initData, int useScaling)
  {
    int n = initData->nz;                /* number of variables */
    int m = (initData->nInitResiduals > initData->nz) ? 0 : initData->nInitResiduals;    /* number of constraints */
    double* x_L = NULL;                  /* lower bounds on x */
    double* x_U = NULL;                  /* upper bounds on x */
    double* g_L = NULL;                  /* lower bounds on g */
    double* g_U = NULL;                  /* upper bounds on g */

    double* x = NULL;                    /* starting point and solution vector */
    double* mult_g = NULL;               /* constraint multipliers at the solution */
    double* mult_x_L = NULL;             /* lower bound multipliers at the solution */
    double* mult_x_U = NULL;             /* upper bound multipliers at the solution */
    double obj;                          /* objective value */
    int i;                               /* generic counter */

    int nele_jac = n*m;                  /* number of nonzeros in the Jacobian of the constraints */
    int nele_hess = 0;                   /* number of nonzeros in the Hessian of the Lagrangian (lower or upper triangual part only) */

    IpoptProblem nlp = NULL;             /* ipopt-problem */
    enum ApplicationReturnStatus status; /* solve return code */

    IPOPT_DATA ipopt_data;

    ipopt_data.data = data;
    ipopt_data.initData = initData;
    ipopt_data.useScaling = useScaling;
    ipopt_data.useSymbolic = (initialAnalyticJacobianG(data) == 0 ? 1 : 0);

    if(ipopt_data.useSymbolic == 1)
    {
      nele_jac = data->simulationInfo.analyticJacobians[INDEX_JAC_G].sparsePattern.leadindex[n-1]; // sparse
      DEBUG_INFO1(LOG_INIT, "number of zeros in the Jacobian of the constraints (jac_g):    %d", n*m-nele_jac);
      DEBUG_INFO1(LOG_INIT, "number of nonzeros in the Jacobian of the constraints (jac_g): %d", nele_jac);
    }

    /* allocate space for the variable bounds */
    x_L = (double*)malloc(n * sizeof(double));
    x_U = (double*)malloc(n * sizeof(double));

    /* allocate space for the constraint bounds */
    g_L = (double*)malloc(m * sizeof(double));
    g_U = (double*)malloc(m * sizeof(double));

    /* allocate space for the initial point */
    x = (double*)malloc(n * sizeof(double));

    /* set values of optimization variable bounds */
    for(i=0; i<n; ++i)
    {
      x[i] = initData->start[i];
      x_L[i] = initData->min[i];
      x_U[i] = initData->max[i];
    }

    /* set values of constraint bounds */
    for(i=0; i<m; ++i)
    {
      g_L[i] = 0.0;
      g_U[i] = 0.0;
    }

    /* create the IpoptProblem */
    nlp = CreateIpoptProblem(
        n,              /* Number of optimization variables */
        x_L,            /* Lower bounds on variables */
        x_U,            /* Upper bounds on variables */
        m,              /* Number of constraints */
        g_L,            /* Lower bounds on constraints */
        g_U,            /* Upper bounds on constraints */
        nele_jac,       /* Number of non-zero elements in constraint Jacobian */
        nele_hess,      /* Number of non-zero elements in Hessian of Lagrangian */
        0,              /* indexing style for iRow & jCol; 0 for C style, 1 for Fortran style */
        &ipopt_f,       /* Callback function for evaluating objective function */
        &ipopt_g,       /* Callback function for evaluating constraint functions */
        &ipopt_grad_f,  /* Callback function for evaluating gradient of objective function */
        &ipopt_jac_g,   /* Callback function for evaluating Jacobian of constraint functions */
        &ipopt_h);      /* Callback function for evaluating Hessian of Lagrangian function */

    ASSERT(nlp, "creating of ipopt problem has failed");

    /* We can free the memory now - the values for the bounds have been
       copied internally in CreateIpoptProblem */
    free(x_L);
    free(x_U);
    free(g_L);
    free(g_U);

    /* Set some options. Note the following ones are only examples,
       they might not be suitable for your problem. */
    AddIpoptNumOption(nlp, "tol", 1e-7);

    AddIpoptIntOption(nlp, "print_level", DEBUG_FLAG(LOG_INIT) ? 5 : 0);
    AddIpoptIntOption(nlp, "max_iter", 5000);

    AddIpoptStrOption(nlp, "mu_strategy", "adaptive");
    AddIpoptStrOption(nlp, "hessian_approximation", "limited-memory");

    /* allocate space to store the bound multipliers at the solution */
    mult_g = (double*)malloc(m*sizeof(double));
    mult_x_L = (double*)malloc(n*sizeof(double));
    mult_x_U = (double*)malloc(n*sizeof(double));

    /* solve the problem */
    status = IpoptSolve(
        nlp,            /* Problem that is to be optimized */
        x,              /* Input: Starting point; Output: Optimal solution */
        NULL,           /* Values of constraint at final point */
        &obj,           /* Final value of objective function */
        mult_g,         /* Final multipliers for constraints */
        mult_x_L,       /* Final multipliers for lower variable bounds */
        mult_x_U,       /* Final multipliers for upper variable bounds */
        &ipopt_data);   /* Pointer to user data */

    setZ(initData, x);

    /* free allocated memory */
    FreeIpoptProblem(nlp);
    free(x);
    free(mult_g);
    free(mult_x_L);
    free(mult_x_U);

    /* debug output */
    DEBUG_INFO1(LOG_INIT, "ending with funcValue = %g", obj);
    DEBUG_INFO_AL(LOG_INIT, "| unfixed variables");
    for(i=0; i<initData->nz; i++)
      DEBUG_INFO_AL4(LOG_INIT, "| | [%ld] %s = %g [scaled: %g]", i+1, initData->name[i], initData->z[i], initData->zScaled[i]);
    DEBUG_INFO_AL(LOG_INIT, "| residuals (> 0.001)");
    for(i=0; i<data->modelData.nInitResiduals; i++)
      if(fabs(initData->initialResiduals[i]) > 1e-3)
        DEBUG_INFO_AL3(LOG_INIT, "| | [%ld] %g [scaled: %g]", i+1, initData->initialResiduals[i], (initData->residualScalingCoefficients[i] != 0.0) ? initData->initialResiduals[i]/initData->residualScalingCoefficients[i] : 0.0);

    if(status != Solve_Succeeded && status != Solved_To_Acceptable_Level)
      THROW("ipopt failed. see last warning. use [-lv LOG_INIT] for more output.");

    return (int)status;
  }